summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore19
-rwxr-xr-xBUILD/SETUP.sh23
-rwxr-xr-xBUILD/autorun.sh22
-rwxr-xr-xBUILD/compile-dist8
-rwxr-xr-xBUILD/compile-pentium-debug-max2
-rwxr-xr-xBUILD/compile-pentium-debug-openssl2
-rwxr-xr-xBUILD/compile-pentium-debug-yassl2
-rwxr-xr-xBUILD/compile-pentium-gcov15
-rw-r--r--CMakeLists.txt (renamed from cmakelists.txt)53
-rw-r--r--Makefile.am7
-rw-r--r--VC++Files/client/mysql_upgrade.dsp105
-rw-r--r--VC++Files/client/mysql_upgrade.vcproj232
-rw-r--r--VC++Files/client/mysql_upgrade_ia64.dsp113
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp4
-rw-r--r--VC++Files/libmysqld/libmysqld_ia64.dsp4
-rw-r--r--VC++Files/mysql.dsw21
-rw-r--r--VC++Files/mysql.sln9
-rw-r--r--VC++Files/mysql_ia64.dsw18
-rw-r--r--VC++Files/mysys/mysys.vcproj43
-rw-r--r--client/CMakeLists.txt (renamed from client/cmakelists.txt)0
-rw-r--r--client/Makefile.am2
-rw-r--r--client/client_priv.h2
-rw-r--r--client/client_priv.h.rej15
-rw-r--r--client/get_password.c4
-rw-r--r--client/mysql.cc87
-rw-r--r--client/mysql_upgrade.c8
-rw-r--r--client/mysqladmin.cc2
-rw-r--r--client/mysqlbinlog.cc6
-rw-r--r--client/mysqldump.c6
-rw-r--r--client/mysqlimport.c2
-rw-r--r--client/mysqlshow.c2
-rw-r--r--client/mysqlslap.c4
-rw-r--r--client/mysqltest.c76
-rw-r--r--config/ac-macros/ha_archive.m429
-rw-r--r--config/ac-macros/ha_berkeley.m418
-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.m49
-rw-r--r--config/ac-macros/ha_partition.m433
-rw-r--r--config/ac-macros/ha_tina.m429
-rw-r--r--config/ac-macros/misc.m413
-rw-r--r--config/ac-macros/openssl.m4135
-rw-r--r--config/ac-macros/plugins.m4762
-rw-r--r--config/ac-macros/replication.m42
-rw-r--r--config/ac-macros/ssl.m4210
-rw-r--r--config/ac-macros/storage.m455
-rw-r--r--config/ac-macros/yassl.m442
-rw-r--r--config/ac-macros/zlib.m48
-rw-r--r--configure.in268
-rw-r--r--dbug/CMakeLists.txt (renamed from dbug/cmakelists.txt)0
-rw-r--r--dbug/Makefile.am2
-rw-r--r--dbug/dbug.c84
-rw-r--r--extra/CMakeLists.txt (renamed from extra/cmakelists.txt)0
-rw-r--r--extra/Makefile.am2
-rw-r--r--extra/yassl/CMakeLists.txt (renamed from extra/yassl/cmakelists.txt)0
-rw-r--r--extra/yassl/Makefile.am4
-rw-r--r--extra/yassl/README168
-rw-r--r--extra/yassl/certs/ca-cert.pem53
-rw-r--r--extra/yassl/certs/client-cert.derbin0 -> 699 bytes
-rw-r--r--extra/yassl/certs/client-cert.pem52
-rw-r--r--extra/yassl/certs/client-key.derbin0 -> 318 bytes
-rw-r--r--extra/yassl/certs/client-key.pem9
-rw-r--r--extra/yassl/certs/dh1024.dat1
-rw-r--r--extra/yassl/certs/dsa-cert.pem68
-rw-r--r--extra/yassl/certs/dsa512.derbin0 -> 250 bytes
-rw-r--r--extra/yassl/certs/dsa512.pem8
-rw-r--r--extra/yassl/certs/server-cert.pem38
-rw-r--r--extra/yassl/certs/server-key.pem9
-rw-r--r--extra/yassl/certs/taoCert.txt50
-rw-r--r--extra/yassl/examples/client/client.cpp98
-rw-r--r--extra/yassl/examples/client/client.dsp102
-rw-r--r--extra/yassl/examples/echoclient/echoclient.cpp90
-rw-r--r--extra/yassl/examples/echoclient/echoclient.dsp102
-rw-r--r--extra/yassl/examples/echoclient/input93
-rw-r--r--extra/yassl/examples/echoclient/quit2
-rw-r--r--extra/yassl/examples/echoserver/echoserver.cpp129
-rw-r--r--extra/yassl/examples/echoserver/echoserver.dsp102
-rw-r--r--extra/yassl/examples/server/server.cpp75
-rw-r--r--extra/yassl/examples/server/server.dsp109
-rw-r--r--extra/yassl/include/cert_wrapper.hpp3
-rw-r--r--extra/yassl/include/crypto_wrapper.hpp6
-rw-r--r--extra/yassl/include/openssl/err.h2
-rw-r--r--extra/yassl/include/openssl/md4.h1
-rw-r--r--extra/yassl/include/openssl/md5.h3
-rw-r--r--extra/yassl/include/openssl/pem.h1
-rw-r--r--extra/yassl/include/openssl/ssl.h132
-rw-r--r--extra/yassl/include/openssl/x509.h1
-rw-r--r--extra/yassl/include/openssl/x509v3.h1
-rw-r--r--extra/yassl/include/socket_wrapper.hpp6
-rw-r--r--extra/yassl/include/yassl.hpp88
-rw-r--r--extra/yassl/include/yassl_error.hpp4
-rw-r--r--extra/yassl/include/yassl_imp.hpp2
-rw-r--r--extra/yassl/include/yassl_int.hpp49
-rw-r--r--extra/yassl/include/yassl_types.hpp75
-rw-r--r--extra/yassl/lib/dummy1
-rw-r--r--extra/yassl/mySTL/helpers.hpp9
-rw-r--r--extra/yassl/mySTL/stdexcept.hpp2
-rw-r--r--extra/yassl/src/buffer.cpp15
-rw-r--r--extra/yassl/src/cert_wrapper.cpp43
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp58
-rw-r--r--extra/yassl/src/handshake.cpp61
-rw-r--r--extra/yassl/src/make.bat27
-rw-r--r--extra/yassl/src/socket_wrapper.cpp36
-rw-r--r--extra/yassl/src/ssl.cpp519
-rw-r--r--extra/yassl/src/template_instnt.cpp12
-rw-r--r--extra/yassl/src/yassl.cpp244
-rw-r--r--extra/yassl/src/yassl_error.cpp185
-rw-r--r--extra/yassl/src/yassl_imp.cpp117
-rw-r--r--extra/yassl/src/yassl_int.cpp277
-rw-r--r--extra/yassl/taocrypt/CMakeLists.txt (renamed from extra/yassl/taocrypt/cmakelists.txt)2
-rw-r--r--extra/yassl/taocrypt/Makefile.am4
-rw-r--r--extra/yassl/taocrypt/benchmark/Makefile.am8
-rw-r--r--extra/yassl/taocrypt/benchmark/benchmark.cpp440
-rw-r--r--extra/yassl/taocrypt/benchmark/benchmark.dsp101
-rw-r--r--extra/yassl/taocrypt/benchmark/dh1024.derbin0 -> 140 bytes
-rw-r--r--extra/yassl/taocrypt/benchmark/dsa1024.derbin0 -> 448 bytes
-rw-r--r--extra/yassl/taocrypt/benchmark/make.bat9
-rw-r--r--extra/yassl/taocrypt/benchmark/rsa1024.derbin0 -> 610 bytes
-rw-r--r--extra/yassl/taocrypt/include/aes.hpp42
-rw-r--r--extra/yassl/taocrypt/include/arc4.hpp1
-rw-r--r--extra/yassl/taocrypt/include/asn.hpp38
-rw-r--r--extra/yassl/taocrypt/include/block.hpp4
-rw-r--r--extra/yassl/taocrypt/include/blowfish.hpp79
-rw-r--r--extra/yassl/taocrypt/include/des.hpp80
-rw-r--r--extra/yassl/taocrypt/include/dh.hpp2
-rw-r--r--extra/yassl/taocrypt/include/hash.hpp13
-rw-r--r--extra/yassl/taocrypt/include/hmac.hpp10
-rw-r--r--extra/yassl/taocrypt/include/integer.hpp1
-rw-r--r--extra/yassl/taocrypt/include/kernelc.hpp49
-rw-r--r--extra/yassl/taocrypt/include/md4.hpp65
-rw-r--r--extra/yassl/taocrypt/include/md5.hpp3
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp154
-rw-r--r--extra/yassl/taocrypt/include/modes.hpp15
-rw-r--r--extra/yassl/taocrypt/include/pwdbased.hpp93
-rw-r--r--extra/yassl/taocrypt/include/ripemd.hpp2
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp8
-rw-r--r--extra/yassl/taocrypt/include/sha.hpp2
-rw-r--r--extra/yassl/taocrypt/include/twofish.hpp86
-rw-r--r--extra/yassl/taocrypt/include/types.hpp5
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am10
-rw-r--r--extra/yassl/taocrypt/src/aes.cpp1453
-rw-r--r--extra/yassl/taocrypt/src/aestables.cpp683
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp2
-rw-r--r--extra/yassl/taocrypt/src/arc4.cpp136
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp107
-rw-r--r--extra/yassl/taocrypt/src/bftables.cpp306
-rw-r--r--extra/yassl/taocrypt/src/blowfish.cpp358
-rw-r--r--extra/yassl/taocrypt/src/coding.cpp7
-rw-r--r--extra/yassl/taocrypt/src/des.cpp623
-rw-r--r--extra/yassl/taocrypt/src/dh.cpp28
-rw-r--r--extra/yassl/taocrypt/src/hash.cpp29
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp28
-rw-r--r--extra/yassl/taocrypt/src/make.bat37
-rw-r--r--extra/yassl/taocrypt/src/md4.cpp154
-rw-r--r--extra/yassl/taocrypt/src/md5.cpp347
-rw-r--r--extra/yassl/taocrypt/src/misc.cpp64
-rw-r--r--extra/yassl/taocrypt/src/random.cpp8
-rw-r--r--extra/yassl/taocrypt/src/ripemd.cpp575
-rw-r--r--extra/yassl/taocrypt/src/sha.cpp481
-rw-r--r--extra/yassl/taocrypt/src/template_instnt.cpp12
-rw-r--r--extra/yassl/taocrypt/src/tftables.cpp352
-rw-r--r--extra/yassl/taocrypt/src/twofish.cpp591
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsp49
-rw-r--r--extra/yassl/taocrypt/test.dsp102
-rw-r--r--extra/yassl/taocrypt/test.dsw29
-rw-r--r--extra/yassl/taocrypt/test/Makefile.am8
-rw-r--r--extra/yassl/taocrypt/test/make.bat9
-rw-r--r--extra/yassl/taocrypt/test/memory.cpp312
-rw-r--r--extra/yassl/taocrypt/test/test.cpp994
-rw-r--r--extra/yassl/testsuite/Makefile.am11
-rw-r--r--extra/yassl/testsuite/input107
-rw-r--r--extra/yassl/testsuite/make.bat14
-rw-r--r--extra/yassl/testsuite/quit2
-rw-r--r--extra/yassl/testsuite/test.hpp358
-rw-r--r--extra/yassl/testsuite/testsuite.cpp156
-rw-r--r--extra/yassl/testsuite/testsuite.dsp127
-rw-r--r--extra/yassl/yassl.dsp4
-rw-r--r--extra/yassl/yassl.dsw15
-rw-r--r--include/config-win.h4
-rw-r--r--include/heap.h2
-rw-r--r--include/m_ctype.h6
-rw-r--r--include/m_string.h24
-rw-r--r--include/my_base.h6
-rw-r--r--include/my_dbug.h3
-rw-r--r--include/my_global.h11
-rw-r--r--include/my_net.h4
-rw-r--r--include/my_nosys.h3
-rw-r--r--include/my_pthread.h6
-rw-r--r--include/my_sys.h36
-rw-r--r--include/my_time.h3
-rw-r--r--include/my_tree.h10
-rw-r--r--include/myisam.h2
-rw-r--r--include/mysql.h4
-rw-r--r--include/mysql/plugin.h21
-rw-r--r--include/mysql_com.h8
-rw-r--r--include/mysys_err.h3
-rw-r--r--include/sslopt-longopts.h19
-rw-r--r--include/sslopt-vars.h20
-rw-r--r--include/violite.h26
-rw-r--r--libmysql/CMakeLists.txt (renamed from libmysql/cmakelists.txt)0
-rw-r--r--libmysql/Makefile.am2
-rw-r--r--libmysql/get_password.c4
-rw-r--r--libmysql/libmysql.c3
-rw-r--r--libmysqld/CMakeLists.txt (renamed from libmysqld/cmakelists.txt)2
-rw-r--r--libmysqld/Makefile.am45
-rw-r--r--libmysqld/examples/CMakeLists.txt (renamed from libmysqld/examples/cmakelists.txt)0
-rw-r--r--mysql-test/Makefile.am8
-rw-r--r--mysql-test/extra/binlog_tests/binlog.test6
-rw-r--r--mysql-test/extra/binlog_tests/blackhole.test12
-rw-r--r--mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test26
-rw-r--r--mysql-test/extra/rpl_tests/rpl_deadlock.test8
-rw-r--r--mysql-test/extra/rpl_tests/rpl_failed_optimize.test5
-rw-r--r--mysql-test/extra/rpl_tests/rpl_flsh_tbls.test2
-rw-r--r--mysql-test/extra/rpl_tests/rpl_insert_id.test70
-rw-r--r--mysql-test/extra/rpl_tests/rpl_log.test7
-rw-r--r--mysql-test/include/have_case_sensitive_file_system.inc4
-rw-r--r--mysql-test/include/have_ndb.inc11
-rw-r--r--mysql-test/include/have_udf.inc10
-rw-r--r--mysql-test/include/not_as_root.inc4
-rw-r--r--mysql-test/include/rpl_multi_engine3.inc4
-rw-r--r--mysql-test/lib/init_db.sql2
-rw-r--r--mysql-test/lib/mtr_misc.pl43
-rw-r--r--mysql-test/lib/mtr_process.pl45
-rw-r--r--mysql-test/lib/mtr_report.pl24
-rwxr-xr-xmysql-test/mysql-test-run.pl487
-rw-r--r--mysql-test/mysql-test-run.sh25
-rw-r--r--mysql-test/ndb/ndbcluster.sh8
-rw-r--r--mysql-test/r/alter_table.result10
-rw-r--r--mysql-test/r/analyze.result8
-rw-r--r--mysql-test/r/ansi.result31
-rw-r--r--mysql-test/r/archive.result2
-rw-r--r--mysql-test/r/auto_increment.result30
-rw-r--r--mysql-test/r/binlog_row_blackhole.result6
-rw-r--r--mysql-test/r/binlog_stm_blackhole.result6
-rw-r--r--mysql-test/r/case.result16
-rw-r--r--mysql-test/r/case_sensitive_file_system.require2
-rw-r--r--mysql-test/r/contributors.result5
-rw-r--r--mysql-test/r/ctype_latin2_ch.result1
-rw-r--r--mysql-test/r/ctype_sjis.result4
-rw-r--r--mysql-test/r/ctype_ucs.result12
-rw-r--r--mysql-test/r/ctype_utf8.result8
-rw-r--r--mysql-test/r/date_formats.result36
-rw-r--r--mysql-test/r/delete.result4
-rw-r--r--mysql-test/r/distinct.result12
-rw-r--r--mysql-test/r/events.result121
-rw-r--r--mysql-test/r/events_bugs.result8
-rw-r--r--mysql-test/r/events_grant.result121
-rw-r--r--mysql-test/r/events_logs_tests.result25
-rw-r--r--mysql-test/r/events_microsec.result46
-rw-r--r--mysql-test/r/events_scheduling.result19
-rw-r--r--mysql-test/r/events_stress.result69
-rw-r--r--mysql-test/r/exampledb.result2
-rw-r--r--mysql-test/r/explain.result4
-rw-r--r--mysql-test/r/func_compress.result7
-rw-r--r--mysql-test/r/func_gconcat.result10
-rw-r--r--mysql-test/r/func_group.result138
-rw-r--r--mysql-test/r/func_in.result120
-rw-r--r--mysql-test/r/func_misc.result36
-rw-r--r--mysql-test/r/func_op.result11
-rw-r--r--mysql-test/r/func_str.result23
-rw-r--r--mysql-test/r/func_time.result52
-rw-r--r--mysql-test/r/gis-rtree.result2
-rw-r--r--mysql-test/r/grant2.result14
-rw-r--r--mysql-test/r/group_min_max.result22
-rw-r--r--mysql-test/r/have_ndb_status_ok.require2
-rw-r--r--mysql-test/r/have_udf.require2
-rw-r--r--mysql-test/r/have_udf_example.require2
-rw-r--r--mysql-test/r/having.result15
-rw-r--r--mysql-test/r/heap.result19
-rw-r--r--mysql-test/r/heap_btree.result10
-rw-r--r--mysql-test/r/im_cmd_line.result40
-rw-r--r--mysql-test/r/im_daemon_life_cycle.result2
-rw-r--r--mysql-test/r/im_instance_conf.result196
-rw-r--r--mysql-test/r/im_life_cycle.result72
-rw-r--r--mysql-test/r/im_options.result150
-rw-r--r--mysql-test/r/im_options_set.result20
-rw-r--r--mysql-test/r/im_options_unset.result15
-rw-r--r--mysql-test/r/im_utils.result6
-rw-r--r--mysql-test/r/information_schema.result42
-rw-r--r--mysql-test/r/information_schema_chmod.result5
-rw-r--r--mysql-test/r/information_schema_db.result1
-rw-r--r--mysql-test/r/information_schema_inno.result31
-rw-r--r--mysql-test/r/innodb.result197
-rw-r--r--mysql-test/r/innodb_mysql.result194
-rw-r--r--mysql-test/r/innodb_unsafe_binlog.result87
-rw-r--r--mysql-test/r/join.result4
-rw-r--r--mysql-test/r/join_outer.result61
-rw-r--r--mysql-test/r/key_cache.result42
-rw-r--r--mysql-test/r/log_tables.result26
-rw-r--r--mysql-test/r/merge.result8
-rw-r--r--mysql-test/r/metadata.result2
-rw-r--r--mysql-test/r/myisam-system.result13
-rw-r--r--mysql-test/r/myisam.result158
-rw-r--r--mysql-test/r/mysql.result22
-rw-r--r--mysql-test/r/mysqlbinlog.result1
-rw-r--r--mysql-test/r/mysqldump.result43
-rw-r--r--mysql-test/r/ndb_alter_table.result65
-rw-r--r--mysql-test/r/ndb_alter_table3.result (renamed from mysql-test/r/ndb_alter_table_row.result)0
-rw-r--r--mysql-test/r/ndb_alter_table_stm.result29
-rw-r--r--mysql-test/r/ndb_autodiscover3.result53
-rw-r--r--mysql-test/r/ndb_basic.result48
-rw-r--r--mysql-test/r/ndb_binlog_discover.result13
-rw-r--r--mysql-test/r/ndb_bitfield.result2
-rw-r--r--mysql-test/r/ndb_blob.result84
-rw-r--r--mysql-test/r/ndb_blob_partition.result104
-rw-r--r--mysql-test/r/ndb_condition_pushdown.result60
-rw-r--r--mysql-test/r/ndb_config.result1
-rw-r--r--mysql-test/r/ndb_config2.result1
-rw-r--r--mysql-test/r/ndb_dd_backuprestore.result330
-rw-r--r--mysql-test/r/ndb_dd_basic.result25
-rw-r--r--mysql-test/r/ndb_dd_ddl.result2
-rw-r--r--mysql-test/r/ndb_dd_disk2memory.result8
-rw-r--r--mysql-test/r/ndb_gis.result4
-rw-r--r--mysql-test/r/ndb_index_unique.result8
-rw-r--r--mysql-test/r/ndb_multi_row.result2
-rw-r--r--mysql-test/r/ndb_partition_error.result47
-rw-r--r--mysql-test/r/ndb_partition_key.result185
-rw-r--r--mysql-test/r/ndb_partition_list.result51
-rw-r--r--mysql-test/r/ndb_partition_range.result263
-rw-r--r--mysql-test/r/ndb_restore_compat.result104
-rw-r--r--mysql-test/r/not_as_root.require2
-rw-r--r--mysql-test/r/not_embedded_server.result1
-rw-r--r--mysql-test/r/null.result42
-rw-r--r--mysql-test/r/openssl_1.result16
-rw-r--r--mysql-test/r/order_by.result32
-rw-r--r--mysql-test/r/outfile.resultbin1130 -> 1159 bytes
-rw-r--r--mysql-test/r/partition.result50
-rw-r--r--mysql-test/r/partition_pruning.result10
-rw-r--r--mysql-test/r/partition_range.result24
-rw-r--r--mysql-test/r/ps.result101
-rw-r--r--mysql-test/r/ps_11bugs.result14
-rw-r--r--mysql-test/r/ps_1general.result5
-rw-r--r--mysql-test/r/ps_2myisam.result4
-rw-r--r--mysql-test/r/ps_3innodb.result4
-rw-r--r--mysql-test/r/ps_4heap.result4
-rw-r--r--mysql-test/r/ps_5merge.result8
-rw-r--r--mysql-test/r/ps_6bdb.result4
-rw-r--r--mysql-test/r/ps_7ndb.result4
-rw-r--r--mysql-test/r/rpl_bit_npk.result68
-rw-r--r--mysql-test/r/rpl_deadlock_innodb.result105
-rw-r--r--mysql-test/r/rpl_failed_optimize.result5
-rw-r--r--mysql-test/r/rpl_insert_id.result58
-rw-r--r--mysql-test/r/rpl_loaddatalocal.result4
-rw-r--r--mysql-test/r/rpl_ndb_2innodb.result855
-rw-r--r--mysql-test/r/rpl_ndb_2myisam.result855
-rw-r--r--mysql-test/r/rpl_ndb_UUID.result2
-rw-r--r--mysql-test/r/rpl_ndb_basic.result25
-rw-r--r--mysql-test/r/rpl_ndb_dd_advance.result12
-rw-r--r--mysql-test/r/rpl_openssl.result1
-rw-r--r--mysql-test/r/rpl_row_log.result4
-rw-r--r--mysql-test/r/rpl_row_log_innodb.result4
-rw-r--r--mysql-test/r/rpl_sp004.result16
-rw-r--r--mysql-test/r/rpl_sp_effects.result77
-rw-r--r--mysql-test/r/rpl_stm_log.result4
-rw-r--r--mysql-test/r/rpl_stm_until.result148
-rw-r--r--mysql-test/r/rpl_temporary.result20
-rw-r--r--mysql-test/r/rpl_user_variables.result1
-rw-r--r--mysql-test/r/select.result56
-rw-r--r--mysql-test/r/show_check.result14
-rw-r--r--mysql-test/r/skip_name_resolve.result1
-rw-r--r--mysql-test/r/sp-dynamic.result6
-rw-r--r--mysql-test/r/sp-error.result4
-rw-r--r--mysql-test/r/sp-goto.result205
-rw-r--r--mysql-test/r/sp-security.result1
-rw-r--r--mysql-test/r/sp-threads.result1
-rw-r--r--mysql-test/r/sp.result112
-rw-r--r--mysql-test/r/sp_notembedded.result4
-rw-r--r--mysql-test/r/sql_mode.result6
-rw-r--r--mysql-test/r/status.result20
-rw-r--r--mysql-test/r/strict.result10
-rw-r--r--mysql-test/r/subselect.result24
-rw-r--r--mysql-test/r/symlink.result6
-rw-r--r--mysql-test/r/system_mysql_db.result2
-rw-r--r--mysql-test/r/timezone2.result15
-rw-r--r--mysql-test/r/timezone_grant.result17
-rw-r--r--mysql-test/r/trigger-grant.result84
-rw-r--r--mysql-test/r/trigger.result140
-rw-r--r--mysql-test/r/type_float.result8
-rw-r--r--mysql-test/r/type_newdecimal.result14
-rw-r--r--mysql-test/r/type_ranges.result4
-rw-r--r--mysql-test/r/udf.result16
-rw-r--r--mysql-test/r/user_var.result3
-rw-r--r--mysql-test/r/variables.result113
-rw-r--r--mysql-test/r/view.result138
-rw-r--r--mysql-test/r/xml.result9
-rw-r--r--mysql-test/std_data/cacert.pem34
-rw-r--r--mysql-test/std_data/client-cert.pem87
-rw-r--r--mysql-test/std_data/client-key.pem20
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1-0.1.Databin0 -> 116228 bytes
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1-0.2.Databin0 -> 113556 bytes
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1.1.ctlbin0 -> 7936 bytes
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1.1.logbin0 -> 7592 bytes
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1.2.ctlbin0 -> 7936 bytes
-rw-r--r--mysql-test/std_data/ndb_backup50/BACKUP-1.2.logbin0 -> 7128 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1-0.1.Databin0 -> 110596 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1-0.2.Databin0 -> 103180 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1.1.ctlbin0 -> 12320 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1.1.logbin0 -> 7592 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1.2.ctlbin0 -> 12320 bytes
-rw-r--r--mysql-test/std_data/ndb_backup51/BACKUP-1.2.logbin0 -> 6996 bytes
-rw-r--r--mysql-test/std_data/server-cert.pem89
-rw-r--r--mysql-test/std_data/server-key.pem20
-rw-r--r--mysql-test/std_data/untrusted-cacert.pem53
-rw-r--r--mysql-test/t/alter_table.test13
-rw-r--r--mysql-test/t/analyze.test8
-rw-r--r--mysql-test/t/ansi.test12
-rw-r--r--mysql-test/t/archive.test2
-rw-r--r--mysql-test/t/auto_increment.test32
-rw-r--r--mysql-test/t/case.test11
-rw-r--r--mysql-test/t/cast.test2
-rw-r--r--mysql-test/t/contributors.test1
-rw-r--r--mysql-test/t/ctype_latin2_ch.test2
-rw-r--r--mysql-test/t/ctype_sjis.test2
-rw-r--r--mysql-test/t/ctype_ucs.test8
-rw-r--r--mysql-test/t/date_formats.test30
-rw-r--r--mysql-test/t/disabled.def49
-rw-r--r--mysql-test/t/distinct.test16
-rw-r--r--mysql-test/t/events.test139
-rw-r--r--mysql-test/t/events_bugs.test22
-rw-r--r--mysql-test/t/events_grant.test105
-rw-r--r--mysql-test/t/events_logs_tests.test20
-rw-r--r--mysql-test/t/events_microsec.test50
-rw-r--r--mysql-test/t/events_scheduling.test12
-rw-r--r--mysql-test/t/events_stress.test118
-rw-r--r--mysql-test/t/exampledb.test4
-rw-r--r--mysql-test/t/explain.test9
-rw-r--r--mysql-test/t/func_compress.test9
-rw-r--r--mysql-test/t/func_gconcat.test11
-rw-r--r--mysql-test/t/func_group.test71
-rw-r--r--mysql-test/t/func_in.test106
-rw-r--r--mysql-test/t/func_misc.test40
-rw-r--r--mysql-test/t/func_op.test14
-rw-r--r--mysql-test/t/func_str.test24
-rw-r--r--mysql-test/t/func_time.test39
-rw-r--r--mysql-test/t/grant2.test26
-rw-r--r--mysql-test/t/group_min_max.test16
-rw-r--r--mysql-test/t/having.test13
-rw-r--r--mysql-test/t/heap.test12
-rw-r--r--mysql-test/t/heap_btree.test12
-rw-r--r--mysql-test/t/im_cmd_line.imtest68
-rw-r--r--mysql-test/t/im_daemon_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_daemon_life_cycle.imtest3
-rw-r--r--mysql-test/t/im_instance_conf-im.opt1
-rw-r--r--mysql-test/t/im_instance_conf.imtest228
-rw-r--r--mysql-test/t/im_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_life_cycle.imtest95
-rw-r--r--mysql-test/t/im_options.imtest268
-rw-r--r--mysql-test/t/im_options_set.imtest142
-rw-r--r--mysql-test/t/im_options_unset.imtest150
-rw-r--r--mysql-test/t/im_utils-im.opt1
-rw-r--r--mysql-test/t/im_utils.imtest8
-rw-r--r--mysql-test/t/information_schema.test51
-rw-r--r--mysql-test/t/information_schema_chmod.test23
-rw-r--r--mysql-test/t/information_schema_inno.test32
-rw-r--r--mysql-test/t/innodb-master.opt2
-rw-r--r--mysql-test/t/innodb.test345
-rw-r--r--mysql-test/t/innodb_mysql.test131
-rw-r--r--mysql-test/t/innodb_unsafe_binlog-master.opt2
-rw-r--r--mysql-test/t/innodb_unsafe_binlog.test199
-rw-r--r--mysql-test/t/join_outer.test44
-rw-r--r--mysql-test/t/key_cache.test41
-rw-r--r--mysql-test/t/log_tables.test19
-rw-r--r--mysql-test/t/merge.test12
-rw-r--r--mysql-test/t/myisam-system.test21
-rw-r--r--mysql-test/t/myisam.test80
-rw-r--r--mysql-test/t/mysql.test13
-rw-r--r--mysql-test/t/mysql_client_test-master.opt1
-rw-r--r--mysql-test/t/mysqlbinlog.test15
-rw-r--r--mysql-test/t/mysqldump.test44
-rw-r--r--mysql-test/t/ndb_alter_table.test73
-rw-r--r--mysql-test/t/ndb_alter_table3.test (renamed from mysql-test/t/ndb_alter_table_row.test)1
-rw-r--r--mysql-test/t/ndb_alter_table_stm.test55
-rw-r--r--mysql-test/t/ndb_autodiscover3.test76
-rw-r--r--mysql-test/t/ndb_basic.test11
-rw-r--r--mysql-test/t/ndb_binlog_discover.test19
-rw-r--r--mysql-test/t/ndb_blob.test81
-rw-r--r--mysql-test/t/ndb_blob_partition.test93
-rw-r--r--mysql-test/t/ndb_condition_pushdown.test37
-rw-r--r--mysql-test/t/ndb_config.test1
-rw-r--r--mysql-test/t/ndb_config2.test7
-rw-r--r--mysql-test/t/ndb_dd_backuprestore.test180
-rw-r--r--mysql-test/t/ndb_dd_basic.test22
-rw-r--r--mysql-test/t/ndb_index_unique.test10
-rw-r--r--mysql-test/t/ndb_partition_error.test71
-rw-r--r--mysql-test/t/ndb_partition_key.test180
-rw-r--r--mysql-test/t/ndb_partition_list.test64
-rw-r--r--mysql-test/t/ndb_partition_range.test260
-rw-r--r--mysql-test/t/ndb_restore_compat.test43
-rw-r--r--mysql-test/t/null.test41
-rw-r--r--mysql-test/t/openssl_1.test48
-rw-r--r--mysql-test/t/order_by.test14
-rw-r--r--mysql-test/t/outfile.test1
-rw-r--r--mysql-test/t/partition.test68
-rw-r--r--mysql-test/t/partition_range.test28
-rw-r--r--mysql-test/t/ps.test36
-rw-r--r--mysql-test/t/ps_11bugs.test14
-rw-r--r--mysql-test/t/ps_1general.test3
-rw-r--r--mysql-test/t/query_cache.test2
-rw-r--r--mysql-test/t/rename.test8
-rw-r--r--mysql-test/t/rpl_bit_npk.test28
-rw-r--r--mysql-test/t/rpl_loaddatalocal.test4
-rw-r--r--mysql-test/t/rpl_multi_engine.test4
-rw-r--r--mysql-test/t/rpl_ndb_basic.test31
-rw-r--r--mysql-test/t/rpl_ndb_dd_partitions.test301
-rw-r--r--mysql-test/t/rpl_ndb_innodb2ndb-slave.opt2
-rw-r--r--mysql-test/t/rpl_ndb_myisam2ndb-slave.opt2
-rw-r--r--mysql-test/t/rpl_openssl.test1
-rw-r--r--mysql-test/t/rpl_rotate_logs.test3
-rw-r--r--mysql-test/t/rpl_row_basic_11bugs.test6
-rw-r--r--mysql-test/t/rpl_row_flsh_tbls.test5
-rw-r--r--mysql-test/t/rpl_sp004.test16
-rw-r--r--mysql-test/t/rpl_sp_effects.test38
-rw-r--r--mysql-test/t/rpl_stm_until.test8
-rw-r--r--mysql-test/t/rpl_temporary.test50
-rw-r--r--mysql-test/t/rpl_user_variables.test5
-rw-r--r--mysql-test/t/rpl_view-slave.opt1
-rw-r--r--mysql-test/t/select.test49
-rw-r--r--mysql-test/t/sp-goto.test238
-rw-r--r--mysql-test/t/sp-security.test1
-rw-r--r--mysql-test/t/sp.test145
-rw-r--r--mysql-test/t/sp_notembedded.test5
-rw-r--r--mysql-test/t/status.test102
-rw-r--r--mysql-test/t/strict.test10
-rw-r--r--mysql-test/t/subselect.test24
-rw-r--r--mysql-test/t/timezone2.test20
-rw-r--r--mysql-test/t/timezone_grant.test31
-rw-r--r--mysql-test/t/trigger-grant.test173
-rw-r--r--mysql-test/t/trigger.test176
-rw-r--r--mysql-test/t/udf.test28
-rw-r--r--mysql-test/t/user_var.test2
-rw-r--r--mysql-test/t/variables-master.opt1
-rw-r--r--mysql-test/t/variables.test135
-rw-r--r--mysql-test/t/view.test142
-rw-r--r--mysql-test/t/view_grant.test2
-rw-r--r--mysql-test/t/wait_timeout.test68
-rw-r--r--mysql-test/t/xml.test8
-rw-r--r--mysql-test/valgrind.supp248
-rw-r--r--mysys/CMakeLists.txt (renamed from mysys/cmakelists.txt)2
-rw-r--r--mysys/Makefile.am3
-rw-r--r--mysys/default.c10
-rw-r--r--mysys/default_modify.c58
-rw-r--r--mysys/errors.c6
-rw-r--r--mysys/mf_iocache2.c92
-rw-r--r--mysys/mf_keycache.c30
-rw-r--r--mysys/mf_path.c2
-rw-r--r--mysys/mf_tempfile.c2
-rw-r--r--mysys/my_access.c4
-rw-r--r--mysys/my_bit.c30
-rw-r--r--mysys/my_clock.c2
-rw-r--r--mysys/my_copy.c2
-rw-r--r--mysys/my_create.c9
-rw-r--r--mysys/my_dup.c2
-rw-r--r--mysys/my_file.c9
-rw-r--r--mysys/my_gethostbyname.c2
-rw-r--r--mysys/my_getopt.c2
-rw-r--r--mysys/my_getwd.c36
-rw-r--r--mysys/my_init.c7
-rw-r--r--mysys/my_lib.c114
-rw-r--r--mysys/my_memmem.c66
-rw-r--r--mysys/my_net.c4
-rw-r--r--mysys/my_open.c25
-rw-r--r--mysys/my_redel.c4
-rw-r--r--mysys/tree.c5
-rw-r--r--plugin/Makefile.am26
-rw-r--r--plugin/fulltext/Makefile.am2
-rw-r--r--plugin/fulltext/plugin_example.c2
-rw-r--r--regex/CMakeLists.txt (renamed from regex/cmakelists.txt)0
-rw-r--r--regex/Makefile.am2
-rw-r--r--scripts/Makefile.am3
-rw-r--r--scripts/make_binary_distribution.sh2
-rw-r--r--scripts/mysql_explain_log.sh392
-rw-r--r--scripts/mysql_fix_privilege_tables.sql4
-rw-r--r--scripts/mysqld_safe.sh68
-rw-r--r--server-tools/instance-manager/CMakeLists.txt (renamed from server-tools/instance-manager/cmakelists.txt)1
-rw-r--r--server-tools/instance-manager/IMService.cpp32
-rw-r--r--server-tools/instance-manager/IMService.h20
-rw-r--r--server-tools/instance-manager/Makefile.am7
-rw-r--r--server-tools/instance-manager/WindowsService.cpp33
-rw-r--r--server-tools/instance-manager/WindowsService.h18
-rw-r--r--server-tools/instance-manager/command.h18
-rw-r--r--server-tools/instance-manager/commands.cc1854
-rw-r--r--server-tools/instance-manager/commands.h303
-rw-r--r--server-tools/instance-manager/exit_codes.h41
-rw-r--r--server-tools/instance-manager/guardian.cc133
-rw-r--r--server-tools/instance-manager/guardian.h34
-rw-r--r--server-tools/instance-manager/instance.cc122
-rw-r--r--server-tools/instance-manager/instance.h118
-rw-r--r--server-tools/instance-manager/instance_map.cc436
-rw-r--r--server-tools/instance-manager/instance_map.h61
-rw-r--r--server-tools/instance-manager/instance_options.cc370
-rw-r--r--server-tools/instance-manager/instance_options.h59
-rw-r--r--server-tools/instance-manager/listener.cc25
-rw-r--r--server-tools/instance-manager/listener.h4
-rw-r--r--server-tools/instance-manager/log.cc12
-rw-r--r--server-tools/instance-manager/manager.cc152
-rw-r--r--server-tools/instance-manager/manager.h4
-rw-r--r--server-tools/instance-manager/messages.cc24
-rw-r--r--server-tools/instance-manager/mysql_connection.cc46
-rw-r--r--server-tools/instance-manager/mysql_manager_error.h8
-rw-r--r--server-tools/instance-manager/mysqlmanager.cc88
-rw-r--r--server-tools/instance-manager/options.cc457
-rw-r--r--server-tools/instance-manager/options.h94
-rw-r--r--server-tools/instance-manager/parse.cc351
-rw-r--r--server-tools/instance-manager/parse.h159
-rw-r--r--server-tools/instance-manager/parse_output.cc8
-rw-r--r--server-tools/instance-manager/parse_output.h2
-rw-r--r--server-tools/instance-manager/portability.h14
-rw-r--r--server-tools/instance-manager/priv.cc8
-rw-r--r--server-tools/instance-manager/priv.h30
-rw-r--r--server-tools/instance-manager/protocol.cc8
-rw-r--r--server-tools/instance-manager/protocol.h5
-rw-r--r--server-tools/instance-manager/thread_registry.cc11
-rw-r--r--server-tools/instance-manager/user_management_commands.cc406
-rw-r--r--server-tools/instance-manager/user_management_commands.h167
-rw-r--r--server-tools/instance-manager/user_map.cc325
-rw-r--r--server-tools/instance-manager/user_map.h63
-rw-r--r--sql-common/client.c126
-rw-r--r--sql-common/my_time.c2
-rw-r--r--sql/CMakeLists.txt (renamed from sql/cmakelists.txt)15
-rw-r--r--sql/Makefile.am39
-rw-r--r--sql/authors.h4
-rw-r--r--sql/contributors.h40
-rw-r--r--sql/event.cc1078
-rw-r--r--sql/event.h332
-rw-r--r--sql/event_executor.cc995
-rw-r--r--sql/event_priv.h70
-rw-r--r--sql/event_scheduler.cc2426
-rw-r--r--sql/event_scheduler.h254
-rw-r--r--sql/event_timed.cc705
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field.h6
-rw-r--r--sql/field_conv.cc3
-rw-r--r--sql/ha_berkeley.cc27
-rw-r--r--sql/ha_federated.cc26
-rw-r--r--sql/ha_heap.cc22
-rw-r--r--sql/ha_innodb.cc354
-rw-r--r--sql/ha_innodb.h3
-rw-r--r--sql/ha_myisam.cc35
-rw-r--r--sql/ha_myisammrg.cc26
-rw-r--r--sql/ha_ndbcluster.cc1133
-rw-r--r--sql/ha_ndbcluster.h56
-rw-r--r--sql/ha_ndbcluster_binlog.cc573
-rw-r--r--sql/ha_ndbcluster_binlog.h48
-rw-r--r--sql/ha_partition.cc396
-rw-r--r--sql/ha_partition.h10
-rw-r--r--sql/handler.cc194
-rw-r--r--sql/handler.h42
-rw-r--r--sql/handlerton-win.cc72
-rw-r--r--sql/handlerton.cc.in14
-rw-r--r--sql/item.cc99
-rw-r--r--sql/item.h134
-rw-r--r--sql/item_cmpfunc.cc56
-rw-r--r--sql/item_cmpfunc.h77
-rw-r--r--sql/item_create.cc10
-rw-r--r--sql/item_func.cc104
-rw-r--r--sql/item_func.h25
-rw-r--r--sql/item_strfunc.cc17
-rw-r--r--sql/item_strfunc.h3
-rw-r--r--sql/item_subselect.cc40
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/item_sum.h2
-rw-r--r--sql/item_timefunc.cc66
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/item_xmlfunc.cc26
-rw-r--r--sql/lex.h10
-rw-r--r--sql/lock.cc56
-rw-r--r--sql/log.cc62
-rw-r--r--sql/log_event.cc116
-rw-r--r--sql/log_event.h3
-rw-r--r--sql/mysql_priv.h222
-rw-r--r--sql/mysqld.cc279
-rw-r--r--sql/net_serv.cc9
-rw-r--r--sql/opt_range.cc314
-rw-r--r--sql/partition_element.h6
-rw-r--r--sql/partition_info.cc69
-rw-r--r--sql/partition_info.h14
-rw-r--r--sql/repl_failsafe.cc6
-rw-r--r--sql/rpl_rli.h11
-rw-r--r--sql/set_var.cc185
-rw-r--r--sql/set_var.h36
-rw-r--r--sql/share/errmsg.txt141
-rw-r--r--sql/sp.cc32
-rw-r--r--sql/sp_head.cc310
-rw-r--r--sql/sp_head.h18
-rw-r--r--sql/sp_pcontext.cc163
-rw-r--r--sql/sp_pcontext.h137
-rw-r--r--sql/sp_rcontext.cc35
-rw-r--r--sql/sp_rcontext.h16
-rw-r--r--sql/spatial.cc5
-rw-r--r--sql/spatial.h2
-rw-r--r--sql/sql_acl.cc118
-rw-r--r--sql/sql_acl.h1
-rw-r--r--sql/sql_base.cc200
-rw-r--r--sql/sql_builtin.cc.in13
-rw-r--r--sql/sql_class.cc42
-rw-r--r--sql/sql_class.h48
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_error.h2
-rw-r--r--sql/sql_insert.cc182
-rw-r--r--sql/sql_lex.cc48
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_parse.cc281
-rw-r--r--sql/sql_partition.cc1206
-rw-r--r--sql/sql_plugin.cc77
-rw-r--r--sql/sql_prepare.cc28
-rw-r--r--sql/sql_repl.cc18
-rw-r--r--sql/sql_select.cc633
-rw-r--r--sql/sql_show.cc606
-rw-r--r--sql/sql_string.cc2
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc1409
-rw-r--r--sql/sql_tablespace.cc50
-rw-r--r--sql/sql_test.cc16
-rw-r--r--sql/sql_trigger.cc4
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_view.cc40
-rw-r--r--sql/sql_yacc.yy474
-rw-r--r--sql/structs.h17
-rw-r--r--sql/table.cc55
-rw-r--r--sql/table.h7
-rw-r--r--sql/tztime.cc82
-rw-r--r--sql/tztime.h13
-rw-r--r--sql/udf_example.cc2
-rw-r--r--sql/unireg.cc35
-rw-r--r--storage/archive/CMakeLists.txt8
-rw-r--r--storage/archive/Makefile.am47
-rw-r--r--storage/archive/ha_archive.cc (renamed from sql/ha_archive.cc)141
-rw-r--r--storage/archive/ha_archive.h (renamed from sql/ha_archive.h)4
-rw-r--r--storage/archive/plug.in4
-rw-r--r--storage/bdb/CMakeLists.txt (renamed from storage/bdb/cmakelists.txt)0
-rw-r--r--storage/bdb/Makefile.in2
-rw-r--r--storage/blackhole/CMakeLists.txt6
-rw-r--r--storage/blackhole/Makefile.am52
-rw-r--r--storage/blackhole/ha_blackhole.cc (renamed from sql/ha_blackhole.cc)24
-rw-r--r--storage/blackhole/ha_blackhole.h (renamed from sql/ha_blackhole.h)0
-rw-r--r--storage/csv/CMakeLists.txt (renamed from storage/archive/cmakelists.txt)6
-rw-r--r--storage/csv/Makefile.am14
-rw-r--r--storage/csv/cmakelists.txt5
-rw-r--r--storage/csv/ha_tina.cc50
-rw-r--r--storage/example/CMakeLists.txt (renamed from storage/example/cmakelists.txt)0
-rw-r--r--storage/example/Makefile.am33
-rw-r--r--storage/example/ha_example.cc17
-rw-r--r--storage/example/plug.in4
-rw-r--r--storage/heap/CMakeLists.txt (renamed from storage/heap/cmakelists.txt)0
-rw-r--r--storage/heap/Makefile.am2
-rw-r--r--storage/heap/hp_create.c2
-rw-r--r--storage/heap/hp_delete.c3
-rw-r--r--storage/innobase/CMakeLists.txt (renamed from storage/innobase/cmakelists.txt)2
-rw-r--r--storage/innobase/Makefile.am32
-rw-r--r--storage/innobase/btr/btr0btr.c29
-rw-r--r--storage/innobase/btr/btr0cur.c23
-rw-r--r--storage/innobase/btr/btr0pcur.c5
-rw-r--r--storage/innobase/btr/btr0sea.c30
-rw-r--r--storage/innobase/buf/buf0lru.c20
-rw-r--r--storage/innobase/configure.in19
-rw-r--r--storage/innobase/data/data0type.c49
-rw-r--r--storage/innobase/dict/dict0crea.c370
-rw-r--r--storage/innobase/dict/dict0dict.c281
-rw-r--r--storage/innobase/dict/dict0load.c40
-rw-r--r--storage/innobase/dict/dict0mem.c50
-rw-r--r--storage/innobase/eval/eval0proc.c32
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c6
-rw-r--r--storage/innobase/include/btr0cur.h5
-rw-r--r--storage/innobase/include/btr0cur.ic6
-rw-r--r--storage/innobase/include/btr0sea.h4
-rw-r--r--storage/innobase/include/buf0lru.h4
-rw-r--r--storage/innobase/include/dict0dict.h55
-rw-r--r--storage/innobase/include/dict0dict.ic2
-rw-r--r--storage/innobase/include/dict0mem.h55
-rw-r--r--storage/innobase/include/eval0proc.h8
-rw-r--r--storage/innobase/include/hash0hash.h26
-rw-r--r--storage/innobase/include/lock0lock.h9
-rw-r--r--storage/innobase/include/mem0mem.h11
-rw-r--r--storage/innobase/include/os0thread.h2
-rw-r--r--storage/innobase/include/page0page.ic13
-rw-r--r--storage/innobase/include/pars0grm.h342
-rw-r--r--storage/innobase/include/pars0pars.h173
-rw-r--r--storage/innobase/include/pars0sym.h25
-rw-r--r--storage/innobase/include/pars0types.h4
-rw-r--r--storage/innobase/include/que0que.h20
-rw-r--r--storage/innobase/include/row0mysql.h3
-rw-r--r--storage/innobase/include/row0sel.h36
-rw-r--r--storage/innobase/include/row0upd.h4
-rw-r--r--storage/innobase/include/srv0srv.h42
-rw-r--r--storage/innobase/include/trx0roll.h6
-rw-r--r--storage/innobase/include/trx0trx.h4
-rw-r--r--storage/innobase/include/univ.i31
-rw-r--r--storage/innobase/include/ut0mem.h24
-rw-r--r--storage/innobase/include/ut0vec.h73
-rw-r--r--storage/innobase/include/ut0vec.ic26
-rw-r--r--storage/innobase/lock/lock0lock.c60
-rw-r--r--storage/innobase/log/log0recv.c9
-rw-r--r--storage/innobase/mem/mem0dbg.c2
-rw-r--r--storage/innobase/mem/mem0mem.c25
-rw-r--r--storage/innobase/os/os0sync.c2
-rw-r--r--storage/innobase/os/os0thread.c10
-rw-r--r--storage/innobase/pars/lexyy.c1083
-rwxr-xr-xstorage/innobase/pars/make_bison.sh3
-rwxr-xr-xstorage/innobase/pars/make_flex.sh20
-rw-r--r--storage/innobase/pars/pars0grm.c1784
-rw-r--r--storage/innobase/pars/pars0grm.h342
-rw-r--r--storage/innobase/pars/pars0grm.y61
-rw-r--r--storage/innobase/pars/pars0lex.l87
-rw-r--r--storage/innobase/pars/pars0opt.c50
-rw-r--r--storage/innobase/pars/pars0pars.c338
-rw-r--r--storage/innobase/pars/pars0sym.c71
-rw-r--r--storage/innobase/que/que0que.c134
-rw-r--r--storage/innobase/row/row0ins.c58
-rw-r--r--storage/innobase/row/row0mysql.c695
-rw-r--r--storage/innobase/row/row0sel.c213
-rw-r--r--storage/innobase/row/row0upd.c18
-rw-r--r--storage/innobase/srv/srv0srv.c68
-rw-r--r--storage/innobase/srv/srv0start.c17
-rw-r--r--storage/innobase/sync/sync0arr.c10
-rw-r--r--storage/innobase/sync/sync0rw.c17
-rw-r--r--storage/innobase/sync/sync0sync.c12
-rw-r--r--storage/innobase/trx/trx0roll.c14
-rw-r--r--storage/innobase/trx/trx0trx.c5
-rw-r--r--storage/innobase/ut/Makefile.am2
-rw-r--r--storage/innobase/ut/ut0mem.c93
-rw-r--r--storage/innobase/ut/ut0vec.c54
-rw-r--r--storage/myisam/CMakeLists.txt (renamed from storage/myisam/cmakelists.txt)0
-rw-r--r--storage/myisam/Makefile.am2
-rw-r--r--storage/myisam/ft_eval.c1
-rw-r--r--storage/myisam/ft_test1.c1
-rw-r--r--storage/myisam/mi_check.c36
-rw-r--r--storage/myisam/mi_create.c27
-rw-r--r--storage/myisam/mi_dynrec.c5
-rw-r--r--storage/myisam/mi_key.c2
-rw-r--r--storage/myisam/mi_open.c10
-rw-r--r--storage/myisam/mi_page.c9
-rw-r--r--storage/myisam/mi_test1.c1
-rw-r--r--storage/myisam/mi_test2.c14
-rw-r--r--storage/myisam/mi_test3.c2
-rw-r--r--storage/myisam/myisam_ftdump.c14
-rw-r--r--storage/myisam/myisamdef.h6
-rw-r--r--storage/myisam/myisamlog.c2
-rw-r--r--storage/myisam/myisampack.c3
-rw-r--r--storage/myisammrg/CMakeLists.txt (renamed from storage/myisammrg/cmakelists.txt)0
-rw-r--r--storage/myisammrg/Makefile.am2
-rwxr-xr-xstorage/ndb/home/bin/Linuxmkisofsbin503146 -> 0 bytes
-rwxr-xr-xstorage/ndb/home/bin/Solarismkisofsbin634084 -> 0 bytes
-rwxr-xr-xstorage/ndb/home/bin/cvs2cl.pl1865
-rwxr-xr-xstorage/ndb/home/bin/fix-cvs-root17
-rwxr-xr-xstorage/ndb/home/bin/import-from-bk.sh158
-rwxr-xr-xstorage/ndb/home/bin/ndb_deploy27
-rwxr-xr-xstorage/ndb/home/bin/ndbdoxy.pl184
-rwxr-xr-xstorage/ndb/home/bin/ngcalc78
-rw-r--r--storage/ndb/home/bin/parseConfigFile.awk98
-rwxr-xr-xstorage/ndb/home/bin/setup-test.sh272
-rw-r--r--storage/ndb/home/bin/signallog2html.lib/signallog2list.awk102
-rw-r--r--storage/ndb/home/bin/signallog2html.lib/uniq_blocks.awk29
-rwxr-xr-xstorage/ndb/home/bin/signallog2html.sh349
-rwxr-xr-xstorage/ndb/home/bin/stripcr90
-rw-r--r--storage/ndb/home/lib/funcs.sh294
-rw-r--r--storage/ndb/include/kernel/signaldata/DropFilegroup.hpp1
-rw-r--r--storage/ndb/include/kernel/signaldata/TcKeyReq.hpp1
-rw-r--r--storage/ndb/include/mgmapi/mgmapi.h18
-rw-r--r--storage/ndb/include/mgmapi/mgmapi_config_parameters.h1
-rw-r--r--storage/ndb/include/ndbapi/Ndb.hpp76
-rw-r--r--storage/ndb/include/ndbapi/NdbBlob.hpp1
-rw-r--r--storage/ndb/include/ndbapi/NdbDictionary.hpp18
-rw-r--r--storage/ndb/include/ndbapi/NdbIndexStat.hpp2
-rw-r--r--storage/ndb/include/ndbapi/NdbOperation.hpp4
-rw-r--r--storage/ndb/include/ndbapi/ndb_cluster_connection.hpp1
-rw-r--r--storage/ndb/include/util/NdbSqlUtil.hpp9
-rw-r--r--storage/ndb/include/util/SocketServer.hpp10
-rw-r--r--storage/ndb/include/util/ndb_opts.h6
-rw-r--r--storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp6
-rw-r--r--storage/ndb/src/common/util/NdbSqlUtil.cpp24
-rw-r--r--storage/ndb/src/common/util/SocketServer.cpp48
-rw-r--r--storage/ndb/src/common/util/socket_io.cpp70
-rw-r--r--storage/ndb/src/kernel/SimBlockList.cpp4
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp11
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupInit.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp85
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp339
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp2
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp37
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp15
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp33
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp3
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp64
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp10
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp70
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.cpp55
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.hpp20
-rw-r--r--storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp2
-rw-r--r--storage/ndb/src/kernel/blocks/restore.cpp29
-rw-r--r--storage/ndb/src/kernel/blocks/restore.hpp1
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.cpp17
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.cpp19
-rw-r--r--storage/ndb/src/mgmapi/mgmapi.cpp43
-rw-r--r--storage/ndb/src/mgmsrv/ConfigInfo.cpp14
-rw-r--r--storage/ndb/src/mgmsrv/MgmtSrvr.cpp164
-rw-r--r--storage/ndb/src/mgmsrv/MgmtSrvr.hpp10
-rw-r--r--storage/ndb/src/mgmsrv/Services.cpp84
-rw-r--r--storage/ndb/src/mgmsrv/Services.hpp2
-rw-r--r--storage/ndb/src/ndbapi/ClusterMgr.cpp18
-rw-r--r--storage/ndb/src/ndbapi/ClusterMgr.hpp8
-rw-r--r--storage/ndb/src/ndbapi/DictCache.cpp149
-rw-r--r--storage/ndb/src/ndbapi/DictCache.hpp11
-rw-r--r--storage/ndb/src/ndbapi/Ndb.cpp394
-rw-r--r--storage/ndb/src/ndbapi/NdbBlob.cpp24
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionary.cpp101
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp368
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp230
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp547
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp47
-rw-r--r--storage/ndb/src/ndbapi/NdbIndexStat.cpp2
-rw-r--r--storage/ndb/src/ndbapi/NdbScanOperation.cpp5
-rw-r--r--storage/ndb/src/ndbapi/NdbTransaction.cpp4
-rw-r--r--storage/ndb/src/ndbapi/Ndbif.cpp3
-rw-r--r--storage/ndb/src/ndbapi/Ndbinit.cpp8
-rw-r--r--storage/ndb/src/ndbapi/SignalSender.cpp2
-rw-r--r--storage/ndb/src/ndbapi/TransporterFacade.cpp9
-rw-r--r--storage/ndb/src/ndbapi/TransporterFacade.hpp9
-rw-r--r--storage/ndb/src/ndbapi/ndb_cluster_connection.cpp6
-rw-r--r--storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp1
-rw-r--r--storage/ndb/src/ndbapi/ndberror.c1
-rw-r--r--storage/ndb/test/ndbapi/Makefile.am2
-rw-r--r--storage/ndb/test/ndbapi/bank/Bank.cpp3
-rw-r--r--storage/ndb/test/ndbapi/bank/Bank.hpp2
-rw-r--r--storage/ndb/test/ndbapi/bank/BankLoad.cpp4
-rw-r--r--storage/ndb/test/ndbapi/bank/bankCreator.cpp3
-rw-r--r--storage/ndb/test/ndbapi/testBasic.cpp84
-rw-r--r--storage/ndb/test/ndbapi/testBlobs.cpp23
-rw-r--r--storage/ndb/test/ndbapi/testDict.cpp22
-rw-r--r--storage/ndb/test/ndbapi/testInterpreter.cpp202
-rw-r--r--storage/ndb/test/run-test/daily-basic-tests.txt12
-rw-r--r--storage/ndb/tools/delete_all.cpp31
-rw-r--r--storage/ndb/tools/desc.cpp8
-rw-r--r--storage/ndb/tools/listTables.cpp2
-rw-r--r--storage/ndb/tools/restore/Restore.cpp82
-rw-r--r--storage/ndb/tools/restore/Restore.hpp2
-rw-r--r--storage/ndb/tools/restore/consumer_restore.cpp9
-rw-r--r--storage/ndb/tools/restore/restore_main.cpp26
-rw-r--r--storage/ndb/tools/waiter.cpp6
-rw-r--r--strings/CHARSET_INFO.txt4
-rw-r--r--strings/CMakeLists.txt (renamed from strings/cmakelists.txt)0
-rw-r--r--strings/Makefile.am2
-rw-r--r--strings/my_vsnprintf.c13
-rw-r--r--support-files/mysql.server.sh5
-rw-r--r--support-files/mysql.spec.sh67
-rw-r--r--tests/CMakeLists.txt (renamed from tests/cmakelists.txt)2
-rw-r--r--tests/Makefile.am13
-rw-r--r--tests/mysql_client_test.c89
-rw-r--r--unittest/examples/no_plan.t.c2
-rw-r--r--unittest/examples/skip_all.t.c2
-rw-r--r--unittest/examples/todo.t.c2
-rw-r--r--unittest/mytap/t/basic.t.c4
-rw-r--r--vio/CMakeLists.txt (renamed from vio/cmakelists.txt)0
-rw-r--r--vio/Makefile.am2
-rw-r--r--vio/test-ssl.c4
-rw-r--r--vio/test-sslclient.c2
-rw-r--r--vio/test-sslserver.c4
-rw-r--r--vio/vio.c29
-rw-r--r--vio/vio_priv.h22
-rw-r--r--vio/viossl.c402
-rw-r--r--vio/viosslfactories.c315
-rw-r--r--zlib/CMakeLists.txt (renamed from zlib/cmakelists.txt)0
-rw-r--r--zlib/Makefile.am2
968 files changed, 49720 insertions, 23519 deletions
diff --git a/.bzrignore b/.bzrignore
index 751b823f1ea..57fcbdd8f73 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -291,6 +291,7 @@ client/my_decimal.h
client/my_user.c
client/mysql
client/mysql.cpp
+client/mysql_upgrade
client/mysqladmin
client/mysqladmin.c
client/mysqladmin.cpp
@@ -321,6 +322,7 @@ cmd-line-utils/libedit/makelist
comon.h
comp_err/*.ds?
comp_err/*.vcproj
+compile
config.cache
config.guess
config.h
@@ -367,6 +369,9 @@ extra/resolve_stack_dump
extra/resolveip
extra/sql_state.h
extra/tztime.cc
+extra/yassl/taocrypt/benchmark/benchmark
+extra/yassl/taocrypt/test/test
+extra/yassl/testsuite/testsuite
fcns.c
fcns.h
gdbinit
@@ -549,6 +554,7 @@ libmysqld/spatial.cc
libmysqld/sql_acl.cc
libmysqld/sql_analyse.cc
libmysqld/sql_base.cc
+libmysqld/sql_builtin.cc
libmysqld/sql_cache.cc
libmysqld/sql_class.cc
libmysqld/sql_command
@@ -679,6 +685,7 @@ mysql-test/mysql-test-run.log
mysql-test/mysql_test_run_new
mysql-test/ndb/ndbcluster
mysql-test/r/*.err
+mysql-test/r/*.log
mysql-test/r/*.out
mysql-test/r/*.reject
mysql-test/r/alter_table.err
@@ -1174,6 +1181,7 @@ sql/share/gmon.out
sql/share/mysql
sql/share/norwegian-ny/errmsg.sys
sql/share/norwegian/errmsg.sys
+sql/sql_builtin.cc
sql/sql_select.cc.orig
sql/sql_yacc.cc
sql/sql_yacc.h
@@ -1747,6 +1755,10 @@ tools/mysqlmanager
tools/mysqlmngd
tools/mysqltestmanager
tools/mysys_priv.h
+unittest/examples/*.t
+unittest/mysys/*.t
+unittest/mytap/t/*.t
+unittest/unit
vi.h
vio/*.ds?
vio/*.vcproj
@@ -1758,9 +1770,4 @@ vio/viotest-sslconnect.cpp
vio/viotest.cpp
zlib/*.ds?
zlib/*.vcproj
-mysql-test/r/*.log
-client/mysql_upgrade
-unittest/examples/*.t
-unittest/mysys/*.t
-unittest/mytap/t/*.t
-unittest/unit
+libmysqld/event_scheduler.cc
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 3c3facae34f..02d160158b3 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -82,8 +82,11 @@ path=`dirname $0`
export AM_MAKEFLAGS
AM_MAKEFLAGS="-j 4"
-# SSL library to use.
-SSL_LIBRARY=--with-yassl
+# SSL library to use.--with-ssl will select our bundled yaSSL
+# implementation of SSL. To use openSSl you will nee too point out
+# the location of openSSL headers and lbs on your system.
+# Ex --with-ssl=/usr
+SSL_LIBRARY=--with-ssl
if [ "x$warning_mode" != "xpedantic" ]; then
# Both C and C++ warnings
@@ -116,6 +119,7 @@ valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max"
# Used in -debug builds
debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS "
debug_cflags="$debug_cflags -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX"
+error_inject="--with-error-inject "
#
# Base C++ flags for all builds
base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
@@ -146,18 +150,9 @@ static_link="$static_link --with-client-ldflags=-all-static"
local_infile_configs="--enable-local-infile"
-max_configs="--with-innodb --with-berkeley-db"
-max_configs="$max_configs --with-archive-storage-engine"
-max_configs="$max_configs --with-big-tables"
-max_configs="$max_configs --with-blackhole-storage-engine"
-max_configs="$max_configs --with-federated-storage-engine"
-max_configs="$max_configs --with-csv-storage-engine"
-max_configs="$max_configs --with-example-storage-engine"
-max_configs="$max_configs --with-partition $SSL_LIBRARY"
-
-max_no_embedded_configs="$max_configs --with-ndbcluster"
-max_no_ndb_configs="$max_configs --without-ndbcluster --with-embedded-server"
-max_configs="$max_configs --with-ndbcluster --with-embedded-server"
+max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
+max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server"
+max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server"
#
# CPU and platform specific compilation flags.
diff --git a/BUILD/autorun.sh b/BUILD/autorun.sh
index 63bab3565c6..9ffe61b250a 100755
--- a/BUILD/autorun.sh
+++ b/BUILD/autorun.sh
@@ -3,19 +3,25 @@
die() { echo "$@"; exit 1; }
+# Added glibtoolize reference to make native OSX autotools work
+if [ -f /usr/bin/glibtoolize ]
+ then
+ LIBTOOLIZE=glibtoolize
+ else
+ LIBTOOLIZE=libtoolize
+fi
+
+(cd storage/bdb/dist && sh s_all)
+(cd storage/innobase && aclocal && autoheader && \
+ $LIBTOOLIZE --automake --force --copy && \
+ automake --force --add-missing --copy && autoconf)
+
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
+$LIBTOOLIZE --automake --force || die "Can't execute libtoolize"
# --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 storage/bdb/dist && sh s_all)
-(cd storage/innobase && aclocal && autoheader && aclocal && automake && autoconf)
diff --git a/BUILD/compile-dist b/BUILD/compile-dist
index dea29d4612b..326de19da13 100755
--- a/BUILD/compile-dist
+++ b/BUILD/compile-dist
@@ -7,13 +7,15 @@
# package" that is used as the basis for all other binary builds.
#
make distclean
+(cd storage/bdb/dist && sh s_all)
+(cd storage/innobase && aclocal && autoheader && \
+ libtoolize --automake --force --copy && \
+ automake --force --add-missing --copy && autoconf)
aclocal
autoheader
libtoolize --automake --force --copy
automake --force --add-missing --copy
autoconf
-(cd storage/bdb/dist && sh s_all)
-(cd storage/innobase && aclocal && autoheader && aclocal && automake && autoconf)
# Default to gcc for CC and CXX
if test -z "$CXX" ; then
@@ -52,7 +54,7 @@ fi
--with-federated-storage-engine \
--with-berkeley-db \
--with-innodb \
- --with-yassl \
+ --with-ssl \
--enable-thread-safe-client \
--with-extra-charsets=complex \
--with-ndbcluster \
diff --git a/BUILD/compile-pentium-debug-max b/BUILD/compile-pentium-debug-max
index d799311526b..adb9b7899a5 100755
--- a/BUILD/compile-pentium-debug-max
+++ b/BUILD/compile-pentium-debug-max
@@ -4,6 +4,6 @@ path=`dirname $0`
. "$path/SETUP.sh" "$@" --with-debug=full
extra_flags="$pentium_cflags $debug_cflags"
-extra_configs="$pentium_configs $debug_configs $max_configs"
+extra_configs="$pentium_configs $debug_configs $max_configs $error_inject"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-debug-openssl b/BUILD/compile-pentium-debug-openssl
index 91c3b448c7e..2e24dbfd2f1 100755
--- a/BUILD/compile-pentium-debug-openssl
+++ b/BUILD/compile-pentium-debug-openssl
@@ -6,6 +6,6 @@ path=`dirname $0`
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs"
-extra_configs="$extra_configs --with-debug=full --with-openssl"
+extra_configs="$extra_configs --with-debug=full --with-ssl=/usr"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-debug-yassl b/BUILD/compile-pentium-debug-yassl
index 84ca489903d..61ad2937c4a 100755
--- a/BUILD/compile-pentium-debug-yassl
+++ b/BUILD/compile-pentium-debug-yassl
@@ -6,6 +6,6 @@ path=`dirname $0`
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs"
-extra_configs="$extra_configs --with-debug=full --with-yassl"
+extra_configs="$extra_configs --with-debug=full --with-ssl"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-gcov b/BUILD/compile-pentium-gcov
index 05cb0bb0d78..b024bba49bf 100755
--- a/BUILD/compile-pentium-gcov
+++ b/BUILD/compile-pentium-gcov
@@ -3,8 +3,19 @@
path=`dirname $0`
. "$path/SETUP.sh"
-extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage"
+# Need to disable ccache, or we loose the gcov-needed compiler output files.
+CCACHE_DISABLE=1
+export CCACHE_DISABLE
+
+# GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well
+# as on the compiler command line), and this requires setting LDFLAGS for BDB.
+export LDFLAGS="-fprofile-arcs -ftest-coverage"
+
+# The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the
+# code with profiling information used by gcov.
+# the -DDISABLE_TAO_ASM is needed to avoid build failures in Yassl.
+extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM"
extra_configs="$pentium_configs $debug_configs --disable-shared $static_link"
-extra_configs="$extra_configs --with-innodb --with-berkeley-db"
+extra_configs="$extra_configs $max_configs"
. "$path/FINISH.sh"
diff --git a/cmakelists.txt b/CMakeLists.txt
index 0e91f49be90..5edc33b9f5a 100644
--- a/cmakelists.txt
+++ b/CMakeLists.txt
@@ -9,56 +9,53 @@ SET(WITH_CSV_STORAGE_ENGINE TRUE)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/mysql_version.h.in
${CMAKE_SOURCE_DIR}/include/mysql_version.h @ONLY)
+SET(WITH_HEAP_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_HEAP_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_heap_plugin")
+
+SET(WITH_MYISAM_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_MYISAM_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisam_plugin")
+
+SET(WITH_MYISAMMRG_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_MYISAMMRG_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisammrg_plugin")
+
IF(WITH_ARCHIVE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_ARCHIVE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &archive_hton")
- SET (mysql_se_decls "${mysql_se_decls}, archive_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_archive.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_archive_plugin")
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_BLACKHOLE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &blackhole_hton")
- SET (mysql_se_decls "${mysql_se_decls}, blackhole_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_blackhole.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_blackhole_plugin")
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
IF(WITH_CSV_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_CSV_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &tina_hton")
- SET (mysql_se_decls "${mysql_se_decls}, tina_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../storage/csv/ha_tina.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_csv_plugin")
ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_EXAMPLE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &example_hton")
- SET (mysql_se_decls "${mysql_se_decls}, example_hton")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_example_plugin")
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
IF(WITH_INNOBASE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_INNOBASE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &innobase_hton")
- SET (mysql_se_decls "${mysql_se_decls}, innobase_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_innodb.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin")
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
IF(WITH_PARTITION_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_PARTITION_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &partition_hton")
- SET (mysql_se_decls "${mysql_se_decls}, partition_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_partition.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
ENDIF(WITH_PARTITION_STORAGE_ENGINE)
IF(WITH_FEDERATED_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_FEDERATED_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &federated_hton")
- SET (mysql_se_decls "${mysql_se_decls}, federated_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_federated.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_federated_plugin")
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
IF(WITH_BERKELEY_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_BERKELEY_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &berkeley_hton")
- SET (mysql_se_decls "${mysql_se_decls}, berkeley_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_berkeley.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_berkeley_plugin")
ENDIF(WITH_BERKELEY_STORAGE_ENGINE)
-CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/handlerton.cc.in
- ${CMAKE_SOURCE_DIR}/sql/handlerton.cc @ONLY)
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
+ ${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc @ONLY)
SET(localstatedir "C:\\mysql\\data")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh
@@ -137,6 +134,12 @@ ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
IF(WITH_BERKELEY_STORAGE_ENGINE)
ADD_SUBDIRECTORY(storage/bdb)
ENDIF(WITH_BERKELEY_STORAGE_ENGINE)
+IF(WITH_BLACKHOLE_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/blackhole)
+ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
+IF(WITH_CSV_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/csv)
+ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
ADD_SUBDIRECTORY(storage/example)
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
diff --git a/Makefile.am b/Makefile.am
index dbf43151d60..dfa6c7f0f07 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,16 +20,15 @@ AUTOMAKE_OPTIONS = foreign
# These are built from source in the Docs directory
EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
- README COPYING EXCEPTIONS-CLIENT cmakelists.txt
+ README COPYING EXCEPTIONS-CLIENT CMakeLists.txt
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
- @sql_union_dirs@ storage \
+ @sql_union_dirs@ storage plugin \
@sql_server@ scripts @man_dirs@ tests \
- @mysql_se_plugins@ \
netware @libmysqld_dirs@ \
mysql-test support-files @tools_dirs@ \
- plugin unittest win
+ unittest win
DIST_SUBDIRS = $(SUBDIRS) BUILD
diff --git a/VC++Files/client/mysql_upgrade.dsp b/VC++Files/client/mysql_upgrade.dsp
index a039098d639..28eb2a58f39 100644
--- a/VC++Files/client/mysql_upgrade.dsp
+++ b/VC++Files/client/mysql_upgrade.dsp
@@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103
-CFG=mysql_upgrade - Win32 Release
+CFG=mysql_upgrade - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
@@ -13,59 +13,112 @@ CFG=mysql_upgrade - Win32 Release
!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 "mysql_upgrade.mak" CFG="mysql_upgrade - Win32 Release"
+!MESSAGE NMAKE /f "mysql_upgrade.mak" CFG="mysql_upgrade - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "mysql_upgrade - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysql_upgrade - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysql_upgrade - Win32 classic" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
+
+!IF "$(CFG)" == "mysql_upgrade - Win32 Release"
+
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "mysql_upgrade___Win32_Release"
-# PROP BASE Intermediate_Dir "mysql_upgrade___Win32_Release"
+# 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 "mysql_upgrade___Win32_Release"
-# PROP Intermediate_Dir "mysql_upgrade___Win32_Release"
+# 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 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /Fp"Release/mysql_upgrade.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c
-# ADD BASE RSC /l 0x416 /d "NDEBUG"
-# ADD RSC /l 0x416 /d "NDEBUG"
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /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=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 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 /pdb:"release/mysql_upgrade.pdb" /machine:I386 /out:"../client_release/mysql_upgrade.exe" /libpath:"..\lib_release\\"
-# SUBTRACT LINK32 /pdb:none
+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 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/mysql_upgrade.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /incremental:yes
+
+!ELSEIF "$(CFG)" == "mysql_upgrade - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqlimp"
+# PROP BASE Intermediate_Dir "mysqlimp"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /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
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+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:console /debug /machine:I386 /pdbtype:sept
+# 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/mysql_upgrade.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ELSEIF "$(CFG)" == "mysql_upgrade - Win32 classic"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysql_upgrade___Win32_classic"
+# PROP BASE Intermediate_Dir "mysql_upgrade___Win32_classic"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "classic"
+# PROP Intermediate_Dir "classic"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /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"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# 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/mysql_upgrade.exe" /libpath:"..\lib_release\\"
+# SUBTRACT BASE LINK32 /incremental:yes
+# 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/mysql_upgrade.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /incremental:yes
+
+!ENDIF
+
# Begin Target
# Name "mysql_upgrade - Win32 Release"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Name "mysql_upgrade - Win32 Debug"
+# Name "mysql_upgrade - Win32 classic"
# Begin Source File
SOURCE=.\mysql_upgrade.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/client/mysql_upgrade.vcproj b/VC++Files/client/mysql_upgrade.vcproj
new file mode 100644
index 00000000000..38cae600a75
--- /dev/null
+++ b/VC++Files/client/mysql_upgrade.vcproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysql_upgrade"
+ 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/mysql_upgrade.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/mysql_upgrade.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysql_upgrade.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysql_upgrade.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/mysql_upgrade.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_upgrade.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysql_upgrade.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysql_upgrade.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/mysql_upgrade.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/mysql_upgrade.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysql_upgrade.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysql_upgrade.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="mysql_upgrade.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/mysql_upgrade_ia64.dsp b/VC++Files/client/mysql_upgrade_ia64.dsp
index a116f3f06c3..5cb42ba0224 100644
--- a/VC++Files/client/mysql_upgrade_ia64.dsp
+++ b/VC++Files/client/mysql_upgrade_ia64.dsp
@@ -4,21 +4,23 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103
-CFG=mysql_upgrade - Win32 Release
+CFG=mysql_upgrade - WinIA64 classic
!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 "mysql_upgrade.mak".
-!MESSAGE
+!MESSAGE
+!MESSAGE NMAKE /f "mysql_upgrade_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 "mysql_upgrade.mak" CFG="mysql_upgrade - Win32 Release"
-!MESSAGE
+!MESSAGE
+!MESSAGE NMAKE /f "mysql_upgrade_ia64.mak" CFG="mysql_upgrade - WinIA64 classic"
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysql_upgrade - WinIA64 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE "mysql_upgrade - WinIA64 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysql_upgrade - WinIA64 classic" (based on "Win32 (x86) Console Application")
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -27,51 +29,96 @@ CFG=mysql_upgrade - Win32 Release
CPP=cl.exe
RSC=rc.exe
-!IF "$(CFG)" == "mysql - WinIA64 Release"
+!IF "$(CFG)" == "mysql_upgrade - WinIA64 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "mysql_upgrade___WinIA64_Release"
-# PROP BASE Intermediate_Dir "mysql_upgrade___WinIA64_Release"
+# 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 "mysql_upgrade___WinIA64_Release"
-# PROP Intermediate_Dir "mysql_upgrade___WinIA64_Release"
+# 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 /MT /W3 /I "../include" /D"NDEBUG" /D"DBUG_OFF" /D"_CONSOLE" /D"_MBCS" /D"_WINDOWS" /Fp"Release/mysql_upgrade.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c /O2 /G2 /EHsc /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Wp64 /Zm600
-# ADD BASE RSC /l 0x416 /d "NDEBUG"
-# ADD RSC /l 0x416 /d "NDEBUG"
+# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /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=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 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 /pdb:"release/mysql_upgrade.pdb" /machine:IA64 /out:"../client_release/mysql_upgrade.exe" /libpath:"..\lib_release\\" /incremental:no
-# SUBTRACT LINK32
+# 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:IA64
+# ADD LINK32 ..\lib_release\zlib.lib 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 bufferoverflowU.lib zlib.lib /nologo /subsystem:console /out:"../client_release/mysql_upgrade.exe" /libpath:"..\lib_release\\" /machine:IA64
-!ENDIF
+!ELSEIF "$(CFG)" == "mysql_upgrade - WinIA64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqlimp"
+# PROP BASE Intermediate_Dir "mysqlimp"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN64" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Zi /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
+# SUBTRACT CPP /YX
+# 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:console /debug /machine:IA64
+# ADD LINK32 setargv.obj ..\lib_debug\zlib.lib ..\lib_debug\dbug.lib 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 bufferoverflowU.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /out:"../client_debug/mysql_upgrade.exe" /libpath:"..\lib_debug\\" /machine:IA64
+
+!ELSEIF "$(CFG)" == "mysql_upgrade - WinIA64 classic"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysql_upgrade___WinIA64_classic"
+# PROP BASE Intermediate_Dir "mysql_upgrade___WinIA64_classic"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "classic"
+# PROP Intermediate_Dir "classic"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+MTL=midl.exe
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../" /D "_CONSOLE" /D "_WINDOWS" /D LICENSE=Commercial /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /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=link.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 /out:"../client_release/mysql_upgrade.exe" /libpath:"..\lib_release\\" /machine:IA64
+# ADD LINK32 ..\lib_release\zlib.lib 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 bufferoverflowU.lib zlib.lib /nologo /subsystem:console /out:"../client_classic/mysql_upgrade.exe" /libpath:"..\lib_release\\" /machine:IA64
+
+!ENDIF
# Begin Target
# Name "mysql_upgrade - WinIA64 Release"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Name "mysql_upgrade - WinIA64 Debug"
+# Name "mysql_upgrade - WinIA64 classic"
# Begin Source File
SOURCE=.\mysql_upgrade.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/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index 9c4485210a6..1c80147a8f5 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -363,6 +363,10 @@ SOURCE=..\mysys\my_getopt.c
SOURCE=..\sql-common\my_time.c
# End Source File
# Begin Source File
+
+SOURCE=..\sql-common\my_user.c
+# End Source File
+# Begin Source File
SOURCE=..\sql\net_serv.cpp
# End Source File
diff --git a/VC++Files/libmysqld/libmysqld_ia64.dsp b/VC++Files/libmysqld/libmysqld_ia64.dsp
index b5223e38f2d..9668193fc1d 100644
--- a/VC++Files/libmysqld/libmysqld_ia64.dsp
+++ b/VC++Files/libmysqld/libmysqld_ia64.dsp
@@ -338,6 +338,10 @@ SOURCE="..\sql-common\my_time.c"
# End Source File
# Begin Source File
+SOURCE="..\sql-common\my_user.c"
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index dd70ad630a1..a5f5a214bd6 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -446,6 +446,9 @@ Package=<4>
Project_Dep_Name mysqlimport
End Project Dependency
Begin Project Dependency
+ Project_Dep_Name mysql_upgrade
+ End Project Dependency
+ Begin Project Dependency
Project_Dep_Name mysqlshow
End Project Dependency
Begin Project Dependency
@@ -530,6 +533,24 @@ Package=<4>
###############################################################################
+Project: "mysql_upgrade"=".\client\mysql_upgade.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+}}}
+
+###############################################################################
+
Project: "mysqlserver"=".\mysqlserver\mysqlserver.dsp" - Package Owner=<4>
Package=<5>
diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln
index 344aaa38507..c5bf8291888 100644
--- a/VC++Files/mysql.sln
+++ b/VC++Files/mysql.sln
@@ -157,6 +157,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlimport", "client\mysql
{44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_upgrade", "client\mysql_upgrade.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}
@@ -249,6 +257,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_client_test", "tests\mysql_client_test.vcproj", "{DA224DAB-5006-42BE-BB77-16E8BE5326D5}"
ProjectSection(ProjectDependencies) = postProject
{26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlmanager", "server-tools\instance-manager\mysqlmanager.vcproj", "{6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}"
diff --git a/VC++Files/mysql_ia64.dsw b/VC++Files/mysql_ia64.dsw
index 96878cd3651..0f9c5471f7e 100644
--- a/VC++Files/mysql_ia64.dsw
+++ b/VC++Files/mysql_ia64.dsw
@@ -528,6 +528,9 @@ Package=<4>
Project_Dep_Name mysqlimport
End Project Dependency
Begin Project Dependency
+ Project_Dep_Name mysql_upgrade
+ End Project Dependency
+ Begin Project Dependency
Project_Dep_Name mysqlshow
End Project Dependency
Begin Project Dependency
@@ -600,6 +603,21 @@ Package=<4>
###############################################################################
+Project: "mysql_upgrade"=".\client\mysql_upgrade_ia64.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
Project: "mysqlserver"=".\mysqlserver\mysqlserver_ia64.dsp" - Package Owner=<4>
Package=<5>
diff --git a/VC++Files/mysys/mysys.vcproj b/VC++Files/mysys/mysys.vcproj
index befb4ad58b0..cf367e5666b 100644
--- a/VC++Files/mysys/mysys.vcproj
+++ b/VC++Files/mysys/mysys.vcproj
@@ -3233,6 +3233,49 @@
</FileConfiguration>
</File>
<File
+ RelativePath="my_memmem.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">
diff --git a/client/cmakelists.txt b/client/CMakeLists.txt
index 26cc36c7f6f..26cc36c7f6f 100644
--- a/client/cmakelists.txt
+++ b/client/CMakeLists.txt
diff --git a/client/Makefile.am b/client/Makefile.am
index 0531d741764..aa78f825c87 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -77,7 +77,7 @@ strings_src=decimal.c
DEFS = -DUNDEF_THREADS_HACK \
-DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
-DDATADIR="\"$(localstatedir)\""
-EXTRA_DIST = get_password.c cmakelists.txt
+EXTRA_DIST = get_password.c CMakeLists.txt
link_sources:
for f in $(sql_src) ; do \
diff --git a/client/client_priv.h b/client/client_priv.h
index 625fbf24fa6..bcaa74d3228 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -58,5 +58,5 @@ enum options_client
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID,
- OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES
+ OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT
};
diff --git a/client/client_priv.h.rej b/client/client_priv.h.rej
new file mode 100644
index 00000000000..ac3818bb1e1
--- /dev/null
+++ b/client/client_priv.h.rej
@@ -0,0 +1,15 @@
+***************
+*** 50,55 ****
+ OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
+ #endif
+ OPT_TRIGGERS,
+ OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
+! OPT_TZ_UTC, OPT_AUTO_CLOSE
+ };
+--- 50,55 ----
+ OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
+ #endif
+ OPT_TRIGGERS,
+ OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
+! OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT
+ };
diff --git a/client/get_password.c b/client/get_password.c
index 1b7b4e65a9f..b643b760718 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -64,7 +64,7 @@
/* were just going to fake it here and get input from
the keyboard */
-char *get_tty_password(char *opt_message)
+char *get_tty_password(const char *opt_message)
{
char to[80];
char *pos=to,*end=to+sizeof(to)-1;
@@ -150,7 +150,7 @@ static void get_password(char *to,uint length,int fd,bool echo)
#endif /* ! HAVE_GETPASS */
-char *get_tty_password(char *opt_message)
+char *get_tty_password(const char *opt_message)
{
#ifdef HAVE_GETPASS
char *passbuff;
diff --git a/client/mysql.cc b/client/mysql.cc
index 900bdec067a..96df1fafc3b 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -136,7 +136,7 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
default_charset_used= 0, opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
- show_warnings = 0;
+ show_warnings= 0, executing_query= 0, interrupted_query= 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;
@@ -338,7 +338,7 @@ static void end_timer(ulong start_time,char *buff);
static void mysql_end_timer(ulong start_time,char *buff);
static void nice_time(double sec,char *buff,bool part_second);
static sig_handler mysql_end(int sig);
-
+static sig_handler handle_sigint(int sig);
int main(int argc,char *argv[])
{
@@ -420,7 +420,7 @@ int main(int argc,char *argv[])
if (opt_sigint_ignore)
signal(SIGINT, SIG_IGN);
else
- signal(SIGINT, mysql_end); // Catch SIGINT to clean up
+ signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
/*
@@ -448,6 +448,14 @@ int main(int argc,char *argv[])
MYF(MY_WME));
if (histfile)
sprintf(histfile,"%s/.mysql_history",getenv("HOME"));
+ char link_name[FN_REFLEN];
+ if (my_readlink(link_name, histfile, 0) == 0 &&
+ strncmp(link_name, "/dev/null", 10) == 0)
+ {
+ /* The .mysql_history file is a symlink to /dev/null, don't use it */
+ my_free(histfile, MYF(MY_ALLOW_ZERO_PTR));
+ histfile= 0;
+ }
}
if (histfile)
{
@@ -484,7 +492,7 @@ sig_handler mysql_end(int sig)
{
mysql_close(&mysql);
#ifdef HAVE_READLINE
- if (!status.batch && !quick && !opt_html && !opt_xml)
+ if (!status.batch && !quick && !opt_html && !opt_xml && histfile)
{
/* write-history */
if (verbose)
@@ -523,6 +531,35 @@ sig_handler mysql_end(int sig)
}
+/*
+ This function handles sigint calls
+ If query is in process, kill query
+ no query in process, terminate like previous behavior
+ */
+sig_handler handle_sigint(int sig)
+{
+ char kill_buffer[40];
+ MYSQL *kill_mysql= NULL;
+
+ /* terminate if no query being executed, or we already tried interrupting */
+ if (!executing_query || interrupted_query)
+ mysql_end(sig);
+
+ kill_mysql= mysql_init(kill_mysql);
+ if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
+ "", opt_mysql_port, opt_mysql_unix_port,0))
+ mysql_end(sig);
+
+ /* kill_buffer is always big enough because max length of %lu is 15 */
+ sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql));
+ mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer));
+ mysql_close(kill_mysql);
+ tee_fprintf(stdout, "Query aborted by Ctrl+C\n");
+
+ interrupted_query= 1;
+}
+
+
static struct my_option my_long_options[] =
{
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -1932,6 +1969,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
uint error= 0;
int err= 0;
+ interrupted_query= 0;
if (!status.batch)
{
old_buffer= *buffer; // Save for edit command
@@ -1967,7 +2005,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
}
timer=start_timer();
-
+ executing_query= 1;
error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
#ifdef HAVE_READLINE
@@ -1981,6 +2019,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (error)
{
+ executing_query= 0;
buffer->length(0); // Remove query on error
return error;
}
@@ -1992,13 +2031,19 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (quick)
{
if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql))
- return put_error(&mysql);
+ {
+ executing_query= 0;
+ return put_error(&mysql);
+ }
}
else
{
error= mysql_store_result_for_lazy(&result);
if (error)
- return error;
+ {
+ executing_query= 0;
+ return error;
+ }
}
if (verbose >= 3 || !opt_silent)
@@ -2073,6 +2118,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
(mysql.server_status & SERVER_STATUS_DB_DROPPED))
get_current_db();
+ executing_query= 0;
return error; /* New command follows */
}
@@ -2241,8 +2287,10 @@ print_table_data(MYSQL_RES *result)
MYSQL_ROW cur;
MYSQL_FIELD *field;
bool *num_flag;
+ bool *not_null_flag;
num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
+ not_null_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
if (info_flag)
{
print_field_types(result);
@@ -2260,7 +2308,7 @@ print_table_data(MYSQL_RES *result)
length=max(length,field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length=4; // Room for "NULL"
- field->max_length=length+1;
+ field->max_length=length;
separator.fill(separator.length()+length+2,'-');
separator.append('+');
}
@@ -2272,10 +2320,11 @@ print_table_data(MYSQL_RES *result)
(void) tee_fputs("|", PAGER);
for (uint off=0; (field = mysql_fetch_field(result)) ; off++)
{
- tee_fprintf(PAGER, " %-*s|",(int) min(field->max_length,
+ tee_fprintf(PAGER, " %-*s |",(int) min(field->max_length,
MAX_COLUMN_LENGTH),
field->name);
num_flag[off]= IS_NUM(field->type);
+ not_null_flag[off]= IS_NOT_NULL(field->flags);
}
(void) tee_fputs("\n", PAGER);
tee_puts((char*) separator.ptr(), PAGER);
@@ -2283,6 +2332,8 @@ print_table_data(MYSQL_RES *result)
while ((cur= mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths= mysql_fetch_lengths(result);
(void) tee_fputs("| ", PAGER);
mysql_field_seek(result, 0);
@@ -2295,7 +2346,7 @@ print_table_data(MYSQL_RES *result)
uint visible_length;
uint extra_padding;
- if (lengths[off] == 0)
+ if (! not_null_flag[off] && (cur[off] == NULL))
{
buffer= "NULL";
data_length= 4;
@@ -2335,6 +2386,7 @@ print_table_data(MYSQL_RES *result)
}
tee_puts((char*) separator.ptr(), PAGER);
my_afree((gptr) num_flag);
+ my_afree((gptr) not_null_flag);
}
@@ -2349,11 +2401,8 @@ tee_print_sized_data(const char *data, unsigned int data_length, unsigned int to
unsigned int i;
const char *p;
- total_bytes_to_send -= 1;
- /* Off by one, perhaps mistakenly accounting for a terminating NUL. */
-
if (right_justified)
- for (i= 0; i < (total_bytes_to_send - data_length); i++)
+ for (i= data_length; i < total_bytes_to_send; i++)
tee_putc((int)' ', PAGER);
for (i= 0, p= data; i < data_length; i+= 1, p+= 1)
@@ -2365,7 +2414,7 @@ tee_print_sized_data(const char *data, unsigned int data_length, unsigned int to
}
if (! right_justified)
- for (i= 0; i < (total_bytes_to_send - data_length); i++)
+ for (i= data_length; i < total_bytes_to_send; i++)
tee_putc((int)' ', PAGER);
}
@@ -2391,6 +2440,8 @@ print_table_data_html(MYSQL_RES *result)
}
while ((cur = mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("<TR>", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
@@ -2420,6 +2471,8 @@ print_table_data_xml(MYSQL_RES *result)
fields = mysql_fetch_fields(result);
while ((cur = mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("\n <row>\n", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
@@ -2454,6 +2507,8 @@ print_table_data_vertically(MYSQL_RES *result)
mysql_field_seek(result,0);
for (uint row_count=1; (cur= mysql_fetch_row(result)); row_count++)
{
+ if (interrupted_query)
+ break;
mysql_field_seek(result,0);
tee_fprintf(PAGER,
"*************************** %d. row ***************************\n", row_count);
@@ -3096,6 +3151,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
#endif
if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 78e4acd4c1d..3288b627554 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -135,7 +135,9 @@ static int create_check_file(const char *path)
if (check_file < 0)
return 1;
- error= my_write(check_file, VERSION, strlen(VERSION), MYF(MY_WME | MY_FNABP));
+ error= my_write(check_file,
+ MYSQL_SERVER_VERSION, strlen(MYSQL_SERVER_VERSION),
+ MYF(MY_WME | MY_FNABP));
error= my_close(check_file, MYF(MY_FAE | MY_WME)) || error;
return error;
}
@@ -243,7 +245,7 @@ int main(int argc, char **argv)
&& (test_file_exists("./bin", "mysqld") ||
test_file_exists("./libexec", "mysqld")))
{
- getcwd(bindir, sizeof(bindir));
+ my_getwd(bindir, sizeof(bindir), MYF(0));
bindir_end= bindir + strlen(bindir);
}
else
@@ -305,7 +307,7 @@ int main(int argc, char **argv)
b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0));
chf_buffer[b_read]= 0;
my_close(check_file, MYF(0));
- if (!strcmp(chf_buffer, VERSION))
+ if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION))
{
if (opt_verbose)
puts("mysql_upgrade already done for this version");
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 5b52d524f8e..57ab4e071fb 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -340,6 +340,8 @@ int main(int argc,char *argv[])
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
#endif
if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 490a74e6035..4b2527c25ef 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -815,7 +815,8 @@ static void die(const char* fmt, ...)
fprintf(stderr, "\n");
va_end(args);
cleanup();
- my_end(0);
+ /* We cannot free DBUG, it is used in global destructors after exit(). */
+ my_end(MY_DONT_FREE_DBUG);
exit(1);
}
@@ -1487,7 +1488,8 @@ int main(int argc, char** argv)
cleanup();
free_defaults(defaults_argv);
my_free_open_file_info();
- my_end(0);
+ /* We cannot free DBUG, it is used in global destructors after exit(). */
+ my_end(MY_DONT_FREE_DBUG);
exit(exit_value);
DBUG_RETURN(exit_value); // Keep compilers happy
}
diff --git a/client/mysqldump.c b/client/mysqldump.c
index f268ca5b468..58cd2342bd3 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -50,6 +50,7 @@
#include "mysql.h"
#include "mysql_version.h"
#include "mysqld_error.h"
+#include "../sql/ha_ndbcluster_tables.h"
/* Exit codes */
@@ -134,7 +135,6 @@ 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[]=
{
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
@@ -918,6 +918,8 @@ static int dbConnect(char *host, char *user,char *passwd)
if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
#endif
if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
@@ -2937,6 +2939,8 @@ static int dump_all_tables_in_db(char *database)
afterdot= strmov(hash_key, database);
*afterdot++= '.';
+ if (!strcmp(database, NDB_REP_DB)) /* Skip cluster internal database */
+ return 0;
if (init_dumping(database))
return 1;
if (opt_xml)
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 42d521a1412..ccd6932e25b 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -406,6 +406,8 @@ static MYSQL *db_connect(char *host, char *database,
if (opt_use_ssl)
mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
#endif
if (opt_protocol)
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 504f0d9844b..d090495ff81 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -109,6 +109,8 @@ int main(int argc, char **argv)
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
#endif
if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index d9b4230348e..11d3ae5a2df 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -457,8 +457,8 @@ static struct my_option my_long_options[] =
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
{"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA,
- "Preserve the schema from the mysqlslap run, this happens unless \
- --auto-generate-sql or --create are used.",
+ "Preserve the schema from the mysqlslap run, this happens unless "
+ "--auto-generate-sql or --create are used.",
(gptr*) &opt_preserve, (gptr*) &opt_preserve, 0, GET_BOOL,
NO_ARG, TRUE, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL,
diff --git a/client/mysqltest.c b/client/mysqltest.c
index cfd69e45ba7..774cbac6e3f 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -87,14 +87,6 @@
#endif
#define MAX_SERVER_ARGS 64
-/*
- Sometimes in a test the client starts before
- the server - to solve the problem, we try again
- after some sleep if connection fails the first
- time
-*/
-#define CON_RETRY_SLEEP 2
-#define MAX_CON_TRIES 5
#define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
#define DEFAULT_DELIMITER ";"
@@ -108,7 +100,7 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL,
- OPT_VIEW_PROTOCOL};
+ OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES};
/* ************************************************************************ */
/*
@@ -153,11 +145,12 @@ static uint global_expected_errors;
/* ************************************************************************ */
-static int record = 0, opt_sleep=0;
+static int record= 0, opt_sleep= -1;
static char *db = 0, *pass=0;
const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
const char *opt_include= 0;
static int port = 0;
+static int opt_max_connect_retries;
static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
static my_bool tty_password= 0;
static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
@@ -688,10 +681,11 @@ static void die(const char *fmt, ...)
/* Note that we will get some memory leaks when calling this! */
-static void abort_not_supported_test()
+static void abort_not_supported_test(const char *fname)
{
DBUG_ENTER("abort_not_supported_test");
- fprintf(stderr, "This test is not supported by this installation\n");
+ fprintf(stderr, "The test '%s' is not supported by this installation\n",
+ fname);
if (!silent)
printf("skipped\n");
free_used_memory();
@@ -814,7 +808,7 @@ static void check_result(DYNAMIC_STRING* ds, const char *fname,
DBUG_ENTER("check_result");
if (res && require_option)
- abort_not_supported_test();
+ abort_not_supported_test(fname);
switch (res) {
case RESULT_OK:
break; /* ok */
@@ -1036,7 +1030,7 @@ int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused)))
int do_require_manager(struct st_query *query __attribute__((unused)) )
{
if (!manager)
- abort_not_supported_test();
+ abort_not_supported_test("manager");
return 0;
}
@@ -1305,7 +1299,9 @@ int var_query_set(VAR* var, const char *query, const char** query_end)
uint i;
ulong *lengths;
char *end;
+#ifdef NOT_YET
MYSQL_FIELD *fields= mysql_fetch_fields(res);
+#endif
init_dynamic_string(&result, "", 16384, 65536);
lengths= mysql_fetch_lengths(res);
@@ -1880,11 +1876,12 @@ int do_sleep(struct st_query *query, my_bool real_sleep)
query->first_argument);
/* Fixed sleep time selected by --sleep option */
- if (opt_sleep && !real_sleep)
+ if (opt_sleep >= 0 && !real_sleep)
sleep_val= opt_sleep;
DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
- my_sleep((ulong) (sleep_val * 1000000L));
+ if (sleep_val)
+ my_sleep((ulong) (sleep_val * 1000000L));
query->last_argument= sleep_end;
return 0;
}
@@ -1919,7 +1916,7 @@ static void set_charset(struct st_query *q)
q->last_argument= p;
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
if (!charset_info)
- abort_not_supported_test();
+ abort_not_supported_test(charset_name);
}
static uint get_errcodes(match_err *to,struct st_query *q)
@@ -1956,7 +1953,13 @@ static uint get_errcodes(match_err *to,struct st_query *q)
;
for (; e->name; e++)
{
- if (!strncmp(start, e->name, (int) (p - start)))
+ /*
+ If we get a match, we need to check the length of the name we
+ matched against in case it was longer than what we are checking
+ (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
+ */
+ if (!strncmp(start, e->name, (int) (p - start)) &&
+ (uint) strlen(e->name) == (uint) (p - start))
{
to[count].code.errnum= (uint) e->code;
to[count].type= ERR_ERRNO;
@@ -2491,9 +2494,16 @@ void init_manager()
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
+
+ Sometimes in a test the client starts before
+ the server - to solve the problem, we try again
+ after some sleep if connection fails the first
+ time
+
+ This function will try to connect to the given server
+ "opt_max_connect_retries" times and sleep "connection_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
@@ -2508,8 +2518,9 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user,
{
int con_error= 1;
my_bool reconnect= 1;
+ static int connection_retry_sleep= 2; /* Seconds */
int i;
- for (i= 0; i < MAX_CON_TRIES; ++i)
+ for (i= 0; i < opt_max_connect_retries; i++)
{
if (mysql_real_connect(mysql, host,user, pass, db, port, sock,
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
@@ -2517,7 +2528,7 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user,
con_error= 0;
break;
}
- sleep(CON_RETRY_SLEEP);
+ sleep(connection_retry_sleep);
}
/*
TODO: change this to 0 in future versions, but the 'kill' test relies on
@@ -2745,8 +2756,12 @@ int do_connect(struct st_query *q)
#ifdef HAVE_OPENSSL
if (opt_use_ssl || con_ssl)
+ {
mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ &opt_ssl_verify_server_cert);
+ }
#endif
if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR)
con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
@@ -3280,6 +3295,10 @@ static struct my_option my_long_options[] =
{"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT,
"Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout,
(gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0},
+ {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
+ "Max number of connection attempts when connecting to server",
+ (gptr*) &opt_max_connect_retries, (gptr*) &opt_max_connect_retries, 0,
+ GET_INT, REQUIRED_ARG, 5, 1, 10, 0, 0, 0},
{"password", 'p', "Password to use when connecting to server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", (gptr*) &port,
@@ -3304,7 +3323,7 @@ static struct my_option my_long_options[] =
"Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
{"sleep", 'T', "Sleep always this many seconds on sleep commands.",
- (gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
+ (gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, 0, 0,
0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &unix_sock, (gptr*) &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
@@ -4322,7 +4341,7 @@ static void handle_error(const char *query, struct st_query *q,
if (err_errno == CR_SERVER_LOST ||
err_errno == CR_SERVER_GONE_ERROR)
die("require query '%s' failed: %d: %s", query, err_errno, err_error);
- abort_not_supported_test();
+ abort_not_supported_test("failed_query");
}
if (q->abort_on_error)
@@ -5094,7 +5113,7 @@ static void init_var_hash(MYSQL *mysql)
DBUG_VOID_RETURN;
}
-static void mark_progress(int line)
+static void mark_progress(int line __attribute__((unused)))
{
#ifdef NOT_YET
static FILE* fp = NULL;
@@ -5197,9 +5216,14 @@ int main(int argc, char **argv)
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
#ifdef HAVE_OPENSSL
+ opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */
if (opt_use_ssl)
+ {
mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ &opt_ssl_verify_server_cert);
+ }
#endif
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
diff --git a/config/ac-macros/ha_archive.m4 b/config/ac-macros/ha_archive.m4
deleted file mode 100644
index 2d2558ea600..00000000000
--- a/config/ac-macros/ha_archive.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-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
index 183a622dfc9..c7d99bd8e03 100644
--- a/config/ac-macros/ha_berkeley.m4
+++ b/config/ac-macros/ha_berkeley.m4
@@ -8,23 +8,20 @@ dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_SETUP_BERKELEY_DB], [
AC_ARG_WITH([berkeley-db],
- [
- --with-berkeley-db[=DIR]
- Use BerkeleyDB located in DIR],
+ AS_HELP_STRING([--with-berkeley-db[[[[[=DIR]]]]]],
+ [Use BerkeleyDB located in DIR]),
[bdb="$withval"],
[bdb=yes])
AC_ARG_WITH([berkeley-db-includes],
- [
- --with-berkeley-db-includes=DIR
- Find Berkeley DB headers in DIR],
+ AS_HELP_STRING([--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],
+ AS_HELP_STRING([--with-berkeley-db-libs=DIR],
+ [Find Berkeley DB libraries in DIR]),
[bdb_libs="$withval"],
[bdb_libs=default])
@@ -120,12 +117,9 @@ AC_DEFUN([MYSQL_SETUP_BERKELEY_DB], [
sh $rel_srcdir/$bdb/dist/configure $bdb_conf_flags) || \
AC_MSG_ERROR([could not configure Berkeley DB])
- mysql_se_libs="$mysql_se_libs $bdb_libs_with_path"
-
AC_SUBST(bdb_includes)
AC_SUBST(bdb_libs)
AC_SUBST(bdb_libs_with_path)
- AC_CONFIG_FILES(storage/bdb/Makefile)
])
AC_DEFUN([MYSQL_CHECK_INSTALLED_BDB], [
diff --git a/config/ac-macros/ha_blackhole.m4 b/config/ac-macros/ha_blackhole.m4
deleted file mode 100644
index cc4d360f5a8..00000000000
--- a/config/ac-macros/ha_blackhole.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-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
deleted file mode 100644
index f8067931ce6..00000000000
--- a/config/ac-macros/ha_example.m4
+++ /dev/null
@@ -1,30 +0,0 @@
-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
deleted file mode 100644
index 5c991f31666..00000000000
--- a/config/ac-macros/ha_federated.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-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
deleted file mode 100644
index 287b77c8851..00000000000
--- a/config/ac-macros/ha_innodb.m4
+++ /dev/null
@@ -1,77 +0,0 @@
-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\$(top_builddir)/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)/storage/innobase/usr/libusr.a\
- \$(top_builddir)/storage/innobase/srv/libsrv.a\
- \$(top_builddir)/storage/innobase/dict/libdict.a\
- \$(top_builddir)/storage/innobase/que/libque.a\
- \$(top_builddir)/storage/innobase/srv/libsrv.a\
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a\
- \$(top_builddir)/storage/innobase/row/librow.a\
- \$(top_builddir)/storage/innobase/pars/libpars.a\
- \$(top_builddir)/storage/innobase/btr/libbtr.a\
- \$(top_builddir)/storage/innobase/trx/libtrx.a\
- \$(top_builddir)/storage/innobase/read/libread.a\
- \$(top_builddir)/storage/innobase/usr/libusr.a\
- \$(top_builddir)/storage/innobase/buf/libbuf.a\
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a\
- \$(top_builddir)/storage/innobase/eval/libeval.a\
- \$(top_builddir)/storage/innobase/log/liblog.a\
- \$(top_builddir)/storage/innobase/fsp/libfsp.a\
- \$(top_builddir)/storage/innobase/fut/libfut.a\
- \$(top_builddir)/storage/innobase/fil/libfil.a\
- \$(top_builddir)/storage/innobase/lock/liblock.a\
- \$(top_builddir)/storage/innobase/mtr/libmtr.a\
- \$(top_builddir)/storage/innobase/page/libpage.a\
- \$(top_builddir)/storage/innobase/rem/librem.a\
- \$(top_builddir)/storage/innobase/thr/libthr.a\
- \$(top_builddir)/storage/innobase/sync/libsync.a\
- \$(top_builddir)/storage/innobase/data/libdata.a\
- \$(top_builddir)/storage/innobase/mach/libmach.a\
- \$(top_builddir)/storage/innobase/ha/libha.a\
- \$(top_builddir)/storage/innobase/dyn/libdyn.a\
- \$(top_builddir)/storage/innobase/mem/libmem.a\
- \$(top_builddir)/storage/innobase/sync/libsync.a\
- \$(top_builddir)/storage/innobase/ut/libut.a\
- \$(top_builddir)/storage/innobase/os/libos.a\
- \$(top_builddir)/storage/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
index 8e839d8fee9..505d000c196 100644
--- a/config/ac-macros/ha_ndbcluster.m4
+++ b/config/ac-macros/ha_ndbcluster.m4
@@ -191,7 +191,6 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs=""
ndb_mgmclient_libs="\$(top_builddir)/storage/ndb/src/mgmclient/libndbmgmclient.la"
- mysql_se_objs="$mysql_se_objs ha_ndbcluster_binlog.o"
MYSQL_CHECK_NDB_OPTIONS
NDBCLUSTER_WORKAROUNDS
@@ -238,7 +237,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
if test X"$have_ndb_binlog" = Xyes
then
- AC_DEFINE([HAVE_NDB_BINLOG], [1],
+ AC_DEFINE([WITH_NDB_BINLOG], [1],
[Including Ndb Cluster Binlog])
AC_MSG_RESULT([Including Ndb Cluster Binlog])
else
@@ -282,9 +281,6 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndb_bin_am_ldflags=""
fi
- mysql_se_libs="$mysql_se_libs $ndbcluster_libs $ndbcluster_system_libs"
- mysql_se_libs="$mysql_se_libs $NDB_SCI_LIBS"
-
AC_SUBST(NDB_VERSION_MAJOR)
AC_SUBST(NDB_VERSION_MINOR)
AC_SUBST(NDB_VERSION_BUILD)
@@ -302,6 +298,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
AC_SUBST(ndbcluster_libs)
AC_SUBST(ndbcluster_system_libs)
AC_SUBST(ndb_mgmclient_libs)
+ AC_SUBST(NDB_SCI_LIBS)
AC_SUBST(ndb_transporter_opt_objs)
AC_SUBST(ndb_port)
@@ -311,7 +308,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
AC_SUBST(NDB_DEFS)
AC_SUBST(ndb_cxxflags_fix)
- AC_CONFIG_FILES(storage/ndb/Makefile storage/ndb/include/Makefile dnl
+ AC_CONFIG_FILES(storage/ndb/include/Makefile dnl
storage/ndb/src/Makefile storage/ndb/src/common/Makefile dnl
storage/ndb/docs/Makefile dnl
storage/ndb/tools/Makefile dnl
diff --git a/config/ac-macros/ha_partition.m4 b/config/ac-macros/ha_partition.m4
deleted file mode 100644
index 1ce7dedc5f3..00000000000
--- a/config/ac-macros/ha_partition.m4
+++ /dev/null
@@ -1,33 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_PARTITIONDB
-dnl Sets HAVE_PARTITION_DB if --with-partition is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_PARTITIONDB], [
- AC_ARG_WITH([partition],
- [
- --with-partition
- Enable the Partition Storage Engine],
- [partitiondb="$withval"],
- [partitiondb=no])
- AC_MSG_CHECKING([for partition])
-
-dnl case "$partitiondb" in
-dnl yes )
-dnl AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
-dnl AC_MSG_RESULT([yes])
-dnl [partitiondb=yes]
-dnl ;;
-dnl * )
-dnl AC_MSG_RESULT([no])
-dnl [partitiondb=no]
-dnl ;;
-dnl esac
- AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
- AC_MSG_RESULT([yes])
- [partitiondb=yes]
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_PARTITION SECTION
-dnl ---------------------------------------------------------------------------
-
diff --git a/config/ac-macros/ha_tina.m4 b/config/ac-macros/ha_tina.m4
deleted file mode 100644
index fe6e382ce20..00000000000
--- a/config/ac-macros/ha_tina.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-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/misc.m4 b/config/ac-macros/misc.m4
index 5346b81fb03..a2f70071e2d 100644
--- a/config/ac-macros/misc.m4
+++ b/config/ac-macros/misc.m4
@@ -361,7 +361,8 @@ 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_CHECK_LIB(tinfo, tgetent, mysql_cv_termcap_lib=libtinfo,
+ 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])
@@ -369,6 +370,8 @@ elif test "$mysql_cv_termcap_lib" = "libtermcap"; then
TERMCAP_LIB=-ltermcap
elif test "$mysql_cv_termcap_lib" = "libncurses"; then
TERMCAP_LIB=-lncurses
+elif test "$mysql_cv_termcap_lib" = "libtinfo"; then
+TERMCAP_LIB=-ltinfo
else
TERMCAP_LIB=-lcurses
fi
@@ -672,8 +675,8 @@ 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],
+ AS_HELP_STRING([--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])
@@ -700,8 +703,8 @@ dnl Sets MAX_INDEXES
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_MAX_INDEXES], [
AC_ARG_WITH([max-indexes],
- [
- --with-max-indexes=\# Sets the maximum number of indexes per table, default 64],
+ AS_HELP_STRING([--with-max-indexes=N],
+ [Sets the maximum number of indexes per table, default 64]),
[max_indexes="$withval"],
[max_indexes=64])
AC_MSG_CHECKING([max indexes per table])
diff --git a/config/ac-macros/openssl.m4 b/config/ac-macros/openssl.m4
deleted file mode 100644
index 1f9d53abe01..00000000000
--- a/config/ac-macros/openssl.m4
+++ /dev/null
@@ -1,135 +0,0 @@
-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
- # Just to be safe, we test for ".so" anyway
- if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl$shrext_cmds ; 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
- # Just to be safe, we test for ".so" anyway
- if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl$shrext_cmds ; 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/plugins.m4 b/config/ac-macros/plugins.m4
new file mode 100644
index 00000000000..4bf9292547d
--- /dev/null
+++ b/config/ac-macros/plugins.m4
@@ -0,0 +1,762 @@
+dnl ===========================================================================
+dnl Support for mysql server plugins
+dnl ===========================================================================
+dnl
+dnl WorkLog#3201
+dnl
+dnl Framework for pluggable static and dynamic plugins for mysql
+dnl
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN([name],[Plugin name],
+dnl [Plugin description],
+dnl [group,group...])
+dnl
+dnl DESCRIPTION
+dnl First declaration for a plugin (mandatory).
+dnl Adds plugin as member to configuration groups (if specified)
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN],[
+ _MYSQL_PLUGIN(
+ [$1],
+ [__MYSQL_PLUGIN_]AS_TR_CPP([$1])[__],
+ m4_default([$2], [$1 plugin]),
+ m4_default([$3], [plugin for $1]),
+ m4_default([$4], []),
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN],[
+ m4_ifdef([$2], [
+ AC_FATAL([Duplicate MYSQL_PLUGIN declaration for $3])
+ ],[
+ m4_define([$2], [$1])
+ _MYSQL_PLUGAPPEND([__mysql_plugin_list__],[$1])
+ m4_define([MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]), [$3])
+ m4_define([MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]), [$4])
+ _MYSQL_PLUGAPPEND_META([$1], $5)
+ ifelse(m4_bregexp(__mysql_include__,[/plug\.in$]),-1,[],[
+ MYSQL_PLUGIN_DIRECTORY([$1],
+ m4_bregexp(__mysql_include__,[^\(.*\)/plug\.in$],[\1]))
+ ])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_STORAGE_ENGINE
+dnl
+dnl SYNOPSIS
+dnl MYSQL_STORAGE_ENGINE([name],[legacy-option],[Storage engine name],
+dnl [Storage engine description],[group,group...])
+dnl
+dnl DESCRIPTION
+dnl Short cut for storage engine declarations
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_STORAGE_ENGINE],[
+ MYSQL_PLUGIN([$1], [$3], [$4], [[$5]])
+ MYSQL_PLUGIN_DEFINE([$1], [WITH_]AS_TR_CPP([$1])[_STORAGE_ENGINE])
+ ifelse([$2],[no],[],[
+ _MYSQL_LEGACY_STORAGE_ENGINE(
+ m4_bpatsubst([$1], -, _),
+ m4_bpatsubst(m4_default([$2], [$1-storage-engine]), -, _))
+ ])
+])
+
+AC_DEFUN([_MYSQL_LEGACY_STORAGE_ENGINE],[
+if test "[${with_]$2[+set}]" = set; then
+ [with_plugin_]$1="[$with_]$2"
+fi
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DEFINE
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEFINE([name],[MYSQL_CPP_DEFINE])
+dnl
+dnl DESCRIPTION
+dnl When a plugin is to be statically linked, define the C macro
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DEFINE],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DIRECTORY
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DIRECTORY([name],[plugin/dir])
+dnl
+dnl DESCRIPTION
+dnl Adds a directory to the build process
+dnl if it contains 'configure' it will be picked up automatically
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DIRECTORY],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_STATIC
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_STATIC([name],[libmyplugin.a])
+dnl
+dnl DESCRIPTION
+dnl Declare the name for the static library
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_STATIC],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DYNAMIC
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DYNAMIC([name],[myplugin.la])
+dnl
+dnl DESCRIPTION
+dnl Declare the name for the shared library
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DYNAMIC],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_MANDATORY
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_MANDATORY([name])
+dnl
+dnl DESCRIPTION
+dnl Marks the specified plugin as a mandatory plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_MANDATORY],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ _MYSQL_PLUGIN_MANDATORY([$1],
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_MANDATORY],[
+ m4_define([$2], [yes])
+ m4_ifdef([$3], [
+ AC_FATAL([mandatory plugin $1 has been disabled])
+ m4_undefine([$2])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DISABLED
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DISABLED([name])
+dnl
+dnl DESCRIPTION
+dnl Marks the specified plugin as a disabled plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DISABLED],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ _MYSQL_PLUGIN_DISABLED([$1],
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_DISABLED],[
+ m4_define([$2], [yes])
+ m4_ifdef([$3], [
+ AC_FATAL([attempt to disable mandatory plugin $1])
+ m4_undefine([$2])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DEPENDS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEPENDS([name],[prereq,prereq...])
+dnl
+dnl DESCRIPTION
+dnl Enables other plugins neccessary for the named plugin
+dnl Dependency checking is not recursive so if any
+dnl required plugin requires further plugins, list them
+dnl here too!
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DEPENDS],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ ifelse($#, 2, [
+ _MYSQL_PLUGIN_DEPEND([$1], $2)
+ ], [
+ AC_FATAL([bad number of arguments])
+ ])
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_DEPEND],[
+ ifelse($#, 1, [], [$#:$2], [2:], [], [
+ MYSQL_REQUIRE_PLUGIN([$2])
+ _MYSQL_PLUGAPPEND([__mysql_plugdepends_$1__],[$2])
+ _MYSQL_PLUGIN_DEPEND([$1], m4_shift(m4_shift($@)))
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_ACTIONS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_ACTIONS([name],[PLUGIN_CONFIGURE_STUFF])
+dnl
+dnl DESCRIPTION
+dnl Declares additional autoconf actions required to configure the plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_ACTIONS],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_ifdef([$2],[
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),m4_defn([$2]))
+ ],[
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]), [$2])
+ ])
+])
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CONFIGURE_PLUGINS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEPENDS([name,name...])
+dnl
+dnl DESCRIPTION
+dnl Used last, emits all required shell code to configure the plugins
+dnl Argument is a list of default plugins or meta-plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CONFIGURE_PLUGINS],[
+ m4_ifdef([__mysql_plugin_configured__],[
+ AC_FATAL([cannot use [MYSQL_CONFIGURE_PLUGINS] multiple times])
+ ],[
+ m4_define([__mysql_plugin_configured__],[done])
+ _MYSQL_INCLUDE_LIST(
+ m4_bpatsubst(m4_esyscmd([ls plugin/*/plug.in storage/*/plug.in 2>/dev/null]),
+[[
+]],[,]))
+ m4_ifdef([__mysql_plugin_list__],[
+ _MYSQL_CHECK_PLUGIN_ARGS([$1])
+ _MYSQL_CONFIGURE_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ _MYSQL_EMIT_PLUGIN_ACTIONS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ AC_SUBST([mysql_se_dirs])
+ AC_SUBST([mysql_pg_dirs])
+ ])
+ ])
+])
+
+AC_DEFUN([_MYSQL_CONFIGURE_PLUGINS],[
+ ifelse($#, 0, [], $#, 1, [
+ _MYSQL_EMIT_CHECK_PLUGIN([$1])
+ ],[
+ _MYSQL_EMIT_CHECK_PLUGIN([$1])
+ _MYSQL_CONFIGURE_PLUGINS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_CHECK_PLUGIN],[
+ __MYSQL_EMIT_CHECK_PLUGIN(
+ [$1],
+ m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[
+ m4_ifdef([$5],[
+ AH_TEMPLATE($5, [Include ]$4[ into mysqld])
+ ])
+ AC_MSG_CHECKING([whether to use ]$3)
+ mysql_use_plugin_dir=""
+ m4_ifdef([$10],[
+ if test "X[$mysql_plugin_]$2" = Xyes -a \
+ "X[$with_plugin_]$2" != Xno -o \
+ "X[$with_plugin_]$2" = Xyes; then
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([disabled])
+ fi
+ AC_MSG_RESULT([no])
+ ],[
+ m4_ifdef([$9],[
+ if test "X[$with_plugin_]$2" = Xno; then
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([cannot disable mandatory plugin])
+ fi
+ [mysql_plugin_]$2=yes
+ ])
+ if test "X[$with_plugin_]$2" = Xno; then
+ AC_MSG_RESULT([no])
+ else
+ m4_ifdef([$8],m4_ifdef([$7],[],[[with_plugin_]$2='']))
+ if test "X[$mysql_plugin_]$2" != Xyes -a \
+ "X[$with_plugin_]$2" != Xyes; then
+ m4_ifdef([$8],[
+ m4_ifdef([$6],[
+ if test -d "$srcdir/$6" ; then
+ mysql_use_plugin_dir="$6"
+ ])
+ AC_SUBST([plugin_]$2[_shared_target], "$8")
+ AC_SUBST([plugin_]$2[_static_target], [""])
+ [with_plugin_]$2=yes
+ AC_MSG_RESULT([plugin])
+ m4_ifdef([$6],[
+ else
+ [mysql_plugin_]$2=no
+ AC_MSG_RESULT([no])
+ fi
+ ])
+ ],[
+ [with_plugin_]$2=no
+ AC_MSG_RESULT([no])
+ ])
+ else
+ m4_ifdef([$7],[
+ ifelse(m4_bregexp($7, [^lib[^.]+\.a$]), -2, [
+dnl change above "-2" to "0" to enable this section
+dnl Although this is "pretty", it breaks libmysqld build
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ mysql_plugin_libs="$mysql_plugin_libs -L[\$(top_builddir)]/$6"
+ ])
+ mysql_plugin_libs="$mysql_plugin_libs dnl
+[-l]m4_bregexp($7, [^lib\([^.]+\)], [\1])"
+ ], m4_bregexp($7, [^\\\$]), 0, [
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ ])
+ mysql_plugin_libs="$mysql_plugin_libs $7"
+ ], [
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ mysql_plugin_libs="$mysql_plugin_libs \$(top_builddir)/$6/$7"
+ ],[
+ mysql_plugin_libs="$mysql_plugin_libs $7"
+ ])
+ ])
+ m4_ifdef([$5],[
+ AC_DEFINE($5)
+ ])
+ AC_SUBST([plugin_]$2[_static_target], "$7")
+ AC_SUBST([plugin_]$2[_shared_target], [""])
+ ],[
+ m4_ifdef([$6],[
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([Plugin $1 does not support static linking])
+ ],[
+ m4_ifdef([$5],[
+ AC_DEFINE($5)
+ AC_SUBST([plugin_]$2[_static_target], ["yes"])
+ AC_SUBST([plugin_]$2[_shared_target], [""])
+ ])
+ ])
+ ])
+ mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ [with_plugin_]$2=yes
+ AC_MSG_RESULT([yes])
+ fi
+ m4_ifdef([$6],[
+ if test -n "$mysql_use_plugin_dir" ; then
+ mysql_plugin_dirs="$mysql_plugin_dirs $6"
+ m4_syscmd(test -f "$6/configure")
+ ifelse(m4_sysval, 0,
+ [other_configures="$other_configures $6/configure"],
+ [AC_CONFIG_FILES($6/Makefile)]
+ )
+ ifelse(m4_substr($6, 0, 8), [storage/],
+ [mysql_se_dirs="$mysql_se_dirs ]m4_substr($6, 8)",
+ m4_substr($6, 0, 7), [plugin/],
+ [mysql_pg_dirs="$mysql_pg_dirs ]m4_substr($6, 7)",
+ [AC_FATAL([don't know how to handle plugin dir ]$6)])
+ fi
+ ])
+ fi
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ACTIONS],[
+ ifelse($#, 0, [], $#, 1, [
+ _MYSQL_EMIT_PLUGIN_ACTION([$1])
+ ],[
+ _MYSQL_EMIT_PLUGIN_ACTION([$1])
+ _MYSQL_EMIT_PLUGIN_ACTIONS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ACTION],[
+ __MYSQL_EMIT_PLUGIN_ACTION(
+ [$1],
+ m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1])
+ )
+])
+
+
+AC_DEFUN([__MYSQL_EMIT_PLUGIN_ACTION],[
+ m4_ifdef([$3], [], [
+ if test "X[$with_plugin_]$2" = Xyes; then
+ if test "X[$plugin_]$2[_static_target]" = X -a \
+ "X[$plugin_]$2[_shared_target]" = X; then
+ AC_MSG_ERROR([that's strange, $1 failed sanity check])
+ fi
+ $4
+ fi
+ ])
+])
+
+
+
+dnl ===========================================================================
+dnl Private helper macros
+dnl ===========================================================================
+
+
+dnl SYNOPSIS
+dnl MYSQL_REQUIRE_PLUGIN([name])
+dnl
+dnl DESCRIPTION
+dnl Checks that the specified plugin does exist
+
+AC_DEFUN([MYSQL_REQUIRE_PLUGIN],[
+ _MYSQL_REQUIRE_PLUGIN([$1], [__MYSQL_PLUGIN_]AS_TR_CPP([$1])[__])
+])
+
+define([_MYSQL_REQUIRE_PLUGIN],[
+ ifdef([$2],[
+ ifelse($2, [$1], [], [
+ AC_FATAL([Misspelt MYSQL_PLUGIN declaration for $1])
+ ])
+ ],[
+ AC_FATAL([Missing MYSQL_PLUGIN declaration for $1])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl _MYSQL_EMIT_METAPLUGINS([name,name...])
+dnl
+dnl DESCRIPTION
+dnl Emits shell code for metaplugins
+
+AC_DEFUN([_MYSQL_EMIT_METAPLUGINS], [ifelse($#, 0, [], $#, 1,
+[_MYSQL_EMIT_METAPLUGIN([$1], [__mysql_]m4_bpatsubst($1, -, _)[_plugins__])
+],
+[_MYSQL_EMIT_METAPLUGIN([$1], [__mysql_]m4_bpatsubst($1, -, _)[_plugins__])
+_MYSQL_EMIT_METAPLUGINS(m4_shift($@))])
+])
+
+AC_DEFUN([_MYSQL_EMIT_METAPLUGIN], [
+ [$1] )
+m4_ifdef([$2], [
+ mysql_plugins='m4_bpatsubst($2, :, [ ])'
+],[
+ mysql_plugins=''
+])
+ ;;
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl _MYSQL_PLUGAPPEND([name],[to-append])
+dnl
+dnl DESCRIPTION
+dnl Helper macro for appending to colon-delimited lists
+dnl Optinal 3rd argument is for actions only required when defining
+dnl macro named for the first time.
+
+AC_DEFUN([_MYSQL_PLUGAPPEND],[
+ m4_ifdef([$1],[
+ m4_define([__plugin_append_tmp__], m4_defn([$1]))
+ m4_undefine([$1])
+ m4_define([$1], __plugin_append_tmp__[:$2])
+ m4_undefine([__plugin_append_tmp__])
+ ],[
+ m4_define([$1], [$2])
+ $3
+ ])
+])
+
+
+dnl SYNOPSIS
+dnl _MYSQL_PLUGAPPEND_META([name],[meta,meta...])
+dnl
+dnl DESCRIPTION
+dnl Helper macro for adding plugins to meta plugins
+
+AC_DEFUN([_MYSQL_PLUGAPPEND_META],[
+ ifelse($#, 1, [], [$#:$2], [2:], [], [$2], [all], [
+ AC_FATAL([protected plugin group: all])
+ ], [$2], [none], [
+ AC_FATAL([protected plugin group: none])
+ ],[
+ _MYSQL_PLUGAPPEND([__mysql_$1_configs__],[$2])
+ _MYSQL_PLUGAPPEND([__mysql_]m4_bpatsubst($2, -, _)[_plugins__],[$1], [
+ _MYSQL_PLUGAPPEND([__mysql_metaplugin_list__],[$2])
+ ])
+ _MYSQL_PLUGAPPEND_META([$1], m4_shift(m4_shift($@)))
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl MYSQL_LIST_PLUGINS
+dnl
+dnl DESCRIPTION
+dnl Emits formatted list of declared plugins
+
+AC_DEFUN([MYSQL_LIST_PLUGINS],[dnl
+ m4_ifdef([__mysql_plugin_list__],[dnl
+ _MYSQL_LIST_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))dnl
+ ])dnl
+])
+
+AC_DEFUN([_MYSQL_LIST_PLUGINS],[dnl
+ ifelse($#, 0, [], $#, 1, [dnl
+ MYSQL_SHOW_PLUGIN([$1])dnl
+ ],[dnl
+ MYSQL_SHOW_PLUGIN([$1])dnl
+ _MYSQL_LIST_PLUGINS(m4_shift($@))dnl
+ ])dnl
+])
+
+AC_DEFUN([MYSQL_SHOW_PLUGIN],[
+ _MYSQL_SHOW_PLUGIN(
+ [$1],
+ [$1-plugin],
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),
+ __mysql_[$1]_configs__,
+ )
+])
+
+AC_DEFUN([_MYSQL_SHOW_PLUGIN],[dnl
+ === $3 ===
+ Plugin Name: [$1]
+ Description: $4
+ Supports build: _PLUGIN_BUILD_TYPE([$7],[$8])[]dnl
+m4_ifdef([$12],[
+ Configurations: m4_bpatsubst($12, :, [, ])])[]dnl
+m4_ifdef([$10],[
+ Status: disabled])[]dnl
+m4_ifdef([$9],[
+ Status: mandatory])[]dnl
+])
+
+AC_DEFUN([_PLUGIN_BUILD_TYPE],
+[m4_ifdef([$1],[static ]m4_ifdef([$2],[and dnl
+]))[]m4_ifdef([$2],[dynamic],[m4_ifdef([$1],[],[static])])])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+AC_DEFUN([_MYSQL_EMIT_PLUGINS],[
+ ifelse($#, 0, [], [$#:$1], [1:], [], [
+ m4_ifdef([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]), [], [
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),[ ])
+ ])
+ [$1] )
+ m4_ifdef([MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),[
+ AC_MSG_ERROR([plugin $1 is disabled])
+ ],[
+ _MYSQL_EMIT_PLUGIN_ENABLE([$1], m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]))
+ ])
+ ;;
+ _MYSQL_EMIT_PLUGINS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ENABLE],[
+ m4_ifdef([$5],m4_ifdef([$4],[
+ [mysql_plugin_]$2=yes
+ ],[
+ AC_MSG_WARN([$3 can only be built as a plugin])
+ ]),[
+ [mysql_plugin_]$2=yes
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_DEPENDS], [
+ ifelse($#, 0, [], [$#:$1], [1:], [], [
+ _MYSQL_EMIT_CHECK_DEPENDS(m4_bpatsubst([$1], -, _),
+ [__mysql_plugdepends_$1__])
+ _MYSQL_EMIT_PLUGIN_DEPENDS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_CHECK_DEPENDS], [
+ m4_ifdef([$2], [
+ if test "X[$mysql_plugin_]$1" = Xyes -a \
+ "X[$with_plugin_]$1" != Xno -o \
+ "X[$with_plugin_]$1" = Xyes; then
+ _MYSQL_EMIT_PLUGIN_DEPENDENCIES(m4_bpatsubst($2, :, [,]))
+ fi
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_DEPENDENCIES], [
+ ifelse([$1], [], [], [
+ m4_ifdef([MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),[
+ AC_MSG_ERROR([depends upon disabled plugin $1])
+ ],[
+ [mysql_plugin_]m4_bpatsubst([$1], -, _)=yes
+ if test "X[$with_plugin_]m4_bpatsubst([$1], -, _)" = Xno; then
+ AC_MSG_ERROR([depends upon disabled plugin $1])
+ fi
+ ])
+ _MYSQL_EMIT_PLUGIN_DEPENDENCIES(m4_shift($@))
+ ])
+])
+
+dnl SYNOPSIS
+dnl _MYSQL_CHECK_PLUGIN_ARGS([plugin],[plugin]...)
+dnl
+dnl DESCRIPTION
+dnl Emits shell script for checking configure arguments
+dnl Arguments to this macro is default value for selected plugins
+
+AC_DEFUN([_MYSQL_CHECK_PLUGIN_ARGS],[
+ __MYSQL_CHECK_PLUGIN_ARGS(m4_default([$1], [none]))
+])
+
+AC_DEFUN([__MYSQL_CHECK_PLUGIN_ARGS],[
+ AC_ARG_WITH([plugins],
+AS_HELP_STRING([--with-plugins=PLUGIN[[[[[,PLUGIN..]]]]]],
+ [Plugins to include in mysqld. (default is: $1) Must be a
+ configuration name or a comma separated list of plugins.])
+AS_HELP_STRING([],
+ [Available configurations are:] dnl
+m4_bpatsubst([none:]m4_ifdef([__mysql_metaplugin_list__],
+ __mysql_metaplugin_list__:)[all], :, [ ])[.])
+AS_HELP_STRING([],
+ [Available plugins are:] dnl
+m4_bpatsubst(__mysql_plugin_list__, :, [ ])[.])
+AS_HELP_STRING([--without-plugin-PLUGIN],
+ [Disable the named plugin from being built. Otherwise, for
+ plugins which are not selected for inclusion in mysqld will be
+ built dynamically (if supported)])
+AS_HELP_STRING([--with-plugin-PLUGIN],
+ [Forces the named plugin to be linked into mysqld statically.]),
+ [mysql_plugins="`echo $withval | tr ',.:;*[]' ' '`"],
+ [mysql_plugins=['$1']])
+
+m4_divert_once([HELP_VAR_END],[
+Description of plugins:
+MYSQL_LIST_PLUGINS])
+
+ case "$mysql_plugins" in
+ all )
+ mysql_plugins='m4_bpatsubst(__mysql_plugin_list__, :, [ ])'
+ ;;
+ none )
+ mysql_plugins=''
+ ;;
+m4_ifdef([__mysql_metaplugin_list__],[
+_MYSQL_EMIT_METAPLUGINS(m4_bpatsubst(__mysql_metaplugin_list__, :, [,]))
+])
+ esac
+
+ for plugin in $mysql_plugins; do
+ case "$plugin" in
+ all | none )
+ AC_MSG_ERROR([bad plugin name: $plugin])
+ ;;
+_MYSQL_EMIT_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ * )
+ AC_MSG_ERROR([unknown plugin: $plugin])
+ ;;
+ esac
+ done
+
+ _MYSQL_EMIT_PLUGIN_DEPENDS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+])
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: _MYSQL_INCLUDE_LIST
+dnl
+dnl SYNOPSIS
+dnl _MYSQL_INCLUDE_LIST([filename,filename...])
+dnl
+dnl DESCRIPTION
+dnl includes all files from the list
+dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([_MYSQL_INCLUDE_LIST],[
+ ifelse([$1], [], [], [
+ m4_define([__mysql_include__],[$1])
+ dnl We have to use builtin(), because sinclude would generate an error
+ dnl "file $1 does not exists" in aclocal-1.8 - which is a bug, clearly
+ dnl violating m4 specs, and which is fixed in aclocal-1.9
+ builtin([include],$1)
+ m4_undefine([__mysql_include__])
+ _MYSQL_INCLUDE_LIST(m4_shift($@))
+ ])
+])
+
+dnl ===========================================================================
diff --git a/config/ac-macros/replication.m4 b/config/ac-macros/replication.m4
index 3a0c83d6498..babfa000a82 100644
--- a/config/ac-macros/replication.m4
+++ b/config/ac-macros/replication.m4
@@ -15,7 +15,7 @@ AC_DEFUN([MYSQL_CHECK_REPLICATION], [
case "$row_based" in
yes )
- AC_DEFINE([HAVE_ROW_BASED_REPLICATION], [1], [Define to have row-based replication])
+ AC_DEFINE([WITH_ROW_BASED_REPLICATION], [1], [Define to have row-based replication])
AC_MSG_RESULT([-- including row-based replication])
[have_row_based=yes]
;;
diff --git a/config/ac-macros/ssl.m4 b/config/ac-macros/ssl.m4
new file mode 100644
index 00000000000..0f2f207c36f
--- /dev/null
+++ b/config/ac-macros/ssl.m4
@@ -0,0 +1,210 @@
+dnl ===========================================================================
+dnl Support for SSL
+dnl ===========================================================================
+dnl
+dnl
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_USE_BUNDLED_YASSL
+dnl
+dnl SYNOPSIS
+dnl MYSQL_USE_BUNDLED_YASSL()
+dnl
+dnl DESCRIPTION
+dnl Add defines so yassl is built and linked with
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_USE_BUNDLED_YASSL], [
+
+ AC_CONFIG_FILES(extra/yassl/Makefile dnl
+ extra/yassl/taocrypt/Makefile dnl
+ extra/yassl/taocrypt/benchmark/Makefile dnl
+ extra/yassl/taocrypt/src/Makefile dnl
+ extra/yassl/taocrypt/test/Makefile dnl
+ extra/yassl/src/Makefile dnl
+ extra/yassl/testsuite/Makefile)
+
+ with_bundled_yassl="yes"
+
+ yassl_dir="yassl"
+ AC_SUBST([yassl_dir])
+
+ yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt"
+ AC_SUBST(yassl_libs)
+ yassl_includes="-I\$(top_srcdir)/extra/yassl/include"
+ AC_SUBST(yassl_includes)
+
+ AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for SSL.])
+ AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for SSL.])
+
+ # System specific checks
+ yassl_integer_extra_cxxflags=""
+ case $host_cpu--$CXX_VERSION in
+ sparc*--*Sun*C++*5.6*)
+ # Disable inlining when compiling taocrypt/src/
+ yassl_taocrypt_extra_cxxflags="+d"
+ AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/])
+ ;;
+ esac
+ AC_SUBST([yassl_taocrypt_extra_cxxflags])
+
+ # Link extra/yassl/include/openssl subdir to include/
+ yassl_h_ln_cmd="\$(LN) -s \$(top_srcdir)/extra/yassl/include/openssl openssl"
+ AC_SUBST(yassl_h_ln_cmd)
+
+ AC_MSG_RESULT([using bundled yaSSL])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_SSL_DIR
+dnl
+dnl SYNOPSIS
+dnl MYSQL_CHECK_SSL_DIR(includes, libs)
+dnl
+dnl DESCRIPTION
+dnl Auxiliary macro to check for ssl at given path
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CHECK_SSL_DIR], [
+ssl_incs="$1"
+ssl_libs="$2"
+save_CPPFLAGS="$CPPFLAGS"
+save_LIBS="$LIBS"
+CPPFLAGS="$ssl_incs $CPPFLAGS"
+LIBS="$LIBS $ssl_libs"
+AC_TRY_LINK([#include <openssl/ssl.h>],
+ [return SSL_library_init();],
+ [mysql_ssl_found="yes"],
+ [mysql_ssl_found="no"])
+CPPFLAGS="$save_CPPFLAGS"
+LIBS="$save_LIBS"
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_FIND_OPENSSL
+dnl
+dnl SYNOPSIS
+dnl MYSQL_FIND_OPENSSL(location)
+dnl
+dnl DESCRIPTION
+dnl Search the location for OpenSSL support
+dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_FIND_OPENSSL], [
+ location="$1"
+
+ #
+ # Set include paths
+ #
+ openssl_include="$location/include"
+ openssl_includes=""
+
+ # Don't set ssl_includes to /usr/include as this gives us a lot of
+ # compiler warnings when using gcc 3.x
+ if test "$openssl_include" != "/usr/include"
+ then
+ openssl_includes="-I$ssl_include"
+ fi
+
+ #
+ # Try to link with openSSL libs in <location>
+ #
+ openssl_libs="-L$location/lib/ -lssl -lcrypto"
+ MYSQL_CHECK_SSL_DIR([$openssl_includes], [$openssl_libs])
+
+ if test "$mysql_ssl_found" == "no"
+ then
+ #
+ # BUG 764: Compile failure with OpenSSL on Red Hat Linux (krb5.h missing)
+ # Try to link with include paths to kerberos set
+ #
+ openssl_includes="$openssl_includes -I/usr/kerberos/include"
+ MYSQL_CHECK_SSL_DIR([$openssl_includes], [$openssl_libs])
+ fi
+
+ if test "$mysql_ssl_found" == "no"
+ then
+ AC_MSG_ERROR([Could not link with SSL libs at $location])
+ fi
+
+ # 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.)
+ case "$CLIENT_EXTRA_LDFLAGS $MYSQLD_EXTRA_LDFLAGS" in
+ *-all-static*)
+ AC_MSG_ERROR([You can't use the --all-static link option when using openssl.])
+ ;;
+ esac
+
+ AC_SUBST(openssl_includes)
+ AC_SUBST(openssl_libs)
+
+ NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
+
+ AC_DEFINE([HAVE_OPENSSL], [1], [OpenSSL])
+ AC_MSG_RESULT([using openSSL from $location])
+])
+
+
+
+dnl ------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_SSL
+dnl
+dnl SYNOPSIS
+dnl MYSQL_CHECK_SSL
+dnl
+dnl Provides the following configure options:
+dnl --with-ssl=DIR
+dnl Possible DIR values are:
+dnl - no - the macro will disable use of ssl
+dnl - bundled, empty or not specified - means use ssl lib
+dnl bundled along with MySQL sources
+dnl - ssl location prefix - given location prefix, the macro expects
+dnl to find the header files in $prefix/include/, and libraries in
+dnl $prefix/lib. If headers or libraries weren't found at $prefix, the
+dnl macro bails out with error.
+dnl
+dnl ------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_SSL], [
+AC_MSG_CHECKING(for SSL)
+ AC_ARG_WITH([ssl],
+ [ --with-ssl[=DIR] Include SSL support],
+ [mysql_ssl_dir="$withval"],
+ [mysql_ssl_dir=no])
+
+ if test "$with_yassl"
+ then
+ AC_MSG_ERROR([The flag --with-yassl is deprecated, use --with-ssl])
+ fi
+
+ if test "$with_openssl"
+ then
+ AC_MSG_ERROR([The flag --with-openssl is deprecated, use --with-ssl])
+ fi
+
+ case "$mysql_ssl_dir" in
+ "no")
+ #
+ # Don't include SSL support
+ #
+ AC_MSG_RESULT([disabled])
+ ;;
+
+ "bundled"|"yes")
+ #
+ # Use the bundled SSL implementation (yaSSL)
+ #
+ MYSQL_USE_BUNDLED_YASSL
+ ;;
+
+ *)
+ #
+ # A location where to search for OpenSSL was specified
+ #
+ MYSQL_FIND_OPENSSL([$mysql_ssl_dir])
+ ;;
+ esac
+ AM_CONDITIONAL([HAVE_YASSL], [ test "$with_bundled_yassl" = "yes" ])
+])
diff --git a/config/ac-macros/storage.m4 b/config/ac-macros/storage.m4
deleted file mode 100644
index 4148aed818d..00000000000
--- a/config/ac-macros/storage.m4
+++ /dev/null
@@ -1,55 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_STORAGE_ENGINE
-dnl
-dnl What it does:
-dnl creates --with-xxx configure option
-dnl adds HAVE_XXX to config.h
-dnl appends &xxx_hton, to the list of hanldertons
-dnl appends a dir to the list of source directories
-dnl appends ha_xxx.cc to the list of handler files
-dnl
-dnl all names above are configurable with reasonable defaults.
-dnl
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_STORAGE_ENGINE],
-[_MYSQL_STORAGE_ENGINE(
-[$1], dnl name
-m4_default([$2], [$1 storage engine]), dnl verbose name
-m4_default([$3], [$1-storage-engine]), dnl with-name
-m4_default([$4], no), dnl default
-m4_default([$5], [WITH_]AS_TR_CPP([$1])[_STORAGE_ENGINE]),
-m4_default([$6], $1[_hton]), dnl hton
-m4_default([$7], []), dnl path to the code
-m4_default([$8], [ha_$1.o]), dnl path to the handler in
-m4_default([$9], []), dnl path to extra libraries
-[$10], dnl code-if-set
-)])
-
-AC_DEFUN([_MYSQL_STORAGE_ENGINE],
-[
-AC_ARG_WITH([$3], AS_HELP_STRING([--with-$3], [enable $2 (default is $4)]),
-[], [ [with_]m4_bpatsubst([$3], -, _)=['$4']])
-AC_CACHE_CHECK([whether to use $2], [mysql_cv_use_]m4_bpatsubst([$3], -, _),
-[mysql_cv_use_]m4_bpatsubst([$3], -, _)=[$with_]m4_bpatsubst([$3], -, _))
-AH_TEMPLATE([$5], [Build $2])
-if test "[$mysql_cv_use_]m4_bpatsubst([$3], -, _)" != no; then
-if test "$6" != "no"
-then
- AC_DEFINE([$5])
- mysql_se_decls="${mysql_se_decls},$6"
- mysql_se_htons="${mysql_se_htons},&$6"
- if test "$8" != "no"
- then
- mysql_se_objs="$mysql_se_objs $8"
- fi
- mysql_se_dirs="$mysql_se_dirs $7"
- mysql_se_libs="$mysql_se_libs $9"
-else
- mysql_se_plugins="$mysql_se_plugins $7"
-fi
-$10
-fi
-])
-
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4
deleted file mode 100644
index 906a65a2fc3..00000000000
--- a/config/ac-macros/yassl.m4
+++ /dev/null
@@ -1,42 +0,0 @@
-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])
- AC_CONFIG_FILES(extra/yassl/Makefile dnl
- extra/yassl/taocrypt/Makefile dnl
- extra/yassl/taocrypt/src/Makefile dnl
- extra/yassl/src/Makefile)
- yassl_dir="yassl"
- yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt"
- yassl_includes="-I\$(top_srcdir)/extra/yassl/include"
- AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
- AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
- # System specific checks
- yassl_integer_extra_cxxflags=""
- case $host_cpu--$CXX_VERSION in
- sparc*--*Sun*C++*5.6*)
- # Disable inlining when compiling taocrypt/src/
- yassl_taocrypt_extra_cxxflags="+d"
- AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/])
- ;;
- esac
- AC_SUBST([yassl_taocrypt_extra_cxxflags])
- # Link extra/yassl/include/openssl subdir to include/
- yassl_h_ln_cmd="\$(LN) -s \$(top_srcdir)/extra/yassl/include/openssl openssl"
- AC_SUBST(yassl_h_ln_cmd)
- else
- yassl_dir=""
- AC_MSG_RESULT(no)
- fi
- AC_SUBST(yassl_libs)
- AC_SUBST(yassl_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
index 23cc132aca8..17b951d4723 100644
--- a/config/ac-macros/zlib.m4
+++ b/config/ac-macros/zlib.m4
@@ -89,9 +89,11 @@ case $SYSTEM_TYPE in
fi
;;
*)
- # Just to be safe, we test for ".so" anyway
- if test \( -f "$mysql_zlib_dir/lib/libz.a" -o -f "$mysql_zlib_dir/lib/libz.so" -o \
- -f "$mysql_zlib_dir/lib/libz$shrext_cmds" \) \
+ # Test for libz using all known library file endings
+ if test \( -f "$mysql_zlib_dir/lib/libz.a" -o \
+ -f "$mysql_zlib_dir/lib/libz.so" -o \
+ -f "$mysql_zlib_dir/lib/libz.sl" -o \
+ -f "$mysql_zlib_dir/lib/libz.dylib" \) \
-a -f "$mysql_zlib_dir/include/zlib.h"; then
ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
diff --git a/configure.in b/configure.in
index 6984f5b5f89..0f0649fd3bc 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ 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, 5.1.10-beta)
+AM_INIT_AUTOMAKE(mysql, 5.1.12-beta)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -31,15 +31,14 @@ 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/storage.m4)
+sinclude(config/ac-macros/plugins.m4)
sinclude(config/ac-macros/ha_berkeley.m4)
sinclude(config/ac-macros/ha_ndbcluster.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/replication.m4)
-sinclude(config/ac-macros/yassl.m4)
+sinclude(config/ac-macros/ssl.m4)
sinclude(config/ac-macros/zlib.m4)
# Remember to add a directory sql/share/LANGUAGE
@@ -51,7 +50,6 @@ romanian russian serbian slovak spanish swedish ukrainian"
#####
#####
-
AC_SUBST(MYSQL_NO_DASH_VERSION)
AC_SUBST(MYSQL_BASE_VERSION)
AC_SUBST(MYSQL_VERSION_ID)
@@ -196,6 +194,7 @@ then
else
AC_PATH_PROG(AS, as, as)
fi
+
# Still need ranlib for readline; local static use only so no libtool.
AC_PROG_RANLIB
# We use libtool
@@ -207,6 +206,13 @@ AC_PROG_LIBTOOL
LIBTOOL="$LIBTOOL --preserve-dup-deps"
AC_SUBST(LIBTOOL)dnl
+AC_SUBST(NM)dnl
+
+# NM= "$NM -X64"
+#archive_expsym_cmds= `echo "$archive_expsym_cmds" | sed -e '/"$(CC)"//'`
+#archive_expsym_cmds= "$CC -q64 $archive_expsym_cmds"
+# CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
+
#AC_LIBTOOL_DLOPEN AC_LIBTOOL_WIN32_DLL AC_DISABLE_FAST_INSTALL AC_DISABLE_SHARED AC_DISABLE_STATIC
# AC_PROG_INSTALL
@@ -482,7 +488,7 @@ then
AC_MSG_ERROR([MySQL requires an ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.])
fi
-NOINST_LDFLAGS=
+NOINST_LDFLAGS="-static"
static_nss=""
STATIC_NSS_FLAGS=""
@@ -666,6 +672,7 @@ else
AC_MSG_RESULT([no])
fi
+
MYSQL_SYS_LARGEFILE
# Types that must be checked AFTER large file support is checked
@@ -704,9 +711,8 @@ AC_CHECK_FUNC(yp_get_default_domain, ,
AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open))
# This may get things to compile even if bind-8 is installed
AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind))
-# For crypt() on Linux
-AC_CHECK_LIB(crypt, crypt)
-AC_CHECK_FUNC(crypt, AC_DEFINE([HAVE_CRYPT], [1], [crypt]))
+# Check if crypt() exists in libc or libcrypt, sets LIBS if needed
+AC_SEARCH_LIBS(crypt, crypt, AC_DEFINE(HAVE_CRYPT, 1, [crypt]))
# For sem_xxx functions on Solaris 2.6
AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init))
@@ -774,6 +780,9 @@ AC_SUBST(WRAPLIBS)
if test "$TARGET_LINUX" = "true"; then
AC_MSG_CHECKING([for atomic operations])
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+
atom_ops=
AC_TRY_RUN([
#include <asm/atomic.h>
@@ -809,6 +818,8 @@ int main()
if test -z "$atom_ops"; then atom_ops="no"; fi
AC_MSG_RESULT($atom_ops)
+ AC_LANG_RESTORE
+
AC_ARG_WITH(pstack,
[ --with-pstack Use the pstack backtrace library],
[ USE_PSTACK=$withval ],
@@ -1076,7 +1087,7 @@ dnl Is this the right match for DEC OSF on alpha?
# Edit Makefile.in files.
#
echo -n "configuring Makefile.in files for NetWare... "
- for file in sql/Makefile.in libmysql/Makefile.in libmysql_r/Makefile.in sql/share/Makefile.in strings/Makefile.in client/Makefile.in
+ for file in sql/Makefile.in extra/Makefile.in client/Makefile.in
do
# echo "#### $file ####"
filedir="`dirname $file`"
@@ -1097,32 +1108,13 @@ dnl Is this the right match for DEC OSF on alpha?
# Add library dependencies to mysqld_DEPENDENCIES
lib_DEPENDENCIES="\$(pstack_libs) \$(openssl_libs) \$(yassl_libs)"
cat > $filesed << EOF
-s,\(^.*\$(MAKE) gen_lex_hash\)\$(EXEEXT),#\1,
s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux,
-s%\(mysqld_DEPENDENCIES = \) %\1$lib_DEPENDENCIES %
-EOF
- ;;
- sql/share/Makefile.in)
- cat > $filesed << EOF
-s,\(extra/comp_err\),\1.linux,
-EOF
- ;;
- libmysql/Makefile.in)
- cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
-EOF
- ;;
- libmysql_r/Makefile.in)
- cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
+s%\(mysqld_DEPENDENCIES = \)%\1$lib_DEPENDENCIES %
EOF
;;
- strings/Makefile.in)
+ extra/Makefile.in)
cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
+s,\(extra/comp_err\)\$(EXEEXT),\1.linux,
EOF
;;
client/Makefile.in)
@@ -1608,6 +1600,21 @@ else
CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS"
fi
+# If we should allow error injection tests
+AC_ARG_WITH(error-inject,
+ AC_HELP_STRING([--with-error-inject],[Enable error injection in MySQL Server]),
+ [ with_error_inject=$withval ],
+ [ with_error_inject=no ])
+
+if test $with_debug != "no"
+then
+ if test "$with_error_inject" = "yes"
+ then
+ AC_DEFINE([ERROR_INJECT_SUPPORT], [1],
+ [Enable error injection in MySQL Server])
+ fi
+fi
+
AC_ARG_WITH([fast-mutexes],
AC_HELP_STRING([--with-fast-mutexes],
[Compile with fast mutexes (default is disabled)]),
@@ -2168,6 +2175,89 @@ then
fi
AC_MSG_RESULT("$netinet_inc")
+#--------------------------------------------------------------------
+# Check for requested features
+#--------------------------------------------------------------------
+
+MYSQL_CHECK_BIG_TABLES
+MYSQL_CHECK_MAX_INDEXES
+MYSQL_CHECK_REPLICATION
+MYSQL_CHECK_VIO
+MYSQL_CHECK_SSL
+
+#--------------------------------------------------------------------
+# Declare our plugin modules
+# Has to be done late, as the plugin may need to check for existence of
+# functions tested above
+#--------------------------------------------------------------------
+
+MYSQL_STORAGE_ENGINE(berkeley, berkeley-db, [BerkeleyDB Storage Engine],
+ [Transactional Tables using BerkeleyDB], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(berkeley,[storage/bdb])
+MYSQL_PLUGIN_STATIC(berkeley, [[\$(bdb_libs_with_path)]])
+MYSQL_PLUGIN_ACTIONS(berkeley, [MYSQL_SETUP_BERKELEY_DB])
+
+MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine],
+ [Basic Write-only Read-never tables], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole])
+MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.a])
+MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la])
+
+MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine],
+ [Stores tables in text CSV format])
+MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv])
+MYSQL_PLUGIN_STATIC(csv, [libcsv.a])
+MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging
+
+MYSQL_STORAGE_ENGINE(federated,,[Federated Storage Engine],
+ [Connects to tables on remote MySQL servers], [max,max-no-ndb])
+
+MYSQL_PLUGIN(ftexample, [Simple Parser],
+ [Simple full-text parser plugin])
+MYSQL_PLUGIN_DIRECTORY(ftexample, [plugin/fulltext])
+MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la])
+
+MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine],
+ [Volatile memory based tables])
+MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap])
+MYSQL_PLUGIN_STATIC(heap, [libheap.a])
+MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables
+
+MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
+ [Transactional Tables using InnoDB], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
+MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
+MYSQL_PLUGIN_ACTIONS(innobase, [
+ AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
+ AC_SUBST(innodb_system_libs)
+])
+
+MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine],
+ [Traditional non-transactional MySQL tables])
+MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam])
+MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a])
+MYSQL_PLUGIN_MANDATORY(myisam) dnl Default
+
+MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine],
+ [Merge multiple MySQL tables into one])
+MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg])
+MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg.a])
+MYSQL_PLUGIN_MANDATORY(myisammrg)
+
+MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine],
+ [High Availability Clustered tables], [max])
+MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb])
+MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]])
+MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER])
+
+MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
+ [MySQL Partitioning Support], [max,max-no-ndb])
+
+dnl -- ndbcluster requires partition to be enabled
+MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition])
+
+MYSQL_CONFIGURE_PLUGINS([none])
+
# Only build client code?
AC_ARG_WITH(server,
[ --without-server Only build the client.],
@@ -2221,21 +2311,18 @@ fi
tools_dirs=""
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_HELP_STRING([--with-mysqlmanager], [Build the mysqlmanager binary: yes/no (default: build if server is built.)]),,)
+
+if test "$with_mysqlmanager" = "yes" -o \
+ '(' "$with_mysqlmanager:$with_server" = ":yes" -a \
+ -d "$srcdir/server-tools" ')' ; then
+ tools_dirs="$tools_dirs server-tools"
+ AC_CONFIG_FILES(server-tools/Makefile server-tools/instance-manager/Makefile)
+fi
AC_SUBST(tools_dirs)
#MYSQL_CHECK_CPU
-MYSQL_CHECK_VIO
-MYSQL_CHECK_OPENSSL
-MYSQL_CHECK_YASSL
libmysqld_dirs=
linked_libmysqld_targets=
@@ -2400,73 +2487,6 @@ AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
AC_SUBST(readline_h_ln_cmd)
-MYSQL_CHECK_BIG_TABLES
-MYSQL_CHECK_MAX_INDEXES
-MYSQL_CHECK_REPLICATION
-
-MYSQL_STORAGE_ENGINE(innobase,,innodb,,,,innobase,ha_innodb.o,[ dnl
- \$(top_builddir)/storage/innobase/usr/libusr.a dnl
- \$(top_builddir)/storage/innobase/srv/libsrv.a dnl
- \$(top_builddir)/storage/innobase/dict/libdict.a dnl
- \$(top_builddir)/storage/innobase/que/libque.a dnl
- \$(top_builddir)/storage/innobase/srv/libsrv.a dnl
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a dnl
- \$(top_builddir)/storage/innobase/row/librow.a dnl
- \$(top_builddir)/storage/innobase/pars/libpars.a dnl
- \$(top_builddir)/storage/innobase/btr/libbtr.a dnl
- \$(top_builddir)/storage/innobase/trx/libtrx.a dnl
- \$(top_builddir)/storage/innobase/read/libread.a dnl
- \$(top_builddir)/storage/innobase/usr/libusr.a dnl
- \$(top_builddir)/storage/innobase/buf/libbuf.a dnl
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a dnl
- \$(top_builddir)/storage/innobase/eval/libeval.a dnl
- \$(top_builddir)/storage/innobase/log/liblog.a dnl
- \$(top_builddir)/storage/innobase/fsp/libfsp.a dnl
- \$(top_builddir)/storage/innobase/fut/libfut.a dnl
- \$(top_builddir)/storage/innobase/fil/libfil.a dnl
- \$(top_builddir)/storage/innobase/lock/liblock.a dnl
- \$(top_builddir)/storage/innobase/mtr/libmtr.a dnl
- \$(top_builddir)/storage/innobase/page/libpage.a dnl
- \$(top_builddir)/storage/innobase/rem/librem.a dnl
- \$(top_builddir)/storage/innobase/thr/libthr.a dnl
- \$(top_builddir)/storage/innobase/sync/libsync.a dnl
- \$(top_builddir)/storage/innobase/data/libdata.a dnl
- \$(top_builddir)/storage/innobase/mach/libmach.a dnl
- \$(top_builddir)/storage/innobase/ha/libha.a dnl
- \$(top_builddir)/storage/innobase/dyn/libdyn.a dnl
- \$(top_builddir)/storage/innobase/mem/libmem.a dnl
- \$(top_builddir)/storage/innobase/sync/libsync.a dnl
- \$(top_builddir)/storage/innobase/ut/libut.a dnl
- \$(top_builddir)/storage/innobase/os/libos.a dnl
- \$(top_builddir)/storage/innobase/ut/libut.a],[
- AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
- AC_SUBST(innodb_includes)
- AC_SUBST(innodb_libs)
- AC_SUBST(innodb_system_libs)
- other_configures="$other_configures storage/innobase/configure"
-])
-
-MYSQL_STORAGE_ENGINE(berkeley,,berkeley-db,,,,bdb,,,[
- MYSQL_SETUP_BERKELEY_DB
-])
-MYSQL_STORAGE_ENGINE(example,,,,,,example,no,
- \$(top_builddir)/storage/example/libexample.a,[
- AC_CONFIG_FILES(storage/example/Makefile)
-])
-MYSQL_STORAGE_ENGINE(archive,,,,,,archive,,
- \$(top_builddir)/storage/archive/libarchive.a, [
- AC_CONFIG_FILES(storage/archive/Makefile)
-])
-MYSQL_STORAGE_ENGINE(csv,,,"yes",,tina_hton,csv,no,
- \$(top_builddir)/storage/csv/libcsv.a,[
- AC_CONFIG_FILES(storage/csv/Makefile)
-])
-MYSQL_STORAGE_ENGINE(blackhole)
-MYSQL_STORAGE_ENGINE(federated)
-MYSQL_STORAGE_ENGINE(ndbcluster,,ndbcluster,,,,ndb,,,[
- MYSQL_SETUP_NDBCLUSTER
-])
-MYSQL_STORAGE_ENGINE(partition,,partition)
# If we have threads generate some library functions and test programs
sql_server_dirs=
@@ -2523,7 +2543,7 @@ then
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
sql_server_dirs="strings mysys dbug extra regex"
- mysql_se_dirs="myisam myisammrg heap $mysql_se_dirs"
+
sql_server="$sql_server vio sql"
fi
@@ -2539,12 +2559,9 @@ AC_SUBST(sql_server)
AC_SUBST(thread_dirs)
AC_SUBST(server_scripts)
-AC_SUBST(mysql_se_dirs)
-AC_SUBST(mysql_se_libs)
-AC_SUBST(mysql_se_objs)
-AC_SUBST(mysql_se_htons)
-AC_SUBST(mysql_se_decls)
-AC_SUBST(mysql_se_plugins)
+AC_SUBST(mysql_plugin_dirs)
+AC_SUBST(mysql_plugin_libs)
+AC_SUBST(mysql_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
@@ -2586,25 +2603,18 @@ AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
# Output results
AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
- unittest/Makefile dnl
- unittest/mytap/Makefile unittest/mytap/t/Makefile dnl
+ unittest/Makefile unittest/mytap/Makefile unittest/mytap/t/Makefile dnl
unittest/mysys/Makefile unittest/examples/Makefile dnl
- strings/Makefile regex/Makefile storage/Makefile storage/heap/Makefile dnl
- storage/myisam/Makefile storage/myisammrg/Makefile dnl
+ strings/Makefile regex/Makefile storage/Makefile dnl
man/Makefile BUILD/Makefile vio/Makefile dnl
libmysql/Makefile client/Makefile dnl
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
- sql/handlerton.cc sql-common/Makefile dnl
- dbug/Makefile scripts/Makefile dnl
- include/Makefile dnl
- server-tools/Makefile server-tools/instance-manager/Makefile dnl
+ sql/sql_builtin.cc sql-common/Makefile dnl
+ dbug/Makefile scripts/Makefile include/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
mysql-test/ndb/Makefile netware/Makefile dnl
- include/mysql_version.h dnl
- plugin/Makefile dnl
- plugin/fulltext/Makefile dnl
- win/Makefile)
+ include/mysql_version.h plugin/Makefile win/Makefile)
AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)
AC_OUTPUT
diff --git a/dbug/cmakelists.txt b/dbug/CMakeLists.txt
index fe20fdd3db6..fe20fdd3db6 100644
--- a/dbug/cmakelists.txt
+++ b/dbug/CMakeLists.txt
diff --git a/dbug/Makefile.am b/dbug/Makefile.am
index b0c8862bede..60a95a82be5 100644
--- a/dbug/Makefile.am
+++ b/dbug/Makefile.am
@@ -20,7 +20,7 @@ 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 = cmakelists.txt example1.c example2.c example3.c \
+EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \
user.r monty.doc dbug_add_tags.pl \
my_main.c main.c factorial.c dbug_analyze.c
NROFF_INC = example1.r example2.r example3.r main.r \
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 52de4b4a92d..07f72a3e758 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -255,6 +255,8 @@ static void DBUGOpenFile(CODE_STATE *,const char *, const char *, int);
static void DBUGCloseFile(CODE_STATE *cs, FILE *fp);
/* Push current debug settings */
static void PushState(CODE_STATE *cs);
+ /* Free memory associated with debug state. */
+static void FreeState (CODE_STATE *cs, struct settings *state);
/* Test for tracing enabled */
static BOOLEAN DoTrace(CODE_STATE *cs);
@@ -742,19 +744,7 @@ void _db_pop_()
if (discard->next != NULL)
{
cs->stack= discard->next;
- if (!is_shared(discard, keywords))
- FreeList(discard->keywords);
- if (!is_shared(discard, functions))
- FreeList(discard->functions);
- if (!is_shared(discard, processes))
- FreeList(discard->processes);
- if (!is_shared(discard, p_functions))
- FreeList(discard->p_functions);
- if (!is_shared(discard, out_file))
- DBUGCloseFile(cs, discard->out_file);
- if (discard->prof_file)
- DBUGCloseFile(cs, discard->prof_file);
- free((char *) discard);
+ FreeState(cs, discard);
}
}
@@ -1425,6 +1415,74 @@ static void PushState(CODE_STATE *cs)
cs->stack= new_malloc;
}
+/*
+ * FUNCTION
+ *
+ * FreeState Free memory associated with a struct state.
+ *
+ * SYNOPSIS
+ *
+ * static void FreeState (state)
+ * struct state *state;
+ *
+ * DESCRIPTION
+ *
+ * Deallocates the memory allocated for various information in a
+ * state.
+ *
+ */
+static void FreeState (
+CODE_STATE *cs,
+struct settings *state)
+{
+ if (!is_shared(state, keywords))
+ FreeList(state->keywords);
+ if (!is_shared(state, functions))
+ FreeList(state->functions);
+ if (!is_shared(state, processes))
+ FreeList(state->processes);
+ if (!is_shared(state, p_functions))
+ FreeList(state->p_functions);
+ if (!is_shared(state, out_file))
+ DBUGCloseFile(cs, state->out_file);
+ if (state->prof_file)
+ DBUGCloseFile(cs, state->prof_file);
+ free((char *) state);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_end_ End debugging, freeing state stack memory.
+ *
+ * SYNOPSIS
+ *
+ * static VOID _db_end_ ()
+ *
+ * DESCRIPTION
+ *
+ * Ends debugging, de-allocating the memory allocated to the
+ * state stack.
+ *
+ * To be called at the very end of the program.
+ *
+ */
+void _db_end_ ()
+{
+ struct settings *discard;
+ CODE_STATE *cs=0;
+
+ get_code_state_or_return;
+
+ while((discard= cs->stack) != NULL) {
+ if(discard == &init_settings)
+ break;
+ cs->stack= discard->next;
+ FreeState (cs, discard);
+ }
+}
+
/*
* FUNCTION
diff --git a/extra/cmakelists.txt b/extra/CMakeLists.txt
index 50e0f04eb14..50e0f04eb14 100644
--- a/extra/cmakelists.txt
+++ b/extra/CMakeLists.txt
diff --git a/extra/Makefile.am b/extra/Makefile.am
index 4b483128439..de8e519e641 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -40,7 +40,7 @@ $(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 innochecksum
noinst_PROGRAMS = charset2html
-EXTRA_DIST = cmakelists.txt
+EXTRA_DIST = CMakeLists.txt
perror.o: perror.c
$(COMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<
diff --git a/extra/yassl/cmakelists.txt b/extra/yassl/CMakeLists.txt
index cafa3011e94..cafa3011e94 100644
--- a/extra/yassl/cmakelists.txt
+++ b/extra/yassl/CMakeLists.txt
diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am
index 3ce5e2632cc..e4a81019cd1 100644
--- a/extra/yassl/Makefile.am
+++ b/extra/yassl/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = taocrypt src
+SUBDIRS = taocrypt src testsuite
EXTRA_DIST = yassl.dsp yassl.dsw yassl.vcproj $(wildcard mySTL/*.hpp) \
- cmakelists.txt
+ CMakeLists.txt
diff --git a/extra/yassl/README b/extra/yassl/README
index 198a1031cb7..62209723f66 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -1,4 +1,170 @@
-yaSSL Release notes, version 0.9.6
+yaSSL Release notes, version 1.3.0 (04/26/06)
+
+
+ This release of yaSSL contains minor bug fixes, portability enhancements,
+ and libcurl support.
+
+See normal build instructions below under 1.0.6.
+
+
+--To build for libcurl on Linux, Solaris, *BSD, Mac OS X, or Cygwin:
+
+ To build for libcurl the library needs to be built without C++ globals since
+ the linker will be called in a C context, also libcurl configure will expect
+ OpenSSL library names so some symbolic links are created.
+
+ ./configure --enable-pure-c
+ make
+ make openssl-links
+
+ (then go to your libcurl home and tell libcurl about yaSSL)
+ ./configure --with-ssl=/yaSSL-HomeDir
+ make
+
+
+--To build for libcurl on Win32:
+
+ Simply add the yaSSL project as a dependency to libcurl, add
+ yaSSL-Home\include and yaSSL-Home\include\openssl to the include list, and
+ define USE_SSLEAY and USE_OPENSSL
+
+ please email todd@yassl.com if you have any questions.
+
+
+*******************yaSSL Release notes, version 1.2.2 (03/27/06)
+
+
+ This release of yaSSL contains minor bug fixes and portability enhancements.
+
+See build instructions below under 1.0.6:
+
+
+
+*******************yaSSL Release notes, version 1.2.0
+
+
+ This release of yaSSL contains minor bug fixes, portability enhancements,
+ Diffie-Hellman compatibility fixes for other servers and client,
+ optimization improvements, and x86 ASM changes.
+
+See build instructions below under 1.0.6:
+
+
+
+*****************yaSSL Release notes, version 1.1.5
+
+ This release of yaSSL contains minor bug fixes, portability enhancements,
+ and user requested changes including the ability to add all certificates in
+ a directory, more robust socket handling, no new overloading unless
+ requested, and an SSL_VERIFY_NONE option.
+
+
+See build instructions below under 1.0.6:
+
+
+
+******************yaSSL Release notes, version 1.0.6
+
+This release of yaSSL contains minor bug fixes, portability enhancements,
+x86 assembly for ARC4, SHA, MD5, and RIPEMD, --enable-ia32-asm configure
+option, and a security patch for certificate chain processing.
+
+--To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin:
+
+ ./configure
+ make
+
+ run testsuite from yaSSL-Home/testsuite to test the build
+
+to make a release build:
+
+ ./configure --disable-debug
+ 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
+
+
+--To enable ia32 assembly for TaoCrypt ciphers and message digests
+
+ On MSVC this is always on
+
+ On GCC **, use ./configure --enable-ia32-asm
+
+ ** This isn't on by default because of the use of intel syntax and the
+ problem that olders versions of gas have with some addressing statements.
+ If you enable this and get assemler errors during compilation or can't
+ pass the TaoCrypt tests, please send todd@yassl.com a message and disable
+ this option in the meantime.
+
+
+***************** yaSSL Release notes, version 1.0.5
+
+This release of yaSSL contains minor bug fixes, portability enhancements,
+x86 assembly for AES, 3DES, BLOWFISH, and TWOFISH, --without-debug configure
+option, and --enable-kernel-mode configure option for using TaoCrypt with
+kernel modules.
+
+--To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin:
+
+ ./configure
+ make
+
+ run testsuite from yaSSL-Home/testsuite to test the build
+
+to make a release build:
+
+ ./configure --without-debug
+ 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 1.0.1
+
+This release of yaSSL contains minor bug fixes, portability enhancements,
+GCC 3.4.4 support, MSVC 2003 support, and more documentation.
+
+Please see build instructions in the release notes for 0.9.6 below.
+
+
+******************yaSSL Release notes, version 1.0
+
+This release of yaSSL contains minor bug fixes, portability enhancements,
+GCC 4.0 support, testsuite, improvements, and API additions.
+
+Please see build instructions in the release notes for 0.9.6 below.
+
+
+******************yaSSL Release notes, version 0.9.9
+
+This release of yaSSL contains minor bug fixes, portability enchancements,
+MSVC 7 support, memory improvements, and API additions.
+
+Please see build instructions in the release notes for 0.9.6 below.
+
+
+******************yaSSL Release notes, version 0.9.8
+
+This release of yaSSL contains minor bug fixes and portability enchancements.
+
+Please see build instructions in the release notes for 0.9.6 below.
+
+
+******************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
diff --git a/extra/yassl/certs/ca-cert.pem b/extra/yassl/certs/ca-cert.pem
new file mode 100644
index 00000000000..981dd004fc6
--- /dev/null
+++ b/extra/yassl/certs/ca-cert.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ Validity
+ Not Before: Jan 18 20:12:32 2005 GMT
+ Not After : Oct 15 20:12:32 2007 GMT
+ Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:cf:2b:14:00:b0:3c:df:6f:9e:91:40:ec:c8:f6:
+ 90:b2:5b:b4:70:80:a5:a4:0a:73:c7:44:f3:2a:26:
+ c4:2f:f1:3a:f1:c3:c4:ac:fc:c3:d2:c3:bf:f5:d7:
+ 6a:38:42:ad:22:ab:c8:c4:4b:4c:1d:16:af:05:34:
+ 7d:79:97:5e:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84
+ X509v3 Authority Key Identifier:
+ keyid:CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84
+ DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: md5WithRSAEncryption
+ 27:f7:3d:fb:39:6f:73:a4:86:f3:a0:48:22:60:84:e9:5c:3d:
+ 28:36:05:16:44:98:07:87:e1:5d:b5:f3:a7:bc:33:5f:f4:29:
+ a9:5f:87:33:df:e6:8e:bd:e2:f3:0a:c8:00:69:ae:3d:41:47:
+ 03:ea:0b:4c:67:45:4b:ab:f3:39
+-----BEGIN CERTIFICATE-----
+MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx
+DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh
+d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb
+BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDExODIwMTIzMloXDTA3
+MTAxNTIwMTIzMlowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP
+BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3
+LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh
+c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDPKxQAsDzfb56RQOzI9pCy
+W7RwgKWkCnPHRPMqJsQv8Trxw8Ss/MPSw7/112o4Qq0iq8jES0wdFq8FNH15l17h
+AgMBAAGjgekwgeYwHQYDVR0OBBYEFMsPH+midnHJ5ugjpsEYt8xEz7mEMIG2BgNV
+HSMEga4wgauAFMsPH+midnHJ5ugjpsEYt8xEz7mEoYGPpIGMMIGJMQswCQYDVQQG
+EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE
+ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv
+bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAANBACf3Pfs5b3OkhvOgSCJghOlcPSg2BRZEmAeH4V21
+86e8M1/0KalfhzPf5o694vMKyABprj1BRwPqC0xnRUur8zk=
+-----END CERTIFICATE-----
diff --git a/extra/yassl/certs/client-cert.der b/extra/yassl/certs/client-cert.der
new file mode 100644
index 00000000000..b28e2753376
--- /dev/null
+++ b/extra/yassl/certs/client-cert.der
Binary files differ
diff --git a/extra/yassl/certs/client-cert.pem b/extra/yassl/certs/client-cert.pem
new file mode 100644
index 00000000000..81110f17252
--- /dev/null
+++ b/extra/yassl/certs/client-cert.pem
@@ -0,0 +1,52 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com
+ Validity
+ Not Before: Jan 18 19:33:15 2005 GMT
+ Not After : Oct 15 19:33:15 2007 GMT
+ Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:cd:1f:78:47:f8:b8:d6:08:bf:bd:7c:23:61:86:
+ 36:28:ac:ee:3c:a8:9a:94:e6:d5:26:e8:71:50:b2:
+ 26:8b:1c:1e:3f:75:b2:d3:b3:67:95:0c:fd:76:28:
+ 65:d5:ce:12:82:9e:06:00:a2:09:dd:ce:3a:26:dd:
+ 46:2a:a0:45:71
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD
+ X509v3 Authority Key Identifier:
+ keyid:AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD
+ DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL/CN=www.yassl.com/emailAddress=info@yassl.com
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: md5WithRSAEncryption
+ c5:82:26:0c:1f:61:01:14:b0:ce:18:99:64:91:0e:f1:f8:90:
+ 3e:a3:0e:be:38:7c:97:ba:05:c9:2a:dc:dd:62:2d:12:61:79:
+ 7a:86:b1:97:5d:1e:e8:f7:e8:32:34:f7:8f:b1:08:3d:13:71:
+ a6:3c:15:91:85:12:35:6e:78:87
+-----BEGIN CERTIFICATE-----
+MIICtzCCAmGgAwIBAgIBADANBgkqhkiG9w0BAQQFADB4MQswCQYDVQQGEwJVUzEP
+MA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwGA1UEChMFeWFT
+U0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A
+eWFzc2wuY29tMB4XDTA1MDExODE5MzMxNVoXDTA3MTAxNTE5MzMxNVoweDELMAkG
+A1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxDjAM
+BgNVBAoTBXlhU1NMMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcN
+AQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDNH3hH
++LjWCL+9fCNhhjYorO48qJqU5tUm6HFQsiaLHB4/dbLTs2eVDP12KGXVzhKCngYA
+ogndzjom3UYqoEVxAgMBAAGjgdUwgdIwHQYDVR0OBBYEFK4lXvpNo1srh97xKvVC
+wP/OtbStMIGiBgNVHSMEgZowgZeAFK4lXvpNo1srh97xKvVCwP/OtbStoXykejB4
+MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFu
+ZDEOMAwGA1UEChMFeWFTU0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkq
+hkiG9w0BCQEWDmluZm9AeWFzc2wuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZI
+hvcNAQEEBQADQQDFgiYMH2EBFLDOGJlkkQ7x+JA+ow6+OHyXugXJKtzdYi0SYXl6
+hrGXXR7o9+gyNPePsQg9E3GmPBWRhRI1bniH
+-----END CERTIFICATE-----
diff --git a/extra/yassl/certs/client-key.der b/extra/yassl/certs/client-key.der
new file mode 100644
index 00000000000..6e8b432a07c
--- /dev/null
+++ b/extra/yassl/certs/client-key.der
Binary files differ
diff --git a/extra/yassl/certs/client-key.pem b/extra/yassl/certs/client-key.pem
new file mode 100644
index 00000000000..6898b2796fa
--- /dev/null
+++ b/extra/yassl/certs/client-key.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOgIBAAJBAM0feEf4uNYIv718I2GGNiis7jyompTm1SbocVCyJoscHj91stOz
+Z5UM/XYoZdXOEoKeBgCiCd3OOibdRiqgRXECAwEAAQJAXwa6OVVvg7Bv63+MAI0l
+n/hlMfLGEj9R9gFvJXwywPSEQhijOZmedpHALufFPNHtwba9dmbqMkBAw9JDaAgg
+QQIhAO+mBaSmoG5AYVKYQZiASe/2wMZjaQSN+zFLyF97OX8ZAiEA2x5iRmXUkbOT
+8Td/vx8R9mq9W5CJu+cN+SWGwTYhPBkCIGZFM6NQeKaUUvQshdHO7b66Twpa4jZP
+YSNoc9pLe/4BAiB+jIvBkKo2A/rbg2waG32qTXdTXKTPiuA9Fnk/OV30cQIhANuA
+uMdo+T+rYcNGJ1hCYKDe9JWBpNfSQ+H/A7sWuW8L
+-----END RSA PRIVATE KEY-----
diff --git a/extra/yassl/certs/dh1024.dat b/extra/yassl/certs/dh1024.dat
new file mode 100644
index 00000000000..86a95518278
--- /dev/null
+++ b/extra/yassl/certs/dh1024.dat
@@ -0,0 +1 @@
+30818702818100DA9A18547FF03B385CC16508C173A7EF4EB61CB40EF8FEF3B31F145051676166BCDC3FE6B799FC394D08C26385F9413F896E09117E46209D6923602683CEA100924A6EE695281775C619DAA94EA8CB3691B4275B0183F1D39639EBC92995FE645D6C1BC28D409E585549BBD2C5DCDD6C208B04EADD8B7A6D997F72CBAD88390F020102 \ No newline at end of file
diff --git a/extra/yassl/certs/dsa-cert.pem b/extra/yassl/certs/dsa-cert.pem
new file mode 100644
index 00000000000..ecca18dae82
--- /dev/null
+++ b/extra/yassl/certs/dsa-cert.pem
@@ -0,0 +1,68 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: dsaWithSHA1
+ Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com
+ Validity
+ Not Before: Jan 23 22:54:51 2005 GMT
+ Not After : Oct 20 22:54:51 2007 GMT
+ Subject: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com
+ Subject Public Key Info:
+ Public Key Algorithm: dsaEncryption
+ DSA Public Key:
+ pub:
+ 04:84:a0:26:31:72:0c:e8:4f:5d:53:17:62:b1:80:
+ ca:c0:16:5f:c3:1e:ea:c5:d9:98:38:f9:be:56:53:
+ 47:68:ce:08:22:57:1c:bb:0d:77:91:cf:5b:36:ed:
+ f3:24:82:90:8a:cd:90:7c:db:77:f9:17:2d:73:73:
+ ef:bb:b9:82
+ P:
+ 00:99:29:69:80:c9:3c:98:68:45:a9:82:fe:67:eb:
+ 95:88:c5:b4:0c:d6:26:45:95:19:2c:a0:20:5b:7e:
+ df:69:e9:dc:c3:0f:f3:61:0a:25:9b:f2:21:01:6a:
+ cd:aa:8c:37:e7:ca:66:db:56:f4:0f:7d:7a:d1:18:
+ b9:42:fd:1b:11
+ Q:
+ 00:ad:25:29:ab:0a:9f:09:1c:c1:ad:03:20:76:7f:
+ a6:b7:dd:4d:03:09
+ G:
+ 12:88:99:da:e7:d0:0b:93:9b:e6:ee:3c:21:7f:9c:
+ b3:b4:8d:a5:8c:e2:37:80:3f:17:d1:81:4f:bd:f0:
+ 71:b6:32:08:54:dd:bf:01:e2:b3:77:06:64:75:8a:
+ 04:d6:79:39:b1:02:03:03:c6:06:74:e5:90:05:0a:
+ 10:46:19:31
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2
+ X509v3 Authority Key Identifier:
+ keyid:BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2
+ DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL DSA/CN=yaSSL DSA/emailAddress=info@yassl.com
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: dsaWithSHA1
+ 30:2b:02:14:74:46:9f:91:7b:24:17:3b:ee:0f:10:e3:76:62:
+ f4:dc:81:e6:fd:fe:02:13:08:f4:87:0a:ab:ba:9c:de:3a:69:
+ 72:59:b8:ec:e9:57:f4:bf:37
+-----BEGIN CERTIFICATE-----
+MIIDMTCCAvKgAwIBAgIBADAJBgcqhkjOOAQDMHgxCzAJBgNVBAYTAlVTMQ8wDQYD
+VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMRIwEAYDVQQKEwl5YVNTTCBE
+U0ExEjAQBgNVBAMTCXlhU1NMIERTQTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNz
+bC5jb20wHhcNMDUwMTIzMjI1NDUxWhcNMDcxMDIwMjI1NDUxWjB4MQswCQYDVQQG
+EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDESMBAGA1UE
+ChMJeWFTU0wgRFNBMRIwEAYDVQQDEwl5YVNTTCBEU0ExHTAbBgkqhkiG9w0BCQEW
+DmluZm9AeWFzc2wuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAmSlpgMk8mGhFqYL+
+Z+uViMW0DNYmRZUZLKAgW37faencww/zYQolm/IhAWrNqow358pm21b0D3160Ri5
+Qv0bEQIVAK0lKasKnwkcwa0DIHZ/prfdTQMJAkASiJna59ALk5vm7jwhf5yztI2l
+jOI3gD8X0YFPvfBxtjIIVN2/AeKzdwZkdYoE1nk5sQIDA8YGdOWQBQoQRhkxA0MA
+AkAEhKAmMXIM6E9dUxdisYDKwBZfwx7qxdmYOPm+VlNHaM4IIlccuw13kc9bNu3z
+JIKQis2QfNt3+Rctc3Pvu7mCo4HVMIHSMB0GA1UdDgQWBBS++Yxd1hy07oHdNlYK
+IeRhRHPp4jCBogYDVR0jBIGaMIGXgBS++Yxd1hy07oHdNlYKIeRhRHPp4qF8pHow
+eDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxh
+bmQxEjAQBgNVBAoTCXlhU1NMIERTQTESMBAGA1UEAxMJeWFTU0wgRFNBMR0wGwYJ
+KoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbYIBADAMBgNVHRMEBTADAQH/MAkGByqG
+SM44BAMDLgAwKwIUdEafkXskFzvuDxDjdmL03IHm/f4CEwj0hwqrupzeOmlyWbjs
+6Vf0vzc=
+-----END CERTIFICATE-----
diff --git a/extra/yassl/certs/dsa512.der b/extra/yassl/certs/dsa512.der
new file mode 100644
index 00000000000..fe79ccb612b
--- /dev/null
+++ b/extra/yassl/certs/dsa512.der
Binary files differ
diff --git a/extra/yassl/certs/dsa512.pem b/extra/yassl/certs/dsa512.pem
new file mode 100644
index 00000000000..04a3dd94a77
--- /dev/null
+++ b/extra/yassl/certs/dsa512.pem
@@ -0,0 +1,8 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIH3AgEAAkEAmSlpgMk8mGhFqYL+Z+uViMW0DNYmRZUZLKAgW37faencww/zYQol
+m/IhAWrNqow358pm21b0D3160Ri5Qv0bEQIVAK0lKasKnwkcwa0DIHZ/prfdTQMJ
+AkASiJna59ALk5vm7jwhf5yztI2ljOI3gD8X0YFPvfBxtjIIVN2/AeKzdwZkdYoE
+1nk5sQIDA8YGdOWQBQoQRhkxAkAEhKAmMXIM6E9dUxdisYDKwBZfwx7qxdmYOPm+
+VlNHaM4IIlccuw13kc9bNu3zJIKQis2QfNt3+Rctc3Pvu7mCAhQjg+e+aqykxwwc
+E2V27tjDFY02uA==
+-----END DSA PRIVATE KEY-----
diff --git a/extra/yassl/certs/server-cert.pem b/extra/yassl/certs/server-cert.pem
new file mode 100644
index 00000000000..403dabdf5fa
--- /dev/null
+++ b/extra/yassl/certs/server-cert.pem
@@ -0,0 +1,38 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ Validity
+ Not Before: Jan 18 20:50:59 2005 GMT
+ Not After : Oct 15 20:50:59 2007 GMT
+ Subject: C=US, ST=Oregon, L=Portland, O=taoSoftDev, CN=www.taosoftdev.com/emailAddress=info@yassl.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:a4:68:bb:bc:b7:27:5f:3c:f5:78:c6:1a:af:b9:
+ 95:fc:7e:61:1f:a8:81:0a:ca:43:88:9a:03:e0:d0:
+ a6:79:70:16:34:b9:7c:75:54:ca:70:19:66:38:be:
+ 6e:28:7e:a5:ff:6b:3c:83:2f:39:42:c3:15:f3:bd:
+ f2:25:93:22:e7
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: md5WithRSAEncryption
+ 08:36:07:8c:3a:7f:f9:91:0a:82:d1:6a:c1:34:be:bc:2d:b2:
+ 20:98:dc:45:50:53:9c:66:e6:26:71:bd:fa:d2:b4:91:d3:53:
+ c0:20:05:c0:b6:84:9a:5f:3f:61:75:f5:fd:c6:ec:e2:f6:9f:
+ a2:13:17:a9:b7:83:60:cc:cb:eb
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAaECAQEwDQYJKoZIhvcNAQEEBQAwgYkxCzAJBgNVBAYTAlVTMQ8wDQYD
+VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290
+aDEkMCIGA1UEAxMbd3d3LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZI
+hvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0wNTAxMTgyMDUwNTlaFw0wNzEwMTUy
+MDUwNTlaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH
+EwhQb3J0bGFuZDETMBEGA1UEChMKdGFvU29mdERldjEbMBkGA1UEAxMSd3d3LnRh
+b3NvZnRkZXYuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0G
+CSqGSIb3DQEBAQUAA0sAMEgCQQCkaLu8tydfPPV4xhqvuZX8fmEfqIEKykOImgPg
+0KZ5cBY0uXx1VMpwGWY4vm4ofqX/azyDLzlCwxXzvfIlkyLnAgMBAAEwDQYJKoZI
+hvcNAQEEBQADQQAINgeMOn/5kQqC0WrBNL68LbIgmNxFUFOcZuYmcb360rSR01PA
+IAXAtoSaXz9hdfX9xuzi9p+iExept4NgzMvr
+-----END CERTIFICATE-----
diff --git a/extra/yassl/certs/server-key.pem b/extra/yassl/certs/server-key.pem
new file mode 100644
index 00000000000..d6055c4cfd8
--- /dev/null
+++ b/extra/yassl/certs/server-key.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOQIBAAJBAKRou7y3J1889XjGGq+5lfx+YR+ogQrKQ4iaA+DQpnlwFjS5fHVU
+ynAZZji+bih+pf9rPIMvOULDFfO98iWTIucCAwEAAQJABLVvMw931DV1vljGKORC
+1HF2LKbx0zJJzt7CX6z6J54vcE79K3NYXdU6o7/j1WTtfD47tFG+4ljGvSYPmrCI
+2QIhANfiY6is6JUJGGgeMxyWeQRPXfaE9Yrk6OhxHhpYf5CTAiEAwvWraeLPy/NE
+B+0w80mh8tCv2tpuKaYMOG53XpYX3N0CIDy/Bj3rUZLGOWjqvoUXzjupPY5lgVYw
+7Vyin87YAiUjAiAgM8X5em5KSMc+6+2+8bWfTtsNMjEqDfRMyepLpE0SvQIgTSYL
+WWfcZoRUPDM9GEuQ40nifVNjobzvjTW4aYyHCEI=
+-----END RSA PRIVATE KEY-----
diff --git a/extra/yassl/certs/taoCert.txt b/extra/yassl/certs/taoCert.txt
new file mode 100644
index 00000000000..585293e4f2b
--- /dev/null
+++ b/extra/yassl/certs/taoCert.txt
@@ -0,0 +1,50 @@
+
+***** Create a self signed cert ************
+
+1) openssl genrsa 512 > client-key.pem
+
+2) openssl req -new -x509 -nodes -md5 -days 1000 -key client-key.pem > client-cert.pem
+
+-- adding metadata to beginning
+
+3) openssl x509 -in client-cert.pem -text > tmp.pem
+
+4) mv tmp.pem client-cert.pem
+
+
+***** Create a CA, signing authority **********
+
+same as self signed, use ca prefix instead of client
+
+
+***** Create a cert signed by CA **************
+
+1) openssl req -newkey rsa:512 -md5 -days 1000 -nodes -keyout server-key.pem > server-req.pem
+
+2) copy ca-key.pem ca-cert.srl (why ????)
+
+3) openssl x509 -req -in server-req.pem -days 1000 -md5 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
+
+
+
+***** To create a dsa cert ********************
+
+1) openssl dsaparam 512 > dsa512.param # creates group params
+
+2) openssl gendsa dsa512.param > dsa512.pem # creates private key
+
+3) openssl req -new -x509 -nodes -days 1000 -key dsa512.pem > dsa-cert.pem
+
+
+
+
+***** To convert from PEM to DER **************
+
+a) openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
+
+to convert rsa private PEM to DER :
+
+b) openssl rsa -in key.pem -outform DER -out key.der
+
+
+
diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp
new file mode 100644
index 00000000000..94bf753210b
--- /dev/null
+++ b/extra/yassl/examples/client/client.cpp
@@ -0,0 +1,98 @@
+/* client.cpp */
+
+#include "../../testsuite/test.hpp"
+
+//#define TEST_RESUME
+
+
+void client_test(void* args)
+{
+#ifdef _WIN32
+ WSADATA wsd;
+ WSAStartup(0x0002, &wsd);
+#endif
+
+ SOCKET_T sockfd = 0;
+ int argc = 0;
+ char** argv = 0;
+
+ set_args(argc, argv, *static_cast<func_args*>(args));
+ tcp_connect(sockfd);
+
+ SSL_METHOD* method = TLSv1_client_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+
+ set_certs(ctx);
+ SSL* ssl = SSL_new(ctx);
+
+ SSL_set_fd(ssl, sockfd);
+
+ if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed");
+ showPeer(ssl);
+
+ const char* cipher = 0;
+ int index = 0;
+ char list[1024];
+ strncpy(list, "cipherlist", 11);
+ while ( (cipher = SSL_get_cipher_list(ssl, index++)) ) {
+ strncat(list, ":", 2);
+ strncat(list, cipher, strlen(cipher) + 1);
+ }
+ printf("%s\n", list);
+ printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl));
+
+ char msg[] = "hello yassl!";
+ if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
+ err_sys("SSL_write failed");
+
+ char reply[1024];
+ reply[SSL_read(ssl, reply, sizeof(reply))] = 0;
+ printf("Server response: %s\n", reply);
+
+#ifdef TEST_RESUME
+ SSL_SESSION* session = SSL_get_session(ssl);
+ SSL* sslResume = SSL_new(ctx);
+#endif
+
+ SSL_shutdown(ssl);
+ SSL_free(ssl);
+
+#ifdef TEST_RESUME
+ tcp_connect(sockfd);
+ SSL_set_fd(sslResume, sockfd);
+ SSL_set_session(sslResume, session);
+
+ if (SSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed");
+
+ if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg))
+ err_sys("SSL_write failed");
+
+ reply[SSL_read(sslResume, reply, sizeof(reply))] = 0;
+ printf("Server response: %s\n", reply);
+
+ SSL_shutdown(sslResume);
+ SSL_free(sslResume);
+#endif // TEST_RESUME
+
+ SSL_CTX_free(ctx);
+ ((func_args*)args)->return_code = 0;
+}
+
+
+#ifndef NO_MAIN_DRIVER
+
+ int main(int argc, char** argv)
+ {
+ func_args args;
+
+ args.argc = argc;
+ args.argv = argv;
+
+ client_test(&args);
+ yaSSL_CleanUp();
+
+ return args.return_code;
+ }
+
+#endif // NO_MAIN_DRIVER
+
diff --git a/extra/yassl/examples/client/client.dsp b/extra/yassl/examples/client/client.dsp
new file mode 100644
index 00000000000..1caa585dadb
--- /dev/null
+++ b/extra/yassl/examples/client/client.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=client - 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 "client.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 "client.mak" CFG="client - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "client - 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 "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "..\..\taocrypt\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\taocrypt\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "client - Win32 Release"
+# Name "client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\client.cpp
+# 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/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp
new file mode 100644
index 00000000000..fd3f7dd48a3
--- /dev/null
+++ b/extra/yassl/examples/echoclient/echoclient.cpp
@@ -0,0 +1,90 @@
+/* echoclient.cpp */
+
+#include "../../testsuite/test.hpp"
+
+
+void echoclient_test(void* args)
+{
+#ifdef _WIN32
+ WSADATA wsd;
+ WSAStartup(0x0002, &wsd);
+#endif
+
+ SOCKET_T sockfd = 0;
+ int argc = 0;
+ char** argv = 0;
+
+ FILE* fin = stdin;
+ FILE* fout = stdout;
+
+ bool inCreated = false;
+ bool outCreated = false;
+
+ set_args(argc, argv, *static_cast<func_args*>(args));
+ if (argc >= 2) {
+ fin = fopen(argv[1], "r");
+ inCreated = true;
+ }
+ if (argc >= 3) {
+ fout = fopen(argv[2], "w");
+ outCreated = true;
+ }
+
+ if (!fin) err_sys("can't open input file");
+ if (!fout) err_sys("can't open output file");
+
+ tcp_connect(sockfd);
+
+ SSL_METHOD* method = TLSv1_client_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+ set_certs(ctx);
+ SSL* ssl = SSL_new(ctx);
+
+ SSL_set_fd(ssl, sockfd);
+ if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed");
+
+ char send[1024];
+ char reply[1024];
+
+ while (fgets(send, sizeof(send), fin)) {
+
+ int sendSz = strlen(send) + 1;
+ if (SSL_write(ssl, send, sendSz) != sendSz)
+ err_sys("SSL_write failed");
+
+ if (strncmp(send, "quit", 4) == 0) {
+ fputs("sending server shutdown command: quit!\n", fout);
+ break;
+ }
+
+ if (SSL_read(ssl, reply, sizeof(reply)) > 0)
+ fputs(reply, fout);
+ }
+
+ SSL_CTX_free(ctx);
+ SSL_free(ssl);
+
+ fflush(fout);
+ if (inCreated) fclose(fin);
+ if (outCreated) fclose(fout);
+
+ ((func_args*)args)->return_code = 0;
+}
+
+
+#ifndef NO_MAIN_DRIVER
+
+ int main(int argc, char** argv)
+ {
+ func_args args;
+
+ args.argc = argc;
+ args.argv = argv;
+
+ echoclient_test(&args);
+ yaSSL_CleanUp();
+
+ return args.return_code;
+ }
+
+#endif // NO_MAIN_DRIVER
diff --git a/extra/yassl/examples/echoclient/echoclient.dsp b/extra/yassl/examples/echoclient/echoclient.dsp
new file mode 100644
index 00000000000..52052c6dc44
--- /dev/null
+++ b/extra/yassl/examples/echoclient/echoclient.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="echoclient" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=echoclient - 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 "echoclient.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 "echoclient.mak" CFG="echoclient - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "echoclient - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "echoclient - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "echoclient - 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 "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "..\..\include" /I "..\..\taocrypt\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "echoclient - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\taocrypt\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "echoclient - Win32 Release"
+# Name "echoclient - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\echoclient.cpp
+# 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/extra/yassl/examples/echoclient/input b/extra/yassl/examples/echoclient/input
new file mode 100644
index 00000000000..438a592852c
--- /dev/null
+++ b/extra/yassl/examples/echoclient/input
@@ -0,0 +1,93 @@
+/* echoclient.cpp */
+
+#include "openssl/ssl.h" /* openssl compatibility test */
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#ifdef WIN32
+ #include <winsock2.h>
+#else
+ #include <string.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <sys/ioctl.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+#endif /* WIN32 */
+
+
+void err_sys(const char* msg)
+{
+ fputs("yassl client error: ", stderr);
+ fputs(msg, stderr);
+ exit(EXIT_FAILURE);
+}
+
+const char* loopback = "127.0.0.1";
+const short yasslPort = 11111;
+
+using namespace yaSSL;
+
+
+int main(int argc, char** argv)
+{
+#ifdef WIN32
+ WSADATA wsd;
+ WSAStartup(0x0002, &wsd);
+ int sockfd;
+#else
+ unsigned int sockfd;
+#endif /* WIN32 */
+
+ FILE* fin = stdin;
+ FILE* fout = stdout;
+
+ if (argc >= 2) fin = fopen(argv[1], "r");
+ if (argc >= 3) fout = fopen(argv[2], "w");
+
+ if (!fin) err_sys("can't open input file");
+ if (!fout) err_sys("can't open output file");
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ sockaddr_in servaddr;
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+
+ servaddr.sin_port = htons(yasslPort);
+ servaddr.sin_addr.s_addr = inet_addr(loopback);
+ if (connect(sockfd, (const sockaddr*)&servaddr, sizeof(servaddr)) != 0)
+ err_sys("tcp connect failed");
+
+ SSL_METHOD* method = TLSv1_client_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+ SSL* ssl = SSL_new(ctx);
+
+ SSL_set_fd(ssl, sockfd);
+ if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed");
+
+ char send[1024];
+ char reply[1024];
+
+ while (fgets(send, sizeof(send), fin)) {
+
+ int sendSz = strlen(send) + 1;
+ if (SSL_write(ssl, send, sendSz) != sendSz)
+ err_sys("SSL_write failed");
+
+ if (strncmp(send, "quit", 4) == 0) {
+ fputs("sending server shutdown command: quit!", fout);
+ break;
+ }
+
+ if (SSL_read(ssl, reply, sizeof(reply)) > 0)
+ fputs(reply, fout);
+ }
+
+ SSL_CTX_free(ctx);
+ SSL_free(ssl);
+
+ return 0;
+}
diff --git a/extra/yassl/examples/echoclient/quit b/extra/yassl/examples/echoclient/quit
new file mode 100644
index 00000000000..3db49b3ad12
--- /dev/null
+++ b/extra/yassl/examples/echoclient/quit
@@ -0,0 +1,2 @@
+quit
+
diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp
new file mode 100644
index 00000000000..8e23ead20ab
--- /dev/null
+++ b/extra/yassl/examples/echoserver/echoserver.cpp
@@ -0,0 +1,129 @@
+/* echoserver.cpp */
+
+#include "../../testsuite/test.hpp"
+
+
+#ifndef NO_MAIN_DRIVER
+ #define ECHO_OUT
+
+ THREAD_RETURN YASSL_API echoserver_test(void*);
+ int main(int argc, char** argv)
+ {
+ func_args args;
+
+ args.argc = argc;
+ args.argv = argv;
+
+ echoserver_test(&args);
+ yaSSL_CleanUp();
+
+ return args.return_code;
+ }
+
+#endif // NO_MAIN_DRIVER
+
+
+THREAD_RETURN YASSL_API echoserver_test(void* args)
+{
+#ifdef _WIN32
+ WSADATA wsd;
+ WSAStartup(0x0002, &wsd);
+#endif
+
+ SOCKET_T sockfd = 0;
+ int argc = 0;
+ char** argv = 0;
+
+ set_args(argc, argv, *static_cast<func_args*>(args));
+
+#ifdef ECHO_OUT
+ FILE* fout = stdout;
+ if (argc >= 2) fout = fopen(argv[1], "w");
+ if (!fout) err_sys("can't open output file");
+#endif
+
+ tcp_listen(sockfd);
+
+ SSL_METHOD* method = TLSv1_server_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+
+ set_serverCerts(ctx);
+ DH* dh = set_tmpDH(ctx);
+
+ bool shutdown(false);
+
+#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER)
+ // signal ready to tcp_accept
+ func_args& server_args = *((func_args*)args);
+ tcp_ready& ready = *server_args.signal_;
+ pthread_mutex_lock(&ready.mutex_);
+ ready.ready_ = true;
+ pthread_cond_signal(&ready.cond_);
+ pthread_mutex_unlock(&ready.mutex_);
+#endif
+
+ while (!shutdown) {
+ sockaddr_in client;
+ socklen_t client_len = sizeof(client);
+ int clientfd = accept(sockfd, (sockaddr*)&client,
+ (ACCEPT_THIRD_T)&client_len);
+ if (clientfd == -1) err_sys("tcp accept failed");
+
+ SSL* ssl = SSL_new(ctx);
+ SSL_set_fd(ssl, clientfd);
+ if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed");
+
+ char command[1024];
+ int echoSz(0);
+ while ( (echoSz = SSL_read(ssl, command, sizeof(command))) > 0) {
+
+ if ( strncmp(command, "quit", 4) == 0) {
+ printf("client sent quit command: shutting down!\n");
+ shutdown = true;
+ break;
+ }
+ else if ( strncmp(command, "GET", 3) == 0) {
+ char type[] = "HTTP/1.0 200 ok\r\nContent-type:"
+ " text/html\r\n\r\n";
+ char header[] = "<html><body BGCOLOR=\"#ffffff\">\n<pre>\n";
+ char body[] = "greetings from yaSSL\n";
+ char footer[] = "</body></html>\r\n\r\n";
+
+ strncpy(command, type, sizeof(type));
+ echoSz = sizeof(type) - 1;
+
+ strncpy(&command[echoSz], header, sizeof(header));
+ echoSz += sizeof(header) - 1;
+ strncpy(&command[echoSz], body, sizeof(body));
+ echoSz += sizeof(body) - 1;
+ strncpy(&command[echoSz], footer, sizeof(footer));
+ echoSz += sizeof(footer);
+
+ if (SSL_write(ssl, command, echoSz) != echoSz)
+ err_sys("SSL_write failed");
+ break;
+ }
+ command[echoSz] = 0;
+
+ #ifdef ECHO_OUT
+ fputs(command, fout);
+ #endif
+
+ if (SSL_write(ssl, command, echoSz) != echoSz)
+ err_sys("SSL_write failed");
+ }
+ SSL_free(ssl);
+ }
+
+#ifdef _WIN32
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
+
+ DH_free(dh);
+ SSL_CTX_free(ctx);
+
+ ((func_args*)args)->return_code = 0;
+ return 0;
+}
diff --git a/extra/yassl/examples/echoserver/echoserver.dsp b/extra/yassl/examples/echoserver/echoserver.dsp
new file mode 100644
index 00000000000..21a965b013c
--- /dev/null
+++ b/extra/yassl/examples/echoserver/echoserver.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="echoserver" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=echoserver - 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 "echoserver.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 "echoserver.mak" CFG="echoserver - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "echoserver - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "echoserver - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "echoserver - 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 "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "..\..\include" /I "..\..\taocrypt\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "echoserver - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\taocrypt\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "echoserver - Win32 Release"
+# Name "echoserver - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\echoserver.cpp
+# 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/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp
new file mode 100644
index 00000000000..73cff19e371
--- /dev/null
+++ b/extra/yassl/examples/server/server.cpp
@@ -0,0 +1,75 @@
+/* server.cpp */
+
+
+#include "../../testsuite/test.hpp"
+
+
+THREAD_RETURN YASSL_API server_test(void* args)
+{
+#ifdef _WIN32
+ WSADATA wsd;
+ WSAStartup(0x0002, &wsd);
+#endif
+
+ SOCKET_T sockfd = 0;
+ int clientfd = 0;
+ int argc = 0;
+ char** argv = 0;
+
+ set_args(argc, argv, *static_cast<func_args*>(args));
+ tcp_accept(sockfd, clientfd, *static_cast<func_args*>(args));
+
+#ifdef _WIN32
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
+
+ SSL_METHOD* method = TLSv1_server_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+
+ //SSL_CTX_set_cipher_list(ctx, "RC4-SHA");
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
+ set_serverCerts(ctx);
+ DH* dh = set_tmpDH(ctx);
+
+ SSL* ssl = SSL_new(ctx);
+ SSL_set_fd(ssl, clientfd);
+
+ if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed");
+ showPeer(ssl);
+ printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl));
+
+ char command[1024];
+ command[SSL_read(ssl, command, sizeof(command))] = 0;
+ printf("First client command: %s\n", command);
+
+ char msg[] = "I hear you, fa shizzle!";
+ if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
+ err_sys("SSL_write failed");
+
+ DH_free(dh);
+ SSL_CTX_free(ctx);
+ SSL_free(ssl);
+
+ ((func_args*)args)->return_code = 0;
+ return 0;
+}
+
+
+#ifndef NO_MAIN_DRIVER
+
+ int main(int argc, char** argv)
+ {
+ func_args args;
+
+ args.argc = argc;
+ args.argv = argv;
+
+ server_test(&args);
+ yaSSL_CleanUp();
+
+ return args.return_code;
+ }
+
+#endif // NO_MAIN_DRIVER
diff --git a/extra/yassl/examples/server/server.dsp b/extra/yassl/examples/server/server.dsp
new file mode 100644
index 00000000000..9c797c54dfe
--- /dev/null
+++ b/extra/yassl/examples/server/server.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="server" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=server - 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 "server.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 "server.mak" CFG="server - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "server - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "server - 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)" == "server - 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 /MT /W3 /O2 /I "..\..\include" /I "..\..\taocrypt\include" /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 Ws2_32.lib /nologo /subsystem:console /machine:I386
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "server - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\taocrypt\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /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 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none /nodefaultlib
+
+!ENDIF
+
+# Begin Target
+
+# Name "server - Win32 Release"
+# Name "server - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\server.cpp
+# 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/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp
index 2381347c27e..2a214c529fd 100644
--- a/extra/yassl/include/cert_wrapper.hpp
+++ b/extra/yassl/include/cert_wrapper.hpp
@@ -83,6 +83,7 @@ class CertManager {
SignerList signers_; // decoded CA keys and names
// plus verified chained certs
bool verifyPeer_;
+ bool verifyNone_; // no error if verify fails
bool failNoCert_;
bool sendVerify_;
public:
@@ -107,10 +108,12 @@ public:
uint get_privateKeyLength() const;
bool verifyPeer() const;
+ bool verifyNone() const;
bool failNoCert() const;
bool sendVerify() const;
void setVerifyPeer();
+ void setVerifyNone();
void setFailNoCert();
void setSendVerify();
private:
diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp
index ca9d870677e..cb542c25a67 100644
--- a/extra/yassl/include/crypto_wrapper.hpp
+++ b/extra/yassl/include/crypto_wrapper.hpp
@@ -41,8 +41,8 @@
namespace yaSSL {
-// Digest policy should implement a get_digest, update, and get sizes for pad and
-// digest
+// 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;
@@ -380,7 +380,7 @@ public:
uint get_agreedKeyLength() const;
const byte* get_agreedKey() const;
const byte* get_publicKey() const;
- void makeAgreement(const byte*);
+ void makeAgreement(const byte*, unsigned int);
void set_sizes(int&, int&, int&) const;
void get_parms(byte*, byte*, byte*) const;
diff --git a/extra/yassl/include/openssl/err.h b/extra/yassl/include/openssl/err.h
index 054d0940509..45ac1ca2469 100644
--- a/extra/yassl/include/openssl/err.h
+++ b/extra/yassl/include/openssl/err.h
@@ -1,6 +1,6 @@
/* err.h for openssl */
-#ifndef ysSSL_err_h__
+#ifndef yaSSL_err_h__
#define yaSSL_err_h__
diff --git a/extra/yassl/include/openssl/md4.h b/extra/yassl/include/openssl/md4.h
new file mode 100644
index 00000000000..2e99f977fca
--- /dev/null
+++ b/extra/yassl/include/openssl/md4.h
@@ -0,0 +1 @@
+/* md4.h for libcurl */
diff --git a/extra/yassl/include/openssl/md5.h b/extra/yassl/include/openssl/md5.h
index a1025b92782..dfaf9799c44 100644
--- a/extra/yassl/include/openssl/md5.h
+++ b/extra/yassl/include/openssl/md5.h
@@ -1 +1,4 @@
/* md5.h for openssl */
+
+#include "ssl.h" /* in there for now */
+
diff --git a/extra/yassl/include/openssl/pem.h b/extra/yassl/include/openssl/pem.h
new file mode 100644
index 00000000000..b4c63d56a4d
--- /dev/null
+++ b/extra/yassl/include/openssl/pem.h
@@ -0,0 +1 @@
+/* pem.h for libcurl */
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
index 8a87196b7ed..23e48d2011f 100644
--- a/extra/yassl/include/openssl/ssl.h
+++ b/extra/yassl/include/openssl/ssl.h
@@ -23,12 +23,28 @@
*
*/
+
+
#ifndef yaSSL_openssl_h__
#define yaSSL_openssl_h__
#include <stdio.h> /* ERR_print fp */
+#include "opensslv.h" /* for version number */
#include "rsa.h"
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ void yaSSL_CleanUp(); /* call once at end of application use to
+ free static singleton memory holders,
+ not a leak per se, but helpful when
+ looking for them */
+
+#if defined(__cplusplus)
+} // extern
+#endif
+
#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
namespace yaSSL {
extern "C" {
@@ -49,7 +65,7 @@ extern "C" {
class X509_NAME;
#else
typedef struct SSL SSL;
- typedef struct SSL_SESION SSL_SESSION;
+ typedef struct SSL_SESSION SSL_SESSION;
typedef struct SSL_METHOD SSL_METHOD;
typedef struct SSL_CTX SSL_CTX;
typedef struct SSL_CIPHER SSL_CIPHER;
@@ -100,7 +116,6 @@ void X509_free(X509*);
typedef struct BIO BIO;
/* ASN stuff */
-typedef struct ASN1_TIME ASN1_TIME;
@@ -258,6 +273,9 @@ int SSL_pending(SSL*);
enum { /* ssl Constants */
+ SSL_WOULD_BLOCK = -8,
+ SSL_BAD_STAT = -7,
+ SSL_BAD_PATH = -6,
SSL_BAD_FILETYPE = -5,
SSL_BAD_FILE = -4,
SSL_NOT_IMPLEMENTED = -3,
@@ -341,8 +359,8 @@ 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 SSL_library_init();
-void SSLeay_add_ssl_algorithms(void);
+int SSL_library_init();
+int SSLeay_add_ssl_algorithms(void);
SSL_CIPHER* SSL_get_current_cipher(SSL*);
@@ -367,6 +385,10 @@ typedef unsigned char DES_cblock[8];
typedef const DES_cblock const_DES_cblock;
typedef DES_cblock DES_key_schedule;
+enum {
+ DES_ENCRYPT = 1,
+ DES_DECRYPT = 0
+};
const EVP_MD* EVP_md5(void);
const EVP_CIPHER* EVP_des_ede3_cbc(void);
@@ -388,6 +410,108 @@ int RAND_write_file(const char*);
int RAND_load_file(const char*, long);
+/* for libcurl */
+int RAND_status(void);
+
+int DES_set_key(const_DES_cblock*, DES_key_schedule*);
+void DES_set_odd_parity(DES_cblock*);
+void DES_ecb_encrypt(DES_cblock*, DES_cblock*, DES_key_schedule*, int);
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata);
+void SSL_SESSION_free(SSL_SESSION* session);
+
+X509* SSL_get_certificate(SSL* ssl);
+EVP_PKEY* SSL_get_privatekey(SSL* ssl);
+EVP_PKEY* X509_get_pubkey(X509* x);
+
+int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from);
+void EVP_PKEY_free(EVP_PKEY* pkey);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+void ERR_free_strings(void);
+void EVP_cleanup(void);
+
+void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx);
+
+#define GEN_IPADD 7
+#define NID_subject_alt_name 85
+#define STACK_OF(x) x
+
+
+/* defined here because libcurl dereferences */
+typedef struct ASN1_STRING {
+ int type;
+ int length;
+ unsigned char* data;
+} ASN1_STRING;
+
+
+typedef struct GENERAL_NAME {
+ int type;
+ union {
+ ASN1_STRING* ia5;
+ } d;
+} GENERAL_NAME;
+
+void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x);
+
+int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x);
+GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i);
+
+
+unsigned char* ASN1_STRING_data(ASN1_STRING* x);
+int ASN1_STRING_length(ASN1_STRING* x);
+int ASN1_STRING_type(ASN1_STRING *x);
+
+typedef ASN1_STRING X509_NAME_ENTRY;
+
+int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos);
+
+ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne);
+X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc);
+
+#define OPENSSL_malloc(x) malloc(x)
+#define OPENSSL_free(x) free(x)
+
+int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in);
+
+SSL_METHOD* SSLv23_client_method(void); /* doesn't actually roll back */
+SSL_METHOD* SSLv2_client_method(void); /* will never work, no v 2 */
+
+
+SSL_SESSION* SSL_get1_session(SSL* ssl); /* what's ref count */
+
+
+#define CRYPTO_free(x) free(x)
+#define ASN1_TIME ASN1_STRING
+
+ASN1_TIME* X509_get_notBefore(X509* x);
+ASN1_TIME* X509_get_notAfter(X509* x);
+
+
+#define ASN1_UTCTIME ASN1_STRING
+#define NID_commonName 13
+#define V_ASN1_UTF8STRING 12
+#define GEN_DNS 2
+
+
+typedef struct MD4_CTX {
+ int buffer[32]; /* big enough to hold, check size in Init */
+} MD4_CTX;
+
+void MD4_Init(MD4_CTX*);
+void MD4_Update(MD4_CTX*, const void*, unsigned long);
+void MD4_Final(unsigned char*, MD4_CTX*);
+
+
+typedef struct MD5_CTX {
+ int buffer[32]; /* big enough to hold, check size in Init */
+} MD5_CTX;
+
+void MD5_Init(MD5_CTX*);
+void MD5_Update(MD5_CTX*, const void*, unsigned long);
+void MD5_Final(unsigned char*, MD5_CTX*);
+
+
#define SSL_DEFAULT_CIPHER_LIST "" /* default all */
diff --git a/extra/yassl/include/openssl/x509.h b/extra/yassl/include/openssl/x509.h
new file mode 100644
index 00000000000..dcd847c0337
--- /dev/null
+++ b/extra/yassl/include/openssl/x509.h
@@ -0,0 +1 @@
+/* x509.h for libcurl */
diff --git a/extra/yassl/include/openssl/x509v3.h b/extra/yassl/include/openssl/x509v3.h
new file mode 100644
index 00000000000..adf94af8f48
--- /dev/null
+++ b/extra/yassl/include/openssl/x509v3.h
@@ -0,0 +1 @@
+/* x509v3.h for libcurl */
diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp
index 38a9ce3bd25..16db142b3a2 100644
--- a/extra/yassl/include/socket_wrapper.hpp
+++ b/extra/yassl/include/socket_wrapper.hpp
@@ -66,6 +66,7 @@ typedef unsigned char byte;
// Wraps Windows Sockets and BSD Sockets
class Socket {
socket_t socket_; // underlying socket descriptor
+ bool wouldBlock_; // for non-blocking data
public:
explicit Socket(socket_t s = INVALID_SOCKET);
~Socket();
@@ -75,9 +76,10 @@ public:
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;
+ uint receive(byte* buf, unsigned int len, int flags = 0);
- void wait() const;
+ bool wait();
+ bool WouldBlock() const;
void closeSocket();
void shutDown(int how = SD_SEND);
diff --git a/extra/yassl/include/yassl.hpp b/extra/yassl/include/yassl.hpp
new file mode 100644
index 00000000000..edb8e416eb6
--- /dev/null
+++ b/extra/yassl/include/yassl.hpp
@@ -0,0 +1,88 @@
+/* yassl.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 externel header defines yaSSL API
+ */
+
+
+#ifndef yaSSL_EXT_HPP
+#define yaSSL_EXT_HPP
+
+
+namespace yaSSL {
+
+
+#ifdef _WIN32
+ typedef unsigned int SOCKET_T;
+#else
+ typedef int SOCKET_T;
+#endif
+
+
+class Client {
+public:
+ Client();
+ ~Client();
+
+ // basics
+ int Connect(SOCKET_T);
+ int Write(const void*, int);
+ int Read(void*, int);
+
+ // options
+ void SetCA(const char*);
+ void SetCert(const char*);
+ void SetKey(const char*);
+private:
+ struct ClientImpl;
+ ClientImpl* pimpl_;
+
+ Client(const Client&); // hide copy
+ Client& operator=(const Client&); // and assign
+};
+
+
+class Server {
+public:
+ Server();
+ ~Server();
+
+ // basics
+ int Accept(SOCKET_T);
+ int Write(const void*, int);
+ int Read(void*, int);
+
+ // options
+ void SetCA(const char*);
+ void SetCert(const char*);
+ void SetKey(const char*);
+private:
+ struct ServerImpl;
+ ServerImpl* pimpl_;
+
+ Server(const Server&); // hide copy
+ Server& operator=(const Server&); // and assign
+};
+
+
+} // namespace yaSSL
+#endif // yaSSL_EXT_HPP
diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp
index 0b06a37a635..9c12b06e34a 100644
--- a/extra/yassl/include/yassl_error.hpp
+++ b/extra/yassl/include/yassl_error.hpp
@@ -59,6 +59,10 @@ enum YasslError {
enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib };
+enum { MAX_ERROR_SZ = 80 };
+
+void SetErrorString(YasslError, char*);
+
// Base class for all yaSSL exceptions
class Error : public mySTL::runtime_error {
diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp
index 3de58901f8e..2f240b71c03 100644
--- a/extra/yassl/include/yassl_imp.hpp
+++ b/extra/yassl/include/yassl_imp.hpp
@@ -662,7 +662,7 @@ struct Parameters {
uint8 suites_size_;
Cipher suites_[MAX_SUITE_SZ];
char cipher_name_[MAX_SUITE_NAME];
- char cipher_list_[MAX_CIPHER_LIST];
+ char cipher_list_[MAX_CIPHERS][MAX_SUITE_NAME];
Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion);
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index e75294ad073..97ae468d2f9 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -34,6 +34,7 @@
#include "cert_wrapper.hpp"
#include "log.hpp"
#include "lock.hpp"
+#include "openssl/ssl.h" // ASN1_STRING and DH
namespace yaSSL {
@@ -77,8 +78,6 @@ enum ServerState {
// combines all states
class States {
- enum {MAX_ERROR_SZ = 80 };
-
RecordLayerState recordLayer_;
HandShakeState handshakeLayer_;
ClientState clientState_;
@@ -128,32 +127,70 @@ private:
};
+// hold add crypt references provided to callers
+class CryptProvider {
+ mySTL::list<Digest*> digestList_;
+ mySTL::list<BulkCipher*> cipherList_;
+ CryptProvider() {} // only GetCryptProvider creates
+public:
+ ~CryptProvider();
+
+ Digest* NewMd5();
+ BulkCipher* NewDesEde();
+
+ friend CryptProvider& GetCryptProvider();
+private:
+ CryptProvider(const CryptProvider&); // hide copy
+ CryptProvider& operator=(const CryptProvider&); // and assign
+};
+
+CryptProvider& GetCryptProvider();
+
#undef X509_NAME // wincrypt.h clash
// openSSL X509 names
class X509_NAME {
char* name_;
+ size_t sz_;
+ ASN1_STRING entry_;
public:
X509_NAME(const char*, size_t sz);
~X509_NAME();
char* GetName();
+ ASN1_STRING* GetEntry(int i);
private:
X509_NAME(const X509_NAME&); // hide copy
X509_NAME& operator=(const X509_NAME&); // and assign
};
+class StringHolder {
+ ASN1_STRING asnString_;
+public:
+ StringHolder(const char* str, int sz);
+ ~StringHolder();
+
+ ASN1_STRING* GetString();
+};
+
+
// openSSL X509
class X509 {
X509_NAME issuer_;
X509_NAME subject_;
+ StringHolder beforeDate_; // not valid before
+ StringHolder afterDate_; // not valid after
public:
- X509(const char* i, size_t, const char* s, size_t);
+ X509(const char* i, size_t, const char* s, size_t,
+ const char* b, int, const char* a, int);
~X509() {}
X509_NAME* GetIssuer();
X509_NAME* GetSubject();
+
+ ASN1_STRING* GetBefore();
+ ASN1_STRING* GetAfter();
private:
X509(const X509&); // hide copy
X509& operator=(const X509&); // and assign
@@ -227,7 +264,8 @@ sslFactory& GetSSL_Factory();
class SSL_METHOD {
ProtocolVersion version_;
ConnectionEnd side_;
- bool verifyPeer_;
+ bool verifyPeer_; // request or send certificate
+ bool verifyNone_; // whether to verify certificate
bool failNoCert_;
public:
explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv);
@@ -236,9 +274,11 @@ public:
ConnectionEnd getSide() const;
void setVerifyPeer();
+ void setVerifyNone();
void setFailNoCert();
bool verifyPeer() const;
+ bool verifyNone() const;
bool failNoCert() const;
private:
SSL_METHOD(const SSL_METHOD&); // hide copy
@@ -331,6 +371,7 @@ public:
const Stats& GetStats() const;
void setVerifyPeer();
+ void setVerifyNone();
void setFailNoCert();
bool SetCipherList(const char*);
bool SetDH(const DH&);
diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp
index 66cc6aa3c68..76c807cd05f 100644
--- a/extra/yassl/include/yassl_types.hpp
+++ b/extra/yassl/include/yassl_types.hpp
@@ -35,36 +35,34 @@
namespace yaSSL {
-// Delete static singleton memory holders
-void CleanUp();
+#ifdef YASSL_PURE_C
+ // library allocation
+ struct new_t {}; // yaSSL New type
+ extern new_t ys; // pass in parameter
-// library allocation
-struct new_t {}; // yaSSL New type
-extern new_t ys; // pass in parameter
+ } // namespace yaSSL
-} // namespace yaSSL
+ void* operator new (size_t, yaSSL::new_t);
+ void* operator new[](size_t, yaSSL::new_t);
-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);
-void operator delete (void*, yaSSL::new_t);
-void operator delete[](void*, yaSSL::new_t);
-
-namespace yaSSL {
+ namespace yaSSL {
-template<typename T>
-void ysDelete(T* ptr)
-{
+ template<typename T>
+ void ysDelete(T* ptr)
+ {
if (ptr) ptr->~T();
::operator delete(ptr, yaSSL::ys);
-}
+ }
-template<typename T>
-void ysArrayDelete(T* ptr)
-{
+ 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
@@ -72,15 +70,40 @@ void ysArrayDelete(T* ptr)
(void)sizeof(builtin);
::operator delete[](ptr, yaSSL::ys);
-}
+ }
+ #define NEW_YS new (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:
+ // 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); }
-};
+ };
+
+
+#else // YASSL_PURE_C
+
+
+ template<typename T>
+ void ysDelete(T* ptr)
+ {
+ delete ptr;
+ }
+
+ template<typename T>
+ void ysArrayDelete(T* ptr)
+ {
+ delete[] ptr;
+ }
+
+ #define NEW_YS new
+
+ class virtual_base {};
+
+
+
+#endif // YASSL_PURE_C
typedef unsigned char uint8;
@@ -110,7 +133,7 @@ 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 MAX_CIPHERS = 32; // max supported ciphers for cipher list
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
diff --git a/extra/yassl/lib/dummy b/extra/yassl/lib/dummy
new file mode 100644
index 00000000000..85c1efd587f
--- /dev/null
+++ b/extra/yassl/lib/dummy
@@ -0,0 +1 @@
+// this is a dummy file
diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp
index de825c23fec..df79025197a 100644
--- a/extra/yassl/mySTL/helpers.hpp
+++ b/extra/yassl/mySTL/helpers.hpp
@@ -28,6 +28,9 @@
#define mySTL_HELPERS_HPP
#include <stdlib.h>
+#ifdef _MSC_VER
+ #include <new>
+#endif
/*
Workaround for the lack of operator new(size_t, void*)
@@ -41,8 +44,12 @@
return static_cast<void*>(d);
}
- typedef Dummy* yassl_pointer;
+ // for compilers that want matching delete
+ inline void operator delete(void* ptr, Dummy* d)
+ {
+ }
+ typedef Dummy* yassl_pointer;
namespace mySTL {
diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/mySTL/stdexcept.hpp
index 33ea43bf0e0..b50dd35edae 100644
--- a/extra/yassl/mySTL/stdexcept.hpp
+++ b/extra/yassl/mySTL/stdexcept.hpp
@@ -46,8 +46,10 @@ public:
// for compiler generated call, never used
static void operator delete(void*) { assert(0); }
private:
+#if defined(__hpux)
// don't allow dynamic creation of exceptions
static void* operator new(size_t);
+#endif
};
diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp
index 56d355bea80..3bc6dced887 100644
--- a/extra/yassl/src/buffer.cpp
+++ b/extra/yassl/src/buffer.cpp
@@ -24,6 +24,7 @@
* with SSL types and sockets
*/
+
#include <string.h> // memcpy
#include "runtime.hpp"
#include "buffer.hpp"
@@ -63,13 +64,13 @@ input_buffer::input_buffer()
input_buffer::input_buffer(uint s)
- : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + 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)
+ : size_(0), current_(0), buffer_(NEW_YS byte[s]), end_(buffer_ + s)
{
assign(t, len);
}
@@ -85,7 +86,7 @@ input_buffer::~input_buffer()
void input_buffer::allocate(uint s)
{
assert(!buffer_); // find realloc error
- buffer_ = new (ys) byte[s];
+ buffer_ = NEW_YS byte[s];
end_ = buffer_ + s;
}
@@ -97,7 +98,7 @@ byte* input_buffer::get_buffer() const
}
-// after a raw write user can set new (ys) size
+// 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)
{
@@ -199,13 +200,13 @@ output_buffer::output_buffer()
// with allocate
output_buffer::output_buffer(uint s)
- : current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + 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)
+ : current_(0), buffer_(NEW_YS byte[s]), end_(buffer_+ s)
{
write(t, len);
}
@@ -240,7 +241,7 @@ void output_buffer::set_current(uint c)
void output_buffer::allocate(uint s)
{
assert(!buffer_); // find realloc error
- buffer_ = new (ys) byte[s]; end_ = buffer_ + s;
+ buffer_ = NEW_YS byte[s]; end_ = buffer_ + s;
}
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
index a775c366a92..ae609b510ba 100644
--- a/extra/yassl/src/cert_wrapper.cpp
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -39,7 +39,7 @@
namespace yaSSL {
-x509::x509(uint sz) : length_(sz), buffer_(new (ys) opaque[sz])
+x509::x509(uint sz) : length_(sz), buffer_(NEW_YS opaque[sz])
{
}
@@ -51,7 +51,7 @@ x509::~x509()
x509::x509(const x509& that) : length_(that.length_),
- buffer_(new (ys) opaque[length_])
+ buffer_(NEW_YS opaque[length_])
{
memcpy(buffer_, that.buffer_, length_);
}
@@ -92,7 +92,8 @@ opaque* x509::use_buffer()
//CertManager
CertManager::CertManager()
- : peerX509_(0), verifyPeer_(false), failNoCert_(false), sendVerify_(false)
+ : peerX509_(0), verifyPeer_(false), verifyNone_(false), failNoCert_(false),
+ sendVerify_(false)
{}
@@ -114,6 +115,12 @@ bool CertManager::verifyPeer() const
}
+bool CertManager::verifyNone() const
+{
+ return verifyNone_;
+}
+
+
bool CertManager::failNoCert() const
{
return failNoCert_;
@@ -132,6 +139,12 @@ void CertManager::setVerifyPeer()
}
+void CertManager::setVerifyNone()
+{
+ verifyNone_ = true;
+}
+
+
void CertManager::setFailNoCert()
{
failNoCert_ = true;
@@ -153,7 +166,7 @@ void CertManager::AddPeerCert(x509* x)
void CertManager::CopySelfCert(const x509* x)
{
if (x)
- list_.push_back(new (ys) x509(*x));
+ list_.push_back(NEW_YS x509(*x));
}
@@ -161,11 +174,12 @@ void CertManager::CopySelfCert(const x509* x)
int CertManager::CopyCaCert(const x509* x)
{
TaoCrypt::Source source(x->get_buffer(), x->get_length());
- TaoCrypt::CertDecoder cert(source, true, &signers_);
+ TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_,
+ TaoCrypt::CertDecoder::CA);
if (!cert.GetError().What()) {
const TaoCrypt::PublicKey& key = cert.GetPublicKey();
- signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(),
cert.GetCommonName(), cert.GetHash()));
}
return cert.GetError().What();
@@ -228,13 +242,13 @@ int CertManager::Validate()
while ( count > 1 ) {
TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
- TaoCrypt::CertDecoder cert(source, true, &signers_);
+ TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_);
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(),
+ signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(),
cert.GetCommonName(), cert.GetHash()));
--last;
--count;
@@ -243,7 +257,7 @@ int CertManager::Validate()
if (count) {
// peer's is at the front
TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
- TaoCrypt::CertDecoder cert(source, true, &signers_);
+ TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_);
if (int err = cert.GetError().What())
return err;
@@ -257,10 +271,13 @@ int CertManager::Validate()
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);
+ int iSz = strlen(cert.GetIssuer()) + 1;
+ int sSz = strlen(cert.GetCommonName()) + 1;
+ int bSz = strlen(cert.GetBeforeDate()) + 1;
+ int aSz = strlen(cert.GetAfterDate()) + 1;
+ peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
+ sSz, cert.GetBeforeDate(), bSz,
+ cert.GetAfterDate(), aSz);
}
return 0;
}
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
index 80cadd3d722..8859fbdd70f 100644
--- a/extra/yassl/src/crypto_wrapper.cpp
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -58,13 +58,13 @@ struct MD5::MD5Impl {
};
-MD5::MD5() : pimpl_(new (ys) MD5Impl) {}
+MD5::MD5() : pimpl_(NEW_YS MD5Impl) {}
MD5::~MD5() { ysDelete(pimpl_); }
-MD5::MD5(const MD5& that) : Digest(), pimpl_(new (ys)
+MD5::MD5(const MD5& that) : Digest(), pimpl_(NEW_YS
MD5Impl(that.pimpl_->md5_)) {}
@@ -116,13 +116,13 @@ struct SHA::SHAImpl {
};
-SHA::SHA() : pimpl_(new (ys) SHAImpl) {}
+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(const SHA& that) : Digest(), pimpl_(NEW_YS SHAImpl(that.pimpl_->sha_)) {}
SHA& SHA::operator=(const SHA& that)
{
@@ -173,13 +173,13 @@ struct RMD::RMDImpl {
};
-RMD::RMD() : pimpl_(new (ys) RMDImpl) {}
+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(const RMD& that) : Digest(), pimpl_(NEW_YS RMDImpl(that.pimpl_->rmd_)) {}
RMD& RMD::operator=(const RMD& that)
{
@@ -230,7 +230,7 @@ struct HMAC_MD5::HMAC_MD5Impl {
HMAC_MD5::HMAC_MD5(const byte* secret, unsigned int len)
- : pimpl_(new (ys) HMAC_MD5Impl)
+ : pimpl_(NEW_YS HMAC_MD5Impl)
{
pimpl_->mac_.SetKey(secret, len);
}
@@ -280,7 +280,7 @@ struct HMAC_SHA::HMAC_SHAImpl {
HMAC_SHA::HMAC_SHA(const byte* secret, unsigned int len)
- : pimpl_(new (ys) HMAC_SHAImpl)
+ : pimpl_(NEW_YS HMAC_SHAImpl)
{
pimpl_->mac_.SetKey(secret, len);
}
@@ -331,7 +331,7 @@ struct HMAC_RMD::HMAC_RMDImpl {
HMAC_RMD::HMAC_RMD(const byte* secret, unsigned int len)
- : pimpl_(new (ys) HMAC_RMDImpl)
+ : pimpl_(NEW_YS HMAC_RMDImpl)
{
pimpl_->mac_.SetKey(secret, len);
}
@@ -379,7 +379,7 @@ struct DES::DESImpl {
};
-DES::DES() : pimpl_(new (ys) DESImpl) {}
+DES::DES() : pimpl_(NEW_YS DESImpl) {}
DES::~DES() { ysDelete(pimpl_); }
@@ -415,7 +415,7 @@ struct DES_EDE::DES_EDEImpl {
};
-DES_EDE::DES_EDE() : pimpl_(new (ys) DES_EDEImpl) {}
+DES_EDE::DES_EDE() : pimpl_(NEW_YS DES_EDEImpl) {}
DES_EDE::~DES_EDE() { ysDelete(pimpl_); }
@@ -453,7 +453,7 @@ struct RC4::RC4Impl {
};
-RC4::RC4() : pimpl_(new (ys) RC4Impl) {}
+RC4::RC4() : pimpl_(NEW_YS RC4Impl) {}
RC4::~RC4() { ysDelete(pimpl_); }
@@ -495,7 +495,7 @@ struct AES::AESImpl {
};
-AES::AES(unsigned int ks) : pimpl_(new (ys) AESImpl(ks)) {}
+AES::AES(unsigned int ks) : pimpl_(NEW_YS AESImpl(ks)) {}
AES::~AES() { ysDelete(pimpl_); }
@@ -536,7 +536,7 @@ struct RandomPool::RandomImpl {
TaoCrypt::RandomNumberGenerator RNG_;
};
-RandomPool::RandomPool() : pimpl_(new (ys) RandomImpl) {}
+RandomPool::RandomPool() : pimpl_(NEW_YS RandomImpl) {}
RandomPool::~RandomPool() { ysDelete(pimpl_); }
@@ -580,7 +580,7 @@ void DSS::DSSImpl::SetPrivate(const byte* key, unsigned int sz)
// Set public or private key
DSS::DSS(const byte* key, unsigned int sz, bool publicKey)
- : pimpl_(new (ys) DSSImpl)
+ : pimpl_(NEW_YS DSSImpl)
{
if (publicKey)
pimpl_->SetPublic(key, sz);
@@ -651,7 +651,7 @@ void RSA::RSAImpl::SetPrivate(const byte* key, unsigned int sz)
// Set public or private key
RSA::RSA(const byte* key, unsigned int sz, bool publicKey)
- : pimpl_(new (ys) RSAImpl)
+ : pimpl_(NEW_YS RSAImpl)
{
if (publicKey)
pimpl_->SetPublic(key, sz);
@@ -723,13 +723,13 @@ struct Integer::IntegerImpl {
explicit IntegerImpl(const TaoCrypt::Integer& i) : int_(i) {}
};
-Integer::Integer() : pimpl_(new (ys) IntegerImpl) {}
+Integer::Integer() : pimpl_(NEW_YS IntegerImpl) {}
Integer::~Integer() { ysDelete(pimpl_); }
-Integer::Integer(const Integer& other) : pimpl_(new (ys)
+Integer::Integer(const Integer& other) : pimpl_(NEW_YS
IntegerImpl(other.pimpl_->int_))
{}
@@ -773,9 +773,9 @@ struct DiffieHellman::DHImpl {
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];
+ publicKey_ = NEW_YS byte[pubSz];
+ privateKey_ = NEW_YS byte[privSz];
+ agreedKey_ = NEW_YS byte[agrSz];
}
};
@@ -784,7 +784,7 @@ struct DiffieHellman::DHImpl {
/*
// server Side DH, server's view
DiffieHellman::DiffieHellman(const char* file, const RandomPool& random)
- : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+ : pimpl_(NEW_YS DHImpl(random.pimpl_->RNG_))
{
using namespace TaoCrypt;
Source source;
@@ -808,12 +808,12 @@ DiffieHellman::DiffieHellman(const char* file, const RandomPool& random)
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_))
+ : 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];
+ pimpl_->publicKey_ = NEW_YS opaque[pubSz];
memcpy(pimpl_->publicKey_, pub, pubSz);
}
@@ -821,7 +821,7 @@ DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g,
// Server Side DH, server's view
DiffieHellman::DiffieHellman(const Integer& p, const Integer& g,
const RandomPool& random)
-: pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+: pimpl_(NEW_YS DHImpl(random.pimpl_->RNG_))
{
using TaoCrypt::Integer;
@@ -839,7 +839,7 @@ 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_(NEW_YS DHImpl(*that.pimpl_))
{
pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
pimpl_->publicKey_);
@@ -855,9 +855,9 @@ DiffieHellman& DiffieHellman::operator=(const DiffieHellman& that)
}
-void DiffieHellman::makeAgreement(const byte* other)
+void DiffieHellman::makeAgreement(const byte* other, unsigned int otherSz)
{
- pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other);
+ pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other, otherSz);
}
@@ -960,7 +960,7 @@ x509* PemToDer(const char* fname, CertType type)
Base64Decoder b64Dec(der);
uint sz = der.size();
- mySTL::auto_ptr<x509> x(new (ys) x509(sz), ysDelete);
+ mySTL::auto_ptr<x509> x(NEW_YS x509(sz), ysDelete);
memcpy(x->use_buffer(), der.get_buffer(), sz);
fclose(file);
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
index 16c9bde2003..2b099af930c 100644
--- a/extra/yassl/src/handshake.cpp
+++ b/extra/yassl/src/handshake.cpp
@@ -24,6 +24,8 @@
* the various handshake messages.
*/
+
+
#include "runtime.hpp"
#include "handshake.hpp"
#include "yassl_int.hpp"
@@ -362,9 +364,9 @@ void p_hash(output_buffer& result, const output_buffer& secret,
if (lastLen) times += 1;
if (hash == md5)
- hmac.reset(new (ys) HMAC_MD5(secret.get_buffer(), secret.get_size()));
+ 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()));
+ 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;
@@ -582,11 +584,11 @@ void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
if (algo == sha)
- hmac.reset(new (ys) HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
+ 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));
+ 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.reset(NEW_YS HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
hmac->update(seq, SEQ_SZ); // seq_num
inner[0] = content; // type
@@ -603,7 +605,7 @@ void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
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;
+ uint half = (secLen + 1) / 2;
output_buffer md5_half(half);
output_buffer sha_half(half);
@@ -648,18 +650,19 @@ void build_certHashes(SSL& ssl, Hashes& hashes)
}
+
// 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) {
- // Nothing to receive after blocking wait => error
+ // wait for input if blocking
+ if (!ssl.useSocket().wait()) {
ssl.SetError(receive_error);
- buffered.reset(0);
- return buffered;
+ buffered.reset(0);
+ return buffered;
}
+ 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;
@@ -670,7 +673,7 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
}
// add new data
- uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
+ uint read = ssl.useSocket().receive(buffer.get_buffer() + buffSz, ready);
buffer.add_size(read);
uint offset = 0;
const MessageFactory& mf = ssl.getFactory().getMessage();
@@ -690,7 +693,7 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
// 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() +
+ buffered.reset(NEW_YS input_buffer(sz, buffer.get_buffer() +
buffer.get_current() - RECORD_HEADER, sz));
break;
}
@@ -730,6 +733,7 @@ void processReply(SSL& ssl)
buffered = tmp;
else
break;
+ if (ssl.GetError()) return;
}
}
@@ -767,7 +771,7 @@ void sendClientKeyExchange(SSL& ssl, BufferOutput buffer)
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ 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());
@@ -788,7 +792,7 @@ void sendServerKeyExchange(SSL& ssl, BufferOutput buffer)
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ 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());
@@ -813,7 +817,7 @@ void sendChangeCipher(SSL& ssl, BufferOutput buffer)
ChangeCipherSpec ccs;
RecordLayerHeader rlHeader;
buildHeader(ssl, rlHeader, ccs);
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildOutput(*out.get(), rlHeader, ccs);
if (buffer == buffered)
@@ -830,7 +834,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
Finished fin;
buildFinished(ssl, fin, side == client_end ? client : server);
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
cipherFinished(ssl, fin, *out.get()); // hashes handshake
if (ssl.getSecurity().get_resuming()) {
@@ -854,6 +858,9 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
// send data
int sendData(SSL& ssl, const void* buffer, int sz)
{
+ if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
+ ssl.SetError(no_error);
+
ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0;
int sent = 0;
@@ -889,6 +896,9 @@ int sendAlert(SSL& ssl, const Alert& alert)
// process input data
int receiveData(SSL& ssl, Data& data)
{
+ if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
+ ssl.SetError(no_error);
+
ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0;
@@ -898,6 +908,11 @@ int receiveData(SSL& ssl, Data& data)
ssl.useLog().ShowData(data.get_length());
if (ssl.GetError()) return 0;
+
+ if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) {
+ ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
+ return SSL_WOULD_BLOCK;
+ }
return data.get_length();
}
@@ -914,7 +929,7 @@ void sendServerHello(SSL& ssl, BufferOutput buffer)
ServerHello sh(ssl.getSecurity().get_connection().version_);
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildServerHello(ssl, sh);
ssl.set_random(sh.get_random(), server_end);
@@ -937,7 +952,7 @@ void sendServerHelloDone(SSL& ssl, BufferOutput buffer)
ServerHelloDone shd;
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildHeaders(ssl, hsHeader, rlHeader, shd);
buildOutput(*out.get(), rlHeader, hsHeader, shd);
@@ -958,7 +973,7 @@ void sendCertificate(SSL& ssl, BufferOutput buffer)
Certificate cert(ssl.getCrypto().get_certManager().get_cert());
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildHeaders(ssl, hsHeader, rlHeader, cert);
buildOutput(*out.get(), rlHeader, hsHeader, cert);
@@ -980,7 +995,7 @@ void sendCertificateRequest(SSL& ssl, BufferOutput buffer)
request.Build();
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildHeaders(ssl, hsHeader, rlHeader, request);
buildOutput(*out.get(), rlHeader, hsHeader, request);
@@ -1002,7 +1017,7 @@ void sendCertificateVerify(SSL& ssl, BufferOutput buffer)
verify.Build(ssl);
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
- mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer, ysDelete);
buildHeaders(ssl, hsHeader, rlHeader, verify);
buildOutput(*out.get(), rlHeader, hsHeader, verify);
diff --git a/extra/yassl/src/make.bat b/extra/yassl/src/make.bat
new file mode 100644
index 00000000000..148427a6f41
--- /dev/null
+++ b/extra/yassl/src/make.bat
@@ -0,0 +1,27 @@
+REM quick and dirty build file for testing different MSDEVs
+setlocal
+
+set myFLAGS= /I../include /I../mySTL /I../taocrypt/include /W3 /c /ZI
+
+cl %myFLAGS% buffer.cpp
+cl %myFLAGS% cert_wrapper.cpp
+cl %myFLAGS% crypto_wrapper.cpp
+cl %myFLAGS% handshake.cpp
+
+cl %myFLAGS% lock.cpp
+cl %myFLAGS% log.cpp
+cl %myFLAGS% socket_wrapper.cpp
+cl %myFLAGS% ssl.cpp
+
+cl %myFLAGS% template_instnt.cpp
+cl %myFLAGS% timer.cpp
+cl %myFLAGS% yassl.cpp
+cl %myFLAGS% yassl_error.cpp
+
+cl %myFLAGS% yassl_imp.cpp
+cl %myFLAGS% yassl_int.cpp
+
+link.exe -lib /out:yassl.lib buffer.obj cert_wrapper.obj crypto_wrapper.obj handshake.obj lock.obj log.obj socket_wrapper.obj ssl.obj template_instnt.obj timer.obj yassl.obj yassl_error.obj yassl_imp.obj yassl_int.obj
+
+
+
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
index 285e0dee2e5..803f4b01249 100644
--- a/extra/yassl/src/socket_wrapper.cpp
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -46,9 +46,11 @@
#ifdef _WIN32
const int SOCKET_EINVAL = WSAEINVAL;
const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
+ const int SOCKET_EAGAIN = WSAEWOULDBLOCK;
#else
const int SOCKET_EINVAL = EINVAL;
const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
+ const int SOCKET_EAGAIN = EAGAIN;
#endif // _WIN32
@@ -56,7 +58,7 @@ namespace yaSSL {
Socket::Socket(socket_t s)
- : socket_(s)
+ : socket_(s), wouldBlock_(false)
{}
@@ -98,10 +100,10 @@ uint Socket::get_ready() const
ioctlsocket(socket_, FIONREAD, &ready);
#else
/*
- 64-bit Solaris requires the variable passed to
- FIONREAD be a 32-bit value.
+ 64-bit Solaris requires the variable passed to
+ FIONREAD be a 32-bit value.
*/
- int ready = 0;
+ unsigned int ready = 0;
ioctl(socket_, FIONREAD, &ready);
#endif
@@ -121,23 +123,33 @@ uint Socket::send(const byte* buf, unsigned int sz, int flags) const
}
-uint Socket::receive(byte* buf, unsigned int sz, int flags) const
+uint Socket::receive(byte* buf, unsigned int sz, int flags)
{
assert(socket_ != INVALID_SOCKET);
+ wouldBlock_ = false;
+
int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
- if (recvd == -1)
+ // idea to seperate error from would block by arnetheduck@gmail.com
+ if (recvd == -1) {
+ if (get_lastError() == SOCKET_EWOULDBLOCK ||
+ get_lastError() == SOCKET_EAGAIN) {
+ wouldBlock_ = true;
return 0;
+ }
+ }
+ else if (recvd == 0)
+ return static_cast<uint>(-1);
return recvd;
}
-// wait if blocking for input, or error
-void Socket::wait() const
+// wait if blocking for input, return false for error
+bool Socket::wait()
{
byte b;
- receive(&b, 1, MSG_PEEK);
+ return receive(&b, 1, MSG_PEEK) != static_cast<uint>(-1);
}
@@ -158,6 +170,12 @@ int Socket::get_lastError()
}
+bool Socket::WouldBlock() const
+{
+ return wouldBlock_;
+}
+
+
void Socket::set_lastError(int errorCode)
{
#ifdef _WIN32
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index 94e783167b3..747305730df 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -1,4 +1,4 @@
-/* ssl.cpp
+ /* ssl.cpp
*
* Copyright (C) 2003 Sawtooth Consulting Ltd.
*
@@ -36,14 +36,71 @@
#include "openssl/ssl.h"
#include "handshake.hpp"
#include "yassl_int.hpp"
+#include "md5.hpp" // for TaoCrypt MD5 size assert
+#include "md4.hpp" // for TaoCrypt MD4 size assert
#include <stdio.h>
+#ifdef _WIN32
+ #include <windows.h> // FindFirstFile etc..
+#else
+ #include <sys/types.h> // file helper
+ #include <sys/stat.h> // stat
+ #include <dirent.h> // opendir
+#endif
+
namespace yaSSL {
using mySTL::min;
+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;
+}
+
+
+extern "C" {
+
+
SSL_METHOD* SSLv3_method()
{
return SSLv3_client_method();
@@ -52,25 +109,25 @@ SSL_METHOD* SSLv3_method()
SSL_METHOD* SSLv3_server_method()
{
- return new (ys) SSL_METHOD(server_end, ProtocolVersion(3,0));
+ 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));
+ 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));
+ 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));
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1));
}
@@ -83,7 +140,7 @@ SSL_METHOD* SSLv23_server_method()
SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
{
- return new (ys) SSL_CTX(method);
+ return NEW_YS SSL_CTX(method);
}
@@ -95,7 +152,7 @@ void SSL_CTX_free(SSL_CTX* ctx)
SSL* SSL_new(SSL_CTX* ctx)
{
- return new (ys) SSL(ctx);
+ return NEW_YS SSL(ctx);
}
@@ -115,7 +172,12 @@ int SSL_set_fd(SSL* ssl, int fd)
int SSL_connect(SSL* ssl)
{
sendClientHello(*ssl);
+ ClientState neededState = ssl->getSecurity().get_resuming() ?
+ serverFinishedComplete : serverHelloDoneComplete;
+ while (ssl->getStates().getClient() < neededState) {
+ if (ssl->GetError()) break;
processReply(*ssl);
+ }
if(ssl->getCrypto().get_certManager().sendVerify())
sendCertificate(*ssl);
@@ -130,7 +192,10 @@ int SSL_connect(SSL* ssl)
sendFinished(*ssl, client_end);
ssl->flushBuffer();
if (!ssl->getSecurity().get_resuming())
+ while (ssl->getStates().getClient() < serverFinishedComplete) {
+ if (ssl->GetError()) break;
processReply(*ssl);
+ }
ssl->verifyState(serverFinishedComplete);
ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
@@ -171,9 +236,7 @@ int SSL_accept(SSL* ssl)
sendServerHelloDone(*ssl);
ssl->flushBuffer();
- // Java Client sends fragmented response
- while (ssl->getStates().getServer() <
- clientFinishedComplete) {
+ while (ssl->getStates().getServer() < clientFinishedComplete) {
if (ssl->GetError()) break;
processReply(*ssl);
}
@@ -182,10 +245,7 @@ int SSL_accept(SSL* ssl)
sendFinished(*ssl, server_end);
ssl->flushBuffer();
if (ssl->getSecurity().get_resuming()) {
-
- // Java Client sends fragmented response
- while (ssl->getStates().getServer() <
- clientFinishedComplete) {
+ while (ssl->getStates().getServer() < clientFinishedComplete) {
if (ssl->GetError()) break;
processReply(*ssl);
}
@@ -281,9 +341,15 @@ char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
}
-const char* SSL_get_cipher_list(SSL* ssl, int /*priority */)
+const char* SSL_get_cipher_list(SSL* ssl, int priority)
{
- return ssl->getSecurity().get_parms().cipher_list_;
+ if (priority < 0 || priority >= MAX_CIPHERS)
+ return 0;
+
+ if (ssl->getSecurity().get_parms().cipher_list_[priority][0])
+ return ssl->getSecurity().get_parms().cipher_list_[priority];
+
+ return 0;
}
@@ -431,50 +497,6 @@ long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
}
-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);
@@ -492,16 +514,74 @@ void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback /*vc*/)
if (mode & SSL_VERIFY_PEER)
ctx->setVerifyPeer();
+ if (mode == SSL_VERIFY_NONE)
+ ctx->setVerifyNone();
+
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*/)
+ const char* path)
{
- // just files for now
- return read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+ int ret = SSL_SUCCESS;
+ const int HALF_PATH = 128;
+
+ if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+
+ if (ret == SSL_SUCCESS && path) {
+ // call read_file for each reqular file in path
+#ifdef _WIN32
+
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+
+ char name[MAX_PATH + 1]; // directory specification
+ strncpy(name, path, MAX_PATH - 3);
+ strncat(name, "\\*", 3);
+
+ hFind = FindFirstFile(name, &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE) return SSL_BAD_PATH;
+
+ do {
+ if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
+ strncpy(name, path, MAX_PATH - 2 - HALF_PATH);
+ strncat(name, "\\", 2);
+ strncat(name, FindFileData.cFileName, HALF_PATH);
+ ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
+ }
+ } while (ret == SSL_SUCCESS && FindNextFile(hFind, &FindFileData));
+
+ FindClose(hFind);
+
+#else // _WIN32
+
+ const int MAX_PATH = 260;
+
+ DIR* dir = opendir(path);
+ if (!dir) return SSL_BAD_PATH;
+
+ struct dirent* entry;
+ struct stat buf;
+ char name[MAX_PATH + 1];
+
+ while (ret == SSL_SUCCESS && (entry = readdir(dir))) {
+ strncpy(name, path, MAX_PATH - 1 - HALF_PATH);
+ strncat(name, "/", 1);
+ strncat(name, entry->d_name, HALF_PATH);
+ if (stat(name, &buf) < 0) return SSL_BAD_STAT;
+
+ if (S_ISREG(buf.st_mode))
+ ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
+ }
+
+ closedir(dir);
+
+#endif
+ }
+
+ return ret;
}
@@ -648,13 +728,15 @@ void OpenSSL_add_all_algorithms() // compatibility only
{}
-void SSL_library_init() // compatibility only
-{}
+int SSL_library_init() // compatiblity only
+{
+ return 1;
+}
DH* DH_new(void)
{
- DH* dh = new (ys) DH;
+ DH* dh = NEW_YS DH;
if (dh)
dh->p = dh->g = 0;
return dh;
@@ -679,7 +761,7 @@ BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
if (!retVal) {
created = true;
- bn.reset(new (ys) BIGNUM);
+ bn.reset(NEW_YS BIGNUM);
retVal = bn.get();
}
@@ -706,12 +788,14 @@ void ERR_print_errors_fp(FILE* /*fp*/)
}
-char* ERR_error_string(unsigned long /*err*/, char* buffer)
+char* ERR_error_string(unsigned long errNumber, char* buffer)
{
- // TODO:
- static char* msg = "Not Implemented";
- if (buffer)
- return strncpy(buffer, msg, strlen(msg));
+ static char* msg = "Please supply a buffer for error string";
+
+ if (buffer) {
+ SetErrorString(YasslError(errNumber), buffer);
+ return buffer;
+ }
return msg;
}
@@ -727,15 +811,13 @@ const char* X509_verify_cert_error_string(long /* error */)
const EVP_MD* EVP_md5(void)
{
- // TODO: FIX add to some list for destruction
- return new (ys) MD5;
+ return GetCryptProvider().NewMd5();
}
const EVP_CIPHER* EVP_des_ede3_cbc(void)
{
- // TODO: FIX add to some list for destruction
- return new (ys) DES_EDE;
+ return GetCryptProvider().NewDesEde();
}
@@ -820,6 +902,284 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
}
+// functions for libcurl
+int RAND_status()
+{
+ return 1; /* TaoCrypt provides enough seed */
+}
+
+
+int DES_set_key(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+ return 1;
+}
+
+
+void DES_set_odd_parity(DES_cblock* key)
+{
+ // not needed now for TaoCrypt
+}
+
+
+void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output,
+ DES_key_schedule* key, int enc)
+{
+ DES des;
+
+ if (enc) {
+ des.set_encryptKey(*key, 0);
+ des.encrypt(*output, *input, DES_BLOCK);
+ }
+ else {
+ des.set_decryptKey(*key, 0);
+ des.decrypt(*output, *input, DES_BLOCK);
+ }
+}
+
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata)
+{
+ // yaSSL doesn't support yet, unencrypt your PEM file with userdata
+ // before handing off to yaSSL
+}
+
+
+X509* SSL_get_certificate(SSL* ssl)
+{
+ // only used to pass to get_privatekey which isn't used
+ return 0;
+}
+
+
+EVP_PKEY* SSL_get_privatekey(SSL* ssl)
+{
+ // only called, not used
+ return 0;
+}
+
+
+void SSL_SESSION_free(SSL_SESSION* session)
+{
+ // managed by singleton
+}
+
+
+
+EVP_PKEY* X509_get_pubkey(X509* x)
+{
+ // called, not used though
+ return 0;
+}
+
+
+int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from)
+{
+ // called, not used though
+ return 0;
+}
+
+
+void EVP_PKEY_free(EVP_PKEY* pkey)
+{
+ // never allocated from above
+}
+
+
+void ERR_error_string_n(unsigned long e, char *buf, size_t len)
+{
+ if (len) ERR_error_string(e, buf);
+}
+
+
+void ERR_free_strings(void)
+{
+ // handled internally
+}
+
+
+void EVP_cleanup(void)
+{
+ // nothing to do yet
+}
+
+
+ASN1_TIME* X509_get_notBefore(X509* x)
+{
+ if (x) return x->GetBefore();
+ return 0;
+}
+
+
+ASN1_TIME* X509_get_notAfter(X509* x)
+{
+ if (x) return x->GetAfter();
+ return 0;
+}
+
+
+SSL_METHOD* SSLv23_client_method(void) /* doesn't actually roll back */
+{
+ return SSLv3_client_method();
+}
+
+
+SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */
+{
+ return 0;
+}
+
+
+SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */
+{
+ return SSL_get_session(ssl);
+}
+
+
+void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x)
+{
+ // no extension names supported yet
+}
+
+
+int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x)
+{
+ // no extension names supported yet
+ return 0;
+}
+
+
+GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i)
+{
+ // no extension names supported yet
+ return 0;
+}
+
+
+unsigned char* ASN1_STRING_data(ASN1_STRING* x)
+{
+ if (x) return x->data;
+ return 0;
+}
+
+
+int ASN1_STRING_length(ASN1_STRING* x)
+{
+ if (x) return x->length;
+ return 0;
+}
+
+
+int ASN1_STRING_type(ASN1_STRING *x)
+{
+ if (x) return x->type;
+ return 0;
+}
+
+
+int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos)
+{
+ int idx = -1; // not found
+ const char* start = &name->GetName()[lastpos + 1];
+
+ switch (nid) {
+ case NID_commonName:
+ const char* found = strstr(start, "/CN=");
+ if (found) {
+ found += 4; // advance to str
+ idx = found - start + lastpos + 1;
+ }
+ break;
+ }
+
+ return idx;
+}
+
+
+ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne)
+{
+ // the same in yaSSL
+ return ne;
+}
+
+
+X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc)
+{
+ return name->GetEntry(loc);
+}
+
+
+// already formatted, caller responsible for freeing *out
+int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in)
+{
+ if (!in) return 0;
+
+ *out = (unsigned char*)malloc(in->length + 1);
+ if (*out) {
+ memcpy(*out, in->data, in->length);
+ (*out)[in->length] = 0;
+ }
+ return in->length;
+}
+
+
+void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx)
+{
+ // no extensions supported yet
+ return 0;
+}
+
+
+void MD4_Init(MD4_CTX* md4)
+{
+ // make sure we have a big enough buffer
+ typedef char ok[sizeof(md4->buffer) >= sizeof(TaoCrypt::MD4) ? 1 : -1];
+ (void) sizeof(ok);
+
+ // using TaoCrypt since no dynamic memory allocated
+ // and no destructor will be called
+ new (reinterpret_cast<yassl_pointer>(md4->buffer)) TaoCrypt::MD4();
+}
+
+
+void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz)
+{
+ reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Update(
+ static_cast<const byte*>(data), static_cast<unsigned int>(sz));
+}
+
+
+void MD4_Final(unsigned char* hash, MD4_CTX* md4)
+{
+ reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Final(hash);
+}
+
+
+void MD5_Init(MD5_CTX* md5)
+{
+ // make sure we have a big enough buffer
+ typedef char ok[sizeof(md5->buffer) >= sizeof(TaoCrypt::MD5) ? 1 : -1];
+ (void) sizeof(ok);
+
+ // using TaoCrypt since no dynamic memory allocated
+ // and no destructor will be called
+ new (reinterpret_cast<yassl_pointer>(md5->buffer)) TaoCrypt::MD5();
+}
+
+
+void MD5_Update(MD5_CTX* md5, const void* data, unsigned long sz)
+{
+ reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Update(
+ static_cast<const byte*>(data), static_cast<unsigned int>(sz));
+}
+
+
+void MD5_Final(unsigned char* hash, MD5_CTX* md5)
+{
+ reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Final(hash);
+}
+
+
// functions for stunnel
void RAND_screen()
@@ -1021,8 +1381,10 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
}
- void SSLeay_add_ssl_algorithms() // compatibility only
- {}
+ int SSLeay_add_ssl_algorithms() // compatibility only
+ {
+ return 1;
+ }
void ERR_remove_state(unsigned long)
@@ -1052,4 +1414,5 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
// end stunnel needs
+} // extern "C"
} // namespace
diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp
index c55ca39bec2..134deb00c75 100644
--- a/extra/yassl/src/template_instnt.cpp
+++ b/extra/yassl/src/template_instnt.cpp
@@ -35,13 +35,6 @@
#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*>;
@@ -58,12 +51,16 @@ template class list<yaSSL::SSL_SESSION*>;
template class list<yaSSL::input_buffer*>;
template class list<yaSSL::output_buffer*>;
template class list<yaSSL::x509*>;
+template class list<yaSSL::Digest*>;
+template class list<yaSSL::BulkCipher*>;
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);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::Digest*>::iterator, mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::BulkCipher*>::iterator, mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero);
}
namespace yaSSL {
@@ -89,6 +86,7 @@ template void ysDelete<X509>(X509*);
template void ysDelete<Message>(Message*);
template void ysDelete<sslFactory>(sslFactory*);
template void ysDelete<Sessions>(Sessions*);
+template void ysDelete<CryptProvider>(CryptProvider*);
template void ysArrayDelete<unsigned char>(unsigned char*);
template void ysArrayDelete<char>(char*);
}
diff --git a/extra/yassl/src/yassl.cpp b/extra/yassl/src/yassl.cpp
new file mode 100644
index 00000000000..86af12fd448
--- /dev/null
+++ b/extra/yassl/src/yassl.cpp
@@ -0,0 +1,244 @@
+/* yassl.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 implements external API
+ */
+
+#include "runtime.hpp"
+#include "yassl.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+#include <stdio.h>
+
+#include "openssl/ssl.h" // get rid of this
+
+
+// yaSSL overloads hide these
+void* operator new[](size_t sz)
+{
+ return ::operator new(sz);
+}
+
+void operator delete[](void* ptr)
+{
+ ::operator delete(ptr);
+}
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+struct Base {
+ SSL_METHOD* method_;
+ SSL_CTX* ctx_;
+ SSL* ssl_;
+
+ char* ca_;
+ char* cert_;
+ char* key_;
+
+ DH* dh_;
+
+ Base() : method_(0), ctx_(0), ssl_(0), ca_(0), cert_(0), key_(0), dh_(0)
+ {}
+
+ ~Base()
+ {
+ if (dh_) DH_free(dh_);
+ delete[] key_;
+ delete[] cert_;
+ delete[] ca_;
+ SSL_CTX_free(ctx_); // frees method_ too
+ SSL_free(ssl_);
+ }
+};
+
+
+void SetDH(Base&);
+
+void SetUpBase(Base& base, ConnectionEnd end, SOCKET_T s)
+{
+ base.method_ = new SSL_METHOD(end, ProtocolVersion(3,1));
+ base.ctx_ = new SSL_CTX(base.method_);
+
+ if (base.ca_)
+ if (SSL_CTX_load_verify_locations(base.ctx_,
+ base.ca_, 0) != SSL_SUCCESS) assert(0);
+ if (base.cert_)
+ if (SSL_CTX_use_certificate_file(base.ctx_,
+ base.cert_, SSL_FILETYPE_PEM) != SSL_SUCCESS) assert(0);
+ if (base.key_)
+ if (SSL_CTX_use_PrivateKey_file(base.ctx_, base.key_,
+ SSL_FILETYPE_PEM) != SSL_SUCCESS) assert(0);
+
+ if (end == server_end) SetDH(base);
+
+ base.ssl_ = new SSL(base.ctx_);
+ base.ssl_->useSocket().set_fd(s);
+}
+
+
+void SetDH(Base& base)
+{
+ static unsigned char dh512_p[] =
+ {
+ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+ 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+ 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+ 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+ 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+ 0x47,0x74,0xE8,0x33,
+ };
+
+ static unsigned char dh512_g[] =
+ {
+ 0x02,
+ };
+
+ if ( (base.dh_ = DH_new()) ) {
+ base.dh_->p = BN_bin2bn(dh512_p, sizeof(dh512_p), 0);
+ base.dh_->g = BN_bin2bn(dh512_g, sizeof(dh512_g), 0);
+ }
+ if (!base.dh_->p || !base.dh_->g) {
+ DH_free(base.dh_);
+ base.dh_ = 0;
+ }
+ SSL_CTX_set_tmp_dh(base.ctx_, base.dh_);
+}
+
+
+void NewCopy(char*& dst, const char* src)
+{
+ size_t len = strlen(src) + 1;
+ dst = new char[len];
+
+ strncpy(dst, src, len);
+}
+
+
+// Client Implementation
+struct Client::ClientImpl {
+ Base base_;
+};
+
+
+Client::Client() : pimpl_(new ClientImpl)
+{}
+
+
+Client::~Client() { delete pimpl_; }
+
+
+int Client::Connect(SOCKET_T s)
+{
+ SetUpBase(pimpl_->base_, client_end, s);
+ return SSL_connect(pimpl_->base_.ssl_);
+}
+
+
+int Client::Write(const void* buffer, int sz)
+{
+ return sendData(*pimpl_->base_.ssl_, buffer, sz);
+}
+
+
+int Client::Read(void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*pimpl_->base_.ssl_, data);
+}
+
+
+void Client::SetCA(const char* name)
+{
+ NewCopy(pimpl_->base_.ca_, name);
+}
+
+
+void Client::SetCert(const char* name)
+{
+ NewCopy(pimpl_->base_.cert_, name);
+}
+
+
+void Client::SetKey(const char* name)
+{
+ NewCopy(pimpl_->base_.key_, name);
+}
+
+
+
+// Server Implementation
+struct Server::ServerImpl {
+ Base base_;
+};
+
+
+Server::Server() : pimpl_(new ServerImpl)
+{}
+
+
+Server::~Server() { delete pimpl_; }
+
+
+int Server::Accept(SOCKET_T s)
+{
+ SetUpBase(pimpl_->base_, server_end, s);
+ return SSL_accept(pimpl_->base_.ssl_);
+}
+
+
+int Server::Write(const void* buffer, int sz)
+{
+ return sendData(*pimpl_->base_.ssl_, buffer, sz);
+}
+
+
+int Server::Read(void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*pimpl_->base_.ssl_, data);
+}
+
+
+void Server::SetCA(const char* name)
+{
+ NewCopy(pimpl_->base_.ca_, name);
+}
+
+
+void Server::SetCert(const char* name)
+{
+ NewCopy(pimpl_->base_.cert_, name);
+}
+
+
+void Server::SetKey(const char* name)
+{
+ NewCopy(pimpl_->base_.key_, name);
+}
+
+
+
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
index c53aef2068d..1973c54d781 100644
--- a/extra/yassl/src/yassl_error.cpp
+++ b/extra/yassl/src/yassl_error.cpp
@@ -25,6 +25,8 @@
#include "runtime.hpp"
#include "yassl_error.hpp"
+#include "error.hpp" // TaoCrypt error numbers
+#include "openssl/ssl.h" // SSL_ERROR_WANT_READ
namespace yaSSL {
@@ -48,6 +50,189 @@ Library Error::get_lib() const
}
+void SetErrorString(YasslError error, char* buffer)
+{
+ using namespace TaoCrypt;
+ const int max = MAX_ERROR_SZ; // shorthand
+
+ switch (error) {
+
+ // yaSSL proper errors
+ case range_error :
+ strncpy(buffer, "buffer index error, out of range", max);
+ break;
+
+ case realloc_error :
+ strncpy(buffer, "trying to realloc a fixed buffer", max);
+ break;
+
+ case factory_error :
+ strncpy(buffer, "unknown factory create request", max);
+ break;
+
+ case unknown_cipher :
+ strncpy(buffer, "trying to use an unknown cipher", max);
+ break;
+
+ case prefix_error :
+ strncpy(buffer, "bad master secret derivation, prefix too big", max);
+ break;
+
+ case record_layer :
+ strncpy(buffer, "record layer not ready yet", max);
+ break;
+
+ case handshake_layer :
+ strncpy(buffer, "handshake layer not ready yet", max);
+ break;
+
+ case out_of_order :
+ strncpy(buffer, "handshake message received in wrong order", max);
+ break;
+
+ case bad_input :
+ strncpy(buffer, "bad cipher suite input", max);
+ break;
+
+ case match_error :
+ strncpy(buffer, "unable to match a supported cipher suite", max);
+ break;
+
+ case no_key_file :
+ strncpy(buffer, "the server needs a private key file", max);
+ break;
+
+ case verify_error :
+ strncpy(buffer, "unable to verify peer checksum", max);
+ break;
+
+ case send_error :
+ strncpy(buffer, "socket layer send error", max);
+ break;
+
+ case receive_error :
+ strncpy(buffer, "socket layer receive error", max);
+ break;
+
+ case certificate_error :
+ strncpy(buffer, "unable to proccess cerificate", max);
+ break;
+
+ // openssl errors
+ case SSL_ERROR_WANT_READ :
+ strncpy(buffer, "the read operation would block", max);
+ break;
+
+ // TaoCrypt errors
+ case NO_ERROR :
+ strncpy(buffer, "not in error state", max);
+ break;
+
+ case WINCRYPT_E :
+ strncpy(buffer, "bad wincrypt acquire", max);
+ break;
+
+ case CRYPTGEN_E :
+ strncpy(buffer, "CryptGenRandom error", max);
+ break;
+
+ case OPEN_RAN_E :
+ strncpy(buffer, "unable to use random device", max);
+ break;
+
+ case READ_RAN_E :
+ strncpy(buffer, "unable to use random device", max);
+ break;
+
+ case INTEGER_E :
+ strncpy(buffer, "ASN: bad DER Integer Header", max);
+ break;
+
+ case SEQUENCE_E :
+ strncpy(buffer, "ASN: bad Sequence Header", max);
+ break;
+
+ case SET_E :
+ strncpy(buffer, "ASN: bad Set Header", max);
+ break;
+
+ case VERSION_E :
+ strncpy(buffer, "ASN: version length not 1", max);
+ break;
+
+ case SIG_OID_E :
+ strncpy(buffer, "ASN: signature OID mismatch", max);
+ break;
+
+ case BIT_STR_E :
+ strncpy(buffer, "ASN: bad BitString Header", max);
+ break;
+
+ case UNKNOWN_OID_E :
+ strncpy(buffer, "ASN: unknown key OID type", max);
+ break;
+
+ case OBJECT_ID_E :
+ strncpy(buffer, "ASN: bad Ojbect ID Header", max);
+ break;
+
+ case TAG_NULL_E :
+ strncpy(buffer, "ASN: expected TAG NULL", max);
+ break;
+
+ case EXPECT_0_E :
+ strncpy(buffer, "ASN: expected 0", max);
+ break;
+
+ case OCTET_STR_E :
+ strncpy(buffer, "ASN: bad Octet String Header", max);
+ break;
+
+ case TIME_E :
+ strncpy(buffer, "ASN: bad TIME", max);
+ break;
+
+ case DATE_SZ_E :
+ strncpy(buffer, "ASN: bad Date Size", max);
+ break;
+
+ case SIG_LEN_E :
+ strncpy(buffer, "ASN: bad Signature Length", max);
+ break;
+
+ case UNKOWN_SIG_E :
+ strncpy(buffer, "ASN: unknown signature OID", max);
+ break;
+
+ case UNKOWN_HASH_E :
+ strncpy(buffer, "ASN: unknown hash OID", max);
+ break;
+
+ case DSA_SZ_E :
+ strncpy(buffer, "ASN: bad DSA r or s size", max);
+ break;
+
+ case BEFORE_DATE_E :
+ strncpy(buffer, "ASN: before date in the future", max);
+ break;
+
+ case AFTER_DATE_E :
+ strncpy(buffer, "ASN: after date in the past", max);
+ break;
+
+ case SIG_CONFIRM_E :
+ strncpy(buffer, "ASN: bad self signature confirmation", max);
+ break;
+
+ case SIG_OTHER_E :
+ strncpy(buffer, "ASN: bad other signature confirmation", max);
+ break;
+
+ default :
+ strncpy(buffer, "unknown error number", max);
+ }
+}
+
} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
index 1d9db46816b..4d6d1fc7aff 100644
--- a/extra/yassl/src/yassl_imp.cpp
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -29,6 +29,7 @@
#include "asn.hpp" // provide crypto wrapper??
+
namespace yaSSL {
@@ -111,10 +112,14 @@ void ClientDiffieHellmanPublic::build(SSL& ssl)
uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same
alloc(keyLength, true);
- dhClient.makeAgreement(dhServer.get_publicKey());
+ dhClient.makeAgreement(dhServer.get_publicKey(), keyLength);
c16toa(keyLength, Yc_);
memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
+ // because of encoding first byte might be zero, don't use it for preMaster
+ if (*dhClient.get_agreedKey() == 0)
+ ssl.set_preMaster(dhClient.get_agreedKey() + 1, keyLength - 1);
+ else
ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
}
@@ -134,10 +139,10 @@ void DH_Server::build(SSL& ssl)
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(),
+ auth.reset(NEW_YS RSA(cert.get_privateKey(),
cert.get_privateKeyLength(), false));
else {
- auth.reset(new (ys) DSS(cert.get_privateKey(),
+ auth.reset(NEW_YS DSS(cert.get_privateKey(),
cert.get_privateKeyLength(), false));
sigSz += DSS_ENCODED_EXTRA;
}
@@ -168,7 +173,7 @@ void DH_Server::build(SSL& ssl)
byte hash[FINISHED_SZ];
MD5 md5;
SHA sha;
- signature_ = new (ys) byte[sigSz];
+ signature_ = NEW_YS byte[sigSz];
const Connection& conn = ssl.getSecurity().get_connection();
// md5
@@ -199,7 +204,7 @@ void DH_Server::build(SSL& ssl)
tmp.write(signature_, sigSz);
// key message
- keyMessage_ = new (ys) opaque[length_];
+ keyMessage_ = NEW_YS opaque[length_];
memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size());
}
@@ -253,7 +258,7 @@ opaque* EncryptedPreMasterSecret::get_clientKey() const
void EncryptedPreMasterSecret::alloc(int sz)
{
length_ = sz;
- secret_ = new (ys) opaque[sz];
+ secret_ = NEW_YS opaque[sz];
}
@@ -269,10 +274,14 @@ void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
ato16(tmp, keyLength);
alloc(keyLength);
- input.read(Yc_, length_);
- dh.makeAgreement(Yc_);
+ input.read(Yc_, keyLength);
+ dh.makeAgreement(Yc_, keyLength);
- ssl.set_preMaster(dh.get_agreedKey(), keyLength);
+ // because of encoding, first byte might be 0, don't use for preMaster
+ if (*dh.get_agreedKey() == 0)
+ ssl.set_preMaster(dh.get_agreedKey() + 1, dh.get_agreedKeyLength() - 1);
+ else
+ ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength());
ssl.makeMasterSecret();
}
@@ -303,7 +312,7 @@ opaque* ClientDiffieHellmanPublic::get_clientKey() const
void ClientDiffieHellmanPublic::alloc(int sz, bool offset)
{
length_ = sz + (offset ? KEY_OFFSET : 0);
- Yc_ = new (ys) opaque[length_];
+ Yc_ = NEW_YS opaque[length_];
}
@@ -348,7 +357,7 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
tmp[1] = input[AUTO];
ato16(tmp, length);
- signature_ = new (ys) byte[length];
+ signature_ = NEW_YS byte[length];
input.read(signature_, length);
// verify signature
@@ -386,7 +395,7 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
}
// save input
- ssl.useCrypto().SetDH(new (ys) DiffieHellman(parms_.get_p(),
+ 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()));
@@ -438,7 +447,7 @@ 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
+ // MAX_CIPHERS is big enough
if (isTLS(pv)) {
suites_[i++] = 0x00;
@@ -510,13 +519,10 @@ void Parameters::SetCipherNames()
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++] = ':';
+ int len = strlen(cipher_names[index]) + 1;
+ strncpy(cipher_list_[pos++], cipher_names[index], len);
}
- if (suites)
- cipher_list_[--pos] = 0;
+ cipher_list_[pos][0] = 0;
}
@@ -928,7 +934,7 @@ void Data::Process(input_buffer& input, SSL& ssl)
// read data
if (dataSz) {
input_buffer* data;
- ssl.addData(data = new (ys) input_buffer(dataSz));
+ ssl.addData(data = NEW_YS input_buffer(dataSz));
input.read(data->get_buffer(), dataSz);
data->add_size(dataSz);
@@ -1025,7 +1031,7 @@ void Certificate::Process(input_buffer& input, SSL& ssl)
c24to32(tmp, cert_sz);
x509* myCert;
- cm.AddPeerCert(myCert = new (ys) x509(cert_sz));
+ cm.AddPeerCert(myCert = NEW_YS x509(cert_sz));
input.read(myCert->use_buffer(), myCert->get_length());
list_sz -= cert_sz + CERT_HEADER;
@@ -1111,21 +1117,21 @@ const opaque* ServerDHParams::get_pub() const
opaque* ServerDHParams::alloc_p(int sz)
{
- p_ = new (ys) opaque[pSz_ = sz];
+ p_ = NEW_YS opaque[pSz_ = sz];
return p_;
}
opaque* ServerDHParams::alloc_g(int sz)
{
- g_ = new (ys) opaque[gSz_ = sz];
+ g_ = NEW_YS opaque[gSz_ = sz];
return g_;
}
opaque* ServerDHParams::alloc_pub(int sz)
{
- Ys_ = new (ys) opaque[pubSz_ = sz];
+ Ys_ = NEW_YS opaque[pubSz_ = sz];
return Ys_;
}
@@ -1323,6 +1329,7 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello)
// Compression
hello.comp_len_ = input[AUTO];
+ while (hello.comp_len_--) // ignore for now
hello.compression_methods_ = CompressionMethod(input[AUTO]);
return input;
@@ -1537,7 +1544,7 @@ void CertificateRequest::Build()
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]);
+ certificate_authorities_.push_back(dn = NEW_YS byte[sz]);
opaque tmp[REQUEST_HEADER];
c16toa(MIN_DIS_SIZE, tmp);
@@ -1584,7 +1591,7 @@ input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
ato16(tmp, dnSz);
DistinguishedName dn;
- request.certificate_authorities_.push_back(dn = new (ys)
+ request.certificate_authorities_.push_back(dn = NEW_YS
byte[REQUEST_HEADER + dnSz]);
memcpy(dn, tmp, REQUEST_HEADER);
input.read(&dn[REQUEST_HEADER], dnSz);
@@ -1630,7 +1637,11 @@ output_buffer& operator<<(output_buffer& output,
// CertificateRequest processing handler
void CertificateRequest::Process(input_buffer&, SSL& ssl)
{
- ssl.useCrypto().use_certManager().setSendVerify();
+ CertManager& cm = ssl.useCrypto().use_certManager();
+
+ // make sure user provided cert and key before sending and using
+ if (cm.get_cert() && cm.get_privateKey())
+ cm.setSendVerify();
}
@@ -1665,7 +1676,7 @@ void CertificateVerify::Build(SSL& ssl)
RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
sz = rsa.get_cipherLength() + VERIFY_HEADER;
- sig.reset(new (ys) byte[sz]);
+ sig.reset(NEW_YS byte[sz]);
c16toa(sz - VERIFY_HEADER, len);
memcpy(sig.get(), len, VERIFY_HEADER);
@@ -1676,7 +1687,7 @@ void CertificateVerify::Build(SSL& ssl)
DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false);
sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER;
- sig.reset(new (ys) byte[sz]);
+ sig.reset(NEW_YS byte[sz]);
c16toa(sz - VERIFY_HEADER, len);
memcpy(sig.get(), len, VERIFY_HEADER);
@@ -1714,7 +1725,7 @@ input_buffer& operator>>(input_buffer& input, CertificateVerify& request)
ato16(tmp, sz);
request.set_length(sz);
- request.signature_ = new (ys) byte[sz];
+ request.signature_ = NEW_YS byte[sz];
input.read(request.signature_, sz);
return input;
@@ -1964,7 +1975,9 @@ 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)
-{}
+{
+ memset(sessionID_, 0, sizeof(sessionID_));
+}
Connection::~Connection()
@@ -1975,7 +1988,7 @@ Connection::~Connection()
void Connection::AllocPreSecret(uint sz)
{
- pre_master_secret_ = new (ys) opaque[pre_secret_len_ = sz];
+ pre_master_secret_ = NEW_YS opaque[pre_secret_len_ = sz];
}
@@ -2011,35 +2024,35 @@ void Connection::CleanPreMaster()
// 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; }
+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)
+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; }
+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; }
+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)
+ClientKeyBase* CreateRSAClient() { return NEW_YS
EncryptedPreMasterSecret; }
-ClientKeyBase* CreateDHClient() { return new (ys)
+ClientKeyBase* CreateDHClient() { return NEW_YS
ClientDiffieHellmanPublic; }
-ClientKeyBase* CreateFortezzaClient() { return new (ys) FortezzaKeys; }
+ClientKeyBase* CreateFortezzaClient() { return NEW_YS FortezzaKeys; }
// Constructor calls this to Register compile time callbacks
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index 87d990b3506..a715d32f282 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -28,43 +28,43 @@
#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* operator new(size_t sz, yaSSL::new_t)
+ {
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
+ void operator delete(void* ptr, yaSSL::new_t)
+ {
if (ptr) free(ptr);
-#else
- ::operator delete(ptr);
-#endif
-}
+ }
-void* operator new[](size_t sz, yaSSL::new_t nt)
-{
+ void* operator new[](size_t sz, yaSSL::new_t nt)
+ {
return ::operator new(sz, nt);
-}
+ }
-void operator delete[](void* ptr, yaSSL::new_t nt)
-{
+ void operator delete[](void* ptr, yaSSL::new_t nt)
+ {
::operator delete(ptr, nt);
-}
+ }
+
+ namespace yaSSL {
+
+ new_t ys; // for yaSSL library new
+ }
+
+#endif // YASSL_PURE_C
namespace yaSSL {
@@ -72,7 +72,6 @@ namespace yaSSL {
using mySTL::min;
-new_t ys; // for yaSSL library new
@@ -286,6 +285,8 @@ SSL::SSL(SSL_CTX* ctx)
if (ctx->getMethod()->verifyPeer())
cm.setVerifyPeer();
+ if (ctx->getMethod()->verifyNone())
+ cm.setVerifyNone();
if (ctx->getMethod()->failNoCert())
cm.setFailNoCert();
@@ -321,8 +322,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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;
@@ -335,8 +336,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -349,8 +350,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -363,8 +364,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -377,8 +378,8 @@ void SSL::set_pending(Cipher suite)
parms.key_size_ = RC4_KEY_SZ;
parms.iv_size_ = 0;
parms.cipher_type_ = stream;
- crypto_.setDigest(new (ys) SHA);
- crypto_.setCipher(new (ys) RC4);
+ 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;
@@ -391,8 +392,8 @@ void SSL::set_pending(Cipher suite)
parms.key_size_ = RC4_KEY_SZ;
parms.iv_size_ = 0;
parms.cipher_type_ = stream;
- crypto_.setDigest(new (ys) MD5);
- crypto_.setCipher(new (ys) RC4);
+ 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;
@@ -407,8 +408,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -423,8 +424,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -439,8 +440,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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;
@@ -455,8 +456,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -471,8 +472,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -487,8 +488,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -503,8 +504,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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;
@@ -519,8 +520,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -533,8 +534,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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;
@@ -547,8 +548,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -561,8 +562,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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;
@@ -577,8 +578,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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);
@@ -594,8 +595,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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);
@@ -611,8 +612,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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);
@@ -628,8 +629,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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);
@@ -645,8 +646,8 @@ void SSL::set_pending(Cipher suite)
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));
+ 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);
@@ -662,8 +663,8 @@ void SSL::set_pending(Cipher suite)
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);
+ 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);
@@ -830,7 +831,7 @@ 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);
+ int rounds = (length + MD5_LEN - 1 ) / MD5_LEN;
input_buffer key_data(rounds * MD5_LEN);
opaque sha_output[SHA_LEN];
@@ -1366,7 +1367,7 @@ static Sessions* sessionsInstance = 0;
Sessions& GetSessions()
{
if (!sessionsInstance)
- sessionsInstance = new (ys) Sessions;
+ sessionsInstance = NEW_YS Sessions;
return *sessionsInstance;
}
@@ -1374,18 +1375,43 @@ Sessions& GetSessions()
static sslFactory* sslFactoryInstance = 0;
sslFactory& GetSSL_Factory()
-{
+{
if (!sslFactoryInstance)
- sslFactoryInstance = new (ys) sslFactory;
+ sslFactoryInstance = NEW_YS sslFactory;
return *sslFactoryInstance;
}
-void CleanUp()
+static CryptProvider* cryptProviderInstance = 0;
+
+CryptProvider& GetCryptProvider()
{
- TaoCrypt::CleanUp();
- ysDelete(sslFactoryInstance);
- ysDelete(sessionsInstance);
+ if (!cryptProviderInstance)
+ cryptProviderInstance = NEW_YS CryptProvider;
+ return *cryptProviderInstance;
+}
+
+
+CryptProvider::~CryptProvider()
+{
+ mySTL::for_each(digestList_.begin(), digestList_.end(), del_ptr_zero());
+ mySTL::for_each(cipherList_.begin(), cipherList_.end(), del_ptr_zero());
+}
+
+
+Digest* CryptProvider::NewMd5()
+{
+ Digest* ptr = NEW_YS MD5();
+ digestList_.push_back(ptr);
+ return ptr;
+}
+
+
+BulkCipher* CryptProvider::NewDesEde()
+{
+ BulkCipher* ptr = NEW_YS DES_EDE();
+ cipherList_.push_back(ptr);
+ return ptr;
}
@@ -1395,7 +1421,7 @@ typedef Mutex::Lock Lock;
void Sessions::add(const SSL& ssl)
{
Lock guard(mutex_);
- list_.push_back(new (ys) SSL_SESSION(ssl, random_));
+ list_.push_back(NEW_YS SSL_SESSION(ssl, random_));
}
@@ -1462,7 +1488,8 @@ void Sessions::remove(const opaque* id)
SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv)
- : version_(pv), side_(ce), verifyPeer_(false), failNoCert_(false)
+ : version_(pv), side_(ce), verifyPeer_(false), verifyNone_(false),
+ failNoCert_(false)
{}
@@ -1484,6 +1511,12 @@ void SSL_METHOD::setVerifyPeer()
}
+void SSL_METHOD::setVerifyNone()
+{
+ verifyNone_ = true;
+}
+
+
void SSL_METHOD::setFailNoCert()
{
failNoCert_ = true;
@@ -1496,6 +1529,12 @@ bool SSL_METHOD::verifyPeer() const
}
+bool SSL_METHOD::verifyNone() const
+{
+ return verifyNone_;
+}
+
+
bool SSL_METHOD::failNoCert() const
{
return failNoCert_;
@@ -1572,6 +1611,12 @@ void SSL_CTX::setVerifyPeer()
}
+void SSL_CTX::setVerifyNone()
+{
+ method_->setVerifyNone();
+}
+
+
void SSL_CTX::setFailNoCert()
{
method_->setFailNoCert();
@@ -1794,7 +1839,7 @@ void Crypto::SetDH(DiffieHellman* dh)
void Crypto::SetDH(const DH_Parms& dh)
{
if (dh.set_)
- dh_ = new (ys) DiffieHellman(dh.p_, dh.g_, random_);
+ dh_ = NEW_YS DiffieHellman(dh.p_, dh.g_, random_);
}
@@ -1958,18 +2003,20 @@ void Security::set_resuming(bool b)
X509_NAME::X509_NAME(const char* n, size_t sz)
- : name_(0)
+ : name_(0), sz_(sz)
{
if (sz) {
- name_ = new (ys) char[sz];
+ name_ = NEW_YS char[sz];
memcpy(name_, n, sz);
}
+ entry_.data = 0;
}
X509_NAME::~X509_NAME()
{
ysArrayDelete(name_);
+ ysArrayDelete(entry_.data);
}
@@ -1979,8 +2026,10 @@ char* X509_NAME::GetName()
}
-X509::X509(const char* i, size_t iSz, const char* s, size_t sSz)
- : issuer_(i, iSz), subject_(s, sSz)
+X509::X509(const char* i, size_t iSz, const char* s, size_t sSz,
+ const char* b, int bSz, const char* a, int aSz)
+ : issuer_(i, iSz), subject_(s, sSz),
+ beforeDate_(b, bSz), afterDate_(a, aSz)
{}
@@ -1996,9 +2045,73 @@ X509_NAME* X509::GetSubject()
}
+ASN1_STRING* X509::GetBefore()
+{
+ return beforeDate_.GetString();
+}
+
+
+ASN1_STRING* X509::GetAfter()
+{
+ return afterDate_.GetString();
+}
+
+
+ASN1_STRING* X509_NAME::GetEntry(int i)
+{
+ if (i < 0 || i >= int(sz_))
+ return 0;
+
+ if (entry_.data)
+ ysArrayDelete(entry_.data);
+ entry_.data = NEW_YS byte[sz_]; // max size;
+
+ memcpy(entry_.data, &name_[i], sz_ - i);
+ if (entry_.data[sz_ -i - 1]) {
+ entry_.data[sz_ - i] = 0;
+ entry_.length = sz_ - i;
+ }
+ else
+ entry_.length = sz_ - i - 1;
+ entry_.type = 0;
+
+ return &entry_;
+}
+
+
+StringHolder::StringHolder(const char* str, int sz)
+{
+ asnString_.length = sz;
+ asnString_.data = NEW_YS byte[sz + 1];
+ memcpy(asnString_.data, str, sz);
+ asnString_.type = 0; // not used for now
+}
+
+
+StringHolder::~StringHolder()
+{
+ ysArrayDelete(asnString_.data);
+}
+
+
+ASN1_STRING* StringHolder::GetString()
+{
+ return &asnString_;
+}
+
} // namespace
+
+extern "C" void yaSSL_CleanUp()
+{
+ TaoCrypt::CleanUp();
+ ysDelete(yaSSL::cryptProviderInstance);
+ ysDelete(yaSSL::sslFactoryInstance);
+ ysDelete(yaSSL::sessionsInstance);
+}
+
+
#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);
diff --git a/extra/yassl/taocrypt/cmakelists.txt b/extra/yassl/taocrypt/CMakeLists.txt
index 3ad9195b372..0af0a242e5d 100644
--- a/extra/yassl/taocrypt/cmakelists.txt
+++ b/extra/yassl/taocrypt/CMakeLists.txt
@@ -2,7 +2,7 @@ INCLUDE_DIRECTORIES(../mySTL include)
ADD_LIBRARY(taocrypt src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp
src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp
- src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp
+ src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp
include/aes.hpp include/algebra.hpp include/arc4.hpp include/asn.hpp include/block.hpp
include/coding.hpp include/des.hpp include/dh.hpp include/dsa.hpp include/dsa.hpp
include/error.hpp include/file.hpp include/hash.hpp include/hmac.hpp include/integer.hpp
diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am
index e882f7bafe6..c242696b82f 100644
--- a/extra/yassl/taocrypt/Makefile.am
+++ b/extra/yassl/taocrypt/Makefile.am
@@ -1,2 +1,2 @@
-SUBDIRS = src
-EXTRA_DIST = taocrypt.dsw taocrypt.dsp taocrypt.vcproj cmakelists.txt
+SUBDIRS = src test benchmark
+EXTRA_DIST = taocrypt.dsw taocrypt.dsp taocrypt.vcproj CMakeLists.txt
diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am
new file mode 100644
index 00000000000..81200ff7e6a
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I../include -I../../mySTL
+bin_PROGRAMS = benchmark
+benchmark_SOURCES = benchmark.cpp
+benchmark_LDFLAGS = -L../src
+benchmark_LDADD = -ltaocrypt
+benchmark_CXXFLAGS = -DYASSL_PURE_C
+benchmark_DEPENDENCIES = ../src/libtaocrypt.la
+EXTRA_DIST = benchmark.dsp rsa1024.der dh1024.der dsa1024.der make.bat
diff --git a/extra/yassl/taocrypt/benchmark/benchmark.cpp b/extra/yassl/taocrypt/benchmark/benchmark.cpp
new file mode 100644
index 00000000000..bb725a90187
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/benchmark.cpp
@@ -0,0 +1,440 @@
+// benchmark.cpp
+// TaoCrypt benchmark
+
+#include <string.h>
+#include <stdio.h>
+
+#include "runtime.hpp"
+#include "des.hpp"
+#include "aes.hpp"
+#include "twofish.hpp"
+#include "blowfish.hpp"
+#include "arc4.hpp"
+#include "md5.hpp"
+#include "sha.hpp"
+#include "ripemd.hpp"
+#include "rsa.hpp"
+#include "dh.hpp"
+#include "dsa.hpp"
+
+
+using namespace TaoCrypt;
+
+void bench_aes(bool show);
+void bench_des();
+void bench_blowfish();
+void bench_twofish();
+void bench_arc4();
+
+void bench_md5();
+void bench_sha();
+void bench_ripemd();
+
+void bench_rsa();
+void bench_dh();
+void bench_dsa();
+
+double current_time();
+
+
+
+
+int main(int argc, char** argv)
+{
+ bench_aes(false);
+ bench_aes(true);
+ bench_blowfish();
+ bench_twofish();
+ bench_arc4();
+ bench_des();
+
+ printf("\n");
+
+ bench_md5();
+ bench_sha();
+ bench_ripemd();
+
+ printf("\n");
+
+ bench_rsa();
+ bench_dh();
+ bench_dsa();
+
+ return 0;
+}
+
+const int megs = 5; // how much to test
+
+const byte key[] =
+{
+ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+ 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10,
+ 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+};
+
+const byte iv[] =
+{
+ 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81
+
+};
+
+
+byte plain [1024*1024];
+byte cipher[1024*1024];
+
+
+void bench_des()
+{
+ DES_EDE3_CBC_Encryption enc;
+ enc.SetKey(key, 16, iv);
+
+ double start = current_time();
+
+ for(int i = 0; i < megs; i++)
+ enc.Process(plain, cipher, sizeof(plain));
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("3DES %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_aes(bool show)
+{
+ AES_CBC_Encryption enc;
+ enc.SetKey(key, 16, iv);
+
+ double start = current_time();
+
+ for(int i = 0; i < megs; i++)
+ enc.Process(plain, cipher, sizeof(plain));
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ if (show)
+ printf("AES %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_twofish()
+{
+ Twofish_CBC_Encryption enc;
+ enc.SetKey(key, 16, iv);
+
+ double start = current_time();
+
+ for(int i = 0; i < megs; i++)
+ enc.Process(plain, cipher, sizeof(plain));
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("Twofish %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+
+}
+
+
+void bench_blowfish()
+{
+ Blowfish_CBC_Encryption enc;
+ enc.SetKey(key, 16, iv);
+
+ double start = current_time();
+
+ for(int i = 0; i < megs; i++)
+ enc.Process(plain, cipher, sizeof(plain));
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("Blowfish %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_arc4()
+{
+ ARC4 enc;
+ enc.SetKey(key, 16);
+
+ double start = current_time();
+
+ for(int i = 0; i < megs; i++)
+ enc.Process(cipher, plain, sizeof(plain));
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("ARC4 %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_md5()
+{
+ MD5 hash;
+ byte digest[MD5::DIGEST_SIZE];
+
+ double start = current_time();
+
+
+ for(int i = 0; i < megs; i++)
+ hash.Update(plain, sizeof(plain));
+
+ hash.Final(digest);
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("MD5 %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_sha()
+{
+ SHA hash;
+ byte digest[SHA::DIGEST_SIZE];
+
+ double start = current_time();
+
+
+ for(int i = 0; i < megs; i++)
+ hash.Update(plain, sizeof(plain));
+
+ hash.Final(digest);
+
+ /*
+ for(int i = 0; i < megs; i++)
+ hash.AsmTransform(plain, 16384);
+ */
+
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("SHA %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+
+void bench_ripemd()
+{
+ RIPEMD160 hash;
+ byte digest[RIPEMD160::DIGEST_SIZE];
+
+ double start = current_time();
+
+
+ for(int i = 0; i < megs; i++)
+ hash.Update(plain, sizeof(plain));
+
+ hash.Final(digest);
+
+ double total = current_time() - start;
+
+ double persec = 1 / total * megs;
+
+ printf("RIPEMD %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total,
+ persec);
+}
+
+RandomNumberGenerator rng;
+
+void bench_rsa()
+{
+ const int times = 100;
+
+ Source source;
+ FileSource("./rsa1024.der", source);
+
+ if (source.size() == 0) {
+ printf("can't find ./rsa1024.der\n");
+ return;
+ }
+ RSA_PrivateKey priv(source);
+ RSAES_Encryptor enc(priv);
+
+ byte message[] = "Everyone gets Friday off.";
+ byte cipher[128]; // for 1024 bit
+ byte plain[128]; // for 1024 bit
+ const int len = strlen((char*)message);
+
+ int i;
+ double start = current_time();
+
+ for (i = 0; i < times; i++)
+ enc.Encrypt(message, len, cipher, rng);
+
+ double total = current_time() - start;
+ double each = total / times; // per second
+ double milliEach = each * 1000; // milliseconds
+
+ printf("RSA 1024 encryption took %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+
+ RSAES_Decryptor dec(priv);
+
+ start = current_time();
+
+ for (i = 0; i < times; i++)
+ dec.Decrypt(cipher, 128, plain, rng);
+
+ total = current_time() - start;
+ each = total / times; // per second
+ milliEach = each * 1000; // milliseconds
+
+ printf("RSA 1024 decryption took %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+}
+
+
+void bench_dh()
+{
+ const int times = 100;
+
+ Source source;
+ FileSource("./dh1024.der", source);
+
+ if (source.size() == 0) {
+ printf("can't find ./dh1024.der\n");
+ return;
+ }
+ DH dh(source);
+
+ byte pub[128]; // for 1024 bit
+ byte priv[128]; // for 1024 bit
+
+ int i;
+ double start = current_time();
+
+ for (i = 0; i < times; i++)
+ dh.GenerateKeyPair(rng, priv, pub);
+
+ double total = current_time() - start;
+ double each = total / times; // per second
+ double milliEach = each * 1000; // milliseconds
+
+ printf("DH 1024 key generation %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+
+ DH dh2(dh);
+ byte pub2[128]; // for 1024 bit
+ byte priv2[128]; // for 1024 bit
+ dh2.GenerateKeyPair(rng, priv2, pub2);
+ unsigned char key[256];
+
+ start = current_time();
+
+ for (i = 0; i < times; i++)
+ dh.Agree(key, priv, pub2);
+
+ total = current_time() - start;
+ each = total / times; // per second
+ milliEach = each * 1000; // in milliseconds
+
+ printf("DH 1024 key agreement %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+}
+
+void bench_dsa()
+{
+ const int times = 100;
+
+ Source source;
+ FileSource("./dsa1024.der", source);
+
+ if (source.size() == 0) {
+ printf("can't find ./dsa1024.der\n");
+ return;
+ }
+
+ DSA_PrivateKey key(source);
+ DSA_Signer signer(key);
+
+ SHA sha;
+ byte digest[SHA::DIGEST_SIZE];
+ byte signature[40];
+ const char msg[] = "this is the message";
+ sha.Update((byte*)msg, sizeof(msg));
+ sha.Final(digest);
+
+ int i;
+ double start = current_time();
+
+ for (i = 0; i < times; i++)
+ signer.Sign(digest, signature, rng);
+
+ double total = current_time() - start;
+ double each = total / times; // per second
+ double milliEach = each * 1000; // milliseconds
+
+ printf("DSA 1024 sign took %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+
+ DSA_Verifier verifier(key);
+
+ start = current_time();
+
+ for (i = 0; i < times; i++)
+ verifier.Verify(digest, signature);
+
+ total = current_time() - start;
+ each = total / times; // per second
+ milliEach = each * 1000; // in milliseconds
+
+ printf("DSA 1024 verify took %6.2f milliseconds, avg over %d"
+ " iterations\n", milliEach, times);
+}
+
+
+
+#ifdef _WIN32
+
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+
+ double current_time()
+ {
+ 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;
+ }
+
+#else
+
+ #include <sys/time.h>
+
+ double current_time()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return static_cast<double>(tv.tv_sec)
+ + static_cast<double>(tv.tv_usec) / 1000000;
+ }
+
+#endif // _WIN32
diff --git a/extra/yassl/taocrypt/benchmark/benchmark.dsp b/extra/yassl/taocrypt/benchmark/benchmark.dsp
new file mode 100644
index 00000000000..ed8fef316bb
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/benchmark.dsp
@@ -0,0 +1,101 @@
+# Microsoft Developer Studio Project File - Name="benchmark" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=benchmark - 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 "benchmark.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 "benchmark.mak" CFG="benchmark - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "benchmark - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "benchmark - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "benchmark - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "benchmark___Win32_Release"
+# PROP BASE Intermediate_Dir "benchmark___Win32_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 /MT /W3 /GX /O2 /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 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
+
+!ELSEIF "$(CFG)" == "benchmark - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "benchmark___Win32_Debug"
+# PROP BASE Intermediate_Dir "benchmark___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 "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "benchmark - Win32 Release"
+# Name "benchmark - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\benchmark.cpp
+# 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/extra/yassl/taocrypt/benchmark/dh1024.der b/extra/yassl/taocrypt/benchmark/dh1024.der
new file mode 100644
index 00000000000..1a85d90f3f7
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/dh1024.der
Binary files differ
diff --git a/extra/yassl/taocrypt/benchmark/dsa1024.der b/extra/yassl/taocrypt/benchmark/dsa1024.der
new file mode 100644
index 00000000000..1fcb37fad6a
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/dsa1024.der
Binary files differ
diff --git a/extra/yassl/taocrypt/benchmark/make.bat b/extra/yassl/taocrypt/benchmark/make.bat
new file mode 100644
index 00000000000..4ebe4b32417
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/make.bat
@@ -0,0 +1,9 @@
+REM quick and dirty build file for testing different MSDEVs
+setlocal
+
+set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2
+
+cl %myFLAGS% benchmark.cpp
+
+link.exe /out:benchmark.exe ../src/taocrypt.lib benchmark.obj advapi32.lib
+
diff --git a/extra/yassl/taocrypt/benchmark/rsa1024.der b/extra/yassl/taocrypt/benchmark/rsa1024.der
new file mode 100644
index 00000000000..8fc91814472
--- /dev/null
+++ b/extra/yassl/taocrypt/benchmark/rsa1024.der
Binary files differ
diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp
index b8436d35c5f..e2c1a34b0e3 100644
--- a/extra/yassl/taocrypt/include/aes.hpp
+++ b/extra/yassl/taocrypt/include/aes.hpp
@@ -26,13 +26,13 @@
#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 };
@@ -45,32 +45,38 @@ public:
: 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;
+ void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION);
+ void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); }
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_;
+ word32 key_[60]; // max size
+
+ static const word32 Te[5][256];
+ static const word32 Td[5][256];
+
+ static const word32* Te0;
+ static const word32* Te1;
+ static const word32* Te2;
+ static const word32* Te3;
+ static const word32* Te4;
+
+ static const word32* Td0;
+ static const word32* Td1;
+ static const word32* Td2;
+ static const word32* Td3;
+ static const word32* Td4;
void encrypt(const byte*, const byte*, byte*) const;
+ void AsmEncrypt(const byte*, byte*, void*) const;
void decrypt(const byte*, const byte*, byte*) const;
+ void AsmDecrypt(const byte*, byte*, void*) const;
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
AES(const AES&); // hide copy
AES& operator=(const AES&); // and assign
diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp
index c919c8ea2ae..c37b89fb294 100644
--- a/extra/yassl/taocrypt/include/arc4.hpp
+++ b/extra/yassl/taocrypt/include/arc4.hpp
@@ -42,6 +42,7 @@ public:
ARC4() {}
void Process(byte*, const byte*, word32);
+ void AsmProcess(byte*, const byte*, word32);
void SetKey(const byte*, word32);
private:
byte x_;
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
index 14fcf22d843..da4c0ce1349 100644
--- a/extra/yassl/taocrypt/include/asn.hpp
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -79,20 +79,27 @@ enum ASNIdFlag
enum DNTags
{
- COMMON_NAME = 0x03
+ COMMON_NAME = 0x03, // CN
+ SUR_NAME = 0x04, // SN
+ COUNTRY_NAME = 0x06, // C
+ LOCALITY_NAME = 0x07, // L
+ STATE_NAME = 0x08, // ST
+ ORG_NAME = 0x0a, // O
+ ORGUNIT_NAME = 0x0b // OU
};
enum Constants
{
MIN_DATE_SZ = 13,
- MAX_DATE_SZ = 15,
+ MAX_DATE_SZ = 16,
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
+ DSA_SIG_SZ = 40,
+ NAME_MAX = 512 // max total of all included names
};
@@ -205,14 +212,14 @@ enum { SHA_SIZE = 20 };
// A Signing Authority
class Signer {
PublicKey key_;
- char* name_;
+ char name_[NAME_MAX];
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 char* GetName() const { return name_; }
const byte* GetHash() const { return hash_; }
private:
@@ -232,7 +239,12 @@ 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);
+ enum DateType { BEFORE, AFTER };
+ enum NameType { ISSUER, SUBJECT };
+ enum CertType { CA, USER };
+
+ explicit CertDecoder(Source&, bool decode = true, SignerList* sl = 0,
+ bool noVerify = false, CertType ct = USER);
~CertDecoder();
const PublicKey& GetPublicKey() const { return key_; }
@@ -240,11 +252,10 @@ public:
const char* GetIssuer() const { return issuer_; }
const char* GetCommonName() const { return subject_; }
const byte* GetHash() const { return subjectHash_; }
+ const char* GetBeforeDate() const { return beforeDate_; }
+ const char* GetAfterDate() const { return afterDate_; }
void DecodeToKey();
-
- enum DateType { BEFORE, AFTER };
- enum NameType { ISSUER, SUBJECT };
private:
PublicKey key_;
word32 certBegin_; // offset to start of cert
@@ -255,11 +266,14 @@ private:
byte subjectHash_[SHA_SIZE]; // hash of all Names
byte issuerHash_[SHA_SIZE]; // hash of all Names
byte* signature_;
- char* issuer_; // CommonName
- char* subject_; // CommonName
+ char issuer_[NAME_MAX]; // Names
+ char subject_[NAME_MAX]; // Names
+ char beforeDate_[MAX_DATE_SZ]; // valid before date
+ char afterDate_[MAX_DATE_SZ]; // valid after date
+ bool verify_; // Default to yes, but could be off
void ReadHeader();
- void Decode(SignerList*);
+ void Decode(SignerList*, CertType);
void StoreKey();
void AddDSA();
bool ValidateSelfSignature();
diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp
index ee00ad7487f..76836615ce6 100644
--- a/extra/yassl/taocrypt/include/block.hpp
+++ b/extra/yassl/taocrypt/include/block.hpp
@@ -96,10 +96,10 @@ public:
pointer allocate(size_type n, const void* = 0)
{
- CheckSize(n);
+ this->CheckSize(n);
if (n == 0)
return 0;
- return new (tc) T[n];
+ return NEW_TC T[n];
}
void deallocate(void* p, size_type n)
diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp
new file mode 100644
index 00000000000..7d794a37329
--- /dev/null
+++ b/extra/yassl/taocrypt/include/blowfish.hpp
@@ -0,0 +1,79 @@
+/* blowfish.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
+ */
+
+/* blowfish.hpp defines Blowfish
+*/
+
+
+#ifndef TAO_CRYPT_BLOWFISH_HPP
+#define TAO_CRYPT_BLOWFISH_HPP
+
+#include "misc.hpp"
+#include "modes.hpp"
+#include "algorithm.hpp"
+
+namespace TaoCrypt {
+
+enum { BLOWFISH_BLOCK_SIZE = 8 };
+
+
+// Blowfish encryption and decryption, see
+class Blowfish : public Mode_BASE {
+public:
+ enum { BLOCK_SIZE = BLOWFISH_BLOCK_SIZE, ROUNDS = 16 };
+
+ Blowfish(CipherDir DIR, Mode MODE)
+ : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION);
+ void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); }
+private:
+ CipherDir dir_;
+ Mode mode_;
+
+ static const word32 p_init_[ROUNDS + 2];
+ static const word32 s_init_[4 * 256];
+
+ word32 pbox_[ROUNDS + 2];
+ word32 sbox_[4 * 256];
+
+ void crypt_block(const word32 in[2], word32 out[2]) const;
+ void AsmProcess(const byte* in, byte* out) const;
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+
+ Blowfish(const Blowfish&); // hide copy
+ Blowfish& operator=(const Blowfish&); // and assign
+};
+
+
+typedef BlockCipher<ENCRYPTION, Blowfish, ECB> Blowfish_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, Blowfish, ECB> Blowfish_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, Blowfish, CBC> Blowfish_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, Blowfish, CBC> Blowfish_CBC_Decryption;
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_BLOWFISH_HPP
+
diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp
index 127b8ddc6d5..e0867b09166 100644
--- a/extra/yassl/taocrypt/include/des.hpp
+++ b/extra/yassl/taocrypt/include/des.hpp
@@ -27,73 +27,87 @@
#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 };
+enum { DES_BLOCK_SIZE = 8, DES_KEY_SIZE = 32 };
- DES_BASE(CipherDir DIR, Mode MODE)
- : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
- void Process(byte*, const byte*, word32);
+class BasicDES {
+public:
+ void SetKey(const byte*, word32, CipherDir dir);
+ void RawProcessBlock(word32&, word32&) const;
protected:
- CipherDir dir_;
- Mode mode_;
-private:
- DES_BASE(const DES_BASE&); // hide copy
- DES_BASE& operator=(const DES_BASE&); // and assign
+ word32 k_[DES_KEY_SIZE];
};
// DES
-class DES : public DES_BASE {
+class DES : public Mode_BASE, public BasicDES {
public:
- DES(CipherDir DIR, Mode MODE) : DES_BASE(DIR, MODE) {}
+ DES(CipherDir DIR, Mode MODE)
+ : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
- void SetKey(const byte*, word32, CipherDir dir);
- void RawProcessBlock(word32&, word32&) const;
- void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+ void Process(byte*, const byte*, word32);
private:
- word32 k_[KEY_SIZE];
+ CipherDir dir_;
+ Mode mode_;
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+
+ DES(const DES&); // hide copy
+ DES& operator=(const DES&); // and assign
};
// DES_EDE2
-class DES_EDE2 : public DES_BASE {
+class DES_EDE2 : public Mode_BASE {
public:
DES_EDE2(CipherDir DIR, Mode MODE)
- : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE) {}
+ : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
void SetKey(const byte*, word32, CipherDir dir);
- void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+ void Process(byte*, const byte*, word32);
private:
- DES des1_;
- DES des2_;
+ CipherDir dir_;
+ Mode mode_;
+
+ BasicDES des1_;
+ BasicDES des2_;
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+
+ DES_EDE2(const DES_EDE2&); // hide copy
+ DES_EDE2& operator=(const DES_EDE2&); // and assign
};
+
// DES_EDE3
-class DES_EDE3 : public DES_BASE {
+class DES_EDE3 : public Mode_BASE {
public:
DES_EDE3(CipherDir DIR, Mode MODE)
- : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE),
- des3_(DIR, MODE) {}
+ : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
void SetKey(const byte*, word32, CipherDir dir);
- void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+ void SetIV(const byte* iv) { memcpy(r_, iv, DES_BLOCK_SIZE); }
+ void Process(byte*, const byte*, word32);
private:
- DES des1_;
- DES des2_;
- DES des3_;
+ CipherDir dir_;
+ Mode mode_;
+
+ BasicDES des1_;
+ BasicDES des2_;
+ BasicDES des3_;
+
+ void AsmProcess(const byte* in, byte* out, void* box) const;
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+
+ DES_EDE3(const DES_EDE3&); // hide copy
+ DES_EDE3& operator=(const DES_EDE3&); // and assign
};
diff --git a/extra/yassl/taocrypt/include/dh.hpp b/extra/yassl/taocrypt/include/dh.hpp
index 54a1705546b..75a5d6280d3 100644
--- a/extra/yassl/taocrypt/include/dh.hpp
+++ b/extra/yassl/taocrypt/include/dh.hpp
@@ -64,7 +64,7 @@ public:
}
void GenerateKeyPair(RandomNumberGenerator&, byte*, byte*);
- void Agree(byte*, const byte*, const byte*);
+ void Agree(byte*, const byte*, const byte*, word32 otherSz = 0);
void SetP(const Integer& p) { p_ = p; }
void SetG(const Integer& g) { g_ = g; }
diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp
index 5c90d01aefe..16112cb644d 100644
--- a/extra/yassl/taocrypt/include/hash.hpp
+++ b/extra/yassl/taocrypt/include/hash.hpp
@@ -57,17 +57,26 @@ public:
virtual void Update(const byte*, word32);
virtual void Final(byte*);
+ word32 GetBitCountLo() const { return loLen_ << 3; }
+ word32 GetBitCountHi() const { return (loLen_ >> (8*sizeof(loLen_) - 3)) +
+ (hiLen_ << 3); }
+
enum { MaxDigestSz = 5, MaxBufferSz = 64 };
protected:
- word32 buffLen_;
- word32 length_; // in Bits
+ typedef word32 HashLengthType;
+ word32 buffLen_; // in bytes
+ HashLengthType loLen_; // length in bytes
+ HashLengthType hiLen_; // length in bytes
word32 digest_[MaxDigestSz];
word32 buffer_[MaxBufferSz / sizeof(word32)];
virtual void Transform() = 0;
+
+ void AddLength(word32);
};
+
} // namespace
#endif // TAO_CRYPT_HASH_HPP
diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp
index cf029812ce2..543366afc3a 100644
--- a/extra/yassl/taocrypt/include/hmac.hpp
+++ b/extra/yassl/taocrypt/include/hmac.hpp
@@ -56,12 +56,12 @@ private:
T mac_;
// MSVC 6 HACK, gives compiler error if calculated in array
- enum { HMAC_BSIZE = T::BLOCK_SIZE / sizeof(word32),
- HMAC_DSIZE = T::DIGEST_SIZE / sizeof(word32) };
+ enum { BSIZE = T::BLOCK_SIZE / sizeof(word32),
+ DSIZE = T::DIGEST_SIZE / sizeof(word32) };
- word32 ip_[HMAC_BSIZE]; // align ipad_ on word32
- word32 op_[HMAC_BSIZE]; // align opad_ on word32
- word32 innerH_[HMAC_DSIZE]; // align innerHash_ on word32
+ word32 ip_[BSIZE]; // align ipad_ on word32
+ word32 op_[BSIZE]; // align opad_ on word32
+ word32 innerH_[DSIZE]; // align innerHash_ on word32
void KeyInnerHash();
diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp
index d3bd731e2bd..ee83906cfbc 100644
--- a/extra/yassl/taocrypt/include/integer.hpp
+++ b/extra/yassl/taocrypt/include/integer.hpp
@@ -274,7 +274,6 @@ private:
Integer& dividend, const Integer& divisor);
AlignedWordBlock reg_;
Sign sign_;
-
};
inline bool operator==(const Integer& a, const Integer& b)
diff --git a/extra/yassl/taocrypt/include/kernelc.hpp b/extra/yassl/taocrypt/include/kernelc.hpp
new file mode 100644
index 00000000000..bb74c10ad07
--- /dev/null
+++ b/extra/yassl/taocrypt/include/kernelc.hpp
@@ -0,0 +1,49 @@
+/* kernelc.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
+ */
+
+/* kernelc.hpp provides support for C std lib when compiled in kernel mode
+*/
+
+#ifndef TAOCRYPT_KERNELC_HPP
+#define TAOCRYPT_KERNELC_HPP
+
+#include <linux/types.h> // get right size_t
+
+// system functions that c++ doesn't like headers for
+
+extern "C" void* memcpy(void*, const void*, size_t);
+extern "C" void* memset(void*, int, size_t);
+extern "C" void printk(char *fmt, ...);
+
+#define KERN_ERR "<3>" /* error conditions */
+
+#if defined(NDEBUG)
+ #define assert(p) ((void)0)
+#else
+ #define assert(expr) \
+ if (!(expr)) { \
+ printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr,__FILE__,__FUNCTION__,__LINE__); }
+#endif
+
+
+
+#endif // TAOCRYPT_KERNELC_HPP
diff --git a/extra/yassl/taocrypt/include/md4.hpp b/extra/yassl/taocrypt/include/md4.hpp
new file mode 100644
index 00000000000..aac930d7498
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md4.hpp
@@ -0,0 +1,65 @@
+/* md4.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
+ */
+
+/* md4.hpp provides MD4 digest support
+ * WANRING: MD4 is considered insecure, only use if you have to, e.g., yaSSL
+ * libcurl supports needs this for NTLM authentication
+*/
+
+#ifndef TAO_CRYPT_MD4_HPP
+#define TAO_CRYPT_MD4_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// MD4 digest
+class MD4 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ MD4() : 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; }
+
+ MD4(const MD4&);
+ MD4& operator= (const MD4&);
+
+ void Init();
+ void Swap(MD4&);
+private:
+ void Transform();
+};
+
+inline void swap(MD4& a, MD4& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD4_HPP
+
diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp
index 0198daa466e..981f29108fe 100644
--- a/extra/yassl/taocrypt/include/md5.hpp
+++ b/extra/yassl/taocrypt/include/md5.hpp
@@ -45,10 +45,13 @@ public:
MD5(const MD5&);
MD5& operator= (const MD5&);
+ void Update(const byte*, word32);
+
void Init();
void Swap(MD5&);
private:
void Transform();
+ void AsmTransform(const byte* data, word32 times);
};
inline void swap(MD5& a, MD5& b)
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
index 26383d4c96b..0808d76ccdf 100644
--- a/extra/yassl/taocrypt/include/misc.hpp
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -24,9 +24,15 @@
#ifndef TAO_CRYPT_MISC_HPP
#define TAO_CRYPT_MISC_HPP
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
+
+#if !defined(DO_TAOCRYPT_KERNEL_MODE)
+ #include <stdlib.h>
+ #include <assert.h>
+ #include <string.h>
+#else
+ #include "kernelc.hpp"
+#endif
+
#include "types.hpp"
#include "type_traits.hpp"
@@ -39,31 +45,33 @@ namespace TaoCrypt {
void CleanUp();
-// library allocation
-struct new_t {}; // TaoCrypt New type
-extern new_t tc; // pass in parameter
+#ifdef YASSL_PURE_C
-} // namespace TaoCrypt
+ // library allocation
+ struct new_t {}; // TaoCrypt New type
+ extern new_t tc; // pass in parameter
-void* operator new (size_t, TaoCrypt::new_t);
-void* operator new[](size_t, TaoCrypt::new_t);
+ } // namespace TaoCrypt
-void operator delete (void*, TaoCrypt::new_t);
-void operator delete[](void*, TaoCrypt::new_t);
+ 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)
-{
+ 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)
-{
+ 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
@@ -71,15 +79,39 @@ void tcArrayDelete(T* ptr)
(void)sizeof(builtin);
::operator delete[](ptr, TaoCrypt::tc);
-}
+ }
+ #define NEW_TC new (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:
+
+ // 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); }
-};
+ };
+
+#else // YASSL_PURE_C
+
+
+ template<typename T>
+ void tcDelete(T* ptr)
+ {
+ delete ptr;
+ }
+
+ template<typename T>
+ void tcArrayDelete(T* ptr)
+ {
+ delete[] ptr;
+ }
+
+ #define NEW_TC new
+
+ class virtual_base {};
+
+
+#endif // YASSL_PURE_C
#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
@@ -100,15 +132,13 @@ public:
#define TAOCRYPT_DISABLE_X86ASM
#endif
-
-// Disable assmebler when compiling with icc
-// Temporary workaround for bug12717
+// icc problem with -03 and integer, disable for now
#if defined(__INTEL_COMPILER)
#define TAOCRYPT_DISABLE_X86ASM
#endif
-
+// Turn on ia32 ASM for Big Integer
// CodeWarrior defines _MSC_VER
#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
!defined(__MWERKS__) && defined(_M_IX86)) || \
@@ -117,6 +147,20 @@ public:
#endif
+// Turn on ia32 ASM for Ciphers and Message Digests
+// Seperate define since these are more complex, use member offsets
+// and user may want to turn off while leaving Big Integer optos on
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && !defined(DISABLE_TAO_ASM)
+ #define TAO_ASM
+#endif
+
+
+// Extra word in older vtable implementations, for ASM member offset
+#if defined(__GNUC__) && __GNUC__ < 3
+ #define OLD_GCC_OFFSET
+#endif
+
+
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# define TAOCRYPT_MALLOC_ALIGNMENT_IS_16
#endif
@@ -437,6 +481,58 @@ inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order)
}
+
+// do Asm Reverse is host is Little and x86asm
+#ifdef LITTLE_ENDIAN_ORDER
+ #ifdef TAOCRYPT_X86ASM_AVAILABLE
+ #define LittleReverse AsmReverse
+ #else
+ #define LittleReverse ByteReverse
+ #endif
+#else
+ #define LittleReverse
+#endif
+
+
+// do Asm Reverse is host is Big and x86asm
+#ifdef BIG_ENDIAN_ORDER
+ #ifdef TAOCRYPT_X86ASM_AVAILABLE
+ #define BigReverse AsmReverse
+ #else
+ #define BigReverse ByteReverse
+ #endif
+#else
+ #define BigReverse
+#endif
+
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+ // faster than rotate, use bswap
+
+ inline word32 AsmReverse(word32 wd)
+ {
+ #ifdef __GNUC__
+ __asm__
+ (
+ "bswap %1"
+ : "=r"(wd)
+ : "0"(wd)
+ );
+ #else
+ __asm
+ {
+ mov eax, wd
+ bswap eax
+ mov wd, eax
+ }
+ #endif
+ return wd;
+ }
+
+#endif
+
+
template <class T>
inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in,
word32 inlen)
diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp
index a23d14db7da..10f336c00eb 100644
--- a/extra/yassl/taocrypt/include/modes.hpp
+++ b/extra/yassl/taocrypt/include/modes.hpp
@@ -26,7 +26,6 @@
#ifndef TAO_CRYPT_MODES_HPP
#define TAO_CRYPT_MODES_HPP
-#include <string.h>
#include "misc.hpp"
namespace TaoCrypt {
@@ -68,14 +67,8 @@ public:
}
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:
+protected:
int blockSz_;
byte* reg_;
byte* tmp_;
@@ -83,9 +76,15 @@ private:
word32 r_[MaxBlockSz / sizeof(word32)]; // align reg_ on word32
word32 t_[MaxBlockSz / sizeof(word32)]; // align tmp_ on word32
+ void ECB_Process(byte*, const byte*, word32);
+ void CBC_Encrypt(byte*, const byte*, word32);
+ void CBC_Decrypt(byte*, const byte*, word32);
Mode_BASE(const Mode_BASE&); // hide copy
Mode_BASE& operator=(const Mode_BASE&); // and assign
+
+private:
+ virtual void ProcessAndXorBlock(const byte*, const byte*, byte*) const = 0;
};
diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp
new file mode 100644
index 00000000000..f40c48fe026
--- /dev/null
+++ b/extra/yassl/taocrypt/include/pwdbased.hpp
@@ -0,0 +1,93 @@
+/* pwdbased.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
+ */
+
+/* pwdbased.hpp defines PBKDF2 from PKCS #5
+*/
+
+
+#ifndef TAO_CRYPT_PWDBASED_HPP
+#define TAO_CRYPT_PWDBASED_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "block.hpp"
+#include "hmac.hpp"
+
+namespace TaoCrypt {
+
+
+// From PKCS #5, T must be type suitable for HMAC<T>
+template <class T>
+class PBKDF2_HMAC {
+public:
+ word32 MaxDerivedKeyLength() const { return 0xFFFFFFFFU;} // avoid overflow
+
+ word32 DeriveKey(byte* derived, word32 dLen, const byte* pwd, word32 pLen,
+ const byte* salt, word32 sLen, word32 iterations) const;
+};
+
+
+
+template <class T>
+word32 PBKDF2_HMAC<T>::DeriveKey(byte* derived, word32 dLen, const byte* pwd,
+ word32 pLen, const byte* salt, word32 sLen,
+ word32 iterations) const
+{
+ assert(dLen <= MaxDerivedKeyLength());
+ assert(iterations > 0);
+
+ ByteBlock buffer(T::DIGEST_SIZE);
+ HMAC<T> hmac;
+
+ hmac.SetKey(pwd, pLen);
+
+ word32 i = 1;
+
+ while (dLen > 0) {
+ hmac.Update(salt, sLen);
+ word32 j;
+ for (j = 0; j < 4; j++) {
+ byte b = i >> ((3-j)*8);
+ hmac.Update(&b, 1);
+ }
+ hmac.Final(buffer.get_buffer());
+
+ word32 segmentLen = mySTL::min(dLen, buffer.size());
+ memcpy(derived, buffer.get_buffer(), segmentLen);
+
+ for (j = 1; j < iterations; j++) {
+ hmac.Update(buffer.get_buffer(), buffer.size());
+ hmac.Final(buffer.get_buffer());
+ xorbuf(derived, buffer.get_buffer(), segmentLen);
+ }
+ derived += segmentLen;
+ dLen -= segmentLen;
+ i++;
+ }
+ return iterations;
+}
+
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_PWDBASED_HPP
diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp
index 4f8e1fd0386..b72e503f095 100644
--- a/extra/yassl/taocrypt/include/ripemd.hpp
+++ b/extra/yassl/taocrypt/include/ripemd.hpp
@@ -45,10 +45,12 @@ public:
RIPEMD160(const RIPEMD160&);
RIPEMD160& operator= (const RIPEMD160&);
+ void Update(const byte*, word32);
void Init();
void Swap(RIPEMD160&);
private:
void Transform();
+ void AsmTransform(const byte* data, word32 times);
};
inline void swap(RIPEMD160& a, RIPEMD160& b)
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
index d9d7877bd93..3a5cf62865a 100644
--- a/extra/yassl/taocrypt/include/runtime.hpp
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -30,7 +30,7 @@
#ifdef __sun
-
+
#include <assert.h>
// Handler for pure virtual functions
@@ -49,7 +49,11 @@ namespace __Crun {
#if __GNUC__ > 2
extern "C" {
-#include <assert.h>
+#if !defined(DO_TAOCRYPT_KERNEL_MODE)
+ #include <assert.h>
+#else
+ #include "kernelc.hpp"
+#endif
/* Disallow inline __cxa_pure_virtual() */
static int __cxa_pure_virtual() __attribute__((noinline, used));
diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp
index b75d9e3f670..3e301a6f0ae 100644
--- a/extra/yassl/taocrypt/include/sha.hpp
+++ b/extra/yassl/taocrypt/include/sha.hpp
@@ -42,6 +42,7 @@ public:
word32 getDigestSize() const { return DIGEST_SIZE; }
word32 getPadSize() const { return PAD_SIZE; }
+ void Update(const byte* data, word32 len);
void Init();
SHA(const SHA&);
@@ -50,6 +51,7 @@ public:
void Swap(SHA&);
private:
void Transform();
+ void AsmTransform(const byte* data, word32 times);
};
diff --git a/extra/yassl/taocrypt/include/twofish.hpp b/extra/yassl/taocrypt/include/twofish.hpp
new file mode 100644
index 00000000000..8605221854f
--- /dev/null
+++ b/extra/yassl/taocrypt/include/twofish.hpp
@@ -0,0 +1,86 @@
+/* twofish.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
+ */
+
+/* twofish.hpp defines Twofish
+*/
+
+
+#ifndef TAO_CRYPT_TWOFISH_HPP
+#define TAO_CRYPT_TWOFISH_HPP
+
+#include "misc.hpp"
+#include "modes.hpp"
+#include "algorithm.hpp"
+
+namespace TaoCrypt {
+
+enum { TWOFISH_BLOCK_SIZE = 16 };
+
+
+// Twofish encryption and decryption, see
+class Twofish : public Mode_BASE {
+public:
+ enum { BLOCK_SIZE = TWOFISH_BLOCK_SIZE };
+
+ Twofish(CipherDir DIR, Mode MODE)
+ : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION);
+ void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); }
+private:
+ CipherDir dir_;
+ Mode mode_;
+
+ static const byte q_[2][256];
+ static const word32 mds_[4][256];
+
+ word32 k_[40];
+ word32 s_[4][256];
+
+ static word32 h0(word32 x, const word32 *key, unsigned int kLen);
+ static word32 h(word32 x, const word32 *key, unsigned int kLen);
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+
+ void encrypt(const byte*, const byte*, byte*) const;
+ void decrypt(const byte*, const byte*, byte*) const;
+
+ void AsmEncrypt(const byte* inBlock, byte* outBlock) const;
+ void AsmDecrypt(const byte* inBlock, byte* outBlock) const;
+
+ Twofish(const Twofish&); // hide copy
+ Twofish& operator=(const Twofish&); // and assign
+};
+
+
+typedef BlockCipher<ENCRYPTION, Twofish, ECB> Twofish_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, Twofish, ECB> Twofish_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, Twofish, CBC> Twofish_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, Twofish, CBC> Twofish_CBC_Decryption;
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_TWOFISH_HPP
+
diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp
index db9c3792bbd..a2453a994fb 100644
--- a/extra/yassl/taocrypt/include/types.hpp
+++ b/extra/yassl/taocrypt/include/types.hpp
@@ -61,10 +61,11 @@ typedef unsigned int word32;
// compilers we've found 64-bit multiply insructions for
#if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX)
-#if !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #if !(defined(__ICC) || defined(__INTEL_COMPILER))
#define HAVE_64_MULTIPLY
+ #endif
#endif
-#endif
+
#if defined(HAVE_64_MULTIPLY) && (defined(__alpha__) || defined(__ia64__) \
|| defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__))
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
index d89fa95a940..1110ed335b8 100644
--- a/extra/yassl/taocrypt/src/Makefile.am
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -2,10 +2,12 @@ INCLUDES = -I../include -I../../mySTL
noinst_LTLIBRARIES = libtaocrypt.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 integer.cpp
+libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \
+ asn.cpp bftables.cpp blowfish.cpp coding.cpp des.cpp dh.cpp \
+ dsa.cpp file.cpp hash.cpp integer.cpp md2.cpp md4.cpp md5.cpp misc.cpp \
+ random.cpp ripemd.cpp rsa.cpp sha.cpp template_instnt.cpp \
+ tftables.cpp twofish.cpp
+
libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C
EXTRA_DIST = $(wildcard ../include/*.hpp)
diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp
index 09cf28a40b0..e737af33df3 100644
--- a/extra/yassl/taocrypt/src/aes.cpp
+++ b/extra/yassl/taocrypt/src/aes.cpp
@@ -19,15 +19,28 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-/* based on Wei Dai's aes.cpp from CryptoPP */
+/* C++ based on Wei Dai's aes.cpp from CryptoPP */
+/* x86 asm original */
+
+#if defined(TAOCRYPT_KERNEL_MODE)
+ #define DO_TAOCRYPT_KERNEL_MODE
+#endif // only some modules now support this
#include "runtime.hpp"
#include "aes.hpp"
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_AES_ASM
+#endif
+
+
namespace TaoCrypt {
+#if !defined(DO_AES_ASM)
+
+// Generic Version
void AES::Process(byte* out, const byte* in, word32 sz)
{
if (mode_ == ECB)
@@ -39,6 +52,52 @@ void AES::Process(byte* out, const byte* in, word32 sz)
CBC_Decrypt(out, in, sz);
}
+#else
+
+// ia32 optimized version
+void AES::Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ if (mode_ == ECB)
+ while (blocks--) {
+ if (dir_ == ENCRYPTION)
+ AsmEncrypt(in, out, (void*)Te0);
+ else
+ AsmDecrypt(in, out, (void*)Td0);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ while (blocks--) {
+ r_[0] ^= *(word32*)in;
+ r_[1] ^= *(word32*)(in + 4);
+ r_[2] ^= *(word32*)(in + 8);
+ r_[3] ^= *(word32*)(in + 12);
+
+ AsmEncrypt((byte*)r_, (byte*)r_, (void*)Te0);
+
+ memcpy(out, r_, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else
+ while (blocks--) {
+ AsmDecrypt(in, out, (void*)Td0);
+
+ *(word32*)out ^= r_[0];
+ *(word32*)(out + 4) ^= r_[1];
+ *(word32*)(out + 8) ^= r_[2];
+ *(word32*)(out + 12) ^= r_[3];
+
+ memcpy(r_, in, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+#endif // DO_AES_ASM
void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
@@ -46,9 +105,8 @@ 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();
+ word32 temp, *rk = key_;
unsigned int i=0;
GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen);
@@ -128,7 +186,7 @@ void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
if (dir_ == DECRYPTION)
{
unsigned int i, j;
- rk = key_.get_buffer();
+ rk = key_;
/* invert the order of the round keys: */
for (i = 0, j = 4*rounds_; i < j; i += 4, j -= 4) {
@@ -166,8 +224,6 @@ void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
}
-typedef BlockGetAndPut<word32, BigEndian> gpBlock;
-
void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
{
if (dir_ == ENCRYPTION)
@@ -177,12 +233,16 @@ void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
}
+typedef BlockGetAndPut<word32, BigEndian> gpBlock;
+
+
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();
+ word32 s0, s1, s2, s3;
+ word32 t0, t1, t2, t3;
+ const word32 *rk = key_;
/*
* map byte array block to cipher state
* and add initial round key:
@@ -192,9 +252,11 @@ void AES::encrypt(const byte* inBlock, const byte* xorBlock,
s1 ^= rk[1];
s2 ^= rk[2];
s3 ^= rk[3];
+
/*
* Nr - 1 full rounds:
*/
+
unsigned int r = rounds_ >> 1;
for (;;) {
t0 =
@@ -252,6 +314,7 @@ void AES::encrypt(const byte* inBlock, const byte* xorBlock,
Te3[GETBYTE(t2, 0)] ^
rk[3];
}
+
/*
* apply last round and
* map cipher state to byte array block:
@@ -282,16 +345,17 @@ void AES::encrypt(const byte* inBlock, const byte* xorBlock,
(Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
rk[3];
- gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+ 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();
+ word32 s0, s1, s2, s3;
+ word32 t0, t1, t2, t3;
+ const word32* rk = key_;
/*
* map byte array block to cipher state
@@ -302,9 +366,11 @@ void AES::decrypt(const byte* inBlock, const byte* xorBlock,
s1 ^= rk[1];
s2 ^= rk[2];
s3 ^= rk[3];
+
/*
* Nr - 1 full rounds:
*/
+
unsigned int r = rounds_ >> 1;
for (;;) {
t0 =
@@ -395,6 +461,1371 @@ void AES::decrypt(const byte* inBlock, const byte* xorBlock,
}
+#if defined(DO_AES_ASM)
+ #ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( sub esp, 4 ) \
+ AS2( movd mm7, ebp ) \
+ AS2( mov [ebp - 4], esi ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov esi, DWORD PTR [ebp + 12] ) \
+ AS2( mov ebp, DWORD PTR [ebp + 20] )
+
+ #define EPILOG() \
+ AS2( mov esi, [ebp - 4] ) \
+ AS2( mov esp, ebp ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+ #else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( sub esp, 4 ) \
+ AS2( movd mm7, ebp ) \
+ AS2( mov [ebp - 4], esi ) \
+ AS2( mov esi, DWORD PTR [ebp + 8] ) \
+ AS2( mov ebp, DWORD PTR [ebp + 16] )
+
+ // ebp is restored at end
+ #define EPILOG() \
+ AS2( mov esi, [ebp - 4] ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 12 )
+
+
+ #endif
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void AES::AsmEncrypt(const byte* inBlock, byte* outBlock, void* boxes) const
+{
+
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( mov edx, DWORD PTR [ecx + 60] ) // rounds
+ AS2( lea edi, [ecx + 64] ) // rk
+ #else
+ AS2( mov edx, DWORD PTR [ecx + 56] ) // rounds
+ AS2( lea edi, [ecx + 60] ) // rk
+ #endif
+
+ AS1( dec edx )
+ AS2( movd mm6, edi ) // save rk
+ AS2( movd mm5, edx ) // save rounds
+
+ AS2( mov eax, DWORD PTR [esi] )
+ AS2( mov ebx, DWORD PTR [esi + 4] )
+ AS2( mov ecx, DWORD PTR [esi + 8] )
+ AS2( mov edx, DWORD PTR [esi + 12] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( xor eax, DWORD PTR [edi] ) // s0
+ AS2( xor ebx, DWORD PTR [edi + 4] ) // s1
+ AS2( xor ecx, DWORD PTR [edi + 8] ) // s2
+ AS2( xor edx, DWORD PTR [edi + 12] ) // s3
+
+ AS1(loop1: )
+ /* Put0 (mm0) =
+ Te0[get0,rs 24] ^
+ Te1[get1,rs 16] ^
+ Te2[get2,rs 8] ^
+ Te3[get3,rs 0]
+ */
+
+ AS2( mov esi, eax )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, ebx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, ch )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, dl )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm0, esi )
+
+ /* Put1 (mm1) =
+ Te0[get1,rs 24] ^
+ Te1[get2,rs 16] ^
+ Te2[get3,rs 8] ^
+ Te3[get0,rs 0]
+ */
+
+ AS2( mov esi, ebx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, ecx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, dh )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, al )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm1, esi )
+
+
+ /* Put2 (mm2) =
+ Te0[get2,rs 24] ^
+ Te1[get3,rs 16] ^
+ Te2[get0,rs 8] ^
+ Te3[get1,rs 0]
+ */
+
+ AS2( mov esi, ecx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, edx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, ah )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, bl )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm2, esi )
+
+ /* Put3 (edx) =
+ Te0[get3,rs 24] ^
+ Te1[get0,rs 16] ^
+ Te2[get1,rs 8] ^
+ Te3[get2,rs 0]
+ */
+
+ AS2( mov esi, edx )
+ AS2( shr esi, 24 )
+ AS2( mov edx, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, eax )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor edx, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx esi, bh )
+ AS2( xor edx, DWORD PTR [ebp + 2048 + esi*4] )
+
+ AS2( movzx edi, cl )
+ AS2( xor edx, DWORD PTR [ebp + 3072 + edi*4] )
+
+ // xOr
+
+ AS2( movd esi, mm6 ) // rk
+
+ AS2( movd eax, mm0 )
+ AS2( add esi, 16 )
+ AS2( movd ebx, mm1 )
+ AS2( movd mm6, esi ) // save back
+ AS2( movd ecx, mm2 )
+
+ AS2( xor eax, DWORD PTR [esi] )
+ AS2( xor ebx, DWORD PTR [esi + 4] )
+ AS2( movd edi, mm5 )
+ AS2( xor ecx, DWORD PTR [esi + 8] )
+ AS2( xor edx, DWORD PTR [esi + 12] )
+
+ AS1( dec edi )
+ AS2( movd mm5, edi )
+
+ AS1( jnz loop1 )
+
+ // last round
+ /*
+ Put0 (mm0) =
+ (Te4[get0, rs24] & 0xff000000) ^ h = 4278190080
+ (Te4[get1, rs16] & 0x00ff0000) ^ h = 16711680
+ (Te4[get2, rs 8] & 0x0000ff00) ^ h = 65280
+ (Te4[get3, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, eax )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, ebx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, ch )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, dl )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm0, esi )
+
+ /*
+ Put1 (mm1) =
+ (Te4[get1, rs24] & 0xff000000) ^ h = 4278190080
+ (Te4[get2, rs16] & 0x00ff0000) ^ h = 16711680
+ (Te4[get3, rs 8] & 0x0000ff00) ^ h = 65280
+ (Te4[get0, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, ebx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, ecx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, dh )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, al )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm1, esi )
+
+ /*
+ Put2 (mm2) =
+ (Te4[get2, rs24] & 0xff000000) ^ h = 4278190080
+ (Te4[get3, rs16] & 0x00ff0000) ^ h = 16711680
+ (Te4[get0, rs 8] & 0x0000ff00) ^ h = 65280
+ (Te4[get1, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, ecx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, edx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, ah )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, bl )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm2, esi )
+
+ /*
+ Put3 (edx) =
+ (Te4[get3, rs24] & 0xff000000) ^ h = 4278190080
+ (Te4[get0, rs16] & 0x00ff0000) ^ h = 16711680
+ (Te4[get1, rs 8] & 0x0000ff00) ^ h = 65280
+ (Te4[get2, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, edx )
+ AS2( shr esi, 24 )
+ AS2( mov edx, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and edx, 4278190080 )
+
+ AS2( mov edi, eax )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and esi, 16711680 )
+ AS2( xor edx, esi )
+
+ AS2( movzx esi, bh )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor edx, edi )
+
+ AS2( movzx edi, cl )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and esi, 255 )
+ AS2( xor edx, esi )
+
+
+ // xOr
+ AS2( movd eax, mm0 )
+ AS2( movd esi, mm6 ) // rk
+ AS2( movd ebx, mm1 )
+ AS2( add esi, 16 )
+ AS2( movd ecx, mm2 )
+
+ AS2( xor eax, DWORD PTR [esi] )
+ AS2( xor ebx, DWORD PTR [esi + 4] )
+ AS2( xor ecx, DWORD PTR [esi + 8] )
+ AS2( xor edx, DWORD PTR [esi + 12] )
+
+ // end
+ AS2( movd ebp, mm7 )
+
+ // swap
+ AS1( bswap eax )
+ AS1( bswap ebx )
+
+ // store
+ #ifdef __GNUC__
+ AS2( mov esi, DWORD PTR [ebp + 16] ) // outBlock
+ #else
+ AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock
+ #endif
+
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( mov DWORD PTR [esi], eax )
+ AS2( mov DWORD PTR [esi + 4], ebx )
+ AS2( mov DWORD PTR [esi + 8], ecx )
+ AS2( mov DWORD PTR [esi + 12], edx )
+
+
+ EPILOG()
+}
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void AES::AsmDecrypt(const byte* inBlock, byte* outBlock, void* boxes) const
+{
+
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( mov edx, DWORD PTR [ecx + 60] ) // rounds
+ AS2( lea edi, [ecx + 64] ) // rk
+ #else
+ AS2( mov edx, DWORD PTR [ecx + 56] ) // rounds
+ AS2( lea edi, [ecx + 60] ) // rk
+ #endif
+
+ AS1( dec edx )
+ AS2( movd mm6, edi ) // save rk
+ AS2( movd mm5, edx ) // save rounds
+
+ AS2( mov eax, DWORD PTR [esi] )
+ AS2( mov ebx, DWORD PTR [esi + 4] )
+ AS2( mov ecx, DWORD PTR [esi + 8] )
+ AS2( mov edx, DWORD PTR [esi + 12] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( xor eax, DWORD PTR [edi] ) // s0
+ AS2( xor ebx, DWORD PTR [edi + 4] ) // s1
+ AS2( xor ecx, DWORD PTR [edi + 8] ) // s2
+ AS2( xor edx, DWORD PTR [edi + 12] ) // s3
+
+
+ AS1(loop2: )
+ /* Put0 (mm0) =
+ Td0[GETBYTE(get0, rs24)] ^
+ Td1[GETBYTE(get3, rs16)] ^
+ Td2[GETBYTE(get2, rs 8)] ^
+ Td3[GETBYTE(tet1, )]
+ */
+ AS2( mov esi, eax )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, edx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, ch )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, bl )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm0, esi )
+
+ /* Put1 (mm1) =
+ Td0[GETBYTE(get1, rs24)] ^
+ Td1[GETBYTE(get0, rs16)] ^
+ Td2[GETBYTE(get3, rs 8)] ^
+ Td3[GETBYTE(tet2, )]
+ */
+ AS2( mov esi, ebx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, eax )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, dh )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, cl )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm1, esi )
+
+ /* Put2 (mm2) =
+ Td0[GETBYTE(get2, rs24)] ^
+ Td1[GETBYTE(get1, rs16)] ^
+ Td2[GETBYTE(get0, rs 8)] ^
+ Td3[GETBYTE(tet3, )]
+ */
+ AS2( mov esi, ecx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, ebx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx edi, ah )
+ AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] )
+
+ AS2( movzx edi, dl )
+ AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] )
+
+ AS2( movd mm2, esi )
+
+ /* Put3 (edx) =
+ Td0[GETBYTE(get3, rs24)] ^
+ Td1[GETBYTE(get2, rs16)] ^
+ Td2[GETBYTE(get1, rs 8)] ^
+ Td3[GETBYTE(tet0, )]
+ */
+ AS2( mov esi, edx )
+ AS2( shr esi, 24 )
+ AS2( mov edx, DWORD PTR [ebp + esi*4] )
+
+ AS2( mov edi, ecx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( xor edx, DWORD PTR [ebp + 1024 + edi*4] )
+
+ AS2( movzx esi, bh )
+ AS2( xor edx, DWORD PTR [ebp + 2048 + esi*4] )
+
+ AS2( movzx edi, al )
+ AS2( xor edx, DWORD PTR [ebp + 3072 + edi*4] )
+
+
+ // xOr
+
+ AS2( movd esi, mm6 ) // rk
+ AS2( add esi, 16 )
+ AS2( movd mm6, esi ) // save back
+
+ AS2( movd eax, mm0 )
+ AS2( movd ebx, mm1 )
+ AS2( movd ecx, mm2 )
+
+ AS2( xor eax, DWORD PTR [esi] )
+ AS2( xor ebx, DWORD PTR [esi + 4] )
+ AS2( xor ecx, DWORD PTR [esi + 8] )
+ AS2( xor edx, DWORD PTR [esi + 12] )
+
+ AS2( movd edi, mm5 )
+ AS1( dec edi )
+ AS2( movd mm5, edi )
+
+ AS1( jnz loop2 )
+
+ // last round
+ /*
+ Put0 (mm0) =
+ (Td4[get0, rs24] & 0xff000000) ^ h = 4278190080
+ (Td4[get3, rs16] & 0x00ff0000) ^ h = 16711680
+ (Td4[get2, rs 8] & 0x0000ff00) ^ h = 65280
+ (Td4[get1, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, eax )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, edx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, ch )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, bl )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm0, esi )
+
+ /*
+ Put1 (mm1) =
+ (Td4[get1, rs24] & 0xff000000) ^ h = 4278190080
+ (Td4[get0, rs16] & 0x00ff0000) ^ h = 16711680
+ (Td4[get3, rs 8] & 0x0000ff00) ^ h = 65280
+ (Td4[get2, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, ebx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, eax )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, dh )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, cl )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm1, esi )
+
+ /*
+ Put2 (mm2) =
+ (Td4[get2, rs24] & 0xff000000) ^ h = 4278190080
+ (Td4[get1, rs16] & 0x00ff0000) ^ h = 16711680
+ (Td4[get0, rs 8] & 0x0000ff00) ^ h = 65280
+ (Td4[get3, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, ecx )
+ AS2( shr esi, 24 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and esi, 4278190080 )
+
+ AS2( mov edi, ebx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 16711680 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, ah )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor esi, edi )
+
+ AS2( movzx edi, dl )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and edi, 255 )
+ AS2( xor esi, edi )
+
+ AS2( movd mm2, esi )
+
+ /*
+ Put3 (edx) =
+ (Td4[get3, rs24] & 0xff000000) ^ h = 4278190080
+ (Td4[get2, rs16] & 0x00ff0000) ^ h = 16711680
+ (Td4[get1, rs 8] & 0x0000ff00) ^ h = 65280
+ (Td4[get0, rs 0] & 0x000000ff) h = 255
+ */
+ AS2( mov esi, edx )
+ AS2( shr esi, 24 )
+ AS2( mov edx, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and edx, 4278190080 )
+
+ AS2( mov edi, ecx )
+ AS2( shr edi, 16 )
+ AS2( and edi, 255 )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and esi, 16711680 )
+ AS2( xor edx, esi )
+
+ AS2( movzx esi, bh )
+ AS2( mov edi, DWORD PTR [ebp + 4096 + esi*4] )
+ AS2( and edi, 65280 )
+ AS2( xor edx, edi )
+
+ AS2( movzx edi, al )
+ AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] )
+ AS2( and esi, 255 )
+ AS2( xor edx, esi )
+
+
+ // xOr
+ AS2( movd esi, mm6 ) // rk
+ AS2( add esi, 16 )
+
+ AS2( movd eax, mm0 )
+ AS2( movd ebx, mm1 )
+ AS2( movd ecx, mm2 )
+
+ AS2( xor eax, DWORD PTR [esi] )
+ AS2( xor ebx, DWORD PTR [esi + 4] )
+ AS2( xor ecx, DWORD PTR [esi + 8] )
+ AS2( xor edx, DWORD PTR [esi + 12] )
+
+ // end
+ AS2( movd ebp, mm7 )
+
+ // swap
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ // store
+ #ifdef __GNUC__
+ AS2( mov esi, DWORD PTR [ebp + 16] ) // outBlock
+ #else
+ AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock
+ #endif
+ AS2( mov DWORD PTR [esi], eax )
+ AS2( mov DWORD PTR [esi + 4], ebx )
+ AS2( mov DWORD PTR [esi + 8], ecx )
+ AS2( mov DWORD PTR [esi + 12], edx )
+
+
+ EPILOG()
+}
+
+
+
+#endif // defined(DO_AES_ASM)
+
+
+
+const word32 AES::Te[5][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,
+},
+{
+ 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,
+},
+{
+ 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,
+},
+{
+ 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,
+},
+{
+ 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::Td[5][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,
+},
+{
+ 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,
+},
+{
+ 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,
+},
+{
+ 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,
+},
+{
+ 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::Te0 = AES::Te[0];
+const word32* AES::Te1 = AES::Te[1];
+const word32* AES::Te2 = AES::Te[2];
+const word32* AES::Te3 = AES::Te[3];
+const word32* AES::Te4 = AES::Te[4];
+
+const word32* AES::Td0 = AES::Td[0];
+const word32* AES::Td1 = AES::Td[1];
+const word32* AES::Td2 = AES::Td[2];
+const word32* AES::Td3 = AES::Td[3];
+const word32* AES::Td4 = AES::Td[4];
+
+
} // namespace
diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp
index 7ba25bc9ffb..af9924703ef 100644
--- a/extra/yassl/taocrypt/src/aestables.cpp
+++ b/extra/yassl/taocrypt/src/aestables.cpp
@@ -28,689 +28,6 @@
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,
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
index 8f4ce051a43..9c485609dd0 100644
--- a/extra/yassl/taocrypt/src/algebra.cpp
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -20,6 +20,8 @@
*/
/* based on Wei Dai's algebra.cpp from CryptoPP */
+#undef NDEBUG
+#define DEBUG // GCC 4.0 bug if NDEBUG and Optimize > 1
#include "runtime.hpp"
#include "algebra.hpp"
diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp
index 1e521b48f0c..6d1c4d4e3a6 100644
--- a/extra/yassl/taocrypt/src/arc4.cpp
+++ b/extra/yassl/taocrypt/src/arc4.cpp
@@ -25,6 +25,11 @@
#include "arc4.hpp"
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_ARC4_ASM
+#endif
+
+
namespace TaoCrypt {
void ARC4::SetKey(const byte* key, word32 length)
@@ -71,6 +76,8 @@ inline unsigned int MakeByte(word32& x, word32& y, byte* s)
} // namespace
+#ifndef DO_ARC4_ASM
+
void ARC4::Process(byte* out, const byte* in, word32 length)
{
if (length == 0) return;
@@ -89,5 +96,134 @@ void ARC4::Process(byte* out, const byte* in, word32 length)
y_ = y;
}
+#else // DO_ARC4_ASM
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void ARC4::Process(byte* out, const byte* in, word32 length)
+{
+#ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov edi, DWORD PTR [ebp + 12] ) \
+ AS2( mov esi, DWORD PTR [ebp + 16] ) \
+ AS2( mov ebp, DWORD PTR [ebp + 20] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( mov esp, ebp ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+#else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, DWORD PTR [ebp + 8] ) \
+ AS2( mov esi, DWORD PTR [ebp + 12] ) \
+ AS2( mov ebp, DWORD PTR [ebp + 16] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 12 )
+
+#endif
+
+ PROLOG()
+
+ AS2( sub esp, 4 ) // make room
+
+ AS2( cmp ebp, 0 )
+ AS1( jz nothing )
+
+ AS2( mov [esp], ebp ) // length
+
+ AS2( movzx edx, BYTE PTR [ecx + 1] ) // y
+ AS2( lea ebp, [ecx + 2] ) // state_
+ AS2( movzx ecx, BYTE PTR [ecx] ) // x
+
+ // setup loop
+ // a = s[x];
+ AS2( movzx eax, BYTE PTR [ebp + ecx] )
+
+
+AS1( begin: )
+
+ // y = (y+a) & 0xff;
+ AS2( add edx, eax )
+ AS2( and edx, 255 )
+
+ // b = s[y];
+ AS2( movzx ebx, BYTE PTR [ebp + edx] )
+
+ // s[x] = b;
+ AS2( mov [ebp + ecx], bl )
+
+ // s[y] = a;
+ AS2( mov [ebp + edx], al )
+
+ // x = (x+1) & 0xff;
+ AS1( inc ecx )
+ AS2( and ecx, 255 )
+
+ //return s[(a+b) & 0xff];
+ AS2( add eax, ebx )
+ AS2( and eax, 255 )
+
+ AS2( movzx ebx, BYTE PTR [ebp + eax] )
+
+ // a = s[x]; for next round
+ AS2( movzx eax, BYTE PTR [ebp + ecx] )
+
+ // xOr w/ inByte
+ AS2( xor bl, BYTE PTR [esi] )
+ AS1( inc esi )
+
+ // write to outByte
+ AS2( mov [edi], bl )
+ AS1( inc edi )
+
+ AS1( dec DWORD PTR [esp] )
+ AS1( jnz begin )
+
+
+ // write back to x_ and y_
+ AS2( mov [ebp - 2], cl )
+ AS2( mov [ebp - 1], dl )
+
+
+AS1( nothing: )
+
+
+ EPILOG()
+}
+
+#endif // DO_ARC4_ASM
+
} // namespace
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index 8f8d2ba52da..383fe65dea6 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -186,7 +186,7 @@ PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0)
void PublicKey::SetSize(word32 s)
{
sz_ = s;
- key_ = new (tc) byte[sz_];
+ key_ = NEW_TC byte[sz_];
}
@@ -198,7 +198,7 @@ void PublicKey::SetKey(const byte* k)
void PublicKey::AddToEnd(const byte* data, word32 len)
{
- mySTL::auto_ptr<byte> tmp(new (tc) byte[sz_ + len], tcArrayDelete);
+ mySTL::auto_ptr<byte> tmp(NEW_TC byte[sz_ + len], tcArrayDelete);
memcpy(tmp.get(), key_, sz_);
memcpy(tmp.get() + sz_, data, len);
@@ -213,21 +213,17 @@ void PublicKey::AddToEnd(const byte* data, word32 len)
Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h)
- : key_(k, kSz), name_(0)
+ : key_(k, kSz)
{
- 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_);
}
@@ -421,19 +417,22 @@ void DH_Decoder::Decode(DH& key)
}
-CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers)
+CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers,
+ bool noVerify, CertType ct)
: BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
- signature_(0), issuer_(0), subject_(0)
+ signature_(0), verify_(!noVerify)
{
+ issuer_[0] = 0;
+ subject_[0] = 0;
+
if (decode)
- Decode(signers);
+ Decode(signers, ct);
+
}
CertDecoder::~CertDecoder()
{
- tcArrayDelete(subject_);
- tcArrayDelete(issuer_);
tcArrayDelete(signature_);
}
@@ -455,7 +454,7 @@ void CertDecoder::ReadHeader()
// Decode a x509v3 Certificate
-void CertDecoder::Decode(SignerList* signers)
+void CertDecoder::Decode(SignerList* signers, CertType ct)
{
if (source_.GetError().What()) return;
DecodeToKey();
@@ -473,12 +472,16 @@ void CertDecoder::Decode(SignerList* signers)
return;
}
+ if (ct == CA) {
if ( memcmp(issuerHash_, subjectHash_, SHA::DIGEST_SIZE) == 0 ) {
- if (!ValidateSelfSignature())
+ if (!ValidateSelfSignature() && verify_)
source_.SetError(SIG_CONFIRM_E);
}
else
- if (!ValidateSignature(signers))
+ if (!ValidateSignature(signers) && verify_)
+ source_.SetError(SIG_OTHER_E);
+ }
+ else if (!ValidateSignature(signers) && verify_)
source_.SetError(SIG_OTHER_E);
}
@@ -631,7 +634,7 @@ word32 CertDecoder::GetSignature()
}
sigLength_--;
- signature_ = new (tc) byte[sigLength_];
+ signature_ = NEW_TC byte[sigLength_];
memcpy(signature_, source_.get_current(), sigLength_);
source_.advance(sigLength_);
@@ -652,7 +655,7 @@ word32 CertDecoder::GetDigest()
sigLength_ = GetLength(source_);
- signature_ = new (tc) byte[sigLength_];
+ signature_ = NEW_TC byte[sigLength_];
memcpy(signature_, source_.get_current(), sigLength_);
source_.advance(sigLength_);
@@ -667,8 +670,12 @@ void CertDecoder::GetName(NameType nt)
SHA sha;
word32 length = GetSequence(); // length of all distinguished names
+ assert (length < NAME_MAX);
length += source_.get_index();
+ char* ptr = (nt == ISSUER) ? issuer_ : subject_;
+ word32 idx = 0;
+
while (source_.get_index() < length) {
GetSet();
GetSequence();
@@ -689,13 +696,49 @@ void CertDecoder::GetName(NameType nt)
byte id = source_.next();
b = source_.next(); // strType
word32 strLen = GetLength(source_);
+ bool copy = false;
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;
+ memcpy(&ptr[idx], "/CN=", 4);
+ idx += 4;
+ copy = true;
+ }
+ else if (id == SUR_NAME) {
+ memcpy(&ptr[idx], "/SN=", 4);
+ idx += 4;
+ copy = true;
+ }
+ else if (id == COUNTRY_NAME) {
+ memcpy(&ptr[idx], "/C=", 3);
+ idx += 3;
+ copy = true;
+ }
+ else if (id == LOCALITY_NAME) {
+ memcpy(&ptr[idx], "/L=", 3);
+ idx += 3;
+ copy = true;
+ }
+ else if (id == STATE_NAME) {
+ memcpy(&ptr[idx], "/ST=", 4);
+ idx += 4;
+ copy = true;
}
+ else if (id == ORG_NAME) {
+ memcpy(&ptr[idx], "/O=", 3);
+ idx += 3;
+ copy = true;
+ }
+ else if (id == ORGUNIT_NAME) {
+ memcpy(&ptr[idx], "/OU=", 4);
+ idx += 4;
+ copy = true;
+ }
+
+ if (copy) {
+ memcpy(&ptr[idx], source_.get_current(), strLen);
+ idx += strLen;
+ }
+
sha.Update(source_.get_current(), strLen);
source_.advance(strLen);
}
@@ -706,6 +749,8 @@ void CertDecoder::GetName(NameType nt)
source_.advance(length);
}
}
+ ptr[idx++] = 0;
+
if (nt == ISSUER)
sha.Final(issuerHash_);
else
@@ -734,11 +779,21 @@ void CertDecoder::GetDate(DateType dt)
memcpy(date, source_.get_current(), length);
source_.advance(length);
- if (!ValidateDate(date, b, dt))
+ if (!ValidateDate(date, b, dt) && verify_)
if (dt == BEFORE)
source_.SetError(BEFORE_DATE_E);
else
source_.SetError(AFTER_DATE_E);
+
+ // save for later use
+ if (dt == BEFORE) {
+ memcpy(beforeDate_, date, length);
+ beforeDate_[length] = 0;
+ }
+ else { // after
+ memcpy(afterDate_, date, length);
+ afterDate_[length] = 0;
+ }
}
@@ -802,22 +857,22 @@ bool CertDecoder::ValidateSignature(SignerList* signers)
}
-// RSA confirm
+// confirm certificate signature
bool CertDecoder::ConfirmSignature(Source& pub)
{
HashType ht;
mySTL::auto_ptr<HASH> hasher(tcDelete);
if (signatureOID_ == MD5wRSA) {
- hasher.reset(new (tc) MD5);
+ hasher.reset(NEW_TC MD5);
ht = MD5h;
}
else if (signatureOID_ == MD2wRSA) {
- hasher.reset(new (tc) MD2);
+ hasher.reset(NEW_TC MD2);
ht = MD2h;
}
else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) {
- hasher.reset(new (tc) SHA);
+ hasher.reset(NEW_TC SHA);
ht = SHAh;
}
else {
diff --git a/extra/yassl/taocrypt/src/bftables.cpp b/extra/yassl/taocrypt/src/bftables.cpp
new file mode 100644
index 00000000000..e072b117f54
--- /dev/null
+++ b/extra/yassl/taocrypt/src/bftables.cpp
@@ -0,0 +1,306 @@
+/* bftables.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 bfinit.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "blowfish.hpp"
+
+
+namespace TaoCrypt {
+
+const word32 Blowfish::p_init_[Blowfish::ROUNDS+2] =
+{
+ 608135816U, 2242054355U, 320440878U, 57701188U,
+ 2752067618U, 698298832U, 137296536U, 3964562569U,
+ 1160258022U, 953160567U, 3193202383U, 887688300U,
+ 3232508343U, 3380367581U, 1065670069U, 3041331479U,
+ 2450970073U, 2306472731U
+} ;
+
+
+const word32 Blowfish::s_init_[4*256] = {
+ 3509652390U, 2564797868U, 805139163U, 3491422135U,
+ 3101798381U, 1780907670U, 3128725573U, 4046225305U,
+ 614570311U, 3012652279U, 134345442U, 2240740374U,
+ 1667834072U, 1901547113U, 2757295779U, 4103290238U,
+ 227898511U, 1921955416U, 1904987480U, 2182433518U,
+ 2069144605U, 3260701109U, 2620446009U, 720527379U,
+ 3318853667U, 677414384U, 3393288472U, 3101374703U,
+ 2390351024U, 1614419982U, 1822297739U, 2954791486U,
+ 3608508353U, 3174124327U, 2024746970U, 1432378464U,
+ 3864339955U, 2857741204U, 1464375394U, 1676153920U,
+ 1439316330U, 715854006U, 3033291828U, 289532110U,
+ 2706671279U, 2087905683U, 3018724369U, 1668267050U,
+ 732546397U, 1947742710U, 3462151702U, 2609353502U,
+ 2950085171U, 1814351708U, 2050118529U, 680887927U,
+ 999245976U, 1800124847U, 3300911131U, 1713906067U,
+ 1641548236U, 4213287313U, 1216130144U, 1575780402U,
+ 4018429277U, 3917837745U, 3693486850U, 3949271944U,
+ 596196993U, 3549867205U, 258830323U, 2213823033U,
+ 772490370U, 2760122372U, 1774776394U, 2652871518U,
+ 566650946U, 4142492826U, 1728879713U, 2882767088U,
+ 1783734482U, 3629395816U, 2517608232U, 2874225571U,
+ 1861159788U, 326777828U, 3124490320U, 2130389656U,
+ 2716951837U, 967770486U, 1724537150U, 2185432712U,
+ 2364442137U, 1164943284U, 2105845187U, 998989502U,
+ 3765401048U, 2244026483U, 1075463327U, 1455516326U,
+ 1322494562U, 910128902U, 469688178U, 1117454909U,
+ 936433444U, 3490320968U, 3675253459U, 1240580251U,
+ 122909385U, 2157517691U, 634681816U, 4142456567U,
+ 3825094682U, 3061402683U, 2540495037U, 79693498U,
+ 3249098678U, 1084186820U, 1583128258U, 426386531U,
+ 1761308591U, 1047286709U, 322548459U, 995290223U,
+ 1845252383U, 2603652396U, 3431023940U, 2942221577U,
+ 3202600964U, 3727903485U, 1712269319U, 422464435U,
+ 3234572375U, 1170764815U, 3523960633U, 3117677531U,
+ 1434042557U, 442511882U, 3600875718U, 1076654713U,
+ 1738483198U, 4213154764U, 2393238008U, 3677496056U,
+ 1014306527U, 4251020053U, 793779912U, 2902807211U,
+ 842905082U, 4246964064U, 1395751752U, 1040244610U,
+ 2656851899U, 3396308128U, 445077038U, 3742853595U,
+ 3577915638U, 679411651U, 2892444358U, 2354009459U,
+ 1767581616U, 3150600392U, 3791627101U, 3102740896U,
+ 284835224U, 4246832056U, 1258075500U, 768725851U,
+ 2589189241U, 3069724005U, 3532540348U, 1274779536U,
+ 3789419226U, 2764799539U, 1660621633U, 3471099624U,
+ 4011903706U, 913787905U, 3497959166U, 737222580U,
+ 2514213453U, 2928710040U, 3937242737U, 1804850592U,
+ 3499020752U, 2949064160U, 2386320175U, 2390070455U,
+ 2415321851U, 4061277028U, 2290661394U, 2416832540U,
+ 1336762016U, 1754252060U, 3520065937U, 3014181293U,
+ 791618072U, 3188594551U, 3933548030U, 2332172193U,
+ 3852520463U, 3043980520U, 413987798U, 3465142937U,
+ 3030929376U, 4245938359U, 2093235073U, 3534596313U,
+ 375366246U, 2157278981U, 2479649556U, 555357303U,
+ 3870105701U, 2008414854U, 3344188149U, 4221384143U,
+ 3956125452U, 2067696032U, 3594591187U, 2921233993U,
+ 2428461U, 544322398U, 577241275U, 1471733935U,
+ 610547355U, 4027169054U, 1432588573U, 1507829418U,
+ 2025931657U, 3646575487U, 545086370U, 48609733U,
+ 2200306550U, 1653985193U, 298326376U, 1316178497U,
+ 3007786442U, 2064951626U, 458293330U, 2589141269U,
+ 3591329599U, 3164325604U, 727753846U, 2179363840U,
+ 146436021U, 1461446943U, 4069977195U, 705550613U,
+ 3059967265U, 3887724982U, 4281599278U, 3313849956U,
+ 1404054877U, 2845806497U, 146425753U, 1854211946U,
+
+ 1266315497U, 3048417604U, 3681880366U, 3289982499U,
+ 2909710000U, 1235738493U, 2632868024U, 2414719590U,
+ 3970600049U, 1771706367U, 1449415276U, 3266420449U,
+ 422970021U, 1963543593U, 2690192192U, 3826793022U,
+ 1062508698U, 1531092325U, 1804592342U, 2583117782U,
+ 2714934279U, 4024971509U, 1294809318U, 4028980673U,
+ 1289560198U, 2221992742U, 1669523910U, 35572830U,
+ 157838143U, 1052438473U, 1016535060U, 1802137761U,
+ 1753167236U, 1386275462U, 3080475397U, 2857371447U,
+ 1040679964U, 2145300060U, 2390574316U, 1461121720U,
+ 2956646967U, 4031777805U, 4028374788U, 33600511U,
+ 2920084762U, 1018524850U, 629373528U, 3691585981U,
+ 3515945977U, 2091462646U, 2486323059U, 586499841U,
+ 988145025U, 935516892U, 3367335476U, 2599673255U,
+ 2839830854U, 265290510U, 3972581182U, 2759138881U,
+ 3795373465U, 1005194799U, 847297441U, 406762289U,
+ 1314163512U, 1332590856U, 1866599683U, 4127851711U,
+ 750260880U, 613907577U, 1450815602U, 3165620655U,
+ 3734664991U, 3650291728U, 3012275730U, 3704569646U,
+ 1427272223U, 778793252U, 1343938022U, 2676280711U,
+ 2052605720U, 1946737175U, 3164576444U, 3914038668U,
+ 3967478842U, 3682934266U, 1661551462U, 3294938066U,
+ 4011595847U, 840292616U, 3712170807U, 616741398U,
+ 312560963U, 711312465U, 1351876610U, 322626781U,
+ 1910503582U, 271666773U, 2175563734U, 1594956187U,
+ 70604529U, 3617834859U, 1007753275U, 1495573769U,
+ 4069517037U, 2549218298U, 2663038764U, 504708206U,
+ 2263041392U, 3941167025U, 2249088522U, 1514023603U,
+ 1998579484U, 1312622330U, 694541497U, 2582060303U,
+ 2151582166U, 1382467621U, 776784248U, 2618340202U,
+ 3323268794U, 2497899128U, 2784771155U, 503983604U,
+ 4076293799U, 907881277U, 423175695U, 432175456U,
+ 1378068232U, 4145222326U, 3954048622U, 3938656102U,
+ 3820766613U, 2793130115U, 2977904593U, 26017576U,
+ 3274890735U, 3194772133U, 1700274565U, 1756076034U,
+ 4006520079U, 3677328699U, 720338349U, 1533947780U,
+ 354530856U, 688349552U, 3973924725U, 1637815568U,
+ 332179504U, 3949051286U, 53804574U, 2852348879U,
+ 3044236432U, 1282449977U, 3583942155U, 3416972820U,
+ 4006381244U, 1617046695U, 2628476075U, 3002303598U,
+ 1686838959U, 431878346U, 2686675385U, 1700445008U,
+ 1080580658U, 1009431731U, 832498133U, 3223435511U,
+ 2605976345U, 2271191193U, 2516031870U, 1648197032U,
+ 4164389018U, 2548247927U, 300782431U, 375919233U,
+ 238389289U, 3353747414U, 2531188641U, 2019080857U,
+ 1475708069U, 455242339U, 2609103871U, 448939670U,
+ 3451063019U, 1395535956U, 2413381860U, 1841049896U,
+ 1491858159U, 885456874U, 4264095073U, 4001119347U,
+ 1565136089U, 3898914787U, 1108368660U, 540939232U,
+ 1173283510U, 2745871338U, 3681308437U, 4207628240U,
+ 3343053890U, 4016749493U, 1699691293U, 1103962373U,
+ 3625875870U, 2256883143U, 3830138730U, 1031889488U,
+ 3479347698U, 1535977030U, 4236805024U, 3251091107U,
+ 2132092099U, 1774941330U, 1199868427U, 1452454533U,
+ 157007616U, 2904115357U, 342012276U, 595725824U,
+ 1480756522U, 206960106U, 497939518U, 591360097U,
+ 863170706U, 2375253569U, 3596610801U, 1814182875U,
+ 2094937945U, 3421402208U, 1082520231U, 3463918190U,
+ 2785509508U, 435703966U, 3908032597U, 1641649973U,
+ 2842273706U, 3305899714U, 1510255612U, 2148256476U,
+ 2655287854U, 3276092548U, 4258621189U, 236887753U,
+ 3681803219U, 274041037U, 1734335097U, 3815195456U,
+ 3317970021U, 1899903192U, 1026095262U, 4050517792U,
+ 356393447U, 2410691914U, 3873677099U, 3682840055U,
+
+ 3913112168U, 2491498743U, 4132185628U, 2489919796U,
+ 1091903735U, 1979897079U, 3170134830U, 3567386728U,
+ 3557303409U, 857797738U, 1136121015U, 1342202287U,
+ 507115054U, 2535736646U, 337727348U, 3213592640U,
+ 1301675037U, 2528481711U, 1895095763U, 1721773893U,
+ 3216771564U, 62756741U, 2142006736U, 835421444U,
+ 2531993523U, 1442658625U, 3659876326U, 2882144922U,
+ 676362277U, 1392781812U, 170690266U, 3921047035U,
+ 1759253602U, 3611846912U, 1745797284U, 664899054U,
+ 1329594018U, 3901205900U, 3045908486U, 2062866102U,
+ 2865634940U, 3543621612U, 3464012697U, 1080764994U,
+ 553557557U, 3656615353U, 3996768171U, 991055499U,
+ 499776247U, 1265440854U, 648242737U, 3940784050U,
+ 980351604U, 3713745714U, 1749149687U, 3396870395U,
+ 4211799374U, 3640570775U, 1161844396U, 3125318951U,
+ 1431517754U, 545492359U, 4268468663U, 3499529547U,
+ 1437099964U, 2702547544U, 3433638243U, 2581715763U,
+ 2787789398U, 1060185593U, 1593081372U, 2418618748U,
+ 4260947970U, 69676912U, 2159744348U, 86519011U,
+ 2512459080U, 3838209314U, 1220612927U, 3339683548U,
+ 133810670U, 1090789135U, 1078426020U, 1569222167U,
+ 845107691U, 3583754449U, 4072456591U, 1091646820U,
+ 628848692U, 1613405280U, 3757631651U, 526609435U,
+ 236106946U, 48312990U, 2942717905U, 3402727701U,
+ 1797494240U, 859738849U, 992217954U, 4005476642U,
+ 2243076622U, 3870952857U, 3732016268U, 765654824U,
+ 3490871365U, 2511836413U, 1685915746U, 3888969200U,
+ 1414112111U, 2273134842U, 3281911079U, 4080962846U,
+ 172450625U, 2569994100U, 980381355U, 4109958455U,
+ 2819808352U, 2716589560U, 2568741196U, 3681446669U,
+ 3329971472U, 1835478071U, 660984891U, 3704678404U,
+ 4045999559U, 3422617507U, 3040415634U, 1762651403U,
+ 1719377915U, 3470491036U, 2693910283U, 3642056355U,
+ 3138596744U, 1364962596U, 2073328063U, 1983633131U,
+ 926494387U, 3423689081U, 2150032023U, 4096667949U,
+ 1749200295U, 3328846651U, 309677260U, 2016342300U,
+ 1779581495U, 3079819751U, 111262694U, 1274766160U,
+ 443224088U, 298511866U, 1025883608U, 3806446537U,
+ 1145181785U, 168956806U, 3641502830U, 3584813610U,
+ 1689216846U, 3666258015U, 3200248200U, 1692713982U,
+ 2646376535U, 4042768518U, 1618508792U, 1610833997U,
+ 3523052358U, 4130873264U, 2001055236U, 3610705100U,
+ 2202168115U, 4028541809U, 2961195399U, 1006657119U,
+ 2006996926U, 3186142756U, 1430667929U, 3210227297U,
+ 1314452623U, 4074634658U, 4101304120U, 2273951170U,
+ 1399257539U, 3367210612U, 3027628629U, 1190975929U,
+ 2062231137U, 2333990788U, 2221543033U, 2438960610U,
+ 1181637006U, 548689776U, 2362791313U, 3372408396U,
+ 3104550113U, 3145860560U, 296247880U, 1970579870U,
+ 3078560182U, 3769228297U, 1714227617U, 3291629107U,
+ 3898220290U, 166772364U, 1251581989U, 493813264U,
+ 448347421U, 195405023U, 2709975567U, 677966185U,
+ 3703036547U, 1463355134U, 2715995803U, 1338867538U,
+ 1343315457U, 2802222074U, 2684532164U, 233230375U,
+ 2599980071U, 2000651841U, 3277868038U, 1638401717U,
+ 4028070440U, 3237316320U, 6314154U, 819756386U,
+ 300326615U, 590932579U, 1405279636U, 3267499572U,
+ 3150704214U, 2428286686U, 3959192993U, 3461946742U,
+ 1862657033U, 1266418056U, 963775037U, 2089974820U,
+ 2263052895U, 1917689273U, 448879540U, 3550394620U,
+ 3981727096U, 150775221U, 3627908307U, 1303187396U,
+ 508620638U, 2975983352U, 2726630617U, 1817252668U,
+ 1876281319U, 1457606340U, 908771278U, 3720792119U,
+ 3617206836U, 2455994898U, 1729034894U, 1080033504U,
+
+ 976866871U, 3556439503U, 2881648439U, 1522871579U,
+ 1555064734U, 1336096578U, 3548522304U, 2579274686U,
+ 3574697629U, 3205460757U, 3593280638U, 3338716283U,
+ 3079412587U, 564236357U, 2993598910U, 1781952180U,
+ 1464380207U, 3163844217U, 3332601554U, 1699332808U,
+ 1393555694U, 1183702653U, 3581086237U, 1288719814U,
+ 691649499U, 2847557200U, 2895455976U, 3193889540U,
+ 2717570544U, 1781354906U, 1676643554U, 2592534050U,
+ 3230253752U, 1126444790U, 2770207658U, 2633158820U,
+ 2210423226U, 2615765581U, 2414155088U, 3127139286U,
+ 673620729U, 2805611233U, 1269405062U, 4015350505U,
+ 3341807571U, 4149409754U, 1057255273U, 2012875353U,
+ 2162469141U, 2276492801U, 2601117357U, 993977747U,
+ 3918593370U, 2654263191U, 753973209U, 36408145U,
+ 2530585658U, 25011837U, 3520020182U, 2088578344U,
+ 530523599U, 2918365339U, 1524020338U, 1518925132U,
+ 3760827505U, 3759777254U, 1202760957U, 3985898139U,
+ 3906192525U, 674977740U, 4174734889U, 2031300136U,
+ 2019492241U, 3983892565U, 4153806404U, 3822280332U,
+ 352677332U, 2297720250U, 60907813U, 90501309U,
+ 3286998549U, 1016092578U, 2535922412U, 2839152426U,
+ 457141659U, 509813237U, 4120667899U, 652014361U,
+ 1966332200U, 2975202805U, 55981186U, 2327461051U,
+ 676427537U, 3255491064U, 2882294119U, 3433927263U,
+ 1307055953U, 942726286U, 933058658U, 2468411793U,
+ 3933900994U, 4215176142U, 1361170020U, 2001714738U,
+ 2830558078U, 3274259782U, 1222529897U, 1679025792U,
+ 2729314320U, 3714953764U, 1770335741U, 151462246U,
+ 3013232138U, 1682292957U, 1483529935U, 471910574U,
+ 1539241949U, 458788160U, 3436315007U, 1807016891U,
+ 3718408830U, 978976581U, 1043663428U, 3165965781U,
+ 1927990952U, 4200891579U, 2372276910U, 3208408903U,
+ 3533431907U, 1412390302U, 2931980059U, 4132332400U,
+ 1947078029U, 3881505623U, 4168226417U, 2941484381U,
+ 1077988104U, 1320477388U, 886195818U, 18198404U,
+ 3786409000U, 2509781533U, 112762804U, 3463356488U,
+ 1866414978U, 891333506U, 18488651U, 661792760U,
+ 1628790961U, 3885187036U, 3141171499U, 876946877U,
+ 2693282273U, 1372485963U, 791857591U, 2686433993U,
+ 3759982718U, 3167212022U, 3472953795U, 2716379847U,
+ 445679433U, 3561995674U, 3504004811U, 3574258232U,
+ 54117162U, 3331405415U, 2381918588U, 3769707343U,
+ 4154350007U, 1140177722U, 4074052095U, 668550556U,
+ 3214352940U, 367459370U, 261225585U, 2610173221U,
+ 4209349473U, 3468074219U, 3265815641U, 314222801U,
+ 3066103646U, 3808782860U, 282218597U, 3406013506U,
+ 3773591054U, 379116347U, 1285071038U, 846784868U,
+ 2669647154U, 3771962079U, 3550491691U, 2305946142U,
+ 453669953U, 1268987020U, 3317592352U, 3279303384U,
+ 3744833421U, 2610507566U, 3859509063U, 266596637U,
+ 3847019092U, 517658769U, 3462560207U, 3443424879U,
+ 370717030U, 4247526661U, 2224018117U, 4143653529U,
+ 4112773975U, 2788324899U, 2477274417U, 1456262402U,
+ 2901442914U, 1517677493U, 1846949527U, 2295493580U,
+ 3734397586U, 2176403920U, 1280348187U, 1908823572U,
+ 3871786941U, 846861322U, 1172426758U, 3287448474U,
+ 3383383037U, 1655181056U, 3139813346U, 901632758U,
+ 1897031941U, 2986607138U, 3066810236U, 3447102507U,
+ 1393639104U, 373351379U, 950779232U, 625454576U,
+ 3124240540U, 4148612726U, 2007998917U, 544563296U,
+ 2244738638U, 2330496472U, 2058025392U, 1291430526U,
+ 424198748U, 50039436U, 29584100U, 3605783033U,
+ 2429876329U, 2791104160U, 1057563949U, 3255363231U,
+ 3075367218U, 3463963227U, 1469046755U, 985887462U
+};
+
+
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp
new file mode 100644
index 00000000000..16e2277dc10
--- /dev/null
+++ b/extra/yassl/taocrypt/src/blowfish.cpp
@@ -0,0 +1,358 @@
+/* blowfish.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
+ */
+
+/* C++ code based on Wei Dai's blowfish.cpp from CryptoPP */
+/* x86 asm is original */
+
+
+#if defined(TAOCRYPT_KERNEL_MODE)
+ #define DO_TAOCRYPT_KERNEL_MODE
+#endif // only some modules now support this
+
+
+#include "runtime.hpp"
+#include "blowfish.hpp"
+
+
+
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_BLOWFISH_ASM
+#endif
+
+
+
+namespace TaoCrypt {
+
+
+#if !defined(DO_BLOWFISH_ASM)
+
+// Generic Version
+void Blowfish::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);
+}
+
+#else
+
+// ia32 optimized version
+void Blowfish::Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ if (mode_ == ECB)
+ while (blocks--) {
+ AsmProcess(in, out);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ while (blocks--) {
+ r_[0] ^= *(word32*)in;
+ r_[1] ^= *(word32*)(in + 4);
+
+ AsmProcess((byte*)r_, (byte*)r_);
+
+ memcpy(out, r_, BLOCK_SIZE);
+
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else
+ while (blocks--) {
+ AsmProcess(in, out);
+
+ *(word32*)out ^= r_[0];
+ *(word32*)(out + 4) ^= r_[1];
+
+ memcpy(r_, in, BLOCK_SIZE);
+
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+#endif // DO_BLOWFISH_ASM
+
+
+void Blowfish::SetKey(const byte* key_string, word32 keylength, CipherDir dir)
+{
+ assert(keylength >= 4 && keylength <= 56);
+
+ unsigned i, j=0, k;
+ word32 data, dspace[2] = {0, 0};
+
+ memcpy(pbox_, p_init_, sizeof(p_init_));
+ memcpy(sbox_, s_init_, sizeof(s_init_));
+
+ // Xor key string into encryption key vector
+ for (i=0 ; i<ROUNDS+2 ; ++i) {
+ data = 0;
+ for (k=0 ; k<4 ; ++k )
+ data = (data << 8) | key_string[j++ % keylength];
+ pbox_[i] ^= data;
+ }
+
+ crypt_block(dspace, pbox_);
+
+ for (i=0; i<ROUNDS; i+=2)
+ crypt_block(pbox_ + i, pbox_ + i + 2);
+
+ crypt_block(pbox_ + ROUNDS, sbox_);
+
+ for (i=0; i < 4*256-2; i+=2)
+ crypt_block(sbox_ + i, sbox_ + i + 2);
+
+ if (dir==DECRYPTION)
+ for (i=0; i<(ROUNDS+2)/2; i++)
+ mySTL::swap(pbox_[i], pbox_[ROUNDS+1-i]);
+}
+
+
+#define BFBYTE_0(x) ( x &0xFF)
+#define BFBYTE_1(x) ((x>> 8)&0xFF)
+#define BFBYTE_2(x) ((x>>16)&0xFF)
+#define BFBYTE_3(x) ( x>>24)
+
+
+#define BF_S(Put, Get, I) (\
+ Put ^= p[I], \
+ tmp = p[18 + BFBYTE_3(Get)], \
+ tmp += p[274+ BFBYTE_2(Get)], \
+ tmp ^= p[530+ BFBYTE_1(Get)], \
+ tmp += p[786+ BFBYTE_0(Get)], \
+ Put ^= tmp \
+ )
+
+
+#define BF_ROUNDS \
+ BF_S(right, left, 1); \
+ BF_S(left, right, 2); \
+ BF_S(right, left, 3); \
+ BF_S(left, right, 4); \
+ BF_S(right, left, 5); \
+ BF_S(left, right, 6); \
+ BF_S(right, left, 7); \
+ BF_S(left, right, 8); \
+ BF_S(right, left, 9); \
+ BF_S(left, right, 10); \
+ BF_S(right, left, 11); \
+ BF_S(left, right, 12); \
+ BF_S(right, left, 13); \
+ BF_S(left, right, 14); \
+ BF_S(right, left, 15); \
+ BF_S(left, right, 16);
+
+#define BF_EXTRA_ROUNDS \
+ BF_S(right, left, 17); \
+ BF_S(left, right, 18); \
+ BF_S(right, left, 19); \
+ BF_S(left, right, 20);
+
+
+// Used by key setup, no byte swapping
+void Blowfish::crypt_block(const word32 in[2], word32 out[2]) const
+{
+ word32 left = in[0];
+ word32 right = in[1];
+
+ const word32* p = pbox_;
+ word32 tmp;
+
+ left ^= p[0];
+
+ BF_ROUNDS
+
+#if ROUNDS == 20
+ BF_EXTRA_ROUNDS
+#endif
+
+ right ^= p[ROUNDS + 1];
+
+ out[0] = right;
+ out[1] = left;
+}
+
+
+typedef BlockGetAndPut<word32, BigEndian> gpBlock;
+
+void Blowfish::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out)
+ const
+{
+ word32 tmp, left, right;
+ const word32* p = pbox_;
+
+ gpBlock::Get(in)(left)(right);
+ left ^= p[0];
+
+ BF_ROUNDS
+
+#if ROUNDS == 20
+ BF_EXTRA_ROUNDS
+#endif
+
+ right ^= p[ROUNDS + 1];
+
+ gpBlock::Put(xOr, out)(right)(left);
+}
+
+
+#if defined(DO_BLOWFISH_ASM)
+ #ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov esi, DWORD PTR [ebp + 12] )
+
+ #define EPILOG() \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+ #else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( mov esi, DWORD PTR [ebp + 8] )
+
+ #define EPILOG() \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 8 )
+
+ #endif
+
+
+#define BF_ROUND(P, G, I) \
+ /* Put ^= p[I] */ \
+ AS2( xor P, [edi + I*4] ) \
+ /* tmp = p[18 + BFBYTE_3(Get)] */ \
+ AS2( mov ecx, G ) \
+ AS2( shr ecx, 16 ) \
+ AS2( movzx edx, ch ) \
+ AS2( mov esi, [edi + edx*4 + 72] ) \
+ /* tmp += p[274+ BFBYTE_2(Get)] */ \
+ AS2( movzx ecx, cl ) \
+ AS2( add esi, [edi + ecx*4 + 1096] ) \
+ /* tmp ^= p[530+ BFBYTE_1(Get)] */ \
+ AS2( mov ecx, G ) \
+ AS2( movzx edx, ch ) \
+ AS2( xor esi, [edi + edx*4 + 2120] ) \
+ /* tmp += p[786+ BFBYTE_0(Get)] */ \
+ AS2( movzx ecx, cl ) \
+ AS2( add esi, [edi + ecx*4 + 3144] ) \
+ /* Put ^= tmp */ \
+ AS2( xor P, esi )
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void Blowfish::AsmProcess(const byte* inBlock, byte* outBlock) const
+{
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( lea edi, [ecx + 60] ) // pbox
+ #else
+ AS2( lea edi, [ecx + 56] ) // pbox
+ #endif
+
+ AS2( mov eax, DWORD PTR [esi] )
+ AS2( mov edx, DWORD PTR [edi] )
+ AS1( bswap eax )
+
+ AS2( mov ebx, DWORD PTR [esi + 4] )
+ AS2( xor eax, edx ) // left
+ AS1( bswap ebx ) // right
+
+
+ BF_ROUND(ebx, eax, 1)
+ BF_ROUND(eax, ebx, 2)
+ BF_ROUND(ebx, eax, 3)
+ BF_ROUND(eax, ebx, 4)
+ BF_ROUND(ebx, eax, 5)
+ BF_ROUND(eax, ebx, 6)
+ BF_ROUND(ebx, eax, 7)
+ BF_ROUND(eax, ebx, 8)
+ BF_ROUND(ebx, eax, 9)
+ BF_ROUND(eax, ebx, 10)
+ BF_ROUND(ebx, eax, 11)
+ BF_ROUND(eax, ebx, 12)
+ BF_ROUND(ebx, eax, 13)
+ BF_ROUND(eax, ebx, 14)
+ BF_ROUND(ebx, eax, 15)
+ BF_ROUND(eax, ebx, 16)
+ #if ROUNDS == 20
+ BF_ROUND(ebx, eax, 17)
+ BF_ROUND(eax, ebx, 18)
+ BF_ROUND(ebx, eax, 19)
+ BF_ROUND(eax, ebx, 20)
+
+ AS2( xor ebx, [edi + 84] ) // 20 + 1 (x4)
+ #else
+ AS2( xor ebx, [edi + 68] ) // 16 + 1 (x4)
+ #endif
+
+ #ifdef __GNUC__
+ AS2( mov edi, [ebp + 16] ) // outBlock
+ #else
+ AS2( mov edi, [ebp + 12] ) // outBlock
+ #endif
+
+ AS1( bswap ebx )
+ AS1( bswap eax )
+
+ AS2( mov [edi] , ebx )
+ AS2( mov [edi + 4], eax )
+
+ EPILOG()
+}
+
+
+#endif // DO_BLOWFISH_ASM
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp
index 944a47c288e..01ea399df13 100644
--- a/extra/yassl/taocrypt/src/coding.cpp
+++ b/extra/yassl/taocrypt/src/coding.cpp
@@ -130,7 +130,7 @@ void Base64Encoder::Encode()
word32 outSz = bytes * 4 / 3;
outSz += (outSz % 4); // 4 byte integrals
- outSz += outSz / pemLineSz + ( (outSz % pemLineSz) ? 1 : 0); // new lines
+ outSz += (outSz + pemLineSz - 1) / pemLineSz; // new lines
encoded_.New(outSz);
word32 i = 0;
@@ -187,9 +187,8 @@ void Base64Encoder::Encode()
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);
+ word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz);
+ plainSz = (plainSz * 3 + 3) / 4;
decoded_.New(plainSz);
word32 i = 0;
diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp
index e5d3331500c..d2db4fc939e 100644
--- a/extra/yassl/taocrypt/src/des.cpp
+++ b/extra/yassl/taocrypt/src/des.cpp
@@ -19,14 +19,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-/* based on Wei Dai's des.cpp from CryptoPP */
+/* C++ part based on Wei Dai's des.cpp from CryptoPP */
+/* x86 asm is original */
+
+
+#if defined(TAOCRYPT_KERNEL_MODE)
+ #define DO_TAOCRYPT_KERNEL_MODE
+#endif // only some modules now support this
+
#include "runtime.hpp"
#include "des.hpp"
-#include <string.h>
#include "algorithm.hpp" // mySTL::swap
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_DES_ASM
+#endif
+
+
namespace TaoCrypt {
@@ -67,101 +78,7 @@ 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] = {
+const word32 Spbox[8][64] = {
{
0x01010400,0x00000000,0x00010000,0x01010404,
0x01010004,0x00010404,0x00000004,0x00010000,
@@ -301,8 +218,105 @@ const word32 Spbox[DES::BOXES][DES::BOX_SIZE] = {
};
+void BasicDES::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]);
+ }
+
+}
-void DES::RawProcessBlock(word32& lIn, word32& rIn) const
+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);
+}
+
+
+void BasicDES::RawProcessBlock(word32& lIn, word32& rIn) const
{
word32 l = lIn, r = rIn;
const word32* kptr = k_;
@@ -336,7 +350,7 @@ void DES::RawProcessBlock(word32& lIn, word32& rIn) const
}
-void DES_BASE::Process(byte* out, const byte* in, word32 sz)
+void DES::Process(byte* out, const byte* in, word32 sz)
{
if (mode_ == ECB)
ECB_Process(out, in, sz);
@@ -358,38 +372,24 @@ void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
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];
- }
+ RawProcessBlock(l, r);
FPERM(l,r);
Block::Put(xOr, out)(r)(l);
}
+void DES_EDE2::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 DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir)
{
des1_.SetKey(key, sz, dir);
@@ -403,9 +403,11 @@ void DES_EDE2::ProcessAndXorBlock(const byte* in, const byte* xOr,
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);
}
@@ -418,18 +420,389 @@ void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir)
des3_.SetKey(key+(dir==DECRYPTION?0:2*8), sz, dir);
}
+
+
+#if !defined(DO_DES_ASM)
+
+// Generic Version
+void DES_EDE3::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);
+}
+
+#else
+
+// ia32 optimized version
+void DES_EDE3::Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / DES_BLOCK_SIZE;
+
+ if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ while (blocks--) {
+ r_[0] ^= *(word32*)in;
+ r_[1] ^= *(word32*)(in + 4);
+
+ AsmProcess((byte*)r_, (byte*)r_, (void*)Spbox);
+
+ memcpy(out, r_, DES_BLOCK_SIZE);
+
+ in += DES_BLOCK_SIZE;
+ out += DES_BLOCK_SIZE;
+ }
+ else
+ while (blocks--) {
+ AsmProcess(in, out, (void*)Spbox);
+
+ *(word32*)out ^= r_[0];
+ *(word32*)(out + 4) ^= r_[1];
+
+ memcpy(r_, in, DES_BLOCK_SIZE);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+ else
+ while (blocks--) {
+ AsmProcess(in, out, (void*)Spbox);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+}
+
+#endif // DO_DES_ASM
+
+
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);
}
+#if defined(DO_DES_ASM)
+
+/* Uses IPERM algorithm from above
+
+ left is in eax
+ right is in ebx
+
+ uses ecx
+*/
+#define AsmIPERM() {\
+ AS2( rol ebx, 4 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0xf0f0f0f0 ) \
+ AS2( xor ebx, ecx ) \
+ AS2( xor eax, ecx ) \
+ AS2( ror ebx, 20 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0xffff0000 ) \
+ AS2( xor ebx, ecx ) \
+ AS2( xor eax, ecx ) \
+ AS2( ror ebx, 18 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0x33333333 ) \
+ AS2( xor ebx, ecx ) \
+ AS2( xor eax, ecx ) \
+ AS2( ror ebx, 6 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0x00ff00ff ) \
+ AS2( xor ebx, ecx ) \
+ AS2( xor eax, ecx ) \
+ AS2( rol ebx, 9 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0xaaaaaaaa ) \
+ AS2( xor eax, ecx ) \
+ AS2( rol eax, 1 ) \
+ AS2( xor ebx, ecx ) }
+
+
+/* Uses FPERM algorithm from above
+
+ left is in eax
+ right is in ebx
+
+ uses ecx
+*/
+#define AsmFPERM() {\
+ AS2( ror ebx, 1 ) \
+ AS2( mov ecx, eax ) \
+ AS2( xor ecx, ebx ) \
+ AS2( and ecx, 0xaaaaaaaa ) \
+ AS2( xor eax, ecx ) \
+ AS2( xor ebx, ecx ) \
+ AS2( ror eax, 9 ) \
+ AS2( mov ecx, ebx ) \
+ AS2( xor ecx, eax ) \
+ AS2( and ecx, 0x00ff00ff ) \
+ AS2( xor eax, ecx ) \
+ AS2( xor ebx, ecx ) \
+ AS2( rol eax, 6 ) \
+ AS2( mov ecx, ebx ) \
+ AS2( xor ecx, eax ) \
+ AS2( and ecx, 0x33333333 ) \
+ AS2( xor eax, ecx ) \
+ AS2( xor ebx, ecx ) \
+ AS2( rol eax, 18 ) \
+ AS2( mov ecx, ebx ) \
+ AS2( xor ecx, eax ) \
+ AS2( and ecx, 0xffff0000 ) \
+ AS2( xor eax, ecx ) \
+ AS2( xor ebx, ecx ) \
+ AS2( rol eax, 20 ) \
+ AS2( mov ecx, ebx ) \
+ AS2( xor ecx, eax ) \
+ AS2( and ecx, 0xf0f0f0f0 ) \
+ AS2( xor eax, ecx ) \
+ AS2( xor ebx, ecx ) \
+ AS2( ror eax, 4 ) }
+
+
+
+
+/* DesRound implements this algorithm:
+
+ word32 work = rotrFixed(r, 4U) ^ key[0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ key[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) ^ key[2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ key[3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ left is in aex
+ right is in ebx
+ key is in edx
+
+ edvances key for next round
+
+ uses ecx, esi, and edi
+*/
+#define DesRound() \
+ AS2( mov ecx, ebx )\
+ AS2( mov esi, DWORD PTR [edx] )\
+ AS2( ror ecx, 4 )\
+ AS2( xor ecx, esi )\
+ AS2( and ecx, 0x3f3f3f3f )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor eax, [ebp + esi*4 + 6*256] )\
+ AS2( shr ecx, 16 )\
+ AS2( xor eax, [ebp + edi*4 + 4*256] )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor eax, [ebp + esi*4 + 2*256] )\
+ AS2( mov esi, DWORD PTR [edx + 4] )\
+ AS2( xor eax, [ebp + edi*4] )\
+ AS2( mov ecx, ebx )\
+ AS2( xor ecx, esi )\
+ AS2( and ecx, 0x3f3f3f3f )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor eax, [ebp + esi*4 + 7*256] )\
+ AS2( shr ecx, 16 )\
+ AS2( xor eax, [ebp + edi*4 + 5*256] )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor eax, [ebp + esi*4 + 3*256] )\
+ AS2( mov esi, DWORD PTR [edx + 8] )\
+ AS2( xor eax, [ebp + edi*4 + 1*256] )\
+ AS2( mov ecx, eax )\
+ AS2( ror ecx, 4 )\
+ AS2( xor ecx, esi )\
+ AS2( and ecx, 0x3f3f3f3f )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor ebx, [ebp + esi*4 + 6*256] )\
+ AS2( shr ecx, 16 )\
+ AS2( xor ebx, [ebp + edi*4 + 4*256] )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor ebx, [ebp + esi*4 + 2*256] )\
+ AS2( mov esi, DWORD PTR [edx + 12] )\
+ AS2( xor ebx, [ebp + edi*4] )\
+ AS2( mov ecx, eax )\
+ AS2( xor ecx, esi )\
+ AS2( and ecx, 0x3f3f3f3f )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor ebx, [ebp + esi*4 + 7*256] )\
+ AS2( shr ecx, 16 )\
+ AS2( xor ebx, [ebp + edi*4 + 5*256] )\
+ AS2( movzx esi, cl )\
+ AS2( movzx edi, ch )\
+ AS2( xor ebx, [ebp + esi*4 + 3*256] )\
+ AS2( add edx, 16 )\
+ AS2( xor ebx, [ebp + edi*4 + 1*256] )
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void DES_EDE3::AsmProcess(const byte* in, byte* out, void* box) const
+{
+#ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ asm(".intel_syntax noprefix");
+
+ #define PROLOG() \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edx, DWORD PTR [ebp + 8] ) \
+ AS2( mov esi, DWORD PTR [ebp + 12] ) \
+ AS2( mov ebp, DWORD PTR [ebp + 20] )
+
+ // ebp restored at end
+ #define EPILOG() \
+ AS2( movd edi, mm3 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd esi, mm5 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+
+#else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov esi, DWORD PTR [ebp + 8] ) \
+ AS2( mov edx, ecx ) \
+ AS2( mov ebp, DWORD PTR [ebp + 16] )
+
+ // ebp restored at end
+ #define EPILOG() \
+ AS2( movd edi, mm3 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 12 )
+
+#endif
+
+
+ PROLOG()
+
+ AS2( movd mm2, edx )
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( add edx, 60 ) // des1 = des1 key
+ #else
+ AS2( add edx, 56 ) // des1 = des1 key
+ #endif
+
+ AS2( mov eax, DWORD PTR [esi] )
+ AS2( mov ebx, DWORD PTR [esi + 4] )
+ AS1( bswap eax ) // left
+ AS1( bswap ebx ) // right
+
+ AsmIPERM()
+
+ DesRound() // 1
+ DesRound() // 2
+ DesRound() // 3
+ DesRound() // 4
+ DesRound() // 5
+ DesRound() // 6
+ DesRound() // 7
+ DesRound() // 8
+
+ // swap left and right
+ AS2( xchg eax, ebx )
+
+ DesRound() // 1
+ DesRound() // 2
+ DesRound() // 3
+ DesRound() // 4
+ DesRound() // 5
+ DesRound() // 6
+ DesRound() // 7
+ DesRound() // 8
+
+ // swap left and right
+ AS2( xchg eax, ebx )
+
+ DesRound() // 1
+ DesRound() // 2
+ DesRound() // 3
+ DesRound() // 4
+ DesRound() // 5
+ DesRound() // 6
+ DesRound() // 7
+ DesRound() // 8
+
+ AsmFPERM()
+
+ //end
+ AS2( movd ebp, mm6 )
+
+ // swap and write out
+ AS1( bswap ebx )
+ AS1( bswap eax )
+
+#ifdef __GNUC__
+ AS2( mov esi, DWORD PTR [ebp + 16] ) // outBlock
+#else
+ AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock
+#endif
+
+ AS2( mov DWORD PTR [esi], ebx ) // right first
+ AS2( mov DWORD PTR [esi + 4], eax )
+
+
+ EPILOG()
+}
+
+
+
+#endif // defined(DO_DES_ASM)
+
+
} // namespace
diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp
index ea1b5846f7d..44934394343 100644
--- a/extra/yassl/taocrypt/src/dh.cpp
+++ b/extra/yassl/taocrypt/src/dh.cpp
@@ -26,10 +26,26 @@
#include "runtime.hpp"
#include "dh.hpp"
#include "asn.hpp"
+#include <math.h>
namespace TaoCrypt {
+namespace { // locals
+
+unsigned int DiscreteLogWorkFactor(unsigned int n)
+{
+ // assuming discrete log takes about the same time as factoring
+ if (n<5)
+ return 0;
+ else
+ return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) *
+ pow(log(double(n)), 2.0/3.0) - 5);
+}
+
+} // namespace locals
+
+
// Generate a DH Key Pair
void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub)
{
@@ -41,7 +57,8 @@ void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub)
// Generate private value
void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv)
{
- Integer x(rng, Integer::One(), p_ - 1);
+ Integer x(rng, Integer::One(), mySTL::min(p_ - 1,
+ Integer::Power2(2*DiscreteLogWorkFactor(p_.BitCount())) ) );
x.Encode(priv, p_.ByteCount());
}
@@ -57,11 +74,16 @@ void DH::GeneratePublic(const byte* priv, byte* pub)
// Generate Agreement
-void DH::Agree(byte* agree, const byte* priv, const byte* otherPub)
+void DH::Agree(byte* agree, const byte* priv, const byte* otherPub, word32
+ otherSz)
{
const word32 bc(p_.ByteCount());
Integer x(priv, bc);
- Integer y(otherPub, bc);
+ Integer y;
+ if (otherSz)
+ y.Decode(otherPub, otherSz);
+ else
+ y.Decode(otherPub, bc);
Integer z(a_exp_b_mod_c(y, x, p_));
z.Encode(agree, bc);
diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp
index 53b1b489b14..4e783e2c3b1 100644
--- a/extra/yassl/taocrypt/src/hash.cpp
+++ b/extra/yassl/taocrypt/src/hash.cpp
@@ -39,6 +39,15 @@ HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz)
}
+void HASHwithTransform::AddLength(word32 len)
+{
+ HashLengthType tmp = loLen_;
+ if ( (loLen_ += len) < tmp)
+ hiLen_++; // carry low to high
+ hiLen_ += SafeRightShift<8*sizeof(HashLengthType)>(len);
+}
+
+
// Update digest with data of size len, do in blocks
void HASHwithTransform::Update(const byte* data, word32 len)
{
@@ -57,6 +66,8 @@ void HASHwithTransform::Update(const byte* data, word32 len)
if (buffLen_ == blockSz) {
ByteReverseIf(local, local, blockSz, getByteOrder());
Transform();
+ AddLength(blockSz);
+ buffLen_ = 0;
}
}
}
@@ -69,25 +80,29 @@ void HASHwithTransform::Final(byte* hash)
word32 digestSz = getDigestSize();
word32 padSz = getPadSize();
ByteOrder order = getByteOrder();
- word32 prePadLen = length_ + buffLen_ * 8; // in bits
+
+ AddLength(buffLen_); // before adding pads
+ HashLengthType preLoLen = GetBitCountLo();
+ HashLengthType preHiLen = GetBitCountHi();
byte* local = reinterpret_cast<byte*>(buffer_);
local[buffLen_++] = 0x80; // add 1
// pad with zeros
if (buffLen_ > padSz) {
- while (buffLen_ < blockSz) local[buffLen_++] = 0;
+ memset(&local[buffLen_], 0, blockSz - buffLen_);
+ buffLen_ += blockSz - buffLen_;
+
ByteReverseIf(local, local, blockSz, order);
Transform();
+ buffLen_ = 0;
}
- while (buffLen_ < padSz) local[buffLen_++] = 0;
+ memset(&local[buffLen_], 0, padSz - buffLen_);
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));
-
+ memcpy(&local[padSz], order ? &preHiLen : &preLoLen, sizeof(preLoLen));
+ memcpy(&local[padSz+4], order ? &preLoLen : &preHiLen, sizeof(preLoLen));
Transform();
ByteReverseIf(digest_, digest_, digestSz, order);
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
index 4ade5491530..885ddfbf630 100644
--- a/extra/yassl/taocrypt/src/integer.cpp
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -114,7 +114,7 @@ CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(
assert(IsAlignedOn(p, 16));
return (T*)p;
}
- return new (tc) T[n];
+ return NEW_TC T[n];
}
@@ -555,7 +555,7 @@ static word AtomicInverseModPower2(word A)
for (unsigned i=3; i<WORD_BITS; i*=2)
R = R*(2-R*A);
- assert(R*A==1);
+ assert(word(R*A)==1);
return R;
}
@@ -568,21 +568,21 @@ 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 Multiply2(word *C, const word *A, const word *B);
+ static 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 unsigned int MultiplyRecursionLimit() {return 8;}
- static inline void Multiply2Bottom(word *C, const word *A, const word *B);
+ static 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 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;}
+ static unsigned int SquareRecursionLimit() {return 4;}
};
word Portable::Add(word *C, const word *A, const word *B, unsigned int N)
@@ -668,7 +668,7 @@ void Portable::Multiply2(word *C, const word *A, const word *B)
C[3] = t.GetHighHalf();
}
-inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
+void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
{
DWord t = DWord::Multiply(A[0], B[0]);
C[0] = t.GetLowHalf();
@@ -2428,7 +2428,7 @@ void PositiveMultiply(Integer& product, const Integer& a, const Integer& b)
product.reg_.CleanNew(RoundupSize(aSize + bSize));
product.sign_ = Integer::POSITIVE;
- WordBlock workspace(aSize + bSize);
+ AlignedWordBlock workspace(aSize + bSize);
AsymmetricMultiply(product.reg_.get_buffer(), workspace.get_buffer(),
a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize);
}
@@ -2714,7 +2714,7 @@ static Integer* zero = 0;
const Integer &Integer::Zero()
{
if (!zero)
- zero = new (tc) Integer;
+ zero = NEW_TC Integer;
return *zero;
}
@@ -2724,7 +2724,7 @@ static Integer* one = 0;
const Integer &Integer::One()
{
if (!one)
- one = new (tc) Integer(1,2);
+ one = NEW_TC Integer(1,2);
return *one;
}
@@ -3375,7 +3375,7 @@ void PositiveDivide(Integer& remainder, Integer& quotient,
quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2));
quotient.sign_ = Integer::POSITIVE;
- WordBlock T(aSize+2*bSize+4);
+ AlignedWordBlock 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);
@@ -3595,7 +3595,7 @@ Integer Integer::InverseMod(const Integer &m) const
return !u ? Zero() : (m*(*this-u)+1)/(*this);
}
- WordBlock T(m.reg_.size() * 4);
+ AlignedWordBlock 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(),
diff --git a/extra/yassl/taocrypt/src/make.bat b/extra/yassl/taocrypt/src/make.bat
new file mode 100644
index 00000000000..ecf7e8f8469
--- /dev/null
+++ b/extra/yassl/taocrypt/src/make.bat
@@ -0,0 +1,37 @@
+REM quick and dirty build file for testing different MSDEVs
+setlocal
+
+set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2
+
+cl %myFLAGS% aes.cpp
+cl %myFLAGS% aestables.cpp
+cl %myFLAGS% algebra.cpp
+cl %myFLAGS% arc4.cpp
+
+cl %myFLAGS% asn.cpp
+cl %myFLAGS% bftables.cpp
+cl %myFLAGS% blowfish.cpp
+cl %myFLAGS% coding.cpp
+
+cl %myFLAGS% des.cpp
+cl %myFLAGS% dh.cpp
+cl %myFLAGS% dsa.cpp
+cl %myFLAGS% file.cpp
+
+cl %myFLAGS% hash.cpp
+cl %myFLAGS% integer.cpp
+cl %myFLAGS% md2.cpp
+cl %myFLAGS% md5.cpp
+
+cl %myFLAGS% misc.cpp
+cl %myFLAGS% random.cpp
+cl %myFLAGS% ripemd.cpp
+cl %myFLAGS% rsa.cpp
+
+cl %myFLAGS% sha.cpp
+cl %myFLAGS% template_instnt.cpp
+cl %myFLAGS% tftables.cpp
+cl %myFLAGS% twofish.cpp
+
+link.exe -lib /out:taocrypt.lib aes.obj aestables.obj algebra.obj arc4.obj asn.obj bftables.obj blowfish.obj coding.obj des.obj dh.obj dsa.obj file.obj hash.obj integer.obj md2.obj md5.obj misc.obj random.obj ripemd.obj rsa.obj sha.obj template_instnt.obj tftables.obj twofish.obj
+
diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp
new file mode 100644
index 00000000000..dfc2b079141
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md4.cpp
@@ -0,0 +1,154 @@
+/* md4.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 md4.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md4.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+
+
+namespace TaoCrypt {
+
+void MD4::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+
+ buffLen_ = 0;
+ loLen_ = 0;
+ hiLen_ = 0;
+}
+
+
+MD4::MD4(const MD4& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ loLen_ = that.loLen_;
+ hiLen_ = that.hiLen_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+MD4& MD4::operator= (const MD4& that)
+{
+ MD4 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void MD4::Swap(MD4& other)
+{
+ mySTL::swap(loLen_, other.loLen_);
+ mySTL::swap(hiLen_, other.hiLen_);
+ mySTL::swap(buffLen_, other.buffLen_);
+
+ memcpy(digest_, other.digest_, DIGEST_SIZE);
+ memcpy(buffer_, other.buffer_, BLOCK_SIZE);
+}
+
+
+void MD4::Transform()
+{
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+ word32 A, B, C, D;
+
+ A = digest_[0];
+ B = digest_[1];
+ C = digest_[2];
+ D = digest_[3];
+
+#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+buffer_[k],s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 1, 7);
+ function(C,D,A,B, 2,11);
+ function(B,C,D,A, 3,19);
+ function(A,B,C,D, 4, 3);
+ function(D,A,B,C, 5, 7);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A, 7,19);
+ function(A,B,C,D, 8, 3);
+ function(D,A,B,C, 9, 7);
+ function(C,D,A,B,10,11);
+ function(B,C,D,A,11,19);
+ function(A,B,C,D,12, 3);
+ function(D,A,B,C,13, 7);
+ function(C,D,A,B,14,11);
+ function(B,C,D,A,15,19);
+
+#undef function
+#define function(a,b,c,d,k,s) a=rotlFixed(a+G(b,c,d)+buffer_[k]+0x5a827999,s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 4, 5);
+ function(C,D,A,B, 8, 9);
+ function(B,C,D,A,12,13);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 5, 5);
+ function(C,D,A,B, 9, 9);
+ function(B,C,D,A,13,13);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C, 6, 5);
+ function(C,D,A,B,10, 9);
+ function(B,C,D,A,14,13);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C, 7, 5);
+ function(C,D,A,B,11, 9);
+ function(B,C,D,A,15,13);
+
+#undef function
+#define function(a,b,c,d,k,s) a=rotlFixed(a+H(b,c,d)+buffer_[k]+0x6ed9eba1,s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 8, 9);
+ function(C,D,A,B, 4,11);
+ function(B,C,D,A,12,15);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C,10, 9);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A,14,15);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 9, 9);
+ function(C,D,A,B, 5,11);
+ function(B,C,D,A,13,15);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C,11, 9);
+ function(C,D,A,B, 7,11);
+ function(B,C,D,A,15,15);
+
+ digest_[0] += A;
+ digest_[1] += B;
+ digest_[2] += C;
+ digest_[3] += D;
+}
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp
index 1c240b43adf..3d64ff8a8a1 100644
--- a/extra/yassl/taocrypt/src/md5.cpp
+++ b/extra/yassl/taocrypt/src/md5.cpp
@@ -26,6 +26,11 @@
#include "md5.hpp"
#include "algorithm.hpp" // mySTL::swap
+
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_MD5_ASM
+#endif
+
namespace TaoCrypt {
void MD5::Init()
@@ -36,7 +41,8 @@ void MD5::Init()
digest_[3] = 0x10325476L;
buffLen_ = 0;
- length_ = 0;
+ loLen_ = 0;
+ hiLen_ = 0;
}
@@ -44,7 +50,8 @@ MD5::MD5(const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
BLOCK_SIZE)
{
buffLen_ = that.buffLen_;
- length_ = that.length_;
+ loLen_ = that.loLen_;
+ hiLen_ = that.hiLen_;
memcpy(digest_, that.digest_, DIGEST_SIZE);
memcpy(buffer_, that.buffer_, BLOCK_SIZE);
@@ -61,7 +68,8 @@ MD5& MD5::operator= (const MD5& that)
void MD5::Swap(MD5& other)
{
- mySTL::swap(length_, other.length_);
+ mySTL::swap(loLen_, other.loLen_);
+ mySTL::swap(hiLen_, other.hiLen_);
mySTL::swap(buffLen_, other.buffLen_);
memcpy(digest_, other.digest_, DIGEST_SIZE);
@@ -69,6 +77,335 @@ void MD5::Swap(MD5& other)
}
+// Update digest with data of size len, do in blocks
+void MD5::Update(const byte* data, word32 len)
+{
+ byte* local = (byte*)buffer_;
+
+ // remove buffered data if possible
+ if (buffLen_) {
+ word32 add = min(len, BLOCK_SIZE - buffLen_);
+ memcpy(&local[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == BLOCK_SIZE) {
+ ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ buffLen_ = 0;
+ }
+ }
+
+ // do block size transforms or all at once for asm
+ if (buffLen_ == 0) {
+ #ifndef DO_MD5_ASM
+ while (len >= BLOCK_SIZE) {
+ memcpy(&local[0], data, BLOCK_SIZE);
+
+ data += BLOCK_SIZE;
+ len -= BLOCK_SIZE;
+
+ ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ }
+ #else
+ word32 times = len / BLOCK_SIZE;
+ if (times) {
+ AsmTransform(data, times);
+ const word32 add = BLOCK_SIZE * times;
+ AddLength(add);
+ len -= add;
+ data += add;
+ }
+ #endif
+ }
+
+ // cache any data left
+ if (len) {
+ memcpy(&local[buffLen_], data, len);
+ buffLen_ += len;
+ }
+}
+
+
+#ifdef DO_MD5_ASM
+
+
+/*
+ // w = rotlFixed(w + f(x, y, z) + index[edi] + data, s) + x
+#define ASMMD5STEP(f, w, x, y, z, index, data, s) \
+ f(x, y, z) \
+ AS2( mov ebp, [edi + index * 4] ) \
+ AS2( lea w, [esi + w + data] ) \
+ AS2( add w, ebp ) \
+ AS2( rol w, s ) \
+ AS2( add w, x )
+
+
+ // F1(x, y, z) (z ^ (x & (y ^ z)))
+ // place in esi
+#define ASMF1(x, y, z) \
+ AS2( mov esi, y ) \
+ AS2( xor esi, z ) \
+ AS2( and esi, x ) \
+ AS2( xor esi, z )
+
+
+#define ASMF2(x, y, z) ASMF1(z, x, y)
+
+
+ // F3(x ^ y ^ z)
+ // place in esi
+#define ASMF3(x, y, z) \
+ AS2( mov esi, x ) \
+ AS2( xor esi, y ) \
+ AS2( xor esi, z )
+
+
+
+ // F4(x, y, z) (y ^ (x | ~z))
+ // place in esi
+#define ASMF4(x, y, z) \
+ AS2( mov esi, z ) \
+ AS1( not esi ) \
+ AS2( or esi, x ) \
+ AS2( xor esi, y )
+*/
+
+
+ // combine above ASMMD5STEP(f w/ each f ASMF1 - F4
+
+ // esi already set up, after using set for next round
+ // ebp already set up, set up using next round index
+
+#define MD5STEP1(w, x, y, z, index, data, s) \
+ AS2( xor esi, z ) \
+ AS2( and esi, x ) \
+ AS2( lea w, [ebp + w + data] ) \
+ AS2( xor esi, z ) \
+ AS2( add w, esi ) \
+ AS2( mov esi, x ) \
+ AS2( rol w, s ) \
+ AS2( mov ebp, [edi + index * 4] ) \
+ AS2( add w, x )
+
+#define MD5STEP2(w, x, y, z, index, data, s) \
+ AS2( xor esi, x ) \
+ AS2( and esi, z ) \
+ AS2( lea w, [ebp + w + data] ) \
+ AS2( xor esi, y ) \
+ AS2( add w, esi ) \
+ AS2( mov esi, x ) \
+ AS2( rol w, s ) \
+ AS2( mov ebp, [edi + index * 4] ) \
+ AS2( add w, x )
+
+
+#define MD5STEP3(w, x, y, z, index, data, s) \
+ AS2( xor esi, z ) \
+ AS2( lea w, [ebp + w + data] ) \
+ AS2( xor esi, x ) \
+ AS2( add w, esi ) \
+ AS2( mov esi, x ) \
+ AS2( rol w, s ) \
+ AS2( mov ebp, [edi + index * 4] ) \
+ AS2( add w, x )
+
+
+#define MD5STEP4(w, x, y, z, index, data, s) \
+ AS2( or esi, x ) \
+ AS2( lea w, [ebp + w + data] ) \
+ AS2( xor esi, y ) \
+ AS2( add w, esi ) \
+ AS2( mov esi, y ) \
+ AS2( rol w, s ) \
+ AS1( not esi ) \
+ AS2( mov ebp, [edi + index * 4] ) \
+ AS2( add w, x )
+
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void MD5::AsmTransform(const byte* data, word32 times)
+{
+#ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov edi, DWORD PTR [ebp + 12] ) \
+ AS2( mov eax, DWORD PTR [ebp + 16] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( mov esp, ebp ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+#else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, DWORD PTR [ebp + 8] ) \
+ AS2( mov eax, DWORD PTR [ebp + 12] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 8 )
+
+#endif
+
+
+ PROLOG()
+
+ AS2( mov esi, ecx )
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( add esi, 20 ) // digest_[0]
+ #else
+ AS2( add esi, 16 ) // digest_[0]
+ #endif
+
+ AS2( movd mm2, eax ) // store times_
+ AS2( movd mm1, esi ) // store digest_
+
+ AS2( mov eax, [esi] ) // a
+ AS2( mov ebx, [esi + 4] ) // b
+ AS2( mov ecx, [esi + 8] ) // c
+ AS2( mov edx, [esi + 12] ) // d
+
+AS1(loopStart:)
+
+ // set up
+ AS2( mov esi, ecx )
+ AS2( mov ebp, [edi] )
+
+ MD5STEP1( eax, ebx, ecx, edx, 1, 0xd76aa478, 7)
+ MD5STEP1( edx, eax, ebx, ecx, 2, 0xe8c7b756, 12)
+ MD5STEP1( ecx, edx, eax, ebx, 3, 0x242070db, 17)
+ MD5STEP1( ebx, ecx, edx, eax, 4, 0xc1bdceee, 22)
+ MD5STEP1( eax, ebx, ecx, edx, 5, 0xf57c0faf, 7)
+ MD5STEP1( edx, eax, ebx, ecx, 6, 0x4787c62a, 12)
+ MD5STEP1( ecx, edx, eax, ebx, 7, 0xa8304613, 17)
+ MD5STEP1( ebx, ecx, edx, eax, 8, 0xfd469501, 22)
+ MD5STEP1( eax, ebx, ecx, edx, 9, 0x698098d8, 7)
+ MD5STEP1( edx, eax, ebx, ecx, 10, 0x8b44f7af, 12)
+ MD5STEP1( ecx, edx, eax, ebx, 11, 0xffff5bb1, 17)
+ MD5STEP1( ebx, ecx, edx, eax, 12, 0x895cd7be, 22)
+ MD5STEP1( eax, ebx, ecx, edx, 13, 0x6b901122, 7)
+ MD5STEP1( edx, eax, ebx, ecx, 14, 0xfd987193, 12)
+ MD5STEP1( ecx, edx, eax, ebx, 15, 0xa679438e, 17)
+ MD5STEP1( ebx, ecx, edx, eax, 1, 0x49b40821, 22)
+
+ MD5STEP2( eax, ebx, ecx, edx, 6, 0xf61e2562, 5)
+ MD5STEP2( edx, eax, ebx, ecx, 11, 0xc040b340, 9)
+ MD5STEP2( ecx, edx, eax, ebx, 0, 0x265e5a51, 14)
+ MD5STEP2( ebx, ecx, edx, eax, 5, 0xe9b6c7aa, 20)
+ MD5STEP2( eax, ebx, ecx, edx, 10, 0xd62f105d, 5)
+ MD5STEP2( edx, eax, ebx, ecx, 15, 0x02441453, 9)
+ MD5STEP2( ecx, edx, eax, ebx, 4, 0xd8a1e681, 14)
+ MD5STEP2( ebx, ecx, edx, eax, 9, 0xe7d3fbc8, 20)
+ MD5STEP2( eax, ebx, ecx, edx, 14, 0x21e1cde6, 5)
+ MD5STEP2( edx, eax, ebx, ecx, 3, 0xc33707d6, 9)
+ MD5STEP2( ecx, edx, eax, ebx, 8, 0xf4d50d87, 14)
+ MD5STEP2( ebx, ecx, edx, eax, 13, 0x455a14ed, 20)
+ MD5STEP2( eax, ebx, ecx, edx, 2, 0xa9e3e905, 5)
+ MD5STEP2( edx, eax, ebx, ecx, 7, 0xfcefa3f8, 9)
+ MD5STEP2( ecx, edx, eax, ebx, 12, 0x676f02d9, 14)
+ MD5STEP2( ebx, ecx, edx, eax, 5, 0x8d2a4c8a, 20)
+
+ MD5STEP3( eax, ebx, ecx, edx, 8, 0xfffa3942, 4)
+ MD5STEP3( edx, eax, ebx, ecx, 11, 0x8771f681, 11)
+ MD5STEP3( ecx, edx, eax, ebx, 14, 0x6d9d6122, 16)
+ MD5STEP3( ebx, ecx, edx, eax, 1, 0xfde5380c, 23)
+ MD5STEP3( eax, ebx, ecx, edx, 4, 0xa4beea44, 4)
+ MD5STEP3( edx, eax, ebx, ecx, 7, 0x4bdecfa9, 11)
+ MD5STEP3( ecx, edx, eax, ebx, 10, 0xf6bb4b60, 16)
+ MD5STEP3( ebx, ecx, edx, eax, 13, 0xbebfbc70, 23)
+ MD5STEP3( eax, ebx, ecx, edx, 0, 0x289b7ec6, 4)
+ MD5STEP3( edx, eax, ebx, ecx, 3, 0xeaa127fa, 11)
+ MD5STEP3( ecx, edx, eax, ebx, 6, 0xd4ef3085, 16)
+ MD5STEP3( ebx, ecx, edx, eax, 9, 0x04881d05, 23)
+ MD5STEP3( eax, ebx, ecx, edx, 12, 0xd9d4d039, 4)
+ MD5STEP3( edx, eax, ebx, ecx, 15, 0xe6db99e5, 11)
+ MD5STEP3( ecx, edx, eax, ebx, 2, 0x1fa27cf8, 16)
+ MD5STEP3( ebx, ecx, edx, eax, 0, 0xc4ac5665, 23)
+
+ // setup
+ AS2( mov esi, edx )
+ AS1( not esi )
+
+ MD5STEP4( eax, ebx, ecx, edx, 7, 0xf4292244, 6)
+ MD5STEP4( edx, eax, ebx, ecx, 14, 0x432aff97, 10)
+ MD5STEP4( ecx, edx, eax, ebx, 5, 0xab9423a7, 15)
+ MD5STEP4( ebx, ecx, edx, eax, 12, 0xfc93a039, 21)
+ MD5STEP4( eax, ebx, ecx, edx, 3, 0x655b59c3, 6)
+ MD5STEP4( edx, eax, ebx, ecx, 10, 0x8f0ccc92, 10)
+ MD5STEP4( ecx, edx, eax, ebx, 1, 0xffeff47d, 15)
+ MD5STEP4( ebx, ecx, edx, eax, 8, 0x85845dd1, 21)
+ MD5STEP4( eax, ebx, ecx, edx, 15, 0x6fa87e4f, 6)
+ MD5STEP4( edx, eax, ebx, ecx, 6, 0xfe2ce6e0, 10)
+ MD5STEP4( ecx, edx, eax, ebx, 13, 0xa3014314, 15)
+ MD5STEP4( ebx, ecx, edx, eax, 4, 0x4e0811a1, 21)
+ MD5STEP4( eax, ebx, ecx, edx, 11, 0xf7537e82, 6)
+ MD5STEP4( edx, eax, ebx, ecx, 2, 0xbd3af235, 10)
+ MD5STEP4( ecx, edx, eax, ebx, 9, 0x2ad7d2bb, 15)
+ MD5STEP4( ebx, ecx, edx, eax, 9, 0xeb86d391, 21)
+
+ AS2( movd esi, mm1 ) // digest_
+
+ AS2( add [esi], eax ) // write out
+ AS2( add [esi + 4], ebx )
+ AS2( add [esi + 8], ecx )
+ AS2( add [esi + 12], edx )
+
+ AS2( add edi, 64 )
+
+ AS2( mov eax, [esi] )
+ AS2( mov ebx, [esi + 4] )
+ AS2( mov ecx, [esi + 8] )
+ AS2( mov edx, [esi + 12] )
+
+ AS2( movd ebp, mm2 ) // times
+ AS1( dec ebp )
+ AS2( movd mm2, ebp )
+ AS1( jnz loopStart )
+
+
+ EPILOG()
+}
+
+
+#endif // DO_MD5_ASM
+
+
void MD5::Transform()
{
#define F1(x, y, z) (z ^ (x & (y ^ z)))
@@ -161,10 +498,8 @@ void MD5::Transform()
// 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
index 0b33bb38aea..4ef163a7f5d 100644
--- a/extra/yassl/taocrypt/src/misc.cpp
+++ b/extra/yassl/taocrypt/src/misc.cpp
@@ -26,57 +26,65 @@
#include "misc.hpp"
-void* operator new(size_t sz, TaoCrypt::new_t)
-{
+extern "C" {
+
+ // for libcurl configure test, these are the signatures they use
+ // locking handled internally by library
+ char CRYPTO_lock() { return 0;}
+ char CRYPTO_add_lock() { return 0;}
+} // extern "C"
+
#ifdef YASSL_PURE_C
+
+ void* operator new(size_t sz, TaoCrypt::new_t)
+ {
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
+ void operator delete(void* ptr, TaoCrypt::new_t)
+ {
if (ptr) free(ptr);
-#else
- ::operator delete(ptr);
-#endif
-}
+ }
-void* operator new[](size_t sz, TaoCrypt::new_t nt)
-{
+ void* operator new[](size_t sz, TaoCrypt::new_t nt)
+ {
return ::operator new(sz, nt);
-}
+ }
-void operator delete[](void* ptr, TaoCrypt::new_t 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);
+ /* 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 delete(void* ptr);
-void* operator new[](size_t sz);
+ void* operator new[](size_t sz);
-void operator delete[](void* ptr);
-*/
+ void operator delete[](void* ptr);
+ */
-namespace TaoCrypt {
+ namespace TaoCrypt {
+
+ new_t tc; // for library new
+
+ }
+
+#endif // YASSL_PURE_C
-new_t tc; // for library new
+namespace TaoCrypt {
inline void XorWords(word* r, const word* a, unsigned int n)
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
index cf0720b11d8..945a7fa6ff7 100644
--- a/extra/yassl/taocrypt/src/random.cpp
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -26,6 +26,8 @@
#include "runtime.hpp"
#include "random.hpp"
+#include <string.h>
+
#if defined(_WIN32)
#define _WIN32_WINNT 0x0400
@@ -52,6 +54,7 @@ RandomNumberGenerator::RandomNumberGenerator()
// place a generated block in output
void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz)
{
+ memset(output, 0, sz);
cipher_.Process(output, output, sz);
}
@@ -94,10 +97,9 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz)
OS_Seed::OS_Seed()
{
fd_ = open("/dev/urandom",O_RDONLY);
+ if (fd_ == -1) {
+ fd_ = open("/dev/random",O_RDONLY);
if (fd_ == -1)
- {
- fd_ = open("/dev/random",O_RDONLY);
- if (fd_ == -1)
error_.SetError(OPEN_RAN_E);
}
}
diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp
index 0534a0d572d..da96b6cc1b4 100644
--- a/extra/yassl/taocrypt/src/ripemd.cpp
+++ b/extra/yassl/taocrypt/src/ripemd.cpp
@@ -26,6 +26,12 @@
#include "ripemd.hpp"
#include "algorithm.hpp" // mySTL::swap
+
+
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_RIPEMD_ASM
+#endif
+
namespace TaoCrypt {
void RIPEMD160::Init()
@@ -37,7 +43,8 @@ void RIPEMD160::Init()
digest_[4] = 0xc3d2e1f0L;
buffLen_ = 0;
- length_ = 0;
+ loLen_ = 0;
+ hiLen_ = 0;
}
@@ -45,7 +52,8 @@ RIPEMD160::RIPEMD160(const RIPEMD160& that)
: HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
{
buffLen_ = that.buffLen_;
- length_ = that.length_;
+ loLen_ = that.loLen_;
+ hiLen_ = that.hiLen_;
memcpy(digest_, that.digest_, DIGEST_SIZE);
memcpy(buffer_, that.buffer_, BLOCK_SIZE);
@@ -63,7 +71,8 @@ RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that)
void RIPEMD160::Swap(RIPEMD160& other)
{
- mySTL::swap(length_, other.length_);
+ mySTL::swap(loLen_, other.loLen_);
+ mySTL::swap(hiLen_, other.hiLen_);
mySTL::swap(buffLen_, other.buffLen_);
memcpy(digest_, other.digest_, DIGEST_SIZE);
@@ -71,6 +80,61 @@ void RIPEMD160::Swap(RIPEMD160& other)
}
+// Update digest with data of size len, do in blocks
+void RIPEMD160::Update(const byte* data, word32 len)
+{
+ byte* local = (byte*)buffer_;
+
+ // remove buffered data if possible
+ if (buffLen_) {
+ word32 add = min(len, BLOCK_SIZE - buffLen_);
+ memcpy(&local[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == BLOCK_SIZE) {
+ ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ buffLen_ = 0;
+ }
+ }
+
+ // do block size transforms or all at once for asm
+ if (buffLen_ == 0) {
+ #ifndef DO_RIPEMD_ASM
+ while (len >= BLOCK_SIZE) {
+ memcpy(&local[0], data, BLOCK_SIZE);
+
+ data += BLOCK_SIZE;
+ len -= BLOCK_SIZE;
+
+ ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ }
+ #else
+ word32 times = len / BLOCK_SIZE;
+ if (times) {
+ AsmTransform(data, times);
+ const word32 add = BLOCK_SIZE * times;
+ AddLength(add);
+ len -= add;
+ data += add;
+ }
+ #endif
+ }
+
+ // cache any data left
+ if (len) {
+ memcpy(&local[buffLen_], data, len);
+ buffLen_ += len;
+ }
+}
+
+
// for all
#define F(x, y, z) (x ^ y ^ z)
#define G(x, y, z) (z ^ (x & (y^z)))
@@ -79,14 +143,14 @@ void RIPEMD160::Swap(RIPEMD160& other)
#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 k1 0x5a827999
+#define k2 0x6ed9eba1
+#define k3 0x8f1bbcdc
+#define k4 0xa953fd4e
+#define k5 0x50a28be6
+#define k6 0x5c4dd124
+#define k7 0x6d703ef3
+#define k8 0x7a6d76e9
#define k9 0
// for 160 and 320
@@ -281,10 +345,495 @@ void RIPEMD160::Transform()
digest_[3] = digest_[4] + a1 + b2;
digest_[4] = digest_[0] + b1 + c2;
digest_[0] = c1;
+}
- buffLen_ = 0;
- length_ += 512;
+
+#ifdef DO_RIPEMD_ASM
+
+/*
+ // F(x ^ y ^ z)
+ // place in esi
+#define ASMF(x, y, z) \
+ AS2( mov esi, x ) \
+ AS2( xor esi, y ) \
+ AS2( xor esi, z )
+
+
+ // G(z ^ (x & (y^z)))
+ // place in esi
+#define ASMG(x, y, z) \
+ AS2( mov esi, z ) \
+ AS2( xor esi, y ) \
+ AS2( and esi, x ) \
+ AS2( xor esi, z )
+
+
+ // H(z ^ (x | ~y))
+ // place in esi
+#define ASMH(x, y, z) \
+ AS2( mov esi, y ) \
+ AS1( not esi ) \
+ AS2( or esi, x ) \
+ AS2( xor esi, z )
+
+
+ // I(y ^ (z & (x^y)))
+ // place in esi
+#define ASMI(x, y, z) \
+ AS2( mov esi, y ) \
+ AS2( xor esi, x ) \
+ AS2( and esi, z ) \
+ AS2( xor esi, y )
+
+
+ // J(x ^ (y | ~z)))
+ // place in esi
+#define ASMJ(x, y, z) \
+ AS2( mov esi, z ) \
+ AS1( not esi ) \
+ AS2( or esi, y ) \
+ AS2( xor esi, x )
+
+
+// for 160 and 320
+// #define ASMSubround(f, a, b, c, d, e, i, s, k)
+// a += f(b, c, d) + data[i] + k;
+// a = rotlFixed((word32)a, s) + e;
+// c = rotlFixed((word32)c, 10U)
+
+#define ASMSubround(f, a, b, c, d, e, index, s, k) \
+ // a += f(b, c, d) + data[i] + k \
+ AS2( mov esp, [edi + index * 4] ) \
+ f(b, c, d) \
+ AS2( add esi, k ) \
+ AS2( add esi, esp ) \
+ AS2( add a, esi ) \
+ // a = rotlFixed((word32)a, s) + e \
+ AS2( rol a, s ) \
+ AS2( rol c, 10 ) \
+ // c = rotlFixed((word32)c, 10U) \
+ AS2( add a, e )
+*/
+
+
+// combine F into subround w/ setup
+// esi already has c, setup for next round when done
+// esp already has edi[index], setup for next round when done
+
+#define ASMSubroundF(a, b, c, d, e, index, s) \
+ /* a += (b ^ c ^ d) + data[i] + k */ \
+ AS2( xor esi, b ) \
+ AS2( add a, [edi + index * 4] ) \
+ AS2( xor esi, d ) \
+ AS2( add a, esi ) \
+ /* a = rotlFixed((word32)a, s) + e */ \
+ AS2( mov esi, b ) \
+ AS2( rol a, s ) \
+ /* c = rotlFixed((word32)c, 10U) */ \
+ AS2( rol c, 10 ) \
+ AS2( add a, e )
+
+
+// combine G into subround w/ setup
+// esi already has c, setup for next round when done
+// esp already has edi[index], setup for next round when done
+
+#define ASMSubroundG(a, b, c, d, e, index, s, k) \
+ /* a += (d ^ (b & (c^d))) + data[i] + k */ \
+ AS2( xor esi, d ) \
+ AS2( and esi, b ) \
+ AS2( add a, [edi + index * 4] ) \
+ AS2( xor esi, d ) \
+ AS2( lea a, [esi + a + k] ) \
+ /* a = rotlFixed((word32)a, s) + e */ \
+ AS2( mov esi, b ) \
+ AS2( rol a, s ) \
+ /* c = rotlFixed((word32)c, 10U) */ \
+ AS2( rol c, 10 ) \
+ AS2( add a, e )
+
+
+// combine H into subround w/ setup
+// esi already has c, setup for next round when done
+// esp already has edi[index], setup for next round when done
+
+#define ASMSubroundH(a, b, c, d, e, index, s, k) \
+ /* a += (d ^ (b | ~c)) + data[i] + k */ \
+ AS1( not esi ) \
+ AS2( or esi, b ) \
+ AS2( add a, [edi + index * 4] ) \
+ AS2( xor esi, d ) \
+ AS2( lea a, [esi + a + k] ) \
+ /* a = rotlFixed((word32)a, s) + e */ \
+ AS2( mov esi, b ) \
+ AS2( rol a, s ) \
+ /* c = rotlFixed((word32)c, 10U) */ \
+ AS2( rol c, 10 ) \
+ AS2( add a, e )
+
+
+// combine I into subround w/ setup
+// esi already has c, setup for next round when done
+// esp already has edi[index], setup for next round when done
+
+#define ASMSubroundI(a, b, c, d, e, index, s, k) \
+ /* a += (c ^ (d & (b^c))) + data[i] + k */ \
+ AS2( xor esi, b ) \
+ AS2( and esi, d ) \
+ AS2( add a, [edi + index * 4] ) \
+ AS2( xor esi, c ) \
+ AS2( lea a, [esi + a + k] ) \
+ /* a = rotlFixed((word32)a, s) + e */ \
+ AS2( mov esi, b ) \
+ AS2( rol a, s ) \
+ /* c = rotlFixed((word32)c, 10U) */ \
+ AS2( rol c, 10 ) \
+ AS2( add a, e )
+
+
+// combine J into subround w/ setup
+// esi already has d, setup for next round when done
+// esp already has edi[index], setup for next round when done
+
+#define ASMSubroundJ(a, b, c, d, e, index, s, k) \
+ /* a += (b ^ (c | ~d))) + data[i] + k */ \
+ AS1( not esi ) \
+ AS2( or esi, c ) \
+ /* c = rotlFixed((word32)c, 10U) */ \
+ AS2( add a, [edi + index * 4] ) \
+ AS2( xor esi, b ) \
+ AS2( rol c, 10 ) \
+ AS2( lea a, [esi + a + k] ) \
+ /* a = rotlFixed((word32)a, s) + e */ \
+ AS2( rol a, s ) \
+ AS2( mov esi, c ) \
+ AS2( add a, e )
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void RIPEMD160::AsmTransform(const byte* data, word32 times)
+{
+#ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov edi, DWORD PTR [ebp + 12] ) \
+ AS2( mov edx, DWORD PTR [ebp + 16] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( mov esp, ebp ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+#else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, DWORD PTR [ebp + 8] ) \
+ AS2( mov edx, DWORD PTR [ebp + 12] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 8 )
+
+#endif
+
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( lea esi, [ecx + 20] ) // digest_[0]
+ #else
+ AS2( lea esi, [ecx + 16] ) // digest_[0]
+ #endif
+
+ AS2( sub esp, 24 ) // make room for tmp a1 - e1
+ AS2( movd mm1, esi ) // store digest_
+
+AS1( loopStart: )
+
+ AS2( movd mm2, edx ) // store times_
+
+ AS2( mov eax, [esi] ) // a1
+ AS2( mov ebx, [esi + 4] ) // b1
+ AS2( mov ecx, [esi + 8] ) // c1
+ AS2( mov edx, [esi + 12] ) // d1
+ AS2( mov ebp, [esi + 16] ) // e1
+
+ // setup
+ AS2( mov esi, ecx )
+
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 0, 11)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 1, 14)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 2, 15)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 3, 12)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 4, 5)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 5, 8)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 6, 7)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 7, 9)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 8, 11)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 9, 13)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 10, 14)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 11, 15)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 12, 6)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 13, 7)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 14, 9)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 15, 8)
+
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 7, 7, k1)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 4, 6, k1)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 13, 8, k1)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 1, 13, k1)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 10, 11, k1)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 6, 9, k1)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 15, 7, k1)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 3, 15, k1)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 12, 7, k1)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 0, 12, k1)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 9, 15, k1)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 5, 9, k1)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 2, 11, k1)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 14, 7, k1)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 11, 13, k1)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 8, 12, k1)
+
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 3, 11, k2)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 10, 13, k2)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 14, 6, k2)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 4, 7, k2)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 9, 14, k2)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 15, 9, k2)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 8, 13, k2)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 1, 15, k2)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 2, 14, k2)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 7, 8, k2)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 0, 13, k2)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 6, 6, k2)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 13, 5, k2)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 11, 12, k2)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 5, 7, k2)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 12, 5, k2)
+
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 1, 11, k3)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 9, 12, k3)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 11, 14, k3)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 10, 15, k3)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 0, 14, k3)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 8, 15, k3)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 12, 9, k3)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 4, 8, k3)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 13, 9, k3)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 3, 14, k3)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 7, 5, k3)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 15, 6, k3)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 14, 8, k3)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 5, 6, k3)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 6, 5, k3)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 2, 12, k3)
+
+ // setup
+ AS2( mov esi, ebp )
+
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 4, 9, k4)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 0, 15, k4)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 5, 5, k4)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 9, 11, k4)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 7, 6, k4)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 12, 8, k4)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 2, 13, k4)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 10, 12, k4)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 14, 5, k4)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 1, 12, k4)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 3, 13, k4)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 8, 14, k4)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 11, 11, k4)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 6, 8, k4)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 15, 5, k4)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 13, 6, k4)
+
+ // store a1 - e1 on stack
+ AS2( movd esi, mm1 ) // digest_
+
+ AS2( mov [esp], eax )
+ AS2( mov [esp + 4], ebx )
+ AS2( mov [esp + 8], ecx )
+ AS2( mov [esp + 12], edx )
+ AS2( mov [esp + 16], ebp )
+
+ AS2( mov eax, [esi] ) // a2
+ AS2( mov ebx, [esi + 4] ) // b2
+ AS2( mov ecx, [esi + 8] ) // c2
+ AS2( mov edx, [esi + 12] ) // d2
+ AS2( mov ebp, [esi + 16] ) // e2
+
+
+ // setup
+ AS2( mov esi, edx )
+
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 5, 8, k5)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 14, 9, k5)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 7, 9, k5)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 0, 11, k5)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 9, 13, k5)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 2, 15, k5)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 11, 15, k5)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 4, 5, k5)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 13, 7, k5)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 6, 7, k5)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 15, 8, k5)
+ ASMSubroundJ( ebp, eax, ebx, ecx, edx, 8, 11, k5)
+ ASMSubroundJ( edx, ebp, eax, ebx, ecx, 1, 14, k5)
+ ASMSubroundJ( ecx, edx, ebp, eax, ebx, 10, 14, k5)
+ ASMSubroundJ( ebx, ecx, edx, ebp, eax, 3, 12, k5)
+ ASMSubroundJ( eax, ebx, ecx, edx, ebp, 12, 6, k5)
+
+ // setup
+ AS2( mov esi, ebx )
+
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 6, 9, k6)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 11, 13, k6)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 3, 15, k6)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 7, 7, k6)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 0, 12, k6)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 13, 8, k6)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 5, 9, k6)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 10, 11, k6)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 14, 7, k6)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 15, 7, k6)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 8, 12, k6)
+ ASMSubroundI( edx, ebp, eax, ebx, ecx, 12, 7, k6)
+ ASMSubroundI( ecx, edx, ebp, eax, ebx, 4, 6, k6)
+ ASMSubroundI( ebx, ecx, edx, ebp, eax, 9, 15, k6)
+ ASMSubroundI( eax, ebx, ecx, edx, ebp, 1, 13, k6)
+ ASMSubroundI( ebp, eax, ebx, ecx, edx, 2, 11, k6)
+
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 15, 9, k7)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 5, 7, k7)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 1, 15, k7)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 3, 11, k7)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 7, 8, k7)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 14, 6, k7)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 6, 6, k7)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 9, 14, k7)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 11, 12, k7)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 8, 13, k7)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 12, 5, k7)
+ ASMSubroundH( ecx, edx, ebp, eax, ebx, 2, 14, k7)
+ ASMSubroundH( ebx, ecx, edx, ebp, eax, 10, 13, k7)
+ ASMSubroundH( eax, ebx, ecx, edx, ebp, 0, 13, k7)
+ ASMSubroundH( ebp, eax, ebx, ecx, edx, 4, 7, k7)
+ ASMSubroundH( edx, ebp, eax, ebx, ecx, 13, 5, k7)
+
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 8, 15, k8)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 6, 5, k8)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 4, 8, k8)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 1, 11, k8)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 3, 14, k8)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 11, 14, k8)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 15, 6, k8)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 0, 14, k8)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 5, 6, k8)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 12, 9, k8)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 2, 12, k8)
+ ASMSubroundG( ebx, ecx, edx, ebp, eax, 13, 9, k8)
+ ASMSubroundG( eax, ebx, ecx, edx, ebp, 9, 12, k8)
+ ASMSubroundG( ebp, eax, ebx, ecx, edx, 7, 5, k8)
+ ASMSubroundG( edx, ebp, eax, ebx, ecx, 10, 15, k8)
+ ASMSubroundG( ecx, edx, ebp, eax, ebx, 14, 8, k8)
+
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 12, 8)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 15, 5)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 10, 12)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 4, 9)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 1, 12)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 5, 5)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 8, 14)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 7, 6)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 6, 8)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 2, 13)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 13, 6)
+ ASMSubroundF( eax, ebx, ecx, edx, ebp, 14, 5)
+ ASMSubroundF( ebp, eax, ebx, ecx, edx, 0, 15)
+ ASMSubroundF( edx, ebp, eax, ebx, ecx, 3, 13)
+ ASMSubroundF( ecx, edx, ebp, eax, ebx, 9, 11)
+ ASMSubroundF( ebx, ecx, edx, ebp, eax, 11, 11)
+
+ // advance data and store for next round
+ AS2( add edi, 64 )
+ AS2( movd esi, mm1 ) // digest_
+ AS2( movd mm0, edi ) // store
+
+ // now edi as tmp
+
+ // c1 = digest_[1] + c1 + d2;
+ AS2( add [esp + 8], edx ) // + d2
+ AS2( mov edi, [esi + 4] ) // digest_[1]
+ AS2( add [esp + 8], edi )
+
+ // digest_[1] = digest_[2] + d1 + e2;
+ AS2( mov [esi + 4], ebp ) // e2
+ AS2( mov edi, [esp + 12] ) // d1
+ AS2( add edi, [esi + 8] ) // digest_[2]
+ AS2( add [esi + 4], edi )
+
+ // digest_[2] = digest_[3] + e1 + a2;
+ AS2( mov [esi + 8], eax ) // a2
+ AS2( mov edi, [esp + 16] ) // e1
+ AS2( add edi, [esi + 12] ) // digest_[3]
+ AS2( add [esi + 8], edi )
+
+ // digest_[3] = digest_[4] + a1 + b2;
+ AS2( mov [esi + 12], ebx ) // b2
+ AS2( mov edi, [esp] ) // a1
+ AS2( add edi, [esi + 16] ) // digest_[4]
+ AS2( add [esi + 12], edi )
+
+ // digest_[4] = digest_[0] + b1 + c2;
+ AS2( mov [esi + 16], ecx ) // c2
+ AS2( mov edi, [esp + 4] ) // b1
+ AS2( add edi, [esi] ) // digest_[0]
+ AS2( add [esi + 16], edi )
+
+ // digest_[0] = c1;
+ AS2( mov edi, [esp + 8] ) // c1
+ AS2( mov [esi], edi )
+
+ // setup for loop back
+ AS2( movd edx, mm2 ) // times
+ AS2( movd edi, mm0 ) // data, already advanced
+ AS1( dec edx )
+ AS1( jnz loopStart )
+
+
+ EPILOG()
}
+#endif // DO_RIPEMD_ASM
+
+
} // namespace TaoCrypt
diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp
index 13a4cfc22d3..12f80c1af75 100644
--- a/extra/yassl/taocrypt/src/sha.cpp
+++ b/extra/yassl/taocrypt/src/sha.cpp
@@ -27,6 +27,11 @@
#include "sha.hpp"
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_SHA_ASM
+#endif
+
+
namespace TaoCrypt {
#define blk0(i) (W[i] = buffer_[i])
@@ -60,7 +65,8 @@ void SHA::Init()
digest_[4] = 0xC3D2E1F0L;
buffLen_ = 0;
- length_ = 0;
+ loLen_ = 0;
+ hiLen_ = 0;
}
@@ -68,7 +74,8 @@ SHA::SHA(const SHA& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
BLOCK_SIZE)
{
buffLen_ = that.buffLen_;
- length_ = that.length_;
+ loLen_ = that.loLen_;
+ hiLen_ = that.hiLen_;
memcpy(digest_, that.digest_, DIGEST_SIZE);
memcpy(buffer_, that.buffer_, BLOCK_SIZE);
@@ -85,7 +92,8 @@ SHA& SHA::operator= (const SHA& that)
void SHA::Swap(SHA& other)
{
- mySTL::swap(length_, other.length_);
+ mySTL::swap(loLen_, other.loLen_);
+ mySTL::swap(hiLen_, other.hiLen_);
mySTL::swap(buffLen_, other.buffLen_);
memcpy(digest_, other.digest_, DIGEST_SIZE);
@@ -93,6 +101,61 @@ void SHA::Swap(SHA& other)
}
+// Update digest with data of size len, do in blocks
+void SHA::Update(const byte* data, word32 len)
+{
+ byte* local = (byte*)buffer_;
+
+ // remove buffered data if possible
+ if (buffLen_) {
+ word32 add = min(len, BLOCK_SIZE - buffLen_);
+ memcpy(&local[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == BLOCK_SIZE) {
+ ByteReverseIf(local, local, BLOCK_SIZE, BigEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ buffLen_ = 0;
+ }
+ }
+
+ // do block size transforms or all at once for asm
+ if (buffLen_ == 0) {
+ #ifndef DO_SHA_ASM
+ while (len >= BLOCK_SIZE) {
+ memcpy(&local[0], data, BLOCK_SIZE);
+
+ data += BLOCK_SIZE;
+ len -= BLOCK_SIZE;
+
+ ByteReverseIf(local, local, BLOCK_SIZE, BigEndianOrder);
+ Transform();
+ AddLength(BLOCK_SIZE);
+ }
+ #else
+ word32 times = len / BLOCK_SIZE;
+ if (times) {
+ AsmTransform(data, times);
+ const word32 add = BLOCK_SIZE * times;
+ AddLength(add);
+ len -= add;
+ data += add;
+ }
+ #endif
+ }
+
+ // cache any data left
+ if (len) {
+ memcpy(&local[buffLen_], data, len);
+ buffLen_ += len;
+ }
+}
+
+
void SHA::Transform()
{
word32 W[BLOCK_SIZE / sizeof(word32)];
@@ -109,17 +172,21 @@ void SHA::Transform()
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);
@@ -136,10 +203,414 @@ void SHA::Transform()
// Wipe variables
a = b = c = d = e = 0;
memset(W, 0, sizeof(W));
+}
- buffLen_ = 0;
- length_ += 512;
+
+#ifdef DO_SHA_ASM
+
+// f1(x,y,z) (z^(x &(y^z)))
+// place in esi
+#define ASMf1(x,y,z) \
+ AS2( mov esi, y ) \
+ AS2( xor esi, z ) \
+ AS2( and esi, x ) \
+ AS2( xor esi, z )
+
+
+// R0(v,w,x,y,z,i) =
+// z+= f1(w,x,y) + W[i] + 0x5A827999 + rotlFixed(v,5);
+// w = rotlFixed(w,30);
+
+// use esi for f
+// use edi as tmp
+
+
+#define ASMR0(v,w,x,y,z,i) \
+ AS2( mov esi, x ) \
+ AS2( mov edi, [esp + i * 4] ) \
+ AS2( xor esi, y ) \
+ AS2( and esi, w ) \
+ AS2( lea z, [edi + z + 0x5A827999] ) \
+ AS2( mov edi, v ) \
+ AS2( xor esi, y ) \
+ AS2( rol edi, 5 ) \
+ AS2( add z, esi ) \
+ AS2( rol w, 30 ) \
+ AS2( add z, edi )
+
+
+/* Some macro stuff, but older gas ( < 2,16 ) can't process &, so do by hand
+ % won't work on gas at all
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define WOFF1(a) ( a & 15)
+#define WOFF2(a) ((a + 2) & 15)
+#define WOFF3(a) ((a + 8) & 15)
+#define WOFF4(a) ((a + 13) & 15)
+
+#ifdef __GNUC__
+ #define WGET1(i) asm("mov esp, [edi - "xstr(WOFF1(i))" * 4] ");
+ #define WGET2(i) asm("xor esp, [edi - "xstr(WOFF2(i))" * 4] ");
+ #define WGET3(i) asm("xor esp, [edi - "xstr(WOFF3(i))" * 4] ");
+ #define WGET4(i) asm("xor esp, [edi - "xstr(WOFF4(i))" * 4] ");
+ #define WPUT1(i) asm("mov [edi - "xstr(WOFF1(i))" * 4], esp ");
+#else
+ #define WGET1(i) AS2( mov esp, [edi - WOFF1(i) * 4] )
+ #define WGET2(i) AS2( xor esp, [edi - WOFF2(i) * 4] )
+ #define WGET3(i) AS2( xor esp, [edi - WOFF3(i) * 4] )
+ #define WGET4(i) AS2( xor esp, [edi - WOFF4(i) * 4] )
+ #define WPUT1(i) AS2( mov [edi - WOFF1(i) * 4], esp )
+#endif
+*/
+
+// ASMR1 = ASMR0 but use esp for W calcs
+
+#define ASMR1(v,w,x,y,z,i,W1,W2,W3,W4) \
+ AS2( mov edi, [esp + W1 * 4] ) \
+ AS2( mov esi, x ) \
+ AS2( xor edi, [esp + W2 * 4] ) \
+ AS2( xor esi, y ) \
+ AS2( xor edi, [esp + W3 * 4] ) \
+ AS2( and esi, w ) \
+ AS2( xor edi, [esp + W4 * 4] ) \
+ AS2( rol edi, 1 ) \
+ AS2( xor esi, y ) \
+ AS2( mov [esp + W1 * 4], edi ) \
+ AS2( lea z, [edi + z + 0x5A827999] ) \
+ AS2( mov edi, v ) \
+ AS2( rol edi, 5 ) \
+ AS2( add z, esi ) \
+ AS2( rol w, 30 ) \
+ AS2( add z, edi )
+
+
+// ASMR2 = ASMR1 but f is xor, xor instead
+
+#define ASMR2(v,w,x,y,z,i,W1,W2,W3,W4) \
+ AS2( mov edi, [esp + W1 * 4] ) \
+ AS2( mov esi, x ) \
+ AS2( xor edi, [esp + W2 * 4] ) \
+ AS2( xor esi, y ) \
+ AS2( xor edi, [esp + W3 * 4] ) \
+ AS2( xor esi, w ) \
+ AS2( xor edi, [esp + W4 * 4] ) \
+ AS2( rol edi, 1 ) \
+ AS2( add z, esi ) \
+ AS2( mov [esp + W1 * 4], edi ) \
+ AS2( lea z, [edi + z + 0x6ED9EBA1] ) \
+ AS2( mov edi, v ) \
+ AS2( rol edi, 5 ) \
+ AS2( rol w, 30 ) \
+ AS2( add z, edi )
+
+
+// ASMR3 = ASMR2 but f is (x&y)|(z&(x|y))
+// which is (w&x)|(y&(w|x))
+
+#define ASMR3(v,w,x,y,z,i,W1,W2,W3,W4) \
+ AS2( mov edi, [esp + W1 * 4] ) \
+ AS2( mov esi, x ) \
+ AS2( xor edi, [esp + W2 * 4] ) \
+ AS2( or esi, w ) \
+ AS2( xor edi, [esp + W3 * 4] ) \
+ AS2( and esi, y ) \
+ AS2( xor edi, [esp + W4 * 4] ) \
+ AS2( movd mm0, esi ) \
+ AS2( rol edi, 1 ) \
+ AS2( mov esi, x ) \
+ AS2( mov [esp + W1 * 4], edi ) \
+ AS2( and esi, w ) \
+ AS2( lea z, [edi + z + 0x8F1BBCDC] ) \
+ AS2( movd edi, mm0 ) \
+ AS2( or esi, edi ) \
+ AS2( mov edi, v ) \
+ AS2( rol edi, 5 ) \
+ AS2( add z, esi ) \
+ AS2( rol w, 30 ) \
+ AS2( add z, edi )
+
+
+// ASMR4 = ASMR2 but different constant
+
+#define ASMR4(v,w,x,y,z,i,W1,W2,W3,W4) \
+ AS2( mov edi, [esp + W1 * 4] ) \
+ AS2( mov esi, x ) \
+ AS2( xor edi, [esp + W2 * 4] ) \
+ AS2( xor esi, y ) \
+ AS2( xor edi, [esp + W3 * 4] ) \
+ AS2( xor esi, w ) \
+ AS2( xor edi, [esp + W4 * 4] ) \
+ AS2( rol edi, 1 ) \
+ AS2( add z, esi ) \
+ AS2( mov [esp + W1 * 4], edi ) \
+ AS2( lea z, [edi + z + 0xCA62C1D6] ) \
+ AS2( mov edi, v ) \
+ AS2( rol edi, 5 ) \
+ AS2( rol w, 30 ) \
+ AS2( add z, edi )
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void SHA::AsmTransform(const byte* data, word32 times)
+{
+#ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov ecx, DWORD PTR [ebp + 8] ) \
+ AS2( mov edi, DWORD PTR [ebp + 12] ) \
+ AS2( mov eax, DWORD PTR [ebp + 16] )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( mov esp, ebp ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+#else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, data ) \
+ AS2( mov eax, times )
+
+ #define EPILOG() \
+ AS2( movd ebp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 8 )
+#endif
+
+ PROLOG()
+
+ AS2( mov esi, ecx )
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( add esi, 20 ) // digest_[0]
+ #else
+ AS2( add esi, 16 ) // digest_[0]
+ #endif
+
+ AS2( movd mm2, eax ) // store times_
+ AS2( movd mm1, esi ) // store digest_
+
+ AS2( sub esp, 68 ) // make room on stack
+
+AS1( loopStart: )
+
+ // byte reverse 16 words of input, 4 at a time, put on stack for W[]
+
+ // part 1
+ AS2( mov eax, [edi] )
+ AS2( mov ebx, [edi + 4] )
+ AS2( mov ecx, [edi + 8] )
+ AS2( mov edx, [edi + 12] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( mov [esp], eax )
+ AS2( mov [esp + 4], ebx )
+ AS2( mov [esp + 8], ecx )
+ AS2( mov [esp + 12], edx )
+
+ // part 2
+ AS2( mov eax, [edi + 16] )
+ AS2( mov ebx, [edi + 20] )
+ AS2( mov ecx, [edi + 24] )
+ AS2( mov edx, [edi + 28] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( mov [esp + 16], eax )
+ AS2( mov [esp + 20], ebx )
+ AS2( mov [esp + 24], ecx )
+ AS2( mov [esp + 28], edx )
+
+
+ // part 3
+ AS2( mov eax, [edi + 32] )
+ AS2( mov ebx, [edi + 36] )
+ AS2( mov ecx, [edi + 40] )
+ AS2( mov edx, [edi + 44] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( mov [esp + 32], eax )
+ AS2( mov [esp + 36], ebx )
+ AS2( mov [esp + 40], ecx )
+ AS2( mov [esp + 44], edx )
+
+
+ // part 4
+ AS2( mov eax, [edi + 48] )
+ AS2( mov ebx, [edi + 52] )
+ AS2( mov ecx, [edi + 56] )
+ AS2( mov edx, [edi + 60] )
+
+ AS1( bswap eax )
+ AS1( bswap ebx )
+ AS1( bswap ecx )
+ AS1( bswap edx )
+
+ AS2( mov [esp + 48], eax )
+ AS2( mov [esp + 52], ebx )
+ AS2( mov [esp + 56], ecx )
+ AS2( mov [esp + 60], edx )
+
+ AS2( mov [esp + 64], edi ) // store edi for end
+
+ // read from digest_
+ AS2( mov eax, [esi] ) // a1
+ AS2( mov ebx, [esi + 4] ) // b1
+ AS2( mov ecx, [esi + 8] ) // c1
+ AS2( mov edx, [esi + 12] ) // d1
+ AS2( mov ebp, [esi + 16] ) // e1
+
+
+ ASMR0(eax, ebx, ecx, edx, ebp, 0)
+ ASMR0(ebp, eax, ebx, ecx, edx, 1)
+ ASMR0(edx, ebp, eax, ebx, ecx, 2)
+ ASMR0(ecx, edx, ebp, eax, ebx, 3)
+ ASMR0(ebx, ecx, edx, ebp, eax, 4)
+ ASMR0(eax, ebx, ecx, edx, ebp, 5)
+ ASMR0(ebp, eax, ebx, ecx, edx, 6)
+ ASMR0(edx, ebp, eax, ebx, ecx, 7)
+ ASMR0(ecx, edx, ebp, eax, ebx, 8)
+ ASMR0(ebx, ecx, edx, ebp, eax, 9)
+ ASMR0(eax, ebx, ecx, edx, ebp, 10)
+ ASMR0(ebp, eax, ebx, ecx, edx, 11)
+ ASMR0(edx, ebp, eax, ebx, ecx, 12)
+ ASMR0(ecx, edx, ebp, eax, ebx, 13)
+ ASMR0(ebx, ecx, edx, ebp, eax, 14)
+ ASMR0(eax, ebx, ecx, edx, ebp, 15)
+
+ ASMR1(ebp, eax, ebx, ecx, edx, 16, 0, 2, 8, 13)
+ ASMR1(edx, ebp, eax, ebx, ecx, 17, 1, 3, 9, 14)
+ ASMR1(ecx, edx, ebp, eax, ebx, 18, 2, 4, 10, 15)
+ ASMR1(ebx, ecx, edx, ebp, eax, 19, 3, 5, 11, 0)
+
+ ASMR2(eax, ebx, ecx, edx, ebp, 20, 4, 6, 12, 1)
+ ASMR2(ebp, eax, ebx, ecx, edx, 21, 5, 7, 13, 2)
+ ASMR2(edx, ebp, eax, ebx, ecx, 22, 6, 8, 14, 3)
+ ASMR2(ecx, edx, ebp, eax, ebx, 23, 7, 9, 15, 4)
+ ASMR2(ebx, ecx, edx, ebp, eax, 24, 8, 10, 0, 5)
+ ASMR2(eax, ebx, ecx, edx, ebp, 25, 9, 11, 1, 6)
+ ASMR2(ebp, eax, ebx, ecx, edx, 26, 10, 12, 2, 7)
+ ASMR2(edx, ebp, eax, ebx, ecx, 27, 11, 13, 3, 8)
+ ASMR2(ecx, edx, ebp, eax, ebx, 28, 12, 14, 4, 9)
+ ASMR2(ebx, ecx, edx, ebp, eax, 29, 13, 15, 5, 10)
+ ASMR2(eax, ebx, ecx, edx, ebp, 30, 14, 0, 6, 11)
+ ASMR2(ebp, eax, ebx, ecx, edx, 31, 15, 1, 7, 12)
+ ASMR2(edx, ebp, eax, ebx, ecx, 32, 0, 2, 8, 13)
+ ASMR2(ecx, edx, ebp, eax, ebx, 33, 1, 3, 9, 14)
+ ASMR2(ebx, ecx, edx, ebp, eax, 34, 2, 4, 10, 15)
+ ASMR2(eax, ebx, ecx, edx, ebp, 35, 3, 5, 11, 0)
+ ASMR2(ebp, eax, ebx, ecx, edx, 36, 4, 6, 12, 1)
+ ASMR2(edx, ebp, eax, ebx, ecx, 37, 5, 7, 13, 2)
+ ASMR2(ecx, edx, ebp, eax, ebx, 38, 6, 8, 14, 3)
+ ASMR2(ebx, ecx, edx, ebp, eax, 39, 7, 9, 15, 4)
+
+
+ ASMR3(eax, ebx, ecx, edx, ebp, 40, 8, 10, 0, 5)
+ ASMR3(ebp, eax, ebx, ecx, edx, 41, 9, 11, 1, 6)
+ ASMR3(edx, ebp, eax, ebx, ecx, 42, 10, 12, 2, 7)
+ ASMR3(ecx, edx, ebp, eax, ebx, 43, 11, 13, 3, 8)
+ ASMR3(ebx, ecx, edx, ebp, eax, 44, 12, 14, 4, 9)
+ ASMR3(eax, ebx, ecx, edx, ebp, 45, 13, 15, 5, 10)
+ ASMR3(ebp, eax, ebx, ecx, edx, 46, 14, 0, 6, 11)
+ ASMR3(edx, ebp, eax, ebx, ecx, 47, 15, 1, 7, 12)
+ ASMR3(ecx, edx, ebp, eax, ebx, 48, 0, 2, 8, 13)
+ ASMR3(ebx, ecx, edx, ebp, eax, 49, 1, 3, 9, 14)
+ ASMR3(eax, ebx, ecx, edx, ebp, 50, 2, 4, 10, 15)
+ ASMR3(ebp, eax, ebx, ecx, edx, 51, 3, 5, 11, 0)
+ ASMR3(edx, ebp, eax, ebx, ecx, 52, 4, 6, 12, 1)
+ ASMR3(ecx, edx, ebp, eax, ebx, 53, 5, 7, 13, 2)
+ ASMR3(ebx, ecx, edx, ebp, eax, 54, 6, 8, 14, 3)
+ ASMR3(eax, ebx, ecx, edx, ebp, 55, 7, 9, 15, 4)
+ ASMR3(ebp, eax, ebx, ecx, edx, 56, 8, 10, 0, 5)
+ ASMR3(edx, ebp, eax, ebx, ecx, 57, 9, 11, 1, 6)
+ ASMR3(ecx, edx, ebp, eax, ebx, 58, 10, 12, 2, 7)
+ ASMR3(ebx, ecx, edx, ebp, eax, 59, 11, 13, 3, 8)
+
+ ASMR4(eax, ebx, ecx, edx, ebp, 60, 12, 14, 4, 9)
+ ASMR4(ebp, eax, ebx, ecx, edx, 61, 13, 15, 5, 10)
+ ASMR4(edx, ebp, eax, ebx, ecx, 62, 14, 0, 6, 11)
+ ASMR4(ecx, edx, ebp, eax, ebx, 63, 15, 1, 7, 12)
+ ASMR4(ebx, ecx, edx, ebp, eax, 64, 0, 2, 8, 13)
+ ASMR4(eax, ebx, ecx, edx, ebp, 65, 1, 3, 9, 14)
+ ASMR4(ebp, eax, ebx, ecx, edx, 66, 2, 4, 10, 15)
+ ASMR4(edx, ebp, eax, ebx, ecx, 67, 3, 5, 11, 0)
+ ASMR4(ecx, edx, ebp, eax, ebx, 68, 4, 6, 12, 1)
+ ASMR4(ebx, ecx, edx, ebp, eax, 69, 5, 7, 13, 2)
+ ASMR4(eax, ebx, ecx, edx, ebp, 70, 6, 8, 14, 3)
+ ASMR4(ebp, eax, ebx, ecx, edx, 71, 7, 9, 15, 4)
+ ASMR4(edx, ebp, eax, ebx, ecx, 72, 8, 10, 0, 5)
+ ASMR4(ecx, edx, ebp, eax, ebx, 73, 9, 11, 1, 6)
+ ASMR4(ebx, ecx, edx, ebp, eax, 74, 10, 12, 2, 7)
+ ASMR4(eax, ebx, ecx, edx, ebp, 75, 11, 13, 3, 8)
+ ASMR4(ebp, eax, ebx, ecx, edx, 76, 12, 14, 4, 9)
+ ASMR4(edx, ebp, eax, ebx, ecx, 77, 13, 15, 5, 10)
+ ASMR4(ecx, edx, ebp, eax, ebx, 78, 14, 0, 6, 11)
+ ASMR4(ebx, ecx, edx, ebp, eax, 79, 15, 1, 7, 12)
+
+
+ AS2( movd esi, mm1 ) // digest_
+
+ AS2( add [esi], eax ) // write out
+ AS2( add [esi + 4], ebx )
+ AS2( add [esi + 8], ecx )
+ AS2( add [esi + 12], edx )
+ AS2( add [esi + 16], ebp )
+
+ // setup next round
+ AS2( movd ebp, mm2 ) // times
+
+ AS2( mov edi, DWORD PTR [esp + 64] ) // data
+
+ AS2( add edi, 64 ) // next round of data
+ AS2( mov [esp + 64], edi ) // restore
+
+ AS1( dec ebp )
+ AS2( movd mm2, ebp )
+ AS1( jnz loopStart )
+
+
+ EPILOG()
}
+#endif // DO_SHA_ASM
+
} // namespace
diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp
index 59814d03209..12bcd8238f2 100644
--- a/extra/yassl/taocrypt/src/template_instnt.cpp
+++ b/extra/yassl/taocrypt/src/template_instnt.cpp
@@ -24,8 +24,14 @@
*/
+#include "runtime.hpp"
#include "integer.hpp"
#include "rsa.hpp"
+#include "sha.hpp"
+#include "md5.hpp"
+#include "hmac.hpp"
+#include "ripemd.hpp"
+#include "pwdbased.hpp"
#include "algebra.hpp"
#include "vector.hpp"
#include "hash.hpp"
@@ -53,6 +59,12 @@ template AllocatorWithCleanup<word32>::pointer StdReallocate<word32, AllocatorWi
#endif
template void tcArrayDelete<char>(char*);
+
+template class PBKDF2_HMAC<SHA>;
+template class HMAC<MD5>;
+template class HMAC<SHA>;
+template class HMAC<RIPEMD160>;
+
}
namespace mySTL {
diff --git a/extra/yassl/taocrypt/src/tftables.cpp b/extra/yassl/taocrypt/src/tftables.cpp
new file mode 100644
index 00000000000..55846d5f79d
--- /dev/null
+++ b/extra/yassl/taocrypt/src/tftables.cpp
@@ -0,0 +1,352 @@
+/* tftables.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 tftables.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "twofish.hpp"
+
+
+namespace TaoCrypt {
+
+
+const byte Twofish::q_[2][256] = {
+{
+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
+ 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
+ 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
+ 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
+ 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
+ 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
+ 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
+ 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
+ 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
+ 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
+ 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
+ 0x4A, 0x5E, 0xC1, 0xE0
+},
+{
+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
+ 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
+ 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
+ 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
+ 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
+ 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
+ 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
+ 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
+ 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
+ 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
+ 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
+ 0x55, 0x09, 0xBE, 0x91
+}
+};
+
+
+const word32 Twofish::mds_[4][256] = {
+ {
+ 0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4,
+ 0xdada03db, 0x02028b7b, 0xe2e22bfb, 0x9e9efac8,
+ 0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b,
+ 0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b,
+ 0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd,
+ 0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1,
+ 0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b,
+ 0xbfbf4887, 0x0d0d70fa, 0xb0b0b306, 0x7575de3f,
+ 0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b,
+ 0x59591c8a, 0x00000000, 0xcdcd93bc, 0x1a1ae09d,
+ 0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e,
+ 0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5,
+ 0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114,
+ 0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3,
+ 0x73732ab2, 0x0c0c8173, 0x79795f4c, 0x6b6b4154,
+ 0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51,
+ 0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a,
+ 0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796,
+ 0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410,
+ 0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c,
+ 0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7,
+ 0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70,
+ 0x29294cca, 0xf0f035e3, 0x0808fe85, 0xc6c617cb,
+ 0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8,
+ 0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff,
+ 0xadad569f, 0x0b0b8477, 0xc8c81dc3, 0x9999ffcc,
+ 0x5858ed03, 0x19199a6f, 0x0e0e0a08, 0x95957ebf,
+ 0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2,
+ 0xb5b53d79, 0x09090f0c, 0x616134aa, 0x57571682,
+ 0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9,
+ 0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97,
+ 0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17,
+ 0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d,
+ 0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3,
+ 0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c,
+ 0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e,
+ 0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f,
+ 0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149,
+ 0x0f0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321,
+ 0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9,
+ 0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd,
+ 0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01,
+ 0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f,
+ 0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48,
+ 0x2121b24f, 0x03037af2, 0xa0a02665, 0x5e5e198e,
+ 0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519,
+ 0x0606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57,
+ 0x17179067, 0x05058e7f, 0xe8e85e05, 0x4f4f7d64,
+ 0x89896aaf, 0x10109563, 0x74742fb6, 0x0a0a75fe,
+ 0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5,
+ 0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544,
+ 0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969,
+ 0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15,
+ 0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e,
+ 0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934,
+ 0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc,
+ 0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b,
+ 0x0101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab,
+ 0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252,
+ 0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9,
+ 0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4,
+ 0x6c6c4450, 0x07070504, 0x04047ff6, 0x272746c2,
+ 0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756,
+ 0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91
+ },
+ {
+ 0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6,
+ 0x04050707, 0xfd985252, 0xa3658080, 0x76dfe4e4,
+ 0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a,
+ 0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a,
+ 0x0d54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2,
+ 0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141,
+ 0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888,
+ 0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e,
+ 0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424,
+ 0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060,
+ 0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d,
+ 0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757,
+ 0x63951010, 0x015befef, 0x834db8b8, 0x2e918686,
+ 0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d,
+ 0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a,
+ 0x16a7acac, 0x0c0f0909, 0xe335f0f0, 0x6123a7a7,
+ 0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c,
+ 0x73810c0c, 0x2c273131, 0x2576d0d0, 0x0be75656,
+ 0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e,
+ 0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b,
+ 0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898,
+ 0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8,
+ 0xccff9999, 0x95ea1414, 0x03ed5858, 0x56f7dcdc,
+ 0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3,
+ 0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c,
+ 0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d,
+ 0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989,
+ 0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb,
+ 0x81fb0f0f, 0x793db5b5, 0x0951e1e1, 0xaddc3e3e,
+ 0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282,
+ 0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696,
+ 0x44557777, 0x080a0e0e, 0x86135050, 0xe730f7f7,
+ 0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e,
+ 0x06b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b,
+ 0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3,
+ 0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc,
+ 0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5,
+ 0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e,
+ 0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a,
+ 0x5fa63d3d, 0x9359a4a4, 0x0abcb9b9, 0xef3af9f9,
+ 0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616,
+ 0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272,
+ 0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0,
+ 0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f,
+ 0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969,
+ 0xfcc3bdbd, 0x975ca3a3, 0x055ee8e8, 0x7ad0eded,
+ 0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5,
+ 0x4bb72626, 0x0eb9bebe, 0xa7608787, 0x5af8d5d5,
+ 0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9,
+ 0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x02b6b7b7,
+ 0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343,
+ 0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2,
+ 0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353,
+ 0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3,
+ 0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab,
+ 0x584e6262, 0x07e85f5f, 0x99e51d1d, 0x34392323,
+ 0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646,
+ 0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba,
+ 0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070,
+ 0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf,
+ 0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4,
+ 0xd309d4d4, 0x5d108a8a, 0x0fe25151, 0x00000000,
+ 0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7,
+ 0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8
+ },
+ {
+ 0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9,
+ 0xdadbda03, 0x027b028b, 0xe2fbe22b, 0x9ec89efa,
+ 0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f,
+ 0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7,
+ 0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298,
+ 0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783,
+ 0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3,
+ 0xbf87bf48, 0x0dfa0d70, 0xb006b0b3, 0x753f75de,
+ 0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3,
+ 0x598a591c, 0x00000000, 0xcdbccd93, 0x1a9d1ae0,
+ 0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9,
+ 0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba,
+ 0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11,
+ 0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065,
+ 0x73b2732a, 0x0c730c81, 0x794c795f, 0x6b546b41,
+ 0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f,
+ 0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8,
+ 0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07,
+ 0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14,
+ 0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af,
+ 0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18,
+ 0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c,
+ 0x29ca294c, 0xf0e3f035, 0x088508fe, 0xc6cbc617,
+ 0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96,
+ 0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e,
+ 0xad9fad56, 0x0b770b84, 0xc8c3c81d, 0x99cc99ff,
+ 0x580358ed, 0x196f199a, 0x0e080e0a, 0x95bf957e,
+ 0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e,
+ 0xb579b53d, 0x090c090f, 0x61aa6134, 0x57825716,
+ 0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd,
+ 0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c,
+ 0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc,
+ 0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40,
+ 0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71,
+ 0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b,
+ 0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85,
+ 0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6,
+ 0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101,
+ 0x0f810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773,
+ 0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5,
+ 0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4,
+ 0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b,
+ 0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6,
+ 0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a,
+ 0x214f21b2, 0x03f2037a, 0xa065a026, 0x5e8e5e19,
+ 0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45,
+ 0x068d06f4, 0x40e54086, 0xf298f2be, 0x335733ac,
+ 0x17671790, 0x057f058e, 0xe805e85e, 0x4f644f7d,
+ 0x89af896a, 0x10631095, 0x74b6742f, 0x0afe0a75,
+ 0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6,
+ 0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755,
+ 0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929,
+ 0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a,
+ 0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d,
+ 0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339,
+ 0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb,
+ 0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53,
+ 0x018901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f,
+ 0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2,
+ 0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9,
+ 0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399,
+ 0x6c506c44, 0x07040705, 0x04f6047f, 0x27c22746,
+ 0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7,
+ 0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef
+ },
+ {
+ 0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2,
+ 0x05070405, 0x9852fd98, 0x6580a365, 0xdfe476df,
+ 0x08459a08, 0x024b9202, 0xa0e080a0, 0x665a7866,
+ 0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836,
+ 0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be,
+ 0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77,
+ 0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b,
+ 0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a,
+ 0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c,
+ 0xa5e784a5, 0x416b5441, 0x06dddf06, 0xc56023c5,
+ 0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915,
+ 0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216,
+ 0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91,
+ 0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63,
+ 0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25,
+ 0xa7ac16a7, 0x0f090c0f, 0x35f0e335, 0x23a76123,
+ 0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592,
+ 0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7,
+ 0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f,
+ 0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197,
+ 0x8347e183, 0x6b18e66b, 0xc822bdc8, 0x0e98450e,
+ 0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb,
+ 0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7,
+ 0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0x0cd3d70c,
+ 0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2,
+ 0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20,
+ 0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a,
+ 0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137,
+ 0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc,
+ 0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee,
+ 0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x04964d04,
+ 0x55774455, 0x0a0e080a, 0x13508613, 0x30f7e730,
+ 0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c,
+ 0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252,
+ 0x0b9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f,
+ 0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4,
+ 0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e,
+ 0x074c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f,
+ 0x0d429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3,
+ 0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a,
+ 0xef1391ef, 0xfe0885fe, 0x01914901, 0x6116ee61,
+ 0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb,
+ 0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3,
+ 0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d,
+ 0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca,
+ 0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0,
+ 0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8,
+ 0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8,
+ 0x22362822, 0x111b1411, 0xde753fde, 0x79d92979,
+ 0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6,
+ 0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc,
+ 0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38,
+ 0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469,
+ 0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da,
+ 0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2,
+ 0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439,
+ 0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872,
+ 0x26a06526, 0x93cdbc93, 0x03dadb03, 0xc6baf8c6,
+ 0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050,
+ 0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d,
+ 0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc,
+ 0x09d4d309, 0x108a5d10, 0xe2510fe2, 0x00000000,
+ 0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6,
+ 0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8
+ }
+};
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp
new file mode 100644
index 00000000000..8b896ad5dc4
--- /dev/null
+++ b/extra/yassl/taocrypt/src/twofish.cpp
@@ -0,0 +1,591 @@
+/* twofish.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
+ */
+
+/* C++ based on Wei Dai's twofish.cpp from CryptoPP */
+/* x86 asm original */
+
+
+#if defined(TAOCRYPT_KERNEL_MODE)
+ #define DO_TAOCRYPT_KERNEL_MODE
+#endif // only some modules now support this
+
+#include "runtime.hpp"
+#include "twofish.hpp"
+
+
+#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
+ #define DO_TWOFISH_ASM
+#endif
+
+
+namespace TaoCrypt {
+
+
+#if !defined(DO_TWOFISH_ASM)
+
+// Generic Version
+void Twofish::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);
+}
+
+#else
+
+// ia32 optimized version
+void Twofish::Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ if (mode_ == ECB)
+ while (blocks--) {
+ if (dir_ == ENCRYPTION)
+ AsmEncrypt(in, out);
+ else
+ AsmDecrypt(in, out);
+
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ while (blocks--) {
+ r_[0] ^= *(word32*)in;
+ r_[1] ^= *(word32*)(in + 4);
+ r_[2] ^= *(word32*)(in + 8);
+ r_[3] ^= *(word32*)(in + 12);
+
+ AsmEncrypt((byte*)r_, (byte*)r_);
+ memcpy(out, r_, BLOCK_SIZE);
+
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+ else
+ while (blocks--) {
+ AsmDecrypt(in, out);
+
+ *(word32*)out ^= r_[0];
+ *(word32*)(out + 4) ^= r_[1];
+ *(word32*)(out + 8) ^= r_[2];
+ *(word32*)(out + 12) ^= r_[3];
+
+ memcpy(r_, in, BLOCK_SIZE);
+
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+#endif // DO_TWOFISH_ASM
+
+
+namespace { // locals
+
+// compute (c * x^4) mod (x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1)
+// over GF(256)
+static inline unsigned int Mod(unsigned int c)
+{
+ static const unsigned int modulus = 0x14d;
+ unsigned int c2 = (c<<1) ^ ((c & 0x80) ? modulus : 0);
+ unsigned int c1 = c2 ^ (c>>1) ^ ((c & 1) ? (modulus>>1) : 0);
+ return c | (c1 << 8) | (c2 << 16) | (c1 << 24);
+}
+
+// compute RS(12,8) code with the above polynomial as generator
+// this is equivalent to multiplying by the RS matrix
+static word32 ReedSolomon(word32 high, word32 low)
+{
+ for (unsigned int i=0; i<8; i++) {
+ high = Mod(high>>24) ^ (high<<8) ^ (low>>24);
+ low <<= 8;
+ }
+ return high;
+}
+
+} // local namespace
+
+
+
+inline word32 Twofish::h0(word32 x, const word32* key, unsigned int kLen)
+{
+ x = x | (x<<8) | (x<<16) | (x<<24);
+ switch(kLen)
+ {
+#define Q(a, b, c, d, t) q_[a][GETBYTE(t,0)] ^ (q_[b][GETBYTE(t,1)] << 8) ^ \
+ (q_[c][GETBYTE(t,2)] << 16) ^ (q_[d][GETBYTE(t,3)] << 24)
+ case 4: x = Q(1, 0, 0, 1, x) ^ key[6];
+ case 3: x = Q(1, 1, 0, 0, x) ^ key[4];
+ case 2: x = Q(0, 1, 0, 1, x) ^ key[2];
+ x = Q(0, 0, 1, 1, x) ^ key[0];
+ }
+ return x;
+}
+
+inline word32 Twofish::h(word32 x, const word32* key, unsigned int kLen)
+{
+ x = h0(x, key, kLen);
+ return mds_[0][GETBYTE(x,0)] ^ mds_[1][GETBYTE(x,1)] ^
+ mds_[2][GETBYTE(x,2)] ^ mds_[3][GETBYTE(x,3)];
+}
+
+
+void Twofish::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
+{
+ assert(keylen >= 16 && keylen <= 32);
+
+ unsigned int len = (keylen <= 16 ? 2 : (keylen <= 24 ? 3 : 4));
+ word32 key[8];
+ GetUserKey(LittleEndianOrder, key, len*2, userKey, keylen);
+
+ unsigned int i;
+ for (i=0; i<40; i+=2) {
+ word32 a = h(i, key, len);
+ word32 b = rotlFixed(h(i+1, key+1, len), 8);
+ k_[i] = a+b;
+ k_[i+1] = rotlFixed(a+2*b, 9);
+ }
+
+ word32 svec[8];
+ for (i=0; i<len; i++)
+ svec[2*(len-i-1)] = ReedSolomon(key[2*i+1], key[2*i]);
+
+ for (i=0; i<256; i++) {
+ word32 t = h0(i, svec, len);
+ s_[0][i] = mds_[0][GETBYTE(t, 0)];
+ s_[1][i] = mds_[1][GETBYTE(t, 1)];
+ s_[2][i] = mds_[2][GETBYTE(t, 2)];
+ s_[3][i] = mds_[3][GETBYTE(t, 3)];
+ }
+}
+
+
+void Twofish::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out)
+ const
+{
+ if (dir_ == ENCRYPTION)
+ encrypt(in, xOr, out);
+ else
+ decrypt(in, xOr, out);
+}
+
+#define G1(x) (s_[0][GETBYTE(x,0)] ^ s_[1][GETBYTE(x,1)] ^ \
+ s_[2][GETBYTE(x,2)] ^ s_[3][GETBYTE(x,3)])
+#define G2(x) (s_[0][GETBYTE(x,3)] ^ s_[1][GETBYTE(x,0)] ^ \
+ s_[2][GETBYTE(x,1)] ^ s_[3][GETBYTE(x,2)])
+
+#define ENCROUND(n, a, b, c, d) \
+ x = G1 (a); y = G2 (b); \
+ x += y; y += x + k[2 * (n) + 1]; \
+ (c) ^= x + k[2 * (n)]; \
+ (c) = rotrFixed(c, 1); \
+ (d) = rotlFixed(d, 1) ^ y
+
+#define ENCCYCLE(n) \
+ ENCROUND (2 * (n), a, b, c, d); \
+ ENCROUND (2 * (n) + 1, c, d, a, b)
+
+#define DECROUND(n, a, b, c, d) \
+ x = G1 (a); y = G2 (b); \
+ x += y; y += x; \
+ (d) ^= y + k[2 * (n) + 1]; \
+ (d) = rotrFixed(d, 1); \
+ (c) = rotlFixed(c, 1); \
+ (c) ^= (x + k[2 * (n)])
+
+#define DECCYCLE(n) \
+ DECROUND (2 * (n) + 1, c, d, a, b); \
+ DECROUND (2 * (n), a, b, c, d)
+
+
+typedef BlockGetAndPut<word32, LittleEndian> gpBlock;
+
+void Twofish::encrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 x, y, a, b, c, d;
+
+ gpBlock::Get(inBlock)(a)(b)(c)(d);
+
+ a ^= k_[0];
+ b ^= k_[1];
+ c ^= k_[2];
+ d ^= k_[3];
+
+ const word32 *k = k_+8;
+
+ ENCCYCLE (0);
+ ENCCYCLE (1);
+ ENCCYCLE (2);
+ ENCCYCLE (3);
+ ENCCYCLE (4);
+ ENCCYCLE (5);
+ ENCCYCLE (6);
+ ENCCYCLE (7);
+
+ c ^= k_[4];
+ d ^= k_[5];
+ a ^= k_[6];
+ b ^= k_[7];
+
+ gpBlock::Put(xorBlock, outBlock)(c)(d)(a)(b);
+}
+
+
+void Twofish::decrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 x, y, a, b, c, d;
+
+ gpBlock::Get(inBlock)(c)(d)(a)(b);
+
+ c ^= k_[4];
+ d ^= k_[5];
+ a ^= k_[6];
+ b ^= k_[7];
+
+ const word32 *k = k_+8;
+ DECCYCLE (7);
+ DECCYCLE (6);
+ DECCYCLE (5);
+ DECCYCLE (4);
+ DECCYCLE (3);
+ DECCYCLE (2);
+ DECCYCLE (1);
+ DECCYCLE (0);
+
+ a ^= k_[0];
+ b ^= k_[1];
+ c ^= k_[2];
+ d ^= k_[3];
+
+ gpBlock::Put(xorBlock, outBlock)(a)(b)(c)(d);
+}
+
+
+
+#if defined(DO_TWOFISH_ASM)
+ #ifdef __GNUC__
+ #define AS1(x) asm(#x);
+ #define AS2(x, y) asm(#x ", " #y);
+
+ #define PROLOG() \
+ asm(".intel_syntax noprefix"); \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, DWORD PTR [ebp + 8] ) \
+ AS2( mov esi, DWORD PTR [ebp + 12] )
+
+ #define EPILOG() \
+ AS2( movd esp, mm6 ) \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS1( emms ) \
+ asm(".att_syntax");
+ #else
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+
+ #define PROLOG() \
+ AS1( push ebp ) \
+ AS2( mov ebp, esp ) \
+ AS2( movd mm3, edi ) \
+ AS2( movd mm4, ebx ) \
+ AS2( movd mm5, esi ) \
+ AS2( movd mm6, ebp ) \
+ AS2( mov edi, ecx ) \
+ AS2( mov esi, DWORD PTR [ebp + 8] )
+
+ /* ebp already set */
+ #define EPILOG() \
+ AS2( movd esi, mm5 ) \
+ AS2( movd ebx, mm4 ) \
+ AS2( movd edi, mm3 ) \
+ AS2( mov esp, ebp ) \
+ AS1( pop ebp ) \
+ AS1( emms ) \
+ AS1( ret 8 )
+
+ #endif
+
+
+
+
+ // x = esi, y = [esp], s_ = ebp
+ // edi always open for G1 and G2
+ // G1 also uses edx after save and restore
+ // G2 also uses eax after save and restore
+ // and ecx for tmp [esp] which Rounds also use
+ // and restore from mm7
+
+ // x = G1(a) bytes(0,1,2,3)
+#define ASMG1(z, zl, zh) \
+ AS2( movd mm2, edx ) \
+ AS2( movzx edi, zl ) \
+ AS2( mov esi, DWORD PTR [ebp + edi*4] ) \
+ AS2( movzx edx, zh ) \
+ AS2( xor esi, DWORD PTR 1024[ebp + edx*4] ) \
+ \
+ AS2( mov edx, z ) \
+ AS2( shr edx, 16 ) \
+ AS2( movzx edi, dl ) \
+ AS2( xor esi, DWORD PTR 2048[ebp + edi*4] ) \
+ AS2( movzx edx, dh ) \
+ AS2( xor esi, DWORD PTR 3072[ebp + edx*4] ) \
+ AS2( movd edx, mm2 )
+
+
+ // y = G2(b) bytes(3,0,1,2) [ put y into ecx for Rounds ]
+#define ASMG2(z, zl, zh) \
+ AS2( movd mm7, ecx ) \
+ AS2( movd mm2, eax ) \
+ AS2( mov edi, z ) \
+ AS2( shr edi, 24 ) \
+ AS2( mov ecx, DWORD PTR [ebp + edi*4] ) \
+ AS2( movzx eax, zl ) \
+ AS2( xor ecx, DWORD PTR 1024[ebp + eax*4] ) \
+ \
+ AS2( mov eax, z ) \
+ AS2( shr eax, 16 ) \
+ AS2( movzx edi, zh ) \
+ AS2( xor ecx, DWORD PTR 2048[ebp + edi*4] ) \
+ AS2( movzx eax, al ) \
+ AS2( xor ecx, DWORD PTR 3072[ebp + eax*4] ) \
+ AS2( movd eax, mm2 )
+
+
+ // encrypt Round (n),
+ // x = esi, k = ebp, edi open
+ // y is in ecx from G2, restore when done from mm7
+ // before C (which be same register!)
+#define ASMENCROUND(N, A, A2, A3, B, B2, B3, C, D) \
+ /* setup s_ */ \
+ AS2( movd ebp, mm1 ) \
+ ASMG1(A, A2, A3) \
+ ASMG2(B, B2, B3) \
+ /* setup k */ \
+ AS2( movd ebp, mm0 ) \
+ /* x += y */ \
+ AS2( add esi, ecx ) \
+ AS2( add ebp, 32 ) \
+ /* y += x + k[2 * (n) + 1] */ \
+ AS2( add ecx, esi ) \
+ AS2( rol D, 1 ) \
+ AS2( add ecx, DWORD PTR [ebp + 8 * N + 4] ) \
+ /* (d) = rotlFixed(d, 1) ^ y */ \
+ AS2( xor D, ecx ) \
+ AS2( movd ecx, mm7 ) \
+ /* (c) ^= x + k[2 * (n)] */ \
+ AS2( mov edi, esi ) \
+ AS2( add edi, DWORD PTR [ebp + 8 * N] ) \
+ AS2( xor C, edi ) \
+ /* (c) = rotrFixed(c, 1) */ \
+ AS2( ror C, 1 )
+
+
+ // decrypt Round (n),
+ // x = esi, k = ebp, edi open
+ // y is in ecx from G2, restore ecx from mm7 when done
+#define ASMDECROUND(N, A, A2, A3, B, B2, B3, C, D) \
+ /* setup s_ */ \
+ AS2( movd ebp, mm1 ) \
+ ASMG1(A, A2, A3) \
+ ASMG2(B, B2, B3) \
+ /* setup k */ \
+ AS2( movd ebp, mm0 ) \
+ /* x += y */ \
+ AS2( add esi, ecx ) \
+ AS2( add ebp, 32 ) \
+ /* y += x */ \
+ AS2( add ecx, esi ) \
+ /* (d) ^= y + k[2 * (n) + 1] */ \
+ AS2( mov edi, DWORD PTR [ebp + 8 * N + 4] ) \
+ AS2( add edi, ecx ) \
+ AS2( movd ecx, mm7 ) \
+ AS2( xor D, edi ) \
+ /* (d) = rotrFixed(d, 1) */ \
+ AS2( ror D, 1 ) \
+ /* (c) = rotlFixed(c, 1) */ \
+ AS2( rol C, 1 ) \
+ /* (c) ^= (x + k[2 * (n)]) */ \
+ AS2( mov edi, esi ) \
+ AS2( add edi, DWORD PTR [ebp + 8 * N] ) \
+ AS2( xor C, edi )
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void Twofish::AsmEncrypt(const byte* inBlock, byte* outBlock) const
+{
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( add edi, 60 ) // k_
+ #else
+ AS2( add edi, 56 ) // k_
+ #endif
+
+ AS2( mov ebp, edi )
+
+ AS2( mov eax, DWORD PTR [esi] ) // a
+ AS2( movd mm0, edi ) // store k_
+ AS2( mov ebx, DWORD PTR [esi + 4] ) // b
+ AS2( add ebp, 160 ) // s_[0]
+ AS2( mov ecx, DWORD PTR [esi + 8] ) // c
+ AS2( movd mm1, ebp ) // store s_
+ AS2( mov edx, DWORD PTR [esi + 12] ) // d
+
+ AS2( xor eax, DWORD PTR [edi] ) // k_[0]
+ AS2( xor ebx, DWORD PTR [edi + 4] ) // [1]
+ AS2( xor ecx, DWORD PTR [edi + 8] ) // [2]
+ AS2( xor edx, DWORD PTR [edi + 12] ) // [3]
+
+
+ ASMENCROUND( 0, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND( 1, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND( 2, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND( 3, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND( 4, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND( 5, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND( 6, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND( 7, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND( 8, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND( 9, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND(10, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND(11, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND(12, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND(13, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMENCROUND(14, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMENCROUND(15, ecx, cl, ch, edx, dl, dh, eax, ebx)
+
+
+ AS2( movd ebp, mm6 )
+ AS2( movd esi, mm0 ) // k_
+ #ifdef __GNUC__
+ AS2( mov edi, [ebp + 16] ) // outBlock
+ #else
+ AS2( mov edi, [ebp + 12] ) // outBlock
+ #endif
+
+ AS2( xor ecx, DWORD PTR [esi + 16] ) // k_[4]
+ AS2( xor edx, DWORD PTR [esi + 20] ) // k_[5]
+ AS2( xor eax, DWORD PTR [esi + 24] ) // k_[6]
+ AS2( xor ebx, DWORD PTR [esi + 28] ) // k_[7]
+
+ AS2( mov [edi], ecx ) // write out
+ AS2( mov [edi + 4], edx ) // write out
+ AS2( mov [edi + 8], eax ) // write out
+ AS2( mov [edi + 12], ebx ) // write out
+
+
+ EPILOG()
+}
+
+
+#ifdef _MSC_VER
+ __declspec(naked)
+#endif
+void Twofish::AsmDecrypt(const byte* inBlock, byte* outBlock) const
+{
+ PROLOG()
+
+ #ifdef OLD_GCC_OFFSET
+ AS2( add edi, 60 ) // k_
+ #else
+ AS2( add edi, 56 ) // k_
+ #endif
+
+ AS2( mov ebp, edi )
+
+ AS2( mov ecx, DWORD PTR [esi] ) // c
+ AS2( movd mm0, edi ) // store k_
+ AS2( mov edx, DWORD PTR [esi + 4] ) // d
+ AS2( add ebp, 160 ) // s_[0]
+ AS2( mov eax, DWORD PTR [esi + 8] ) // a
+ AS2( movd mm1, ebp ) // store s_
+ AS2( mov ebx, DWORD PTR [esi + 12] ) // b
+
+ AS2( xor ecx, DWORD PTR [edi + 16] ) // k_[4]
+ AS2( xor edx, DWORD PTR [edi + 20] ) // [5]
+ AS2( xor eax, DWORD PTR [edi + 24] ) // [6]
+ AS2( xor ebx, DWORD PTR [edi + 28] ) // [7]
+
+
+ ASMDECROUND(15, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND(14, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND(13, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND(12, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND(11, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND(10, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND( 9, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND( 8, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND( 7, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND( 6, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND( 5, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND( 4, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND( 3, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND( 2, eax, al, ah, ebx, bl, bh, ecx, edx)
+ ASMDECROUND( 1, ecx, cl, ch, edx, dl, dh, eax, ebx)
+ ASMDECROUND( 0, eax, al, ah, ebx, bl, bh, ecx, edx)
+
+
+ AS2( movd ebp, mm6 )
+ AS2( movd esi, mm0 ) // k_
+ #ifdef __GNUC__
+ AS2( mov edi, [ebp + 16] ) // outBlock
+ #else
+ AS2( mov edi, [ebp + 12] ) // outBlock
+ #endif
+
+ AS2( xor eax, DWORD PTR [esi ] ) // k_[0]
+ AS2( xor ebx, DWORD PTR [esi + 4] ) // k_[1]
+ AS2( xor ecx, DWORD PTR [esi + 8] ) // k_[2]
+ AS2( xor edx, DWORD PTR [esi + 12] ) // k_[3]
+
+ AS2( mov [edi], eax ) // write out
+ AS2( mov [edi + 4], ebx ) // write out
+ AS2( mov [edi + 8], ecx ) // write out
+ AS2( mov [edi + 12], edx ) // write out
+
+
+ EPILOG()
+}
+
+
+
+#endif // defined(DO_TWOFISH_ASM)
+
+
+
+
+
+} // namespace
+
+
diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp
index 115ad0cb272..19edf7b2f22 100644
--- a/extra/yassl/taocrypt/taocrypt.dsp
+++ b/extra/yassl/taocrypt/taocrypt.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 /MT /W3 /GX- /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /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
@@ -64,7 +64,8 @@ LIB32=link.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 /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -105,6 +106,14 @@ SOURCE=.\src\asn.cpp
# End Source File
# Begin Source File
+SOURCE=.\src\bftables.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\blowfish.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\src\coding.cpp
# End Source File
# Begin Source File
@@ -137,6 +146,10 @@ SOURCE=.\src\md2.cpp
# End Source File
# Begin Source File
+SOURCE=.\src\md4.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\src\md5.cpp
# End Source File
# Begin Source File
@@ -159,6 +172,14 @@ SOURCE=.\src\rsa.cpp
SOURCE=.\src\sha.cpp
# End Source File
+# Begin Source File
+
+SOURCE=.\src\tftables.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\twofish.cpp
+# End Source File
# End Group
# Begin Group "Header Files"
@@ -185,6 +206,10 @@ SOURCE=.\include\block.hpp
# End Source File
# Begin Source File
+SOURCE=.\include\blowfish.hpp
+# End Source File
+# Begin Source File
+
SOURCE=.\include\coding.hpp
# End Source File
# Begin Source File
@@ -225,6 +250,10 @@ SOURCE=.\include\md2.hpp
# End Source File
# Begin Source File
+SOURCE=.\include\md4.hpp
+# End Source File
+# Begin Source File
+
SOURCE=.\include\md5.hpp
# End Source File
# Begin Source File
@@ -241,6 +270,10 @@ SOURCE=.\include\modes.hpp
# End Source File
# Begin Source File
+SOURCE=.\include\pwdbased.hpp
+# End Source File
+# Begin Source File
+
SOURCE=.\include\random.hpp
# End Source File
# Begin Source File
@@ -255,6 +288,18 @@ SOURCE=.\include\rsa.hpp
SOURCE=.\include\sha.hpp
# End Source File
+# Begin Source File
+
+SOURCE=.\include\twofish.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\type_traits.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\types.hpp
+# End Source File
# End Group
# End Target
# End Project
diff --git a/extra/yassl/taocrypt/test.dsp b/extra/yassl/taocrypt/test.dsp
new file mode 100644
index 00000000000..a5e05ed0ac0
--- /dev/null
+++ b/extra/yassl/taocrypt/test.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=test - 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 "test.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 "test.mak" CFG="test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "test___Win32_Release"
+# PROP BASE Intermediate_Dir "test___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "test\Release"
+# PROP Intermediate_Dir "test\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 /MT /W3 /O2 /I "include" /I "../mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /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
+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 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
+
+!ELSEIF "$(CFG)" == "test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "test___Win32_Debug"
+# PROP BASE Intermediate_Dir "test___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "test\Debug"
+# PROP Intermediate_Dir "test\Debug"
+# 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 /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "../mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "test - Win32 Release"
+# Name "test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\test\test.cpp
+# 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/extra/yassl/taocrypt/test.dsw b/extra/yassl/taocrypt/test.dsw
new file mode 100644
index 00000000000..b5c03bc6e03
--- /dev/null
+++ b/extra/yassl/taocrypt/test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "test"=.\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am
new file mode 100644
index 00000000000..0b238f1e057
--- /dev/null
+++ b/extra/yassl/taocrypt/test/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I../include -I../../mySTL
+bin_PROGRAMS = test
+test_SOURCES = test.cpp
+test_LDFLAGS = -L../src
+test_LDADD = -ltaocrypt
+test_DEPENDENCIES = ../src/libtaocrypt.la
+test_CXXFLAGS = -DYASSL_PURE_C
+EXTRA_DIST = make.bat
diff --git a/extra/yassl/taocrypt/test/make.bat b/extra/yassl/taocrypt/test/make.bat
new file mode 100644
index 00000000000..5f01db68d0d
--- /dev/null
+++ b/extra/yassl/taocrypt/test/make.bat
@@ -0,0 +1,9 @@
+REM quick and dirty build file for testing different MSDEVs
+setlocal
+
+set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2
+
+cl %myFLAGS% test.cpp
+
+link.exe /out:test.exe ../src/taocrypt.lib test.obj advapi32.lib
+
diff --git a/extra/yassl/taocrypt/test/memory.cpp b/extra/yassl/taocrypt/test/memory.cpp
new file mode 100644
index 00000000000..726c9c0ef54
--- /dev/null
+++ b/extra/yassl/taocrypt/test/memory.cpp
@@ -0,0 +1,312 @@
+// memory.cpp
+#include "../../include/lock.hpp" // locking
+#include <new> // std::bad_alloc
+#include <cstdlib> // malloc
+#include <cstring> // memset
+#include <fstream> // ofstream
+#include <sstream> // stringstream
+#include <cassert> // assert
+#include <iomanip> // setiosflags
+
+/*********************************************************************
+
+To use MemoryTracker merely add this file to your project
+No need to instantiate anything
+
+If your app is multi threaded define MULTI_THREADED
+
+*********************************************************************/
+
+
+// locals
+namespace {
+
+class MemoryTracker {
+ std::ofstream log_;
+public:
+ MemoryTracker();
+ ~MemoryTracker();
+private:
+ MemoryTracker(const MemoryTracker&); // hide copy
+ MemoryTracker& operator=(const MemoryTracker&); // and assign
+
+ void LogStats();
+};
+
+
+struct alloc_node {
+ alloc_node* left_;
+ alloc_node* right_;
+
+ alloc_node() : left_(0), right_(0) {}
+};
+
+
+alloc_node* Root = 0;
+
+size_t Allocs = 0;
+size_t DeAllocs = 0;
+size_t Bytes = 0;
+
+
+struct size_tracker {
+ size_t size_;
+ size_t count_;
+};
+
+size_tracker sizes[] =
+{
+ {0,0},
+ {2,0},
+ {4,0},
+ {8,0},
+ {16,0},
+ {32,0},
+ {64,0},
+ {128,0},
+ {256,0},
+ {512,0},
+ {1024,0},
+ {2048,0},
+ {4096,0},
+ {8192,0},
+};
+
+const size_t size_elements(sizeof(sizes) / sizeof(size_tracker));
+
+bool Tracking(false);
+
+using yaSSL::Mutex;
+typedef Mutex::Lock Lock;
+
+Mutex mutex;
+
+MemoryTracker theTracker;
+
+
+bool lookup(alloc_node*& find, void* key, alloc_node*& prev)
+{
+ bool found(false);
+
+ while (find) {
+ if (find == key) {
+ found = true;
+ break;
+ }
+ prev = find;
+ if (key < find)
+ find = find->left_;
+ else
+ find = find->right_;
+ }
+ return found;
+}
+
+
+// iterative insert
+void insert(alloc_node* entry)
+{
+ if (!Root) {
+ Root = entry;
+ return;
+ }
+
+ alloc_node* tmp = Root;
+ alloc_node* prev = 0;
+
+ if (lookup(tmp, entry, prev))
+ assert(0); // duplicate
+
+ if (entry < prev)
+ prev->left_ = entry;
+ else
+ prev->right_ = entry;
+}
+
+
+alloc_node* predecessorSwap(alloc_node* del)
+{
+ alloc_node* pred = del->left_;
+ alloc_node* predPrev = del;
+
+ while (pred->right_) {
+ predPrev = pred;
+ pred = pred->right_;
+ }
+ if (predPrev == del)
+ predPrev->left_ = pred->left_;
+ else
+ predPrev->right_ = pred->left_;
+
+ pred->left_ = del->left_;
+ pred->right_ = del->right_;
+
+ return pred;
+}
+
+
+// iterative remove
+void remove(void* ptr)
+{
+ alloc_node* del = Root;
+ alloc_node* prev = 0;
+ alloc_node* replace = 0;
+
+ if ( lookup(del, ptr, prev) == false)
+ assert(0); // oops, not there
+
+ if (del->left_ && del->right_) // two children
+ replace = predecessorSwap(del);
+ else if (!del->left_ && !del->right_) // no children
+ replace = 0;
+ else // one child
+ replace = (del->left_) ? del->left_ : del->right_;
+
+ if (del == Root)
+ Root = replace;
+ else if (prev->left_ == del)
+ prev->left_ = replace;
+ else
+ prev->right_ = replace;
+}
+
+
+typedef void (*fp)(alloc_node*, void*);
+
+void applyInOrder(alloc_node* root, fp f, void* arg)
+{
+ if (root == 0)
+ return;
+
+ applyInOrder(root->left_, f, arg);
+ f(root, arg);
+ applyInOrder(root->right_, f, arg);
+}
+
+
+void show(alloc_node* ptr, void* arg)
+{
+ std::ofstream* log = static_cast<std::ofstream*>(arg);
+ *log << ptr << '\n';
+}
+
+
+MemoryTracker::MemoryTracker() : log_("memory.log")
+{
+#ifdef __GNUC__
+ // Force pool allocator to cleanup at exit
+ setenv("GLIBCPP_FORCE_NEW", "1", 0);
+#endif
+
+#ifdef _MSC_VER
+ // msvc6 needs to create Facility for ostream before main starts, otherwise
+ // if another ostream is created and destroyed in main scope, log stats
+ // will access a dead Facility reference (std::numput)
+ int msvcFac = 6;
+ log_ << "MSVC " << msvcFac << "workaround" << std::endl;
+#endif
+
+
+ Tracking = true;
+}
+
+
+MemoryTracker::~MemoryTracker()
+{
+ // stop tracking before log (which will alloc on output)
+ Tracking = false;
+ LogStats();
+
+ //assert(Allocs == DeAllocs);
+ //assert(Root == 0);
+}
+
+
+void MemoryTracker::LogStats()
+{
+ log_ << "Number of Allocs: " << Allocs << '\n';
+ log_ << "Number of DeAllocs: " << DeAllocs << '\n';
+ log_ << "Number of bytes used: " << Bytes << '\n';
+
+ log_ << "Alloc size table:\n";
+ log_ << " Bytes " << '\t' << " Times\n";
+
+ for (size_t i = 0; i < size_elements; ++i) {
+ log_ << " " << sizes[i].size_ << " " << '\t';
+ log_ << std::setiosflags(std::ios::right) << std::setw(8);
+ log_ << sizes[i].count_ << '\n';
+ }
+
+ if (Allocs != DeAllocs) {
+ log_<< "Showing new'd allocs with no deletes" << '\n';
+ applyInOrder(Root, show, &log_);
+ }
+ log_.flush();
+}
+
+
+// return power of 2 up to size_tracker elements
+size_t powerOf2(size_t sz)
+{
+ size_t shifts = 0;
+
+ if (sz)
+ sz -= 1;
+ else
+ return 0;
+
+ while (sz) {
+ sz >>= 1;
+ ++shifts;
+ }
+
+ return shifts < size_elements ? shifts : size_elements;
+}
+
+
+} // namespace local
+
+
+void* operator new(size_t sz)
+{
+ // put alloc node in front of requested memory
+ void* ptr = malloc(sz + sizeof(alloc_node));
+ if (ptr) {
+ if (Tracking) {
+ Lock l(mutex);
+ ++Allocs;
+ Bytes += sz;
+ ++sizes[powerOf2(sz)].count_;
+ insert(new (ptr) alloc_node);
+ }
+ return static_cast<char*>(ptr) + sizeof(alloc_node);
+ }
+ else
+ assert(0);
+}
+
+
+void operator delete(void* ptr)
+{
+ if (ptr) {
+ ptr = static_cast<char*>(ptr) - sizeof(alloc_node); // correct offset
+ if (Tracking) {
+ Lock l(mutex);
+ ++DeAllocs;
+ remove(ptr);
+ }
+ free(ptr);
+ }
+}
+
+
+void* operator new[](size_t sz)
+{
+ return ::operator new(sz);
+}
+
+
+void operator delete[](void* ptr)
+{
+ ::operator delete(ptr);
+}
diff --git a/extra/yassl/taocrypt/test/test.cpp b/extra/yassl/taocrypt/test/test.cpp
new file mode 100644
index 00000000000..28ef73dfac8
--- /dev/null
+++ b/extra/yassl/taocrypt/test/test.cpp
@@ -0,0 +1,994 @@
+// test.cpp
+// test taocrypt functionality
+
+#include <string.h>
+#include <stdio.h>
+
+#include "runtime.hpp"
+#include "sha.hpp"
+#include "md5.hpp"
+#include "md2.hpp"
+#include "md4.hpp"
+#include "ripemd.hpp"
+#include "hmac.hpp"
+#include "arc4.hpp"
+#include "des.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "aes.hpp"
+#include "twofish.hpp"
+#include "blowfish.hpp"
+#include "asn.hpp"
+#include "dh.hpp"
+#include "coding.hpp"
+#include "random.hpp"
+#include "pwdbased.hpp"
+
+
+
+using TaoCrypt::byte;
+using TaoCrypt::word32;
+using TaoCrypt::SHA;
+using TaoCrypt::MD5;
+using TaoCrypt::MD2;
+using TaoCrypt::MD4;
+using TaoCrypt::RIPEMD160;
+using TaoCrypt::HMAC;
+using TaoCrypt::ARC4;
+using TaoCrypt::DES_EDE3_CBC_Encryption;
+using TaoCrypt::DES_EDE3_CBC_Decryption;
+using TaoCrypt::DES_CBC_Encryption;
+using TaoCrypt::DES_CBC_Decryption;
+using TaoCrypt::DES_ECB_Encryption;
+using TaoCrypt::DES_ECB_Decryption;
+using TaoCrypt::AES_CBC_Encryption;
+using TaoCrypt::AES_CBC_Decryption;
+using TaoCrypt::AES_ECB_Encryption;
+using TaoCrypt::AES_ECB_Decryption;
+using TaoCrypt::Twofish_CBC_Encryption;
+using TaoCrypt::Twofish_CBC_Decryption;
+using TaoCrypt::Twofish_ECB_Encryption;
+using TaoCrypt::Twofish_ECB_Decryption;
+using TaoCrypt::Blowfish_CBC_Encryption;
+using TaoCrypt::Blowfish_CBC_Decryption;
+using TaoCrypt::Blowfish_ECB_Encryption;
+using TaoCrypt::Blowfish_ECB_Decryption;
+using TaoCrypt::RSA_PrivateKey;
+using TaoCrypt::RSA_PublicKey;
+using TaoCrypt::DSA_PrivateKey;
+using TaoCrypt::DSA_PublicKey;
+using TaoCrypt::DSA_Signer;
+using TaoCrypt::DSA_Verifier;
+using TaoCrypt::RSAES_Encryptor;
+using TaoCrypt::RSAES_Decryptor;
+using TaoCrypt::Source;
+using TaoCrypt::FileSource;
+using TaoCrypt::FileSource;
+using TaoCrypt::HexDecoder;
+using TaoCrypt::HexEncoder;
+using TaoCrypt::Base64Decoder;
+using TaoCrypt::Base64Encoder;
+using TaoCrypt::CertDecoder;
+using TaoCrypt::DH;
+using TaoCrypt::EncodeDSA_Signature;
+using TaoCrypt::DecodeDSA_Signature;
+using TaoCrypt::PBKDF2_HMAC;
+using TaoCrypt::tcArrayDelete;
+
+
+
+struct testVector {
+ byte* input_;
+ byte* output_;
+ size_t inLen_;
+ size_t outLen_;
+
+ testVector(const char* in, const char* out) : input_((byte*)in),
+ output_((byte*)out), inLen_(strlen(in)), outLen_(strlen(out)) {}
+};
+
+void file_test(int, char**);
+int sha_test();
+int md5_test();
+int md2_test();
+int md4_test();
+int ripemd_test();
+int hmac_test();
+int arc4_test();
+int des_test();
+int aes_test();
+int twofish_test();
+int blowfish_test();
+int rsa_test();
+int dsa_test();
+int dh_test();
+int pwdbased_test();
+
+TaoCrypt::RandomNumberGenerator rng;
+
+
+void err_sys(const char* msg, int es)
+{
+ printf("%s", msg);
+ exit(es);
+}
+
+// func_args from test.hpp, so don't have to pull in other junk
+struct func_args {
+ int argc;
+ char** argv;
+ int return_code;
+};
+
+
+/*
+ DES, AES, Blowfish, and Twofish need aligned (4 byte) input/output for
+ processing, can turn this off by setting gpBlock(assumeAligned = false)
+ but would hurt performance. yaSSL always uses dynamic memory so we have
+ at least 8 byte alignment. This test tried to force alignment for stack
+ variables (for convenience) but some compiler versions and optimizations
+ seemed to be off. So we have msgTmp variable which we copy into dynamic
+ memory at runtime to ensure proper alignment, along with plain/cipher.
+ Whew!
+*/
+const byte msgTmp[] = { // "now is the time for all " w/o trailing 0
+ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
+ 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
+};
+
+byte* msg = 0; // for block cipher input
+byte* plain = 0; // for cipher decrypt comparison
+byte* cipher = 0; // block output
+
+
+void taocrypt_test(void* args)
+{
+ ((func_args*)args)->return_code = -1; // error state
+
+ msg = NEW_TC byte[24];
+ plain = NEW_TC byte[24];
+ cipher = NEW_TC byte[24];
+
+ memcpy(msg, msgTmp, 24);
+
+ int ret = 0;
+ if ( (ret = sha_test()) )
+ err_sys("SHA test failed!\n", ret);
+ else
+ printf( "SHA test passed!\n");
+
+ if ( (ret = md5_test()) )
+ err_sys("MD5 test failed!\n", ret);
+ else
+ printf( "MD5 test passed!\n");
+
+ if ( (ret = md2_test()) )
+ err_sys("MD2 test failed!\n", ret);
+ else
+ printf( "MD2 test passed!\n");
+
+ if ( (ret = md4_test()) )
+ err_sys("MD4 test failed!\n", ret);
+ else
+ printf( "MD4 test passed!\n");
+
+ if ( (ret = ripemd_test()) )
+ err_sys("RIPEMD test failed!\n", ret);
+ else
+ printf( "RIPEMD test passed!\n");
+
+ if ( ( ret = hmac_test()) )
+ err_sys("HMAC test failed!\n", ret);
+ else
+ printf( "HMAC test passed!\n");
+
+ if ( (ret = arc4_test()) )
+ err_sys("ARC4 test failed!\n", ret);
+ else
+ printf( "ARC4 test passed!\n");
+
+ if ( (ret = des_test()) )
+ err_sys("DES test failed!\n", ret);
+ else
+ printf( "DES test passed!\n");
+
+ if ( (ret = aes_test()) )
+ err_sys("AES test failed!\n", ret);
+ else
+ printf( "AES test passed!\n");
+
+ if ( (ret = twofish_test()) )
+ err_sys("Twofish test failed!\n", ret);
+ else
+ printf( "Twofish test passed!\n");
+
+ if ( (ret = blowfish_test()) )
+ err_sys("Blowfish test failed!\n", ret);
+ else
+ printf( "Blowfish test passed!\n");
+
+ if ( (ret = rsa_test()) )
+ err_sys("RSA test failed!\n", ret);
+ else
+ printf( "RSA test passed!\n");
+
+ if ( (ret = dh_test()) )
+ err_sys("DH test failed!\n", ret);
+ else
+ printf( "DH test passed!\n");
+
+ if ( (ret = dsa_test()) )
+ err_sys("DSA test failed!\n", ret);
+ else
+ printf( "DSA test passed!\n");
+
+ if ( (ret = pwdbased_test()) )
+ err_sys("PBKDF2 test failed!\n", ret);
+ else
+ printf( "PBKDF2 test passed!\n");
+
+ tcArrayDelete(cipher);
+ tcArrayDelete(plain);
+ tcArrayDelete(msg);
+
+ ((func_args*)args)->return_code = ret;
+}
+
+
+// so overall tests can pull in test function
+#ifndef NO_MAIN_DRIVER
+
+ int main(int argc, char** argv)
+ {
+ func_args args;
+
+ args.argc = argc;
+ args.argv = argv;
+
+ taocrypt_test(&args);
+ return args.return_code;
+ }
+
+#endif // NO_MAIN_DRIVER
+
+
+void file_test(char* file, byte* check)
+{
+ FILE* f;
+ int i(0);
+ MD5 md5;
+ byte buf[1024];
+ byte md5sum[MD5::DIGEST_SIZE];
+
+ if( !( f = fopen( file, "rb" ) )) {
+ printf("Can't open %s\n", file);
+ return;
+ }
+ while( ( i = fread(buf, 1, sizeof(buf), f )) > 0 )
+ md5.Update(buf, i);
+
+ md5.Final(md5sum);
+ memcpy(check, md5sum, sizeof(md5sum));
+
+ for(int j = 0; j < MD5::DIGEST_SIZE; ++j )
+ printf( "%02x", md5sum[j] );
+
+ printf(" %s\n", file);
+
+ fclose(f);
+}
+
+
+int sha_test()
+{
+ SHA sha;
+ byte hash[SHA::DIGEST_SIZE];
+
+ testVector test_sha[] =
+ {
+ testVector("abc",
+ "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2"
+ "\x6C\x9C\xD0\xD8\x9D"),
+ testVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29"
+ "\xE5\xE5\x46\x70\xF1"),
+ testVector("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "\x00\x98\xBA\x82\x4B\x5C\x16\x42\x7B\xD7\xA1\x12\x2A\x5A\x44"
+ "\x2A\x25\xEC\x64\x4D"),
+ testVector("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaa",
+ "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7"
+ "\x53\x99\x5E\x26\xA0")
+ };
+
+ int times( sizeof(test_sha) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ sha.Update(test_sha[i].input_, test_sha[i].inLen_);
+ sha.Final(hash);
+
+ if (memcmp(hash, test_sha[i].output_, SHA::DIGEST_SIZE) != 0)
+ return -1 - i;
+ }
+
+ return 0;
+}
+
+
+int md5_test()
+{
+ MD5 md5;
+ byte hash[MD5::DIGEST_SIZE];
+
+ testVector test_md5[] =
+ {
+ testVector("abc",
+ "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f"
+ "\x72"),
+ testVector("message digest",
+ "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61"
+ "\xd0"),
+ testVector("abcdefghijklmnopqrstuvwxyz",
+ "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1"
+ "\x3b"),
+ testVector("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
+ "6789",
+ "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d"
+ "\x9f"),
+ testVector("1234567890123456789012345678901234567890123456789012345678"
+ "9012345678901234567890",
+ "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6"
+ "\x7a")
+ };
+
+ int times( sizeof(test_md5) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ md5.Update(test_md5[i].input_, test_md5[i].inLen_);
+ md5.Final(hash);
+
+ if (memcmp(hash, test_md5[i].output_, MD5::DIGEST_SIZE) != 0)
+ return -5 - i;
+ }
+
+ return 0;
+}
+
+
+int md4_test()
+{
+ MD4 md4;
+ byte hash[MD4::DIGEST_SIZE];
+
+ testVector test_md4[] =
+ {
+ testVector("",
+ "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89"
+ "\xc0"),
+ testVector("a",
+ "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb"
+ "\x24"),
+ testVector("abc",
+ "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72"
+ "\x9d"),
+ testVector("message digest",
+ "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01"
+ "\x4b"),
+ testVector("abcdefghijklmnopqrstuvwxyz",
+ "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d"
+ "\xa9"),
+ testVector("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
+ "6789",
+ "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0"
+ "\xe4"),
+ testVector("1234567890123456789012345678901234567890123456789012345678"
+ "9012345678901234567890",
+ "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05"
+ "\x36")
+ };
+
+ int times( sizeof(test_md4) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ md4.Update(test_md4[i].input_, test_md4[i].inLen_);
+ md4.Final(hash);
+
+ if (memcmp(hash, test_md4[i].output_, MD4::DIGEST_SIZE) != 0)
+ return -5 - i;
+ }
+
+ return 0;
+}
+
+
+int md2_test()
+{
+ MD2 md5;
+ byte hash[MD2::DIGEST_SIZE];
+
+ testVector test_md2[] =
+ {
+ testVector("",
+ "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69"
+ "\x27\x73"),
+ testVector("a",
+ "\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0"
+ "\xb5\xd1"),
+ testVector("abc",
+ "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde"
+ "\xd6\xbb"),
+ testVector("message digest",
+ "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe"
+ "\x06\xb0"),
+ testVector("abcdefghijklmnopqrstuvwxyz",
+ "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47"
+ "\x94\x0b"),
+ testVector("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789",
+ "\xda\x33\xde\xf2\xa4\x2d\xf1\x39\x75\x35\x28\x46\xc3\x03"
+ "\x38\xcd"),
+ testVector("12345678901234567890123456789012345678901234567890123456"
+ "789012345678901234567890",
+ "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3"
+ "\xef\xd8")
+ };
+
+ int times( sizeof(test_md2) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ md5.Update(test_md2[i].input_, test_md2[i].inLen_);
+ md5.Final(hash);
+
+ if (memcmp(hash, test_md2[i].output_, MD2::DIGEST_SIZE) != 0)
+ return -10 - i;
+ }
+
+ return 0;
+}
+
+
+int ripemd_test()
+{
+ RIPEMD160 ripe160;
+ byte hash[RIPEMD160::DIGEST_SIZE];
+
+ testVector test_ripemd[] =
+ {
+ testVector("",
+ "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8"
+ "\xf5\x48\xb2\x25\x8d\x31"),
+ testVector("a",
+ "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4"
+ "\xdc\x83\x5a\x46\x7f\xfe"),
+ testVector("abc",
+ "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6"
+ "\xb0\x87\xf1\x5a\x0b\xfc"),
+ testVector("message digest",
+ "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8"
+ "\x5f\xfa\x21\x59\x5f\x36"),
+ testVector("abcdefghijklmnopqrstuvwxyz",
+ "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb\xdc\xeb\x5b\x9d"
+ "\x28\x65\xb3\x70\x8d\xbc"),
+ testVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc"
+ "\xf4\x9a\xda\x62\xeb\x2b"),
+ testVector("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123"
+ "456789",
+ "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed\x3a\x87\xa5\x71"
+ "\x30\x79\xb2\x1f\x51\x89"),
+ testVector("12345678901234567890123456789012345678901234567890123456"
+ "789012345678901234567890",
+ "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab"
+ "\x82\xbf\x63\x32\x6b\xfb"),
+ };
+
+ int times( sizeof(test_ripemd) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ ripe160.Update(test_ripemd[i].input_, test_ripemd[i].inLen_);
+ ripe160.Final(hash);
+
+ if (memcmp(hash, test_ripemd[i].output_, RIPEMD160::DIGEST_SIZE) != 0)
+ return -100 - i;
+ }
+
+ return 0;
+}
+
+
+int hmac_test()
+{
+ HMAC<MD5> hmacMD5;
+ byte hash[MD5::DIGEST_SIZE];
+
+ const char* keys[]=
+ {
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ "Jefe",
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ };
+
+ testVector test_hmacMD5[] =
+ {
+ testVector("Hi There",
+ "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc"
+ "\x9d"),
+ testVector("what do ya want for nothing?",
+ "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7"
+ "\x38"),
+ testVector("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD",
+ "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3"
+ "\xf6")
+ };
+
+ int times( sizeof(test_hmacMD5) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ hmacMD5.SetKey((byte*)keys[i], strlen(keys[i]));
+ hmacMD5.Update(test_hmacMD5[i].input_, test_hmacMD5[i].inLen_);
+ hmacMD5.Final(hash);
+
+ if (memcmp(hash, test_hmacMD5[i].output_, MD5::DIGEST_SIZE) != 0)
+ return -20 - i;
+ }
+
+ return 0;
+}
+
+
+int arc4_test()
+{
+ byte cipher[16];
+ byte plain[16];
+
+ const char* keys[] =
+ {
+ "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xef\x01\x23\x45"
+ };
+
+ testVector test_arc4[] =
+ {
+ testVector("\x01\x23\x45\x67\x89\xab\xcd\xef",
+ "\x75\xb7\x87\x80\x99\xe0\xc5\x96"),
+ testVector("\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x74\x94\xc2\xe7\x10\x4b\x08\x79"),
+ testVector("\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xde\x18\x89\x41\xa3\x37\x5d\x3a"),
+ testVector("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf\xbd\x61")
+ };
+
+
+ int times( sizeof(test_arc4) / sizeof(testVector) );
+ for (int i = 0; i < times; ++i) {
+ ARC4::Encryption enc;
+ ARC4::Decryption dec;
+
+ enc.SetKey((byte*)keys[i], strlen(keys[i]));
+ dec.SetKey((byte*)keys[i], strlen(keys[i]));
+
+ enc.Process(cipher, test_arc4[i].input_, test_arc4[i].outLen_);
+ dec.Process(plain, cipher, test_arc4[i].outLen_);
+
+ if (memcmp(plain, test_arc4[i].input_, test_arc4[i].outLen_))
+ return -30 - i;
+
+ if (memcmp(cipher, test_arc4[i].output_, test_arc4[i].outLen_))
+ return -40 - i;
+ }
+
+ return 0;
+}
+
+
+int des_test()
+{
+ //ECB mode
+ DES_ECB_Encryption enc;
+ DES_ECB_Decryption dec;
+
+ const int sz = TaoCrypt::DES_BLOCK_SIZE * 3;
+ const byte key[] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef };
+ const byte iv[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef };
+
+ enc.SetKey(key, sizeof(key));
+ enc.Process(cipher, msg, sz);
+ dec.SetKey(key, sizeof(key));
+ dec.Process(plain, cipher, sz);
+
+ if (memcmp(plain, msg, sz))
+ return -50;
+
+ const byte verify1[] =
+ {
+ 0xf9,0x99,0xb8,0x8e,0xaf,0xea,0x71,0x53,
+ 0x6a,0x27,0x17,0x87,0xab,0x88,0x83,0xf9,
+ 0x89,0x3d,0x51,0xec,0x4b,0x56,0x3b,0x53
+ };
+
+ if (memcmp(cipher, verify1, sz))
+ return -51;
+
+ // CBC mode
+ DES_CBC_Encryption enc2;
+ DES_CBC_Decryption dec2;
+
+ enc2.SetKey(key, sizeof(key), iv);
+ enc2.Process(cipher, msg, sz);
+ dec2.SetKey(key, sizeof(key), iv);
+ dec2.Process(plain, cipher, sz);
+
+ if (memcmp(plain, msg, sz))
+ return -52;
+
+ const byte verify2[] =
+ {
+ 0x8b,0x7c,0x52,0xb0,0x01,0x2b,0x6c,0xb8,
+ 0x4f,0x0f,0xeb,0xf3,0xfb,0x5f,0x86,0x73,
+ 0x15,0x85,0xb3,0x22,0x4b,0x86,0x2b,0x4b
+ };
+
+ if (memcmp(cipher, verify2, sz))
+ return -53;
+
+ // EDE3 CBC mode
+ DES_EDE3_CBC_Encryption enc3;
+ DES_EDE3_CBC_Decryption dec3;
+
+ const byte key3[] =
+ {
+ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+ 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10,
+ 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+ };
+ const byte iv3[] =
+ {
+ 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81
+
+ };
+
+ enc3.SetKey(key3, sizeof(key3), iv3);
+ enc3.Process(cipher, msg, sz);
+ dec3.SetKey(key3, sizeof(key3), iv3);
+ dec3.Process(plain, cipher, sz);
+
+ if (memcmp(plain, msg, sz))
+ return -54;
+
+ const byte verify3[] =
+ {
+ 0x08,0x8a,0xae,0xe6,0x9a,0xa9,0xc1,0x13,
+ 0x93,0x7d,0xf7,0x3a,0x11,0x56,0x66,0xb3,
+ 0x18,0xbc,0xbb,0x6d,0xd2,0xb1,0x16,0xda
+ };
+
+ if (memcmp(cipher, verify3, sz))
+ return -55;
+
+ return 0;
+}
+
+
+int aes_test()
+{
+ AES_CBC_Encryption enc;
+ AES_CBC_Decryption dec;
+ const int bs(TaoCrypt::AES::BLOCK_SIZE);
+
+ byte key[] = "0123456789abcdef "; // align
+ byte iv[] = "1234567890abcdef "; // align
+
+ enc.SetKey(key, bs, iv);
+ dec.SetKey(key, bs, iv);
+
+ enc.Process(cipher, msg, bs);
+ dec.Process(plain, cipher, bs);
+
+ if (memcmp(plain, msg, bs))
+ return -60;
+
+ const byte verify[] =
+ {
+ 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53,
+ 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb
+ };
+
+ if (memcmp(cipher, verify, bs))
+ return -61;
+
+ AES_ECB_Encryption enc2;
+ AES_ECB_Decryption dec2;
+
+ enc2.SetKey(key, bs, iv);
+ dec2.SetKey(key, bs, iv);
+
+ enc2.Process(cipher, msg, bs);
+ dec2.Process(plain, cipher, bs);
+
+ if (memcmp(plain, msg, bs))
+ return -62;
+
+ const byte verify2[] =
+ {
+ 0xd0,0xc9,0xd9,0xc9,0x40,0xe8,0x97,0xb6,
+ 0xc8,0x8c,0x33,0x3b,0xb5,0x8f,0x85,0xd1
+ };
+
+ if (memcmp(cipher, verify2, bs))
+ return -63;
+
+ return 0;
+}
+
+
+int twofish_test()
+{
+ Twofish_CBC_Encryption enc;
+ Twofish_CBC_Decryption dec;
+ const int bs(TaoCrypt::Twofish::BLOCK_SIZE);
+
+ byte key[] = "0123456789abcdef "; // align
+ byte iv[] = "1234567890abcdef "; // align
+
+ enc.SetKey(key, bs, iv);
+ dec.SetKey(key, bs, iv);
+
+ enc.Process(cipher, msg, bs);
+ dec.Process(plain, cipher, bs);
+
+ if (memcmp(plain, msg, bs))
+ return -60;
+
+ const byte verify[] =
+ {
+ 0xD2,0xD7,0x47,0x47,0x4A,0x65,0x4E,0x16,
+ 0x21,0x03,0x58,0x79,0x5F,0x02,0x27,0x2C
+ };
+
+ if (memcmp(cipher, verify, bs))
+ return -61;
+
+ Twofish_ECB_Encryption enc2;
+ Twofish_ECB_Decryption dec2;
+
+ enc2.SetKey(key, bs, iv);
+ dec2.SetKey(key, bs, iv);
+
+ enc2.Process(cipher, msg, bs);
+ dec2.Process(plain, cipher, bs);
+
+ if (memcmp(plain, msg, bs))
+ return -62;
+
+ const byte verify2[] =
+ {
+ 0x3B,0x6C,0x63,0x10,0x34,0xAB,0xB2,0x87,
+ 0xC4,0xCD,0x6B,0x91,0x14,0xC5,0x3A,0x09
+ };
+
+ if (memcmp(cipher, verify2, bs))
+ return -63;
+
+ return 0;
+}
+
+
+int blowfish_test()
+{
+ Blowfish_CBC_Encryption enc;
+ Blowfish_CBC_Decryption dec;
+ const int bs(TaoCrypt::Blowfish::BLOCK_SIZE);
+
+ byte key[] = "0123456789abcdef "; // align
+ byte iv[] = "1234567890abcdef "; // align
+
+ enc.SetKey(key, 16, iv);
+ dec.SetKey(key, 16, iv);
+
+ enc.Process(cipher, msg, bs * 2);
+ dec.Process(plain, cipher, bs * 2);
+
+ if (memcmp(plain, msg, bs))
+ return -60;
+
+ const byte verify[] =
+ {
+ 0x0E,0x26,0xAA,0x29,0x11,0x25,0xAB,0xB5,
+ 0xBC,0xD9,0x08,0xC4,0x94,0x6C,0x89,0xA3
+ };
+
+ if (memcmp(cipher, verify, bs))
+ return -61;
+
+ Blowfish_ECB_Encryption enc2;
+ Blowfish_ECB_Decryption dec2;
+
+ enc2.SetKey(key, 16, iv);
+ dec2.SetKey(key, 16, iv);
+
+ enc2.Process(cipher, msg, bs * 2);
+ dec2.Process(plain, cipher, bs * 2);
+
+ if (memcmp(plain, msg, bs))
+ return -62;
+
+ const byte verify2[] =
+ {
+ 0xE7,0x42,0xB9,0x37,0xC8,0x7D,0x93,0xCA,
+ 0x8F,0xCE,0x39,0x32,0xDE,0xD7,0xBC,0x5B
+ };
+
+ if (memcmp(cipher, verify2, bs))
+ return -63;
+
+ return 0;
+}
+
+
+int rsa_test()
+{
+ Source source;
+ FileSource("../certs/client-key.der", source);
+ if (source.size() == 0) {
+ FileSource("../../certs/client-key.der", source); // for testsuite
+ if (source.size() == 0) {
+ FileSource("../../../certs/client-key.der", source); // Debug dir
+ if (source.size() == 0)
+ err_sys("where's your certs dir?", -79);
+ }
+ }
+ RSA_PrivateKey priv(source);
+
+ RSAES_Encryptor enc(priv);
+ byte message[] = "Everyone gets Friday off.";
+ const int len(strlen((char*)message));
+ byte cipher[64];
+ enc.Encrypt(message, len, cipher, rng);
+
+ RSAES_Decryptor dec(priv);
+ byte plain[64];
+ dec.Decrypt(cipher, sizeof(plain), plain, rng);
+
+ if (memcmp(plain, message, len))
+ return -70;
+
+ dec.SSL_Sign(message, len, cipher, rng);
+ if (!enc.SSL_Verify(message, len, cipher))
+ return -71;
+
+
+ // test decode
+ Source source2;
+ FileSource("../certs/client-cert.der", source2);
+ if (source2.size() == 0) {
+ FileSource("../../certs/client-cert.der", source2); // for testsuite
+ if (source2.size() == 0) {
+ FileSource("../../../certs/client-cert.der", source2); // Debug dir
+ if (source2.size() == 0)
+ err_sys("where's your certs dir?", -79);
+ }
+ }
+ CertDecoder cd(source2, true, 0, false, CertDecoder::CA);
+ Source source3(cd.GetPublicKey().GetKey(), cd.GetPublicKey().size());
+ RSA_PublicKey pub(source3);
+
+ return 0;
+}
+
+
+int dh_test()
+{
+ Source source;
+ FileSource("../certs/dh1024.dat", source);
+ if (source.size() == 0) {
+ FileSource("../../certs/dh1024.dat", source); // for testsuite
+ if (source.size() == 0) {
+ FileSource("../../../certs/dh1024.dat", source); // win32 Debug dir
+ if (source.size() == 0)
+ err_sys("where's your certs dir?", -79);
+ }
+ }
+ HexDecoder hDec(source);
+
+ DH dh(source);
+
+ byte pub[128];
+ byte priv[128];
+ byte agree[128];
+ byte pub2[128];
+ byte priv2[128];
+ byte agree2[128];
+
+ DH dh2(dh);
+
+ dh.GenerateKeyPair(rng, priv, pub);
+ dh2.GenerateKeyPair(rng, priv2, pub2);
+ dh.Agree(agree, priv, pub2);
+ dh2.Agree(agree2, priv2, pub);
+
+
+ if ( memcmp(agree, agree2, dh.GetByteLength()) )
+ return -80;
+
+ return 0;
+}
+
+
+int dsa_test()
+{
+ Source source;
+ FileSource("../certs/dsa512.der", source);
+ if (source.size() == 0) {
+ FileSource("../../certs/dsa512.der", source); // for testsuite
+ if (source.size() == 0) {
+ FileSource("../../../certs/dsa512.der", source); // win32 Debug dir
+ if (source.size() == 0)
+ err_sys("where's your certs dir?", -89);
+ }
+ }
+
+ const char msg[] = "this is the message";
+ byte signature[40];
+
+ DSA_PrivateKey priv(source);
+ DSA_Signer signer(priv);
+
+ SHA sha;
+ byte digest[SHA::DIGEST_SIZE];
+ sha.Update((byte*)msg, sizeof(msg));
+ sha.Final(digest);
+
+ signer.Sign(digest, signature, rng);
+
+ byte encoded[sizeof(signature) + 6];
+ byte decoded[40];
+
+ word32 encSz = EncodeDSA_Signature(signer.GetR(), signer.GetS(), encoded);
+ DecodeDSA_Signature(decoded, encoded, encSz);
+
+ DSA_PublicKey pub(priv);
+ DSA_Verifier verifier(pub);
+
+ if (!verifier.Verify(digest, decoded))
+ return -90;
+
+ return 0;
+}
+
+
+int pwdbased_test()
+{
+ PBKDF2_HMAC<SHA> pb;
+
+ byte derived[32];
+ const byte pwd1[] = "password "; // align
+ const byte salt[] = { 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 };
+
+ pb.DeriveKey(derived, 8, pwd1, 8, salt, sizeof(salt), 5);
+
+ const byte verify1[] = { 0xD1, 0xDA, 0xA7, 0x86, 0x15, 0xF2, 0x87, 0xE6 };
+
+ if ( memcmp(derived, verify1, sizeof(verify1)) )
+ return -101;
+
+
+ const byte pwd2[] = "All n-entities must communicate with other n-entities"
+ " via n-1 entiteeheehees "; // align
+
+ pb.DeriveKey(derived, 24, pwd2, 76, salt, sizeof(salt), 500);
+
+ const byte verify2[] = { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE,
+ 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86,
+ 0x07, 0x12, 0x63, 0x80, 0xCC, 0x47, 0xAB, 0x2D
+ };
+
+ if ( memcmp(derived, verify2, sizeof(verify2)) )
+ return -102;
+
+ return 0;
+}
diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am
new file mode 100644
index 00000000000..d91822f609e
--- /dev/null
+++ b/extra/yassl/testsuite/Makefile.am
@@ -0,0 +1,11 @@
+INCLUDES = -I../include -I../taocrypt/include -I../mySTL
+bin_PROGRAMS = testsuite
+testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \
+ ../examples/client/client.cpp ../examples/server/server.cpp \
+ ../examples/echoclient/echoclient.cpp \
+ ../examples/echoserver/echoserver.cpp
+testsuite_LDFLAGS = -L../src/ -L../taocrypt/src
+testsuite_CXXFLAGS = -DYASSL_PURE_C -DNO_MAIN_DRIVER
+testsuite_LDADD = -lyassl -ltaocrypt
+testsuite_DEPENDENCIES = ../src/libyassl.la ../taocrypt/src/libtaocrypt.la
+EXTRA_DIST = testsuite.dsp test.hpp input quit make.bat
diff --git a/extra/yassl/testsuite/input b/extra/yassl/testsuite/input
new file mode 100644
index 00000000000..d16cbc40750
--- /dev/null
+++ b/extra/yassl/testsuite/input
@@ -0,0 +1,107 @@
+// testsuite.cpp
+
+#include "test.hpp"
+#include "md5.hpp"
+
+typedef unsigned char byte;
+
+void taocrypt_test(void*);
+void file_test(char*, byte*);
+
+void client_test(void*);
+void echoclient_test(void*);
+
+THREAD_RETURN YASSL_API server_test(void*);
+THREAD_RETURN YASSL_API echoserver_test(void*);
+
+int main(int argc, char** argv)
+{
+ func_args args(argc, argv);
+ func_args server_args(args);
+
+ // *** Crypto Test ***
+ taocrypt_test(&args);
+ assert(args.return_code == 0);
+
+
+ // *** Simple yaSSL client server test ***
+ THREAD_TYPE thread;
+
+ start_thread(server_test, &server_args, &thread);
+ client_test(&args);
+
+ assert(args.return_code == 0);
+ join_thread(thread);
+ assert(server_args.return_code == 0);
+
+
+ // *** Echo input yaSSL client server test ***
+ start_thread(echoserver_test, &server_args, &thread);
+ func_args echo_args;
+
+ // setup args
+ echo_args.argc = 3;
+ echo_args.argv = new char*[echo_args.argc];
+ for (int i = 0; i < echo_args.argc; i++)
+ echo_args.argv[i] = new char[32];
+
+ strcpy(echo_args.argv[0], "echoclient");
+ strcpy(echo_args.argv[1], "input");
+ strcpy(echo_args.argv[2], "output");
+ remove("output");
+
+ // make sure OK
+ echoclient_test(&echo_args);
+ assert(echo_args.return_code == 0);
+
+
+ // *** Echo quit yaSSL client server test ***
+ echo_args.argc = 2;
+ strcpy(echo_args.argv[1], "quit");
+
+ echoclient_test(&echo_args);
+ assert(echo_args.return_code == 0);
+ join_thread(thread);
+ assert(server_args.return_code == 0);
+
+
+ // input output compare
+ byte input[TaoCrypt::MD5::DIGEST_SIZE];
+ byte output[TaoCrypt::MD5::DIGEST_SIZE];
+ file_test("input", input);
+ file_test("output", output);
+ assert(memcmp(input, output, sizeof(input)) == 0);
+
+ printf("\nAll tests passed!\n");
+
+ // cleanup
+ for (int j = echo_args.argc; j >= 0; j--)
+ delete[] echo_args.argv[j];
+ delete[] echo_args.argv;
+
+ return 0;
+}
+
+
+
+void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread)
+{
+#ifdef _WIN32
+ *thread = _beginthreadex(0, 0, fun, args, 0, 0);
+#else
+ pthread_create(thread, 0, fun, args);
+#endif
+}
+
+
+void join_thread(THREAD_TYPE thread)
+{
+#ifdef _WIN32
+ int res = WaitForSingleObject(reinterpret_cast<HANDLE>(thread), INFINITE);
+ assert(res == WAIT_OBJECT_0);
+ res = CloseHandle(reinterpret_cast<HANDLE>(thread));
+ assert(res);
+#else
+ pthread_join(thread, 0);
+#endif
+}
diff --git a/extra/yassl/testsuite/make.bat b/extra/yassl/testsuite/make.bat
new file mode 100644
index 00000000000..1bc7ce0513d
--- /dev/null
+++ b/extra/yassl/testsuite/make.bat
@@ -0,0 +1,14 @@
+REM quick and dirty build file for testing different MSDEVs
+setlocal
+
+set myFLAGS= /I../include /I../taocrypt/include /I../mySTL /c /W3 /G6 /O2 /MT /D"WIN32" /D"NO_MAIN_DRIVER"
+
+cl %myFLAGS% testsuite.cpp
+cl %myFLAGS% ../examples/client/client.cpp
+cl %myFLAGS% ../examples/echoclient/echoclient.cpp
+cl %myFLAGS% ../examples/server/server.cpp
+cl %myFLAGS% ../examples/echoserver/echoserver.cpp
+cl %myFLAGS% ../taocrypt/test/test.cpp
+
+link.exe /out:testsuite.exe ../src/yassl.lib ../taocrypt/src/taocrypt.lib testsuite.obj client.obj server.obj echoclient.obj echoserver.obj test.obj advapi32.lib Ws2_32.lib
+
diff --git a/extra/yassl/testsuite/quit b/extra/yassl/testsuite/quit
new file mode 100644
index 00000000000..3db49b3ad12
--- /dev/null
+++ b/extra/yassl/testsuite/quit
@@ -0,0 +1,2 @@
+quit
+
diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp
new file mode 100644
index 00000000000..c80e3ad23da
--- /dev/null
+++ b/extra/yassl/testsuite/test.hpp
@@ -0,0 +1,358 @@
+// test.hpp
+
+#ifndef yaSSL_TEST_HPP
+#define yaSSL_TEST_HPP
+
+#include "runtime.hpp"
+#include "openssl/ssl.h" /* openssl compatibility test */
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <process.h>
+ #define SOCKET_T unsigned int
+#else
+ #include <string.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <sys/ioctl.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <pthread.h>
+ #define SOCKET_T int
+#endif /* _WIN32 */
+
+
+#if !defined(_SOCKLEN_T) && (defined(__MACH__) || defined(_WIN32))
+ typedef int socklen_t;
+#endif
+
+
+// HPUX doesn't use socklent_t for third parameter to accept
+#if !defined(__hpux)
+ typedef socklen_t* ACCEPT_THIRD_T;
+#else
+ typedef int* ACCEPT_THIRD_T;
+
+// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented
+#ifndef _POSIX_THREADS
+#define _POSIX_THREADS
+#endif
+
+#endif
+
+
+#ifndef _POSIX_THREADS
+ typedef unsigned int THREAD_RETURN;
+ typedef unsigned long THREAD_TYPE;
+ #define YASSL_API __stdcall
+#else
+ typedef void* THREAD_RETURN;
+ typedef pthread_t THREAD_TYPE;
+ #define YASSL_API
+#endif
+
+
+struct tcp_ready {
+#ifdef _POSIX_THREADS
+ pthread_mutex_t mutex_;
+ pthread_cond_t cond_;
+ bool ready_; // predicate
+
+ tcp_ready() : ready_(false)
+ {
+ pthread_mutex_init(&mutex_, 0);
+ pthread_cond_init(&cond_, 0);
+ }
+
+ ~tcp_ready()
+ {
+ pthread_mutex_destroy(&mutex_);
+ pthread_cond_destroy(&cond_);
+ }
+#endif
+};
+
+
+struct func_args {
+ int argc;
+ char** argv;
+ int return_code;
+ tcp_ready* signal_;
+
+ func_args(int c = 0, char** v = 0) : argc(c), argv(v) {}
+
+ void SetSignal(tcp_ready* p) { signal_ = p; }
+};
+
+typedef THREAD_RETURN YASSL_API THREAD_FUNC(void*);
+
+void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*);
+void join_thread(THREAD_TYPE);
+
+// yaSSL
+const char* const yasslIP = "127.0.0.1";
+const unsigned short yasslPort = 11111;
+
+
+// client
+const char* const cert = "../certs/client-cert.pem";
+const char* const key = "../certs/client-key.pem";
+
+const char* const certSuite = "../../certs/client-cert.pem";
+const char* const keySuite = "../../certs/client-key.pem";
+
+const char* const certDebug = "../../../certs/client-cert.pem";
+const char* const keyDebug = "../../../certs/client-key.pem";
+
+
+// server
+const char* const svrCert = "../certs/server-cert.pem";
+const char* const svrKey = "../certs/server-key.pem";
+
+const char* const svrCert2 = "../../certs/server-cert.pem";
+const char* const svrKey2 = "../../certs/server-key.pem";
+
+const char* const svrCert3 = "../../../certs/server-cert.pem";
+const char* const svrKey3 = "../../../certs/server-key.pem";
+
+
+// server dsa
+const char* const dsaCert = "../certs/dsa-cert.pem";
+const char* const dsaKey = "../certs/dsa512.der";
+
+const char* const dsaCert2 = "../../certs/dsa-cert.pem";
+const char* const dsaKey2 = "../../certs/dsa512.der";
+
+const char* const dsaCert3 = "../../../certs/dsa-cert.pem";
+const char* const dsaKey3 = "../../../certs/dsa512.der";
+
+
+// CA
+const char* const caCert = "../certs/ca-cert.pem";
+const char* const caCert2 = "../../certs/ca-cert.pem";
+const char* const caCert3 = "../../../certs/ca-cert.pem";
+
+
+using namespace yaSSL;
+
+
+inline void err_sys(const char* msg)
+{
+ printf("yassl error: %s\n", msg);
+ exit(EXIT_FAILURE);
+}
+
+
+inline void store_ca(SSL_CTX* ctx)
+{
+ // To allow testing from serveral dirs
+ if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, caCert2, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, caCert3, 0) != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/cacert.pem");
+
+ // load client CA for server verify
+ if (SSL_CTX_load_verify_locations(ctx, cert, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, certSuite, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, certDebug,0) != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/client-cert.pem");
+}
+
+
+// client
+inline void set_certs(SSL_CTX* ctx)
+{
+ store_ca(ctx);
+
+ // To allow testing from serveral dirs
+ if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, certSuite, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, certDebug, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/client-cert.pem");
+
+ // To allow testing from several dirs
+ if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx, keySuite, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx,keyDebug,SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ err_sys("failed to use key file: certs/client-key.pem");
+}
+
+
+// server
+inline void set_serverCerts(SSL_CTX* ctx)
+{
+ store_ca(ctx);
+
+ // To allow testing from serveral dirs
+ if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, svrCert2, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, svrCert3, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/server-cert.pem");
+
+ // To allow testing from several dirs
+ if (SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx, svrKey2, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx, svrKey3,SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ err_sys("failed to use key file: certs/server-key.pem");
+}
+
+
+// dsa server
+inline void set_dsaServerCerts(SSL_CTX* ctx)
+{
+ store_ca(ctx);
+
+ // To allow testing from serveral dirs
+ if (SSL_CTX_use_certificate_file(ctx, dsaCert, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, dsaCert2, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_certificate_file(ctx, dsaCert3, SSL_FILETYPE_PEM)
+ != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/dsa-cert.pem");
+
+ // To allow testing from several dirs
+ if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey, SSL_FILETYPE_ASN1)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey2, SSL_FILETYPE_ASN1)
+ != SSL_SUCCESS)
+ if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey3,SSL_FILETYPE_ASN1)
+ != SSL_SUCCESS)
+ err_sys("failed to use key file: certs/dsa512.der");
+}
+
+
+inline void set_args(int& argc, char**& argv, func_args& args)
+{
+ argc = args.argc;
+ argv = args.argv;
+ args.return_code = -1; // error state
+}
+
+
+inline void tcp_socket(SOCKET_T& sockfd, sockaddr_in& addr)
+{
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+
+ addr.sin_port = htons(yasslPort);
+ addr.sin_addr.s_addr = inet_addr(yasslIP);
+}
+
+
+inline void tcp_connect(SOCKET_T& sockfd)
+{
+ sockaddr_in addr;
+ tcp_socket(sockfd, addr);
+
+ if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0)
+ err_sys("tcp connect failed");
+}
+
+
+inline void tcp_listen(SOCKET_T& sockfd)
+{
+ sockaddr_in addr;
+ tcp_socket(sockfd, addr);
+
+ if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0)
+ err_sys("tcp bind failed");
+ if (listen(sockfd, 3) != 0)
+ err_sys("tcp listen failed");
+}
+
+
+inline void tcp_accept(SOCKET_T& sockfd, int& clientfd, func_args& args)
+{
+ tcp_listen(sockfd);
+
+ sockaddr_in client;
+ socklen_t client_len = sizeof(client);
+
+#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER)
+ // signal ready to tcp_accept
+ tcp_ready& ready = *args.signal_;
+ pthread_mutex_lock(&ready.mutex_);
+ ready.ready_ = true;
+ pthread_cond_signal(&ready.cond_);
+ pthread_mutex_unlock(&ready.mutex_);
+#endif
+
+ clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len);
+
+ if (clientfd == -1)
+ err_sys("tcp accept failed");
+}
+
+
+inline void showPeer(SSL* ssl)
+{
+ X509* peer = SSL_get_peer_certificate(ssl);
+ if (peer) {
+ char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0);
+ char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0);
+
+ printf("peer's cert info:\n");
+ printf("issuer : %s\n", issuer);
+ printf("subject: %s\n", subject);
+
+ free(subject);
+ free(issuer);
+ }
+ else
+ printf("peer has no cert!\n");
+}
+
+
+
+inline DH* set_tmpDH(SSL_CTX* ctx)
+{
+ static unsigned char dh512_p[] =
+ {
+ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+ 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+ 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+ 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+ 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+ 0x47,0x74,0xE8,0x33,
+ };
+
+ static unsigned char dh512_g[] =
+ {
+ 0x02,
+ };
+
+ DH* dh;
+ if ( (dh = DH_new()) ) {
+ dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), 0);
+ dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), 0);
+ }
+ if (!dh->p || !dh->g) {
+ DH_free(dh);
+ dh = 0;
+ }
+ SSL_CTX_set_tmp_dh(ctx, dh);
+ return dh;
+}
+
+
+#endif // yaSSL_TEST_HPP
+
diff --git a/extra/yassl/testsuite/testsuite.cpp b/extra/yassl/testsuite/testsuite.cpp
new file mode 100644
index 00000000000..1cf6a78ebe7
--- /dev/null
+++ b/extra/yassl/testsuite/testsuite.cpp
@@ -0,0 +1,156 @@
+// testsuite.cpp
+
+#include "test.hpp"
+#include "md5.hpp"
+
+
+typedef unsigned char byte;
+
+void taocrypt_test(void*);
+void file_test(char*, byte*);
+
+void client_test(void*);
+void echoclient_test(void*);
+
+THREAD_RETURN YASSL_API server_test(void*);
+THREAD_RETURN YASSL_API echoserver_test(void*);
+
+void wait_tcp_ready(func_args&);
+
+
+
+int main(int argc, char** argv)
+{
+ func_args args(argc, argv);
+ func_args server_args(argc, argv);
+
+ // *** Crypto Test ***
+ taocrypt_test(&args);
+ assert(args.return_code == 0);
+
+
+ // *** Simple yaSSL client server test ***
+ tcp_ready ready;
+ server_args.SetSignal(&ready);
+
+ THREAD_TYPE serverThread;
+ start_thread(server_test, &server_args, &serverThread);
+ wait_tcp_ready(server_args);
+
+ client_test(&args);
+ assert(args.return_code == 0);
+ join_thread(serverThread);
+ assert(server_args.return_code == 0);
+
+
+ // *** Echo input yaSSL client server test ***
+ start_thread(echoserver_test, &server_args, &serverThread);
+ wait_tcp_ready(server_args);
+ func_args echo_args;
+
+ // setup args
+ const int numArgs = 3;
+ echo_args.argc = numArgs;
+ char* myArgv[numArgs];
+
+ char argc0[32];
+ char argc1[32];
+ char argc2[32];
+
+ myArgv[0] = argc0;
+ myArgv[1] = argc1;
+ myArgv[2] = argc2;
+
+ echo_args.argv = myArgv;
+
+ strcpy(echo_args.argv[0], "echoclient");
+ strcpy(echo_args.argv[1], "input");
+ strcpy(echo_args.argv[2], "output");
+ remove("output");
+
+ // make sure OK
+ echoclient_test(&echo_args);
+ assert(echo_args.return_code == 0);
+
+
+ // *** Echo quit yaSSL client server test ***
+ echo_args.argc = 2;
+ strcpy(echo_args.argv[1], "quit");
+
+ echoclient_test(&echo_args);
+ assert(echo_args.return_code == 0);
+ join_thread(serverThread);
+ assert(server_args.return_code == 0);
+
+
+ // input output compare
+ byte input[TaoCrypt::MD5::DIGEST_SIZE];
+ byte output[TaoCrypt::MD5::DIGEST_SIZE];
+ file_test("input", input);
+ file_test("output", output);
+ assert(memcmp(input, output, sizeof(input)) == 0);
+
+ printf("\nAll tests passed!\n");
+ yaSSL_CleanUp();
+
+ return 0;
+}
+
+
+
+void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread)
+{
+#ifndef _POSIX_THREADS
+ *thread = _beginthreadex(0, 0, fun, args, 0, 0);
+#else
+ pthread_create(thread, 0, fun, args);
+#endif
+}
+
+
+void join_thread(THREAD_TYPE thread)
+{
+#ifndef _POSIX_THREADS
+ int res = WaitForSingleObject(reinterpret_cast<HANDLE>(thread), INFINITE);
+ assert(res == WAIT_OBJECT_0);
+ res = CloseHandle(reinterpret_cast<HANDLE>(thread));
+ assert(res);
+#else
+ pthread_join(thread, 0);
+#endif
+}
+
+
+
+void wait_tcp_ready(func_args& args)
+{
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(&args.signal_->mutex_);
+
+ if (!args.signal_->ready_)
+ pthread_cond_wait(&args.signal_->cond_, &args.signal_->mutex_);
+ args.signal_->ready_ = false; // reset
+
+ pthread_mutex_unlock(&args.signal_->mutex_);
+#endif
+}
+
+
+int test_openSSL_des()
+{
+ /* test des encrypt/decrypt */
+ char data[] = "this is my data ";
+ int dataSz = strlen(data);
+ DES_key_schedule key[3];
+ byte iv[8];
+ EVP_BytesToKey(EVP_des_ede3_cbc(), EVP_md5(), NULL, (byte*)data, dataSz, 1,
+ (byte*)key, iv);
+
+ byte cipher[16];
+ DES_ede3_cbc_encrypt((byte*)data, cipher, dataSz, &key[0], &key[1],
+ &key[2], &iv, true);
+ byte plain[16];
+ DES_ede3_cbc_encrypt(cipher, plain, 16, &key[0], &key[1], &key[2],
+ &iv, false);
+ return 0;
+}
diff --git a/extra/yassl/testsuite/testsuite.dsp b/extra/yassl/testsuite/testsuite.dsp
new file mode 100644
index 00000000000..24c325fa878
--- /dev/null
+++ b/extra/yassl/testsuite/testsuite.dsp
@@ -0,0 +1,127 @@
+# Microsoft Developer Studio Project File - Name="testsuite" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=testsuite - 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 "testsuite.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 "testsuite.mak" CFG="testsuite - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "testsuite - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "testsuite - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "testsuite - 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 "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /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
+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 Ws2_32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"LIBC"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF "$(CFG)" == "testsuite - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /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
+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 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCD" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "testsuite - Win32 Release"
+# Name "testsuite - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\client\client.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\examples\echoclient\echoclient.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\examples\echoserver\echoserver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\examples\server\server.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\taocrypt\test\test.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsuite.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\test.hpp
+# End Source File
+# 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/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp
index f51c19eebbf..dc090512743 100644
--- a/extra/yassl/yassl.dsp
+++ b/extra/yassl/yassl.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 /MT /W3 /GX- /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /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
@@ -64,7 +64,7 @@ LIB32=link.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 /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 CPP /nologo /MTd /W3 /Gm /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
diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw
index c0bba9acdce..288c88dfd5b 100644
--- a/extra/yassl/yassl.dsw
+++ b/extra/yassl/yassl.dsw
@@ -3,6 +3,21 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
###############################################################################
+Project: "benchmark"=.\taocrypt\benchmark\benchmark.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
Project: "client"=.\examples\client\client.dsp - Package Owner=<4>
Package=<5>
diff --git a/include/config-win.h b/include/config-win.h
index b6fb1077cc6..aa372762191 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -25,6 +25,7 @@ functions */
#if defined(_MSC_VER) && _MSC_VER >= 1400
/* Avoid endless warnings about sprintf() etc. being unsafe. */
#define _CRT_SECURE_NO_DEPRECATE 1
+#define _USE_32BIT_TIME_T 1 /* force time_t to be 32 bit */
#endif
#include <sys/locking.h>
@@ -95,7 +96,7 @@ functions */
#define O_SHORT_LIVED 0
#define SH_DENYNO _SH_DENYNO
#else
-#define O_BINARY _O_BINARY /* compability with MSDOS */
+#define O_BINARY _O_BINARY /* compability with older style names */
#define FILE_BINARY _O_BINARY /* my_fopen in binary mode */
#define O_TEMPORARY _O_TEMPORARY
#define O_SHORT_LIVED _O_SHORT_LIVED
@@ -382,6 +383,7 @@ inline double ulonglong2double(ulonglong value)
#include <custom_conf.h>
#else
#define DEFAULT_MYSQL_HOME "c:\\mysql"
+#define DATADIR "c:\\mysql\\data"
#define PACKAGE "mysql"
#define DEFAULT_BASEDIR "C:\\"
#define SHAREDIR "share"
diff --git a/include/heap.h b/include/heap.h
index 855cff117e2..4c003462a45 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -111,7 +111,7 @@ struct st_heap_info; /* For referense */
typedef struct st_hp_keydef /* Key definition with open */
{
- uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */
+ uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */
uint keysegs; /* Number of key-segment */
uint length; /* Length of key (automatic) */
uint8 algorithm; /* HASH / BTREE */
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 913272b2a11..40cadad0017 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -176,7 +176,7 @@ typedef struct my_charset_handler_st
uint (*lengthsp)(struct charset_info_st *, const char *ptr, uint length);
uint (*numcells)(struct charset_info_st *, const char *b, const char *e);
- /* Unicode convertion */
+ /* Unicode conversion */
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
const unsigned char *s,const unsigned char *e);
int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
@@ -186,7 +186,7 @@ typedef struct my_charset_handler_st
int (*ctype)(struct charset_info_st *cs, int *ctype,
const unsigned char *s, const unsigned char *e);
- /* Functions for case and sort convertion */
+ /* Functions for case and sort conversion */
void (*caseup_str)(struct charset_info_st *, char *);
void (*casedn_str)(struct charset_info_st *, char *);
uint (*caseup)(struct charset_info_st *, char *src, uint srclen,
@@ -204,7 +204,7 @@ typedef struct my_charset_handler_st
void (*fill)(struct charset_info_st *, char *to, uint len, int fill);
- /* String-to-number convertion routines */
+ /* String-to-number conversion routines */
long (*strntol)(struct charset_info_st *, const char *s, uint l,
int base, char **e, int *err);
ulong (*strntoul)(struct charset_info_st *, const char *s, uint l,
diff --git a/include/m_string.h b/include/m_string.h
index e73f5c11487..9f7ec220f2c 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -106,12 +106,6 @@ extern char NEAR _dig_vec_lower[];
#define memcpy_fixed(A,B,C) memcpy((A),(B),(C))
#endif
-#ifdef MSDOS
-#undef bmove_align
-#define bmove512(A,B,C) bmove_align(A,B,C)
-extern void bmove_align(gptr dst,const gptr src,uint len);
-#endif
-
#if (!defined(USE_BMOVE512) || defined(HAVE_purify)) && !defined(bmove512)
#define bmove512(A,B,C) memcpy(A,B,C)
#endif
@@ -246,4 +240,22 @@ extern int my_snprintf(char* to, size_t n, const char* fmt, ...);
#if defined(__cplusplus)
}
#endif
+
+/*
+ LEX_STRING -- a pair of a C-string and its length.
+
+ NOTE: this exactly form of declaration is required for some C-compilers
+ (for one, Sun C 5.7 2005/01/07). Unfortunatelt with such declaration
+ LEX_STRING can not be forward declared.
+*/
+
+typedef struct
+{
+ char *str;
+ uint length;
+} LEX_STRING;
+
+#define STRING_WITH_LEN(X) (X), ((uint) (sizeof(X) - 1))
+#define C_STRING_WITH_SIZE(X) ((char *) (X)), ((uint) (sizeof(X) - 1))
+
#endif
diff --git a/include/my_base.h b/include/my_base.h
index b9a806cc02f..e77bffeaf94 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -33,9 +33,6 @@
#define EOVERFLOW 84
#endif
-#ifdef MSDOS
-#include <share.h> /* Neaded for sopen() */
-#endif
#if !defined(USE_MY_FUNC) && !defined(THREAD)
#include <my_nosys.h> /* For faster code, after test */
#endif /* USE_MY_FUNC */
@@ -231,6 +228,7 @@ enum ha_base_keytype {
#define HA_VAR_LENGTH_KEY 8
#define HA_NULL_PART_KEY 64
#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */
+#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
/*
Key has a part that can have end space. If this is an unique key
@@ -339,7 +337,7 @@ enum ha_base_keytype {
#define HA_ERR_WRONG_COMMAND 131 /* Command not supported */
#define HA_ERR_OLD_FILE 132 /* old databasfile */
#define HA_ERR_NO_ACTIVE_RECORD 133 /* No record read in update() */
-#define HA_ERR_RECORD_DELETED 134 /* Intern error-code */
+#define HA_ERR_RECORD_DELETED 134 /* A record is not there */
#define HA_ERR_RECORD_FILE_FULL 135 /* No more room in file */
#define HA_ERR_INDEX_FILE_FULL 136 /* No more room in file */
#define HA_ERR_END_OF_FILE 137 /* end in next/prev/first/last */
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 65bb7b55d0d..a397861c1af 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -42,6 +42,7 @@ 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_end_(void);
extern void _db_lock_file_(void);
extern void _db_unlock_file_(void);
extern FILE *_db_fp_(void);
@@ -73,6 +74,7 @@ extern FILE *_db_fp_(void);
#define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
#define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
+#define DBUG_END() _db_end_ ()
#define DBUG_LOCK_FILE _db_lock_file_()
#define DBUG_UNLOCK_FILE _db_unlock_file_()
#define DBUG_ASSERT(A) assert(A)
@@ -97,6 +99,7 @@ extern FILE *_db_fp_(void);
#define DBUG_SETJMP(a1) setjmp(a1)
#define DBUG_LONGJMP(a1) longjmp(a1)
#define DBUG_DUMP(keyword,a1,a2)
+#define DBUG_END()
#define DBUG_ASSERT(A)
#define DBUG_LOCK_FILE
#define DBUG_FILE (stderr)
diff --git a/include/my_global.h b/include/my_global.h
index cd0eda8aa45..100e695a0de 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -78,6 +78,15 @@
#endif
#endif /* _WIN32... */
+#ifndef EMBEDDED_LIBRARY
+#ifdef WITH_ROW_BASED_REPLICATION
+#define HAVE_ROW_BASED_REPLICATION 1
+#endif
+#ifdef WITH_NDB_BINLOG
+#define HAVE_NDB_BINLOG 1
+#endif
+#endif /* !EMBEDDED_LIBRARY */
+
/* Some defines to avoid ifdefs in the code */
#ifndef NETWARE_YIELD
#define NETWARE_YIELD
@@ -536,7 +545,7 @@ typedef unsigned short ushort;
/*
Wen using the embedded library, users might run into link problems,
- dupicate declaration of __cxa_pure_virtual, solved by declaring it a
+ duplicate declaration of __cxa_pure_virtual, solved by declaring it a
weak symbol.
*/
#ifdef USE_MYSYS_NEW
diff --git a/include/my_net.h b/include/my_net.h
index f953a832e6b..b26e525016b 100644
--- a/include/my_net.h
+++ b/include/my_net.h
@@ -44,7 +44,7 @@ C_MODE_START
#include <sys/ioctl.h>
#endif
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__NETWARE__)
+#if !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__NETWARE__)
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -53,7 +53,7 @@ C_MODE_START
#endif
#endif
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#define O_NONBLOCK 1 /* For emulation of fcntl() */
#endif
diff --git a/include/my_nosys.h b/include/my_nosys.h
index 605906f0e07..41b919c1a72 100644
--- a/include/my_nosys.h
+++ b/include/my_nosys.h
@@ -27,9 +27,6 @@ extern "C" {
#ifndef __MY_NOSYS__
#define __MY_NOSYS__
-#ifdef MSDOS
-#include <io.h> /* Get prototypes for read()... */
-#endif
#ifndef HAVE_STDLIB_H
#include <malloc.h>
#endif
diff --git a/include/my_pthread.h b/include/my_pthread.h
index acd1d2b558b..0cb38d29be8 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -226,12 +226,14 @@ int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */
we want to make sure that no such flags are set.
*/
#if defined(HAVE_SIGACTION) && !defined(my_sigset)
-#define my_sigset(A,B) do { struct sigaction s; sigset_t set; \
+#define my_sigset(A,B) do { struct sigaction s; sigset_t set; int rc; \
+ DBUG_ASSERT((A) != 0); \
sigemptyset(&set); \
s.sa_handler = (B); \
s.sa_mask = set; \
s.sa_flags = 0; \
- sigaction((A), &s, (struct sigaction *) NULL); \
+ rc= sigaction((A), &s, (struct sigaction *) NULL);\
+ DBUG_ASSERT(rc == 0); \
} while (0)
#elif defined(HAVE_SIGSET) && !defined(my_sigset)
#define my_sigset(A,B) sigset((A),(B))
diff --git a/include/my_sys.h b/include/my_sys.h
index 51883e8d6f9..5024505a821 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -75,6 +75,11 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
#define MY_GIVE_INFO 2 /* Give time info about process*/
+#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */
+
+#define MY_REMOVE_NONE 0 /* Params for modify_defaults_file */
+#define MY_REMOVE_OPTION 1
+#define MY_REMOVE_SECTION 2
#define ME_HIGHBYTE 8 /* Shift for colours */
#define ME_NOCUR 1 /* Don't use curses message */
@@ -196,22 +201,6 @@ extern void my_large_free(gptr ptr, myf my_flags);
#define my_afree(PTR) my_free(PTR,MYF(MY_WME))
#endif /* HAVE_ALLOCA */
-#ifdef MSDOS
-#ifdef __ZTC__
-void * __CDECL halloc(long count,size_t length);
-void __CDECL hfree(void *ptr);
-#endif
-#if defined(USE_HALLOC)
-#if defined(_VCM_) || defined(M_IC80386)
-#undef USE_HALLOC
-#endif
-#endif
-#ifdef USE_HALLOC
-#define malloc(a) halloc((long) (a),1)
-#define free(a) hfree(a)
-#endif
-#endif /* MSDOS */
-
#ifndef errno /* did we already get it? */
#ifdef HAVE_ERRNO_AS_DEFINE
#include <errno.h> /* errno is a define */
@@ -558,8 +547,9 @@ 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,
uint error_message_number, myf MyFlags);
+extern void my_print_open_files(void);
extern File my_create(const char *FileName,int CreateFlags,
- int AccsesFlags, myf MyFlags);
+ int AccessFlags, myf MyFlags);
extern int my_close(File Filedes,myf MyFlags);
extern File my_dup(File file, myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
@@ -601,6 +591,11 @@ extern char *_my_strndup(const byte *from, uint length,
const char *sFile, uint uLine,
myf MyFlag);
+/* implemented in my_memmem.c */
+extern void *my_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+
+
#ifdef __WIN__
extern int my_access(const char *path, int amode);
extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
@@ -642,6 +637,12 @@ extern void allow_break(void);
#define allow_break()
#endif
+#ifdef EXTRA_DEBUG
+void my_print_open_files();
+#else
+#define my_print_open_files()
+#endif
+
extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist);
extern char *my_tmpdir(MY_TMPDIR *tmpdir);
extern void free_tmpdir(MY_TMPDIR *tmpdir);
@@ -812,6 +813,7 @@ extern int unpackfrm(const void **, uint *, const void *);
extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
+extern uint32 my_round_up_to_next_power(uint32 v);
extern uint my_count_bits(ulonglong v);
extern uint my_count_bits_ushort(ushort v);
extern void my_sleep(ulong m_seconds);
diff --git a/include/my_time.h b/include/my_time.h
index 2b0dc4ac6ff..df500dc501b 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -38,7 +38,10 @@ typedef long my_time_t;
#define MY_TIME_T_MAX LONG_MAX
#define MY_TIME_T_MIN LONG_MIN
+/* two-digit years < this are 20..; >= this are 19.. */
#define YY_PART_YEAR 70
+/* apply above magic to years < this */
+#define YY_MAGIC_BELOW 200
/* Flags to str_to_datetime */
#define TIME_FUZZY_DATE 1
diff --git a/include/my_tree.h b/include/my_tree.h
index 14d8593b6dc..e9746ca1b2c 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -40,19 +40,11 @@ typedef int (*tree_walk_action)(void *,element_count,void *);
typedef enum { free_init, free_free, free_end } TREE_FREE;
typedef void (*tree_element_free)(void*, TREE_FREE, void *);
-#ifdef MSDOS
-typedef struct st_tree_element {
- struct st_tree_element *left,*right;
- unsigned long count;
- uchar colour; /* black is marked as 1 */
-} TREE_ELEMENT;
-#else
typedef struct st_tree_element {
struct st_tree_element *left,*right;
uint32 count:31,
colour:1; /* black is marked as 1 */
} TREE_ELEMENT;
-#endif /* MSDOS */
#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs))
@@ -84,7 +76,7 @@ TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit);
-int tree_delete(TREE *tree, void *key, void *custom_arg);
+int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg);
void *tree_search_key(TREE *tree, const void *key,
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
enum ha_rkey_function flag, void *custom_arg);
diff --git a/include/myisam.h b/include/myisam.h
index 5116f48eeb5..db1a7bd984d 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -192,7 +192,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
uint16 keylength; /* Tot length of keyparts (auto) */
uint16 minlength; /* min length of (packed) key (auto) */
uint16 maxlength; /* max length of (packed) key (auto) */
- uint16 block_size; /* block_size (auto) */
+ uint16 block_size_index; /* block_size (auto) */
uint32 version; /* For concurrent read/write */
uint32 ftparser_nr; /* distinct ftparser number */
diff --git a/include/mysql.h b/include/mysql.h
index 6217ce631b5..3a71e47f414 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -149,7 +149,8 @@ enum mysql_option
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_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT
+ MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT
};
struct st_mysql_options {
@@ -164,6 +165,7 @@ struct st_mysql_options {
char *ssl_ca; /* PEM CA file */
char *ssl_capath; /* PEM directory of CA-s? */
char *ssl_cipher; /* cipher to use */
+ my_bool ssl_verify_server_cert; /* if to verify server cert */
char *shared_memory_base_name;
unsigned long max_allowed_packet;
my_bool use_ssl; /* if to use SSL or not */
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index a7b3606061f..ab5ca6e7be4 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -37,10 +37,25 @@
be a st_mysql_plugin struct for each plugin to be declared.
*/
-#define mysql_declare_plugin \
-int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
-int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
+
+#ifndef MYSQL_DYNAMIC_PLUGIN
+#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_mysql_plugin); \
+struct st_mysql_plugin DECLS[]= {
+#else
+#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
+int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
+int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+#endif
+
+#define mysql_declare_plugin(NAME) \
+__MYSQL_DECLARE_PLUGIN(NAME, \
+ builtin_ ## NAME ## _plugin_interface_version, \
+ builtin_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0}}
/*
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 2af0fb86906..bff5fcc47d2 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -423,17 +423,11 @@ char *octet2hex(char *to, const char *str, unsigned int len);
/* end of password.c */
-char *get_tty_password(char *opt_message);
+char *get_tty_password(const char *opt_message);
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);
void my_thread_end(void);
diff --git a/include/mysys_err.h b/include/mysys_err.h
index 341e6950792..9f104357f41 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -62,7 +62,8 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_SYNC 27
#define EE_UNKNOWN_COLLATION 28
#define EE_FILENOTFOUND 29
-#define EE_ERROR_LAST 29 /*Copy last error nr.*/
+#define EE_FILE_NOT_CLOSED 30
+#define EE_ERROR_LAST 30 /* 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/sslopt-longopts.h b/include/sslopt-longopts.h
index dc3b0922327..0435ddb815a 100644
--- a/include/sslopt-longopts.h
+++ b/include/sslopt-longopts.h
@@ -20,12 +20,6 @@
"Enable SSL for connection (automatically enabled with other flags). Disable with --skip-ssl.",
(gptr*) &opt_use_ssl, (gptr*) &opt_use_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
- {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).",
- (gptr*) &opt_ssl_key, (gptr*) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG,
- 0, 0, 0, 0, 0, 0},
- {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).",
- (gptr*) &opt_ssl_cert, (gptr*) &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG,
- 0, 0, 0, 0, 0, 0},
{"ssl-ca", OPT_SSL_CA,
"CA file in PEM format (check OpenSSL docs, implies --ssl).",
(gptr*) &opt_ssl_ca, (gptr*) &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG,
@@ -34,8 +28,19 @@
"CA directory (check OpenSSL docs, implies --ssl).",
(gptr*) &opt_ssl_capath, (gptr*) &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).",
+ (gptr*) &opt_ssl_cert, (gptr*) &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).",
(gptr*) &opt_ssl_cipher, (gptr*) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
-
+ {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).",
+ (gptr*) &opt_ssl_key, (gptr*) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+#ifdef MYSQL_CLIENT
+ {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT,
+ "Verify server's \"Common Name\" in its cert against hostname used when connecting. This option is disabled by default.",
+ (gptr*) &opt_ssl_verify_server_cert, (gptr*) &opt_ssl_verify_server_cert,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
#endif /* HAVE_OPENSSL */
diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h
index 164cf541381..7204145fc28 100644
--- a/include/sslopt-vars.h
+++ b/include/sslopt-vars.h
@@ -15,10 +15,18 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_OPENSSL
-static my_bool opt_use_ssl = 0;
-static char *opt_ssl_key = 0;
-static char *opt_ssl_cert = 0;
-static char *opt_ssl_ca = 0;
-static char *opt_ssl_capath = 0;
-static char *opt_ssl_cipher = 0;
+#ifdef SSL_VARS_NOT_STATIC
+#define SSL_STATIC
+#else
+#define SSL_STATIC static
+#endif
+SSL_STATIC my_bool opt_use_ssl = 0;
+SSL_STATIC char *opt_ssl_ca = 0;
+SSL_STATIC char *opt_ssl_capath = 0;
+SSL_STATIC char *opt_ssl_cert = 0;
+SSL_STATIC char *opt_ssl_cipher = 0;
+SSL_STATIC char *opt_ssl_key = 0;
+#ifdef MYSQL_CLIENT
+SSL_STATIC my_bool opt_ssl_verify_server_cert= 0;
+#endif
#endif
diff --git a/include/violite.h b/include/violite.h
index b48f3724f5b..4837ade64b4 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -105,33 +105,23 @@ void vio_timeout(Vio *vio,uint which, uint timeout);
#include <openssl/ssl.h>
#include <openssl/err.h>
-struct st_VioSSLAcceptorFd
+struct st_VioSSLFd
{
SSL_CTX *ssl_context;
- SSL_METHOD *ssl_method;
- struct st_VioSSLAcceptorFd *session_id_context;
};
-/* One copy for client */
-struct st_VioSSLConnectorFd
-{
- SSL_CTX *ssl_context;
- /* function pointers which are only once for SSL client */
- SSL_METHOD *ssl_method;
-};
-
-int sslaccept(struct st_VioSSLAcceptorFd*, Vio *, long timeout);
-int sslconnect(struct st_VioSSLConnectorFd*, Vio *, long timeout);
+int sslaccept(struct st_VioSSLFd*, Vio *, long timeout);
+int sslconnect(struct st_VioSSLFd*, Vio *, long timeout);
-struct st_VioSSLConnectorFd
+struct st_VioSSLFd
*new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
const char *ca_file, const char *ca_path,
const char *cipher);
-struct st_VioSSLAcceptorFd
+struct st_VioSSLFd
*new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
const char *ca_file,const char *ca_path,
const char *cipher);
-Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state);
+void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_SMEM
@@ -140,6 +130,8 @@ int vio_write_shared_memory(Vio *vio, const gptr buf, int size);
int vio_close_shared_memory(Vio * vio);
#endif
+void vio_end(void);
+
#ifdef __cplusplus
}
#endif
@@ -204,7 +196,9 @@ struct st_vio
my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
+#ifdef HAVE_OPENSSL
void *ssl_arg;
+#endif
#ifdef HAVE_SMEM
HANDLE handle_file_map;
char *handle_map;
diff --git a/libmysql/cmakelists.txt b/libmysql/CMakeLists.txt
index 35795102082..35795102082 100644
--- a/libmysql/cmakelists.txt
+++ b/libmysql/CMakeLists.txt
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 9a6f418fa49..787ffc51de7 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -31,7 +31,7 @@ include $(srcdir)/Makefile.shared
libmysqlclient_la_SOURCES = $(target_sources)
libmysqlclient_la_LIBADD = $(target_libadd) $(yassl_las)
libmysqlclient_la_LDFLAGS = $(target_ldflags)
-EXTRA_DIST = Makefile.shared libmysql.def dll.c mytest.c cmakelists.txt
+EXTRA_DIST = Makefile.shared libmysql.def dll.c mytest.c CMakeLists.txt
noinst_HEADERS = client_settings.h
# This is called from the toplevel makefile
diff --git a/libmysql/get_password.c b/libmysql/get_password.c
index a48cb6d7a6e..4c251677a66 100644
--- a/libmysql/get_password.c
+++ b/libmysql/get_password.c
@@ -75,7 +75,7 @@
#define _cputs(A) putstring(A)
#endif
-char *get_tty_password(char *opt_message)
+char *get_tty_password(const char *opt_message)
{
char to[80];
char *pos=to,*end=to+sizeof(to)-1;
@@ -159,7 +159,7 @@ static void get_password(char *to,uint length,int fd,bool echo)
#endif /* ! HAVE_GETPASS */
-char *get_tty_password(char *opt_message)
+char *get_tty_password(const char *opt_message)
{
#ifdef HAVE_GETPASS
char *passbuff;
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index b750e9cc4b2..225b3926aa7 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -178,7 +178,7 @@ void STDCALL mysql_server_end()
/* If library called my_init(), free memory allocated by it */
if (!org_my_init_done)
{
- my_end(0);
+ my_end(MY_DONT_FREE_DBUG);
/* Remove TRACING, if enabled by mysql_debug() */
DBUG_POP();
}
@@ -186,6 +186,7 @@ void STDCALL mysql_server_end()
mysql_thread_end();
finish_client_errs();
free_charsets();
+ vio_end();
mysql_client_init= org_my_init_done= 0;
#ifdef EMBEDDED_SERVER
if (stderror_file)
diff --git a/libmysqld/cmakelists.txt b/libmysqld/CMakeLists.txt
index 8bd0e0baa32..ff8ceda5c5b 100644
--- a/libmysqld/cmakelists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -33,7 +33,7 @@ ADD_LIBRARY(mysqldemb emb_qcache.cc libmysqld.c lib_sql.cc
../sql/field_conv.cc ../sql/field.cc ../sql/filesort.cc
../sql/gstream.cc ../sql/ha_heap.cc ../sql/ha_myisam.cc
../sql/ha_myisammrg.cc ${mysql_se_ha_src}
- ../sql/handler.cc ../sql/handlerton-win.cc ../sql/hash_filo.cc
+ ../sql/handler.cc ../sql/hash_filo.cc
../sql/hostname.cc ../sql/init.cc ../sql/item_buff.cc
../sql/item_cmpfunc.cc ../sql/item.cc ../sql/item_create.cc
../sql/item_func.cc ../sql/item_geofunc.cc ../sql/item_row.cc
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index a869a3ccfe9..a3af2d43bd5 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -44,7 +44,10 @@ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
- ha_heap.cc ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
+ ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
+ ha_innodb.cc ha_berkeley.cc ha_federated.cc ha_ndbcluster.cc \
+ ha_ndbcluster_binlog.cc ha_partition.cc \
+ handler.cc sql_handler.cc \
hostname.cc init.cc password.c \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
@@ -65,17 +68,12 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
spatial.cc gstream.cc sql_help.cc tztime.cc sql_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 \
- event_executor.cc event.cc event_timed.cc \
- rpl_filter.cc sql_partition.cc handlerton.cc sql_plugin.cc \
- sql_tablespace.cc \
- rpl_injector.cc my_user.c partition_info.cc
+ event_scheduler.cc event.cc event_timed.cc \
+ rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
+ sql_tablespace.cc \
+ rpl_injector.cc my_user.c partition_info.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
-EXTRA_libmysqld_a_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
- ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
- ha_ndbcluster_binlog.cc \
- ha_partition.cc
-libmysqld_a_DEPENDENCIES= @mysql_se_objs@
libmysqld_a_SOURCES=
sqlstoragesources = $(EXTRA_libmysqld_a_SOURCES)
@@ -85,20 +83,16 @@ sql_yacc.cc sql_yacc.h: $(top_srcdir)/sql/sql_yacc.yy
# The following libraries should be included in libmysqld.a
INC_LIB= $(top_builddir)/regex/libregex.a \
- $(top_builddir)/storage/myisam/libmyisam.a \
- $(top_builddir)/storage/myisammrg/libmyisammrg.a \
- $(top_builddir)/storage/archive/libarchive.a \
- $(top_builddir)/storage/heap/libheap.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/vio/libvio.a \
- @mysql_se_libs@ \
- $(yassl_las)
+ @mysql_plugin_libs@ \
+ $(yassl_inc_libs)
if HAVE_YASSL
-yassl_las = $(top_srcdir)/extra/yassl/src/libyassl.la \
- $(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la
+yassl_inc_libs= $(top_srcdir)/extra/yassl/src/.libs/libyassl.a \
+ $(top_srcdir)/extra/yassl/taocrypt/src/.libs/libtaocrypt.a
endif
# Storage engine specific compilation options
@@ -141,12 +135,12 @@ else
(for arc in ./libmysqld_int.a $(INC_LIB); do \
arpath=`echo $$arc|sed 's|[^/]*$$||'|sed 's|\.libs/$$||'`; \
artmp=`echo $$arc|sed 's|^.*/|tmp/lib-|'`; \
- for F in `$(AR) t $$arc`; do \
+ for F in `$(AR) t $$arc | grep -v SYMDEF`; do \
if test -e "$$arpath/$$F" ; then echo "$$arpath/$$F"; else \
mkdir $$artmp; cd $$artmp > /dev/null; \
$(AR) x ../../$$arc; \
cd $$current_dir > /dev/null; \
- ls $$artmp/*; \
+ ls $$artmp/* | grep -v SYMDEF; \
continue 2; fi; done; \
done; echo $(libmysqld_a_DEPENDENCIES) ) | sort -u | xargs $(AR) cq libmysqld.a ; \
$(RANLIB) libmysqld.a ; \
@@ -173,10 +167,13 @@ link_sources:
rm -f $$f; \
@LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \
done; \
- for f in $(sqlstoragesources); do \
- rm -f $$f; \
- @LN_CP_F@ `find $(srcdir)/../sql -name $$f` $$f; \
- done; \
+ if test -n "$(sqlstoragesources)" ; \
+ then \
+ for f in "$(sqlstoragesources)"; do \
+ rm -f "$$f"; \
+ @LN_CP_F@ `find $(srcdir)/../sql -name "$$f"` "$$f"; \
+ done; \
+ fi; \
rm -f client_settings.h; \
@LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
diff --git a/libmysqld/examples/cmakelists.txt b/libmysqld/examples/CMakeLists.txt
index 5c58264a7e7..5c58264a7e7 100644
--- a/libmysqld/examples/cmakelists.txt
+++ b/libmysqld/examples/CMakeLists.txt
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index 8ddf7668844..5aaddf36aa3 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -43,6 +43,8 @@ dist-hook:
$(distdir)/r \
$(distdir)/include \
$(distdir)/std_data \
+ $(distdir)/std_data/ndb_backup50 \
+ $(distdir)/std_data/ndb_backup51 \
$(distdir)/lib
-$(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t
@@ -63,6 +65,8 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(distdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup50/BACKUP* $(distdir)/std_data/ndb_backup50
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51/BACKUP* $(distdir)/std_data/ndb_backup51
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib
@@ -74,6 +78,8 @@ install-data-local:
$(DESTDIR)$(testdir)/r \
$(DESTDIR)$(testdir)/include \
$(DESTDIR)$(testdir)/std_data \
+ $(DESTDIR)$(testdir)/std_data/ndb_backup50 \
+ $(DESTDIR)$(testdir)/std_data/ndb_backup51 \
$(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir)
-$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t
@@ -98,6 +104,8 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup50/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup50
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib
diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test
index ff43debf967..6f7990893f0 100644
--- a/mysql-test/extra/binlog_tests/binlog.test
+++ b/mysql-test/extra/binlog_tests/binlog.test
@@ -22,7 +22,7 @@ insert t2 values (5);
commit;
# first COMMIT must be Query_log_event, second - Xid_log_event
--replace_column 2 # 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
drop table t1,t2;
@@ -44,8 +44,8 @@ while ($1)
commit;
drop table t1;
--replace_column 2 # 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events in 'master-bin.000001' from 102;
--replace_column 2 # 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events in 'master-bin.000002' from 102;
diff --git a/mysql-test/extra/binlog_tests/blackhole.test b/mysql-test/extra/binlog_tests/blackhole.test
index 71aec90e9a0..97243015aba 100644
--- a/mysql-test/extra/binlog_tests/blackhole.test
+++ b/mysql-test/extra/binlog_tests/blackhole.test
@@ -147,3 +147,15 @@ set autocommit=1;
--replace_column 2 # 5 #
--replace_regex /table_id: [0-9]+/table_id: #/
show binlog events;
+
+#
+# BUG#10952 - alter table ... lost data without errors and warnings
+#
+drop table if exists t1;
+create table t1 (c char(20)) engine=MyISAM;
+insert into t1 values ("Monty"),("WAX"),("Walrus");
+--error 1031
+alter table t1 engine=blackhole;
+drop table t1;
+
+# End of 5.0 tests
diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
index b75a326d5a8..241c96d078b 100644
--- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
+++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
@@ -30,7 +30,7 @@ insert into t2 select * from t1;
commit;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -44,7 +44,7 @@ insert into t2 select * from t1;
rollback;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -60,7 +60,7 @@ rollback to savepoint my_savepoint;
commit;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -78,7 +78,7 @@ commit;
select a from t1 order by a; # check that savepoints work :)
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
# and when ROLLBACK is not explicit?
@@ -100,7 +100,7 @@ connection con2;
# logging has been done, we use a user lock.
select get_lock("a",10);
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
# and when not in a transact1on?
@@ -112,7 +112,7 @@ insert into t1 values(9);
insert into t2 select * from t1;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
# Check that when the query updat1ng the MyISAM table is the first in the
@@ -125,13 +125,13 @@ insert into t1 values(10); # first make t1 non-empty
begin;
insert into t2 select * from t1;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
insert into t1 values(11);
commit;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
@@ -150,7 +150,7 @@ insert into t2 select * from t1;
commit;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -163,7 +163,7 @@ insert into t2 select * from t1;
rollback;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -179,7 +179,7 @@ rollback to savepoint my_savepoint;
commit;
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
delete from t1;
@@ -197,7 +197,7 @@ commit;
select a from t1 order by a; # check that savepoints work :)
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
# Test for BUG#5714, where a MyISAM update in the transaction used to
@@ -258,7 +258,7 @@ disconnect con2;
connection con3;
select get_lock("lock1",60);
--replace_column 5 #
---replace_regex /table_id: [0-9]+/table_id: #/
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
show binlog events from 102;
do release_lock("lock1");
drop table t0,t2;
diff --git a/mysql-test/extra/rpl_tests/rpl_deadlock.test b/mysql-test/extra/rpl_tests/rpl_deadlock.test
index 2582a901b3b..64df1f272cc 100644
--- a/mysql-test/extra/rpl_tests/rpl_deadlock.test
+++ b/mysql-test/extra/rpl_tests/rpl_deadlock.test
@@ -66,7 +66,9 @@ select * from t2;
# check that no error is reported
--replace_column 1 # 7 # 8 # 9 # 16 # 22 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
# 2) Test lock wait timeout
@@ -81,9 +83,11 @@ sync_with_master;
select * from t1; # check that slave succeeded finally
select * from t2;
# check that no error is reported
---replace_column 1 # 7 # 8 # 9 # 16 # 22 # 23 # 33 #
+--replace_column 1 # 7 # 8 # 9 # 11 # 16 # 22 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
# Now we repeat 2), but with BEGIN in the same relay log as
# COMMIT (to see if seeking into hot log is ok).
@@ -103,7 +107,9 @@ select * from t1;
select * from t2;
--replace_column 1 # 7 # 8 # 9 # 11 # 16 # 22 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
connection master;
drop table t1,t2,t3,t4;
diff --git a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
index 598f9746fab..0c537ee188d 100644
--- a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
+++ b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
@@ -17,3 +17,8 @@ OPTIMIZE TABLE non_existing;
sync_slave_with_master;
# End of 4.1 tests
+
+connection master;
+select * from t1;
+commit;
+drop table t1;
diff --git a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
index cfa943228fa..7a097fd1eae 100644
--- a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
+++ b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
@@ -3,6 +3,8 @@
# RENAME TABLE work with MERGE tables on the slave.
# Test of FLUSH NO_WRITE_TO_BINLOG by the way.
#
+
+
-- source include/master-slave.inc
create table t1 (a int);
diff --git a/mysql-test/extra/rpl_tests/rpl_insert_id.test b/mysql-test/extra/rpl_tests/rpl_insert_id.test
index a832076fbe2..304fade7e1d 100644
--- a/mysql-test/extra/rpl_tests/rpl_insert_id.test
+++ b/mysql-test/extra/rpl_tests/rpl_insert_id.test
@@ -86,3 +86,73 @@ INSERT INTO t1 VALUES (1),(1);
sync_slave_with_master;
# End of 4.1 tests
+
+
+#
+# BUG#15728: LAST_INSERT_ID function inside a stored function returns 0
+#
+# The solution is not to reset last_insert_id on enter to sub-statement.
+#
+connection master;
+--disable_warnings
+drop function if exists bug15728;
+drop function if exists bug15728_insert;
+drop table if exists t1, t2;
+--enable_warnings
+
+create table t1 (
+ id int not null auto_increment,
+ last_id int,
+ primary key (id)
+);
+create function bug15728() returns int(11)
+ return last_insert_id();
+
+insert into t1 (last_id) values (0);
+insert into t1 (last_id) values (last_insert_id());
+insert into t1 (last_id) values (bug15728());
+
+# Check that nested call replicates too.
+create table t2 (
+ id int not null auto_increment,
+ last_id int,
+ primary key (id)
+);
+delimiter |;
+create function bug15728_insert() returns int(11) modifies sql data
+begin
+ insert into t2 (last_id) values (bug15728());
+ return bug15728();
+end|
+create trigger t1_bi before insert on t1 for each row
+begin
+ declare res int;
+ select bug15728_insert() into res;
+ set NEW.last_id = res;
+end|
+delimiter ;|
+
+insert into t1 (last_id) values (0);
+
+drop trigger t1_bi;
+
+# Check that nested call doesn't affect outer context.
+select last_insert_id();
+select bug15728_insert();
+select last_insert_id();
+insert into t1 (last_id) values (bug15728());
+# This should be exactly one greater than in the previous call.
+select last_insert_id();
+
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+select * from t2;
+connection master;
+
+drop function bug15728;
+drop function bug15728_insert;
+drop table t1, t2;
+
+# End of 5.0 tests
diff --git a/mysql-test/extra/rpl_tests/rpl_log.test b/mysql-test/extra/rpl_tests/rpl_log.test
index 116bdd1028e..20ee7cd0d8f 100644
--- a/mysql-test/extra/rpl_tests/rpl_log.test
+++ b/mysql-test/extra/rpl_tests/rpl_log.test
@@ -77,11 +77,8 @@ connection slave;
# to go into the relay log (the master always sends a fake one when replication
# starts).
start slave;
-#
-# This is timing out in pushbuild and should be changed to use
-# wait_slave_status.inc
-#
-sleep 2;
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%';
+--source include/wait_slave_status.inc
sync_with_master;
flush logs;
stop slave;
diff --git a/mysql-test/include/have_case_sensitive_file_system.inc b/mysql-test/include/have_case_sensitive_file_system.inc
new file mode 100644
index 00000000000..730af975497
--- /dev/null
+++ b/mysql-test/include/have_case_sensitive_file_system.inc
@@ -0,0 +1,4 @@
+--require r/case_sensitive_file_system.require
+--disable_query_log
+show variables like "lower_case_file_system";
+--enable_query_log
diff --git a/mysql-test/include/have_ndb.inc b/mysql-test/include/have_ndb.inc
index 28fcf18cb16..8c277ea82a0 100644
--- a/mysql-test/include/have_ndb.inc
+++ b/mysql-test/include/have_ndb.inc
@@ -1,6 +1,15 @@
---exec test x$NDB_STATUS_OK = x1
+# Check that server is compiled and started with support for NDB
-- require r/have_ndb.require
disable_query_log;
show variables like "have_ndbcluster";
enable_query_log;
+# Check that NDB is installed and known to be working
+# This will disable ndb from the shell script 'mysql-test-run'
+
+-- require r/have_ndb_status_ok.require
+disable_query_log;
+eval select "$NDB_STATUS_OK" as ndb_status_ok;
+enable_query_log;
+
+
diff --git a/mysql-test/include/have_udf.inc b/mysql-test/include/have_udf.inc
index 5ed1c587385..42b9942f74d 100644
--- a/mysql-test/include/have_udf.inc
+++ b/mysql-test/include/have_udf.inc
@@ -4,11 +4,13 @@
#
--require r/have_udf.require
disable_query_log;
-show variables like "have_dlopen";
+show variables like "have_dynamic_loading";
enable_query_log;
#
-# Check that the "udf_example.so" file has been created
+# Check if the variable UDF_EXAMPLE_LIB is set
#
-
-# TODO
+--require r/have_udf_example.require
+disable_query_log;
+eval select LENGTH("$UDF_EXAMPLE_LIB") > 0 as "have_udf_example_lib";
+enable_query_log;
diff --git a/mysql-test/include/not_as_root.inc b/mysql-test/include/not_as_root.inc
new file mode 100644
index 00000000000..e0277ea593e
--- /dev/null
+++ b/mysql-test/include/not_as_root.inc
@@ -0,0 +1,4 @@
+-- require r/not_as_root.require
+disable_query_log;
+eval select "$MYSQL_TEST_ROOT" as running_as_root;
+enable_query_log;
diff --git a/mysql-test/include/rpl_multi_engine3.inc b/mysql-test/include/rpl_multi_engine3.inc
index cc1b3f13025..5d8f7e46409 100644
--- a/mysql-test/include/rpl_multi_engine3.inc
+++ b/mysql-test/include/rpl_multi_engine3.inc
@@ -28,6 +28,7 @@ INSERT INTO t1 VALUES(412,1,'Testing MySQL databases is a cool ',
select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
sync_slave_with_master;
+--sleep 5
--echo --- Select from t1 on slave ---
select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
@@ -41,9 +42,9 @@ SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
# Must give injector thread a little time to get update
# into the binlog other wise we will miss the update.
-sleep 10;
sync_slave_with_master;
+--sleep 5
--echo --- Check Update on slave ---
SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
@@ -55,6 +56,7 @@ DELETE FROM t1 WHERE id = 42;
SELECT COUNT(*) FROM t1;
sync_slave_with_master;
+--sleep 5
--echo --- Show current count on slave for t1 ---
SELECT COUNT(*) FROM t1;
diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql
index a7079b0ac33..a5736ed4b9b 100644
--- a/mysql-test/lib/init_db.sql
+++ b/mysql-test/lib/init_db.sql
@@ -631,7 +631,7 @@ CREATE TABLE event (
'HIGH_NOT_PRECEDENCE'
) DEFAULT '' NOT NULL,
comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- PRIMARY KEY (definer, db, name)
+ PRIMARY KEY (db, name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE DATABASE IF NOT EXISTS cluster;
diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl
index 5b2fd5c6df6..bc44c440c32 100644
--- a/mysql-test/lib/mtr_misc.pl
+++ b/mysql-test/lib/mtr_misc.pl
@@ -12,6 +12,7 @@ sub mtr_init_args ($);
sub mtr_add_arg ($$@);
sub mtr_path_exists(@);
sub mtr_script_exists(@);
+sub mtr_file_exists(@);
sub mtr_exe_exists(@);
sub mtr_copy_dir($$);
sub mtr_same_opts($$);
@@ -94,12 +95,27 @@ sub mtr_script_exists (@) {
}
}
+sub mtr_file_exists (@) {
+ foreach my $path ( @_ )
+ {
+ return $path if -e $path;
+ }
+ return "";
+}
+
sub mtr_exe_exists (@) {
my @path= @_;
map {$_.= ".exe"} @path if $::glob_win32;
foreach my $path ( @path )
{
- return $path if -x $path;
+ if($::glob_win32)
+ {
+ return $path if -f $path;
+ }
+ else
+ {
+ return $path if -x $path;
+ }
}
if ( @path == 1 )
{
@@ -111,18 +127,27 @@ sub mtr_exe_exists (@) {
}
}
+
sub mtr_copy_dir($$) {
- my $srcdir= shift;
- my $dstdir= shift;
+ my $from_dir= shift;
+ my $to_dir= shift;
+
+ mkpath("$to_dir");
+ opendir(DIR, "$from_dir")
+ or mtr_error("Can't find $from_dir$!");
+ for(readdir(DIR)) {
+ next if "$_" eq "." or "$_" eq "..";
+ if ( -d "$from_dir/$_" )
+ {
+ mtr_copy_dir("$from_dir/$_", "$to_dir/$_");
+ next;
+ }
+ copy("$from_dir/$_", "$to_dir/$_");
+ }
+ closedir(DIR);
- # Create destination directory
- mkpath($dstdir);
- find(\&mtr_copy_one_file, $dstdir);
}
-sub mtr_copy_one_file {
- print $File::Find::name, "\n";
-}
sub mtr_same_opts ($$) {
my $l1= shift;
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 779be3d7081..d6fb9382b90 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -20,6 +20,7 @@ sub mtr_record_dead_children ();
sub mtr_exit ($);
sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($);
+sub mtr_kill_process ($$$$);
# static in C
sub spawn_impl ($$$$$$$$);
@@ -672,12 +673,15 @@ sub mtr_mysqladmin_shutdown {
# Shutdown time must be high as slave may be in reconnect
mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo");
mtr_add_arg($args, "shutdown");
+ my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log";
# Start mysqladmin in paralell and wait for termination later
my $pid= mtr_spawn($::exe_mysqladmin, $args,
- "", $::path_manager_log, $::path_manager_log, "",
+ "", $path_mysqladmin_log, $path_mysqladmin_log, "",
{ append_log_file => 1 });
# Save the pid of the mysqladmin process
$mysql_admin_pids{$pid}= 1;
+
+ # We don't wait for termination of mysqladmin
}
# Wait for all the started mysqladmin to exit
@@ -720,8 +724,6 @@ sub mtr_mysqladmin_shutdown {
$timeout or mtr_debug("At least one server is still listening to its port");
- sleep(5) if $::glob_win32; # FIXME next startup fails if no sleep
-
return $res;
}
@@ -821,8 +823,10 @@ sub sleep_until_file_created ($$$) {
my $pidfile= shift;
my $timeout= shift;
my $pid= shift;
+ my $sleeptime= 100; # Milliseconds
+ my $loops= ($timeout * 1000) / $sleeptime;
- for ( my $loop= 1; $loop <= $timeout; $loop++ )
+ for ( my $loop= 1; $loop <= $loops; $loop++ )
{
if ( -r $pidfile )
{
@@ -835,16 +839,20 @@ sub sleep_until_file_created ($$$) {
return 0;
}
- mtr_debug("Sleep 1 second waiting for creation of $pidfile");
+ mtr_debug("Sleep $sleeptime milliseconds waiting for ".
+ "creation of $pidfile");
- if ( $loop % 60 == 0 )
+ # Print extra message every 60 seconds
+ my $seconds= ($loop * $sleeptime) / 1000;
+ if ( $seconds > 1 and $seconds % 60 == 0 )
{
- my $left= $timeout - $loop;
- mtr_warning("Waited $loop seconds for $pidfile to be created, " .
+ my $left= $timeout - $seconds;
+ mtr_warning("Waited $seconds seconds for $pidfile to be created, " .
"still waiting for $left seconds...");
}
- sleep(1);
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, ($sleeptime/1000));
}
return 0;
@@ -868,6 +876,25 @@ sub mtr_kill_processes ($) {
}
}
+
+sub mtr_kill_process ($$$$) {
+ my $pid= shift;
+ my $signal= shift;
+ my $retries= shift;
+ my $timeout= shift;
+
+ while (1)
+ {
+ kill($signal, $pid);
+
+ last unless kill (0, $pid) and $retries--;
+
+ mtr_debug("Sleep $timeout second waiting for processes to die");
+
+ sleep($timeout);
+ }
+}
+
##############################################################################
#
# When we exit, we kill off all children
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 4587c8bc385..f2da89355f7 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -157,6 +157,7 @@ sub mtr_report_stats ($) {
my $tot_passed= 0;
my $tot_failed= 0;
my $tot_tests= 0;
+ my $found_problems= 0; # Some warnings are errors...
foreach my $tinfo (@$tests)
{
@@ -214,10 +215,11 @@ sub mtr_report_stats ($) {
}
else
{
- my $found_problems= 0; # Some warnings are errors...
-
# We report different types of problems in order
- foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x" )
+ foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x",
+ "InnoDB: Warning", "missing DBUG_RETURN",
+ "mysqld: Warning",
+ "Attempting backtrace", "Assertion .* failed" )
{
foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
{
@@ -231,7 +233,8 @@ sub mtr_report_stats ($) {
# Skip some non fatal warnings from the log files
if ( /Warning:\s+Table:.* on (delete|rename)/ or
/Warning:\s+Setting lower_case_table_names=2/ or
- /Warning:\s+One can only use the --user.*root/ )
+ /Warning:\s+One can only use the --user.*root/ or
+ /InnoDB: Warning: we did not need to do crash recovery/)
{
next; # Skip these lines
}
@@ -242,11 +245,11 @@ sub mtr_report_stats ($) {
}
}
}
- if ( $found_problems )
- {
- mtr_warning("Got errors/warnings while running tests, please examine",
- "\"$warnlog\" for details.");
- }
+ }
+ if ( $found_problems )
+ {
+ mtr_warning("Got errors/warnings while running tests, please examine",
+ "\"$warnlog\" for details.");
}
}
}
@@ -266,6 +269,9 @@ sub mtr_report_stats ($) {
}
}
print "\n";
+ }
+ if ( $tot_failed != 0 || $found_problems)
+ {
mtr_error("there where failing test cases");
}
}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index a9a1d46079c..cb61b15a240 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -134,7 +134,6 @@ our $glob_win32= 0; # OS and native Win32 executables
our $glob_win32_perl= 0; # ActiveState Win32 Perl
our $glob_cygwin_perl= 0; # Cygwin Perl
our $glob_cygwin_shell= undef;
-our $glob_use_libtool= 1;
our $glob_mysql_test_dir= undef;
our $glob_mysql_bench_dir= undef;
our $glob_hostname= undef;
@@ -158,9 +157,9 @@ our $path_client_bindir;
our $path_language;
our $path_timefile;
our $path_snapshot;
-our $path_manager_log; # Used by mysqldadmin
our $path_slave_load_tmpdir; # What is this?!
our $path_mysqltest_log;
+our $path_current_test_log;
our $path_my_basedir;
our $opt_vardir; # A path but set directly on cmd line
our $opt_vardir_trace; # unix formatted opt_vardir for trace files
@@ -191,6 +190,8 @@ our $exe_mysqltest;
our $exe_slave_mysqld;
our $exe_im;
our $exe_my_print_defaults;
+our $lib_udf_example;
+our $exe_libtool;
our $opt_bench= 0;
our $opt_small_bench= 0;
@@ -207,7 +208,6 @@ our $opt_sp_protocol;
our $opt_cursor_protocol;
our $opt_view_protocol;
-our $opt_current_test;
our $opt_debug;
our $opt_do_test;
our @opt_cases; # The test cases names in argv
@@ -250,9 +250,6 @@ our $opt_ndbconnectstring;
our $opt_ndbcluster_port_slave;
our $opt_ndbconnectstring_slave;
-our $opt_no_manager; # Does nothing now, we never use manager
-our $opt_manager_port; # Does nothing now, we never use manager
-
our $opt_old_master;
our $opt_record;
@@ -262,6 +259,7 @@ our $opt_result_ext;
our $opt_skip;
our $opt_skip_rpl;
+our $use_slaves;
our $opt_skip_test;
our $opt_skip_im;
@@ -321,6 +319,8 @@ our $opt_with_ndbcluster_slave;
our $opt_with_ndbcluster_all= 0;
our $opt_with_ndbcluster_only= 0;
our $opt_ndb_extra_test= 0;
+our $opt_skip_master_binlog= 0;
+our $opt_skip_slave_binlog= 0;
our $exe_ndb_mgm;
our $path_ndb_tools_dir;
@@ -341,11 +341,13 @@ our @data_dir_lst;
sub main ();
sub initial_setup ();
sub command_line_setup ();
+sub snapshot_setup ();
sub executable_setup ();
sub environment_setup ();
sub kill_running_server ();
sub kill_and_cleanup ();
sub check_ssl_support ();
+sub check_running_as_root();
sub check_ndbcluster_support ();
sub rm_ndbcluster_tables ($);
sub ndbcluster_install ();
@@ -355,7 +357,7 @@ sub ndbcluster_install_slave ();
sub ndbcluster_start_slave ($);
sub ndbcluster_stop_slave ();
sub run_benchmarks ($);
-sub run_tests ();
+sub initialize_servers ();
sub mysql_install_db ();
sub install_db ($$);
sub run_testcase ($);
@@ -386,7 +388,7 @@ sub main () {
command_line_setup();
executable_setup();
- check_ndbcluster_support();
+ check_ndbcluster_support(); # We check whether to actually use it later
check_ssl_support();
environment_setup();
@@ -402,49 +404,37 @@ sub main () {
gprof_prepare();
}
- if ( ! $glob_use_running_server )
- {
- if ( $opt_start_dirty )
- {
- kill_running_server();
- }
- else
- {
- kill_and_cleanup();
- mysql_install_db();
- if ( $opt_force )
- {
- save_installed_db();
- }
- }
- }
-
- if ( $opt_start_dirty )
- {
- if ( ndbcluster_start($opt_with_ndbcluster) )
- {
- mtr_error("Can't start ndbcluster");
- }
- if ( mysqld_start('master',0,[],[],$using_ndbcluster_master) )
- {
- mtr_report("Servers started, exiting");
- }
- else
- {
- mtr_error("Can't start the mysqld server");
- }
- }
- elsif ( $opt_bench )
+ if ( $opt_bench )
{
+ initialize_servers();
run_benchmarks(shift); # Shift what? Extra arguments?!
}
elsif ( $opt_stress )
{
+ initialize_servers();
run_stress_test()
}
else
{
- run_tests();
+ # Figure out which tests we are going to run
+ my $tests= collect_test_cases($opt_suite);
+
+ # Turn off NDB and other similar options if no tests use it
+ my ($need_ndbcluster,$need_im);
+ foreach my $test (@$tests)
+ {
+ $need_ndbcluster||= $test->{ndb_test};
+ $need_im||= $test->{component_id} eq 'im';
+ $use_slaves||= $test->{slave_num};
+ }
+ $opt_with_ndbcluster= $opt_with_ndbcluster_slave= 0
+ unless $need_ndbcluster;
+ $opt_skip_im= 1 unless $need_im;
+
+ snapshot_setup();
+ initialize_servers();
+
+ run_suite($opt_suite, $tests);
}
mtr_exit(0);
@@ -467,12 +457,6 @@ sub initial_setup () {
$glob_cygwin_perl= ($^O eq "cygwin");
$glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
- # Use libtool on all platforms except windows
- if ( $glob_win32 )
- {
- $glob_use_libtool= 0;
- }
-
# We require that we are in the "mysql-test" directory
# to run mysql-test-run
@@ -587,7 +571,6 @@ sub command_line_setup () {
'compress' => \$opt_compress,
'bench' => \$opt_bench,
'small-bench' => \$opt_small_bench,
- 'no-manager' => \$opt_no_manager, # Currently not used
# Control what test suites or cases to run
'force' => \$opt_force,
@@ -599,6 +582,8 @@ sub command_line_setup () {
'with-ndbcluster-all' => \$opt_with_ndbcluster_all,
'with-ndbcluster-only' => \$opt_with_ndbcluster_only,
'ndb-extra-test' => \$opt_ndb_extra_test,
+ 'skip-master-binlog' => \$opt_skip_master_binlog,
+ 'skip-slave-binlog' => \$opt_skip_slave_binlog,
'do-test=s' => \$opt_do_test,
'start-from=s' => \$opt_start_from,
'suite=s' => \$opt_suite,
@@ -612,7 +597,6 @@ sub command_line_setup () {
'slave_port=i' => \$opt_slave_myport,
'ndbcluster-port|ndbcluster_port=i' => \$opt_ndbcluster_port,
'ndbcluster-port-slave=i' => \$opt_ndbcluster_port_slave,
- '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
@@ -746,11 +730,6 @@ sub command_line_setup () {
$opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir;
$opt_tmpdir =~ s,/+$,,; # Remove ending slash if any
- # FIXME maybe not needed?
- $path_manager_log= "$opt_vardir/log/manager.log"
- unless $path_manager_log;
- $opt_current_test= "$opt_vardir/log/current_test"
- unless $opt_current_test;
# --------------------------------------------------------------------------
# Do sanity checks of command line arguments
@@ -950,6 +929,7 @@ sub command_line_setup () {
path_err => "$opt_vardir/log/im.err",
path_log => "$opt_vardir/log/im.log",
path_pid => "$opt_vardir/run/im.pid",
+ path_angel_pid => "$opt_vardir/run/im.angel.pid",
path_sock => "$sockdir/im.sock",
port => $im_port,
start_timeout => $master->[0]->{'start_timeout'},
@@ -990,22 +970,32 @@ sub command_line_setup () {
$path_timefile= "$opt_vardir/log/mysqltest-time";
$path_mysqltest_log= "$opt_vardir/log/mysqltest.log";
+ $path_current_test_log= "$opt_vardir/log/current_test";
$path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/";
+}
+
+sub snapshot_setup () {
# Make a list of all data_dirs
@data_dir_lst = (
$master->[0]->{'path_myddir'},
- $master->[1]->{'path_myddir'},
- $slave->[0]->{'path_myddir'},
- $slave->[1]->{'path_myddir'},
- $slave->[2]->{'path_myddir'});
+ $master->[1]->{'path_myddir'});
- foreach my $instance (@{$instance_manager->{'instances'}})
+ if ($use_slaves)
{
- push(@data_dir_lst, $instance->{'path_datadir'});
+ push @data_dir_lst, ($slave->[0]->{'path_myddir'},
+ $slave->[1]->{'path_myddir'},
+ $slave->[2]->{'path_myddir'});
}
+ unless ($opt_skip_im)
+ {
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ push(@data_dir_lst, $instance->{'path_datadir'});
+ }
+ }
}
@@ -1017,6 +1007,21 @@ sub command_line_setup () {
sub executable_setup () {
+ #
+ # Check if libtool is available in this distribution/clone
+ # we need it when valgrinding or debugging non installed binary
+ # Otherwise valgrind will valgrind the libtool wrapper or bash
+ # and gdb will not find the real executable to debug
+ #
+ if ( -x "../libtool")
+ {
+ $exe_libtool= "../libtool";
+ if ($opt_valgrind or $glob_debugger)
+ {
+ mtr_report("Using \"$exe_libtool\" when running valgrind or debugger");
+ }
+ }
+
if ( $opt_source_dist )
{
if ( $glob_win32 )
@@ -1087,6 +1092,8 @@ sub executable_setup () {
"/usr/bin/false");
$path_ndb_tools_dir= mtr_path_exists("$glob_basedir/storage/ndb/tools");
$exe_ndb_mgm= "$glob_basedir/storage/ndb/src/mgmclient/ndb_mgm";
+ $lib_udf_example=
+ mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so");
}
else
{
@@ -1184,7 +1191,7 @@ sub environment_setup () {
# Add the path where mysqld will find udf_example.so
# --------------------------------------------------------------------------
$ENV{'LD_LIBRARY_PATH'}=
- "$glob_basedir/sql/.libs" .
+ ($lib_udf_example ? dirname($lib_udf_example) : "") .
($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
@@ -1211,9 +1218,14 @@ sub environment_setup () {
$ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
$ENV{'NDBCLUSTER_PORT_SLAVE'}=$opt_ndbcluster_port_slave;
+ $ENV{'NDB_STATUS_OK'}= "YES";
+ $ENV{'IM_EXE'}= $exe_im;
$ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
+ $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
$ENV{'IM_PORT'}= $instance_manager->{port};
+ $ENV{'IM_DEFAULTS_PATH'}= $instance_manager->{defaults_file};
+ $ENV{'IM_PASSWORD_PATH'}= $instance_manager->{password_file};
$ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
$ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};
@@ -1225,17 +1237,20 @@ sub environment_setup () {
$ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
# We are nice and report a bit about our settings
- print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
- print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
- print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
- print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
- print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
- print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
- print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
- print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
- print "Using IM_PORT = $ENV{IM_PORT}\n";
- print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
- print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ if (!$opt_extern)
+ {
+ print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
+ print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
+ print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
+ print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
+ print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
+ print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
+ print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
+ print "Using IM_PORT = $ENV{IM_PORT}\n";
+ print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
+ print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ }
}
@@ -1250,6 +1265,7 @@ sub signal_setup () {
$SIG{INT}= \&handle_int_signal;
}
+
sub handle_int_signal () {
$SIG{INT}= 'DEFAULT'; # If we get a ^C again, we die...
mtr_warning("got INT signal, cleaning up.....");
@@ -1369,10 +1385,37 @@ sub kill_and_cleanup () {
}
+sub check_running_as_root () {
+ # Check if running as root
+ # i.e a file can be read regardless what mode we set it to
+ my $test_file= "$opt_vardir/test_running_as_root.txt";
+ mtr_tofile($test_file, "MySQL");
+ chmod(oct("0000"), $test_file);
+
+ my $result="";
+ if (open(FILE,"<",$test_file))
+ {
+ $result= join('', <FILE>);
+ close FILE;
+ }
+
+ chmod(oct("0755"), $test_file);
+ unlink($test_file);
+
+ $ENV{'MYSQL_TEST_ROOT'}= "NO";
+ if ($result eq "MySQL")
+ {
+ mtr_warning("running this script as _root_ will cause some " .
+ "tests to be skipped");
+ $ENV{'MYSQL_TEST_ROOT'}= "YES";
+ }
+}
+
+
sub check_ssl_support () {
- if ($opt_skip_ssl)
+ if ($opt_skip_ssl || $opt_extern)
{
mtr_report("Skipping SSL");
$opt_ssl_supported= 0;
@@ -1436,7 +1479,7 @@ sub check_ndbcluster_support () {
return;
}
- mtr_report("Using ndbcluster, mysqld supports it");
+ mtr_report("Using ndbcluster if necessary, mysqld supports it");
$opt_with_ndbcluster= 1;
if ( $opt_ndbconnectstring )
{
@@ -1467,7 +1510,6 @@ sub check_ndbcluster_support () {
return;
}
-# FIXME why is there a different start below?!
sub ndbcluster_install () {
@@ -1497,6 +1539,7 @@ sub ndbcluster_install () {
return 0;
}
+
sub ndbcluster_start ($) {
my $use_ndbcluster= shift;
@@ -1520,6 +1563,7 @@ sub ndbcluster_start ($) {
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
"--data-dir=$opt_vardir",
+ "--character-sets-dir=$path_charsetsdir",
"--verbose=2",
"--core"],
"", "/dev/null", "", "") )
@@ -1723,12 +1767,9 @@ sub run_benchmarks ($) {
# FIXME how to specify several suites to run? Comma separated list?
-sub run_tests () {
- run_suite($opt_suite);
-}
sub run_suite () {
- my $suite= shift;
+ my ($suite, $tests)= @_;
mtr_print_thick_line();
@@ -1736,8 +1777,6 @@ sub run_suite () {
mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout);
- my $tests= collect_test_cases($suite);
-
mtr_report("Starting Tests in the '$suite' suite");
mtr_print_header();
@@ -1779,14 +1818,38 @@ sub run_suite () {
#
##############################################################################
+sub initialize_servers () {
+ if ( ! $glob_use_running_server )
+ {
+ if ( $opt_start_dirty )
+ {
+ kill_running_server();
+ }
+ else
+ {
+ kill_and_cleanup();
+ mysql_install_db();
+ if ( $opt_force )
+ {
+ save_installed_db();
+ }
+ }
+ check_running_as_root();
+ }
+}
+
sub mysql_install_db () {
# FIXME not exactly true I think, needs improvements
install_db('master', $master->[0]->{'path_myddir'});
install_db('master', $master->[1]->{'path_myddir'});
- install_db('slave', $slave->[0]->{'path_myddir'});
- install_db('slave', $slave->[1]->{'path_myddir'});
- install_db('slave', $slave->[2]->{'path_myddir'});
+
+ if ( $use_slaves )
+ {
+ install_db('slave', $slave->[0]->{'path_myddir'});
+ install_db('slave', $slave->[1]->{'path_myddir'});
+ install_db('slave', $slave->[2]->{'path_myddir'});
+ }
if ( ! $opt_skip_im )
{
@@ -1801,6 +1864,7 @@ sub mysql_install_db () {
mtr_report("ndbcluster_install failed, continuing without cluster");
$opt_with_ndbcluster= 0;
$flag_ndb_status_ok= 0;
+ $ENV{'NDB_STATUS_OK'}= "NO";
}
else
{
@@ -1810,7 +1874,7 @@ sub mysql_install_db () {
}
}
- if ( ndbcluster_install_slave() )
+ if ( $use_slaves and ndbcluster_install_slave() )
{
if ( $opt_force)
{
@@ -1840,7 +1904,7 @@ sub install_db ($$) {
my $init_db_sql_tmp= "/tmp/init_db.sql$$";
my $args;
- mtr_report("Installing \u$type Databases");
+ mtr_report("Installing \u$type Database");
open(IN, $init_db_sql)
or mtr_error("Can't open $init_db_sql: $!");
@@ -1884,8 +1948,15 @@ sub install_db ($$) {
mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
}
+ # Log bootstrap command
+ my $path_bootstrap_log= "$opt_vardir/log/bootstrap.log";
+ mtr_tofile($path_bootstrap_log,
+ "$exe_mysqld " . join(" ", @$args) . "\n");
+
if ( mtr_run($exe_mysqld, $args, $init_db_sql_tmp,
- $path_manager_log, $path_manager_log, "") != 0 )
+ $path_bootstrap_log, $path_bootstrap_log,
+ "", { append_log_file => 1 }) != 0 )
+
{
unlink($init_db_sql_tmp);
mtr_error("Error executing mysqld --bootstrap\n" .
@@ -1907,15 +1978,15 @@ 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);
}
@@ -1927,12 +1998,13 @@ sub im_create_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}
+angel-pid-file = $instance_manager->{path_angel_pid}
socket = $instance_manager->{path_sock}
port = $instance_manager->{port}
password-file = $instance_manager->{password_file}
@@ -1957,7 +2029,7 @@ 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
+server_id = $server_id
skip-stack-trace
skip-innodb
skip-bdb
@@ -2009,7 +2081,7 @@ sub run_testcase ($) {
my $ndbcluster_opt;
- mtr_tonewfile($opt_current_test,"$tname\n"); # Always tell where we are
+ mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are
# output current test to ndbcluster log file to enable diagnostics
mtr_tofile($file_ndb_testrun_log,"CURRENT TEST $tname\n");
@@ -2088,7 +2160,7 @@ sub run_testcase ($) {
# ----------------------------------------------------------------------
stop_slaves();
- }
+ }
# ----------------------------------------------------------------------
# Prepare to start masters. Even if we use embedded, we want to run
@@ -2105,9 +2177,9 @@ sub run_testcase ($) {
mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
}
-# FIXME test cases that depend on each other, prevent this from
-# being at this location.
-# do_before_start_master($tname,$tinfo->{'master_sh'});
+ # FIXME test cases that depend on each other, prevent this from
+ # being at this location.
+ # do_before_start_master($tname,$tinfo->{'master_sh'});
# ----------------------------------------------------------------------
# If any mysqld servers running died, we have to know
@@ -2157,6 +2229,14 @@ sub run_testcase ($) {
if ( $using_ndbcluster_master and ! $master->[1]->{'pid'} )
{
# Test needs cluster, start an extra mysqld connected to cluster
+ # First wait for first mysql server to have created ndb system tables ok
+ if ( ! sleep_until_file_created("$master->[0]->{'path_myddir'}/cluster/apply_status.ndb",
+ $master->[0]->{'start_timeout'},
+ $master->[0]->{'pid'}))
+ {
+ report_failure_and_restart($tinfo);
+ return;
+ }
mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
$master->[1]->{'pid'}=
mysqld_start('master',1,$tinfo->{'master_opt'},[],
@@ -2230,10 +2310,11 @@ sub run_testcase ($) {
}
# ----------------------------------------------------------------------
- # If --start-and-exit given, stop here to let user manually run tests
+ # If --start-and-exit or --start-dirty given, stop here to let user manually
+ # run tests
# ----------------------------------------------------------------------
- if ( $opt_start_and_exit )
+ if ( $opt_start_and_exit or $opt_start_dirty )
{
mtr_report("\nServers started, exiting");
exit(0);
@@ -2299,25 +2380,6 @@ sub run_testcase ($) {
}
}
-sub copy_dir($$) {
- my $from_dir= shift;
- my $to_dir= shift;
-
- mkpath("$to_dir");
- opendir(DIR, "$from_dir")
- or mtr_error("Can't find $from_dir$!");
- for(readdir(DIR)) {
- next if "$_" eq "." or "$_" eq "..";
- if ( -d "$from_dir/$_" )
- {
- copy_dir("$from_dir/$_", "$to_dir/$_");
- next;
- }
- copy("$from_dir/$_", "$to_dir/$_");
- }
- closedir(DIR);
-
-}
#
# Save a snapshot of the installed test db(s)
@@ -2331,7 +2393,7 @@ sub save_installed_db () {
foreach my $data_dir (@data_dir_lst)
{
my $name= basename($data_dir);
- copy_dir("$data_dir", "$path_snapshot/$name");
+ mtr_copy_dir("$data_dir", "$path_snapshot/$name");
}
}
@@ -2355,6 +2417,7 @@ sub save_files_before_restore($$) {
}
}
+
#
# Restore snapshot of the installed test db(s)
# if the snapshot exists
@@ -2373,7 +2436,7 @@ sub restore_installed_db ($) {
my $name= basename($data_dir);
save_files_before_restore($test_name, $data_dir);
rmtree("$data_dir");
- copy_dir("$path_snapshot/$name", "$data_dir");
+ mtr_copy_dir("$path_snapshot/$name", "$data_dir");
}
if ($opt_with_ndbcluster)
{
@@ -2430,9 +2493,9 @@ sub report_failure_and_restart ($) {
#
##############################################################################
+
# The embedded server needs the cleanup so we do some of the start work
# but stop before actually running mysqld or anything.
-
sub do_before_start_master ($$) {
my $tname= shift;
my $init_script= shift;
@@ -2465,13 +2528,14 @@ sub do_before_start_master ($$) {
if ( $ret != 0 )
{
# FIXME rewrite those scripts to return 0 if successful
-# mtr_warning("$init_script exited with code $ret");
+ # mtr_warning("$init_script exited with code $ret");
}
}
# for gcov FIXME needed? If so we need more absolute paths
-# chdir($glob_basedir);
+ # chdir($glob_basedir);
}
+
sub do_before_start_slave ($$) {
my $tname= shift;
my $init_script= shift;
@@ -2499,7 +2563,7 @@ sub do_before_start_slave ($$) {
if ( $ret != 0 )
{
# FIXME rewrite those scripts to return 0 if successful
-# mtr_warning("$init_script exited with code $ret");
+ # mtr_warning("$init_script exited with code $ret");
}
}
@@ -2509,6 +2573,7 @@ sub do_before_start_slave ($$) {
}
}
+
sub mysqld_arguments ($$$$$$) {
my $args= shift;
my $type= shift; # master/slave/bootstrap
@@ -2538,7 +2603,6 @@ sub mysqld_arguments ($$$$$$) {
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-function-creators", $prefix);
- mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $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);
@@ -2555,8 +2619,11 @@ sub mysqld_arguments ($$$$$$) {
{
my $id= $idx > 0 ? $idx + 101 : 1;
- mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
- $opt_vardir, $sidx);
+ if (! $opt_skip_master_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
+ $opt_vardir, $sidx);
+ }
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
$master->[$idx]->{'path_mypid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
@@ -2597,9 +2664,12 @@ sub mysqld_arguments ($$$$$$) {
# FIXME slave get this option twice?!
mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix);
- mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
- $opt_vardir, $sidx); # FIXME use own dir for binlogs
- mtr_add_arg($args, "%s--log-slave-updates", $prefix);
+ if (! $opt_skip_slave_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
+ $opt_vardir, $sidx); # FIXME use own dir for binlogs
+ mtr_add_arg($args, "%s--log-slave-updates", $prefix);
+ }
# FIXME option duplicated for slave
mtr_add_arg($args, "%s--log=%s", $prefix,
$slave->[$idx]->{'path_mylog'});
@@ -2678,7 +2748,6 @@ sub mysqld_arguments ($$$$$$) {
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-function-creators", $prefix);
- mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $prefix);
if ( $opt_ssl_supported )
{
@@ -2747,14 +2816,6 @@ sub mysqld_arguments ($$$$$$) {
return $args;
}
-# FIXME
-# if ( $type eq 'master' and $glob_use_embedded_server )
-# {
-# # Add a -A to each argument to pass it to embedded server
-# my @mysqltest_opt= map {("-A",$_)} @args;
-# $opt_extra_mysqltest_opt= \@mysqltest_opt;
-# return;
-# }
##############################################################################
#
@@ -2821,6 +2882,15 @@ sub mysqld_start ($$$$$) {
$exe= undef;
}
+ if ($exe_libtool and $opt_valgrind)
+ {
+ # Add "libtool --mode-execute"
+ # if running in valgrind(to avoid valgrinding bash)
+ unshift(@$args, "--mode=execute", $exe);
+ $exe= $exe_libtool;
+ }
+
+
if ( $type eq 'master' )
{
if ( ! defined $exe or
@@ -2854,6 +2924,7 @@ sub mysqld_start ($$$$$) {
return 0;
}
+
sub stop_masters_slaves () {
print "Ending Tests\n";
@@ -2863,7 +2934,7 @@ sub stop_masters_slaves () {
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";
@@ -2871,6 +2942,7 @@ sub stop_masters_slaves () {
print "Slave(s) shutdown finished\n";
}
+
sub stop_masters () {
my @args;
@@ -2900,6 +2972,7 @@ sub stop_masters () {
mtr_stop_mysqld_servers(\@args);
}
+
sub stop_slaves () {
my $force= shift;
@@ -2954,7 +3027,7 @@ sub im_start($$) {
mtr_add_arg($args, $opt);
}
- $instance_manager->{'pid'} =
+ $instance_manager->{'pid'} =
mtr_spawn(
$exe_im, # path to the executable
$args, # cmd-line args
@@ -2970,7 +3043,7 @@ sub im_start($$) {
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.
@@ -2988,9 +3061,22 @@ sub im_start($$) {
mtr_get_pid_from_file($instance_manager->{'path_pid'});
}
+
sub im_stop($) {
my $instance_manager = shift;
+ # Obtain mysqld-process pids before we start stopping IM (it can delete pid
+ # files).
+
+ my @mysqld_pids = ();
+ my $instances = $instance_manager->{'instances'};
+
+ push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'}))
+ if -r $instances->[0]->{'path_pid'};
+
+ push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'}))
+ if -r $instances->[1]->{'path_pid'};
+
# Re-read pid from the file, since during tests Instance Manager could have
# been restarted, so its pid could have been changed.
@@ -2998,36 +3084,82 @@ sub im_stop($) {
mtr_get_pid_from_file($instance_manager->{'path_pid'})
if -f $instance_manager->{'path_pid'};
+ if (-f $instance_manager->{'path_angel_pid'})
+ {
+ $instance_manager->{'angel_pid'} =
+ mtr_get_pid_from_file($instance_manager->{'path_angel_pid'})
+ }
+ else
+ {
+ $instance_manager->{'angel_pid'} = undef;
+ }
+
# 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.
+ # Try graceful shutdown.
- my @pids = ( $instance_manager->{'pid'} );
- my $instances = $instance_manager->{'instances'};
+ mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1);
+
+ # Check that all processes died.
+
+ my $clean_shutdown= 0;
- if ( -r $instances->[0]->{'path_pid'} )
+ while (1)
{
- push(@pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'}));
+ last if kill (0, $instance_manager->{'pid'});
+
+ last if (defined $instance_manager->{'angel_pid'}) &&
+ kill (0, $instance_manager->{'angel_pid'});
+
+ foreach my $pid (@mysqld_pids)
+ {
+ last if kill (0, $pid);
+ }
+
+ $clean_shutdown= 1;
+ last;
}
- if ( -r $instances->[1]->{'path_pid'} )
+ # Kill leftovers (the order is important).
+
+ unless ($clean_shutdown)
{
- push(@pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'}));
+ mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
+ if defined $instance_manager->{'angel_pid'};
+
+ mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1);
+
+ # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM
+ # will not stop them on shutdown. So, we should firstly try to end them
+ # legally.
+
+ mtr_kill_processes(\@mysqld_pids);
+
+ # Complain in error log so that a warning will be shown.
+
+ my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
+
+ open (ERRLOG, ">>$errlog") ||
+ mtr_error("Can not open error log ($errlog)");
+
+ my $ts= localtime();
+ print ERRLOG
+ "Warning: [$ts] Instance Manager did not shutdown gracefully.\n";
+
+ close ERRLOG;
}
- # Kill processes.
+ # That's all.
- mtr_kill_processes(\@pids);
-
stop_reap_all();
$instance_manager->{'pid'} = undef;
+ $instance_manager->{'angel_pid'} = undef;
}
+
#
# Run include/check-testcase.test
# Before a testcase, run in record mode, save result file to var
@@ -3076,6 +3208,7 @@ sub run_check_testcase ($) {
}
}
+
sub run_mysqltest ($) {
my $tinfo= shift;
@@ -3169,11 +3302,6 @@ sub run_mysqltest ($) {
"--port=$master->[0]->{'path_myport'} " .
"--socket=$master->[0]->{'path_mysock'}";
-
-
- # FIXME really needing a PATH???
- # $ENV{'PATH'}= "/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$ENV{'PATH'}";
-
$ENV{'MYSQL'}= $cmdline_mysql;
$ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
$ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
@@ -3186,9 +3314,11 @@ sub run_mysqltest ($) {
$ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
$ENV{'CHARSETSDIR'}= $path_charsetsdir;
$ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
+ $ENV{'UDF_EXAMPLE_LIB'}=
+ ($lib_udf_example ? basename($lib_udf_example) : "");
- $ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok;
- $ENV{'NDB_SLAVE_STATUS_OK'}= $flag_ndb_slave_status_ok;
+ $ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok ? "YES" : "NO";
+ $ENV{'NDB_SLAVE_STATUS_OK'}= $flag_ndb_slave_status_ok ? "YES" : "NO";
$ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
$ENV{'NDB_MGM'}= $exe_ndb_mgm;
$ENV{'NDB_BACKUP_DIR'}= $path_ndb_data_dir;
@@ -3352,12 +3482,12 @@ sub run_mysqltest ($) {
debugger_arguments(\$args, \$exe, "client");
}
- if ($glob_use_libtool and $opt_valgrind)
+ if ($exe_libtool and $opt_valgrind)
{
# Add "libtool --mode-execute" before the test to execute
# if running in valgrind(to avoid valgrinding bash)
unshift(@$args, "--mode=execute", $exe);
- $exe= "libtool";
+ $exe= $exe_libtool;
}
if ( $opt_check_testcases )
@@ -3427,9 +3557,9 @@ sub gdb_arguments {
mtr_add_arg($$args, "$type");
mtr_add_arg($$args, "-e");
- if ( $glob_use_libtool )
+ if ( $exe_libtool )
{
- mtr_add_arg($$args, "libtool");
+ mtr_add_arg($$args, $exe_libtool);
mtr_add_arg($$args, "--mode=execute");
}
@@ -3441,6 +3571,7 @@ sub gdb_arguments {
$$exe= "xterm";
}
+
#
# Modify the exe and args so that program is run in ddd
#
@@ -3472,8 +3603,7 @@ sub ddd_arguments {
"break mysql_parse\n" .
"commands 1\n" .
"disable 1\n" .
- "end\n" .
- "run");
+ "end");
}
if ( $opt_manual_ddd )
@@ -3489,9 +3619,9 @@ sub ddd_arguments {
my $save_exe= $$exe;
$$args= [];
- if ( $glob_use_libtool )
+ if ( $exe_libtool )
{
- $$exe= "libtool";
+ $$exe= $exe_libtool;
mtr_add_arg($$args, "--mode=execute");
mtr_add_arg($$args, "ddd");
}
@@ -3512,6 +3642,8 @@ sub debugger_arguments {
my $exe= shift;
my $debugger= $opt_debugger || $opt_client_debugger;
+ # FIXME Need to change the below "eq"'s to
+ # "case unsensitive string contains"
if ( $debugger eq "vcexpress" or $debugger eq "vc")
{
# vc[express] /debugexe exe arg1 .. argn
@@ -3561,7 +3693,7 @@ sub valgrind_arguments {
if ( $opt_valgrind_options )
{
- mtr_add_arg($args, split(' ', $opt_valgrind_options));
+ mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
}
@@ -3681,11 +3813,12 @@ Misc options
comment=STR Write STR to the output
notimer Don't show test case execution time
script-debug Debug this script itself
- start-and-exit Only initiate and start the "mysqld" servers, use
- the startup settings for the specified test case if any
- start-dirty Only start the "mysqld" servers without initiation
- fast Don't try to cleanup from earlier runs
- reorder Reorder tests to get less server restarts
+ start-and-exit Only initialize and start the servers, using the
+ startup settings for the specified test case (if any)
+ start-dirty Only start the servers (without initialization) for
+ the specified test case (if any)
+ fast Don't try to clean up from earlier runs
+ reorder Reorder tests to get fewer server restarts
help Get this help text
unified-diff | udiff When presenting differences, use unified diff
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index aad71f89ef2..d4e70054d82 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -205,6 +205,7 @@ TOT_SKIP=0
TOT_PASS=0
TOT_FAIL=0
TOT_TEST=0
+GOT_WARNINGS=0
USERT=0
SYST=0
REALT=0
@@ -669,7 +670,9 @@ fi
[ -d $MYSQL_TEST_DIR/var/tmp ] || mkdir $MYSQL_TEST_DIR/var/tmp
[ -d $MYSQL_TEST_DIR/var/run ] || mkdir $MYSQL_TEST_DIR/var/run
[ -d $MYSQL_TEST_DIR/var/log ] || mkdir $MYSQL_TEST_DIR/var/log
-if ! test -L $MYSQL_TEST_DIR/var/std_data_ln ; then
+
+# Use 'test', not '[' as the shell builtin might not have '-L
+if test ! -L "$MYSQL_TEST_DIR/var/std_data_ln" ; then
ln -s $MYSQL_TEST_DIR/std_data/ $MYSQL_TEST_DIR/var/std_data_ln
fi
@@ -1070,22 +1073,21 @@ report_stats () {
#
$RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp
# Remove some non fatal warnings from the log files
- $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
+ $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' -e 's|InnoDB: Warning: we did not need to do crash recovery||g' \
$MY_LOG_DIR/*.err \
| $SED -e 's!Warning: Table:.* on rename!!g' \
> $MY_LOG_DIR/warnings.tmp
- found_error=0
# Find errors
- for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN"
+ for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning" "Attempting backtrace" "Assertion .* failed"
do
if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then
- found_error=1
+ GOT_WARNINGS=1
fi
done
$RM -f $MY_LOG_DIR/warnings.tmp
- if [ $found_error = "1" ]
+ if [ $GOT_WARNINGS = "1" ]
then
echo "WARNING: Got errors/warnings while running tests. Please examine"
echo "$MY_LOG_DIR/warnings for details."
@@ -1230,7 +1232,7 @@ start_ndbcluster()
then
NDBCLUSTER_EXTRA_OPTS="--small"
fi
- OPTS="$NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --verbose=$NDB_VERBOSE --initial --relative-config-data-dir --core"
+ OPTS="$NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --character-sets-dir=$CHARSETSDIR --verbose=$NDB_VERBOSE --initial --relative-config-data-dir --core"
if [ "x$NDB_VERBOSE" != "x0" ] ; then
echo "Starting master ndbcluster " $OPTS
fi
@@ -1343,7 +1345,6 @@ start_master()
--innodb_data_file_path=ibdata1:128M:autoextend \
--open-files-limit=1024 \
--log-bin-trust-function-creators \
- --loose-binlog-show-xid=0 \
$MASTER_40_ARGS \
$SMALL_SERVER \
$MASTER_MYSQLD_BINLOG_OPT \
@@ -1367,7 +1368,6 @@ start_master()
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:128M:autoextend \
--log-bin-trust-function-creators \
- --loose-binlog-show-xid=0 \
$MASTER_40_ARGS \
$SMALL_SERVER \
$MASTER_MYSQLD_BINLOG_OPT \
@@ -1540,7 +1540,6 @@ start_slave()
--master-retry-count=10 \
-O slave_net_timeout=10 \
--log-bin-trust-function-creators \
- --loose-binlog-show-xid=0 \
$SMALL_SERVER \
$SLAVE_MYSQLD_BINLOG_OPT \
$EXTRA_SLAVE_MYSQLD_OPT $EXTRA_SLAVE_OPT \
@@ -2298,6 +2297,8 @@ if [ $TOT_FAIL -ne 0 ]; then
$ECHO "mysql-test-run in $TEST_MODE mode: *** Failing the test(s):$FAILED_CASES"
$ECHO
exit 1
-else
- exit 0
fi
+if [ $GOT_WARNINGS -ne 0 ]; then
+ exit 1
+fi
+exit 0
diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh
index 6812067a8ed..74f21fdef92 100644
--- a/mysql-test/ndb/ndbcluster.sh
+++ b/mysql-test/ndb/ndbcluster.sh
@@ -66,6 +66,7 @@ VERBOSE=100
NDB_MGM_EXTRA_OPTS=
NDB_MGMD_EXTRA_OPTS=
NDBD_EXTRA_OPTS=
+CHARSETSDIR=
while test $# -gt 0; do
case "$1" in
@@ -119,6 +120,9 @@ while test $# -gt 0; do
--ndbd-extra-opts=*)
NDBD_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndbd-extra-opts=;;"`
;;
+ --character-sets-dir=*)
+ CHARSETSDIR=`echo "$1" | sed -e "s;--character-sets-dir=;;"`
+ ;;
--core)
opt_core="--core"
;;
@@ -159,7 +163,7 @@ fi
exec_mgmtclient="$exec_mgmtclient --no-defaults $opt_core $NDB_MGM_EXTRA_OPTS"
exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $opt_core $NDB_MGMD_EXTRA_OPTS"
-exec_ndb="$exec_ndb --no-defaults $opt_core $NDBD_EXTRA_OPTS"
+exec_ndb="$exec_ndb --no-defaults $opt_core $NDBD_EXTRA_OPTS --character-sets-dir=$CHARSETSDIR"
exec_waiter="$exec_waiter --no-defaults $opt_core"
ndb_host="localhost"
@@ -260,7 +264,7 @@ done
# test if Ndb Cluster starts properly
if [ `expr $VERBOSE \> 1` = 1 ] ; then
- echo "Waiting for started..."
+ echo "Waiting for NDB data nodes to start..."
fi
if ( $exec_waiter ) | grep "NDBT_ProgramExit: 0 - OK" > /dev/null 2>&1 ; then :; else
if [ `expr $VERBOSE \> 0` = 1 ] ; then
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 1ad9cd6d1e9..f4332ea9888 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -647,3 +647,13 @@ SELECT LENGTH(s) FROM t1;
LENGTH(s)
10
DROP TABLE t1;
+CREATE TABLE t1 (v VARCHAR(3), b INT);
+INSERT INTO t1 VALUES ('abc', 5);
+SELECT * FROM t1;
+v b
+abc 5
+ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4);
+SELECT * FROM t1;
+v b
+abc 5
+DROP TABLE t1;
diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result
index 65c6955a959..fc267cb598d 100644
--- a/mysql-test/r/analyze.result
+++ b/mysql-test/r/analyze.result
@@ -46,4 +46,12 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
execute stmt1;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
deallocate prepare stmt1;
+create temporary table t1(a int, index(a));
+insert into t1 values('1'),('2'),('3'),('4'),('5');
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+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 5 NULL NULL YES BTREE
drop table t1;
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result
index 00a526df8ea..527748e00d5 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,HIGH_NOT_PRECEDENCE
+MYSQL40,HIGH_NOT_PRECEDENCE
set @@sql_mode="ANSI";
select @@sql_mode;
@@sql_mode
@@ -17,3 +17,32 @@ SELECT id FROM t1 GROUP BY id2;
id
drop table t1;
SET @@SQL_MODE="";
+CREATE TABLE t1 (i int auto_increment NOT NULL, PRIMARY KEY (i));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SET @@SQL_MODE="MYSQL323";
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`i`)
+) TYPE=MyISAM
+SET @@SQL_MODE="MYSQL40";
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`i`)
+) TYPE=MyISAM
+SET @@SQL_MODE="NO_FIELD_OPTIONS";
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL,
+ PRIMARY KEY (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 09813458069..19cb0c9768f 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index 2fe4db859b5..d9e9392f618 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -355,6 +355,30 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE IF EXISTS t1;
+CREATE TABLE `t1` (
+t1_name VARCHAR(255) DEFAULT NULL,
+t1_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+KEY (t1_name),
+PRIMARY KEY (t1_id)
+) AUTO_INCREMENT = 1000;
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+SELECT * from t1;
+t1_name t1_id
+MySQL 1000
+MySQL 1001
+MySQL 1002
+SHOW CREATE TABLE `t1`;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `t1_name` varchar(255) DEFAULT NULL,
+ `t1_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`t1_id`),
+ KEY `t1_name` (`t1_name`)
+) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1
+DROP TABLE `t1`;
+End of 4.1 tests
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);
@@ -394,3 +418,9 @@ a val
2 1
3 1
drop table t1;
+CREATE TABLE t1 (t1 INT(10) PRIMARY KEY, t2 INT(10));
+INSERT INTO t1 VALUES(0, 0);
+INSERT INTO t1 VALUES(1, 1);
+ALTER TABLE t1 CHANGE t1 t1 INT(10) auto_increment;
+ERROR 23000: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
+DROP TABLE t1;
diff --git a/mysql-test/r/binlog_row_blackhole.result b/mysql-test/r/binlog_row_blackhole.result
index aa5c943de00..42bf7a10888 100644
--- a/mysql-test/r/binlog_row_blackhole.result
+++ b/mysql-test/r/binlog_row_blackhole.result
@@ -156,3 +156,9 @@ master-bin.000001 # Query 1 # use `test`; BEGIN
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `test`; COMMIT
+drop table if exists t1;
+create table t1 (c char(20)) engine=MyISAM;
+insert into t1 values ("Monty"),("WAX"),("Walrus");
+alter table t1 engine=blackhole;
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+drop table t1;
diff --git a/mysql-test/r/binlog_stm_blackhole.result b/mysql-test/r/binlog_stm_blackhole.result
index 90eabc6fa66..64569993a7b 100644
--- a/mysql-test/r/binlog_stm_blackhole.result
+++ b/mysql-test/r/binlog_stm_blackhole.result
@@ -149,3 +149,9 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int) engine=blackho
master-bin.000001 # Query 1 # use `test`; BEGIN
master-bin.000001 # Query 1 # use `test`; insert into t1 values(1)
master-bin.000001 # Query 1 # use `test`; COMMIT
+drop table if exists t1;
+create table t1 (c char(20)) engine=MyISAM;
+insert into t1 values ("Monty"),("WAX"),("Walrus");
+alter table t1 engine=blackhole;
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+drop table t1;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index d28c3af4e0b..1d2041432fe 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -103,8 +103,8 @@ t1 CREATE TABLE `t1` (
`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(3) NOT NULL DEFAULT '',
- `c6` varbinary(3) 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,
@@ -152,11 +152,11 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(1)` int(1) NOT NULL DEFAULT '0',
- `COALESCE(1.0)` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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(3) 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;
@@ -175,6 +175,14 @@ SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
case+union+test
case+union+test
nobug
+create table t1(a float, b int default 3);
+insert into t1 (a) values (2), (11), (8);
+select min(a), min(case when 1=1 then a else NULL end),
+min(case when 1!=1 then NULL else a end)
+from t1 where b=3 group by b;
+min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end)
+2 2 2
+drop table t1;
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
diff --git a/mysql-test/r/case_sensitive_file_system.require b/mysql-test/r/case_sensitive_file_system.require
new file mode 100644
index 00000000000..d0bdc6bf4ce
--- /dev/null
+++ b/mysql-test/r/case_sensitive_file_system.require
@@ -0,0 +1,2 @@
+Variable_name Value
+lower_case_file_system OFF
diff --git a/mysql-test/r/contributors.result b/mysql-test/r/contributors.result
new file mode 100644
index 00000000000..5739c2244c3
--- /dev/null
+++ b/mysql-test/r/contributors.result
@@ -0,0 +1,5 @@
+SHOW CONTRIBUTORS;
+Name Location Comment
+Ronald Bradford Brisbane, Australia EFF contribution for UC2006 Auction
+Sheeri Kritzer Boston, Mass. USA EFF contribution for UC2006 Auction
+Mark Shuttleworth London, UK. EFF contribution for UC2006 Auction
diff --git a/mysql-test/r/ctype_latin2_ch.result b/mysql-test/r/ctype_latin2_ch.result
index 2b3765c07c4..5b607872737 100644
--- a/mysql-test/r/ctype_latin2_ch.result
+++ b/mysql-test/r/ctype_latin2_ch.result
@@ -28,3 +28,4 @@ select * from t1 ignore index (primary) where tt like 'AA%';
id tt
select * from t1 where tt like '%AA%';
id tt
+drop table t1;
diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result
index eaea2e7479a..1c9d540d574 100644
--- a/mysql-test/r/ctype_sjis.result
+++ b/mysql-test/r/ctype_sjis.result
@@ -172,6 +172,6 @@ c2h
ab_def
drop table t1;
SET NAMES sjis;
-SELECT HEX('²“‘@\Œ\') FROM DUAL;
-HEX('²“‘@_Œ\')
+SELECT HEX('²“‘@Œ\') FROM DUAL;
+HEX('²“‘@Œ\')
8DB2939181408C5C
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index e58aaa4554f..62e2085ae09 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -674,6 +674,18 @@ Warnings:
Warning 1264 Out of range value for column 'Field1' at row 1
DROP TABLE t1;
SET NAMES latin1;
+SELECT CONVERT(103, CHAR(50) UNICODE);
+CONVERT(103, CHAR(50) UNICODE)
+103
+SELECT CONVERT(103.0, CHAR(50) UNICODE);
+CONVERT(103.0, CHAR(50) UNICODE)
+103.0
+SELECT CONVERT(-103, CHAR(50) UNICODE);
+CONVERT(-103, CHAR(50) UNICODE)
+-103
+SELECT CONVERT(-103.0, CHAR(50) UNICODE);
+CONVERT(-103.0, CHAR(50) UNICODE)
+-103.0
CREATE TABLE t1 (
a varchar(255) NOT NULL default '',
KEY a (a)
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 44f6945238c..1246c6f3d5d 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -412,7 +412,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) CHARACTER SET utf8 DEFAULT NULL,
- UNIQUE KEY `a` USING HASH (`c`(1))
+ UNIQUE KEY `a` (`c`(1)) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
@@ -448,7 +448,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) CHARACTER SET utf8 DEFAULT NULL,
- UNIQUE KEY `a` USING BTREE (`c`(1))
+ UNIQUE KEY `a` (`c`(1)) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
@@ -570,7 +570,7 @@ show create table t1;
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))
+ UNIQUE KEY `a` (`c`(1)) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
@@ -606,7 +606,7 @@ show create table t1;
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))
+ UNIQUE KEY `a` (`c`(1)) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index 214c9466c8c..ea4ae8a8438 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -515,3 +515,39 @@ NULL
select str_to_date( 1, IF(1=1,NULL,NULL) );
str_to_date( 1, IF(1=1,NULL,NULL) )
NULL
+SELECT TIME_FORMAT("24:00:00", '%r');
+TIME_FORMAT("24:00:00", '%r')
+12:00:00 AM
+SELECT TIME_FORMAT("00:00:00", '%r');
+TIME_FORMAT("00:00:00", '%r')
+12:00:00 AM
+SELECT TIME_FORMAT("12:00:00", '%r');
+TIME_FORMAT("12:00:00", '%r')
+12:00:00 PM
+SELECT TIME_FORMAT("15:00:00", '%r');
+TIME_FORMAT("15:00:00", '%r')
+03:00:00 PM
+SELECT TIME_FORMAT("01:00:00", '%r');
+TIME_FORMAT("01:00:00", '%r')
+01:00:00 AM
+SELECT TIME_FORMAT("25:00:00", '%r');
+TIME_FORMAT("25:00:00", '%r')
+01:00:00 AM
+SELECT TIME_FORMAT("00:00:00", '%l %p');
+TIME_FORMAT("00:00:00", '%l %p')
+12 AM
+SELECT TIME_FORMAT("01:00:00", '%l %p');
+TIME_FORMAT("01:00:00", '%l %p')
+1 AM
+SELECT TIME_FORMAT("12:00:00", '%l %p');
+TIME_FORMAT("12:00:00", '%l %p')
+12 PM
+SELECT TIME_FORMAT("23:00:00", '%l %p');
+TIME_FORMAT("23:00:00", '%l %p')
+11 PM
+SELECT TIME_FORMAT("24:00:00", '%l %p');
+TIME_FORMAT("24:00:00", '%l %p')
+12 AM
+SELECT TIME_FORMAT("25:00:00", '%l %p');
+TIME_FORMAT("25:00:00", '%l %p')
+1 AM
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index ddfeeac77b5..05f1c967e77 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -186,8 +186,8 @@ a b a b a b
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
+1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 8 test.t2.b,test.t1.b 1 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
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index a6ad95570f8..89b17d69f40 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -533,3 +533,15 @@ select count(distinct concat(x,y)) from t1;
count(distinct concat(x,y))
2
drop table t1;
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b));
+INSERT INTO t1 VALUES (1, 101);
+INSERT INTO t1 SELECT a + 1, a + 101 FROM t1;
+INSERT INTO t1 SELECT a + 2, a + 102 FROM t1;
+INSERT INTO t1 SELECT a + 4, a + 104 FROM t1;
+INSERT INTO t1 SELECT a + 8, a + 108 FROM t1;
+EXPLAIN SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 8 NULL 16 Using where; Using index
+SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a;
+a a
+DROP TABLE t1;
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result
index 01d206be7cb..77280f99b7c 100644
--- a/mysql-test/r/events.result
+++ b/mysql-test/r/events.result
@@ -17,13 +17,13 @@ db_x
SHOW TABLES FROM db_x;
Tables_in_db_x
x_table
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
DROP EVENT e_x1;
DROP EVENT e_x2;
DROP DATABASE db_x;
DROP USER pauline@localhost;
USE events_test;
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
drop event if exists event1;
Warnings:
Note 1305 Event event1 does not exist
@@ -100,7 +100,7 @@ a
800219
drop event non_qualif_ev;
drop table non_qualif;
-set global event_scheduler = 0;
+set global event_scheduler = 2;
create table t_event3 (a int, b float);
drop event if exists event3;
Warnings:
@@ -254,7 +254,7 @@ event CREATE TABLE `event` (
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
`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 (`definer`,`db`,`name`)
+ PRIMARY KEY (`db`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log.
@@ -280,87 +280,6 @@ SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED
DROP EVENT intact_check;
-create event one_event on schedule every 10 second do select 123;
-SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
-SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
-EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
-NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
-CREATE DATABASE events_test2;
-CREATE USER ev_test@localhost;
-GRANT ALL ON events_test.* to ev_test@localhost;
-GRANT ALL on events_test2.* to ev_test@localhost;
-REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
-REVOKE PROCESS on *.* from ev_test@localhost;
-select "NEW CONNECTION";
-NEW CONNECTION
-NEW CONNECTION
-SELECT USER(), DATABASE();
-USER() DATABASE()
-ev_test@localhost events_test2
-SHOW GRANTS;
-Grants for ev_test@localhost
-GRANT USAGE ON *.* TO 'ev_test'@'localhost'
-GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost'
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, TRIGGER ON `events_test2`.* TO 'ev_test'@'localhost'
-"Here comes an error:";
-SHOW EVENTS;
-ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2'
-USE events_test;
-"Now the list should be empty:";
-SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-select concat("Let's create some new events from the name of ",user());
-concat("Let's create some new events from the name of ",user())
-Let's create some new events from the name of ev_test@localhost
-create event one_event on schedule every 20 second do select 123;
-create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123;
-create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123;
-"Now we should see 3 events:";
-SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-"This should show us only 3 events:";
-SHOW FULL EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-"This should show us only 2 events:";
-SHOW FULL EVENTS LIKE 't%event';
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-"This should show us no events:";
-SHOW FULL EVENTS FROM test LIKE '%';
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-DROP DATABASE events_test2;
-"should see 1 event:";
-SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
-"we should see 4 events now:";
-SHOW FULL EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
-SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
-EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
-NULL events_test one_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE
-NULL events_test three_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
-NULL events_test two_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
-NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
-drop event one_event;
-drop event two_event;
-drop event three_event;
-drop user ev_test@localhost;
-drop event one_event;
-"Sleep a bit so the server closes the second connection"
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
@@ -373,12 +292,12 @@ ERROR HY000: Incorrect AT value: 'definitely not a datetime'
set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
drop event задачка;
-set event_scheduler=0;
+set event_scheduler=2;
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
-set global event_scheduler=2;
-ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2'
+set global event_scheduler=3;
+ERROR 42000: Variable 'event_scheduler' can't be set to the value of '3'
"DISABLE the scheduler. Testing that it does not work when the variable is 0"
-set global event_scheduler=0;
+set global event_scheduler=2;
select definer, name, db from mysql.event;
definer name db
select get_lock("test_lock1", 20);
@@ -389,9 +308,10 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
select definer, name, db from mysql.event;
definer name db
root@localhost закачка events_test
-"Should be 0 processes"
+"Should be only 1 process"
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db command state info
+event_scheduler localhost NULL Connect Suspended NULL
select release_lock("test_lock1");
release_lock("test_lock1")
1
@@ -409,11 +329,12 @@ get_lock("test_lock2", 20)
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
"Let some time pass to the event starts"
"Should have only 2 processes: the scheduler and the locked event"
-select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
+select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL
root localhost events_test Connect User lock select get_lock("test_lock2", 20)
"Release the mutex, the event worker should finish."
+"Release the mutex, the event worker should finish."
select release_lock("test_lock2");
release_lock("test_lock2")
1
@@ -423,21 +344,17 @@ select get_lock("test_lock2_1", 20);
get_lock("test_lock2_1", 20)
1
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
-"Should see 1 process, locked on get_lock("
-"Shutting down the scheduler, it should wait for the running event"
-set global event_scheduler=0;
-"Should have only 2 processes: the scheduler and the locked event"
-select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
+"Should have only 3 processes: the scheduler, our conn and the locked event"
+select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
-"Release the lock so the child process should finish. Hence the scheduler also"
-select release_lock("test_lock2_1");
-release_lock("test_lock2_1")
-1
-"Should see 0 processes now:"
-select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
+set global event_scheduler=2;
+"Should have only our process now:"
+select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db command state info
+event_scheduler localhost NULL Connect Suspended NULL
+root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
drop event закачка21;
create table t_16 (s1 int);
create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5;
diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
index ef1ccfadecb..bc89c692f9a 100644
--- a/mysql-test/r/events_bugs.result
+++ b/mysql-test/r/events_bugs.result
@@ -35,7 +35,7 @@ create event e_55 on schedule every 10 hour starts 99990101000000 do drop table
ERROR HY000: Incorrect STARTS value: '99990101000000'
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
ERROR HY000: ENDS is either invalid or before STARTS
-set global event_scheduler=0;
+set global event_scheduler=2;
"Wait a bit to settle down"
delete from mysql.event;
set global event_scheduler= 1;
@@ -57,7 +57,7 @@ root localhost events_test Connect User lock select get_lock('test_bug16407', 60
select release_lock('test_bug16407');
release_lock('test_bug16407')
1
-set global event_scheduler= 0;
+set global event_scheduler= 2;
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode
events_test e_16407 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
@@ -115,7 +115,7 @@ release_lock('ee_16407_2')
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL
-set global event_scheduler= 0;
+set global event_scheduler= 2;
select * from events_smode_test order by ev_name, a;
ev_name a
ee_16407_3 1980-02-19
@@ -175,7 +175,7 @@ drop event ee_16407_5;
drop event ee_16407_6;
drop procedure ee_16407_5_pendant;
drop procedure ee_16407_6_pendant;
-set global event_scheduler= 0;
+set global event_scheduler= 2;
drop table events_smode_test;
set sql_mode=@old_sql_mode;
drop database events_test;
diff --git a/mysql-test/r/events_grant.result b/mysql-test/r/events_grant.result
new file mode 100644
index 00000000000..6c140f91eaa
--- /dev/null
+++ b/mysql-test/r/events_grant.result
@@ -0,0 +1,121 @@
+CREATE DATABASE IF NOT EXISTS events_test;
+use events_test;
+CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123;
+SHOW EVENTS;
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+CREATE DATABASE events_test2;
+CREATE USER ev_test@localhost;
+GRANT ALL ON events_test.* to ev_test@localhost;
+GRANT ALL ON events_test2.* to ev_test@localhost;
+REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
+select "NEW CONNECTION";
+NEW CONNECTION
+NEW CONNECTION
+SELECT USER(), DATABASE();
+USER() DATABASE()
+ev_test@localhost events_test2
+SHOW GRANTS;
+Grants for ev_test@localhost
+GRANT USAGE ON *.* TO 'ev_test'@'localhost'
+GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, TRIGGER ON `events_test2`.* TO 'ev_test'@'localhost'
+"Here comes an error:";
+SHOW EVENTS;
+ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2'
+USE events_test;
+"We should see one event";
+SHOW EVENTS;
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
+SELECT CONCAT("Let's create some new events from the name of ", USER());
+CONCAT("Let's create some new events from the name of ", USER())
+Let's create some new events from the name of ev_test@localhost
+CREATE EVENT one_event ON SCHEDULE EVERY 20 SECOND DO SELECT 123;
+ERROR HY000: Event 'one_event' already exists
+CREATE EVENT two_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION NOT PRESERVE COMMENT "two event" DO SELECT 123;
+CREATE EVENT three_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION PRESERVE COMMENT "three event" DO SELECT 123;
+"Now we should see 3 events:";
+SHOW EVENTS;
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
+events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+"This should show us only 2 events:";
+SHOW EVENTS LIKE 't%event';
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+"This should show us no events:";
+SHOW EVENTS FROM test LIKE '%';
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+GRANT EVENT ON events_test2.* TO ev_test@localhost;
+USE events_test2;
+CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42;
+USE events_test;
+"We should see 4 events : one_event, two_event, three_event & four_event"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
+NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
+NULL events_test2 four_event ev_test@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE
+DROP DATABASE events_test2;
+"We should see 3 events : one_event, two_event, three_event"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
+NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
+CREATE DATABASE events_test2;
+USE events_test2;
+CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42;
+"Should see 4 events - one, two, three & five"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
+NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
+NULL events_test2 five_event root@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE
+REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
+USE test;
+"Should see 3 events - one, two & three"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
+NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
+"Let's test ALTER EVENT which changes the definer"
+USE events_test;
+ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND;
+"The definer should be ev_test@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event ev_test@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
+USE events_test;
+ALTER EVENT one_event COMMENT "comment";
+"The definer should be root@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment
+ALTER EVENT one_event DO SELECT 12;
+"The definer should be ev_test@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test one_event ev_test@localhost SELECT 12 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment
+"make the definer again root@localhost"
+ALTER EVENT one_event COMMENT "new comment";
+"test DROP by another user"
+DROP EVENT one_event;
+"One event should not be there"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
+NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event
+NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event
+NULL events_test2 five_event root@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE
+DROP USER ev_test@localhost;
+DROP DATABASE events_test2;
+DROP DATABASE events_test;
diff --git a/mysql-test/r/events_logs_tests.result b/mysql-test/r/events_logs_tests.result
index e6ca3c29e9b..ce58e0ec059 100644
--- a/mysql-test/r/events_logs_tests.result
+++ b/mysql-test/r/events_logs_tests.result
@@ -8,7 +8,7 @@ BEGIN
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
END|
"Check General Query Log"
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
TRUNCATE mysql.general_log;
"1 row, the current statement!"
@@ -19,10 +19,10 @@ SET GLOBAL event_scheduler=1;
"Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
call select_general_log();
user_host argument
-root[root] @ localhost [localhost] SELect 'alabala', sleep(3) from dual
+USER_HOST SELect 'alabala', sleep(3) from dual
DROP PROCEDURE select_general_log;
DROP EVENT log_general;
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
"Check slow query log"
"Save the values"
SET @old_global_long_query_time:=(select get_value());
@@ -36,14 +36,14 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text
"Set new values"
SET GLOBAL long_query_time=4;
-SET SESSION long_query_time=2;
+SET SESSION long_query_time=1;
"Check that logging is working"
-SELECT SLEEP(3);
-SLEEP(3)
+SELECT SLEEP(2);
+SLEEP(2)
0
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text
-root[root] @ localhost [] 00:00:03 events_test SELECT SLEEP(3)
+USER_HOST SLEEPVAL events_test SELECT SLEEP(2)
TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
"This won't go to the slow log"
@@ -54,7 +54,7 @@ SET GLOBAL event_scheduler=1;
"Sleep some more time than the actual event run will take"
SHOW VARIABLES LIKE 'event_scheduler';
Variable_name Value
-event_scheduler ON
+event_scheduler 1
"Check our table. Should see 1 row"
SELECT * FROM slow_event_test;
slo_val val
@@ -64,18 +64,19 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text
"This should go to the slow log"
SET SESSION long_query_time=10;
+SET GLOBAL long_query_time=1;
DROP EVENT long_event;
-CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5);
+CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2);
"Sleep some more time than the actual event run will take"
"Check our table. Should see 2 rows"
SELECT * FROM slow_event_test;
slo_val val
4 0
-4 0
-"Check slow log. Should see 1 row because 5 is over the threshold of 4 for GLOBAL, though under SESSION which is 10"
+1 0
+"Check slow log. Should see 1 row because 4 is over the threshold of 3 for GLOBAL, though under SESSION which is 10"
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text
-root[root] @ localhost [localhost] 00:00:05 events_test INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5)
+USER_HOST SLEEPVAL events_test INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2)
DROP EVENT long_event2;
SET GLOBAL long_query_time =@old_global_long_query_time;
SET SESSION long_query_time =@old_session_long_query_time;
diff --git a/mysql-test/r/events_microsec.result b/mysql-test/r/events_microsec.result
index ed15b066b93..b96bd551511 100644
--- a/mysql-test/r/events_microsec.result
+++ b/mysql-test/r/events_microsec.result
@@ -10,50 +10,4 @@ CREATE EVENT micro_test ON SCHEDULE EVERY 100 MINUTE_MICROSECOND DO SELECT 1;
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1;
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-"Now create normal event and change it on SQL level"
-CREATE EVENT micro_test2 ON SCHEDULE EVERY 1 MONTH DO SELECT 1;
-UPDATE mysql.event SET interval_field='MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
-SHOW CREATE EVENT micro_test2;
-ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-SET GLOBAL event_scheduler=0;
-"Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-Variable_name Value
-event_scheduler OFF
-UPDATE mysql.event SET interval_field='DAY_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
-SHOW CREATE EVENT micro_test2;
-ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-SET GLOBAL event_scheduler=0;
-"Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-Variable_name Value
-event_scheduler OFF
-UPDATE mysql.event SET interval_field='SECOND_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
-SHOW CREATE EVENT micro_test2;
-ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-SET GLOBAL event_scheduler=0;
-"Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-Variable_name Value
-event_scheduler OFF
-UPDATE mysql.event SET interval_field='HOUR_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
-SHOW CREATE EVENT micro_test2;
-ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-SET GLOBAL event_scheduler=0;
-"Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-Variable_name Value
-event_scheduler OFF
-UPDATE mysql.event SET interval_field='MINUTE_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
-SHOW CREATE EVENT micro_test2;
-ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
-SET GLOBAL event_scheduler=0;
-"Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-Variable_name Value
-event_scheduler OFF
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER='event_scheduler';
-COUNT(*)
-0
-DROP EVENT micro_test2;
drop database events_test;
diff --git a/mysql-test/r/events_scheduling.result b/mysql-test/r/events_scheduling.result
index 67e8e6d5691..aec2053f0e7 100644
--- a/mysql-test/r/events_scheduling.result
+++ b/mysql-test/r/events_scheduling.result
@@ -4,7 +4,9 @@ CREATE TABLE table_1(a int);
CREATE TABLE table_2(a int);
CREATE TABLE table_3(a int);
CREATE TABLE table_4(a int);
+CREATE TABLE T19170(s1 TIMESTAMP);
SET GLOBAL event_scheduler=1;
+CREATE EVENT E19170 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO T19170 VALUES(CURRENT_TIMESTAMP);
CREATE EVENT two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
CREATE EVENT start_n_end
ON SCHEDULE EVERY 1 SECOND
@@ -12,7 +14,7 @@ ENDS NOW() + INTERVAL 6 SECOND
ON COMPLETION PRESERVE
DO INSERT INTO table_2 VALUES(1);
CREATE EVENT only_one_time ON SCHEDULE EVERY 2 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_3 VALUES(1);
-CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_4 VALUES(1);
+CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND ON COMPLETION PRESERVE DO INSERT INTO table_4 VALUES(1);
SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
IF(SUM(a) >= 4, 'OK', 'ERROR')
OK
@@ -29,18 +31,25 @@ DROP EVENT two_sec;
SELECT IF(TIME_TO_SEC(TIMEDIFF(ENDS,STARTS))=6, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
IF(TIME_TO_SEC(TIMEDIFF(ENDS,STARTS))=6, 'OK', 'ERROR')
OK
-SELECT IF(LAST_EXECUTED-ENDS < 2, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
-IF(LAST_EXECUTED-ENDS < 2, 'OK', 'ERROR')
+SELECT IF(LAST_EXECUTED-ENDS < 3, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
+IF(LAST_EXECUTED-ENDS < 3, 'OK', 'ERROR')
OK
DROP EVENT start_n_end;
"Already dropped because ended. Therefore an error."
DROP EVENT only_one_time;
ERROR HY000: Unknown event 'only_one_time'
-"Already dropped because ended. Therefore an error."
+"Should be preserved"
+SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
+EVENT_NAME STATUS
+E19170 ENABLED
+two_time DISABLED
DROP EVENT two_time;
-ERROR HY000: Unknown event 'two_time'
DROP TABLE table_1;
DROP TABLE table_2;
DROP TABLE table_3;
DROP TABLE table_4;
+"Checking for multiple executions in one second, should not happen -> 0 as result"
+SELECT COUNT(*) FROM (SELECT s1, COUNT(*) AS cnt FROM T19170 GROUP BY s1) AS tmp WHERE tmp.cnt > 1;
+COUNT(*)
+0
DROP DATABASE events_test;
diff --git a/mysql-test/r/events_stress.result b/mysql-test/r/events_stress.result
index 9f95cfad75d..ead618e8136 100644
--- a/mysql-test/r/events_stress.result
+++ b/mysql-test/r/events_stress.result
@@ -1,46 +1,61 @@
CREATE DATABASE IF NOT EXISTS events_test;
-CREATE DATABASE events_test2;
-USE events_test2;
+CREATE DATABASE events_conn1_test2;
+CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime);
+CREATE USER event_user2@localhost;
+CREATE DATABASE events_conn2_db;
+GRANT ALL ON *.* TO event_user2@localhost;
+CREATE USER event_user3@localhost;
+CREATE DATABASE events_conn3_db;
+GRANT ALL ON *.* TO event_user3@localhost;
+"In the second connection we create some events which won't be dropped till the end"
+"In the second connection we create some events which won't be dropped till the end"
+USE events_conn1_test2;
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
USE events_test;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
+COUNT(*)
+103
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*)
3
-DROP DATABASE events_test2;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+DROP DATABASE events_conn1_test2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*)
0
"Now testing stability - dropping db -> events while they are running"
-CREATE DATABASE events_test2;
-USE events_test2;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+CREATE DATABASE events_conn1_test2;
+USE events_conn1_test2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*)
-1000
+50
SET GLOBAL event_scheduler=1;
-DROP DATABASE events_test2;
-SET GLOBAL event_scheduler=0;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+DROP DATABASE events_conn1_test2;
+SET GLOBAL event_scheduler=2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*)
0
-CREATE DATABASE events_test3;
-USE events_test3;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
+CREATE DATABASE events_conn1_test3;
+USE events_conn1_test3;
+SET GLOBAL event_scheduler=1;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
COUNT(*)
-950
-CREATE DATABASE events_test4;
-USE events_test4;
-CREATE DATABASE events_test2;
-USE events_test2;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+50
+CREATE DATABASE events_conn1_test4;
+USE events_conn1_test4;
+CREATE DATABASE events_conn1_test2;
+USE events_conn1_test2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*)
-1050
-DROP DATABASE events_test2;
-SET GLOBAL event_scheduler=0;
-DROP DATABASE events_test3;
-SET GLOBAL event_scheduler=1;
-DROP DATABASE events_test4;
+50
+DROP DATABASE events_conn2_db;
+DROP DATABASE events_conn3_db;
+DROP DATABASE events_conn1_test2;
+DROP DATABASE events_conn1_test3;
+SET GLOBAL event_scheduler=2;
+DROP DATABASE events_conn1_test4;
SET GLOBAL event_scheduler=1;
USE events_test;
+DROP TABLE fill_it;
DROP DATABASE events_test;
diff --git a/mysql-test/r/exampledb.result b/mysql-test/r/exampledb.result
index 9bfb77c1c0b..6eea24e2e1f 100644
--- a/mysql-test/r/exampledb.result
+++ b/mysql-test/r/exampledb.result
@@ -1,3 +1,5 @@
+drop database if exists events_test;
+drop database if exists events_test2;
drop table if exists t1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index d66dec741bd..75e1548cdee 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -53,3 +53,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ÔÁÂ ref ÉÎÄ0,ÉÎÄ01 ÉÎÄ0 5 const 1 Using where; Using index
drop table ÔÁÂ;
set names latin1;
+select 3 into @v1;
+explain select 3 into @v1;
+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_compress.result b/mysql-test/r/func_compress.result
index 9bc8e417e19..8d6fa9927ce 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -72,3 +72,10 @@ set @@max_allowed_packet=1048576*100;
select compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null;
compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null
0
+create table t1(a blob);
+insert into t1 values(NULL), (compress('a'));
+select uncompress(a), uncompressed_length(a) from t1;
+uncompress(a) uncompressed_length(a)
+NULL NULL
+a 1
+drop table t1;
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 23a587ca3a7..62b4ddf868a 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -611,6 +611,16 @@ count(distinct (f1+1))
1
3
drop table t1;
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+select f2,group_concat(f1) from t1 group by f2;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 f2 f2 253 255 255 Y 0 0 8
+def group_concat(f1) 253 400 1 Y 128 0 63
+f2 group_concat(f1)
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2
+drop table t1;
set names latin1;
create table t1 (a char, b char);
insert into t1 values ('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b');
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 58bf3b36469..824edbbe3a6 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -821,144 +821,6 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
MAX(id)
NULL
DROP TABLE t1;
-create table t1m (a int) engine=myisam;
-create table t1i (a int) engine=innodb;
-create table t2m (a int) engine=myisam;
-create table t2i (a int) engine=innodb;
-insert into t2m values (5);
-insert into t2i values (5);
-select min(a) from t1m;
-min(a)
-NULL
-select min(7) from t1m;
-min(7)
-NULL
-select min(7) from DUAL;
-min(7)
-NULL
-explain select min(7) from t2m join t1m;
-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
-select min(7) from t2m join t1m;
-min(7)
-NULL
-select max(a) from t1m;
-max(a)
-NULL
-select max(7) from t1m;
-max(7)
-NULL
-select max(7) from DUAL;
-max(7)
-NULL
-explain select max(7) from t2m join t1m;
-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
-select max(7) from t2m join t1m;
-max(7)
-NULL
-select 1, min(a) from t1m where a=99;
-1 min(a)
-1 NULL
-select 1, min(a) from t1m where 1=99;
-1 min(a)
-1 NULL
-select 1, min(1) from t1m where a=99;
-1 min(1)
-1 NULL
-select 1, min(1) from t1m where 1=99;
-1 min(1)
-1 NULL
-select 1, max(a) from t1m where a=99;
-1 max(a)
-1 NULL
-select 1, max(a) from t1m where 1=99;
-1 max(a)
-1 NULL
-select 1, max(1) from t1m where a=99;
-1 max(1)
-1 NULL
-select 1, max(1) from t1m where 1=99;
-1 max(1)
-1 NULL
-select min(a) from t1i;
-min(a)
-NULL
-select min(7) from t1i;
-min(7)
-NULL
-select min(7) from DUAL;
-min(7)
-NULL
-explain select min(7) from t2i join t1i;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2i ALL NULL NULL NULL NULL 1
-1 SIMPLE t1i ALL NULL NULL NULL NULL 1
-select min(7) from t2i join t1i;
-min(7)
-NULL
-select max(a) from t1i;
-max(a)
-NULL
-select max(7) from t1i;
-max(7)
-NULL
-select max(7) from DUAL;
-max(7)
-NULL
-explain select max(7) from t2i join t1i;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2i ALL NULL NULL NULL NULL 1
-1 SIMPLE t1i ALL NULL NULL NULL NULL 1
-select max(7) from t2i join t1i;
-max(7)
-NULL
-select 1, min(a) from t1i where a=99;
-1 min(a)
-1 NULL
-select 1, min(a) from t1i where 1=99;
-1 min(a)
-1 NULL
-select 1, min(1) from t1i where a=99;
-1 min(1)
-1 NULL
-select 1, min(1) from t1i where 1=99;
-1 min(1)
-1 NULL
-select 1, max(a) from t1i where a=99;
-1 max(a)
-1 NULL
-select 1, max(a) from t1i where 1=99;
-1 max(a)
-1 NULL
-select 1, max(1) from t1i where a=99;
-1 max(1)
-1 NULL
-select 1, max(1) from t1i where 1=99;
-1 max(1)
-1 NULL
-explain select count(*), min(7), max(7) from t1m, t1i;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
-1 SIMPLE t1i ALL NULL NULL NULL NULL 1
-select count(*), min(7), max(7) from t1m, t1i;
-count(*) min(7) max(7)
-0 NULL NULL
-explain select count(*), min(7), max(7) from t1m, t2i;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
-1 SIMPLE t2i ALL NULL NULL NULL NULL 1
-select count(*), min(7), max(7) from t1m, t2i;
-count(*) min(7) max(7)
-0 NULL NULL
-explain select count(*), min(7), max(7) from t2m, t1i;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2m system NULL NULL NULL NULL 1
-1 SIMPLE t1i ALL NULL NULL NULL NULL 1
-select count(*), min(7), max(7) from t2m, t1i;
-count(*) min(7) max(7)
-0 NULL NULL
-drop table t1m, t1i, t2m, t2i;
create table t2 (ff double);
insert into t2 values (2.2);
select cast(sum(distinct ff) as decimal(5,2)) from t2;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index 60022ae0d8f..e38e2624e19 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1, t2;
select 1 in (1,2,3);
1 in (1,2,3)
1
@@ -225,3 +225,121 @@ a
46
DROP VIEW v1;
DROP TABLE t1;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, filler char(200), key(a));
+insert into t2 select C.a*2, 'no' from t1 A, t1 B, t1 C;
+insert into t2 select C.a*2+1, 'yes' from t1 C;
+explain
+select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 5 NULL 12 Using where
+select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
+a filler
+1 yes
+3 yes
+5 yes
+7 yes
+9 yes
+11 yes
+13 yes
+15 yes
+17 yes
+19 yes
+explain select * from t2 force index(a) where a NOT IN (2,2,2,2,2,2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 5 NULL 912 Using where
+explain select * from t2 force index(a) where a <> 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 5 NULL 912 Using where
+drop table t2;
+create table t2 (a datetime, filler char(200), key(a));
+insert into t2 select '2006-04-25 10:00:00' + interval C.a minute,
+'no' from t1 A, t1 B, t1 C where C.a % 2 = 0;
+insert into t2 select '2006-04-25 10:00:00' + interval C.a*2+1 minute,
+'yes' from t1 C;
+explain
+select * from t2 where a NOT IN (
+'2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
+'2006-04-25 10:06:00', '2006-04-25 10:08:00');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 9 NULL 18 Using where
+select * from t2 where a NOT IN (
+'2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
+'2006-04-25 10:06:00', '2006-04-25 10:08:00');
+a filler
+2006-04-25 10:01:00 yes
+2006-04-25 10:03:00 yes
+2006-04-25 10:05:00 yes
+2006-04-25 10:07:00 yes
+2006-04-25 10:09:00 yes
+2006-04-25 10:11:00 yes
+2006-04-25 10:13:00 yes
+2006-04-25 10:15:00 yes
+2006-04-25 10:17:00 yes
+2006-04-25 10:19:00 yes
+drop table t2;
+create table t2 (a varchar(10), filler char(200), key(a));
+insert into t2 select 'foo', 'no' from t1 A, t1 B;
+insert into t2 select 'barbar', 'no' from t1 A, t1 B;
+insert into t2 select 'bazbazbaz', 'no' from t1 A, t1 B;
+insert into t2 values ('fon', '1'), ('fop','1'), ('barbaq','1'),
+('barbas','1'), ('bazbazbay', '1'),('zz','1');
+explain select * from t2 where a not in('foo','barbar', 'bazbazbaz');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 13 NULL 7 Using where
+drop table t2;
+create table t2 (a decimal(10,5), filler char(200), key(a));
+insert into t2 select 345.67890, 'no' from t1 A, t1 B;
+insert into t2 select 43245.34, 'no' from t1 A, t1 B;
+insert into t2 select 64224.56344, 'no' from t1 A, t1 B;
+insert into t2 values (0, '1'), (22334.123,'1'), (33333,'1'),
+(55555,'1'), (77777, '1');
+explain
+select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 7 NULL 7 Using where
+select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
+a filler
+0.00000 1
+22334.12300 1
+33333.00000 1
+55555.00000 1
+77777.00000 1
+drop table t2;
+create table t2 (a int, key(a), b int);
+insert into t2 values (1,1),(2,2);
+set @cnt= 1;
+set @str="update t2 set b=1 where a not in (";
+select count(*) from (
+select @str:=concat(@str, @cnt:=@cnt+1, ",")
+from t1 A, t1 B, t1 C, t1 D) Z;
+count(*)
+10000
+set @str:=concat(@str, "10000)");
+select substr(@str, 1, 50);
+substr(@str, 1, 50)
+update t2 set b=1 where a not in (2,3,4,5,6,7,8,9,
+prepare s from @str;
+execute s;
+deallocate prepare s;
+set @str=NULL;
+drop table t2;
+drop table t1;
+create table t1 (
+some_id smallint(5) unsigned,
+key (some_id)
+);
+insert into t1 values (1),(2);
+select some_id from t1 where some_id not in(2,-1);
+some_id
+1
+select some_id from t1 where some_id not in(-4,-1,-4);
+some_id
+1
+2
+select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
+some_id
+1
+2
+drop table t1;
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 5e375472c5f..10d20c001f1 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -51,6 +51,42 @@ select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
a
2004-01-06 12:34:00
drop table t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (conn CHAR(7), connection_id INT);
+INSERT INTO t1 VALUES ('default', CONNECTION_ID());
+SELECT GET_LOCK('bug16501',600);
+GET_LOCK('bug16501',600)
+1
+INSERT INTO t1 VALUES ('con1', CONNECTION_ID());
+SELECT IS_USED_LOCK('bug16501') = connection_id
+FROM t1
+WHERE conn = 'default';
+IS_USED_LOCK('bug16501') = connection_id
+1
+ SELECT GET_LOCK('bug16501',600);
+SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
+IS_USED_LOCK('bug16501') = CONNECTION_ID()
+1
+SELECT RELEASE_LOCK('bug16501');
+RELEASE_LOCK('bug16501')
+1
+GET_LOCK('bug16501',600)
+1
+SELECT IS_USED_LOCK('bug16501') = connection_id
+FROM t1
+WHERE conn = 'con1';
+IS_USED_LOCK('bug16501') = connection_id
+1
+SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
+IS_USED_LOCK('bug16501') = CONNECTION_ID()
+1
+SELECT RELEASE_LOCK('bug16501');
+RELEASE_LOCK('bug16501')
+1
+SELECT IS_USED_LOCK('bug16501');
+IS_USED_LOCK('bug16501')
+NULL
+DROP TABLE t1;
create table t1 as select uuid(), length(uuid());
show create table t1;
Table Create Table
diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result
index 61b29e9380d..24685d07f3d 100644
--- a/mysql-test/r/func_op.result
+++ b/mysql-test/r/func_op.result
@@ -35,3 +35,14 @@ select -1 >> 0, -1 << 0;
select -1 >> 1, -1 << 1;
-1 >> 1 -1 << 1
9223372036854775807 18446744073709551614
+drop table if exists t1,t2;
+create table t1(a int);
+create table t2(a int, b int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1, 7), (3, 7);
+select t1.a, t2.a, t2.b, bit_count(t2.b) from t1 left join t2 on t1.a=t2.a;
+a a b bit_count(t2.b)
+1 1 7 3
+2 NULL NULL NULL
+3 3 7 3
+drop table t1, t2;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 46c37795531..354c886b19b 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1017,6 +1017,13 @@ t
1000000
1
drop table t1;
+select load_file("lkjlkj");
+load_file("lkjlkj")
+NULL
+select ifnull(load_file("lkjlkj"),"it's null");
+ifnull(load_file("lkjlkj"),"it's null")
+it's null
+End of 4.1 tests
create table t1 (d decimal default null);
insert into t1 values (null);
select format(d, 2) from t1;
@@ -1030,3 +1037,19 @@ c res
y,abc abc
y,abc abc
drop table t1;
+select cast(rtrim(' 20.06 ') as decimal(19,2));
+cast(rtrim(' 20.06 ') as decimal(19,2))
+20.06
+select cast(ltrim(' 20.06 ') as decimal(19,2));
+cast(ltrim(' 20.06 ') as decimal(19,2))
+20.06
+select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2));
+cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2))
+20.06
+select conv("18383815659218730760",10,10) + 0;
+conv("18383815659218730760",10,10) + 0
+1.8383815659219e+19
+select "18383815659218730760" + 0;
+"18383815659218730760" + 0
+1.8383815659219e+19
+End of 5.0 tests
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index b5fd35d926f..516809b8906 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -732,12 +732,6 @@ 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
@@ -753,6 +747,17 @@ last_day('2005-01-00')
NULL
Warnings:
Warning 1292 Incorrect datetime value: '2005-01-00'
+select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
+monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
+monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m'))
+NULL NULL January NULL
+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;
+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 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
@@ -872,3 +877,38 @@ id day id day
1 2005-06-01 3 2005-07-15
3 2005-07-01 3 2005-07-15
DROP TABLE t1,t2;
+End of 5.0 tests
+select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND)
+NULL
+select date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND)
+NULL
+select date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND);
+date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND)
+NULL
+select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND)
+0199-12-31 23:59:59
+select date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND);
+date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND)
+0200-01-01 00:00:00
+select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND)
+0199-12-31 23:59:59
+select date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR);
+date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR)
+0001-01-01 23:59:59
+select date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND)
+2049-12-31 23:59:59
+select date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND)
+1989-12-31 23:59:59
+select date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND)
+NULL
+select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
+date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND)
+NULL
+End of 5.1 tests
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index bf4a10a0041..cd6a2510001 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -294,7 +294,7 @@ t2 CREATE TABLE `t2` (
`g` geometry NOT NULL,
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32))
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1
SELECT count(*) FROM t2;
count(*)
100
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 6c6e0f19e08..12d20978cf9 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -355,3 +355,17 @@ insert into mysql.user select * from t1;
drop table t1, t2;
drop database TESTDB;
flush privileges;
+grant all privileges on test.* to `a@`@localhost;
+grant execute on * to `a@`@localhost;
+create table t2 (s1 int);
+insert into t2 values (1);
+drop function if exists f2;
+create function f2 () returns int begin declare v int; select s1 from t2
+into v; return v; end//
+select f2();
+f2()
+1
+drop function f2;
+drop table t2;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
+drop user `a@`@localhost;
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 6370f7699b3..f9b55cc6a7b 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -2116,3 +2116,25 @@ COUNT(DISTINCT a)
1
DROP TABLE t1;
DROP PROCEDURE a;
+CREATE TABLE t1 (a varchar(64) NOT NULL default '', PRIMARY KEY(a));
+INSERT INTO t1 (a) VALUES
+(''), ('CENTRAL'), ('EASTERN'), ('GREATER LONDON'),
+('NORTH CENTRAL'), ('NORTH EAST'), ('NORTH WEST'), ('SCOTLAND'),
+('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN');
+EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL PRIMARY 66 NULL 12 Using index for group-by
+SELECT DISTINCT a,a FROM t1 ORDER BY a;
+a a
+
+CENTRAL CENTRAL
+EASTERN EASTERN
+GREATER LONDON GREATER LONDON
+NORTH CENTRAL NORTH CENTRAL
+NORTH EAST NORTH EAST
+NORTH WEST NORTH WEST
+SCOTLAND SCOTLAND
+SOUTH EAST SOUTH EAST
+SOUTH WEST SOUTH WEST
+WESTERN WESTERN
+DROP TABLE t1;
diff --git a/mysql-test/r/have_ndb_status_ok.require b/mysql-test/r/have_ndb_status_ok.require
new file mode 100644
index 00000000000..8a82871234b
--- /dev/null
+++ b/mysql-test/r/have_ndb_status_ok.require
@@ -0,0 +1,2 @@
+ndb_status_ok
+YES
diff --git a/mysql-test/r/have_udf.require b/mysql-test/r/have_udf.require
index 6204435c17a..2d21f65e4ac 100644
--- a/mysql-test/r/have_udf.require
+++ b/mysql-test/r/have_udf.require
@@ -1,2 +1,2 @@
Variable_name Value
-have_dlopen YES
+have_dynamic_loading YES
diff --git a/mysql-test/r/have_udf_example.require b/mysql-test/r/have_udf_example.require
new file mode 100644
index 00000000000..e60fab1dbe0
--- /dev/null
+++ b/mysql-test/r/have_udf_example.require
@@ -0,0 +1,2 @@
+have_udf_example_lib
+1
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index fe918e4c3ff..68b13b5fc0a 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -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 0 having (count(`test`.`t1`.`a`) >= 0)
+Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where 0 having (`b` >= 0)
drop table t1;
CREATE TABLE t1 (
raw_id int(10) NOT NULL default '0',
@@ -392,3 +392,16 @@ HAVING HU.PROJ.CITY = HU.STAFF.CITY);
EMPNUM GRADE*1000
E3 13000
DROP SCHEMA HU;
+USE test;
+create table t1(f1 int);
+select f1 from t1 having max(f1)=f1;
+f1
+select f1 from t1 group by f1 having max(f1)=f1;
+f1
+set session sql_mode='ONLY_FULL_GROUP_BY';
+select f1 from t1 having max(f1)=f1;
+ERROR 42000: non-grouping field 'f1' is used in HAVING clause
+select f1 from t1 group by f1 having max(f1)=f1;
+f1
+set session sql_mode='';
+drop table t1;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 5a2d07db5e6..a75f6c96b20 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -556,9 +556,9 @@ 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))
+ KEY `v` (`v`) USING BTREE,
+ KEY `c` (`c`) USING BTREE,
+ KEY `t` (`t`(10)) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -718,3 +718,16 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I
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;
+CREATE TABLE t1(a VARCHAR(1), b VARCHAR(2), c VARCHAR(256),
+KEY(a), KEY(b), KEY(c)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES('a','aa',REPEAT('a', 256)),('a','aa',REPEAT('a',256));
+SELECT COUNT(*) FROM t1 WHERE a='a';
+COUNT(*)
+2
+SELECT COUNT(*) FROM t1 WHERE b='aa';
+COUNT(*)
+2
+SELECT COUNT(*) FROM t1 WHERE c=REPEAT('a',256);
+COUNT(*)
+2
+DROP TABLE t1;
diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
index a100266978b..7b944558a62 100644
--- a/mysql-test/r/heap_btree.result
+++ b/mysql-test/r/heap_btree.result
@@ -246,3 +246,13 @@ DELETE from t1 where a < 100;
SELECT * from t1;
a
DROP TABLE t1;
+CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
+INSERT INTO t1 VALUES(0);
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+INDEX_LENGTH
+21
+UPDATE t1 SET val=1;
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+INDEX_LENGTH
+21
+DROP TABLE t1;
diff --git a/mysql-test/r/im_cmd_line.result b/mysql-test/r/im_cmd_line.result
new file mode 100644
index 00000000000..5b289549a3f
--- /dev/null
+++ b/mysql-test/r/im_cmd_line.result
@@ -0,0 +1,40 @@
+--> Listing users...
+im_admin
+
+==> Adding user 'testuser'...
+
+--> IM password file:
+testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
+im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
+--> EOF
+
+--> Printing out line for 'testuser'...
+testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
+
+--> Listing users...
+im_admin
+testuser
+
+==> Changing the password of 'testuser'...
+
+--> IM password file:
+im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
+testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
+--> EOF
+
+--> Printing out line for 'testuser'...
+testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
+
+--> Listing users...
+testuser
+im_admin
+
+==> Dropping user 'testuser'...
+
+--> IM password file:
+im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
+--> EOF
+
+--> Listing users...
+im_admin
+
diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result
index d0a76b450fe..29c9ea2047d 100644
--- a/mysql-test/r/im_daemon_life_cycle.result
+++ b/mysql-test/r/im_daemon_life_cycle.result
@@ -1,5 +1,5 @@
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
Killing the process...
diff --git a/mysql-test/r/im_instance_conf.result b/mysql-test/r/im_instance_conf.result
new file mode 100644
index 00000000000..efda9439f38
--- /dev/null
+++ b/mysql-test/r/im_instance_conf.result
@@ -0,0 +1,196 @@
+--------------------------------------------------------------------
+server_id = 1
+server_id = 2
+--------------------------------------------------------------------
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+
+---> connection: mysql1_con
+SHOW VARIABLES LIKE 'server_id';
+Variable_name Value
+server_id 1
+
+---> connection: default
+CREATE INSTANCE mysqld3;
+SHOW INSTANCES;
+instance_name state
+mysqld3 offline
+mysqld2 offline
+mysqld1 online
+--------------------------------------------------------------------
+server_id = 1
+server_id = 2
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld1;
+ERROR HY000: Instance already exists
+CREATE INSTANCE mysqld2;
+ERROR HY000: Instance already exists
+CREATE INSTANCE mysqld3;
+ERROR HY000: Instance already exists
+--------------------------------------------------------------------
+nonguarded
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld4 nonguarded;
+SHOW INSTANCES;
+instance_name state
+mysqld3 offline
+mysqld4 offline
+mysqld1 online
+mysqld2 offline
+--------------------------------------------------------------------
+nonguarded
+nonguarded
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld4 offline
+mysqld5 offline
+mysqld2 offline
+mysqld3 offline
+--------------------------------------------------------------------
+test-A=000
+--------------------------------------------------------------------
+test-B=test
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+--------------------------------------------------------------------
+test-C1=10
+--------------------------------------------------------------------
+test-C2=02
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld7 test-D = test-D-value ;
+ERROR 42000: 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
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+CREATE INSTANCE mysqld8 test-E 0 ;
+ERROR 42000: 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
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+CREATE INSTANCE mysqld8 test-F = ;
+ERROR 42000: 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
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+mysqld9 offline
+CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld9a offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+mysqld9 offline
+mysqld2 offline
+CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
+SHOW INSTANCES;
+instance_name state
+mysqld9b offline
+mysqld9a offline
+mysqld5 offline
+mysqld6 offline
+mysqld3 offline
+mysqld4 offline
+mysqld9 offline
+mysqld2 offline
+mysqld1 online
+CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
+SHOW INSTANCES;
+instance_name state
+mysqld9b offline
+mysqld6 offline
+mysqld5 offline
+mysqld9c offline
+mysqld3 offline
+mysqld4 offline
+mysqld9 offline
+mysqld2 offline
+mysqld1 online
+mysqld9a offline
+CREATE INSTANCE mysqld10 test-bad=' \ ';
+ERROR 42000: 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
+SHOW INSTANCES;
+instance_name state
+mysqld9b offline
+mysqld6 offline
+mysqld5 offline
+mysqld9c offline
+mysqld3 offline
+mysqld4 offline
+mysqld9 offline
+mysqld2 offline
+mysqld1 online
+mysqld9a offline
+--------------------------------------------------------------------
+test-1= hello world
+--------------------------------------------------------------------
+test-2=
+--------------------------------------------------------------------
+test-3=abc def
+--------------------------------------------------------------------
+test-4=abc def
+--------------------------------------------------------------------
+test-5=abc
+--------------------------------------------------------------------
+test-6=abc def
+--------------------------------------------------------------------
+test-7=abc\def
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+CREATE INSTANCE qqq1;
+ERROR HY000: Malformed instance name.
diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result
index e208ccb9f00..876fbb38eee 100644
--- a/mysql-test/r/im_life_cycle.result
+++ b/mysql-test/r/im_life_cycle.result
@@ -1,69 +1,93 @@
+
+--------------------------------------------------------------------
+-- 1.1.1.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+
+--------------------------------------------------------------------
+-- 1.1.2.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 online
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 online VERSION_NUMBER VERSION
SHOW VARIABLES LIKE 'port';
Variable_name Value
-port IM_MYSQLD1_PORT
+port IM_MYSQLD2_PORT
+
+--------------------------------------------------------------------
+-- 1.1.3.
+--------------------------------------------------------------------
STOP INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
+instance_name state version_number version mysqld_compatible
+mysqld1 online VERSION_NUMBER VERSION no
SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+instance_name state version_number version mysqld_compatible
+mysqld2 offline VERSION_NUMBER VERSION no
+
+--------------------------------------------------------------------
+-- 1.1.4.
+--------------------------------------------------------------------
START INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
START INSTANCE mysqld1;
ERROR HY000: The instance is already started
+
+--------------------------------------------------------------------
+-- 1.1.5.
+--------------------------------------------------------------------
STOP INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
+
+--------------------------------------------------------------------
+-- 1.1.6.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
Killing the process...
Sleeping...
Success: the process was restarted.
+
+--------------------------------------------------------------------
+-- 1.1.7.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 online
Killing the process...
Sleeping...
Success: the process was killed.
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.8.
+--------------------------------------------------------------------
SHOW INSTANCE STATUS;
ERROR 42000: 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
+
+--------------------------------------------------------------------
+-- BUG#12813
+--------------------------------------------------------------------
START INSTANCE mysqld1,mysqld2,mysqld3;
ERROR 42000: 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
STOP INSTANCE mysqld1,mysqld2,mysqld3;
diff --git a/mysql-test/r/im_options.result b/mysql-test/r/im_options.result
new file mode 100644
index 00000000000..8039333b7d9
--- /dev/null
+++ b/mysql-test/r/im_options.result
@@ -0,0 +1,150 @@
+--------------------------------------------------------------------
+server_id = 1
+server_id = 2
+--------------------------------------------------------------------
+SHOW VARIABLES LIKE 'server_id';
+Variable_name Value
+server_id 1
+SHOW INSTANCES;
+instance_name state
+mysqld1 starting
+mysqld2 offline
+UNSET mysqld1.server_id;
+ERROR HY000: The instance is active. Stop the instance first
+SET mysqld1.server_id = 11;
+ERROR HY000: The instance is active. Stop the instance first
+CREATE INSTANCE mysqld3 datadir = '/';
+START INSTANCE mysqld3;
+UNSET mysqld3.server_id;
+ERROR HY000: The instance is active. Stop the instance first
+SET mysqld3.server_id = 11;
+ERROR HY000: The instance is active. Stop the instance first
+STOP INSTANCE mysqld3;
+SHOW INSTANCE STATUS mysqld3;
+instance_name state version_number version mysqld_compatible
+mysqld3 offline VERSION_NUMBER VERSION no
+UNSET mysqld2.server_id;
+UNSET mysqld2.server_id;
+SHOW INSTANCE OPTIONS mysqld2;
+option_name value
+instance_name option_value
+socket option_value
+pid-file option_value
+port option_value
+datadir option_value
+log option_value
+log-error option_value
+log-slow-queries option_value
+language option_value
+character-sets-dir option_value
+basedir option_value
+skip-stack-trace option_value
+skip-innodb option_value
+skip-bdb option_value
+skip-ndbcluster option_value
+nonguarded option_value
+log-output option_value
+SET mysqld2.server_id = 2;
+SET mysqld2.server_id = 2;
+SHOW INSTANCE OPTIONS mysqld2;
+option_name value
+instance_name option_value
+socket option_value
+pid-file option_value
+port option_value
+datadir option_value
+log option_value
+log-error option_value
+log-slow-queries option_value
+language option_value
+character-sets-dir option_value
+basedir option_value
+skip-stack-trace option_value
+skip-innodb option_value
+skip-bdb option_value
+skip-ndbcluster option_value
+nonguarded option_value
+log-output option_value
+server_id option_value
+UNSET mysqld2.server_id = 11;
+ERROR 42000: 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
+SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
+--------------------------------------------------------------------
+aaa
+--------------------------------------------------------------------
+bbb
+--------------------------------------------------------------------
+ccc=0010
+--------------------------------------------------------------------
+ddd=0020
+--------------------------------------------------------------------
+UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
+ERROR HY000: Bad instance name. Check that the instance with such a name exists
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
+ERROR HY000: The instance is active. Stop the instance first
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
+ERROR HY000: Bad instance name. Check that the instance with such a name exists
+--------------------------------------------------------------------
+server_id = 1
+server_id=2
+--------------------------------------------------------------------
+UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
+ERROR HY000: The instance is active. Stop the instance first
+--------------------------------------------------------------------
+server_id = 1
+server_id=2
+--------------------------------------------------------------------
+DROP INSTANCE mysqld3;
+SET mysqld2.server_id=222;
+SET mysqld2.server_id = 222;
+SET mysqld2.server_id = 222 ;
+SET mysqld2 . server_id = 222 ;
+SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
+--------------------------------------------------------------------
+server_id = 1
+server_id=222
+--------------------------------------------------------------------
+aaa
+--------------------------------------------------------------------
+bbb
+--------------------------------------------------------------------
+UNSET mysqld2 . aaa , mysqld2 . bbb ;
+--------------------------------------------------------------------
+server_id = 1
+server_id=222
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+server_id = 1
+server_id=222
+--------------------------------------------------------------------
+SHOW VARIABLES LIKE 'server_id';
+Variable_name Value
+server_id 1
+SHOW INSTANCES;
+instance_name state
+mysqld1 online
+mysqld2 offline
+FLUSH INSTANCES;
+ERROR HY000: At least one instance is active. Stop all instances first
+STOP INSTANCE mysqld1;
+SHOW INSTANCES;
+instance_name state
+mysqld1 offline
+mysqld2 offline
+FLUSH INSTANCES;
diff --git a/mysql-test/r/im_options_set.result b/mysql-test/r/im_options_set.result
deleted file mode 100644
index 0d2fa699fc7..00000000000
--- a/mysql-test/r/im_options_set.result
+++ /dev/null
@@ -1,20 +0,0 @@
-server_id =1
-server_id =2
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SET mysqld1.server_id = 11;
-server_id =11
-server_id =2
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SET mysqld2.server_id = 12;
-server_id =11
-server_id =12
-FLUSH INSTANCES;
-server_id =11
-server_id =12
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
diff --git a/mysql-test/r/im_options_unset.result b/mysql-test/r/im_options_unset.result
deleted file mode 100644
index 834152c35d2..00000000000
--- a/mysql-test/r/im_options_unset.result
+++ /dev/null
@@ -1,15 +0,0 @@
-server_id =1
-server_id =2
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-UNSET mysqld1.server_id;
-server_id =2
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-UNSET mysqld2.server_id;
-FLUSH INSTANCES;
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result
index 504b2efe4af..ae8e03bf8ea 100644
--- a/mysql-test/r/im_utils.result
+++ b/mysql-test/r/im_utils.result
@@ -1,11 +1,10 @@
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
SHOW INSTANCE OPTIONS mysqld1;
option_name value
instance_name VALUE
-mysqld-path VALUE
socket VALUE
pid-file VALUE
port VALUE
@@ -25,8 +24,6 @@ log-output VALUE
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name VALUE
-mysqld-path VALUE
-nonguarded VALUE
socket VALUE
pid-file VALUE
port VALUE
@@ -42,6 +39,7 @@ skip-stack-trace VALUE
skip-innodb VALUE
skip-bdb VALUE
skip-ndbcluster VALUE
+nonguarded VALUE
log-output VALUE
START INSTANCE mysqld2;
STOP INSTANCE mysqld2;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 5e915b5742c..603b7815d5b 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -50,6 +50,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
+REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
@@ -745,7 +746,7 @@ 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(*)
-112
+113
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
@@ -759,6 +760,7 @@ information_schema PARTITIONS PARTITION_EXPRESSION
information_schema PARTITIONS SUBPARTITION_EXPRESSION
information_schema PARTITIONS PARTITION_DESCRIPTION
information_schema PLUGINS PLUGIN_DESCRIPTION
+information_schema PROCESSLIST INFO
information_schema ROUTINES ROUTINE_DEFINITION
information_schema ROUTINES SQL_MODE
information_schema TRIGGERS ACTION_CONDITION
@@ -832,6 +834,7 @@ COLUMN_PRIVILEGES TABLE_NAME select
FILES TABLE_NAME select
KEY_COLUMN_USAGE TABLE_NAME select
PARTITIONS TABLE_NAME select
+REFERENTIAL_CONSTRAINTS TABLE_NAME select
STATISTICS TABLE_NAME select
TABLES TABLE_NAME select
TABLE_CONSTRAINTS TABLE_NAME select
@@ -843,7 +846,7 @@ flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
cluster 1
-information_schema 22
+information_schema 23
mysql 21
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
@@ -1126,11 +1129,6 @@ DROP TABLE t1;
DROP VIEW v1;
DROP FUNCTION func1;
DROP FUNCTION func2;
-create database mysqltest;
-create table mysqltest.t1(a int);
-select table_schema from information_schema.tables where table_schema='mysqltest';
-table_schema
-drop database mysqltest;
select column_type, group_concat(table_schema, '.', table_name), count(*) as num
from information_schema.columns where
table_schema='information_schema' and
@@ -1139,6 +1137,23 @@ group by column_type order by num;
column_type group_concat(table_schema, '.', table_name) num
varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2
varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS 6
+create table t1(f1 char(1) not null, f2 char(9) not null)
+default character set utf8;
+select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from
+information_schema.columns where table_schema='test' and table_name = 't1';
+CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH
+1 3
+9 27
+drop table t1;
+use mysql;
+INSERT INTO `proc` VALUES ('test','','PROCEDURE','','SQL','CONTAINS_SQL',
+'NO','DEFINER','','','BEGIN\r\n \r\nEND','root@%','2006-03-02 18:40:03',
+'2006-03-02 18:40:03','','');
+select routine_name from information_schema.routines;
+routine_name
+
+delete from proc where name='';
+use test;
select * from information_schema.engines WHERE ENGINE="MyISAM";
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO
@@ -1147,3 +1162,16 @@ select user,db from information_schema.processlist;
user db
user3148 test
drop user user3148@localhost;
+grant select on test.* to mysqltest_1@localhost;
+create table t1 (id int);
+create view v1 as select * from t1;
+create definer = mysqltest_1@localhost
+sql security definer view v2 as select 1;
+select * from information_schema.views
+where table_name='v1' or table_name='v2';
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE
+NULL test v1 NONE YES root@localhost DEFINER
+NULL test v2 select 1 AS `1` NONE NO mysqltest_1@localhost DEFINER
+drop view v1, v2;
+drop table t1;
+drop user mysqltest_1@localhost;
diff --git a/mysql-test/r/information_schema_chmod.result b/mysql-test/r/information_schema_chmod.result
new file mode 100644
index 00000000000..36124559439
--- /dev/null
+++ b/mysql-test/r/information_schema_chmod.result
@@ -0,0 +1,5 @@
+create database mysqltest;
+create table mysqltest.t1(a int);
+select table_schema from information_schema.tables where table_schema='mysqltest';
+table_schema
+drop database mysqltest;
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index 584e1701a14..37537e257da 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -13,6 +13,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
+REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result
index fb6584673f6..9bb3185c6fb 100644
--- a/mysql-test/r/information_schema_inno.result
+++ b/mysql-test/r/information_schema_inno.result
@@ -25,3 +25,34 @@ 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;
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT NOT NULL,
+PRIMARY KEY(a1, a2)) ENGINE=INNODB;
+CREATE TABLE t2(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A1
+FOREIGN KEY (b1, b2) REFERENCES t1(a1, a2)
+ON UPDATE CASCADE ON DELETE NO ACTION) ENGINE=INNODB;
+CREATE TABLE t3(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A2
+FOREIGN KEY (b1, b2) REFERENCES t2(b1, b2)
+ON UPDATE SET NULL ON DELETE RESTRICT) ENGINE=INNODB;
+CREATE TABLE t4(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A3
+FOREIGN KEY (b1, b2) REFERENCES t3(b1, b2)
+ON UPDATE NO ACTION ON DELETE SET NULL) ENGINE=INNODB;
+CREATE TABLE t5(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A4
+FOREIGN KEY (b1, b2) REFERENCES t4(b1, b2)
+ON UPDATE RESTRICT ON DELETE CASCADE) ENGINE=INNODB;
+select a.CONSTRAINT_SCHEMA, b.TABLE_NAME, CONSTRAINT_TYPE,
+b.CONSTRAINT_NAME, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME,
+MATCH_OPTION, UPDATE_RULE, DELETE_RULE
+from information_schema.TABLE_CONSTRAINTS a,
+information_schema.REFERENTIAL_CONSTRAINTS b
+where a.CONSTRAINT_SCHEMA = 'test' and a.CONSTRAINT_SCHEMA = b.CONSTRAINT_SCHEMA and
+a.CONSTRAINT_NAME = b.CONSTRAINT_NAME;
+CONSTRAINT_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_NAME UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE
+test t2 FOREIGN KEY A1 test t1 NONE CASCADE NO ACTION
+test t3 FOREIGN KEY A2 test t2 NONE SET NULL RESTRICT
+test t4 FOREIGN KEY A3 test t3 NONE NO ACTION SET NULL
+test t5 FOREIGN KEY A4 test t4 NONE RESTRICT CASCADE
+drop tables t5, t4, t3, t2, t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index a003ed14c77..7ae87e42b8c 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1306,13 +1306,13 @@ insert into t1 (a) select b from t2;
select count(*) from t1;
count(*)
29267
-explain select * from t1 where c between 1 and 10000;
+explain select * from t1 where c between 1 and 2500;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL # Using where
update t1 set c=a;
-explain select * from t1 where c between 1 and 10000;
+explain select * from t1 where c between 1 and 2500;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL c NULL NULL NULL # Using where
+1 SIMPLE t1 range c c 5 NULL # Using where
drop table t1,t2;
create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) engine=innodb;
insert into t1 (id) values (null),(null),(null),(null),(null);
@@ -3233,15 +3233,6 @@ drop trigger t2t;
drop trigger t3t;
drop trigger t4t;
drop table t1, t2, t3, t4, t5;
-create table t1(a date) engine=innodb;
-create table t2(a date, key(a)) engine=innodb;
-insert into t1 values('2005-10-01');
-insert into t2 values('2005-10-01');
-select * from t1, t2
-where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
-a a
-2005-10-01 2005-10-01
-drop table t1, t2;
CREATE TABLE t1 (
field1 varchar(8) NOT NULL DEFAULT '',
field2 varchar(8) NOT NULL DEFAULT '',
@@ -3291,3 +3282,185 @@ t1 CREATE TABLE `t1` (
UNIQUE KEY `c2` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1, t2;
+create table t1(a date) engine=innodb;
+create table t2(a date, key(a)) engine=innodb;
+insert into t1 values('2005-10-01');
+insert into t2 values('2005-10-01');
+select * from t1, t2
+where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
+a a
+2005-10-01 2005-10-01
+drop table t1, t2;
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+commit;
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
+where mm.id is null lock in share mode;
+id f_id f
+drop table t1,t2;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
+commit;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+update t1 set b = 5 where b = 1;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+select * from t1 where a = 7 and b = 3 for update;
+a b
+7 3
+commit;
+commit;
+drop table t1;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
+commit;
+set autocommit = 0;
+select * from t1 lock in share mode;
+a b
+1 1
+2 2
+3 1
+4 2
+5 1
+6 2
+update t1 set b = 5 where b = 1;
+set autocommit = 0;
+select * from t1 where a = 2 and b = 2 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+commit;
+commit;
+drop table t1;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(d int not null, e int, primary key(d)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+d e
+3 1
+8 6
+12 1
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+insert into t1 select * from t2;
+update t1 set b = (select e from t2 where a = d);
+create table t3(d int not null, e int, primary key(d)) engine=innodb
+select * from t2;
+commit;
+commit;
+drop table t1, t2, t3;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(a int not null, b int, primary key(a)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+create table t3(d int not null, b int, primary key(d)) engine=innodb;
+insert into t3 values (8,6),(12,1),(3,1);
+create table t5(a int not null, b int, primary key(a)) engine=innodb;
+insert into t5 values (1,2),(5,3),(4,2);
+create table t6(d int not null, e int, primary key(d)) engine=innodb;
+insert into t6 values (8,6),(12,1),(3,1);
+create table t8(a int not null, b int, primary key(a)) engine=innodb;
+insert into t8 values (1,2),(5,3),(4,2);
+create table t9(d int not null, e int, primary key(d)) engine=innodb;
+insert into t9 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+a b
+3 1
+8 6
+12 1
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+insert into t1 select * from t2;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+update t3 set b = (select b from t2 where a = d);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+insert into t5 (select * from t2 lock in share mode);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+update t6 set e = (select b from t2 where a = d lock in share mode);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+insert into t8 (select * from t2 for update);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+update t9 set e = (select b from t2 where a = d for update);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+commit;
+drop table t1, t2, t3, t5, t6, t8, t9;
+CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
+ERROR HY000: Can't create table 'test.t1' (errno: -1)
+CREATE TABLE t1 (
+a BIGINT(20) NOT NULL,
+PRIMARY KEY (a)
+) ENGINE=INNODB DEFAULT CHARSET=UTF8;
+CREATE TABLE t2 (
+a BIGINT(20) NOT NULL,
+b VARCHAR(128) NOT NULL,
+c TEXT NOT NULL,
+PRIMARY KEY (a,b),
+KEY idx_t2_b_c (b,c(200)),
+CONSTRAINT t_fk FOREIGN KEY (a) REFERENCES t1 (a)
+ON DELETE CASCADE
+) ENGINE=INNODB DEFAULT CHARSET=UTF8;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1, 'bar', 'vbar');
+INSERT INTO t2 VALUES (1, 'BAR2', 'VBAR');
+INSERT INTO t2 VALUES (1, 'bar_bar', 'bibi');
+INSERT INTO t2 VALUES (1, 'customer_over', '1');
+SELECT * FROM t2 WHERE b = 'customer_over';
+a b c
+1 customer_over 1
+SELECT * FROM t2 WHERE BINARY b = 'customer_over';
+a b c
+1 customer_over 1
+SELECT DISTINCT p0.a FROM t2 p0 WHERE p0.b = 'customer_over';
+a
+1
+/* Bang: Empty result set, above was expected: */
+SELECT DISTINCT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
+a
+1
+SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
+a
+1
+drop table t2, t1;
+create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
+ERROR HY000: The used table type doesn't support SPATIAL indexes
+CREATE TABLE t1 ( a int ) ENGINE=innodb;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+DROP TABLE t1;
diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
new file mode 100644
index 00000000000..bbd9550196f
--- /dev/null
+++ b/mysql-test/r/innodb_mysql.result
@@ -0,0 +1,194 @@
+drop table if exists t1,t2;
+create table t1 (
+c_id int(11) not null default '0',
+org_id int(11) default null,
+unique key contacts$c_id (c_id),
+key contacts$org_id (org_id)
+) engine=innodb;
+insert into t1 values
+(2,null),(120,null),(141,null),(218,7), (128,1),
+(151,2),(234,2),(236,2),(243,2),(255,2),(259,2),(232,3),(235,3),(238,3),
+(246,3),(253,3),(269,3),(285,3),(291,3),(293,3),(131,4),(230,4),(231,4);
+create table t2 (
+slai_id int(11) not null default '0',
+owner_tbl int(11) default null,
+owner_id int(11) default null,
+sla_id int(11) default null,
+inc_web int(11) default null,
+inc_email int(11) default null,
+inc_chat int(11) default null,
+inc_csr int(11) default null,
+inc_total int(11) default null,
+time_billed int(11) default null,
+activedate timestamp null default null,
+expiredate timestamp null default null,
+state int(11) default null,
+sla_set int(11) default null,
+unique key t2$slai_id (slai_id),
+key t2$owner_id (owner_id),
+key t2$sla_id (sla_id)
+) engine=innodb;
+insert into t2(slai_id, owner_tbl, owner_id, sla_id) values
+(1,3,1,1), (3,3,10,2), (4,3,3,6), (5,3,2,5), (6,3,8,3), (7,3,9,7),
+(8,3,6,8), (9,3,4,9), (10,3,5,10), (11,3,11,11), (12,3,7,12);
+flush tables;
+select si.slai_id
+from t1 c join t2 si on
+((si.owner_tbl = 3 and si.owner_id = c.org_id) or
+( si.owner_tbl = 2 and si.owner_id = c.c_id))
+where
+c.c_id = 218 and expiredate is null;
+slai_id
+12
+select * from t1 where org_id is null;
+c_id org_id
+2 NULL
+120 NULL
+141 NULL
+select si.slai_id
+from t1 c join t2 si on
+((si.owner_tbl = 3 and si.owner_id = c.org_id) or
+( si.owner_tbl = 2 and si.owner_id = c.c_id))
+where
+c.c_id = 218 and expiredate is null;
+slai_id
+12
+drop table t1, t2;
+create table t1m (a int) engine=myisam;
+create table t1i (a int) engine=innodb;
+create table t2m (a int) engine=myisam;
+create table t2i (a int) engine=innodb;
+insert into t2m values (5);
+insert into t2i values (5);
+select min(a) from t1m;
+min(a)
+NULL
+select min(7) from t1m;
+min(7)
+NULL
+select min(7) from DUAL;
+min(7)
+NULL
+explain select min(7) from t2m join t1m;
+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
+select min(7) from t2m join t1m;
+min(7)
+NULL
+select max(a) from t1m;
+max(a)
+NULL
+select max(7) from t1m;
+max(7)
+NULL
+select max(7) from DUAL;
+max(7)
+NULL
+explain select max(7) from t2m join t1m;
+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
+select max(7) from t2m join t1m;
+max(7)
+NULL
+select 1, min(a) from t1m where a=99;
+1 min(a)
+1 NULL
+select 1, min(a) from t1m where 1=99;
+1 min(a)
+1 NULL
+select 1, min(1) from t1m where a=99;
+1 min(1)
+1 NULL
+select 1, min(1) from t1m where 1=99;
+1 min(1)
+1 NULL
+select 1, max(a) from t1m where a=99;
+1 max(a)
+1 NULL
+select 1, max(a) from t1m where 1=99;
+1 max(a)
+1 NULL
+select 1, max(1) from t1m where a=99;
+1 max(1)
+1 NULL
+select 1, max(1) from t1m where 1=99;
+1 max(1)
+1 NULL
+select min(a) from t1i;
+min(a)
+NULL
+select min(7) from t1i;
+min(7)
+NULL
+select min(7) from DUAL;
+min(7)
+NULL
+explain select min(7) from t2i join t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select min(7) from t2i join t1i;
+min(7)
+NULL
+select max(a) from t1i;
+max(a)
+NULL
+select max(7) from t1i;
+max(7)
+NULL
+select max(7) from DUAL;
+max(7)
+NULL
+explain select max(7) from t2i join t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select max(7) from t2i join t1i;
+max(7)
+NULL
+select 1, min(a) from t1i where a=99;
+1 min(a)
+1 NULL
+select 1, min(a) from t1i where 1=99;
+1 min(a)
+1 NULL
+select 1, min(1) from t1i where a=99;
+1 min(1)
+1 NULL
+select 1, min(1) from t1i where 1=99;
+1 min(1)
+1 NULL
+select 1, max(a) from t1i where a=99;
+1 max(a)
+1 NULL
+select 1, max(a) from t1i where 1=99;
+1 max(a)
+1 NULL
+select 1, max(1) from t1i where a=99;
+1 max(1)
+1 NULL
+select 1, max(1) from t1i where 1=99;
+1 max(1)
+1 NULL
+explain select count(*), min(7), max(7) from t1m, t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t1m, t1i;
+count(*) min(7) max(7)
+0 NULL NULL
+explain select count(*), min(7), max(7) from t1m, t2i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t1m, t2i;
+count(*) min(7) max(7)
+0 NULL NULL
+explain select count(*), min(7), max(7) from t2m, t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2m system NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t2m, t1i;
+count(*) min(7) max(7)
+0 NULL NULL
+drop table t1m, t1i, t2m, t2i;
diff --git a/mysql-test/r/innodb_unsafe_binlog.result b/mysql-test/r/innodb_unsafe_binlog.result
index e741fbb75a4..38f0c2a12fa 100644
--- a/mysql-test/r/innodb_unsafe_binlog.result
+++ b/mysql-test/r/innodb_unsafe_binlog.result
@@ -15,7 +15,7 @@ where mm.id is null lock in share mode;
id f_id f
drop table t1,t2;
create table t1(a int not null, b int, primary key(a)) engine=innodb;
-insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
commit;
set autocommit = 0;
select * from t1 lock in share mode;
@@ -26,6 +26,7 @@ a b
4 2
5 1
6 2
+7 3
update t1 set b = 5 where b = 1;
set autocommit = 0;
select * from t1 where a = 2 and b = 2 for update;
@@ -33,3 +34,87 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
commit;
drop table t1;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
+commit;
+set autocommit = 0;
+update t1 set b = 5 where b = 1;
+set autocommit = 0;
+select * from t1 where a = 7 and b = 3 for update;
+a b
+7 3
+commit;
+commit;
+drop table t1;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(d int not null, e int, primary key(d)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+d e
+3 1
+8 6
+12 1
+set autocommit = 0;
+insert into t1 select * from t2;
+update t1 set b = (select e from t2 where a = d);
+create table t3(d int not null, e int, primary key(d)) engine=innodb
+select * from t2;
+commit;
+commit;
+drop table t1, t2, t3;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(a int not null, b int, primary key(a)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+create table t3(d int not null, b int, primary key(d)) engine=innodb;
+insert into t3 values (8,6),(12,1),(3,1);
+create table t5(a int not null, b int, primary key(a)) engine=innodb;
+insert into t5 values (1,2),(5,3),(4,2);
+create table t6(d int not null, e int, primary key(d)) engine=innodb;
+insert into t6 values (8,6),(12,1),(3,1);
+create table t8(a int not null, b int, primary key(a)) engine=innodb;
+insert into t8 values (1,2),(5,3),(4,2);
+create table t9(d int not null, e int, primary key(d)) engine=innodb;
+insert into t9 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+a b
+3 1
+8 6
+12 1
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+insert into t1 select * from t2;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+update t3 set b = (select b from t2 where a = d);
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
+set autocommit = 0;
+insert into t5 (select * from t2 lock in share mode);
+set autocommit = 0;
+update t6 set e = (select b from t2 where a = d lock in share mode);
+set autocommit = 0;
+create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
+set autocommit = 0;
+insert into t8 (select * from t2 for update);
+set autocommit = 0;
+update t9 set e = (select b from t2 where a = d for update);
+set autocommit = 0;
+create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+commit;
+drop table t1, t2, t3, t5, t6, t8, t9;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index ecf76d477a0..86288caf398 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -700,8 +700,8 @@ ERROR 42S22: Unknown column 't1.b' in 'on clause'
select * from information_schema.statistics join information_schema.columns
using(table_name,column_name) where table_name='user';
TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA 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
-user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql 1 NO char 20 60 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references
-user User NULL mysql 0 mysql PRIMARY 2 A 5 NULL NULL BTREE NULL mysql 2 NO char 5 16 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references
+user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references
+user User NULL mysql 0 mysql PRIMARY 2 A 5 NULL NULL BTREE NULL mysql 2 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references
drop table t1;
drop table t2;
drop table t3;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 8a30f3c18ec..f4ec997e50c 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1151,6 +1151,63 @@ EXPLAIN
SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%' OR FALSE;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index
-1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index
+1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where
+DROP TABLE t1,t2;
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (a int);
+CREATE table t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3);
+INSERT INTO t2 VALUES (2), (3);
+CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b;
+CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a;
+SELECT v1.a, v2. b
+FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3)
+GROUP BY v1.a;
+a b
+2 NULL
+3 3
+SELECT v1.a, v2. b
+FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) }
+GROUP BY v1.a;
+a b
+2 NULL
+3 3
+DROP VIEW v1,v2;
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (2), (3);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1);
+a b
+1 NULL
+2 2
+3 3
+4 NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1 OR 1);
+a b
+1 NULL
+2 2
+3 3
+4 NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (0 OR 1);
+a b
+1 NULL
+2 2
+3 3
+4 NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 2=2);
+a b
+1 NULL
+2 2
+3 3
+4 NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 1=0);
+a b
+1 NULL
+2 2
+3 3
+4 NULL
DROP TABLE t1,t2;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index de9a2b2c003..99f5277f817 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -289,6 +289,48 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1);
+SELECT @@key_cache_block_size;
+@@key_cache_block_size
+1536
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1;
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1,0);
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4181
+SELECT @@key_cache_block_size;
+@@key_cache_block_size
+1536
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1,t2;
set @@global.key_buffer_size=0;
Warnings:
Warning 1438 Cannot drop default keycache
diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result
index 2164c18823f..c61dd2247ee 100644
--- a/mysql-test/r/log_tables.result
+++ b/mysql-test/r/log_tables.result
@@ -2,14 +2,14 @@ use mysql;
truncate table general_log;
select * from general_log;
event_time user_host thread_id server_id command_type argument
-TIMESTAMP root[root] @ localhost [] 1 1 Query select * from general_log
+TIMESTAMP USER_HOST THREAD_ID 1 Query select * from general_log
truncate table slow_log;
select * from slow_log;
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
truncate table general_log;
select * from general_log where argument like '%general_log%';
event_time user_host thread_id server_id command_type argument
-TIMESTAMP root[root] @ localhost [] 1 1 Query select * from general_log where argument like '%general_log%'
+TIMESTAMP USER_HOST THREAD_ID 1 Query select * from general_log where argument like '%general_log%'
create table join_test (verbose_comment varchar (80), command_type varchar(64));
insert into join_test values ("User performed a usual SQL query", "Query");
insert into join_test values ("New DB connection was registered", "Connect");
@@ -18,12 +18,12 @@ select verbose_comment, user_host, argument
from mysql.general_log join join_test
on (mysql.general_log.command_type = join_test.command_type);
verbose_comment user_host argument
-User performed a usual SQL query root[root] @ localhost [] select * from general_log where argument like '%general_log%'
-User performed a usual SQL query root[root] @ localhost [] create table join_test (verbose_comment varchar (80), command_type varchar(64))
-User performed a usual SQL query root[root] @ localhost [] insert into join_test values ("User performed a usual SQL query", "Query")
-User performed a usual SQL query root[root] @ localhost [] insert into join_test values ("New DB connection was registered", "Connect")
-User performed a usual SQL query root[root] @ localhost [] insert into join_test values ("Get the table info", "Field List")
-User performed a usual SQL query root[root] @ localhost [] select verbose_comment, user_host, argument
+User performed a usual SQL query USER_HOST select * from general_log where argument like '%general_log%'
+User performed a usual SQL query USER_HOST create table join_test (verbose_comment varchar (80), command_type varchar(64))
+User performed a usual SQL query USER_HOST insert into join_test values ("User performed a usual SQL query", "Query")
+User performed a usual SQL query USER_HOST insert into join_test values ("New DB connection was registered", "Connect")
+User performed a usual SQL query USER_HOST insert into join_test values ("Get the table info", "Field List")
+User performed a usual SQL query USER_HOST select verbose_comment, user_host, argument
from mysql.general_log join join_test
on (mysql.general_log.command_type = join_test.command_type)
drop table join_test;
@@ -59,10 +59,10 @@ create table bug16905 (s char(15) character set utf8 default 'пуÑто');
insert into bug16905 values ('новое');
select * from mysql.general_log;
event_time user_host thread_id server_id command_type argument
-TIMESTAMP root[root] @ localhost [] 2 1 Query set names utf8
-TIMESTAMP root[root] @ localhost [] 2 1 Query create table bug16905 (s char(15) character set utf8 default 'пуÑто')
-TIMESTAMP root[root] @ localhost [] 2 1 Query insert into bug16905 values ('новое')
-TIMESTAMP root[root] @ localhost [] 2 1 Query select * from mysql.general_log
+TIMESTAMP USER_HOST THREAD_ID 1 Query set names utf8
+TIMESTAMP USER_HOST THREAD_ID 1 Query create table bug16905 (s char(15) character set utf8 default 'пуÑто')
+TIMESTAMP USER_HOST THREAD_ID 1 Query insert into bug16905 values ('новое')
+TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log
drop table bug16905;
truncate table mysql.slow_log;
set session long_query_time=1;
@@ -71,4 +71,4 @@ sleep(2)
0
select * from mysql.slow_log;
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
-TIMESTAMP, root[root] @ localhost [] USER_HOST, QUERY_TIME 1 0 test 0 0 1 select sleep(2)
+TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2)
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 538f1fa1a20..2f5f382028a 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -771,3 +771,11 @@ Table Op Msg_type Msg_text
test.t1 check status OK
test.t2 check status OK
drop table t1, t2, t3;
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+create table t1 (c char(20)) engine=MyISAM;
+insert into t1 values ("Monty"),("WAX"),("Walrus");
+alter table t1 engine=MERGE;
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+drop table t1;
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 0a170e16188..50b0b6ae294 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -2,7 +2,7 @@ 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 246 3 3 N 161 1 63
+def 1.0 246 4 3 N 129 1 63
def -1 8 2 2 N 32897 0 63
def hello 253 5 5 N 1 31 8
def NULL 6 0 0 Y 32896 0 63
diff --git a/mysql-test/r/myisam-system.result b/mysql-test/r/myisam-system.result
new file mode 100644
index 00000000000..e0629d955ae
--- /dev/null
+++ b/mysql-test/r/myisam-system.result
@@ -0,0 +1,13 @@
+drop table if exists t1,t2;
+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'
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 60836408698..3226351f966 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -1344,18 +1344,6 @@ 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);
@@ -1433,3 +1421,149 @@ 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;
+create table t1 (a int not null, key `a` (a) key_block_size=1024);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=2048);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=2048
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`),
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024
+alter table t1 key_block_size=2048;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
+alter table t1 add c int, add key (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096,
+ KEY `c` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
+alter table t1 key_block_size=0;
+alter table t1 add d int, add key (d);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096,
+ KEY `c` (`c`) KEY_BLOCK_SIZE=2048,
+ KEY `d` (`d`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`),
+ KEY `b` (`b`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
+drop table t1;
+create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`) KEY_BLOCK_SIZE=8192
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=16384
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=512);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=1025);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=2048
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key key_block_size=1024 (a));
+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 '=1024 (a))' at line 1
+create table t1 (a int not null, key `a` key_block_size=1024 (a));
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_block_size=1024 (a))' at line 1
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index ae50c714bba..4b7084e813c 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -74,7 +74,7 @@ c_cp932
+----------------------+------------+--------+
| >a < | b | 123421 |
| >a < | 0123456789 | 4 |
-| >abcd< | NULL | 4 |
+| >abcd< | | 4 |
+----------------------+------------+--------+
+------+------+---------------------------+
| i | j | k |
@@ -85,3 +85,23 @@ c_cp932
| NULL | NULL | Τη γλώσσα |
| NULL | NULL | á›–áš´ áš·á›–á› |
+------+------+---------------------------+
++------+---+------+
+| i | j | k |
++------+---+------+
+| NULL | 1 | NULL |
++------+---+------+
++-------+---------+------+-----+---------+-------+
+| Field | Type | Null | Key | Default | Extra |
++-------+---------+------+-----+---------+-------+
+| i | int(11) | YES | | NULL | |
+| j | int(11) | NO | | | |
+| k | int(11) | YES | | NULL | |
++-------+---------+------+-----+---------+-------+
++------+------+
+| i | s1 |
++------+------+
+| 1 | x |
+| 2 | NULL |
+| 3 | |
++------+------+
+End of 5.0 tests
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index 50e4cc28d93..664833fab2a 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -189,4 +189,5 @@ HEX(f)
select HEX(f) from t4;
HEX(f)
835C
+flush logs;
drop table t1, t2, t03, t04, t3, t4;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index c35e1c09c5c..493e79d4136 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -3,13 +3,14 @@ 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);
+CREATE TABLE t1(a int, key (a)) key_block_size=1024;
INSERT INTO t1 VALUES (1), (2);
<?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="t1">
- <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ <field Field="a" Type="int(11)" Null="YES" Key="MUL" Extra="" />
+ <key Table="t1" Non_unique="1" Key_name="a" Seq_in_index="1" Column_name="a" Collation="A" Null="YES" Index_type="BTREE" Comment="" />
</table_structure>
<table_data name="t1">
<row>
@@ -1700,6 +1701,44 @@ select * from t1;
a b
Osnabrück Köln
drop table t1;
+create table `t1` (
+t1_name varchar(255) default null,
+t1_id int(10) unsigned not null auto_increment,
+key (t1_name),
+primary key (t1_id)
+) auto_increment = 1000 default charset=latin1;
+insert into t1 (t1_name) values('bla');
+insert into t1 (t1_name) values('bla');
+insert into t1 (t1_name) values('bla');
+select * from t1;
+t1_name t1_id
+bla 1000
+bla 1001
+bla 1002
+show create table `t1`;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `t1_name` varchar(255) DEFAULT NULL,
+ `t1_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`t1_id`),
+ KEY `t1_name` (`t1_name`)
+) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1
+DROP TABLE `t1`;
+select * from t1;
+t1_name t1_id
+bla 1000
+bla 1001
+bla 1002
+show create table `t1`;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `t1_name` varchar(255) DEFAULT NULL,
+ `t1_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`t1_id`),
+ KEY `t1_name` (`t1_name`)
+) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1
+drop table `t1`;
+End of 4.1 tests
create table t1 (a binary(1), b blob);
insert into t1 values ('','');
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
index a0220a0bad8..e506973f347 100644
--- a/mysql-test/r/ndb_alter_table.result
+++ b/mysql-test/r/ndb_alter_table.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
drop database if exists mysqltest;
CREATE TABLE t1 (
a INT NOT NULL,
@@ -286,3 +286,66 @@ unique key tx1 (c002, c003, c004, c005)) engine=ndb;
create index tx2
on t1 (c010, c011, c012, c013);
drop table t1;
+CREATE TABLE t1 (
+auto int(5) unsigned NOT NULL auto_increment,
+string char(10),
+vstring varchar(10),
+bin binary(2),
+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;
+CREATE TEMPORARY TABLE ndb_show_tables (id INT, type VARCHAR(20), state VARCHAR(20), logging VARCHAR(20), _database VARCHAR(255), _schema VARCHAR(20), name VARCHAR(255));
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+set @t1_id = (select id from ndb_show_tables where name like '%t1%');
+truncate ndb_show_tables;
+alter table t1 change tiny new_tiny tinyint(4) DEFAULT '0' NOT NULL;
+create index i1 on t1(medium);
+alter table t1 add index i2(long_int);
+drop index i1 on t1;
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%';
+no_copy
+no_copy
+DROP TABLE t1, ndb_show_tables;
+create table t1 (a int primary key auto_increment, b int) engine=ndb;
+insert into t1 (b) values (101),(102),(103);
+select * from t1 where a = 3;
+a b
+3 103
+alter table t1 rename t2;
+insert into t2 (b) values (201),(202),(203);
+select * from t2 where a = 6;
+a b
+6 203
+alter table t2 add c int;
+insert into t2 (b) values (301),(302),(303);
+select * from t2 where a = 9;
+a b c
+9 303 NULL
+alter table t2 rename t1;
+insert into t1 (b) values (401),(402),(403);
+select * from t1 where a = 12;
+a b c
+12 403 NULL
+drop table t1;
diff --git a/mysql-test/r/ndb_alter_table_row.result b/mysql-test/r/ndb_alter_table3.result
index ee7c9b1c7b0..ee7c9b1c7b0 100644
--- a/mysql-test/r/ndb_alter_table_row.result
+++ b/mysql-test/r/ndb_alter_table3.result
diff --git a/mysql-test/r/ndb_alter_table_stm.result b/mysql-test/r/ndb_alter_table_stm.result
deleted file mode 100644
index 7cb7b990e2c..00000000000
--- a/mysql-test/r/ndb_alter_table_stm.result
+++ /dev/null
@@ -1,29 +0,0 @@
-DROP TABLE IF EXISTS t1;
-create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
-engine=ndb;
-insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
-create index c on t1(c);
-select * from t1 where c = 'two';
-a b c
-2 two two
-alter table t1 drop index c;
-select * from t1 where c = 'two';
-select * from t1 where c = 'two';
-a b c
-2 two two
-drop table t1;
-create table t3 (a int primary key) engine=ndbcluster;
-begin;
-insert into t3 values (1);
-alter table t3 rename t4;
-delete from t3;
-insert into t3 values (1);
-commit;
-select * from t3;
-ERROR HY000: Can't lock file (errno: 155)
-select * from t4;
-a
-1
-drop table t4;
-show tables;
-Tables_in_test
diff --git a/mysql-test/r/ndb_autodiscover3.result b/mysql-test/r/ndb_autodiscover3.result
new file mode 100644
index 00000000000..86495ebb3eb
--- /dev/null
+++ b/mysql-test/r/ndb_autodiscover3.result
@@ -0,0 +1,53 @@
+drop table if exists t1, t2;
+create table t1 (a int key) engine=ndbcluster;
+begin;
+insert into t1 values (1);
+insert into t1 values (2);
+ERROR HY000: Got temporary error 4025 'Node failure caused abort of transaction' from NDBCLUSTER
+commit;
+ERROR HY000: Got error 4350 'Transaction already aborted' from NDBCLUSTER
+drop table t1;
+create table t2 (a int, b int, primary key(a,b)) engine=ndbcluster;
+insert into t2 values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1);
+select * from t2 order by a limit 3;
+a b
+1 1
+2 1
+3 1
+select * from t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+show tables like 't2';
+Tables_in_test (t2)
+reset master;
+create table t2 (a int key) engine=ndbcluster;
+insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t2 order by a limit 3;
+a
+1
+2
+3
+select * from t2 order by a limit 3;
+a
+1
+2
+3
+reset master;
+select * from t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+show tables like 't2';
+Tables_in_test (t2)
+reset master;
+create table t2 (a int key) engine=ndbcluster;
+insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t2 order by a limit 3;
+a
+1
+2
+3
+select * from t2 order by a limit 3;
+a
+1
+2
+3
+reset master;
+drop table t2;
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index 4a1f5f587df..b8bafd398fe 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -642,30 +642,30 @@ counter datavalue
6 newval
7 newval
8 newval
-35 newval
-36 newval
-37 newval
-38 newval
-39 newval
-40 newval
-41 newval
-42 newval
-43 newval
-44 newval
-45 newval
-46 newval
-47 newval
-48 newval
-49 newval
-50 newval
-51 newval
-52 newval
-53 newval
-54 newval
-55 newval
-56 newval
-57 newval
-58 newval
+9 newval
+10 newval
+11 newval
+12 newval
+13 newval
+14 newval
+15 newval
+16 newval
+17 newval
+18 newval
+19 newval
+20 newval
+21 newval
+22 newval
+23 newval
+24 newval
+25 newval
+26 newval
+27 newval
+28 newval
+29 newval
+30 newval
+31 newval
+32 newval
drop table t1;
CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb;
select * from t1;
diff --git a/mysql-test/r/ndb_binlog_discover.result b/mysql-test/r/ndb_binlog_discover.result
new file mode 100644
index 00000000000..2a1bf6efa84
--- /dev/null
+++ b/mysql-test/r/ndb_binlog_discover.result
@@ -0,0 +1,13 @@
+drop table if exists t1;
+create table t1 (a int key) engine=ndb;
+reset master;
+insert into t1 values(1);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Table_map # # table_id: # (cluster.apply_status)
+master-bin.000001 # Write_rows # # table_id: #
+master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+drop table t1;
diff --git a/mysql-test/r/ndb_bitfield.result b/mysql-test/r/ndb_bitfield.result
index 9a8c571cfba..59c4d420b22 100644
--- a/mysql-test/r/ndb_bitfield.result
+++ b/mysql-test/r/ndb_bitfield.result
@@ -9,7 +9,7 @@ t1 CREATE TABLE `t1` (
`pk1` int(11) NOT NULL,
`b` bit(64) DEFAULT NULL,
PRIMARY KEY (`pk1`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
insert into t1 values
(0,b'1111111111111111111111111111111111111111111111111111111111111111'),
(1,b'1000000000000000000000000000000000000000000000000000000000000000'),
diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result
index 9c76d46f4f0..829c67905bf 100644
--- a/mysql-test/r/ndb_blob.result
+++ b/mysql-test/r/ndb_blob.result
@@ -481,14 +481,88 @@ msg text NOT NULL
insert into t1 (msg) values(
'Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
-so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).');
+so bad data will not crash kernel.');
select * from t1;
id msg
1 Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).
+drop table t1;
+create table t1 (
+a int primary key not null auto_increment,
+b text
+) engine=ndbcluster;
+select count(*) from t1;
+count(*)
+500
+truncate t1;
+select count(*) from t1;
+count(*)
+0
+drop table t1;
+create table t1 (
+a varchar(40) not null,
+b mediumint not null,
+t text,
+c varchar(2) not null,
+d bigint not null,
+primary key (a,b,c),
+key (c,a),
+unique key (d)
+) engine=ndb;
+insert into t1 (a,b,c,d,t) values ('a',1110,'a',1,@v1);
+insert into t1 (a,b,c,d,t) values ('b',1110,'a',2,@v2);
+insert into t1 (a,b,c,d,t) values ('a',1110,'b',3,@v3);
+insert into t1 (a,b,c,d,t) values ('b',1110,'b',4,@v4);
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='a';
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='b';
+a b c d sha1(t)
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+update t1 set t=@v4 where a='b' and b=1110 and c='a';
+update t1 set t=@v2 where a='b' and b=1110 and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 NULL
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+update t1 set t=@v2 where d=2;
+update t1 set t=@v4 where d=4;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+update t1 set t=@v4 where a='b' and c='a';
+update t1 set t=@v2 where a='b' and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 NULL
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+update t1 set t=@v2 where b+d=1112;
+update t1 set t=@v4 where b+d=1114;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+delete from t1 where a='a' and b=1110 and c='a';
+delete from t1 where a='b' and c='a';
+delete from t1 where d=3;
+delete from t1 where b+d=1114;
+select count(*) from t1;
+count(*)
+0
drop table t1;
diff --git a/mysql-test/r/ndb_blob_partition.result b/mysql-test/r/ndb_blob_partition.result
deleted file mode 100644
index b08a91f0cdd..00000000000
--- a/mysql-test/r/ndb_blob_partition.result
+++ /dev/null
@@ -1,104 +0,0 @@
-drop table if exists t1;
-create table t1 (
-a mediumint not null,
-b text not null,
-c int not null,
-d longblob,
-primary key using hash (a,c),
-unique key (c)
-)
-engine=ndb
-partition by range (c)
-partitions 3
-( partition p1 values less than (200),
-partition p2 values less than (300),
-partition p3 values less than (400));
-insert into t1 values (1, @v1, 101, @v2);
-insert into t1 values (1, @v2, 102, @v3);
-insert into t1 values (1, @v3, 103, @v4);
-insert into t1 values (2, @v4, 201, @v5);
-insert into t1 values (2, @v5, 202, @v6);
-insert into t1 values (2, @v6, 203, @v7);
-insert into t1 values (3, @v7, 301, @v8);
-insert into t1 values (3, @v8, 302, @v9);
-insert into t1 values (3, @v9, 303, @v1);
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 101 10d3c783026b310218d10b7188da96a2401648c6
-1 10d3c783026b310218d10b7188da96a2401648c6 102 a33549d9844092289a58ac348dd59f09fc28406a
-1 a33549d9844092289a58ac348dd59f09fc28406a 103 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 201 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 70fc9a7d08beebc522258bfb02000a30c77a8f1d 202 090565c580809efed3d369481a4bbb168b20713e
-2 090565c580809efed3d369481a4bbb168b20713e 203 1e0070bec426871a46291de27b9bd6e4255ab4e5
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 301 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 acbaba01bc2e682f015f40e79d9cbe475db3002e 302 9ee30d99162574f79c66ae95cdf132dcf9cbc259
-3 9ee30d99162574f79c66ae95cdf132dcf9cbc259 303 1d42dd9090cf78314a06665d4ea938c35cc760f4
-select a, sha1(b), c, sha1(d) from t1 where a = 1 and c = 101;
-a sha1(b) c sha1(d)
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 101 10d3c783026b310218d10b7188da96a2401648c6
-select a, sha1(b), c, sha1(d) from t1 where a = 2 and c = 201;
-a sha1(b) c sha1(d)
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 201 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-select a, sha1(b), c, sha1(d) from t1 where a = 3 and c = 301;
-a sha1(b) c sha1(d)
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 301 acbaba01bc2e682f015f40e79d9cbe475db3002e
-update t1 set b = @v3, d = @v4 where a = 1 and c = 102;
-update t1 set b = @v6, d = @v7 where a = 2 and c = 202;
-update t1 set b = @v9, d = @v1 where a = 3 and c = 302;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 101 10d3c783026b310218d10b7188da96a2401648c6
-1 a33549d9844092289a58ac348dd59f09fc28406a 102 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c
-1 a33549d9844092289a58ac348dd59f09fc28406a 103 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 201 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 090565c580809efed3d369481a4bbb168b20713e 202 1e0070bec426871a46291de27b9bd6e4255ab4e5
-2 090565c580809efed3d369481a4bbb168b20713e 203 1e0070bec426871a46291de27b9bd6e4255ab4e5
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 301 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 9ee30d99162574f79c66ae95cdf132dcf9cbc259 302 1d42dd9090cf78314a06665d4ea938c35cc760f4
-3 9ee30d99162574f79c66ae95cdf132dcf9cbc259 303 1d42dd9090cf78314a06665d4ea938c35cc760f4
-update t1 set b = @v4, d = @v5 where c = 103;
-update t1 set b = @v7, d = @v8 where c = 203;
-update t1 set b = @v1, d = @v2 where c = 303;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 101 10d3c783026b310218d10b7188da96a2401648c6
-1 a33549d9844092289a58ac348dd59f09fc28406a 102 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c
-1 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 103 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 201 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 090565c580809efed3d369481a4bbb168b20713e 202 1e0070bec426871a46291de27b9bd6e4255ab4e5
-2 1e0070bec426871a46291de27b9bd6e4255ab4e5 203 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 301 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 9ee30d99162574f79c66ae95cdf132dcf9cbc259 302 1d42dd9090cf78314a06665d4ea938c35cc760f4
-3 1d42dd9090cf78314a06665d4ea938c35cc760f4 303 10d3c783026b310218d10b7188da96a2401648c6
-update t1 set b = @v5, d = @v6;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-1 70fc9a7d08beebc522258bfb02000a30c77a8f1d 101 090565c580809efed3d369481a4bbb168b20713e
-1 70fc9a7d08beebc522258bfb02000a30c77a8f1d 102 090565c580809efed3d369481a4bbb168b20713e
-1 70fc9a7d08beebc522258bfb02000a30c77a8f1d 103 090565c580809efed3d369481a4bbb168b20713e
-2 70fc9a7d08beebc522258bfb02000a30c77a8f1d 201 090565c580809efed3d369481a4bbb168b20713e
-2 70fc9a7d08beebc522258bfb02000a30c77a8f1d 202 090565c580809efed3d369481a4bbb168b20713e
-2 70fc9a7d08beebc522258bfb02000a30c77a8f1d 203 090565c580809efed3d369481a4bbb168b20713e
-3 70fc9a7d08beebc522258bfb02000a30c77a8f1d 301 090565c580809efed3d369481a4bbb168b20713e
-3 70fc9a7d08beebc522258bfb02000a30c77a8f1d 302 090565c580809efed3d369481a4bbb168b20713e
-3 70fc9a7d08beebc522258bfb02000a30c77a8f1d 303 090565c580809efed3d369481a4bbb168b20713e
-update t1 set b = @v1, d = @v2 where 100 < c and c < 200;
-update t1 set b = @v4, d = @v5 where 200 < c and c < 300;
-update t1 set b = @v7, d = @v8 where 300 < c and c < 400;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 101 10d3c783026b310218d10b7188da96a2401648c6
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 102 10d3c783026b310218d10b7188da96a2401648c6
-1 1d42dd9090cf78314a06665d4ea938c35cc760f4 103 10d3c783026b310218d10b7188da96a2401648c6
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 201 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 202 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-2 daa61c6de36a0526f0d47dc29d6b9de7e6d2630c 203 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 301 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 302 acbaba01bc2e682f015f40e79d9cbe475db3002e
-3 1e0070bec426871a46291de27b9bd6e4255ab4e5 303 acbaba01bc2e682f015f40e79d9cbe475db3002e
-delete from t1 where a = 1 and c = 101;
-delete from t1 where c = 102;
-delete from t1;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-a sha1(b) c sha1(d)
-drop table t1;
diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result
index 24fe30604ae..140324a21d8 100644
--- a/mysql-test/r/ndb_condition_pushdown.result
+++ b/mysql-test/r/ndb_condition_pushdown.result
@@ -1782,5 +1782,65 @@ select * from t5 where b like '%jo%' order by a;
a b
1 jonas
3 johan
+drop table t1;
+create table t1 (a int, b varchar(3), primary key using hash(a))
+engine=ndb;
+insert into t1 values (1,'a'), (2,'ab'), (3,'abc');
+set engine_condition_pushdown = off;
+select * from t1 where b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'ab' or b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'abc';
+a b
+3 abc
+select * from t1 where b like 'abc' or b like 'abc';
+a b
+3 abc
+set engine_condition_pushdown = on;
+select * from t1 where b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'ab' or b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'abc';
+a b
+3 abc
+select * from t1 where b like 'abc' or b like 'abc';
+a b
+3 abc
+drop table t1;
+create table t1 (a int, b char(3), primary key using hash(a))
+engine=ndb;
+insert into t1 values (1,'a'), (2,'ab'), (3,'abc');
+set engine_condition_pushdown = off;
+select * from t1 where b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'ab' or b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'abc';
+a b
+3 abc
+select * from t1 where b like 'abc' or b like 'abc';
+a b
+3 abc
+set engine_condition_pushdown = on;
+select * from t1 where b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'ab' or b like 'ab';
+a b
+2 ab
+select * from t1 where b like 'abc';
+a b
+3 abc
+select * from t1 where b like 'abc' or b like 'abc';
+a b
+3 abc
set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5;
diff --git a/mysql-test/r/ndb_config.result b/mysql-test/r/ndb_config.result
index d2a8a91828c..c364b8f1b5d 100644
--- a/mysql-test/r/ndb_config.result
+++ b/mysql-test/r/ndb_config.result
@@ -8,4 +8,3 @@ ndbd,1,localhost,52428800,26214400 ndbd,2,localhost,52428800,36700160 ndbd,3,loc
ndbd,1,localhost ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndb_mgmd,5,localhost mysqld,6, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndb_mgmd,6,localhost mysqld,1, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndbd,6,localhost ndb_mgmd,1,localhost ndb_mgmd,2,localhost mysqld,11, mysqld,12, mysqld,13, mysqld,14, mysqld,15,
-shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
diff --git a/mysql-test/r/ndb_config2.result b/mysql-test/r/ndb_config2.result
new file mode 100644
index 00000000000..cfd012933c4
--- /dev/null
+++ b/mysql-test/r/ndb_config2.result
@@ -0,0 +1 @@
+shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
diff --git a/mysql-test/r/ndb_dd_backuprestore.result b/mysql-test/r/ndb_dd_backuprestore.result
index e7568e4ce49..8c39c8c582f 100644
--- a/mysql-test/r/ndb_dd_backuprestore.result
+++ b/mysql-test/r/ndb_dd_backuprestore.result
@@ -155,333 +155,3 @@ DROP TABLE test.t1;
DROP TABLE test.t2;
DROP TABLE test.t3;
DROP TABLE test.t4;
-**** Test 3 Adding partition Test backup and restore ****
-CREATE TABLESPACE table_space2
-ADD DATAFILE './table_space2/datafile.dat'
-USE LOGFILE GROUP log_group1
-INITIAL_SIZE 12M
-ENGINE NDB;
-CREATE TABLE test.t1 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(150) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space1 STORAGE DISK ENGINE=NDB PARTITION BY HASH(c3) PARTITIONS 4;
-CREATE TABLE test.t4 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(180) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY HASH(c3) PARTITIONS 2;
-CREATE TABLE test.t2 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 TEXT NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space2 STORAGE DISK ENGINE=NDB PARTITION BY KEY(c3) (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-CREATE TABLE test.t5 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 TEXT NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY KEY(pk1) (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-CREATE TABLE test.t3 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(202) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space2 STORAGE DISK ENGINE=NDB PARTITION BY RANGE (c3) PARTITIONS 3 (PARTITION x1 VALUES LESS THAN (105), PARTITION x2 VALUES LESS THAN (333), PARTITION x3 VALUES LESS THAN (720));
-CREATE TABLE test.t6 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(220) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY RANGE (pk1) PARTITIONS 2 (PARTITION x1 VALUES LESS THAN (333), PARTITION x2 VALUES LESS THAN (720));
-SHOW CREATE TABLE test.t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(150) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH (c3) PARTITIONS 4
-SHOW CREATE TABLE test.t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` text NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space2 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (c3) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t3;
-Table Create Table
-t3 CREATE TABLE `t3` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(202) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space2 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (c3) (PARTITION x1 VALUES LESS THAN (105) ENGINE = ndbcluster, PARTITION x2 VALUES LESS THAN (333) ENGINE = ndbcluster, PARTITION x3 VALUES LESS THAN (720) ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(180) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH (c3) PARTITIONS 2
-SHOW CREATE TABLE test.t5;
-Table Create Table
-t5 CREATE TABLE `t5` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` text NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (pk1) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t6;
-Table Create Table
-t6 CREATE TABLE `t6` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(220) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (pk1) (PARTITION x1 VALUES LESS THAN (333) ENGINE = ndbcluster, PARTITION x2 VALUES LESS THAN (720) ENGINE = ndbcluster)
-SELECT * FROM information_schema.partitions WHERE table_name= 't1';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t1 p0 NULL 1 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p1 NULL 2 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p2 NULL 3 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p3 NULL 4 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't2';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t2 p0 NULL 1 NULL KEY NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t2 p1 NULL 2 NULL KEY NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't3';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t3 x1 NULL 1 NULL RANGE NULL c3 NULL 105 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t3 x2 NULL 2 NULL RANGE NULL c3 NULL 333 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t3 x3 NULL 3 NULL RANGE NULL c3 NULL 720 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't4';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t4 p0 NULL 1 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t4 p1 NULL 2 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't5';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t5 p0 NULL 1 NULL KEY NULL pk1 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t5 p1 NULL 2 NULL KEY NULL pk1 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't6';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t6 x1 NULL 1 NULL RANGE NULL pk1 NULL 333 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t6 x2 NULL 2 NULL RANGE NULL pk1 NULL 720 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t1 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas 2 0
-249 Sweden, Texas 4 0
-248 Sweden, Texas 6 0
-247 Sweden, Texas 8 0
-246 Sweden, Texas 10 0
-SELECT COUNT(*) FROM test.t2;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t2 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 1 1
-249 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 3 1
-248 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 5 1
-247 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 7 1
-246 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 9 1
-SELECT COUNT(*) FROM test.t3;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t3 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 0 1
-249 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 2 1
-248 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 4 1
-247 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 6 1
-246 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 8 1
-SELECT COUNT(*) FROM test.t4;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t4 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas 2 0
-249 Sweden, Texas 4 0
-248 Sweden, Texas 6 0
-247 Sweden, Texas 8 0
-246 Sweden, Texas 10 0
-SELECT COUNT(*) FROM test.t5;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t5 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 1 1
-249 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 3 1
-248 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 5 1
-247 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 7 1
-246 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 9 1
-SELECT COUNT(*) FROM test.t6;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t6 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 0 1
-249 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 2 1
-248 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 4 1
-247 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 6 1
-246 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 8 1
-CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
-DELETE FROM test.backup_info;
-LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
-SELECT @the_backup_id:=backup_id FROM test.backup_info;
-@the_backup_id:=backup_id
-<the_backup_id>
-DROP TABLE test.backup_info;
-DROP TABLE test.t1;
-DROP TABLE test.t2;
-DROP TABLE test.t3;
-DROP TABLE test.t4;
-DROP TABLE test.t5;
-DROP TABLE test.t6;
-ALTER TABLESPACE table_space1
-DROP DATAFILE './table_space1/datafile.dat'
-ENGINE = NDB;
-ALTER TABLESPACE table_space2
-DROP DATAFILE './table_space2/datafile.dat'
-ENGINE = NDB;
-DROP TABLESPACE table_space1
-ENGINE = NDB;
-DROP TABLESPACE table_space2
-ENGINE = NDB;
-DROP LOGFILE GROUP log_group1
-ENGINE =NDB;
-SHOW CREATE TABLE test.t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(150) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH (c3) PARTITIONS 4
-SHOW CREATE TABLE test.t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` text NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space2 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (c3) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t3;
-Table Create Table
-t3 CREATE TABLE `t3` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(202) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) TABLESPACE table_space2 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (c3) (PARTITION x1 VALUES LESS THAN (105) ENGINE = ndbcluster, PARTITION x2 VALUES LESS THAN (333) ENGINE = ndbcluster, PARTITION x3 VALUES LESS THAN (720) ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(180) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH (c3) PARTITIONS 2
-SHOW CREATE TABLE test.t5;
-Table Create Table
-t5 CREATE TABLE `t5` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` text NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (pk1) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-SHOW CREATE TABLE test.t6;
-Table Create Table
-t6 CREATE TABLE `t6` (
- `pk1` mediumint(9) NOT NULL AUTO_INCREMENT,
- `c2` varchar(220) NOT NULL,
- `c3` int(11) NOT NULL,
- `c4` bit(1) NOT NULL,
- PRIMARY KEY (`pk1`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (pk1) (PARTITION x1 VALUES LESS THAN (333) ENGINE = ndbcluster, PARTITION x2 VALUES LESS THAN (720) ENGINE = ndbcluster)
-SELECT * FROM information_schema.partitions WHERE table_name= 't1';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t1 p0 NULL 1 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p1 NULL 2 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p2 NULL 3 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t1 p3 NULL 4 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't2';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t2 p0 NULL 1 NULL KEY NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t2 p1 NULL 2 NULL KEY NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't3';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t3 x1 NULL 1 NULL RANGE NULL c3 NULL 105 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t3 x2 NULL 2 NULL RANGE NULL c3 NULL 333 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t3 x3 NULL 3 NULL RANGE NULL c3 NULL 720 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't4';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t4 p0 NULL 1 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t4 p1 NULL 2 NULL HASH NULL c3 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't5';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t5 p0 NULL 1 NULL KEY NULL pk1 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t5 p1 NULL 2 NULL KEY NULL pk1 NULL NULL 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT * FROM information_schema.partitions WHERE table_name= 't6';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t6 x1 NULL 1 NULL RANGE NULL pk1 NULL 333 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-NULL test t6 x2 NULL 2 NULL RANGE NULL pk1 NULL 720 0 0 0 NULL 0 0 NULL NULL NULL NULL default 0 default
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t1 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas 2 0
-249 Sweden, Texas 4 0
-248 Sweden, Texas 6 0
-247 Sweden, Texas 8 0
-246 Sweden, Texas 10 0
-SELECT COUNT(*) FROM test.t2;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t2 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 1 1
-249 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 3 1
-248 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 5 1
-247 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 7 1
-246 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 9 1
-SELECT COUNT(*) FROM test.t3;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t3 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 0 1
-249 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 2 1
-248 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 4 1
-247 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 6 1
-246 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 8 1
-SELECT COUNT(*) FROM test.t4;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t4 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas 2 0
-249 Sweden, Texas 4 0
-248 Sweden, Texas 6 0
-247 Sweden, Texas 8 0
-246 Sweden, Texas 10 0
-SELECT COUNT(*) FROM test.t5;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t5 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 1 1
-249 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 3 1
-248 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 5 1
-247 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 7 1
-246 Sweden, Texas, ITALY, Kyle, JO, JBM,TU 9 1
-SELECT COUNT(*) FROM test.t6;
-COUNT(*)
-250
-SELECT pk1, c2, c3, hex(c4) FROM test.t6 ORDER BY c3 LIMIT 5;
-pk1 c2 c3 hex(c4)
-250 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 0 1
-249 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 2 1
-248 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 4 1
-247 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 6 1
-246 TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU 8 1
-DROP TABLE test.t1;
-DROP TABLE test.t2;
-DROP TABLE test.t3;
-DROP TABLE test.t4;
-DROP TABLE test.t5;
-DROP TABLE test.t6;
-ALTER TABLESPACE table_space1 DROP DATAFILE './table_space1/datafile.dat' ENGINE=NDB;
-ALTER TABLESPACE table_space2 DROP DATAFILE './table_space2/datafile.dat' ENGINE=NDB;
-DROP TABLESPACE table_space1 ENGINE = NDB;
-DROP TABLESPACE table_space2 ENGINE = NDB;
-DROP LOGFILE GROUP log_group1 ENGINE = NDB;
diff --git a/mysql-test/r/ndb_dd_basic.result b/mysql-test/r/ndb_dd_basic.result
index 8b16bce830c..008be3aa79f 100644
--- a/mysql-test/r/ndb_dd_basic.result
+++ b/mysql-test/r/ndb_dd_basic.result
@@ -3,11 +3,32 @@ CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
-ENGINE=NDB;
+ENGINE=MYISAM;
+Warnings:
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+ALTER LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile02.dat'
+INITIAL_SIZE = 4M
+ENGINE=XYZ;
+Warnings:
+Error 1266 Using storage engine MyISAM for table 'lg1'
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 12M;
+Warnings:
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+set storage_engine=ndb;
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 16M
+UNDO_BUFFER_SIZE = 1M;
ALTER LOGFILE GROUP lg1
ADD UNDOFILE 'undofile02.dat'
INITIAL_SIZE = 4M
ENGINE=NDB;
+set storage_engine=myisam;
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
@@ -28,7 +49,7 @@ t1 CREATE TABLE `t1` (
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`pk1`)
-) TABLESPACE ts1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) TABLESPACE ts1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (0, 0, 0);
SELECT * FROM t1;
pk1 b c
diff --git a/mysql-test/r/ndb_dd_ddl.result b/mysql-test/r/ndb_dd_ddl.result
index 39dceef1573..47b95214024 100644
--- a/mysql-test/r/ndb_dd_ddl.result
+++ b/mysql-test/r/ndb_dd_ddl.result
@@ -16,7 +16,7 @@ ERROR HY000: Failed to create LOGFILE GROUP
SHOW WARNINGS;
Level Code Message
Error 1296 Got error 1514 'Currently there is a limit of one logfile group' from NDB
-Error 1507 Failed to create LOGFILE GROUP
+Error 1515 Failed to create LOGFILE GROUP
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
diff --git a/mysql-test/r/ndb_dd_disk2memory.result b/mysql-test/r/ndb_dd_disk2memory.result
index 80056b7269d..bd5bbda42f3 100644
--- a/mysql-test/r/ndb_dd_disk2memory.result
+++ b/mysql-test/r/ndb_dd_disk2memory.result
@@ -218,7 +218,7 @@ t2 CREATE TABLE `t2` (
`b2` int(11) NOT NULL,
`c2` int(11) NOT NULL,
PRIMARY KEY (`pk2`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
SHOW CREATE TABLE test.t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -226,7 +226,7 @@ t1 CREATE TABLE `t1` (
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`pk1`)
-) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1
ALTER TABLE test.t2 TABLESPACE table_space1 STORAGE DISK
ENGINE=NDB;
SHOW CREATE TABLE test.t2;
@@ -236,7 +236,7 @@ t2 CREATE TABLE `t2` (
`b2` int(11) NOT NULL,
`c2` int(11) NOT NULL,
PRIMARY KEY (`pk2`)
-) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) TABLESPACE table_space1 STORAGE DISK ENGINE=ndbcluster DEFAULT CHARSET=latin1
ALTER TABLE test.t1 ENGINE=NDBCLUSTER;
SHOW CREATE TABLE test.t1;
Table Create Table
@@ -245,7 +245,7 @@ t1 CREATE TABLE `t1` (
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`pk1`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
DROP TABLE test.t1;
DROP TABLE test.t2;
diff --git a/mysql-test/r/ndb_gis.result b/mysql-test/r/ndb_gis.result
index f9b9ceb76a5..67447a69242 100644
--- a/mysql-test/r/ndb_gis.result
+++ b/mysql-test/r/ndb_gis.result
@@ -14,7 +14,7 @@ gis_point CREATE TABLE `gis_point` (
`fid` int(11) NOT NULL AUTO_INCREMENT,
`g` point DEFAULT NULL,
PRIMARY KEY (`fid`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra
fid int(11) NO PRI NULL auto_increment
@@ -476,7 +476,7 @@ gis_point CREATE TABLE `gis_point` (
`fid` int(11) NOT NULL AUTO_INCREMENT,
`g` point DEFAULT NULL,
PRIMARY KEY (`fid`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra
fid int(11) NO PRI NULL auto_increment
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index 229339d603e..bd42595f060 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -45,6 +45,8 @@ a b c
8 2 3
alter table t1 drop index ib;
insert into t1 values(1, 2, 3);
+create unique index ib on t1(b);
+ERROR 23000: Can't write, because of unique constraint, to table 't1'
drop table t1;
CREATE TABLE t1 (
a int unsigned NOT NULL PRIMARY KEY,
@@ -97,7 +99,7 @@ CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
c int unsigned not null,
-UNIQUE USING HASH (b, c)
+UNIQUE (b, c) USING HASH
) engine=ndbcluster;
insert t2 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
select * from t2 where a = 3;
@@ -140,14 +142,14 @@ CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
c int unsigned,
-UNIQUE USING HASH (b, c)
+UNIQUE (b, c) USING HASH
) engine=ndbcluster;
ERROR 42000: Column 'c' is used with UNIQUE or INDEX but is not defined as NOT NULL
CREATE TABLE t3 (
a int unsigned NOT NULL,
b int unsigned not null,
c int unsigned,
-PRIMARY KEY USING HASH (a, b)
+PRIMARY KEY (a, b) USING HASH
) engine=ndbcluster;
insert t3 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
select * from t3 where a = 3;
diff --git a/mysql-test/r/ndb_multi_row.result b/mysql-test/r/ndb_multi_row.result
index 64b151d42a9..cf5a76d6f01 100644
--- a/mysql-test/r/ndb_multi_row.result
+++ b/mysql-test/r/ndb_multi_row.result
@@ -62,4 +62,6 @@ t4
drop table t1, t2, t3, t4;
drop table if exists t1, t3, t4;
Warnings:
+Error 155 Table 'test.t1' doesn't exist
Error 155 Table 'test.t3' doesn't exist
+Error 155 Table 'test.t4' doesn't exist
diff --git a/mysql-test/r/ndb_partition_error.result b/mysql-test/r/ndb_partition_error.result
deleted file mode 100644
index d86dc382185..00000000000
--- a/mysql-test/r/ndb_partition_error.result
+++ /dev/null
@@ -1,47 +0,0 @@
-drop table if exists t1;
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a,b),
-index (a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5) nodegroup 12,
-partition x2 values less than (10) nodegroup 13,
-partition x3 values less than (20) nodegroup 14);
-ERROR HY000: Can't create table 'test.t1' (errno: 140)
-show warnings;
-Level Code Message
-Error 1296 Got error 771 'Given NODEGROUP doesn't exist in this cluster' from NDB
-Error 1005 Can't create table 'test.t1' (errno: 140)
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5),
-partition x2 values less than (10),
-partition x3 values less than (20));
-drop table t1;
-CREATE TABLE t1 (id INT) ENGINE=NDB
-PARTITION BY LIST(id)
-(PARTITION p0 VALUES IN (2, 4),
-PARTITION p1 VALUES IN (42, 142));
-INSERT INTO t1 VALUES (2);
-UPDATE t1 SET id=5 WHERE id=2;
-ERROR HY000: Table has no partition for value 5
-DROP TABLE t1;
-create table t1 (a int,b int, c int)
-engine = ndb
-partition by list(a)
-partitions 2
-(partition x123 values in (11, 12),
-partition x234 values in (5, 1));
-insert into t1 values (NULL,1,1);
-ERROR HY000: Table has no partition for value NULL
-drop table t1;
diff --git a/mysql-test/r/ndb_partition_key.result b/mysql-test/r/ndb_partition_key.result
deleted file mode 100644
index 8225fca7a54..00000000000
--- a/mysql-test/r/ndb_partition_key.result
+++ /dev/null
@@ -1,185 +0,0 @@
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b,c))
-ENGINE = NDB
-PARTITION BY KEY (a,b);
-insert into t1 values (1,1,1,1);
-select * from t1;
-a b c d
-1 1 1 1
-update t1 set d = 2 where a = 1 and b = 1 and c = 1;
-select * from t1;
-a b c d
-1 1 1 2
-delete from t1;
-select * from t1;
-a b c d
-drop table t1;
-CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b))
-ENGINE = NDB
-PARTITION BY KEY (c);
-ERROR HY000: A PRIMARY KEY need to include all fields in the partition function
-CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY(a,b))
-ENGINE = NDB
-PARTITION BY KEY (a);
-insert into t1 values
-(1,1,3),(1,2,3),(1,3,3),(1,4,3),(1,5,3),(1,6,3),
-(1,7,3),(1,8,3),(1,9,3),(1,10,3),(1,11,3),(1,12,3);
-select * from t1 order by b;
-a b c
-1 1 3
-1 2 3
-1 3 3
-1 4 3
-1 5 3
-1 6 3
-1 7 3
-1 8 3
-1 9 3
-1 10 3
-1 11 3
-1 12 3
-DROP TABLE t1;
-CREATE TABLE t1 (a INT, b CHAR(10) COLLATE latin1_bin, c INT, d INT,
-PRIMARY KEY USING HASH (a,b,c))
-ENGINE=NDB
-DEFAULT CHARSET=latin1
-PARTITION BY KEY (b);
-insert into t1 values (1,"a",1,1),(2,"a",1,1),(3,"a",1,1);
--- t1 --
-
-Fragment type: 5
-K Value: 6
-Min load factor: 78
-Max load factor: 80
-Temporary table: no
-Number of attributes: 4
-Number of primary keys: 3
-Length of frm data: #
-Row Checksum: 1
-Row GCI: 1
-TableStatus: Retrieved
--- Attributes --
-a Int PRIMARY KEY AT=FIXED ST=MEMORY
-b Char(10;latin1_bin) PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
-c Int PRIMARY KEY AT=FIXED ST=MEMORY
-d Int NULL AT=FIXED ST=MEMORY
-
--- Indexes --
-PRIMARY KEY(a, b, c) - UniqueHashIndex
-
-
-NDBT_ProgramExit: 0 - OK
-
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL DEFAULT '0',
- `b` char(10) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '',
- `c` int(11) NOT NULL DEFAULT '0',
- `d` int(11) DEFAULT NULL,
- PRIMARY KEY USING HASH (`a`,`b`,`c`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (b)
-DROP TABLE t1;
-CREATE TABLE t1 (a int not null primary key)
-PARTITION BY KEY(a)
-(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-drop table t1;
-CREATE TABLE t1 (a int not null primary key);
-ALTER TABLE t1
-PARTITION BY KEY(a)
-(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-drop table t1;
-create table t1 (a int)
-engine=ndb
-partition by key(a)
-(partition p0, partition p1);
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-alter table t1 engine=heap;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY)
-alter table t1 engine=ndb;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-alter table t1 engine=heap remove partitioning;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=MEMORY DEFAULT CHARSET=latin1
-alter table t1 engine=ndb
-partition by key(a)
-(partition p0, partition p1 engine = ndb);
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-alter table t1
-partition by key (a)
-(partition p0 engine=ndb, partition p1 engine=ndb);
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-alter table t1 remove partitioning;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
-alter table t1
-partition by key(a)
-(partition p0 engine=ndb, partition p1);
-ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
-alter table t1
-engine=ndb
-partition by key(a)
-(partition p0 engine=ndb, partition p1 engine = ndb);
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster)
-drop table t1;
-CREATE TABLE t1 (
-c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
-c2 TEXT NOT NULL,
-c3 INT NOT NULL,
-c4 BIT NOT NULL,
-c5 FLOAT,
-c6 VARCHAR(255),
-c7 TIMESTAMP,
-PRIMARY KEY(c1,c3))
-ENGINE=NDB
-PARTITION BY KEY(c3) PARTITIONS 5;
-ALTER TABLE t1 COALESCE PARTITION 4;
-DROP TABLE t1;
-CREATE TABLE t1 (
-c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
-c2 TEXT NOT NULL,
-c3 INT NOT NULL,
-PRIMARY KEY(c1,c3))
-ENGINE=NDB
-PARTITION BY KEY(c3) PARTITIONS 5;
-ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1;
-DROP TABLE t1;
-CREATE TABLE t1 (
-c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
-c2 TEXT NOT NULL,
-c3 INT NOT NULL,
-PRIMARY KEY(c1,c3))
-ENGINE=NDB
-PARTITION BY KEY(c3);
-ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1;
-DROP TABLE t1;
diff --git a/mysql-test/r/ndb_partition_list.result b/mysql-test/r/ndb_partition_list.result
deleted file mode 100644
index ce2574ddcc4..00000000000
--- a/mysql-test/r/ndb_partition_list.result
+++ /dev/null
@@ -1,51 +0,0 @@
-drop table if exists t1;
-CREATE TABLE t1 ( f_int1 INTEGER NOT NULL, f_int2 INTEGER NOT NULL,
-f_char1 CHAR(10),
-f_char2 CHAR(10), f_charbig VARCHAR(1000),
-PRIMARY KEY (f_int1,f_int2))
-ENGINE = NDB
-PARTITION BY LIST(MOD(f_int1 + f_int2,4))
-(PARTITION part_3 VALUES IN (-3),
-PARTITION part_2 VALUES IN (-2),
-PARTITION part_1 VALUES IN (-1),
-PARTITION part0 VALUES IN (0),
-PARTITION part1 VALUES IN (1),
-PARTITION part2 VALUES IN (2),
-PARTITION part3 VALUES IN (3,4,5));
-INSERT INTO t1 SET f_int1 = -2, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 1, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 2, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 3, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 4, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 5, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 20, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-SELECT * FROM t1 ORDER BY f_int1;
-f_int1 f_int2 f_char1 f_char2 f_charbig
--2 20 20 20 ===20===
-1 1 1 1 ===1===
-2 1 1 1 ===1===
-3 1 1 1 ===1===
-4 1 1 1 ===1===
-5 1 1 1 ===1===
-20 1 1 1 ===1===
-DROP TABLE t1;
-CREATE TABLE t1 ( f_int1 INTEGER, f_int2 INTEGER, f_char1 CHAR(10),
-f_char2 CHAR(10), f_charbig VARCHAR(1000))
-ENGINE = NDB
-PARTITION BY LIST(f_int1)
-(PARTITION part_1 VALUES IN (-1),
-PARTITION part0 VALUES IN (0,1),
-PARTITION part1 VALUES IN (2));
-INSERT INTO t1 SET f_int1 = -1, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 0, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 1, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 2, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 20, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-ERROR HY000: Table has no partition for value 20
-SELECT * FROM t1 ORDER BY f_int1;
-f_int1 f_int2 f_char1 f_char2 f_charbig
--1 20 20 20 ===20===
-0 20 20 20 ===20===
-1 1 1 1 ===1===
-2 1 1 1 ===1===
-DROP TABLE t1;
diff --git a/mysql-test/r/ndb_partition_range.result b/mysql-test/r/ndb_partition_range.result
deleted file mode 100644
index cb79f04873e..00000000000
--- a/mysql-test/r/ndb_partition_range.result
+++ /dev/null
@@ -1,263 +0,0 @@
-drop table if exists t1;
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a,b),
-index (a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5),
-partition x2 values less than (10),
-partition x3 values less than (20));
-INSERT into t1 values (1, 1, 1);
-INSERT into t1 values (6, 1, 1);
-INSERT into t1 values (10, 1, 1);
-INSERT into t1 values (15, 1, 1);
-select * from information_schema.partitions where table_name= 't1';
-TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
-NULL test t1 x1 NULL 1 NULL RANGE NULL a NULL 5 0 0 0 # 0 0 # # NULL NULL default 0 default
-NULL test t1 x2 NULL 2 NULL RANGE NULL a NULL 10 0 0 0 # 0 0 # # NULL NULL default 0 default
-NULL test t1 x3 NULL 3 NULL RANGE NULL a NULL 20 0 0 0 # 0 0 # # NULL NULL default 0 default
-select * from t1 order by a;
-a b c
-1 1 1
-6 1 1
-10 1 1
-15 1 1
-select * from t1 where a=1 order by a;
-a b c
-1 1 1
-select * from t1 where a=15 and b=1 order by a;
-a b c
-15 1 1
-select * from t1 where a=21 and b=1 order by a;
-a b c
-select * from t1 where a=21 order by a;
-a b c
-select * from t1 where a in (1,6,10,21) order by a;
-a b c
-1 1 1
-6 1 1
-10 1 1
-select * from t1 where b=1 and a in (1,6,10,21) order by a;
-a b c
-1 1 1
-6 1 1
-10 1 1
-drop table t1;
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(b),
-unique (a))
-engine = ndb
-partition by range (b)
-partitions 3
-(partition x1 values less than (5),
-partition x2 values less than (10),
-partition x3 values less than (20));
-INSERT into t1 values (1, 1, 1);
-INSERT into t1 values (2, 6, 1);
-INSERT into t1 values (3, 10, 1);
-INSERT into t1 values (4, 15, 1);
-select * from t1 order by a;
-a b c
-1 1 1
-2 6 1
-3 10 1
-4 15 1
-UPDATE t1 set a = 5 WHERE b = 15;
-select * from t1 order by a;
-a b c
-1 1 1
-2 6 1
-3 10 1
-5 15 1
-UPDATE t1 set a = 6 WHERE a = 5;
-select * from t1 order by a;
-a b c
-1 1 1
-2 6 1
-3 10 1
-6 15 1
-select * from t1 where b=1 order by b;
-a b c
-1 1 1
-select * from t1 where b=15 and a=1 order by b;
-a b c
-select * from t1 where b=21 and a=1 order by b;
-a b c
-select * from t1 where b=21 order by b;
-a b c
-select * from t1 where b in (1,6,10,21) order by b;
-a b c
-1 1 1
-2 6 1
-3 10 1
-select * from t1 where a in (1,2,5,6) order by b;
-a b c
-1 1 1
-2 6 1
-6 15 1
-select * from t1 where a=1 and b in (1,6,10,21) order by b;
-a b c
-1 1 1
-DELETE from t1 WHERE b = 6;
-DELETE from t1 WHERE a = 6;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL,
- `b` int(11) NOT NULL,
- `c` int(11) NOT NULL,
- PRIMARY KEY (`b`),
- UNIQUE KEY `a` (`a`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (b) (PARTITION x1 VALUES LESS THAN (5) ENGINE = ndbcluster, PARTITION x2 VALUES LESS THAN (10) ENGINE = ndbcluster, PARTITION x3 VALUES LESS THAN (20) ENGINE = ndbcluster)
-drop table t1;
-CREATE TABLE t1
-(id MEDIUMINT NOT NULL,
-b1 BIT(8),
-vc VARCHAR(255),
-bc CHAR(255),
-d DECIMAL(10,4) DEFAULT 0,
-f FLOAT DEFAULT 0,
-total BIGINT UNSIGNED,
-y YEAR,
-t DATE) ENGINE=NDB
-PARTITION BY RANGE (YEAR(t))
-(PARTITION p0 VALUES LESS THAN (1901),
-PARTITION p1 VALUES LESS THAN (1946),
-PARTITION p2 VALUES LESS THAN (1966),
-PARTITION p3 VALUES LESS THAN (1986),
-PARTITION p4 VALUES LESS THAN (2005),
-PARTITION p5 VALUES LESS THAN MAXVALUE);
-INSERT INTO t1 VALUES (0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-SELECT * FROM t1;
-id b1 vc bc d f total y t
-0 NULL NULL NULL NULL NULL NULL NULL NULL
-ALTER TABLE t1 ENGINE=MYISAM;
-SELECT * FROM t1;
-id b1 vc bc d f total y t
-0 NULL NULL NULL NULL NULL NULL NULL NULL
-DROP TABLE t1;
-CREATE LOGFILE GROUP lg1
-ADD UNDOFILE 'undofile.dat'
- INITIAL_SIZE 16M
-UNDO_BUFFER_SIZE=1M
-ENGINE=NDB;
-CREATE TABLESPACE ts1
-ADD DATAFILE 'datafile.dat'
- USE LOGFILE GROUP lg1
-INITIAL_SIZE 12M
-ENGINE NDB;
-CREATE TABLE test.t1 (
-a1 INT,
-a2 TEXT NOT NULL,
-a3 BIT NOT NULL,
-a4 DECIMAL(8,3),
-a5 INT NOT NULL,
-a6 INT,
-PRIMARY KEY(a1))
-TABLESPACE ts1 STORAGE DISK ENGINE=NDB
-PARTITION BY LIST (a1)
-(PARTITION p0 VALUES IN (1,2,3,4,5),
-PARTITION p1 VALUES IN (6,7,8,9, 10),
-PARTITION p2 VALUES IN (11, 12, 13, 14, 15));
-ALTER TABLE test.t1 DROP COLUMN a6;
-ALTER TABLE test.t1 ADD COLUMN a6 VARCHAR(255);
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-15
-ALTER TABLE test.t1 DROP COLUMN a4;
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-15
-DROP TABLE t1;
-CREATE TABLE test.t1 (
-a1 INT,
-a2 TEXT NOT NULL,
-a3 BIT NOT NULL,
-a4 DECIMAL(8,3),
-a5 INT NOT NULL,
-a6 VARCHAR(255),
-PRIMARY KEY(a1))
-TABLESPACE ts1 STORAGE DISK ENGINE=NDB
-PARTITION BY HASH(a1)
-PARTITIONS 4;
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-15
-ALTER TABLE test.t1 DROP COLUMN a4;
-SELECT COUNT(*) FROM test.t1;
-COUNT(*)
-15
-DROP TABLE t1;
-ALTER TABLESPACE ts1
-DROP DATAFILE 'datafile.dat'
-ENGINE=NDB;
-DROP TABLESPACE ts1 ENGINE=NDB;
-DROP LOGFILE GROUP lg1 ENGINE=NDB;
-CREATE TABLE t1
-(id MEDIUMINT NOT NULL,
-b1 BIT(8),
-vc VARCHAR(255),
-bc CHAR(255),
-d DECIMAL(10,4) DEFAULT 0,
-f FLOAT DEFAULT 0,
-total BIGINT UNSIGNED,
-y YEAR,
-t DATE) ENGINE=NDB
-PARTITION BY LIST(id)
-(PARTITION p0 VALUES IN (2, 4),
-PARTITION p1 VALUES IN (42, 142));
-INSERT INTO t1 VALUES (2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-SELECT * FROM t1;
-id b1 vc bc d f total y t
-2 NULL NULL NULL NULL NULL NULL NULL NULL
-ALTER TABLE t1 ADD PARTITION
-(PARTITION p2 VALUES IN (412));
-SELECT * FROM t1;
-id b1 vc bc d f total y t
-2 NULL NULL NULL NULL NULL NULL NULL NULL
-DROP TABLE t1;
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null)
-partition by list(a)
-partitions 2
-(partition x123 values in (1,5,6),
-partition x234 values in (4,7,8));
-INSERT into t1 VALUES (5,1,1);
-select * from t1;
-a b c
-5 1 1
-UPDATE t1 SET a=8 WHERE a=5 AND b=1;
-select * from t1;
-a b c
-8 1 1
-drop table t1;
-CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) engine=ndb
-PARTITION BY RANGE(f1)
-( PARTITION part1 VALUES LESS THAN (2),
-PARTITION part2 VALUES LESS THAN (1000));
-INSERT INTO t1 VALUES(1, '---1---');
-INSERT INTO t1 VALUES(2, '---2---');
-select * from t1 order by f1;
-f1 f2
-1 ---1---
-2 ---2---
-UPDATE t1 SET f1 = f1 + 4 WHERE f1 = 2;
-select * from t1 order by f1;
-f1 f2
-1 ---1---
-6 ---2---
-UPDATE t1 SET f1 = f1 + 4 WHERE f1 = 1;
-select * from t1 order by f1;
-f1 f2
-5 ---1---
-6 ---2---
-drop table t1;
diff --git a/mysql-test/r/ndb_restore_compat.result b/mysql-test/r/ndb_restore_compat.result
new file mode 100644
index 00000000000..358ca36b2df
--- /dev/null
+++ b/mysql-test/r/ndb_restore_compat.result
@@ -0,0 +1,104 @@
+DROP DATABASE IF EXISTS BANK;
+CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
+USE BANK;
+SHOW TABLES;
+Tables_in_BANK
+ACCOUNT
+GL
+ACCOUNT_TYPE
+TRANSACTION
+SYSTEM_VALUES
+SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE;
+TIME ACCOUNT_TYPE BALANCE DEPOSIT_COUNT DEPOSIT_SUM WITHDRAWAL_COUNT WITHDRAWAL_SUM PURGED
+0 0 10000000 0 0 0 0 1
+0 1 30000 0 0 0 0 1
+0 2 20000 0 0 0 0 1
+0 3 20000 0 0 0 0 1
+0 4 20000 0 0 0 0 1
+1 0 10000000 0 0 0 0 0
+1 1 30000 0 0 0 0 0
+1 2 20000 0 0 0 0 0
+1 3 20000 0 0 0 0 0
+1 4 20000 0 0 0 0 0
+2 0 9981761 17 80457 19 98696 0
+2 1 17823 55 203688 46 215865 0
+2 2 47056 33 159275 33 132219 0
+2 3 15719 26 126833 29 131114 0
+2 4 27641 32 133459 36 125818 0
+SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID;
+ACCOUNT_ID OWNER BALANCE ACCOUNT_TYPE
+0 0 9863546 0
+1 3001 12885 1
+2 3002 11012 2
+3 3003 32789 3
+4 3004 10992 4
+5 3005 2247 1
+6 3006 3170 1
+7 3007 60321 2
+8 3008 30508 3
+9 3009 62530 4
+SELECT COUNT(*) FROM TRANSACTION;
+COUNT(*)
+3444
+SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID;
+SYSTEM_VALUES_ID VALUE
+0 2039
+1 3
+SELECT * FROM cluster.apply_status WHERE server_id=0;
+server_id epoch
+0 151
+TRUNCATE GL;
+TRUNCATE ACCOUNT;
+TRUNCATE TRANSACTION;
+TRUNCATE SYSTEM_VALUES;
+TRUNCATE ACCOUNT_TYPE;
+SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE;
+TIME ACCOUNT_TYPE BALANCE DEPOSIT_COUNT DEPOSIT_SUM WITHDRAWAL_COUNT WITHDRAWAL_SUM PURGED
+0 0 10000000 0 0 0 0 1
+0 1 30000 0 0 0 0 1
+0 2 20000 0 0 0 0 1
+0 3 20000 0 0 0 0 1
+0 4 20000 0 0 0 0 1
+1 0 10000000 0 0 0 0 1
+1 1 30000 0 0 0 0 1
+1 2 20000 0 0 0 0 1
+1 3 20000 0 0 0 0 1
+1 4 20000 0 0 0 0 1
+2 0 10000000 0 0 0 0 1
+2 1 30000 0 0 0 0 1
+2 2 20000 0 0 0 0 1
+2 3 20000 0 0 0 0 1
+2 4 20000 0 0 0 0 1
+3 0 9963591 14 59111 19 95520 0
+3 1 44264 49 255559 53 241295 0
+3 2 25515 39 177806 36 172291 0
+3 3 16779 26 129200 29 132421 0
+3 4 39851 43 182771 34 162920 0
+4 0 9733661 141 632616 162 862546 0
+4 1 63853 426 2005337 415 1985748 0
+4 2 140473 314 1548632 297 1433674 0
+4 3 13481 310 1528043 324 1531341 0
+4 4 138532 316 1540206 309 1441525 0
+SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID;
+ACCOUNT_ID OWNER BALANCE ACCOUNT_TYPE
+0 0 9679579 0
+1 3001 18130 1
+2 3002 12318 2
+3 3003 3049 3
+4 3004 39517 4
+5 3005 37051 1
+6 3006 144497 1
+7 3007 130670 2
+8 3008 13747 3
+9 3009 11442 4
+SELECT COUNT(*) FROM TRANSACTION;
+COUNT(*)
+4056
+SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID;
+SYSTEM_VALUES_ID VALUE
+0 2297
+1 5
+SELECT * FROM cluster.apply_status WHERE server_id=0;
+server_id epoch
+0 331
+DROP DATABASE BANK;
diff --git a/mysql-test/r/not_as_root.require b/mysql-test/r/not_as_root.require
new file mode 100644
index 00000000000..d9ea5244efc
--- /dev/null
+++ b/mysql-test/r/not_as_root.require
@@ -0,0 +1,2 @@
+running_as_root
+NO
diff --git a/mysql-test/r/not_embedded_server.result b/mysql-test/r/not_embedded_server.result
index e471b5a3afa..7cbe91b3753 100644
--- a/mysql-test/r/not_embedded_server.result
+++ b/mysql-test/r/not_embedded_server.result
@@ -1,5 +1,6 @@
prepare stmt1 from ' show full processlist ';
execute stmt1;
Id User Host db Command Time State Info
+number event_scheduler localhost NULL Connect time Suspended NULL
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 9a7ae446707..68fc6ff7f5f 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -278,3 +278,45 @@ field('str1', null, 'STR1') as c05,
c01 c02 c03 c04 c05 c08 c09
str str 0 1 2 1 1
set names latin1;
+create table bug19145a (e enum('a','b','c') default 'b' , s set('x', 'y', 'z') default 'y' ) engine=MyISAM;
+create table bug19145b (e enum('a','b','c') default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+create table bug19145c (e enum('a','b','c') not null default 'b' , s set('x', 'y', 'z') not null default 'y' ) engine=MyISAM;
+create table bug19145setnotnulldefaultnull (e enum('a','b','c') default null, s set('x', 'y', 'z') not null default null) engine=MyISAM;
+ERROR 42000: Invalid default value for 's'
+create table bug19145enumnotnulldefaultnull (e enum('a','b','c') not null default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+ERROR 42000: Invalid default value for 'e'
+alter table bug19145a alter column e set default null;
+alter table bug19145a alter column s set default null;
+alter table bug19145a add column (i int);
+alter table bug19145b alter column e set default null;
+alter table bug19145b alter column s set default null;
+alter table bug19145b add column (i int);
+alter table bug19145c alter column e set default null;
+ERROR 42000: Invalid default value for 'e'
+alter table bug19145c alter column s set default null;
+ERROR 42000: Invalid default value for 's'
+alter table bug19145c add column (i int);
+show create table bug19145a;
+Table Create Table
+bug19145a CREATE TABLE `bug19145a` (
+ `e` enum('a','b','c') DEFAULT NULL,
+ `s` set('x','y','z') DEFAULT NULL,
+ `i` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table bug19145b;
+Table Create Table
+bug19145b CREATE TABLE `bug19145b` (
+ `e` enum('a','b','c') DEFAULT NULL,
+ `s` set('x','y','z') DEFAULT NULL,
+ `i` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table bug19145c;
+Table Create Table
+bug19145c CREATE TABLE `bug19145c` (
+ `e` enum('a','b','c') NOT NULL DEFAULT 'b',
+ `s` set('x','y','z') NOT NULL DEFAULT 'y',
+ `i` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table bug19145a;
+drop table bug19145b;
+drop table bug19145c;
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 77f2d5495a9..1fcfb11525e 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -3,8 +3,8 @@ create table t1(f1 int);
insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
-grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/emailAddress=abstract.mysql.developer@mysql.com";
flush privileges;
SHOW STATUS LIKE 'Ssl_cipher';
Variable_name Value
@@ -38,7 +38,13 @@ f1
5
delete from t1;
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;
+drop user ssl_user1@localhost, ssl_user2@localhost,
+ssl_user3@localhost, ssl_user4@localhost;
drop table t1;
+mysqltest: Could not open connection 'default': 2026 SSL connection error
+mysqltest: Could not open connection 'default': 2026 SSL connection error
+mysqltest: Could not open connection 'default': 2026 SSL connection error
+Error when connection to server using SSL:Unable to get private key from ''
+mysqltest: Could not open connection 'default': 2026 SSL connection error
+Error when connection to server using SSL:Unable to get certificate from ''
+mysqltest: Could not open connection 'default': 2026 SSL connection error
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 6864c35dbfc..a36935a583d 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -820,3 +820,35 @@ a
2
2
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+b a
+10 1
+10 2
+20 1
+20 2
+30 1
+30 2
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+b
+10
+10
+20
+20
+30
+30
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+b a
+10 1
+20 1
+30 1
+10 2
+20 2
+30 2
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+b a
+10 1
+20 1
+10 2
+DROP TABLE t1;
diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result
index ee8c3249c9d..040dff576f8 100644
--- a/mysql-test/r/outfile.result
+++ b/mysql-test/r/outfile.result
Binary files differ
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 0da071374ea..3be9f3edee2 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -1,4 +1,8 @@
drop table if exists t1;
+create table t1 (a int)
+partition by key(a)
+(partition p0 engine = MEMORY);
+drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -886,4 +890,50 @@ s1
2
3
drop table t1;
+create table t1 (a int) engine=memory
+partition by key(a);
+insert into t1 values (1);
+create index inx1 on t1(a);
+drop table t1;
+create table t1 (a int)
+partition by key (a)
+(partition p0 engine = MERGE);
+ERROR HY000: MyISAM Merge handler cannot be used in partitioned tables
+create table t1 (a varchar(1))
+partition by key (a)
+as select 'a';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a)
+drop table t1;
+CREATE TABLE t1 (a int) ENGINE = MYISAM PARTITION BY KEY(a);
+INSERT into t1 values (1), (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 MyISAM 10 Fixed 2 7 14 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+DELETE from t1 where a = 1;
+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 1 14 14 0 0 7 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+ALTER TABLE t1 OPTIMIZE PARTITION p0;
+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 1 7 7 0 1024 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+DROP TABLE t1;
+CREATE TABLE t1 (a int, index(a)) PARTITION BY KEY(a);
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+DROP TABLE t1;
+create table t1 (a int)
+engine=MEMORY
+partition by key (a);
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair note The storage engine for the table doesn't support repair
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note The storage engine for the table doesn't support optimize
+drop table t1;
End of 5.1 tests
diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result
index b13f0d55e39..405cc3e6e25 100644
--- a/mysql-test/r/partition_pruning.result
+++ b/mysql-test/r/partition_pruning.result
@@ -596,7 +596,7 @@ f_int1
NULL
explain partitions select * from t1 where f_int1 is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part4_p2sp0 system NULL NULL NULL NULL 1
+1 SIMPLE t1 part4_part4sp0 system NULL NULL NULL NULL 1
drop table t1;
create table t1 (a int not null, b int not null)
partition by list(a)
@@ -625,16 +625,16 @@ insert into t1 values (1,1),(1,2),(1,3),(1,4),
(2,1),(2,2),(2,3),(2,4), (NULL,1);
explain partitions select * from t1 where a IS NULL AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn_p3sp0,pn_p3sp1 system NULL NULL NULL NULL 1
+1 SIMPLE t1 pn_pnsp0,pn_pnsp1 system NULL NULL NULL NULL 1
explain partitions select * from t1 where (a IS NULL or a < 1) AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn_p3sp0,pn_p3sp1 system NULL NULL NULL NULL 1
+1 SIMPLE t1 pn_pnsp0,pn_pnsp1 system NULL NULL NULL NULL 1
explain partitions select * from t1 where (a IS NULL or a < 2) AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp0,p0_p0sp1,pn_p3sp0,pn_p3sp1 ALL NULL NULL NULL NULL 5 Using where
+1 SIMPLE t1 p0_p0sp0,p0_p0sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 5 Using where
explain partitions select * from t1 where (a IS NULL or a <= 1) AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp0,p0_p0sp1,pn_p3sp0,pn_p3sp1 ALL NULL NULL NULL NULL 5 Using where
+1 SIMPLE t1 p0_p0sp0,p0_p0sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 5 Using where
drop table t1;
create table t1 ( a int) partition by list (MOD(a, 10))
( partition p0 values in (0), partition p1 values in (1),
diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result
index fc9350f5902..c7257db4910 100644
--- a/mysql-test/r/partition_range.result
+++ b/mysql-test/r/partition_range.result
@@ -363,3 +363,27 @@ SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31';
COUNT(*)
10
DROP TABLE t1;
+create table t1 (a int)
+partition by range (MOD(a,3))
+subpartition by hash(a)
+subpartitions 2
+(partition p0 values less than (1),
+partition p1 values less than (2),
+partition p2 values less than (3),
+partition p3 values less than (4));
+ALTER TABLE t1 DROP PARTITION p3;
+ALTER TABLE t1 DROP PARTITION p1;
+ALTER TABLE t1 DROP PARTITION p2;
+drop table t1;
+create table t1 (a int)
+partition by range (MOD(a,3))
+subpartition by hash(a)
+subpartitions 2
+(partition p0 values less than (1),
+partition p1 values less than (2),
+partition p2 values less than (3),
+partition p3 values less than (4));
+ALTER TABLE t1 DROP PARTITION p0;
+ALTER TABLE t1 DROP PARTITION p1;
+ALTER TABLE t1 DROP PARTITION p2;
+drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 3de7ab61e73..06443cde01d 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1056,3 +1056,104 @@ a b
1 9
3 7
drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t2;
+prepare stmt from "repair table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+prepare stmt from "optimize table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+prepare stmt from "analyze table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+prepare stmt from "repair table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t2 repair status OK
+test.t3 repair status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t2 repair status OK
+test.t3 repair status OK
+prepare stmt from "optimize table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+test.t2 optimize status OK
+test.t3 optimize status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+test.t2 optimize status Table is already up to date
+test.t3 optimize status Table is already up to date
+prepare stmt from "analyze table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status Table is already up to date
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status Table is already up to date
+prepare stmt from "repair table t1, t4, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t4 repair error Table 'test.t4' doesn't exist
+test.t3 repair status OK
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t4 repair error Table 'test.t4' doesn't exist
+test.t3 repair status OK
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+prepare stmt from "optimize table t1, t3, t4";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+test.t3 optimize status OK
+test.t4 optimize error Table 'test.t4' doesn't exist
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+test.t3 optimize status Table is already up to date
+test.t4 optimize error Table 'test.t4' doesn't exist
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+prepare stmt from "analyze table t4, t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t4 analyze error Table 'test.t4' doesn't exist
+test.t1 analyze status Table is already up to date
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t4 analyze error Table 'test.t4' doesn't exist
+test.t1 analyze status Table is already up to date
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+deallocate prepare stmt;
diff --git a/mysql-test/r/ps_11bugs.result b/mysql-test/r/ps_11bugs.result
index c0d7fe502af..c849c25d646 100644
--- a/mysql-test/r/ps_11bugs.result
+++ b/mysql-test/r/ps_11bugs.result
@@ -116,3 +116,17 @@ execute st_1676 using @arg0, @arg1, @arg2;
cola colb cold
aaaa yyyy R
drop table t1, t2;
+create table t1 (a int primary key);
+insert into t1 values (1);
+explain select * from t1 where 3 in (select (1+1) union select 1);
+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
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
+3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
+select * from t1 where 3 in (select (1+1) union select 1);
+a
+prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)';
+execute st_18492;
+a
+drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 22d59c7bd8f..1a1d6432411 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -299,7 +299,7 @@ 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
-Threads_running 1
+Threads_running 2
prepare stmt4 from ' show variables like ''sql_mode'' ';
execute stmt4;
Variable_name Value
@@ -410,13 +410,10 @@ ERROR HY000: This command is not supported in the prepared statement protocol ye
prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
execute stmt1 ;
prepare stmt1 from ' optimize table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' analyze table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' checksum table t1 ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' repair table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' handler t1 open ';
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index ffe2b4d6409..5ba601bf305 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1777,7 +1777,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -1807,7 +1807,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 707e5ed681f..836fb7b58c2 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -1790,7 +1790,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index 06429f92580..150820d92f0 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1761,7 +1761,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -1791,7 +1791,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index c1002970932..72573ce3294 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1697,7 +1697,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -1727,7 +1727,7 @@ 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 246 3 3 N 33 1 63
+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
@@ -4711,7 +4711,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -4741,7 +4741,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index ea1212addf5..44b4ebf33d4 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL DEFAULT '0',
`param01` bigint(20) DEFAULT NULL,
- `const02` decimal(2,1) unsigned NOT NULL DEFAULT '0.0',
+ `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,
@@ -1790,7 +1790,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index 65cf7c1f88c..543435e4cd9 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `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,
@@ -1790,7 +1790,7 @@ 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 246 3 3 N 33 1 63
+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
diff --git a/mysql-test/r/rpl_bit_npk.result b/mysql-test/r/rpl_bit_npk.result
index 2850e63aabd..9599660f18f 100644
--- a/mysql-test/r/rpl_bit_npk.result
+++ b/mysql-test/r/rpl_bit_npk.result
@@ -56,86 +56,90 @@ INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4
UNLOCK TABLES;
UPDATE test.t1 set x034 = 50 where bit3 = b'000000';
UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0';
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+FROM test.t1
+ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
oSupp sSuppD GSuppDf VNotSupp x034
5 5 3 NULL 1
5 5 3 2 1
-5 5 3 33 1
5 5 3 2 50
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
-SELECT hex(bit1) from test.t1;
+5 5 3 33 1
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
hex(bit1)
-3F
-3F
-0
-2A
0
0
0
0
-SELECT hex(bit2) from test.t1;
-hex(bit2)
-3E
0
2A
3F
+3F
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+hex(bit2)
+0
1
1
1
1
-SELECT hex(bit3) from test.t1;
+2A
+3E
+3F
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
hex(bit3)
-35
-24
-15
0
1
1
1
1
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+15
+24
+35
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+FROM test.t1
+ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
oSupp sSuppD GSuppDf VNotSupp x034
5 5 3 NULL 1
5 5 3 2 1
-5 5 3 33 1
5 5 3 2 50
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
-SELECT hex(bit1) from test.t1;
+5 5 3 33 1
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
hex(bit1)
-3F
-3F
-0
-2A
0
0
0
0
-SELECT hex(bit2) from test.t1;
-hex(bit2)
-3E
0
2A
3F
+3F
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+hex(bit2)
+0
1
1
1
1
-SELECT hex(bit3) from test.t1;
+2A
+3E
+3F
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
hex(bit3)
-35
-24
-15
0
1
1
1
1
+15
+24
+35
CREATE TABLE test.t2 (a INT, b BIT(1));
INSERT INTO test.t2 VALUES (1, b'0');
INSERT INTO test.t2 VALUES (1, b'1');
@@ -144,19 +148,19 @@ CREATE TABLE test.t3 (a INT, b INT);
INSERT INTO test.t3 VALUES (1, NULL);
INSERT INTO test.t3 VALUES (1, 0);
UPDATE test.t3 SET a = 2 WHERE b = 0;
-SELECT a, hex(b) FROM test.t2;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
a hex(b)
1 0
2 1
-SELECT * FROM test.t3;
+SELECT * FROM test.t3 ORDER BY a,b;
a b
1 NULL
2 0
-SELECT a, hex(b) FROM test.t2;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
a hex(b)
1 0
2 1
-SELECT * FROM test.t3;
+SELECT * FROM test.t3 ORDER BY a,b;
a b
1 NULL
2 0
diff --git a/mysql-test/r/rpl_deadlock_innodb.result b/mysql-test/r/rpl_deadlock_innodb.result
index 7d592c2d0cd..b9a23950ed8 100644
--- a/mysql-test/r/rpl_deadlock_innodb.result
+++ b/mysql-test/r/rpl_deadlock_innodb.result
@@ -44,8 +44,39 @@ select * from t2;
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 # # # master-bin.000001 Yes Yes # 0 0 # # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
stop slave;
change master to master_log_pos=536;
begin;
@@ -62,8 +93,39 @@ select * from t2;
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 # # # master-bin.000001 Yes Yes # 0 0 # # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
set global max_relay_log_size=0;
stop slave;
change master to master_log_pos=536;
@@ -82,6 +144,37 @@ select * from t2;
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 # # # master-bin.000001 # Yes # 0 0 # # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
drop table t1,t2,t3,t4;
diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result
index fd711f89222..ec0b3856ae7 100644
--- a/mysql-test/r/rpl_failed_optimize.result
+++ b/mysql-test/r/rpl_failed_optimize.result
@@ -18,3 +18,8 @@ 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
+select * from t1;
+a
+1
+commit;
+drop table t1;
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index 4504ad8e5a7..622b1489f91 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -73,3 +73,61 @@ CREATE TABLE t1 ( a INT UNIQUE );
SET FOREIGN_KEY_CHECKS=0;
INSERT INTO t1 VALUES (1),(1);
Got one of the listed errors
+drop function if exists bug15728;
+drop function if exists bug15728_insert;
+drop table if exists t1, t2;
+create table t1 (
+id int not null auto_increment,
+last_id int,
+primary key (id)
+);
+create function bug15728() returns int(11)
+return last_insert_id();
+insert into t1 (last_id) values (0);
+insert into t1 (last_id) values (last_insert_id());
+insert into t1 (last_id) values (bug15728());
+create table t2 (
+id int not null auto_increment,
+last_id int,
+primary key (id)
+);
+create function bug15728_insert() returns int(11) modifies sql data
+begin
+insert into t2 (last_id) values (bug15728());
+return bug15728();
+end|
+create trigger t1_bi before insert on t1 for each row
+begin
+declare res int;
+select bug15728_insert() into res;
+set NEW.last_id = res;
+end|
+insert into t1 (last_id) values (0);
+drop trigger t1_bi;
+select last_insert_id();
+last_insert_id()
+4
+select bug15728_insert();
+bug15728_insert()
+2
+select last_insert_id();
+last_insert_id()
+4
+insert into t1 (last_id) values (bug15728());
+select last_insert_id();
+last_insert_id()
+5
+select * from t1;
+id last_id
+1 0
+2 1
+3 2
+4 1
+5 4
+select * from t2;
+id last_id
+1 3
+2 4
+drop function bug15728;
+drop function bug15728_insert;
+drop table t1, t2;
diff --git a/mysql-test/r/rpl_loaddatalocal.result b/mysql-test/r/rpl_loaddatalocal.result
index 20e56a62133..bb1b0610aa8 100644
--- a/mysql-test/r/rpl_loaddatalocal.result
+++ b/mysql-test/r/rpl_loaddatalocal.result
@@ -18,12 +18,12 @@ select * into outfile 'MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_out
drop table t1;
create table t1(a int primary key);
load data local infile 'MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
2
3
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
2
diff --git a/mysql-test/r/rpl_ndb_2innodb.result b/mysql-test/r/rpl_ndb_2innodb.result
new file mode 100644
index 00000000000..f8ec4624062
--- /dev/null
+++ b/mysql-test/r/rpl_ndb_2innodb.result
@@ -0,0 +1,855 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+SET storage_engine=ndb;
+--- Doing pre test cleanup ---
+DROP TABLE IF EXISTS t1;
+--- Start test 1 Basic testing ---
+--- Create Table Section ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE,PRIMARY KEY(id));
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+--- Show table on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly --
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 1 Basic testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 2 partition RANGE testing --
+--- Do setup --
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY RANGE (YEAR(t))
+(PARTITION p0 VALUES LESS THAN (1901),
+PARTITION p1 VALUES LESS THAN (1946),
+PARTITION p2 VALUES LESS THAN (1966),
+PARTITION p3 VALUES LESS THAN (1986),
+PARTITION p4 VALUES LESS THAN (2005),
+PARTITION p5 VALUES LESS THAN MAXVALUE);
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = ndbcluster, PARTITION p1 VALUES LESS THAN (1946) ENGINE = ndbcluster, PARTITION p2 VALUES LESS THAN (1966) ENGINE = ndbcluster, PARTITION p3 VALUES LESS THAN (1986) ENGINE = ndbcluster, PARTITION p4 VALUES LESS THAN (2005) ENGINE = ndbcluster, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = ndbcluster)
+--- Show table on slave --
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (1946) ENGINE = InnoDB, PARTITION p2 VALUES LESS THAN (1966) ENGINE = InnoDB, PARTITION p3 VALUES LESS THAN (1986) ENGINE = InnoDB, PARTITION p4 VALUES LESS THAN (2005) ENGINE = InnoDB, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(t,id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = ndbcluster, PARTITION p1 VALUES LESS THAN (1946) ENGINE = ndbcluster, PARTITION p2 VALUES LESS THAN (1966) ENGINE = ndbcluster, PARTITION p3 VALUES LESS THAN (1986) ENGINE = ndbcluster, PARTITION p4 VALUES LESS THAN (2005) ENGINE = ndbcluster, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = ndbcluster)
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (1946) ENGINE = InnoDB, PARTITION p2 VALUES LESS THAN (1966) ENGINE = InnoDB, PARTITION p3 VALUES LESS THAN (1986) ENGINE = InnoDB, PARTITION p4 VALUES LESS THAN (2005) ENGINE = InnoDB, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 2 partition RANGE testing ---
+--- Do Cleanup ---
+DROP TABLE IF EXISTS t1;
+--- Start test 3 partition LIST testing ---
+--- Do setup ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY LIST(id)
+(PARTITION p0 VALUES IN (2, 4),
+PARTITION p1 VALUES IN (42, 142));
+--- Test 3 Alter to add partition ---
+ALTER TABLE t1 ADD PARTITION (PARTITION p2 VALUES IN (412));
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = ndbcluster, PARTITION p1 VALUES IN (42,142) ENGINE = ndbcluster, PARTITION p2 VALUES IN (412) ENGINE = ndbcluster)
+--- Show table on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = InnoDB, PARTITION p1 VALUES IN (42,142) ENGINE = InnoDB, PARTITION p2 VALUES IN (412) ENGINE = InnoDB)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = ndbcluster, PARTITION p1 VALUES IN (42,142) ENGINE = ndbcluster, PARTITION p2 VALUES IN (412) ENGINE = ndbcluster)
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = InnoDB, PARTITION p1 VALUES IN (42,142) ENGINE = InnoDB, PARTITION p2 VALUES IN (412) ENGINE = InnoDB)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 3 partition LIST testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 4 partition HASH testing ---
+--- Do setup ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY HASH( YEAR(t) )
+PARTITIONS 4;
+--- show that tables have been created correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(t,id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 4 partition HASH testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 5 partition by key testing ---
+--- Create Table Section ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE,PRIMARY KEY(id))
+PARTITION BY KEY()
+PARTITIONS 4;
+--- Show that tables on master are ndbcluster tables ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Show that tables on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Make sure that our tables on slave are still right type ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 5 key partition testing ---
+--- Do Cleanup ---
+DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/r/rpl_ndb_2myisam.result b/mysql-test/r/rpl_ndb_2myisam.result
new file mode 100644
index 00000000000..00fb2f5455f
--- /dev/null
+++ b/mysql-test/r/rpl_ndb_2myisam.result
@@ -0,0 +1,855 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+SET storage_engine=ndb;
+--- Doing pre test cleanup ---
+DROP TABLE IF EXISTS t1;
+--- Start test 1 Basic testing ---
+--- Create Table Section ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE,PRIMARY KEY(id));
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+--- Show table on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly --
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 1 Basic testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 2 partition RANGE testing --
+--- Do setup --
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY RANGE (YEAR(t))
+(PARTITION p0 VALUES LESS THAN (1901),
+PARTITION p1 VALUES LESS THAN (1946),
+PARTITION p2 VALUES LESS THAN (1966),
+PARTITION p3 VALUES LESS THAN (1986),
+PARTITION p4 VALUES LESS THAN (2005),
+PARTITION p5 VALUES LESS THAN MAXVALUE);
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = ndbcluster, PARTITION p1 VALUES LESS THAN (1946) ENGINE = ndbcluster, PARTITION p2 VALUES LESS THAN (1966) ENGINE = ndbcluster, PARTITION p3 VALUES LESS THAN (1986) ENGINE = ndbcluster, PARTITION p4 VALUES LESS THAN (2005) ENGINE = ndbcluster, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = ndbcluster)
+--- Show table on slave --
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (1946) ENGINE = MyISAM, PARTITION p2 VALUES LESS THAN (1966) ENGINE = MyISAM, PARTITION p3 VALUES LESS THAN (1986) ENGINE = MyISAM, PARTITION p4 VALUES LESS THAN (2005) ENGINE = MyISAM, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(t,id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = ndbcluster, PARTITION p1 VALUES LESS THAN (1946) ENGINE = ndbcluster, PARTITION p2 VALUES LESS THAN (1966) ENGINE = ndbcluster, PARTITION p3 VALUES LESS THAN (1986) ENGINE = ndbcluster, PARTITION p4 VALUES LESS THAN (2005) ENGINE = ndbcluster, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = ndbcluster)
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (YEAR(t)) (PARTITION p0 VALUES LESS THAN (1901) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (1946) ENGINE = MyISAM, PARTITION p2 VALUES LESS THAN (1966) ENGINE = MyISAM, PARTITION p3 VALUES LESS THAN (1986) ENGINE = MyISAM, PARTITION p4 VALUES LESS THAN (2005) ENGINE = MyISAM, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 2 partition RANGE testing ---
+--- Do Cleanup ---
+DROP TABLE IF EXISTS t1;
+--- Start test 3 partition LIST testing ---
+--- Do setup ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY LIST(id)
+(PARTITION p0 VALUES IN (2, 4),
+PARTITION p1 VALUES IN (42, 142));
+--- Test 3 Alter to add partition ---
+ALTER TABLE t1 ADD PARTITION (PARTITION p2 VALUES IN (412));
+--- Show table on master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = ndbcluster, PARTITION p1 VALUES IN (42,142) ENGINE = ndbcluster, PARTITION p2 VALUES IN (412) ENGINE = ndbcluster)
+--- Show table on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = MyISAM, PARTITION p1 VALUES IN (42,142) ENGINE = MyISAM, PARTITION p2 VALUES IN (412) ENGINE = MyISAM)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = ndbcluster, PARTITION p1 VALUES IN (42,142) ENGINE = ndbcluster, PARTITION p2 VALUES IN (412) ENGINE = ndbcluster)
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY LIST (id) (PARTITION p0 VALUES IN (2,4) ENGINE = MyISAM, PARTITION p1 VALUES IN (42,142) ENGINE = MyISAM, PARTITION p2 VALUES IN (412) ENGINE = MyISAM)
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 3 partition LIST testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 4 partition HASH testing ---
+--- Do setup ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE)
+PARTITION BY HASH( YEAR(t) )
+PARTITIONS 4;
+--- show that tables have been created correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 ADD PRIMARY KEY(t,id);
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date NOT NULL DEFAULT '0000-00-00',
+ PRIMARY KEY (`t`,`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY HASH ( YEAR(t)) PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 4 partition HASH testing ---
+--- Do Cleanup --
+DROP TABLE IF EXISTS t1;
+--- Start test 5 partition by key testing ---
+--- Create Table Section ---
+CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255),
+bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
+f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
+y YEAR, t DATE,PRIMARY KEY(id))
+PARTITION BY KEY()
+PARTITIONS 4;
+--- Show that tables on master are ndbcluster tables ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Show that tables on slave ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned DEFAULT NULL,
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Make sure that our tables on slave are still right type ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` varchar(255) DEFAULT NULL,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- Check that simple Alter statements are replicated correctly ---
+ALTER TABLE t1 MODIFY vc TEXT;
+--- Show the new improved table on the master ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Make sure that our tables on slave are still same engine ---
+--- and that the alter statements replicated correctly ---
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` mediumint(9) NOT NULL,
+ `b1` bit(8) DEFAULT NULL,
+ `vc` text,
+ `bc` char(255) DEFAULT NULL,
+ `d` decimal(10,4) DEFAULT '0.0000',
+ `f` float DEFAULT '0',
+ `total` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `y` year(4) DEFAULT NULL,
+ `t` date DEFAULT NULL,
+ PRIMARY KEY (`id`,`total`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY () PARTITIONS 4
+--- Perform basic operation on master ---
+--- and ensure replicated correctly ---
+"--- Insert into t1 --" as "";
+--- Select from t1 on master ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Select from t1 on slave ---
+select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id;
+id hex(b1) vc bc d f total y t
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14
+--- Update t1 on master --
+UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
+--- Check the update on master ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Check Update on slave ---
+SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412;
+id hex(b1) vc bc d f total y t
+412 0 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2006-02-22
+--- Remove a record from t1 on master ---
+DELETE FROM t1 WHERE id = 42;
+--- Show current count on master for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+--- Show current count on slave for t1 ---
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4
+DELETE FROM t1;
+--- End test 5 key partition testing ---
+--- Do Cleanup ---
+DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/r/rpl_ndb_UUID.result b/mysql-test/r/rpl_ndb_UUID.result
index c768779c49b..422379d4f55 100644
--- a/mysql-test/r/rpl_ndb_UUID.result
+++ b/mysql-test/r/rpl_ndb_UUID.result
@@ -33,7 +33,7 @@ t1 CREATE TABLE `t1` (
`blob_column` longblob,
`vchar_column` varchar(100) DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
DROP PROCEDURE test.p1;
DROP FUNCTION test.fn1;
DROP TABLE test.t1;
diff --git a/mysql-test/r/rpl_ndb_basic.result b/mysql-test/r/rpl_ndb_basic.result
index 40e3384be3b..b23e5f03f27 100644
--- a/mysql-test/r/rpl_ndb_basic.result
+++ b/mysql-test/r/rpl_ndb_basic.result
@@ -122,3 +122,28 @@ select * from t1 order by nid;
nid nom prenom
1 DEAD ABC1
DROP TABLE t1;
+CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+ALTER TABLE t1 ADD c2 INT;
+SELECT * FROM t1 ORDER BY c1;
+c1 c2
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+7 NULL
+8 NULL
+9 NULL
+10 NULL
+ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8;
+ALTER TABLE t1 CHANGE c2 c2 BLOB;
+SELECT * FROM t1 ORDER BY c1 LIMIT 5;
+c1 c2
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/rpl_ndb_dd_advance.result b/mysql-test/r/rpl_ndb_dd_advance.result
index ba89592b532..2cb1cce649b 100644
--- a/mysql-test/r/rpl_ndb_dd_advance.result
+++ b/mysql-test/r/rpl_ndb_dd_advance.result
@@ -69,7 +69,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`,`c3`),
KEY `c5` (`c5`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
**** Show first set of ALTERs on SLAVE ****
SHOW CREATE TABLE t1;
Table Create Table
@@ -82,7 +82,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`,`c3`),
KEY `c5` (`c5`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
**** Second set of alters test 1 ****
ALTER TABLE t1 RENAME t2;
ALTER TABLE t2 DROP INDEX c5;
@@ -101,7 +101,7 @@ t1 CREATE TABLE `t1` (
`c5` double DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
**** Show second set of ALTERs on SLAVE ****
SHOW CREATE TABLE t1;
Table Create Table
@@ -113,7 +113,7 @@ t1 CREATE TABLE `t1` (
`c5` double DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`,`c3`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
**** Third and last set of alters for test1 ****
ALTER TABLE t1 CHANGE c1 c1 DOUBLE;
ALTER TABLE t1 CHANGE c2 c2 DECIMAL(10,2);
@@ -135,7 +135,7 @@ t1 CREATE TABLE `t1` (
`c5` double DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
c1 c2 c3 c5
1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL
@@ -153,7 +153,7 @@ t1 CREATE TABLE `t1` (
`c5` double DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `t1_i` (`c2`)
-) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
SELECT * FROM t1 where c1 = 1;
c1 c2 c3 c5
1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL
diff --git a/mysql-test/r/rpl_openssl.result b/mysql-test/r/rpl_openssl.result
index be9ab29d8b7..4fe02088632 100644
--- a/mysql-test/r/rpl_openssl.result
+++ b/mysql-test/r/rpl_openssl.result
@@ -24,6 +24,7 @@ Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File
stop slave;
change master to master_user='root',master_password='', master_ssl=0;
start slave;
+drop user replssl@localhost;
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
diff --git a/mysql-test/r/rpl_row_log.result b/mysql-test/r/rpl_row_log.result
index 12b573b8bf6..65e9ee9fb9f 100644
--- a/mysql-test/r/rpl_row_log.result
+++ b/mysql-test/r/rpl_row_log.result
@@ -39,6 +39,10 @@ master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
flush logs;
create table t3 (a int)ENGINE=MyISAM;
start slave;
+
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ;
+
+--source include/wait_slave_status.inc
flush logs;
stop slave;
create table t2 (n int)ENGINE=MyISAM;
diff --git a/mysql-test/r/rpl_row_log_innodb.result b/mysql-test/r/rpl_row_log_innodb.result
index 48c79c9ab11..2c89ca5f8ff 100644
--- a/mysql-test/r/rpl_row_log_innodb.result
+++ b/mysql-test/r/rpl_row_log_innodb.result
@@ -41,6 +41,10 @@ master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
flush logs;
create table t3 (a int)ENGINE=InnoDB;
start slave;
+
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ;
+
+--source include/wait_slave_status.inc
flush logs;
stop slave;
create table t2 (n int)ENGINE=InnoDB;
diff --git a/mysql-test/r/rpl_sp004.result b/mysql-test/r/rpl_sp004.result
index dfc672d4cd7..1c0ed3cc50a 100644
--- a/mysql-test/r/rpl_sp004.result
+++ b/mysql-test/r/rpl_sp004.result
@@ -26,25 +26,25 @@ DROP TABLE IF EXISTS test.t2;
INSERT INTO test.t3 VALUES(NULL,11111111.233333,NOW());
END|
CALL test.p1();
-SELECT * FROM test.t1;
+SELECT * FROM test.t1 ORDER BY a;
a
1
2
3
12
-SELECT * FROM test.t2;
+SELECT * FROM test.t2 ORDER BY a;
a
1
2
3
8
-SELECT * FROM test.t1;
+SELECT * FROM test.t1 ORDER BY a;
a
1
2
3
12
-SELECT * FROM test.t2;
+SELECT * FROM test.t2 ORDER BY a;
a
1
2
@@ -62,25 +62,25 @@ t3
CALL test.p1();
Warnings:
Note 1050 Table 't3' already exists
-SELECT * FROM test.t1;
+SELECT * FROM test.t1 ORDER BY a;
a
1
2
3
12
-SELECT * FROM test.t2;
+SELECT * FROM test.t2 ORDER BY a;
a
1
2
3
8
-SELECT * FROM test.t1;
+SELECT * FROM test.t1 ORDER BY a;
a
1
2
3
12
-SELECT * FROM test.t2;
+SELECT * FROM test.t2 ORDER BY a;
a
1
2
diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result
index bf8128d9385..26455b65beb 100644
--- a/mysql-test/r/rpl_sp_effects.result
+++ b/mysql-test/r/rpl_sp_effects.result
@@ -19,24 +19,30 @@ set spv=spv+1;
end while;
end//
call p1();
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+4
+5
+SELECT * FROM t1 ORDER BY a;
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;
+SELECT * FROM t2 ORDER BY a;
a
4
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
a
4
drop procedure p1;
@@ -61,43 +67,58 @@ end//
call p1(f1(1), f1(2));
yes
yes
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
+1
+2
2
+3
+4
+5
5
6
7
8
create table t2(a int);
insert into t2 values (10),(11);
-select a,f1(a) from t2;
+SELECT a,f1(a) FROM t2 ORDER BY a;
a f1(a)
10 11
11 12
insert into t2 select f1(3);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 1
+master: 1
+master: 2
master: 2
+master: 3
+master: 3
+master: 4
+master: 5
master: 5
master: 6
master: 7
master: 8
master: 10
master: 11
-master: 3
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 1
+slave: 1
+slave: 2
slave: 2
+slave: 3
+slave: 3
+slave: 4
+slave: 5
slave: 5
slave: 6
slave: 7
slave: 8
slave: 10
slave: 11
-slave: 3
drop procedure p1;
delete from t1;
delete from t2;
@@ -108,11 +129,11 @@ select * from v1;
f1(a)
2
3
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 1
master: 2
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 1
slave: 2
@@ -123,10 +144,10 @@ set @xx=123;
execute s1 using @xx;
f1(?)
124
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 123
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 123
delete from t1;
@@ -141,18 +162,18 @@ set spv= spv - 10;
end while;
end//
call p1(15);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
-master: 15
-master: 15
master: 6
master: 6
-select 'slave:',a from t1;
+master: 15
+master: 15
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
-slave: 15
-slave: 15
slave: 6
slave: 6
+slave: 15
+slave: 15
drop procedure p1;
drop function f1;
drop table t1,t2;
@@ -187,26 +208,26 @@ f1()
0
set @x=30;
call p1();
-select 'master', a from t1;
+SELECT 'master', a FROM t1 ORDER BY a;
master a
-master 20
master 10
master 11
-master 100
-master 101
+master 20
master 30
master 31
+master 100
+master 101
master 101
master 102
-select 'slave', a from t1;
+SELECT 'slave', a FROM t1 ORDER BY a;
slave a
-slave 20
slave 10
slave 11
-slave 100
-slave 101
+slave 20
slave 30
slave 31
+slave 100
+slave 101
slave 101
slave 102
drop table t1;
diff --git a/mysql-test/r/rpl_stm_log.result b/mysql-test/r/rpl_stm_log.result
index af774c5075f..02a861ceb53 100644
--- a/mysql-test/r/rpl_stm_log.result
+++ b/mysql-test/r/rpl_stm_log.result
@@ -39,6 +39,10 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values (NULL)
flush logs;
create table t3 (a int)ENGINE=MyISAM;
start slave;
+
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ;
+
+--source include/wait_slave_status.inc
flush logs;
stop slave;
create table t2 (n int)ENGINE=MyISAM;
diff --git a/mysql-test/r/rpl_stm_until.result b/mysql-test/r/rpl_stm_until.result
index 11b69f55f82..e8e33b66864 100644
--- a/mysql-test/r/rpl_stm_until.result
+++ b/mysql-test/r/rpl_stm_until.result
@@ -19,9 +19,40 @@ n
2
3
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 780 slave-relay-bin.000004 # master-bin.000001 # No 0 0 323 # Master master-bin.000001 323 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 780
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 323
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-bin.000001
+Until_Log_Pos 323
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
select * from t1;
n
@@ -29,23 +60,116 @@ n
2
3
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 780 slave-relay-bin.000004 # master-bin.000001 # No 0 0 323 # Master master-no-such-bin.000001 291 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 780
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 323
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-no-such-bin.000001
+Until_Log_Pos 291
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
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 780 slave-relay-bin.000004 # master-bin.000001 # No 0 0 612 # Relay slave-relay-bin.000004 746 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 780
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 612
+Relay_Log_Space #
+Until_Condition Relay
+Until_Log_File slave-relay-bin.000004
+Until_Log_Pos 746
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave;
stop slave;
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 780 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 780 # Master master-bin.000001 776 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 780
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 780
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-bin.000001
+Until_Log_Pos 776
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
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;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
index bc5cc262079..01882c683a4 100644
--- a/mysql-test/r/rpl_temporary.result
+++ b/mysql-test/r/rpl_temporary.result
@@ -88,3 +88,23 @@ f
1
drop temporary table t4;
drop table t5;
+set @@session.pseudo_thread_id=100;
+create temporary table t101 (id int);
+create temporary table t102 (id int);
+set @@session.pseudo_thread_id=200;
+create temporary table t201 (id int);
+create temporary table `#sql_not_user_table202` (id int);
+set @@session.pseudo_thread_id=300;
+create temporary table t301 (id int);
+create temporary table t302 (id int);
+create temporary table `#sql_not_user_table303` (id int);
+create table t1(f int);
+insert into t1 values (1);
+select * from t1 /* must be 1 */;
+f
+1
+drop table t1;
+select * from t1;
+a
+1
+drop table t1;
diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result
index b553d37a187..ed0d2782394 100644
--- a/mysql-test/r/rpl_user_variables.result
+++ b/mysql-test/r/rpl_user_variables.result
@@ -78,5 +78,6 @@ abcn1
abcn1n2
abc\def
This is a test
+insert into t1 select * FROM (select @var1 union select @var2) AS t2;
drop table t1;
stop slave;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 9b9f67efeb5..f45e16f66c1 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3390,3 +3390,59 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
DROP TABLE t1,t2;
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = i - 1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+255
+DROP TABLE t1;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, b int, c int, e int, primary key(a,b,c));
+insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C;
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+select 'In next EXPLAIN, B.rows must be exactly 10:' Z;
+Z
+In next EXPLAIN, B.rows must be exactly 10:
+explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
+and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A range PRIMARY PRIMARY 12 NULL 3 Using where
+1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10
+drop table t1, t2;
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
+INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2),
+(3,1), (5,1), (8,9), (2,2), (0,9);
+CREATE TABLE t2 (c int, d int, f int, INDEX(c,f));
+INSERT INTO t2 VALUES
+(1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1),
+(5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1),
+(0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1);
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index a8af5c59b81..5dcb8b2afd6 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -460,7 +460,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) DEFAULT NULL,
- KEY `i` USING HASH (`i`)
+ KEY `i` (`i`) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY USING BTREE (i)) ENGINE=MEMORY;
@@ -468,7 +468,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) DEFAULT NULL,
- KEY `i` USING BTREE (`i`)
+ KEY `i` (`i`) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM;
@@ -484,7 +484,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) DEFAULT NULL,
- KEY `i` USING BTREE (`i`)
+ KEY `i` (`i`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM;
@@ -507,14 +507,14 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) DEFAULT NULL,
- KEY `i` USING BTREE (`i`)
+ KEY `i` (`i`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1
ALTER TABLE t1 ENGINE=MEMORY;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) DEFAULT NULL,
- KEY `i` USING BTREE (`i`)
+ KEY `i` (`i`) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(
@@ -549,8 +549,8 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL,
`c2` int(11) NOT NULL,
- PRIMARY KEY USING HASH (`c1`),
- KEY `c2` USING BTREE (`c2`)
+ PRIMARY KEY (`c1`) USING HASH,
+ KEY `c2` (`c2`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
flush tables;
diff --git a/mysql-test/r/skip_name_resolve.result b/mysql-test/r/skip_name_resolve.result
index 8ef52e75238..855876825ad 100644
--- a/mysql-test/r/skip_name_resolve.result
+++ b/mysql-test/r/skip_name_resolve.result
@@ -10,5 +10,6 @@ user()
#
show processlist;
Id User Host db Command Time State Info
+<id> event_scheduler <host> NULL <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info>
diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result
index c00b09f90e1..d9d5706cded 100644
--- a/mysql-test/r/sp-dynamic.result
+++ b/mysql-test/r/sp-dynamic.result
@@ -286,12 +286,12 @@ 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
+4 analyze table t1 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
+8 optimize table t1 supported
+9 repair table t1 supported
10 describe extended select * from t1 supported
11 help help not supported
12 show databases supported
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 931fa2ee402..fde273c55ee 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -282,9 +282,9 @@ 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
+ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
call p(42, @tmp_y, 43)|
-ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable
+ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
drop procedure p|
create procedure p() begin end|
lock table t1 read|
diff --git a/mysql-test/r/sp-goto.result b/mysql-test/r/sp-goto.result
deleted file mode 100644
index ca560f62318..00000000000
--- a/mysql-test/r/sp-goto.result
+++ /dev/null
@@ -1,205 +0,0 @@
-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-security.result b/mysql-test/r/sp-security.result
index a1e78cd9d7e..af4f1c16c56 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -322,6 +322,7 @@ Warnings:
Warning 1541 The syntax 'SHOW INNODB STATUS' is deprecated and will be removed in MySQL 5.2. Please use 'SHOW ENGINE INNODB STATUS' instead.
GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
DROP DATABASE db_bug7787;
+drop user user_bug7787@localhost;
use test;
---> connection: root
diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result
index c516d7a643f..3cba437e0a6 100644
--- a/mysql-test/r/sp-threads.result
+++ b/mysql-test/r/sp-threads.result
@@ -34,6 +34,7 @@ lock tables t2 write;
call bug9486();
show processlist;
Id User Host db Command Time State Info
+# event_scheduler localhost NULL Connect # Suspended NULL
# 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
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 4468991c0ef..8330c391715 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4858,4 +4858,116 @@ c 2
b 3
a 1
delete from t1|
+drop function if exists bug15728|
+drop table if exists t3|
+create table t3 (
+id int not null auto_increment,
+primary key (id)
+)|
+create function bug15728() returns int(11)
+return last_insert_id()|
+insert into t3 values (0)|
+select last_insert_id()|
+last_insert_id()
+1
+select bug15728()|
+bug15728()
+1
+drop function bug15728|
+drop table t3|
+drop procedure if exists bug18787|
+create procedure bug18787()
+begin
+declare continue handler for sqlexception begin end;
+select no_such_function();
+end|
+call bug18787()|
+no_such_function()
+NULL
+drop procedure bug18787|
+create database bug18344_012345678901|
+use bug18344_012345678901|
+create procedure bug18344() begin end|
+create procedure bug18344_2() begin end|
+create database bug18344_0123456789012|
+use bug18344_0123456789012|
+create procedure bug18344() begin end|
+create procedure bug18344_2() begin end|
+use test|
+select schema_name from information_schema.schemata where
+schema_name like 'bug18344%'|
+schema_name
+bug18344_012345678901
+bug18344_0123456789012
+select routine_name,routine_schema from information_schema.routines where
+routine_schema like 'bug18344%'|
+routine_name routine_schema
+bug18344 bug18344_012345678901
+bug18344_2 bug18344_012345678901
+bug18344 bug18344_0123456789012
+bug18344_2 bug18344_0123456789012
+drop database bug18344_012345678901|
+drop database bug18344_0123456789012|
+select schema_name from information_schema.schemata where
+schema_name like 'bug18344%'|
+schema_name
+select routine_name,routine_schema from information_schema.routines where
+routine_schema like 'bug18344%'|
+routine_name routine_schema
+drop function if exists bug12472|
+create function bug12472() returns int return (select count(*) from t1)|
+create table t3 as select bug12472() as i|
+show create table t3|
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t3|
+i
+0
+drop table t3|
+create view v1 as select bug12472() as j|
+create table t3 as select * from v1|
+show create table t3|
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `j` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t3|
+j
+0
+drop table t3|
+drop view v1|
+drop function bug12472|
+DROP FUNCTION IF EXISTS bug18589_f1|
+DROP PROCEDURE IF EXISTS bug18589_p1|
+DROP PROCEDURE IF EXISTS bug18589_p2|
+CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT
+BEGIN
+RETURN CONCAT(arg, "");
+END|
+CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT)
+BEGIN
+SET ret = CONCAT(arg, "");
+END|
+CREATE PROCEDURE bug18589_p2(arg TEXT)
+BEGIN
+DECLARE v TEXT;
+CALL bug18589_p1(arg, v);
+SELECT v;
+END|
+SELECT bug18589_f1(REPEAT("a", 767))|
+bug18589_f1(REPEAT("a", 767))
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+SET @bug18589_v1 = ""|
+CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)|
+SELECT @bug18589_v1|
+@bug18589_v1
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+CALL bug18589_p2(REPEAT("a", 767))|
+v
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+DROP FUNCTION bug18589_f1|
+DROP PROCEDURE bug18589_p1|
+DROP PROCEDURE bug18589_p2|
drop table t1,t2;
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index d434f5c32ce..c5d60446e0a 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t3;
drop procedure if exists bug4902|
create procedure bug4902()
begin
@@ -17,9 +18,11 @@ show processlist;
end|
call bug4902_2()|
Id User Host db Command Time State Info
+# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist
call bug4902_2()|
Id User Host db Command Time State Info
+# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist
drop procedure bug4902_2|
drop function if exists bug5278|
@@ -204,3 +207,4 @@ drop procedure bug10100pv|
drop procedure bug10100pd|
drop procedure bug10100pc|
drop view v1|
+drop table t3|
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 31b67529f8d..3466282a4b1 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` (
`pseudo` varchar(35) CHARACTER SET latin2 NOT NULL DEFAULT '',
`email` varchar(60) CHARACTER SET latin2 NOT NULL DEFAULT '',
PRIMARY KEY (`a`),
- UNIQUE KEY `email` USING BTREE (`email`)
+ UNIQUE KEY `email` (`email`) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="ansi_quotes";
show variables like 'sql_mode';
@@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" (
"pseudo" varchar(35) CHARACTER SET latin2 NOT NULL DEFAULT '',
"email" varchar(60) CHARACTER SET latin2 NOT NULL DEFAULT '',
PRIMARY KEY ("a"),
- UNIQUE KEY "email" USING BTREE ("email")
+ UNIQUE KEY "email" ("email") USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_table_options";
show variables like 'sql_mode';
@@ -44,7 +44,7 @@ t1 CREATE TABLE `t1` (
`pseudo` varchar(35) CHARACTER SET latin2 NOT NULL DEFAULT '',
`email` varchar(60) CHARACTER SET latin2 NOT NULL DEFAULT '',
PRIMARY KEY (`a`),
- UNIQUE KEY `email` USING BTREE (`email`)
+ UNIQUE KEY `email` (`email`) USING BTREE
)
set @@sql_mode="no_key_options";
show variables like 'sql_mode';
diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result
index 5461e4dd563..e83ade78cf6 100644
--- a/mysql-test/r/status.result
+++ b/mysql-test/r/status.result
@@ -23,3 +23,23 @@ select 1;
show status like 'last_query_cost';
Variable_name Value
Last_query_cost 0.000000
+FLUSH STATUS;
+SHOW STATUS LIKE 'max_used_connections';
+Variable_name Value
+Max_used_connections 2
+SET @save_thread_cache_size=@@thread_cache_size;
+SET GLOBAL thread_cache_size=3;
+SHOW STATUS LIKE 'max_used_connections';
+Variable_name Value
+Max_used_connections 4
+FLUSH STATUS;
+SHOW STATUS LIKE 'max_used_connections';
+Variable_name Value
+Max_used_connections 3
+SHOW STATUS LIKE 'max_used_connections';
+Variable_name Value
+Max_used_connections 4
+SHOW STATUS LIKE 'max_used_connections';
+Variable_name Value
+Max_used_connections 5
+SET GLOBAL thread_cache_size=@save_thread_cache_size;
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index 92f1ba3a23e..5ca185d6abc 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -1288,3 +1288,13 @@ ERROR 22001: Data too long for column 'a' at row 1
select * from t1;
a
drop table t1;
+set sql_mode='traditional';
+create table t1 (date date not null);
+create table t2 select date from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `date` date NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t2,t1;
+set @@sql_mode= @org_mode;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 37823c66de9..71a71a14ad2 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -744,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 `1` having (<cache>(`test`.`t2`.`id`) = <ref_null_helper>(1)) union select 3 AS `3` having (<cache>(`test`.`t2`.`id`) = <ref_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);
@@ -1354,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 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
+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
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`))))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1480,7 +1480,7 @@ Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<e
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
+2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 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 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;
@@ -3169,3 +3169,17 @@ create table t2 (a int, b int);
insert into t2 values (2, 1), (1, 0);
delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1;
drop table t1, t2;
+CREATE TABLE t1 (a INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'where clause'
+CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'where clause'
+SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'IN/ALL/ANY subquery'
+DROP TABLE t1;
+create table t1 (i int, j bigint);
+insert into t1 values (1, 2), (2, 2), (3, 2);
+select * from (select min(i) from t1 where j=(select * from (select min(j) from t1) t2)) t3;
+min(i)
+1
+drop table t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index b3cb244c735..3b24210dd5d 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -40,7 +40,7 @@ t9 CREATE TABLE `t9` (
`b` char(16) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`a`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
+) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
alter table t9 rename t8, add column d int not null;
alter table t8 rename t7;
rename table t7 to t9;
@@ -53,7 +53,7 @@ t9 CREATE TABLE `t9` (
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
+) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
Got one of the listed errors
Got one of the listed errors
Got one of the listed errors
@@ -71,7 +71,7 @@ t9 CREATE TABLE `t9` (
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
+) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
drop database mysqltest;
create table t1 (a int not null) engine=myisam;
show create table t1;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 30cde39531d..b9d3504993c 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -208,7 +208,7 @@ event CREATE TABLE `event` (
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
`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 (`definer`,`db`,`name`)
+ PRIMARY KEY (`db`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
show create table general_log;
Table Create Table
diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result
index 5cc4150e374..fe9e971af2f 100644
--- a/mysql-test/r/timezone2.result
+++ b/mysql-test/r/timezone2.result
@@ -1,4 +1,5 @@
drop table if exists t1, t2;
+drop function if exists f1;
create table t1 (ts timestamp);
set time_zone='+00:00';
select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
@@ -268,3 +269,17 @@ select * from t1;
convert_tz(NULL, NULL, NULL)
NULL
drop table t1;
+create table t1 (ldt datetime, udt datetime);
+create function f1(i datetime) returns datetime
+return convert_tz(i, 'UTC', 'Europe/Moscow');
+create trigger t1_bi before insert on t1 for each row
+set new.udt:= convert_tz(new.ldt, 'Europe/Moscow', 'UTC');
+insert into t1 (ldt) values ('2006-04-19 16:30:00');
+select * from t1;
+ldt udt
+2006-04-19 16:30:00 2006-04-19 12:30:00
+select ldt, f1(udt) as ldt2 from t1;
+ldt ldt2
+2006-04-19 16:30:00 2006-04-19 16:30:00
+drop table t1;
+drop function f1;
diff --git a/mysql-test/r/timezone_grant.result b/mysql-test/r/timezone_grant.result
index 77cfe1c151e..49918038da5 100644
--- a/mysql-test/r/timezone_grant.result
+++ b/mysql-test/r/timezone_grant.result
@@ -1,3 +1,5 @@
+drop tables if exists t1, t2;
+drop view if exists v1;
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\_%';
@@ -59,3 +61,18 @@ delete from mysql.db where user like 'mysqltest\_%';
delete from mysql.tables_priv where user like 'mysqltest\_%';
flush privileges;
drop table t1, t2;
+create table t1 (a int, b datetime);
+insert into t1 values (1, 20010101000000), (2, 20020101000000);
+grant all privileges on test.* to mysqltest_1@localhost;
+create view v1 as select a, convert_tz(b, 'UTC', 'Europe/Moscow') as lb from t1;
+select * from v1;
+a lb
+1 2001-01-01 03:00:00
+2 2002-01-01 03:00:00
+select * from v1, mysql.time_zone;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'time_zone'
+drop view v1;
+create view v1 as select a, convert_tz(b, 'UTC', 'Europe/Moscow') as lb from t1, mysql.time_zone;
+ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for table 'time_zone'
+drop table t1;
+drop user mysqltest_1@localhost;
diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger-grant.result
index 10f1e08eded..fec5d4812d9 100644
--- a/mysql-test/r/trigger-grant.result
+++ b/mysql-test/r/trigger-grant.result
@@ -364,3 +364,87 @@ SELECT @mysqltest_var;
Hello, world!
DROP USER mysqltest_u1@localhost;
DROP DATABASE mysqltest_db1;
+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 DATABASE IF EXISTS mysqltest_db1;
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+CREATE TABLE t1 (i1 INT);
+CREATE TABLE t2 (i1 INT);
+CREATE USER mysqltest_dfn@localhost;
+CREATE USER mysqltest_inv@localhost;
+GRANT EXECUTE, CREATE ROUTINE, TRIGGER ON *.* TO mysqltest_dfn@localhost;
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3;
+CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (7);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+INSERT INTO t2 VALUES (11);
+ERROR 42000: SELECT,UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (13);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+INSERT INTO t2 VALUES (17);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (19);
+INSERT INTO t2 VALUES (23);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (29);
+INSERT INTO t2 VALUES (31);
+REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+INSERT INTO t1 VALUES (41);
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43;
+INSERT INTO t1 VALUES (47);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51;
+INSERT INTO t1 VALUES (53);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+DROP PROCEDURE p1;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t1_bi;
+DROP USER mysqltest_inv@localhost;
+DROP USER mysqltest_dfn@localhost;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP DATABASE mysqltest_db1;
+USE test;
+End of 5.0 tests.
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index ac451c5c34d..24675f2cd66 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -949,6 +949,144 @@ insert into t1 values
create function f2() returns int return (select max(b) from t2);
insert into t2 select a, f2() from t1;
load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1();
-drop table t1;
drop function f1;
drop function f2;
+drop table t1, t2;
+create table t1(i int not null, j int not null, n numeric(15,2), primary key(i,j));
+create table t2(i int not null, n numeric(15,2), primary key(i));
+create trigger t1_ai after insert on t1 for each row
+begin
+declare sn numeric(15,2);
+select sum(n) into sn from t1 where i=new.i;
+replace into t2 values(new.i, sn);
+end|
+insert into t1 values
+(1,1,10.00),(1,2,10.00),(1,3,10.00),(1,4,10.00),(1,5,10.00),
+(1,6,10.00),(1,7,10.00),(1,8,10.00),(1,9,10.00),(1,10,10.00),
+(1,11,10.00),(1,12,10.00),(1,13,10.00),(1,14,10.00),(1,15,10.00);
+select * from t1;
+i j n
+1 1 10.00
+1 2 10.00
+1 3 10.00
+1 4 10.00
+1 5 10.00
+1 6 10.00
+1 7 10.00
+1 8 10.00
+1 9 10.00
+1 10 10.00
+1 11 10.00
+1 12 10.00
+1 13 10.00
+1 14 10.00
+1 15 10.00
+select * from t2;
+i n
+1 150.00
+drop tables t1, t2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+conn_id INT,
+trigger_conn_id INT
+);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+SET NEW.trigger_conn_id = CONNECTION_ID();
+INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
+INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
+SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
+conn_id trigger_conn_id
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i1 INT);
+SET @save_sql_mode=@@sql_mode;
+SET SQL_MODE='';
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+SET @x = 5/0;
+SET SQL_MODE='traditional';
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+SET @x = 5/0;
+SET @x=1;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+@x
+NULL
+SET @x=2;
+UPDATE t1 SET i1 = @x;
+ERROR 22012: Division by 0
+SELECT @x;
+@x
+2
+SET SQL_MODE='';
+SET @x=3;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+@x
+NULL
+SET @x=4;
+UPDATE t1 SET i1 = @x;
+ERROR 22012: Division by 0
+SELECT @x;
+@x
+4
+SET @@sql_mode=@save_sql_mode;
+DROP TRIGGER t1_ai;
+DROP TRIGGER t1_au;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+CREATE TABLE t1 (i1 INT);
+INSERT INTO t1 VALUES (3);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5;
+CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+CALL p1(NEW.i1);
+CALL p2(NEW.i1);
+END//
+UPDATE t1 SET i1 = 11 WHERE i1 = 3;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (13);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+CALL p1(OLD.i1);
+UPDATE t1 SET i1 = 19 WHERE i1 = 13;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (23);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+CALL p1(OLD.i1);
+UPDATE t1 SET i1 = 31 WHERE i1 = 23;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (37);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+UPDATE t1 SET i1 = 43 WHERE i1 = 37;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (47);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+UPDATE t1 SET i1 = 51 WHERE i1 = 47;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+SELECT * FROM t1;
+i1
+35
+13
+23
+43
+51
+DROP TABLE t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index d3c80a7c80e..cfae61d5e91 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -245,22 +245,22 @@ show warnings;
Level Code Message
desc t1;
Field Type Null Key Default Extra
-x decimal(21,2) unsigned NO 0.00
+x decimal(21,2) NO 0.00
drop table t1;
create table t1 select 0.0 x;
desc t1;
Field Type Null Key Default Extra
-x decimal(2,1) unsigned NO 0.0
+x decimal(2,1) NO 0.0
create table t2 select 105213674794682365.00 y;
desc t2;
Field Type Null Key Default Extra
-y decimal(20,2) unsigned NO 0.00
+y decimal(20,2) NO 0.00
create table t3 select x+y a from t1,t2;
show warnings;
Level Code Message
desc t3;
Field Type Null Key Default Extra
-a decimal(21,2) unsigned NO 0.00
+a decimal(21,2) NO 0.00
drop table t1,t2,t3;
create table t1 (s1 float(0,2));
ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1').
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index f96d5e383f4..702b589c911 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -68,10 +68,10 @@ 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) unsigned DEFAULT NULL,
- `nullif(1.1, 1.2)` decimal(2,1) unsigned DEFAULT NULL,
- `nullif(1.1, 0.11e1)` decimal(2,1) unsigned DEFAULT NULL,
- `nullif(1.0, 1)` decimal(2,1) unsigned DEFAULT NULL,
+ `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
@@ -174,9 +174,9 @@ create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(-
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `round(15.4,-1)` decimal(3,0) unsigned NOT NULL DEFAULT '0',
+ `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(2,1) NOT NULL DEFAULT '0.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;
@@ -771,7 +771,7 @@ create table t1 as select 0.5;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `0.5` decimal(2,1) unsigned NOT NULL DEFAULT '0.0'
+ `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);
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index 0ba8916f5b1..ba401a22945 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -241,7 +241,7 @@ Field Type Collation Null Key Default Extra Privileges Comment
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 #
+short smallint(6) NULL NO #
medium mediumint(8) NULL NO 0 #
long_int int(11) NULL NO 0 #
longlong bigint(13) NULL NO 0 #
@@ -259,7 +259,7 @@ 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 NO #
-options enum('one','two','tree') latin1_swedish_ci NO one #
+options enum('one','two','tree') latin1_swedish_ci NO #
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)));
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index 1b5f59c038a..01aa8539262 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -1,15 +1,15 @@
drop table if exists t1;
-CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
-CREATE FUNCTION myfunc_double RETURNS REAL SONAME 'udf_example.so';
-CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME 'udf_example.so';
+CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
ERROR HY000: Can't find symbol 'myfunc_nonexist' in library
-CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME 'udf_example.so';
-CREATE FUNCTION sequence RETURNS INTEGER SONAME "udf_example.so";
-CREATE FUNCTION lookup RETURNS STRING SONAME 'udf_example.so';
+CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION sequence RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION lookup RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
CREATE FUNCTION reverse_lookup
-RETURNS STRING SONAME 'udf_example.so';
+RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
CREATE AGGREGATE FUNCTION avgcost
-RETURNS REAL SONAME 'udf_example.so';
+RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
select myfunc_double();
ERROR HY000: myfunc_double must have at least one argument
select myfunc_double(1);
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 8f2b89c18fd..9c3fdf0d8d2 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -215,9 +215,6 @@ select @@version;
select @@global.version;
@@global.version
#
-select @@session.VERSION;
-@@session.VERSION
-#
set @first_var= NULL;
create table t1 select @first_var;
show create table t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ec8a715de1b..e4b3fc2c2e2 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1,4 +1,31 @@
drop table if exists t1,t2;
+set @my_binlog_cache_size =@@global.binlog_cache_size;
+set @my_connect_timeout =@@global.connect_timeout;
+set @my_delayed_insert_timeout =@@global.delayed_insert_timeout;
+set @my_delayed_queue_size =@@global.delayed_queue_size;
+set @my_flush =@@global.flush;
+set @my_flush_time =@@global.flush_time;
+set @my_key_buffer_size =@@global.key_buffer_size;
+set @my_max_binlog_cache_size =@@global.max_binlog_cache_size;
+set @my_max_binlog_size =@@global.max_binlog_size;
+set @my_max_connect_errors =@@global.max_connect_errors;
+set @my_max_delayed_threads =@@global.max_delayed_threads;
+set @my_max_heap_table_size =@@global.max_heap_table_size;
+set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
+set @my_max_join_size =@@global.max_join_size;
+set @my_max_user_connections =@@global.max_user_connections;
+set @my_max_write_lock_count =@@global.max_write_lock_count;
+set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
+set @my_net_buffer_length =@@global.net_buffer_length;
+set @my_net_write_timeout =@@global.net_write_timeout;
+set @my_net_read_timeout =@@global.net_read_timeout;
+set @my_query_cache_limit =@@global.query_cache_limit;
+set @my_query_cache_type =@@global.query_cache_type;
+set @my_rpl_recovery_rank =@@global.rpl_recovery_rank;
+set @my_server_id =@@global.server_id;
+set @my_slow_launch_time =@@global.slow_launch_time;
+set @my_storage_engine =@@global.storage_engine;
+set @my_thread_cache_size =@@global.thread_cache_size;
set @`test`=1;
select @test, @`test`, @TEST, @`TEST`, @"teSt";
@test @`test` @TEST @`TEST` @"teSt"
@@ -275,7 +302,7 @@ ERROR HY000: Variable 'autocommit' is a SESSION variable and can't be used with
select @@global.timestamp;
ERROR HY000: Variable 'timestamp' is a SESSION variable
set @@version='';
-ERROR HY000: Unknown system variable 'version'
+ERROR HY000: Variable 'version' is a read only variable
set @@concurrent_insert=1;
ERROR HY000: Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL
set @@global.sql_auto_is_null=1;
@@ -384,6 +411,7 @@ select @@sql_max_join_size,@@max_join_size;
set sql_quote_show_create=1;
set sql_safe_updates=1;
set sql_select_limit=1;
+set sql_select_limit=default;
set sql_warnings=1;
set global table_open_cache=100;
set storage_engine=myisam;
@@ -584,3 +612,86 @@ set @@global.character_set_filesystem=default;
select @@global.character_set_filesystem;
@@global.character_set_filesystem
binary
+set @old_sql_big_selects = @@sql_big_selects;
+set @@sql_big_selects = 1;
+show variables like 'sql_big_selects';
+Variable_name Value
+sql_big_selects ON
+set @@sql_big_selects = @old_sql_big_selects;
+set @@sql_notes = 0, @@sql_warnings = 0;
+show variables like 'sql_notes';
+Variable_name Value
+sql_notes OFF
+show variables like 'sql_warnings';
+Variable_name Value
+sql_warnings OFF
+set @@sql_notes = 1, @@sql_warnings = 1;
+show variables like 'sql_notes';
+Variable_name Value
+sql_notes ON
+show variables like 'sql_warnings';
+Variable_name Value
+sql_warnings ON
+select @@system_time_zone;
+@@system_time_zone
+#
+select @@version, @@version_comment, @@version_compile_machine,
+@@version_compile_os;
+@@version @@version_comment @@version_compile_machine @@version_compile_os
+# # # #
+select @@basedir, @@datadir, @@tmpdir;
+@@basedir @@datadir @@tmpdir
+# # #
+show variables like 'basedir';
+Variable_name Value
+basedir #
+show variables like 'datadir';
+Variable_name Value
+datadir #
+show variables like 'tmpdir';
+Variable_name Value
+tmpdir #
+select @@ssl_ca, @@ssl_capath, @@ssl_cert, @@ssl_cipher, @@ssl_key;
+@@ssl_ca @@ssl_capath @@ssl_cert @@ssl_cipher @@ssl_key
+# # # # #
+show variables like 'ssl%';
+Variable_name Value
+ssl_ca #
+ssl_capath #
+ssl_cert #
+ssl_cipher #
+ssl_key #
+select @@log_queries_not_using_indexes;
+@@log_queries_not_using_indexes
+0
+show variables like 'log_queries_not_using_indexes';
+Variable_name Value
+log_queries_not_using_indexes OFF
+End of 5.0 tests
+set global binlog_cache_size =@my_binlog_cache_size;
+set global connect_timeout =@my_connect_timeout;
+set global delayed_insert_timeout =@my_delayed_insert_timeout;
+set global delayed_queue_size =@my_delayed_queue_size;
+set global flush =@my_flush;
+set global flush_time =@my_flush_time;
+set global key_buffer_size =@my_key_buffer_size;
+set global max_binlog_cache_size =default;
+set global max_binlog_size =@my_max_binlog_size;
+set global max_connect_errors =@my_max_connect_errors;
+set global max_delayed_threads =@my_max_delayed_threads;
+set global max_heap_table_size =@my_max_heap_table_size;
+set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
+set global max_join_size =@my_max_join_size;
+set global max_user_connections =@my_max_user_connections;
+set global max_write_lock_count =@my_max_write_lock_count;
+set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
+set global net_buffer_length =@my_net_buffer_length;
+set global net_write_timeout =@my_net_write_timeout;
+set global net_read_timeout =@my_net_read_timeout;
+set global query_cache_limit =@my_query_cache_limit;
+set global query_cache_type =@my_query_cache_type;
+set global rpl_recovery_rank =@my_rpl_recovery_rank;
+set global server_id =@my_server_id;
+set global slow_launch_time =@my_slow_launch_time;
+set global storage_engine =@my_storage_engine;
+set global thread_cache_size =@my_thread_cache_size;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 0b6ebe9dd89..10a9ac87748 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -706,7 +706,7 @@ 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`)
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `t2`.`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`;
@@ -2600,3 +2600,139 @@ id td
5 2005-01-04
DROP VIEW v1;
DROP TABLE t1;
+create table t1 (a int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+drop table t1;
+rename table v2 to t1;
+select * from v1;
+ERROR HY000: `test`.`v1` contains view recursion
+drop view t1, v1;
+create table t1 (a int);
+create function f1() returns int
+begin
+declare mx int;
+select max(a) from t1 into mx;
+return mx;
+end//
+create view v1 as select f1() as a;
+create view v2 as select * from v1;
+drop table t1;
+rename table v2 to t1;
+select * from v1;
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+drop function f1;
+drop view t1, v1;
+create table t1 (dt datetime);
+insert into t1 values (20040101000000), (20050101000000), (20060101000000);
+create view v1 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from t1;
+select * from v1;
+ldt
+2004-01-01 03:00:00
+2005-01-01 03:00:00
+2006-01-01 03:00:00
+drop view v1;
+create view v1 as select * from t1 where convert_tz(dt, 'UTC', 'Europe/Moscow') >= 20050101000000;
+select * from v1;
+dt
+2005-01-01 00:00:00
+2006-01-01 00:00:00
+create view v2 as select * from v1 where dt < 20060101000000;
+select * from v2;
+dt
+2005-01-01 00:00:00
+drop view v2;
+create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1;
+select * from v2;
+ldt
+2005-01-01 03:00:00
+2006-01-01 03:00:00
+drop view v1, v2;
+drop table t1;
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime);
+CREATE VIEW v1 AS
+SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*)
+FROM t1 GROUP BY id, t;
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`id` AS `id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second) AS `t`,count(0) AS `COUNT(*)` from `t1` group by `t1`.`id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second)
+SELECT * FROM v1;
+id t COUNT(*)
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (i INT, j BIGINT);
+INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
+CREATE VIEW v1 AS SELECT MIN(j) AS j FROM t1;
+CREATE VIEW v2 AS SELECT MIN(i) FROM t1 WHERE j = ( SELECT * FROM v1 );
+SELECT * FROM v2;
+MIN(i)
+1
+DROP VIEW v2, v1;
+DROP TABLE t1;
+CREATE TABLE t1(
+fName varchar(25) NOT NULL,
+lName varchar(25) NOT NULL,
+DOB date NOT NULL,
+uID int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY);
+INSERT INTO t1(fName, lName, DOB) VALUES
+('Hank', 'Hill', '1964-09-29'),
+('Tom', 'Adams', '1908-02-14'),
+('Homer', 'Simpson', '1968-03-05');
+CREATE VIEW v1 AS
+SELECT (year(now())-year(DOB)) AS Age
+FROM t1 HAVING Age < 75;
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache (year(now()) - year(`t1`.`DOB`)) AS `Age` from `t1` having (`Age` < 75)
+SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75;
+Age
+42
+38
+SELECT * FROM v1;
+Age
+42
+38
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx');
+INSERT INTO t1(id) VALUES (1), (2), (3), (4);
+INSERT INTO t1 VALUES (5,'yyy'), (6,'yyy');
+SELECT * FROM t1;
+id a
+1 xxx
+2 xxx
+3 xxx
+4 xxx
+5 yyy
+6 yyy
+CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
+SELECT * FROM v1;
+a m
+xxx 1
+yyy 5
+CREATE TABLE t2 SELECT * FROM v1;
+INSERT INTO t2(m) VALUES (0);
+SELECT * FROM t2;
+a m
+xxx 1
+yyy 5
+xxx 0
+DROP VIEW v1;
+DROP TABLE t1,t2;
+CREATE TABLE t1 (id int PRIMARY KEY, e ENUM('a','b') NOT NULL DEFAULT 'b');
+INSERT INTO t1(id) VALUES (1), (2), (3);
+INSERT INTO t1 VALUES (4,'a');
+SELECT * FROM t1;
+id e
+1 b
+2 b
+3 b
+4 a
+CREATE VIEW v1(m, e) AS SELECT MIN(id), e FROM t1 GROUP BY e;
+CREATE TABLE t2 SELECT * FROM v1;
+SELECT * FROM t2;
+m e
+4 a
+1 b
+DROP VIEW v1;
+DROP TABLE IF EXISTS t1,t2;
diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result
index 61dd1390a6a..06dc2f3d78a 100644
--- a/mysql-test/r/xml.result
+++ b/mysql-test/r/xml.result
@@ -665,3 +665,12 @@ CALL p2();
EXTRACTVALUE(p,'/Ñ/r')
A
DROP PROCEDURE p2;
+select extractValue('<ns:element xmlns:ns="myns"/>','count(ns:element)');
+extractValue('<ns:element xmlns:ns="myns"/>','count(ns:element)')
+1
+select extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element');
+extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element')
+a
+select extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element/@xmlns:ns');
+extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element/@xmlns:ns')
+myns
diff --git a/mysql-test/std_data/cacert.pem b/mysql-test/std_data/cacert.pem
index a63dae57767..b445e77d7c4 100644
--- a/mysql-test/std_data/cacert.pem
+++ b/mysql-test/std_data/cacert.pem
@@ -1,21 +1,17 @@
-----BEGIN CERTIFICATE-----
-MIIDcTCCAtqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux
-EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB
-YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0
-Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYxNDE2WhcNMTMw
-OTA5MTYxNDE2WjCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAP
-BgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9w
-ZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNx
-bC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKrT7zp5tp5djXp+TEQs
-5ZEds1XUglp/EQUQ1FMMb1Xe6gqJsQ62O+jsUe0nrUjXBrUCUy49k6mcnmQtZREj
-l1pWKmzx1fgcYpxTwxaY7IKB2jik5IWprhVPmSQ+AWss43oolXMZWR+csKehqm3j
-+YNZc9NsR4ydE71l0VEtJEQvAgMBAAGjgegwgeUwHQYDVR0OBBYEFIiYZdnz8osD
-HWZgYSP6rXNt02iSMIG1BgNVHSMEga0wgaqAFIiYZdnz8osDHWZgYSP6rXNt02iS
-oYGOpIGLMIGIMQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UE
-ChMITXlTUUwgQUIxITAfBgNVBAMTGEFic3RyYWN0IE15U1FMIERldmVsb3BlcjEx
-MC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNv
-bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAGIL22MCIU/0sKDp
-pZIhoabvNVDTfuhtene+WBCrzCzGXPZjB4+b/KAJJNvOR4zi43Kk7euu+PENs9M7
-nKpInMdhvT1RcCnUHJ3jBCvDDzXab2msqn3rxhwetWWbfE0OeEn/PoQcwiZCe7x5
-h+Zz+oUbvsEe4DjtDVgG4UH9nSSS
+MIICrTCCAhagAwIBAgIJAIAO/Ybiptv1MA0GCSqGSIb3DQEBBAUAMEQxCzAJBgNV
+BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYD
+VQQKEwhNeVNRTCBBQjAeFw0wNjA1MDMwODQ4NTRaFw0wOTAxMjcwODQ4NTRaMEQx
+CzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxh
+MREwDwYDVQQKEwhNeVNRTCBBQjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
++C46EQl1u7tQ6gb9eqc8V079gr8YmDPCEqtjO8bCIbchpjOpDITx0WZz36Sn9E72
+GPJwNip4FxLaPRIA3xNQHM5cE5U53qznlRx1Fc4O3hcWCvyCqNDl/vzPAh3pI6Bl
+Ku9hfHXpp93W812smVPe9haShEXGgbEPYGzvOfVdu/MCAwEAAaOBpjCBozAdBgNV
+HQ4EFgQUjIy/6OCTmqtPHBFha6/qzVk3yTcwdAYDVR0jBG0wa4AUjIy/6OCTmqtP
+HBFha6/qzVk3yTehSKRGMEQxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxh
+MRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQoIJAIAO/Ybiptv1
+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEA8lD9zyB820Oq1aj7ZafX
+De/hbdt9RIl2tzgw2K3r1KZGdXJVL0vSt5fZ51Nq9lg7OPJy3iXf+caBJEp0IJpB
+uf4Gfr6zfXw+UlY6ZthRtHQHoXKcbskECjH5/ps/Uaa+dpVQ9O+Ii1rPzmgo6ztM
+s+xZ46ESBt4WiHXm8kwbU9Y=
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/client-cert.pem b/mysql-test/std_data/client-cert.pem
index 4c81162c911..fdd5c86a23f 100644
--- a/mysql-test/std_data/client-cert.pem
+++ b/mysql-test/std_data/client-cert.pem
@@ -1,67 +1,42 @@
Certificate:
Data:
- Version: 3 (0x2)
+ Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
- Issuer: C=SE, L=Uppsala, O=MySQL AB, CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com
+ Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
Validity
- Not Before: Sep 12 16:21:19 2003 GMT
- Not After : Sep 9 16:21:19 2013 GMT
- Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Client/Email=abstract.mysql.developer@mysql.com
+ Not Before: May 3 08:55:39 2006 GMT
+ Not After : Jan 27 08:55:39 2009 GMT
+ Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c4:03:0a:ee:e3:b1:12:fc:ee:b4:19:f4:e1:60:
- 1d:e0:28:c3:96:2d:df:82:69:cd:74:7c:54:58:d0:
- ae:b3:59:3f:0c:19:1c:99:10:a6:12:c9:cf:3a:64:
- 05:43:8e:bf:d2:65:36:80:91:0b:65:b0:27:26:38:
- c9:23:d8:36:a2:4a:f0:f7:c0:2f:68:38:70:01:27:
- 29:ff:b2:c5:52:e1:6b:f1:c8:d7:c3:5c:ee:f0:37:
- 6c:2a:9b:96:1a:05:9e:eb:33:a2:39:5a:77:66:62:
- 27:75:1f:2f:6f:38:da:e5:9f:78:af:ca:6b:22:3f:
- 57:2b:bc:a6:8f:47:d1:99:6f
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:d8:db:68:28:49:84:4d:d6:0f:5c:bc:3d:9a:ab:
+ 70:d5:3e:f5:b5:17:ba:ef:e1:f8:87:54:30:22:1f:
+ 81:07:bf:f9:24:7f:8a:54:10:e9:5f:e6:99:50:04:
+ d4:3b:55:a9:f1:52:ad:12:2b:5a:da:5c:be:8c:3e:
+ 5b:9e:b0:5a:19
Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- 80:81:A9:22:EB:AB:D6:CA:7E:3F:8D:BB:D1:AC:2A:F4:87:9D:13:29
- X509v3 Authority Key Identifier:
- keyid:88:98:65:D9:F3:F2:8B:03:1D:66:60:61:23:FA:AD:73:6D:D3:68:92
- DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com
- serial:00
-
Signature Algorithm: md5WithRSAEncryption
- 86:17:1c:f3:9f:10:1b:75:47:03:ca:54:ea:ef:f7:15:54:8d:
- 8f:58:c9:64:7d:de:2e:bf:ea:a6:5d:72:56:c9:81:be:bb:1c:
- 78:a5:91:d6:f8:77:df:9d:d2:cb:94:d9:06:61:4f:05:21:22:
- 2a:ea:9e:c3:8b:4d:fe:94:c7:98:61:cd:7e:88:19:c9:92:01:
- 1f:10:5b:c6:16:95:99:9b:32:01:3a:89:df:fa:0a:89:ac:fa:
- b5:40:55:7a:ca:0a:bd:5d:8b:06:d8:7e:e1:44:8c:70:c8:63:
- c7:77:6a:37:3d:a4:ac:57:dc:00:c1:c1:f3:72:17:5b:50:95:
- ee:b7
+ 07:57:bf:07:92:c2:8e:86:24:6b:0a:bf:e5:31:21:44:c3:60:
+ 02:a6:ac:9e:f7:db:7a:6e:fc:4f:d4:7b:54:18:80:47:d2:4a:
+ 63:0e:e3:f8:af:6e:58:e3:97:5a:2b:82:5d:76:20:d1:33:a0:
+ f5:43:a1:d1:51:f4:ca:c8:b3:1a:66:4e:0e:55:df:d2:e8:fa:
+ 83:18:42:f5:ec:66:40:f0:39:e8:f9:d7:cf:f6:dd:e4:7b:69:
+ dd:0c:92:d8:52:95:43:6f:29:3d:f0:8d:4c:dd:52:ea:6b:a0:
+ 39:0f:dc:59:a7:5c:37:6b:8b:05:44:b7:69:ea:a3:58:e0:4e:
+ ce:d6
-----BEGIN CERTIFICATE-----
-MIIDkTCCAvqgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux
-EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB
-YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0
-Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMTE5WhcNMTMw
-OTA5MTYyMTE5WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G
-A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIENsaWVudDExMC8GCSqGSIb3
-DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEAxAMK7uOxEvzutBn04WAd4CjDli3fgmnNdHxU
-WNCus1k/DBkcmRCmEsnPOmQFQ46/0mU2gJELZbAnJjjJI9g2okrw98AvaDhwAScp
-/7LFUuFr8cjXw1zu8DdsKpuWGgWe6zOiOVp3ZmIndR8vbzja5Z94r8prIj9XK7ym
-j0fRmW8CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w
-ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSAgaki66vWyn4/
-jbvRrCr0h50TKTCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB
-jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT
-CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv
-BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C
-AQAwDQYJKoZIhvcNAQEEBQADgYEAhhcc858QG3VHA8pU6u/3FVSNj1jJZH3eLr/q
-pl1yVsmBvrsceKWR1vh3353Sy5TZBmFPBSEiKuqew4tN/pTHmGHNfogZyZIBHxBb
-xhaVmZsyATqJ3/oKiaz6tUBVesoKvV2LBth+4USMcMhjx3dqNz2krFfcAMHB83IX
-W1CV7rc=
+MIIB5jCCAU8CAQEwDQYJKoZIhvcNAQEEBQAwRDELMAkGA1UEBhMCU0UxEDAOBgNV
+BAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFC
+MB4XDTA2MDUwMzA4NTUzOVoXDTA5MDEyNzA4NTUzOVowdzELMAkGA1UEBhMCU0Ux
+EDAOBgNVBAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15
+U1FMIEFCMTEwLwYJKoZIhvcNAQkBFiJhYnN0cmFjdC5teXNxbC5kZXZlbG9wZXJA
+bXlzcWwuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANjbaChJhE3WD1y8PZqr
+cNU+9bUXuu/h+IdUMCIfgQe/+SR/ilQQ6V/mmVAE1DtVqfFSrRIrWtpcvow+W56w
+WhkCAwEAATANBgkqhkiG9w0BAQQFAAOBgQAHV78HksKOhiRrCr/lMSFEw2ACpqye
+99t6bvxP1HtUGIBH0kpjDuP4r25Y45daK4JddiDRM6D1Q6HRUfTKyLMaZk4OVd/S
+6PqDGEL17GZA8Dno+dfP9t3ke2ndDJLYUpVDbyk98I1M3VLqa6A5D9xZp1w3a4sF
+RLdp6qNY4E7O1g==
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/client-key.pem b/mysql-test/std_data/client-key.pem
index 58fa805e620..22f8e23ab2a 100644
--- a/mysql-test/std_data/client-key.pem
+++ b/mysql-test/std_data/client-key.pem
@@ -1,15 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDEAwru47ES/O60GfThYB3gKMOWLd+Cac10fFRY0K6zWT8MGRyZ
-EKYSyc86ZAVDjr/SZTaAkQtlsCcmOMkj2DaiSvD3wC9oOHABJyn/ssVS4WvxyNfD
-XO7wN2wqm5YaBZ7rM6I5WndmYid1Hy9vONrln3ivymsiP1crvKaPR9GZbwIDAQAB
-AoGAcR7IaoGhKbIrGGl6d67+zuT3q24h9aOV3Mn7653TlNHGnvbHGFcRYPpyy+H5
-X7m8XnHm+F+80hzNGzPecP9Q12oPOyoZgeQn6bTK73OFkNcX7FAkNdyH4xVhf2aK
-YOzTcQfq3gRCqXtVIg4qBShTMjJLE31R8H430Or62XmJgFECQQDjP+Kz+ecQwuTB
-HADLm+GQgceIB1kLgdQoZ3deUxGvqtVImuDRViSM0F2srfJ4GfkEDhc27UI5f6ir
-ZTOw4ww7AkEA3M9wCPgWNtbOXbYjaNA0IzHcjMDxQDVvJAmb3EiZlKQp4EfrESxR
-ly/u08TyfwrK6q5WS7xE0ad8+95G1af4XQJBAI9+3ME20SB1YItMCniHYwSj3oHX
-2fN5NKWax/Zoz+c0IV+qZMHq+kNso2oRoOUTyXk1CJWndcTnBnPMALr2c9cCQQCZ
-VL7Cq6uZVx6kemcqUHH0AprZbt3YLYLI7pc5p3xmeHzPzoEQQstBhjp8+aU+zPrN
-blRkcQ8E2x5yNA7SLLrNAkAhzkA+EK8hc0f9W3ncy+py0Rn0i5Ay0N3T715vkThf
-CfOHE3L91dLlmYpL5xVqOpugY/2sHyxwctv97DgS6tHZ
+MIIBOgIBAAJBANjbaChJhE3WD1y8PZqrcNU+9bUXuu/h+IdUMCIfgQe/+SR/ilQQ
+6V/mmVAE1DtVqfFSrRIrWtpcvow+W56wWhkCAwEAAQJAK27WT6tZylUjQomZNQ89
+TBiOEbUtBbqWklQ0R8FTkH9uKV+8KYQ+k+tMkoAEGFfChB0YfofNQ2KZYWWw4yOB
+WQIhAPXXDQt73aou10s+cmKM3C3WzLmIZtrvm9wNBXWDGxgTAiEA4dG4cXrZfa1M
+TTbjzNU1/Jf50/M8SvZDWMPQWxJ8oqMCIH6zBpYUkHlVCsBMvsbrsc4uFfTIx7mu
+I7WVQGr/1sbhAiBf4uFirjtztgZUMx5/d3k5DH80lG/hlLf8FQl/4lWx6QIhAPHw
+CXfPUbUFl4r/i9Br5+exGol50qX4F3aP5Sh5EnZT
-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1-0.1.Data b/mysql-test/std_data/ndb_backup50/BACKUP-1-0.1.Data
new file mode 100644
index 00000000000..32494d5a1e7
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1-0.1.Data
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1-0.2.Data b/mysql-test/std_data/ndb_backup50/BACKUP-1-0.2.Data
new file mode 100644
index 00000000000..2141fb0a6e4
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1-0.2.Data
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1.1.ctl b/mysql-test/std_data/ndb_backup50/BACKUP-1.1.ctl
new file mode 100644
index 00000000000..cbe548e0ca5
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1.1.ctl
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1.1.log b/mysql-test/std_data/ndb_backup50/BACKUP-1.1.log
new file mode 100644
index 00000000000..e4e114d4b46
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1.1.log
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1.2.ctl b/mysql-test/std_data/ndb_backup50/BACKUP-1.2.ctl
new file mode 100644
index 00000000000..cbe548e0ca5
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1.2.ctl
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup50/BACKUP-1.2.log b/mysql-test/std_data/ndb_backup50/BACKUP-1.2.log
new file mode 100644
index 00000000000..a1c89b7015c
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup50/BACKUP-1.2.log
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1-0.1.Data b/mysql-test/std_data/ndb_backup51/BACKUP-1-0.1.Data
new file mode 100644
index 00000000000..2407d1f261b
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1-0.1.Data
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1-0.2.Data b/mysql-test/std_data/ndb_backup51/BACKUP-1-0.2.Data
new file mode 100644
index 00000000000..f21e9886523
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1-0.2.Data
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1.1.ctl b/mysql-test/std_data/ndb_backup51/BACKUP-1.1.ctl
new file mode 100644
index 00000000000..99e2f297693
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1.1.ctl
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1.1.log b/mysql-test/std_data/ndb_backup51/BACKUP-1.1.log
new file mode 100644
index 00000000000..4448cd98c04
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1.1.log
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1.2.ctl b/mysql-test/std_data/ndb_backup51/BACKUP-1.2.ctl
new file mode 100644
index 00000000000..99e2f297693
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1.2.ctl
Binary files differ
diff --git a/mysql-test/std_data/ndb_backup51/BACKUP-1.2.log b/mysql-test/std_data/ndb_backup51/BACKUP-1.2.log
new file mode 100644
index 00000000000..3be69891402
--- /dev/null
+++ b/mysql-test/std_data/ndb_backup51/BACKUP-1.2.log
Binary files differ
diff --git a/mysql-test/std_data/server-cert.pem b/mysql-test/std_data/server-cert.pem
index debf7026e3c..f420b4f3124 100644
--- a/mysql-test/std_data/server-cert.pem
+++ b/mysql-test/std_data/server-cert.pem
@@ -1,67 +1,42 @@
Certificate:
Data:
- Version: 3 (0x2)
- Serial Number: 2 (0x2)
+ Version: 1 (0x0)
+ Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
- Issuer: C=SE, L=Uppsala, O=MySQL AB, CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com
+ Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
Validity
- Not Before: Sep 12 16:22:06 2003 GMT
- Not After : Sep 9 16:22:06 2013 GMT
- Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Server/Email=abstract.mysql.developer@mysql.com
+ Not Before: May 3 08:54:13 2006 GMT
+ Not After : Jan 27 08:54:13 2009 GMT
+ Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:e9:86:7a:55:84:88:4c:be:a4:f8:92:73:30:12:
- 49:0b:7a:85:87:39:34:39:0d:7d:0b:8d:18:c2:17:
- 95:13:52:d2:3f:55:10:57:c8:3f:5a:f5:b2:fa:8b:
- d0:67:49:cc:aa:82:fc:9f:ce:00:b4:73:f3:36:d2:
- 3a:d3:c2:b0:0e:14:c3:d4:b2:21:74:a1:f0:31:81:
- 60:87:98:73:5c:10:c1:b1:1a:4d:f1:f3:b0:98:3f:
- f0:d7:97:9b:2b:fd:d5:21:79:b2:2f:eb:64:15:c9:
- 9b:9d:fc:9e:2d:d4:f8:04:5b:ea:a9:75:4b:42:c3:
- 3d:0e:4d:2a:a8:b8:ca:99:8d
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:d9:fd:da:b3:fb:7c:e0:b0:03:be:97:c6:a4:36:
+ ac:71:af:bb:2d:e5:84:ed:f3:8f:2b:eb:11:e5:aa:
+ 66:ed:bf:62:6b:e3:ce:fa:80:ed:90:ff:b9:4a:39:
+ 20:40:b6:f2:99:bf:2f:33:b5:f2:ec:3a:90:60:1d:
+ 9e:94:7e:a4:1b
Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- 6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4
- X509v3 Authority Key Identifier:
- keyid:88:98:65:D9:F3:F2:8B:03:1D:66:60:61:23:FA:AD:73:6D:D3:68:92
- DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com
- serial:00
-
Signature Algorithm: md5WithRSAEncryption
- 31:77:69:b9:bd:ab:29:f3:fc:5a:09:16:6f:5d:42:ea:ba:01:
- 55:69:e3:75:cf:b8:d1:b7:b9:bf:da:63:85:8c:48:92:06:60:
- 76:97:e0:00:78:4b:ad:da:ab:6a:90:6d:8b:03:a8:b1:e9:09:
- 78:e1:29:98:56:12:60:6b:42:fe:e8:a7:c4:f8:d6:15:07:e8:
- 2b:c2:d8:8a:e5:1b:2e:51:08:9b:56:e3:b3:7a:4c:3e:e5:be:
- 4a:4d:f8:65:7b:a8:21:e0:ca:fe:8b:ab:d7:ec:f2:2d:f7:d0:
- bf:d7:c5:23:1c:08:d8:aa:57:c7:f3:5f:ba:33:3f:78:d1:f4:
- 8e:5e
+ de:5e:35:cd:7b:11:e6:7c:c5:7c:d6:27:4e:72:12:49:42:eb:
+ 6f:2c:96:f3:f4:00:78:a7:4f:9f:2d:7b:d7:30:39:af:49:4d:
+ df:b1:55:0d:30:be:23:6f:06:67:fd:dd:ba:98:66:36:c6:32:
+ b7:ed:63:fc:aa:49:cd:4f:72:98:3b:13:0e:f6:28:d7:d4:eb:
+ 04:6b:dc:e8:c7:04:80:92:e4:04:86:0b:ed:32:25:76:1d:a9:
+ 5c:a9:2c:18:2c:bd:bc:15:ed:e1:76:96:4d:bb:0d:41:44:06:
+ 2c:ad:45:bb:db:61:ad:17:11:cb:49:70:67:eb:c6:27:d3:91:
+ c8:f2
-----BEGIN CERTIFICATE-----
-MIIDkTCCAvqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux
-EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB
-YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0
-Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMjA2WhcNMTMw
-OTA5MTYyMjA2WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G
-A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIFNlcnZlcjExMC8GCSqGSIb3
-DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEA6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40Y
-wheVE1LSP1UQV8g/WvWy+ovQZ0nMqoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFg
-h5hzXBDBsRpN8fOwmD/w15ebK/3VIXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0q
-qLjKmY0CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w
-ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRu5Jtqxerk5sfv
-1x7IY0VgKxvU1DCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB
-jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT
-CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv
-BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C
-AQAwDQYJKoZIhvcNAQEEBQADgYEAMXdpub2rKfP8WgkWb11C6roBVWnjdc+40be5
-v9pjhYxIkgZgdpfgAHhLrdqrapBtiwOosekJeOEpmFYSYGtC/uinxPjWFQfoK8LY
-iuUbLlEIm1bjs3pMPuW+Sk34ZXuoIeDK/our1+zyLffQv9fFIxwI2KpXx/NfujM/
-eNH0jl4=
+MIIB+zCCAWQCAQEwDQYJKoZIhvcNAQEEBQAwRDELMAkGA1UEBhMCU0UxEDAOBgNV
+BAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFC
+MB4XDTA2MDUwMzA4NTQxM1oXDTA5MDEyNzA4NTQxM1owgYsxCzAJBgNVBAYTAlNF
+MRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhN
+eVNRTCBBQjESMBAGA1UEAxMJbG9jYWxob3N0MTEwLwYJKoZIhvcNAQkBFiJhYnN0
+cmFjdC5teXNxbC5kZXZlbG9wZXJAbXlzcWwuY29tMFwwDQYJKoZIhvcNAQEBBQAD
+SwAwSAJBANn92rP7fOCwA76XxqQ2rHGvuy3lhO3zjyvrEeWqZu2/YmvjzvqA7ZD/
+uUo5IEC28pm/LzO18uw6kGAdnpR+pBsCAwEAATANBgkqhkiG9w0BAQQFAAOBgQDe
+XjXNexHmfMV81idOchJJQutvLJbz9AB4p0+fLXvXMDmvSU3fsVUNML4jbwZn/d26
+mGY2xjK37WP8qknNT3KYOxMO9ijX1OsEa9zoxwSAkuQEhgvtMiV2HalcqSwYLL28
+Fe3hdpZNuw1BRAYsrUW722GtFxHLSXBn68Yn05HI8g==
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-key.pem b/mysql-test/std_data/server-key.pem
index 4292dc79929..a4842624c0c 100644
--- a/mysql-test/std_data/server-key.pem
+++ b/mysql-test/std_data/server-key.pem
@@ -1,15 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDphnpVhIhMvqT4knMwEkkLeoWHOTQ5DX0LjRjCF5UTUtI/VRBX
-yD9a9bL6i9BnScyqgvyfzgC0c/M20jrTwrAOFMPUsiF0ofAxgWCHmHNcEMGxGk3x
-87CYP/DXl5sr/dUhebIv62QVyZud/J4t1PgEW+qpdUtCwz0OTSqouMqZjQIDAQAB
-AoGBALTq11nrjIEQbdSZ+R1z/R0kddB2U+wjdA3/6P9tr7PBxVsFdtzbKaI5mcib
-iwCKX0J2qmrP+SHUdsexBZxLR4KV/Z55v9Pym99Dy+DxDA95zURyCMKRBIzlU5uN
-F7USEQoltLUCsmZwNWdit0gfxSWdddkHNuI0uxTzHwuDcUlNAkEA/76zVremngNL
-DlekM9NPn/8E/TXBHN1b1jdUKd7WymSJykdcm3viU98dFNZFWF8B0jiTcuBKXgpR
-vTShNab/swJBAOnCGp554BLhioTyyk8qjRLt3xEsjsDljJULHVLYWcUqIkMf97GL
-VLBhl6ZEI9i0WduqvgZ+Bacd0uHqIHz1Yb8CQQDm1CjqTDiGxlIoT9JVNJTZxEOs
-h6gVdXY+kxHT+N3FL5luiZp8fAR7zxVgiUVtzdLG+2madfapiobcT3RyCJkhAkBI
-64AaR7KasTjg2Ew7/e4cJZAcb2XozrLYG6t+GHeIhehCQEqoW+qDSy5fc4orI7eU
-SuMUa2OgCjGqv7p6wKFJAkEAznmum/MbVOBpC4FsdnIGkxyFKIbh2OLY2aUb2KkK
-Ouf4S8Y5Ldgszi0fnDPRaxWJzewwZKvcff2zj+mYZeAXbA==
+MIIBOgIBAAJBANn92rP7fOCwA76XxqQ2rHGvuy3lhO3zjyvrEeWqZu2/YmvjzvqA
+7ZD/uUo5IEC28pm/LzO18uw6kGAdnpR+pBsCAwEAAQJBAMieYdpmRoUaODf9wqh6
+ULXH/sG8i1vaXRcUHcJ50oRVfVK8/tGGvUuTDu6MeINTdahNDlYfjwOjKWVXys1w
+h6ECIQDs6s7DfczK2bKCLt0zqg24mZL3rOpGmDU+TatwN1yVgwIhAOuMzdVTX39p
+328+5WxJvBOFfxmSmqdDhIFpnRMvgguJAiByvKjT/km+970+1OllyvaIL0AA2OpA
+tBgdC0p6tyUMdwIgKuHAWzTJbu28UolVxQgLaFZmVCZ/ZzIAfnrWsLZ2a1kCIBq/
+ywJ2cpyFlgazu8AH6KCQa0ok9s70ElaB6FEC85Al
-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/std_data/untrusted-cacert.pem b/mysql-test/std_data/untrusted-cacert.pem
new file mode 100644
index 00000000000..981dd004fc6
--- /dev/null
+++ b/mysql-test/std_data/untrusted-cacert.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ Validity
+ Not Before: Jan 18 20:12:32 2005 GMT
+ Not After : Oct 15 20:12:32 2007 GMT
+ Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (512 bit)
+ Modulus (512 bit):
+ 00:cf:2b:14:00:b0:3c:df:6f:9e:91:40:ec:c8:f6:
+ 90:b2:5b:b4:70:80:a5:a4:0a:73:c7:44:f3:2a:26:
+ c4:2f:f1:3a:f1:c3:c4:ac:fc:c3:d2:c3:bf:f5:d7:
+ 6a:38:42:ad:22:ab:c8:c4:4b:4c:1d:16:af:05:34:
+ 7d:79:97:5e:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84
+ X509v3 Authority Key Identifier:
+ keyid:CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84
+ DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: md5WithRSAEncryption
+ 27:f7:3d:fb:39:6f:73:a4:86:f3:a0:48:22:60:84:e9:5c:3d:
+ 28:36:05:16:44:98:07:87:e1:5d:b5:f3:a7:bc:33:5f:f4:29:
+ a9:5f:87:33:df:e6:8e:bd:e2:f3:0a:c8:00:69:ae:3d:41:47:
+ 03:ea:0b:4c:67:45:4b:ab:f3:39
+-----BEGIN CERTIFICATE-----
+MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx
+DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh
+d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb
+BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDExODIwMTIzMloXDTA3
+MTAxNTIwMTIzMlowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP
+BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3
+LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh
+c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDPKxQAsDzfb56RQOzI9pCy
+W7RwgKWkCnPHRPMqJsQv8Trxw8Ss/MPSw7/112o4Qq0iq8jES0wdFq8FNH15l17h
+AgMBAAGjgekwgeYwHQYDVR0OBBYEFMsPH+midnHJ5ugjpsEYt8xEz7mEMIG2BgNV
+HSMEga4wgauAFMsPH+midnHJ5ugjpsEYt8xEz7mEoYGPpIGMMIGJMQswCQYDVQQG
+EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE
+ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv
+bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAANBACf3Pfs5b3OkhvOgSCJghOlcPSg2BRZEmAeH4V21
+86e8M1/0KalfhzPf5o694vMKyABprj1BRwPqC0xnRUur8zk=
+-----END CERTIFICATE-----
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 7cddb8bafa9..efe58579785 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -469,3 +469,16 @@ ALTER TABLE t1 MODIFY s BINARY(10);
SELECT HEX(s) FROM t1;
SELECT LENGTH(s) FROM t1;
DROP TABLE t1;
+
+#
+# Bug#19386: Multiple alter causes crashed table
+# The trailing column would get corrupted data, or server could not even read
+# it.
+#
+
+CREATE TABLE t1 (v VARCHAR(3), b INT);
+INSERT INTO t1 VALUES ('abc', 5);
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4);
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test
index a8fd0a4283e..1801a4a440f 100644
--- a/mysql-test/t/analyze.test
+++ b/mysql-test/t/analyze.test
@@ -61,6 +61,14 @@ prepare stmt1 from "SELECT * FROM t1 PROCEDURE ANALYSE()";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
+
+#
+# bug#15225 (ANALYZE temporary has no effect)
+#
+create temporary table t1(a int, index(a));
+insert into t1 values('1'),('2'),('3'),('4'),('5');
+analyze table t1;
+show index from t1;
drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test
index 444bf982b8a..fa7f999954e 100644
--- a/mysql-test/t/ansi.test
+++ b/mysql-test/t/ansi.test
@@ -26,4 +26,16 @@ drop table t1;
SET @@SQL_MODE="";
+# Bug#14515
+
+CREATE TABLE t1 (i int auto_increment NOT NULL, PRIMARY KEY (i));
+SHOW CREATE TABLE t1;
+SET @@SQL_MODE="MYSQL323";
+SHOW CREATE TABLE t1;
+SET @@SQL_MODE="MYSQL40";
+SHOW CREATE TABLE t1;
+SET @@SQL_MODE="NO_FIELD_OPTIONS";
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index 7e091991475..c89d31c69b9 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -5,7 +5,7 @@
-- source include/have_archive.inc
--disable_warnings
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
--enable_warnings
CREATE TABLE t1 (
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index b20fe80303d..e0b024d021b 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -219,7 +219,26 @@ INSERT INTO t1 (b) VALUES ('bbbb');
CHECK TABLE t1;
DROP TABLE IF EXISTS t1;
-# End of 4.1 tests
+# BUG #19025:
+
+CREATE TABLE `t1` (
+ t1_name VARCHAR(255) DEFAULT NULL,
+ t1_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ KEY (t1_name),
+ PRIMARY KEY (t1_id)
+) AUTO_INCREMENT = 1000;
+
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+INSERT INTO t1 (t1_name) VALUES('MySQL');
+
+SELECT * from t1;
+
+SHOW CREATE TABLE `t1`;
+
+DROP TABLE `t1`;
+
+--echo End of 4.1 tests
#
# Bug #11080 & #11005 Multi-row REPLACE fails on a duplicate key error
@@ -256,3 +275,14 @@ update t1 set a=2 where a=1;
insert into t1 (val) values (1);
select * from t1;
drop table t1;
+
+#
+# Test key duplications with auto-increment in ALTER TABLE
+# bug #14573
+#
+CREATE TABLE t1 (t1 INT(10) PRIMARY KEY, t2 INT(10));
+INSERT INTO t1 VALUES(0, 0);
+INSERT INTO t1 VALUES(1, 1);
+--error ER_DUP_ENTRY
+ALTER TABLE t1 CHANGE t1 t1 INT(10) auto_increment;
+DROP TABLE t1;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 42536ce8a3b..1bdfc5cc10f 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -122,6 +122,17 @@ SELECT 'case+union+test'
UNION
SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
+#
+# Bug #17896: problem with MIN(CASE...)
+#
+
+create table t1(a float, b int default 3);
+insert into t1 (a) values (2), (11), (8);
+select min(a), min(case when 1=1 then a else NULL end),
+ min(case when 1!=1 then NULL else a end)
+from t1 where b=3 group by b;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index 533da542855..b733a23f398 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -47,7 +47,7 @@ select cast('1a' as signed);
select cast('' as signed);
#
-# Character set convertion
+# Character set conversion
#
set names binary;
select cast(_latin1'test' as char character set latin2);
diff --git a/mysql-test/t/contributors.test b/mysql-test/t/contributors.test
new file mode 100644
index 00000000000..e463c4a888b
--- /dev/null
+++ b/mysql-test/t/contributors.test
@@ -0,0 +1 @@
+SHOW CONTRIBUTORS;
diff --git a/mysql-test/t/ctype_latin2_ch.test b/mysql-test/t/ctype_latin2_ch.test
index 626d83fa17d..3925d02659d 100644
--- a/mysql-test/t/ctype_latin2_ch.test
+++ b/mysql-test/t/ctype_latin2_ch.test
@@ -28,3 +28,5 @@ select * from t1 ignore index (primary) where tt like 'AA%';
select * from t1 where tt like '%AA%';
# End of 4.1 tests
+
+drop table t1;
diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test
index 1d807b5e9a8..01e0b334554 100644
--- a/mysql-test/t/ctype_sjis.test
+++ b/mysql-test/t/ctype_sjis.test
@@ -78,6 +78,6 @@ SET collation_connection='sjis_bin';
--character_set sjis
SET NAMES sjis;
-SELECT HEX('²“‘@\Œ\') FROM DUAL;
+SELECT HEX('²“‘@Œ\') FROM DUAL;
# End of 4.1 tests
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index af46b9c385a..c7662f4f85a 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -410,6 +410,14 @@ DROP TABLE t1;
SET NAMES latin1;
#
+# Bug#18691 Converting number to UNICODE string returns invalid result
+#
+SELECT CONVERT(103, CHAR(50) UNICODE);
+SELECT CONVERT(103.0, CHAR(50) UNICODE);
+SELECT CONVERT(-103, CHAR(50) UNICODE);
+SELECT CONVERT(-103.0, CHAR(50) UNICODE);
+
+#
# Bug#9557 MyISAM utf8 table crash
#
CREATE TABLE t1 (
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
index 2e1af51efa7..39a530ba733 100644
--- a/mysql-test/t/date_formats.test
+++ b/mysql-test/t/date_formats.test
@@ -280,3 +280,33 @@ select str_to_date( 1, NULL );
select str_to_date( NULL, 1 );
select str_to_date( 1, IF(1=1,NULL,NULL) );
# End of 4.1 tests
+
+#
+# Bug#11326
+# TIME_FORMAT using "%r" returns wrong hour using 24:00:00 in TIME column
+#
+# This tests that 24:00:00 does not return PM, when it should be AM.
+# Some other values are being tested same time.
+#
+
+SELECT TIME_FORMAT("24:00:00", '%r');
+SELECT TIME_FORMAT("00:00:00", '%r');
+SELECT TIME_FORMAT("12:00:00", '%r');
+SELECT TIME_FORMAT("15:00:00", '%r');
+SELECT TIME_FORMAT("01:00:00", '%r');
+SELECT TIME_FORMAT("25:00:00", '%r');
+
+#
+# Bug#11324
+# TIME_FORMAT using "%l:%i" returns 36:00 with 24:00:00 in TIME column
+#
+# This tests that 24:00:00 does not change to "36:00 AM". Testing
+# some other values same time.
+#
+
+SELECT TIME_FORMAT("00:00:00", '%l %p');
+SELECT TIME_FORMAT("01:00:00", '%l %p');
+SELECT TIME_FORMAT("12:00:00", '%l %p');
+SELECT TIME_FORMAT("23:00:00", '%l %p');
+SELECT TIME_FORMAT("24:00:00", '%l %p');
+SELECT TIME_FORMAT("25:00:00", '%l %p');
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 2a9feec91c1..552827c47f9 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -9,48 +9,33 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-events_bugs : BUG#17619 2006-02-21 andrey Race conditions
-events_stress : BUG#17619 2006-02-21 andrey Race conditions
-events : BUG#17619 2006-02-21 andrey Race conditions
-events_scheduling : BUG#18958 2006-04-13 andrey Test case unstable
-events_logs_tests : BUG#18953 2006-04-12 kent Test is randomly failing
+#events_bugs : BUG#17619 2006-02-21 andrey Race conditions
+#events_stress : BUG#17619 2006-02-21 andrey Race conditions
+#events : BUG#17619 2006-02-21 andrey Race conditions
+#events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked.
ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
-ndb_cache2 : BUG#18597 2006-03-28 brian simultaneous drop table and ndb statistics update triggers node failure
-ndb_cache_multi2 : BUG#18597 2006-04-10 kent simultaneous drop table and ndb statistics update triggers node failure
+#ndb_binlog_discover : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always detect cluster shutdown
+#ndb_cache2 : BUG#18597 2006-03-28 brian simultaneous drop table and ndb statistics update triggers node failure
+#ndb_cache_multi2 : BUG#18597 2006-04-10 kent simultaneous drop table and ndb statistics update triggers node failure
+ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
-rpl_deadlock_innodb : BUG#16920 2006-04-12 kent fails in show slave status (randomly)
-rpl_ndb_2innodb : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs
-rpl_ndb_2myisam : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs
+rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
+rpl_ndb_2myisam : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er
-rpl_ndb_ddl : result file needs update + test needs to checked
-rpl_ndb_innodb2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure
+rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop
+rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD
+rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked
+rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ
-rpl_ndb_myisam2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure
-#rpl_ndb_relay_space : BUG#16993 2006-02-16 jmiller RBR: ALTER TABLE ZEROFILL AUTO_INCREMENT is not replicated correctly
+rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian
-#rpl_row_basic_7ndb : BUG#17400 2006-04-09 brian Cluster Replication: delete & update of rows in table without pk fails on slave.
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
-rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed
+rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed
rpl_row_inexist_tbl : BUG#18948 2006-03-09 mats Disabled since patch makes this test wait forever
rpl_sp : BUG#16456 2006-02-16 jmiller
-rpl_until : BUG#15886 2006-02-16 jmiller Unstable test case
-sp-goto : BUG#18949 2006-02-16 jmiller GOTO is currently is disabled - will be fixed in the future
-mysqldump : BUG#18078 2006-03-10 lars
-udf : BUG#18564 2006-03-27 ian (Permission by Brian)
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
#ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events
-
-# the below ndb failures have not been objerved for > 5 push builds, close bugs
-#ndb_gis : BUG#18600 2006-03-28 brian ndb_gis test failure
-#ndb_load : BUG#17233 2006-02-16 jmiller failed load data from infile causes mysqld dbug_assert, binlog not flushed
-#rpl_ndb_basic : BUG#18592 2006-03-28 brian rpl_ndb_basic failure
-#rpl_ndb_dd_advance : BUG#18924 2006-04-09 brian rpl_ndb_dd_advance failure
-rpl_ndb_dd_partitions : BUG#18094 2006-04-19 mats Slave caches invalid table definition...
-#rpl_ndb_dd_basic : BUG#18569 2006-03-28 brian rpl_ndb_dd_basic failure
-#rpl_ndb_insert_ignore : BUG#18567 2006-03-28 brian rpl_ndb_insert_ignore failure
-#rpl_ndb_multi_update2 : BUG#18928 2006-04-09 brian rpl_ndb_multi_update2 failed
-#rpl_ndb_multi_update3 : BUG#18627 2006-03-29 monty Cluster Replication: rpl_ndb_multi_update3 fails on Intel 64 bit
-#rpl_ndb_trig004 : BUG#18977 2006-04-10 kent Test fails randomly
+ndb_dd_backuprestore : Nikolay: removed partitions from the test. Review pending.
diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test
index 45bd0c7a51c..09f07c2852f 100644
--- a/mysql-test/t/distinct.test
+++ b/mysql-test/t/distinct.test
@@ -382,3 +382,19 @@ INSERT INTO t1 VALUES
select count(distinct x,y) from t1;
select count(distinct concat(x,y)) from t1;
drop table t1;
+
+#
+# Bug #18068: SELECT DISTINCT
+#
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b));
+
+INSERT INTO t1 VALUES (1, 101);
+INSERT INTO t1 SELECT a + 1, a + 101 FROM t1;
+INSERT INTO t1 SELECT a + 2, a + 102 FROM t1;
+INSERT INTO t1 SELECT a + 4, a + 104 FROM t1;
+INSERT INTO t1 SELECT a + 8, a + 108 FROM t1;
+
+EXPLAIN SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a;
+SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test
index f80297682b7..a3e2bbc0998 100644
--- a/mysql-test/t/events.test
+++ b/mysql-test/t/events.test
@@ -15,11 +15,10 @@ CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
connection default;
SHOW DATABASES LIKE 'db_x';
SET GLOBAL event_scheduler=1;
---sleep 2
+--sleep 1.5
SHOW DATABASES LIKE 'db_x';
SHOW TABLES FROM db_x;
-SET GLOBAL event_scheduler=0;
---sleep 1
+SET GLOBAL event_scheduler=2;
connection priv_conn;
DROP EVENT e_x1;
DROP EVENT e_x2;
@@ -31,8 +30,7 @@ USE events_test;
#
# END: BUG #17289 Events: missing privilege check for drop database
#
-SET GLOBAL event_scheduler=0;
---sleep 1
+SET GLOBAL event_scheduler=2;
drop event if exists event1;
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
alter event event1 rename to event2 enable;
@@ -92,11 +90,11 @@ drop event e_43;
--echo "Let's check whether we can use non-qualified names"
create table non_qualif(a int);
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
---sleep 2
+--sleep 1
select * from non_qualif;
drop event non_qualif_ev;
drop table non_qualif;
-set global event_scheduler = 0;
+set global event_scheduler = 2;
create table t_event3 (a int, b float);
drop event if exists event3;
@@ -150,9 +148,9 @@ set names cp1251;
create event ðóóò21 on schedule every '50:23:59:95' day_second COMMENT 'òîâà å 1251 êîìåíòàð' do select 1;
SHOW CREATE EVENT ðóóò21;
insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
---error 1235
+--error ER_NOT_SUPPORTED_YET
show create event root22;
---error 1235
+--error ER_NOT_SUPPORTED_YET
SHOW EVENTS;
drop event root22;
drop event root6;
@@ -241,88 +239,12 @@ DROP EVENT intact_check;
# mysql.event intact checking end
#
-#
-#INFORMATION_SCHEMA.EVENTS test begin
-#
-create event one_event on schedule every 10 second do select 123;
---replace_column 8 # 9 #
-SHOW EVENTS;
-SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
-CREATE DATABASE events_test2;
-CREATE USER ev_test@localhost;
-GRANT ALL ON events_test.* to ev_test@localhost;
-GRANT ALL on events_test2.* to ev_test@localhost;
-REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
-REVOKE PROCESS on *.* from ev_test@localhost;
-#now we are on con1
-connect (ev_con1,localhost,ev_test,,events_test2);
-select "NEW CONNECTION";
-SELECT USER(), DATABASE();
-SHOW GRANTS;
-
---echo "Here comes an error:";
-#NO EVENT_ACL on events_test2
---error 1044
-SHOW EVENTS;
-USE events_test;
-
---echo "Now the list should be empty:";
---replace_column 8 # 9 #
-SHOW EVENTS;
-#now create an event with the same name but we are different user
-select concat("Let's create some new events from the name of ",user());
-create event one_event on schedule every 20 second do select 123;
-create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123;
-create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123;
-
---echo "Now we should see 3 events:";
---replace_column 8 # 9 #
-SHOW EVENTS;
-
---echo "This should show us only 3 events:";
---replace_column 8 # 9 #
-SHOW FULL EVENTS;
-
---echo "This should show us only 2 events:";
---replace_column 8 # 9 #
-SHOW FULL EVENTS LIKE 't%event';
-
---echo "This should show us no events:";
---replace_column 8 # 9 #
-SHOW FULL EVENTS FROM test LIKE '%';
-#ok, we are back
-connection default;
-DROP DATABASE events_test2;
-
---echo "should see 1 event:";
---replace_column 8 # 9 #
-SHOW EVENTS;
-
---echo "we should see 4 events now:";
---replace_column 8 # 9 #
-SHOW FULL EVENTS;
-SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
-
-connection ev_con1;
-drop event one_event;
-drop event two_event;
-drop event three_event;
-disconnect ev_con1;
-connection default;
-drop user ev_test@localhost;
-drop event one_event;
-#
-##INFORMATION_SCHEMA.EVENTS test end
-#
-
---echo "Sleep a bit so the server closes the second connection"
---sleep 2
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
drop event e_26;
---error 1504
+--error ER_WRONG_VALUE
create event e_26 on schedule at NULL disabled do set @a = 5;
---error 1504
+--error ER_WRONG_VALUE
create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
set names utf8;
@@ -330,21 +252,21 @@ create event задачка on schedule every 123 minute starts now() ends now()
drop event задачка;
# event_scheduler is a global var
---error 1229
-set event_scheduler=0;
-# event_scheduler could be only either 0 or 1
---error 1231
-set global event_scheduler=2;
+--error ER_GLOBAL_VARIABLE
+set event_scheduler=2;
+# event_scheduler could be only either 1 or 2
+--error ER_WRONG_VALUE_FOR_VAR
+set global event_scheduler=3;
--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0"
-set global event_scheduler=0;
+set global event_scheduler=2;
select definer, name, db from mysql.event;
select get_lock("test_lock1", 20);
create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
--echo "Should return 1 row"
select definer, name, db from mysql.event;
---echo "Should be 0 processes"
+--echo "Should be only 1 process"
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
select release_lock("test_lock1");
drop event закачка;
@@ -360,9 +282,9 @@ select get_lock("test_lock2", 20);
--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
--echo "Let some time pass to the event starts"
---sleep 2
+--sleep 1
--echo "Should have only 2 processes: the scheduler and the locked event"
-select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
+select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;--echo "Release the mutex, the event worker should finish."
--echo "Release the mutex, the event worker should finish."
select release_lock("test_lock2");
drop event закачка;
@@ -379,18 +301,11 @@ set global event_scheduler=1;
select get_lock("test_lock2_1", 20);
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
--sleep 1
---echo "Should see 1 process, locked on get_lock("
-#select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
---echo "Shutting down the scheduler, it should wait for the running event"
-set global event_scheduler=0;
---sleep 1
---echo "Should have only 2 processes: the scheduler and the locked event"
+--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
+select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
+set global event_scheduler=2;
+--echo "Should have only our process now:"
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
---echo "Release the lock so the child process should finish. Hence the scheduler also"
-select release_lock("test_lock2_1");
---sleep 1
---echo "Should see 0 processes now:"
-select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
drop event закачка21;
####
@@ -426,7 +341,7 @@ drop event white_space;
# END: BUG #17453: Creating Event crash the server
#
-##set global event_scheduler=1;
+#
# Bug#17403 "Events: packets out of order with show create event"
#
create event e1 on schedule every 1 year do set @a = 5;
@@ -440,7 +355,7 @@ drop event e1;
##select get_lock("test_lock3", 20);
##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
##select sleep(2);
-##show processlist;
+##select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
##drop event закачка;
##select release_lock("test_lock3");
@@ -450,14 +365,14 @@ drop event e1;
##select get_lock("test_lock4", 20);
##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20);
##select sleep(3);
-##--replace_column 1 # 6 #
+##select /*6*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
##drop event закачка4;
##select release_lock("test_lock4");
-##set global event_scheduler=0;
+##set global event_scheduler=2;
##select sleep(2);
##--replace_column 1 # 6 #
+##show processlist;
##select count(*) from mysql.event;
drop database events_test;
-
diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test
index 3f339ff0398..e3b79a6bd13 100644
--- a/mysql-test/t/events_bugs.test
+++ b/mysql-test/t/events_bugs.test
@@ -30,13 +30,13 @@ set @a=3;
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
call p_16();
--echo "Here we used to crash!"
---error 1516
+--error ER_EVENT_ALREADY_EXISTS
call p_16();
---error 1516
+--error ER_EVENT_ALREADY_EXISTS
call p_16();
DROP EVENT e_16;
CALL p_16();
---error 1516
+--error ER_EVENT_ALREADY_EXISTS
CALL p_16();
DROP PROCEDURE p_16;
DROP EVENT e_16;
@@ -47,9 +47,9 @@ DROP EVENT e_16;
#
# Start - 16396: Events: Distant-future dates become past dates
#
---error 1504
+--error ER_WRONG_VALUE
create event e_55 on schedule at 99990101000000 do drop table t;
---error 1504
+--error ER_WRONG_VALUE
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
--error ER_EVENT_ENDS_BEFORE_STARTS
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
@@ -60,7 +60,7 @@ create event e_55 on schedule every 10 minute ends 99990101000000 do drop table
#
# Start - 16407: Events: Changes in sql_mode won't be taken into account
#
-set global event_scheduler=0;
+set global event_scheduler=2;
--echo "Wait a bit to settle down"
--sleep 1
delete from mysql.event;
@@ -79,7 +79,7 @@ delimiter ;|
--echo "Now if everything is fine the event has compiled and is locked
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
select release_lock('test_bug16407');
-set global event_scheduler= 0;
+set global event_scheduler= 2;
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
--echo "Let's check whether we change the sql_mode on ALTER EVENT"
set sql_mode='traditional';
@@ -121,9 +121,9 @@ set global event_scheduler= 1;
--sleep 1
select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
select release_lock('ee_16407_2');
---sleep 3
+--sleep 2
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
-set global event_scheduler= 0;
+set global event_scheduler= 2;
select * from events_smode_test order by ev_name, a;
--echo "OK, last check before we drop them"
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
@@ -156,7 +156,7 @@ set global event_scheduler= 1;
--echo "Should have 2 locked processes"
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
select release_lock('ee_16407_5');
---sleep 3
+--sleep 2
--echo "Should have 0 processes locked"
select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
select * from events_smode_test order by ev_name, a;
@@ -166,7 +166,7 @@ drop event ee_16407_5;
drop event ee_16407_6;
drop procedure ee_16407_5_pendant;
drop procedure ee_16407_6_pendant;
-set global event_scheduler= 0;
+set global event_scheduler= 2;
drop table events_smode_test;
set sql_mode=@old_sql_mode;
#
diff --git a/mysql-test/t/events_grant.test b/mysql-test/t/events_grant.test
new file mode 100644
index 00000000000..ba94944a3cf
--- /dev/null
+++ b/mysql-test/t/events_grant.test
@@ -0,0 +1,105 @@
+CREATE DATABASE IF NOT EXISTS events_test;
+use events_test;
+#
+# Events grants test begin
+#
+CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123;
+--replace_column 8 # 9 #
+SHOW EVENTS;
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
+CREATE DATABASE events_test2;
+CREATE USER ev_test@localhost;
+GRANT ALL ON events_test.* to ev_test@localhost;
+GRANT ALL ON events_test2.* to ev_test@localhost;
+REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
+#now we are on con1
+connect (ev_con1,localhost,ev_test,,events_test2);
+select "NEW CONNECTION";
+SELECT USER(), DATABASE();
+SHOW GRANTS;
+--echo "Here comes an error:";
+#NO EVENT_ACL on events_test2
+--error 1044
+SHOW EVENTS;
+USE events_test;
+--echo "We should see one event";
+--replace_column 8 # 9 #
+SHOW EVENTS;
+#now create an event with the same name but we are different user
+SELECT CONCAT("Let's create some new events from the name of ", USER());
+--error ER_EVENT_ALREADY_EXISTS
+CREATE EVENT one_event ON SCHEDULE EVERY 20 SECOND DO SELECT 123;
+CREATE EVENT two_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION NOT PRESERVE COMMENT "two event" DO SELECT 123;
+CREATE EVENT three_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION PRESERVE COMMENT "three event" DO SELECT 123;
+
+--echo "Now we should see 3 events:";
+--replace_column 8 # 9 #
+SHOW EVENTS;
+
+--echo "This should show us only 2 events:";
+--replace_column 8 # 9 #
+SHOW EVENTS LIKE 't%event';
+
+--echo "This should show us no events:";
+--replace_column 8 # 9 #
+SHOW EVENTS FROM test LIKE '%';
+#ok, we are back
+connection default;
+GRANT EVENT ON events_test2.* TO ev_test@localhost;
+connection ev_con1;
+USE events_test2;
+CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42;
+connection default;
+USE events_test;
+--echo "We should see 4 events : one_event, two_event, three_event & four_event"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+DROP DATABASE events_test2;
+--echo "We should see 3 events : one_event, two_event, three_event"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+
+connection default;
+CREATE DATABASE events_test2;
+USE events_test2;
+CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42;
+
+connection ev_con1;
+--echo "Should see 4 events - one, two, three & five"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+connection default;
+REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
+connection ev_con1;
+USE test;
+--echo "Should see 3 events - one, two & three"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+--echo "Let's test ALTER EVENT which changes the definer"
+USE events_test;
+ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND;
+--echo "The definer should be ev_test@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+connection default;
+USE events_test;
+ALTER EVENT one_event COMMENT "comment";
+connection ev_con1;
+--echo "The definer should be root@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+ALTER EVENT one_event DO SELECT 12;
+--echo "The definer should be ev_test@localhost"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event';
+connection default;
+--echo "make the definer again root@localhost"
+ALTER EVENT one_event COMMENT "new comment";
+connection ev_con1;
+--echo "test DROP by another user"
+DROP EVENT one_event;
+connection default;
+--echo "One event should not be there"
+SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS;
+disconnect ev_con1;
+connection default;
+DROP USER ev_test@localhost;
+DROP DATABASE events_test2;
+#
+## EVENTS grants test end
+#
+
+DROP DATABASE events_test;
diff --git a/mysql-test/t/events_logs_tests.test b/mysql-test/t/events_logs_tests.test
index e586184c9e4..6d3b3292630 100644
--- a/mysql-test/t/events_logs_tests.test
+++ b/mysql-test/t/events_logs_tests.test
@@ -10,19 +10,21 @@ BEGIN
END|
delimiter ;|
--echo "Check General Query Log"
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
TRUNCATE mysql.general_log;
--echo "1 row, the current statement!"
+--replace_column 1 USER_HOST
call select_general_log();
SET GLOBAL event_scheduler=1;
--echo "Wait the scheduler to start"
--echo "Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
--sleep 2
+--replace_column 1 USER_HOST
call select_general_log();
DROP PROCEDURE select_general_log;
DROP EVENT log_general;
-SET GLOBAL event_scheduler=0;
+SET GLOBAL event_scheduler=2;
--sleep 1
--echo "Check slow query log"
@@ -50,12 +52,14 @@ SET @old_session_long_query_time:=@@long_query_time;
SHOW VARIABLES LIKE 'log_slow_queries';
DROP FUNCTION get_value;
TRUNCATE mysql.slow_log;
+--replace_column 1 USER_HOST
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
--echo "Set new values"
SET GLOBAL long_query_time=4;
-SET SESSION long_query_time=2;
+SET SESSION long_query_time=1;
--echo "Check that logging is working"
-SELECT SLEEP(3);
+SELECT SLEEP(2);
+--replace_column 1 USER_HOST 2 SLEEPVAL
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
@@ -72,13 +76,15 @@ SELECT * FROM slow_event_test;
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
--echo "This should go to the slow log"
SET SESSION long_query_time=10;
+SET GLOBAL long_query_time=1;
DROP EVENT long_event;
-CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5);
+CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2);
--echo "Sleep some more time than the actual event run will take"
---sleep 7
+--sleep 3
--echo "Check our table. Should see 2 rows"
SELECT * FROM slow_event_test;
---echo "Check slow log. Should see 1 row because 5 is over the threshold of 4 for GLOBAL, though under SESSION which is 10"
+--echo "Check slow log. Should see 1 row because 4 is over the threshold of 3 for GLOBAL, though under SESSION which is 10"
+--replace_column 1 USER_HOST 2 SLEEPVAL
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
DROP EVENT long_event2;
SET GLOBAL long_query_time =@old_global_long_query_time;
diff --git a/mysql-test/t/events_microsec.test b/mysql-test/t/events_microsec.test
index 34855fdadff..e01120a0756 100644
--- a/mysql-test/t/events_microsec.test
+++ b/mysql-test/t/events_microsec.test
@@ -1,55 +1,15 @@
create database if not exists events_test;
use events_test;
---error 1235
+--error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 MICROSECOND DO SELECT 1;
---error 1235
+--error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 DAY_MICROSECOND DO SELECT 1;
---error 1235
+--error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 HOUR_MICROSECOND DO SELECT 1;
---error 1235
+--error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 MINUTE_MICROSECOND DO SELECT 1;
---error 1235
+--error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1;
---echo "Now create normal event and change it on SQL level"
-CREATE EVENT micro_test2 ON SCHEDULE EVERY 1 MONTH DO SELECT 1;
-UPDATE mysql.event SET interval_field='MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
---error 1235
-SHOW CREATE EVENT micro_test2;
-SET GLOBAL event_scheduler=0;
---sleep 1
---echo "Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-UPDATE mysql.event SET interval_field='DAY_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
---error 1235
-SHOW CREATE EVENT micro_test2;
-SET GLOBAL event_scheduler=0;
---sleep 1
---echo "Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-UPDATE mysql.event SET interval_field='SECOND_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
---error 1235
-SHOW CREATE EVENT micro_test2;
-SET GLOBAL event_scheduler=0;
---sleep 1
---echo "Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-UPDATE mysql.event SET interval_field='HOUR_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
---error 1235
-SHOW CREATE EVENT micro_test2;
-SET GLOBAL event_scheduler=0;
---sleep 1
---echo "Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-UPDATE mysql.event SET interval_field='MINUTE_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
---error 1235
-SHOW CREATE EVENT micro_test2;
-SET GLOBAL event_scheduler=0;
---sleep 1
---echo "Should not be running:"
-SHOW VARIABLES like 'event_scheduler';
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER='event_scheduler';
-DROP EVENT micro_test2;
-
drop database events_test;
diff --git a/mysql-test/t/events_scheduling.test b/mysql-test/t/events_scheduling.test
index f83d919515b..a73d25cd8ee 100644
--- a/mysql-test/t/events_scheduling.test
+++ b/mysql-test/t/events_scheduling.test
@@ -4,7 +4,9 @@ CREATE TABLE table_1(a int);
CREATE TABLE table_2(a int);
CREATE TABLE table_3(a int);
CREATE TABLE table_4(a int);
+CREATE TABLE T19170(s1 TIMESTAMP);
SET GLOBAL event_scheduler=1;
+CREATE EVENT E19170 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO T19170 VALUES(CURRENT_TIMESTAMP);
CREATE EVENT two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
CREATE EVENT start_n_end
ON SCHEDULE EVERY 1 SECOND
@@ -13,7 +15,7 @@ CREATE EVENT start_n_end
DO INSERT INTO table_2 VALUES(1);
--sleep 5
CREATE EVENT only_one_time ON SCHEDULE EVERY 2 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_3 VALUES(1);
-CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_4 VALUES(1);
+CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND ON COMPLETION PRESERVE DO INSERT INTO table_4 VALUES(1);
--sleep 5
SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
SELECT IF(SUM(a) >= 5, 'OK', 'ERROR') FROM table_2;
@@ -21,16 +23,18 @@ SELECT IF(SUM(a) > 0, 'OK', 'ERROR') FROM table_3;
SELECT IF(SUM(a) > 0, 'OK', 'ERROR') FROM table_4;
DROP EVENT two_sec;
SELECT IF(TIME_TO_SEC(TIMEDIFF(ENDS,STARTS))=6, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
-SELECT IF(LAST_EXECUTED-ENDS < 2, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
+SELECT IF(LAST_EXECUTED-ENDS < 3, 'OK', 'ERROR') FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=DATABASE() AND EVENT_NAME='start_n_end' AND ENDS IS NOT NULL;
DROP EVENT start_n_end;
--echo "Already dropped because ended. Therefore an error."
--error ER_EVENT_DOES_NOT_EXIST
DROP EVENT only_one_time;
---echo "Already dropped because ended. Therefore an error."
---error ER_EVENT_DOES_NOT_EXIST
+--echo "Should be preserved"
+SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
DROP EVENT two_time;
DROP TABLE table_1;
DROP TABLE table_2;
DROP TABLE table_3;
DROP TABLE table_4;
+--echo "Checking for multiple executions in one second, should not happen -> 0 as result"
+SELECT COUNT(*) FROM (SELECT s1, COUNT(*) AS cnt FROM T19170 GROUP BY s1) AS tmp WHERE tmp.cnt > 1;
DROP DATABASE events_test;
diff --git a/mysql-test/t/events_stress.test b/mysql-test/t/events_stress.test
index f6eed79425c..8d0034c232e 100644
--- a/mysql-test/t/events_stress.test
+++ b/mysql-test/t/events_stress.test
@@ -2,78 +2,124 @@ CREATE DATABASE IF NOT EXISTS events_test;
#
# DROP DATABASE test start (bug #16406)
#
-CREATE DATABASE events_test2;
-USE events_test2;
+CREATE DATABASE events_conn1_test2;
+CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime);
+CREATE USER event_user2@localhost;
+CREATE DATABASE events_conn2_db;
+GRANT ALL ON *.* TO event_user2@localhost;
+CREATE USER event_user3@localhost;
+CREATE DATABASE events_conn3_db;
+GRANT ALL ON *.* TO event_user3@localhost;
+connect (conn2,localhost,event_user2,,events_conn2_db);
+--echo "In the second connection we create some events which won't be dropped till the end"
+--disable_query_log
+let $1= 50;
+while ($1)
+{
+ eval CREATE EVENT conn2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn2_ev$1", NOW());
+ dec $1;
+}
+--enable_query_log
+connect (conn3,localhost,event_user3,,events_conn3_db);
+--echo "In the second connection we create some events which won't be dropped till the end"
+--disable_query_log
+let $1= 50;
+while ($1)
+{
+ eval CREATE EVENT conn3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn3_ev$1", NOW());
+ dec $1;
+}
+--enable_query_log
+connection default;
+USE events_conn1_test2;
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
USE events_test;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
-DROP DATABASE events_test2;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
+DROP DATABASE events_conn1_test2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
--echo "Now testing stability - dropping db -> events while they are running"
-CREATE DATABASE events_test2;
-USE events_test2;
+CREATE DATABASE events_conn1_test2;
+USE events_conn1_test2;
--disable_query_log
-let $1= 1000;
+let $1= 50;
while ($1)
{
- eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
+ eval CREATE EVENT conn1_round1_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round1_ev$1", NOW());
dec $1;
}
--enable_query_log
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
SET GLOBAL event_scheduler=1;
---sleep 4
-DROP DATABASE events_test2;
+--sleep 6
+DROP DATABASE events_conn1_test2;
-SET GLOBAL event_scheduler=0;
---sleep 2
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
-CREATE DATABASE events_test3;
-USE events_test3;
+SET GLOBAL event_scheduler=2;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
+CREATE DATABASE events_conn1_test3;
+USE events_conn1_test3;
--disable_query_log
-let $1= 950;
+let $1= 50;
while ($1)
{
- eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
+ eval CREATE EVENT conn1_round2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round2_ev$1", NOW());
dec $1;
}
--enable_query_log
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
---sleep 3
-CREATE DATABASE events_test4;
-USE events_test4;
+SET GLOBAL event_scheduler=1;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
+CREATE DATABASE events_conn1_test4;
+USE events_conn1_test4;
--disable_query_log
-let $1= 860;
+let $1= 50;
while ($1)
{
- eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
+ eval CREATE EVENT conn1_round3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round3_ev$1", NOW());
dec $1;
}
--enable_query_log
-
-CREATE DATABASE events_test2;
-USE events_test2;
+CREATE DATABASE events_conn1_test2;
+USE events_conn1_test2;
--disable_query_log
-let $1= 1050;
+let $1= 50;
while ($1)
{
- eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
+ eval CREATE EVENT ev_round4_drop$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round4_ev$1", NOW());
dec $1;
}
--enable_query_log
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
--sleep 6
-DROP DATABASE events_test2;
-SET GLOBAL event_scheduler=0;
-DROP DATABASE events_test3;
-SET GLOBAL event_scheduler=1;
-DROP DATABASE events_test4;
+connection conn2;
+--send
+DROP DATABASE events_conn2_db;
+connection conn3;
+--send
+DROP DATABASE events_conn3_db;
+connection default;
+--send
+DROP DATABASE events_conn1_test2;
+DROP DATABASE events_conn1_test3;
+SET GLOBAL event_scheduler=2;
+DROP DATABASE events_conn1_test4;
SET GLOBAL event_scheduler=1;
+connection conn2;
+reap;
+disconnect conn2;
+connection conn3;
+reap;
+disconnect conn3;
+connection default;
USE events_test;
+DROP TABLE fill_it;
+--disable_query_log
+DROP USER event_user2@localhost;
+DROP USER event_user3@localhost;
+--enable_query_log
#
# DROP DATABASE test end (bug #16406)
#
diff --git a/mysql-test/t/exampledb.test b/mysql-test/t/exampledb.test
index 946d25325dc..fbb2a18f344 100644
--- a/mysql-test/t/exampledb.test
+++ b/mysql-test/t/exampledb.test
@@ -5,6 +5,10 @@
-- source include/have_exampledb.inc
--disable_warnings
+# Clean up if event's test fails
+drop database if exists events_test;
+drop database if exists events_test2;
+
drop table if exists t1;
--enable_warnings
diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test
index 2a3a23c5f96..a38771db233 100644
--- a/mysql-test/t/explain.test
+++ b/mysql-test/t/explain.test
@@ -43,3 +43,12 @@ drop table ÔÁÂ;
set names latin1;
# End of 4.1 tests
+
+
+#
+# Bug#15463: EXPLAIN SELECT..INTO hangs the client (QB, command line)
+#
+select 3 into @v1;
+explain select 3 into @v1;
+
+# End of 5.0 tests.
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index a78017ddb2f..4ae749f2343 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -47,4 +47,13 @@ set @@max_allowed_packet=1048576*100;
--replace_result "''" XXX "'1'" XXX
eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null;
+#
+# Bug #18643: problem with null values
+#
+
+create table t1(a blob);
+insert into t1 values(NULL), (compress('a'));
+select uncompress(a), uncompressed_length(a) from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index aa28c9d5f52..fbfdfa3b5d0 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -397,6 +397,17 @@ insert into t1 values(1),(2),(3);
select f1, group_concat(f1+1) from t1 group by f1 with rollup;
select count(distinct (f1+1)) from t1 group by f1 with rollup;
drop table t1;
+
+#
+# Bug#14169 type of group_concat() result changed to blob if tmp_table was used
+#
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+--enable_metadata
+select f2,group_concat(f1) from t1 group by f2;
+--disable_metadata
+drop table t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index c667f90940c..fb9470c16dd 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -539,77 +539,6 @@ INSERT INTO t1 VALUES
SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
DROP TABLE t1;
-#
-# Bug #12882 min/max inconsistent on empty table
-#
-
---disable_warnings
-create table t1m (a int) engine=myisam;
-create table t1i (a int) engine=innodb;
-create table t2m (a int) engine=myisam;
-create table t2i (a int) engine=innodb;
---enable_warnings
-insert into t2m values (5);
-insert into t2i values (5);
-
-# test with MyISAM
-select min(a) from t1m;
-select min(7) from t1m;
-select min(7) from DUAL;
-explain select min(7) from t2m join t1m;
-select min(7) from t2m join t1m;
-
-select max(a) from t1m;
-select max(7) from t1m;
-select max(7) from DUAL;
-explain select max(7) from t2m join t1m;
-select max(7) from t2m join t1m;
-
-select 1, min(a) from t1m where a=99;
-select 1, min(a) from t1m where 1=99;
-select 1, min(1) from t1m where a=99;
-select 1, min(1) from t1m where 1=99;
-
-select 1, max(a) from t1m where a=99;
-select 1, max(a) from t1m where 1=99;
-select 1, max(1) from t1m where a=99;
-select 1, max(1) from t1m where 1=99;
-
-# test with InnoDB
-select min(a) from t1i;
-select min(7) from t1i;
-select min(7) from DUAL;
-explain select min(7) from t2i join t1i;
-select min(7) from t2i join t1i;
-
-select max(a) from t1i;
-select max(7) from t1i;
-select max(7) from DUAL;
-explain select max(7) from t2i join t1i;
-select max(7) from t2i join t1i;
-
-select 1, min(a) from t1i where a=99;
-select 1, min(a) from t1i where 1=99;
-select 1, min(1) from t1i where a=99;
-select 1, min(1) from t1i where 1=99;
-
-select 1, max(a) from t1i where a=99;
-select 1, max(a) from t1i where 1=99;
-select 1, max(1) from t1i where a=99;
-select 1, max(1) from t1i where 1=99;
-
-# mixed MyISAM/InnoDB test
-explain select count(*), min(7), max(7) from t1m, t1i;
-select count(*), min(7), max(7) from t1m, t1i;
-
-explain select count(*), min(7), max(7) from t1m, t2i;
-select count(*), min(7), max(7) from t1m, t2i;
-
-explain select count(*), min(7), max(7) from t2m, t1i;
-select count(*), min(7), max(7) from t2m, t1i;
-
-drop table t1m, t1i, t2m, t2i;
-
# End of 4.1 tests
#
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 0472968f918..8ddf1fbe314 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -1,6 +1,6 @@
# Initialise
--disable_warnings
-drop table if exists t1;
+drop table if exists t1, t2;
--enable_warnings
#
# test of IN (NULL)
@@ -128,3 +128,107 @@ SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
+
+# BUG#15872: Excessive memory consumption of range analysis of NOT IN
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, filler char(200), key(a));
+
+insert into t2 select C.a*2, 'no' from t1 A, t1 B, t1 C;
+insert into t2 select C.a*2+1, 'yes' from t1 C;
+
+explain
+select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
+select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
+
+explain select * from t2 force index(a) where a NOT IN (2,2,2,2,2,2);
+explain select * from t2 force index(a) where a <> 2;
+
+drop table t2;
+
+#
+# Repeat the test for DATETIME
+#
+create table t2 (a datetime, filler char(200), key(a));
+
+insert into t2 select '2006-04-25 10:00:00' + interval C.a minute,
+ 'no' from t1 A, t1 B, t1 C where C.a % 2 = 0;
+
+insert into t2 select '2006-04-25 10:00:00' + interval C.a*2+1 minute,
+ 'yes' from t1 C;
+
+explain
+select * from t2 where a NOT IN (
+ '2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
+ '2006-04-25 10:06:00', '2006-04-25 10:08:00');
+select * from t2 where a NOT IN (
+ '2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
+ '2006-04-25 10:06:00', '2006-04-25 10:08:00');
+drop table t2;
+
+#
+# Repeat the test for CHAR(N)
+#
+create table t2 (a varchar(10), filler char(200), key(a));
+
+insert into t2 select 'foo', 'no' from t1 A, t1 B;
+insert into t2 select 'barbar', 'no' from t1 A, t1 B;
+insert into t2 select 'bazbazbaz', 'no' from t1 A, t1 B;
+
+insert into t2 values ('fon', '1'), ('fop','1'), ('barbaq','1'),
+ ('barbas','1'), ('bazbazbay', '1'),('zz','1');
+
+explain select * from t2 where a not in('foo','barbar', 'bazbazbaz');
+
+drop table t2;
+
+#
+# Repeat for DECIMAL
+#
+create table t2 (a decimal(10,5), filler char(200), key(a));
+
+insert into t2 select 345.67890, 'no' from t1 A, t1 B;
+insert into t2 select 43245.34, 'no' from t1 A, t1 B;
+insert into t2 select 64224.56344, 'no' from t1 A, t1 B;
+
+insert into t2 values (0, '1'), (22334.123,'1'), (33333,'1'),
+ (55555,'1'), (77777, '1');
+
+explain
+select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
+select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
+
+drop table t2;
+
+# Try a very big IN-list
+create table t2 (a int, key(a), b int);
+insert into t2 values (1,1),(2,2);
+
+set @cnt= 1;
+set @str="update t2 set b=1 where a not in (";
+select count(*) from (
+ select @str:=concat(@str, @cnt:=@cnt+1, ",")
+ from t1 A, t1 B, t1 C, t1 D) Z;
+
+set @str:=concat(@str, "10000)");
+select substr(@str, 1, 50);
+prepare s from @str;
+execute s;
+deallocate prepare s;
+set @str=NULL;
+
+drop table t2;
+drop table t1;
+
+# BUG#19618: Crash in range optimizer for
+# "unsigned_keypart NOT IN(negative_number,...)"
+# (introduced in fix BUG#15872)
+create table t1 (
+ some_id smallint(5) unsigned,
+ key (some_id)
+);
+insert into t1 values (1),(2);
+select some_id from t1 where some_id not in(2,-1);
+select some_id from t1 where some_id not in(-4,-1,-4);
+select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
+drop table t1;
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index 4a618a56483..0475dd4bdb6 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -38,6 +38,46 @@ select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
drop table t1;
+
+#
+# Bug#16501: IS_USED_LOCK does not appear to work
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (conn CHAR(7), connection_id INT);
+INSERT INTO t1 VALUES ('default', CONNECTION_ID());
+
+SELECT GET_LOCK('bug16501',600);
+
+connect (con1,localhost,root,,);
+INSERT INTO t1 VALUES ('con1', CONNECTION_ID());
+SELECT IS_USED_LOCK('bug16501') = connection_id
+FROM t1
+WHERE conn = 'default';
+send SELECT GET_LOCK('bug16501',600);
+
+connection default;
+SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
+SELECT RELEASE_LOCK('bug16501');
+connection con1;
+reap;
+connection default;
+SELECT IS_USED_LOCK('bug16501') = connection_id
+FROM t1
+WHERE conn = 'con1';
+
+connection con1;
+SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
+SELECT RELEASE_LOCK('bug16501');
+SELECT IS_USED_LOCK('bug16501');
+
+disconnect con1;
+connection default;
+
+DROP TABLE t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/func_op.test b/mysql-test/t/func_op.test
index 24266150e4c..0a4f5034f4c 100644
--- a/mysql-test/t/func_op.test
+++ b/mysql-test/t/func_op.test
@@ -17,4 +17,18 @@ select 0 | -1, 0 ^ -1, 0 & -1;
select -1 >> 0, -1 << 0;
select -1 >> 1, -1 << 1;
+#
+# Bug 13044: wrong bit_count() results
+#
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+create table t1(a int);
+create table t2(a int, b int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1, 7), (3, 7);
+select t1.a, t2.a, t2.b, bit_count(t2.b) from t1 left join t2 on t1.a=t2.a;
+drop table t1, t2;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index ef20d766bce..7f809dbc4a1 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -666,7 +666,14 @@ select rpad(i, 7, ' ') as t from t1;
--disable_metadata
drop table t1;
-# End of 4.1 tests
+#
+# Bug #10418: LOAD_FILE does not behave like in manual if file does not exist
+#
+
+select load_file("lkjlkj");
+select ifnull(load_file("lkjlkj"),"it's null");
+
+--echo End of 4.1 tests
#
# Bug #13361: SELECT FORMAT(<decimal field with null>, 2) crashes
@@ -684,4 +691,17 @@ insert into t1 values ('y,abc'),('y,abc');
select c, substring_index(lcase(c), @q:=',', -1) as res from t1;
drop table t1;
-# End of 5.0 tests
+#
+# Bug #17043: Casting trimmed string to decimal loses precision
+#
+select cast(rtrim(' 20.06 ') as decimal(19,2));
+select cast(ltrim(' 20.06 ') as decimal(19,2));
+select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2));
+
+#
+# Bug #13975: "same string" + 0 has 2 different results
+#
+select conv("18383815659218730760",10,10) + 0;
+select "18383815659218730760" + 0;
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 4e4fb8f777a..5c993028cb4 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -352,12 +352,6 @@ 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
#
@@ -367,6 +361,18 @@ select last_day('2005-00-01');
select last_day('2005-01-00');
#
+# Bug #18501: monthname and NULLs
+#
+
+select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
+ monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
+
+--echo 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 #10590: %h, %I, and %l format specifies should all return results in
# the 0-11 range
#
@@ -468,4 +474,23 @@ SELECT * FROM t1, t2
DROP TABLE t1,t2;
-# End of 5.0 tests
+--echo End of 5.0 tests
+
+#
+# Bug #18997
+#
+
+select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND);
+select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND);
+select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR);
+select date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND);
+select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
+
+
+--echo End of 5.1 tests
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index ce1d0fb2271..b3e2d2f7998 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -462,3 +462,29 @@ drop table t1, t2;
drop database TESTDB;
flush privileges;
+#
+# BUG#13310 incorrect user parsing by SP
+#
+
+grant all privileges on test.* to `a@`@localhost;
+grant execute on * to `a@`@localhost;
+connect (bug13310,localhost,'a@',,test);
+connection bug13310;
+create table t2 (s1 int);
+insert into t2 values (1);
+--disable_warnings
+drop function if exists f2;
+--enable_warnings
+delimiter //;
+create function f2 () returns int begin declare v int; select s1 from t2
+into v; return v; end//
+delimiter ;//
+select f2();
+
+drop function f2;
+drop table t2;
+disconnect bug13310;
+
+connection default;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
+drop user `a@`@localhost;
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index bff07366ec2..d9836ccc8df 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -782,3 +782,19 @@ SELECT COUNT(DISTINCT a) FROM t1 WHERE a=0;
DROP TABLE t1;
DROP PROCEDURE a;
+
+#
+# Bug #18068: SELECT DISTINCT
+#
+
+CREATE TABLE t1 (a varchar(64) NOT NULL default '', PRIMARY KEY(a));
+
+INSERT INTO t1 (a) VALUES
+ (''), ('CENTRAL'), ('EASTERN'), ('GREATER LONDON'),
+ ('NORTH CENTRAL'), ('NORTH EAST'), ('NORTH WEST'), ('SCOTLAND'),
+ ('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN');
+
+EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a;
+SELECT DISTINCT a,a FROM t1 ORDER BY a;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 9b21e544657..41266cc6d32 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -393,3 +393,16 @@ SELECT EMPNUM, GRADE*1000
HAVING HU.PROJ.CITY = HU.STAFF.CITY);
DROP SCHEMA HU;
+USE test;
+#
+# Bug#18739: non-standard HAVING extension was allowed in strict ANSI sql mode.
+#
+create table t1(f1 int);
+select f1 from t1 having max(f1)=f1;
+select f1 from t1 group by f1 having max(f1)=f1;
+set session sql_mode='ONLY_FULL_GROUP_BY';
+--error ER_NON_GROUPING_FIELD_USED
+select f1 from t1 having max(f1)=f1;
+select f1 from t1 group by f1 having max(f1)=f1;
+set session sql_mode='';
+drop table t1;
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index 82294db336d..e501fce1eeb 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -458,4 +458,16 @@ create table t2 (c varchar(10)) engine=memory;
show table status like 't_';
drop table t1, t2;
+#
+# BUG#18233 - Memory tables INDEX USING HASH (a,b) returns 1 row on
+# SELECT WHERE a= AND b=
+#
+CREATE TABLE t1(a VARCHAR(1), b VARCHAR(2), c VARCHAR(256),
+ KEY(a), KEY(b), KEY(c)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES('a','aa',REPEAT('a', 256)),('a','aa',REPEAT('a',256));
+SELECT COUNT(*) FROM t1 WHERE a='a';
+SELECT COUNT(*) FROM t1 WHERE b='aa';
+SELECT COUNT(*) FROM t1 WHERE c=REPEAT('a',256);
+DROP TABLE t1;
+
# End of 5.0 tests
diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test
index 5e493c2643b..f1b9d290885 100644
--- a/mysql-test/t/heap_btree.test
+++ b/mysql-test/t/heap_btree.test
@@ -164,4 +164,16 @@ DELETE from t1 where a < 100;
SELECT * from t1;
DROP TABLE t1;
+#
+# BUG#18160 - Memory-/HEAP Table endless growing indexes
+#
+CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
+INSERT INTO t1 VALUES(0);
+--replace_result 37 21
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+UPDATE t1 SET val=1;
+--replace_result 37 21
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/im_cmd_line.imtest b/mysql-test/t/im_cmd_line.imtest
new file mode 100644
index 00000000000..00e8351535e
--- /dev/null
+++ b/mysql-test/t/im_cmd_line.imtest
@@ -0,0 +1,68 @@
+###########################################################################
+#
+# Tests for user-management command-line options.
+#
+###########################################################################
+
+--source include/im_check_os.inc
+
+###########################################################################
+
+# List users so we are sure about starting conditions.
+
+--echo --> Listing users...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
+--echo
+
+# Add a new user.
+
+--echo ==> Adding user 'testuser'...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --add-user --username=testuser --password=abc 2>&1 >/dev/null
+--echo
+
+--echo --> IM password file:
+--exec cat $IM_PASSWORD_PATH
+--echo --> EOF
+--echo
+
+--echo --> Printing out line for 'testuser'...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --passwd --username=testuser --password=abc | tail -1
+--echo
+
+--echo --> Listing users...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
+--echo
+
+# Edit user's attributes.
+
+--echo ==> Changing the password of 'testuser'...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --edit-user --username=testuser --password=xyz 2>&1 >/dev/null
+--echo
+
+--echo --> IM password file:
+--exec cat $IM_PASSWORD_PATH
+--echo --> EOF
+--echo
+
+--echo --> Printing out line for 'testuser'...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --passwd --username=testuser --password=xyz | tail -1
+--echo
+
+--echo --> Listing users...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
+--echo
+
+# Drop user.
+
+--echo ==> Dropping user 'testuser'...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --drop-user --username=testuser 2>&1 >/dev/null
+--echo
+
+--echo --> IM password file:
+--exec cat $IM_PASSWORD_PATH
+--echo --> EOF
+--echo
+
+--echo --> Listing users...
+--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
+--echo
diff --git a/mysql-test/t/im_daemon_life_cycle-im.opt b/mysql-test/t/im_daemon_life_cycle-im.opt
index 21c01191e4c..3a45c7a41f7 100644
--- a/mysql-test/t/im_daemon_life_cycle-im.opt
+++ b/mysql-test/t/im_daemon_life_cycle-im.opt
@@ -1,2 +1,3 @@
--run-as-service
--log=$MYSQLTEST_VARDIR/log/im.log
+--monitoring-interval=1
diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest
index 87388d7c1e6..d173ce2a6e2 100644
--- a/mysql-test/t/im_daemon_life_cycle.imtest
+++ b/mysql-test/t/im_daemon_life_cycle.imtest
@@ -10,6 +10,9 @@
###########################################################################
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted
diff --git a/mysql-test/t/im_instance_conf-im.opt b/mysql-test/t/im_instance_conf-im.opt
new file mode 100644
index 00000000000..34b74ce0c95
--- /dev/null
+++ b/mysql-test/t/im_instance_conf-im.opt
@@ -0,0 +1 @@
+--monitoring-interval=1
diff --git a/mysql-test/t/im_instance_conf.imtest b/mysql-test/t/im_instance_conf.imtest
new file mode 100644
index 00000000000..17703fdd303
--- /dev/null
+++ b/mysql-test/t/im_instance_conf.imtest
@@ -0,0 +1,228 @@
+###########################################################################
+#
+# This test suite checks the following statements:
+# - CREATE INSTANCE <instance_name> [option1[=option1_value], ...];
+# - DROP INSTANCE <instance_name>;
+#
+# For CREATE INSTANCE we check that:
+# - CREATE INSTANCE succeeds for non-existing instance;
+# - CREATE INSTANCE fails for existing instance;
+# - CREATE INSTANCE can get additional options with and w/o values;
+# - CREATE INSTANCE parses options and handles grammar errors correctly.
+# Check that strings with spaces are handled correctly, unknown (for
+# mysqld) options should also be handled;
+# - CREATE INSTANCE updates both config file and internal configuration cache;
+# - CREATE INSTANCE allows to create instances only with properly formed
+# names (mysqld*);
+#
+# For DROP INSTANCE we check that:
+# - DROP INSTANCE succeeds for existing instance;
+# - DROP INSTANCE fails for non-existing instance;
+# - DROP INSTANCE fails for active instance.
+# - DROP INSTANCE updates both config file and internal configuration cache;
+#
+###########################################################################
+
+--source include/im_check_os.inc
+
+###########################################################################
+#
+# Check starting conditions.
+#
+###########################################################################
+
+# Check that the configuration file contains only instances that we expect.
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+# Check that mysqld1 is reported as running.
+
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
+SHOW INSTANCES;
+
+# Check that the expected mysqld instance is actually run (check that we can
+# connect and execute something).
+
+--echo
+--echo ---> connection: mysql1_con
+--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
+--connection mysql1_con
+
+SHOW VARIABLES LIKE 'server_id';
+
+--disconnect mysql1_con
+
+--echo
+--echo ---> connection: default
+--connection default
+
+###########################################################################
+#
+# CREATE INSTANCE tests.
+#
+###########################################################################
+
+# Check that CREATE INSTANCE succeeds for non-existing instance and also check
+# that both config file and internal configuration cache have been updated.
+
+CREATE INSTANCE mysqld3;
+
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+
+# Check that CREATE INSTANCE fails for existing instance. Let's all three
+# existing instances (running one, stopped one and just created one). Just in
+# case...
+
+--error 3012 # ER_CREATE_EXISTING_INSTANCE
+CREATE INSTANCE mysqld1;
+
+--error 3012 # ER_CREATE_EXISTING_INSTANCE
+CREATE INSTANCE mysqld2;
+
+--error 3012 # ER_CREATE_EXISTING_INSTANCE
+CREATE INSTANCE mysqld3;
+
+# Check that CREATE INSTANCE can get additional options with and w/o values.
+# Ensure that config file is updated properly.
+
+# - without values;
+
+--echo --------------------------------------------------------------------
+--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+CREATE INSTANCE mysqld4 nonguarded;
+
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+# - with value;
+
+--echo --------------------------------------------------------------------
+--exec grep test-A $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-B $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
+
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep test-A $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-B $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+# Check that CREATE INSTANCE parses options and handles grammar errors
+# correctly. Check that strings with spaces are handled correctly,
+# unknown (for mysqld) options should also be handled.
+
+# - check handling of extra spaces;
+
+--echo --------------------------------------------------------------------
+--exec grep test-C $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
+
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep test-C1 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-C2 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+# - check handling of grammar error;
+
+--echo --------------------------------------------------------------------
+--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
+CREATE INSTANCE mysqld7 test-D = test-D-value ;
+SHOW INSTANCES;
+
+--error ER_SYNTAX_ERROR
+CREATE INSTANCE mysqld8 test-E 0 ;
+SHOW INSTANCES;
+
+--error ER_SYNTAX_ERROR
+CREATE INSTANCE mysqld8 test-F = ;
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+# - check parsing of string option values
+
+--echo --------------------------------------------------------------------
+--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
+SHOW INSTANCES;
+
+CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
+# test-3='abc def'
+SHOW INSTANCES;
+
+CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
+SHOW INSTANCES;
+
+CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
+# test-6=abc
+SHOW INSTANCES;
+
+--error ER_SYNTAX_ERROR
+CREATE INSTANCE mysqld10 test-bad=' \ ';
+SHOW INSTANCES;
+
+--echo --------------------------------------------------------------------
+--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-5 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-6 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-7 $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+--exec grep test-bad $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+
+# Check that CREATE INSTANCE allows to create instances only with properly
+# formed names (mysqld*).
+
+--error 3014 # ER_MALFORMED_INSTANCE_NAME
+CREATE INSTANCE qqq1;
+
diff --git a/mysql-test/t/im_life_cycle-im.opt b/mysql-test/t/im_life_cycle-im.opt
new file mode 100644
index 00000000000..34b74ce0c95
--- /dev/null
+++ b/mysql-test/t/im_life_cycle-im.opt
@@ -0,0 +1 @@
+--monitoring-interval=1
diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest
index 246843a022b..d71cdc86624 100644
--- a/mysql-test/t/im_life_cycle.imtest
+++ b/mysql-test/t/im_life_cycle.imtest
@@ -17,11 +17,15 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.1.
+--echo --------------------------------------------------------------------
+
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld2;
###########################################################################
#
@@ -33,20 +37,22 @@ SHOW INSTANCE STATUS mysqld2;
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.2.
+--echo --------------------------------------------------------------------
+
START INSTANCE mysqld2;
-# FIXME
+# FIXME: START INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld2;
---connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
+--connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD2_PORT,$IM_MYSQLD2_SOCK)
--connection mysql_con
---replace_result $IM_MYSQLD1_PORT IM_MYSQLD1_PORT
+--replace_result $IM_MYSQLD2_PORT IM_MYSQLD2_PORT
SHOW VARIABLES LIKE 'port';
--connection default
@@ -61,9 +67,15 @@ SHOW VARIABLES LIKE 'port';
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.3.
+--echo --------------------------------------------------------------------
+
STOP INSTANCE mysqld2;
-# FIXME
+# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to stop instance.
SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION
@@ -81,16 +93,17 @@ SHOW INSTANCE STATUS mysqld2;
#
###########################################################################
---error 3000
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.4.
+--echo --------------------------------------------------------------------
+
+--error 3000 # ER_BAD_INSTANCE_NAME
START INSTANCE mysqld3;
---error 3002
+--error 3002 # ER_INSTANCE_ALREADY_STARTED
START INSTANCE mysqld1;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# START INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.5. Check that Instance Manager reports correct errors for 'STOP INSTANCE'
@@ -101,39 +114,54 @@ START INSTANCE mysqld1;
#
###########################################################################
---error 3000
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.5.
+--echo --------------------------------------------------------------------
+
+--error 3000 # ER_BAD_INSTANCE_NAME
STOP INSTANCE mysqld3;
# TODO: IM should be fixed.
# BUG#12673: Instance Manager allows to stop the instance many times
-# --error 3002
+# --error 3002 # ER_INSTANCE_ALREADY_STARTED
# STOP INSTANCE mysqld2;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# STOP INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.6. Check that Instance Manager is able to restart guarded instances.
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.6.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
###########################################################################
#
# 1.1.7. Check that Instance Manager does not restart non-guarded instance.
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.7.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
START INSTANCE mysqld2;
-# FIXME
+# FIXME: START INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
@@ -147,7 +175,13 @@ SHOW INSTANCES;
# incomplete SHOW INSTANCE STATUS command.
#
###########################################################################
---error 1149
+
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.8.
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
SHOW INSTANCE STATUS;
#
@@ -159,8 +193,13 @@ SHOW INSTANCE STATUS;
# a list as argument.
#
---error 1149
+--echo
+--echo --------------------------------------------------------------------
+--echo -- BUG#12813
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
START INSTANCE mysqld1,mysqld2,mysqld3;
---error 1149
+--error ER_SYNTAX_ERROR
STOP INSTANCE mysqld1,mysqld2,mysqld3;
diff --git a/mysql-test/t/im_options.imtest b/mysql-test/t/im_options.imtest
new file mode 100644
index 00000000000..cd905416cda
--- /dev/null
+++ b/mysql-test/t/im_options.imtest
@@ -0,0 +1,268 @@
+###########################################################################
+#
+# This test suite checks the following statements:
+# - SET <instance id>.<option name> = <option value>;
+# - UNSET <instance id>.<option name> = <option value>;
+# - FLUSH INSTANCES;
+#
+# For SET/UNSET we check that:
+# - SET ignores spaces correctly;
+# - UNSET does not allow option-value part (= <option value>);
+# - SET/UNSET can be applied several times w/o error;
+# - SET/UNSET is allowed only for stopped instances;
+# - SET/UNSET updates both the configuration cache in IM and
+# the configuration file;
+#
+# For FLUSH INSTANCES we check that:
+# - FLUSH INSTANCES is allowed only when all instances are stopped;
+#
+# According to the IM implementation details, we should play at least with the
+# following options:
+# - server_id
+# - port
+# - nonguarded
+
+# Let's test SET statement on the option 'server_id'. It's expected that
+# originally the instances have the following server ids and states:
+# - mysqld1: server_id: 1; running (online)
+# - mysqld2: server_id: 2; stopped (offline)
+#
+###########################################################################
+
+--source include/im_check_os.inc
+
+###########################################################################
+#
+# Check starting conditions.
+#
+###########################################################################
+
+# - check the configuration file;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+
+# - check the running instances.
+
+--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
+
+--connection mysql1_con
+
+SHOW VARIABLES LIKE 'server_id';
+
+--connection default
+
+# - check the internal cache.
+
+SHOW INSTANCES;
+
+###########################################################################
+#
+# Check that SET/UNSET is allowed only for stopped instances.
+#
+###########################################################################
+
+# - check that SET/UNSET is denied for running instances;
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+UNSET mysqld1.server_id;
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+SET mysqld1.server_id = 11;
+
+# - check that SET/UNSET is denied for active instances:
+# - create dummy misconfigured instance;
+# - start it;
+# - try to set/unset options;
+
+CREATE INSTANCE mysqld3 datadir = '/';
+START INSTANCE mysqld3;
+
+# FIXME: START INSTANCE should be synchronous.
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
+# NOTE: We can not analyze state of the instance here -- it can be Failed or
+# Starting because Instance Manager is trying to start the misconfigured
+# instance several times.
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+UNSET mysqld3.server_id;
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+SET mysqld3.server_id = 11;
+
+STOP INSTANCE mysqld3;
+
+# FIXME: STOP INSTANCE should be synchronous.
+--sleep 3
+# should be longer than monitoring interval and enough to stop instance.
+
+--replace_column 3 VERSION_NUMBER 4 VERSION
+SHOW INSTANCE STATUS mysqld3;
+
+# - check that SET/UNSET succeed for stopped instances;
+# - check that SET/UNSET can be applied multiple times;
+
+UNSET mysqld2.server_id;
+UNSET mysqld2.server_id;
+
+--replace_column 2 option_value
+SHOW INSTANCE OPTIONS mysqld2;
+
+SET mysqld2.server_id = 2;
+SET mysqld2.server_id = 2;
+
+--replace_column 2 option_value
+SHOW INSTANCE OPTIONS mysqld2;
+
+# - check that UNSET does not allow option-value part (= <option value>);
+
+--error ER_SYNTAX_ERROR
+UNSET mysqld2.server_id = 11;
+
+# - check that SET/UNSET working properly with multiple options;
+
+SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
+
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep ccc $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep ddd $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+
+UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
+
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep ddd $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+# - check that if some instance name is invalid or the active is active,
+# whole SET-statement will not be executed;
+
+--error 3000 # ER_BAD_INSTANCE_NAME
+SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
+
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
+
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+# - check that if some instance name is invalid or the active is active,
+# whole UNSET-statement will not be executed;
+
+--error 3000 # ER_BAD_INSTANCE_NAME
+UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+--error 3015 # ER_INSTANCE_IS_ACTIVE
+UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
+--echo --------------------------------------------------------------------
+
+DROP INSTANCE mysqld3;
+
+# - check that spaces are handled correctly;
+
+SET mysqld2.server_id=222;
+SET mysqld2.server_id = 222;
+SET mysqld2.server_id = 222 ;
+SET mysqld2 . server_id = 222 ;
+SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+
+UNSET mysqld2 . aaa , mysqld2 . bbb ;
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
+--echo --------------------------------------------------------------------
+
+###########################################################################
+#
+# Check that SET/UNSET updates both the configuration cache in IM and
+# the configuration file.
+#
+###########################################################################
+
+# - check that the configuration file has been updated (i.e. contains
+# server_id=SERVER_ID for mysqld2);
+
+--echo --------------------------------------------------------------------
+--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
+--echo --------------------------------------------------------------------
+
+# - (for mysqld1) check that the running instance has not been affected:
+# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
+# returns zero;
+
+--connection mysql1_con
+
+SHOW VARIABLES LIKE 'server_id';
+
+--connection default
+
+# - check that internal cache of Instance Manager has been affected;
+# TODO: we should check only server_id option here.
+
+# SHOW INSTANCE OPTIONS mysqld2;
+
+###########################################################################
+#
+# Check that FLUSH INSTANCES is allowed only when all instances are stopped.
+#
+###########################################################################
+
+SHOW INSTANCES;
+
+--error 3016 # ER_THERE_IS_ACTIVE_INSTACE
+FLUSH INSTANCES;
+
+STOP INSTANCE mysqld1;
+# FIXME: STOP INSTANCE should be synchronous.
+--sleep 3
+# should be longer than monitoring interval and enough to stop instance.
+
+SHOW INSTANCES;
+
+FLUSH INSTANCES;
diff --git a/mysql-test/t/im_options_set.imtest b/mysql-test/t/im_options_set.imtest
deleted file mode 100644
index a9b64861f99..00000000000
--- a/mysql-test/t/im_options_set.imtest
+++ /dev/null
@@ -1,142 +0,0 @@
-###########################################################################
-#
-# This file contains test for (3) test suite.
-#
-# Consult WL#2789 for more information.
-#
-###########################################################################
-
-#
-# Check the options-management commands:
-# - SET;
-# - FLUSH INSTANCES;
-#
-# Let's test the commands on the option 'server_id'. It's expected that
-# originally the instances have the following server ids:
-# - mysqld1: 1
-# - mysqld2: 2
-#
-# 1. SET <instance_id>.server_id= SERVER_ID); where SERVER_ID is 11 or 12.
-# 1.1. check that the configuration file has been updated (i.e. contains
-# server_id=SERVER_ID for the instance);
-# 1.2. (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns zero;
-# 1.3. check that internal cache of Instance Manager has not been affected
-# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
-#
-# 2. FLUSH INSTANCES;
-# 2.1. check that the configuration file has not been updated;
-# 2.2. (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns zero value;
-# 2.3. check that internal cache of Instance Manager has been updated (i.e.
-# SHOW INSTANCE OPTIONS <instance> contains 'server_id=SERVER_ID' line).
-#
-# 3. Restore options.
-#
-
-###########################################################################
-
---source include/im_check_os.inc
-
-###########################################################################
-#
-# 0. Check starting conditions.
-#
-###########################################################################
-
-# - check the configuration file;
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - check the running instances.
-
---connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check the internal cache.
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-# SHOW INSTANCE OPTIONS mysqld2;
-
-###########################################################################
-#
-# 1. SET <instance_id>.server_id= SERVER_ID); where SERVER_ID is 11 or 12.
-#
-###########################################################################
-
-# * mysqld1
-
-SET mysqld1.server_id = 11;
-
-# - check that the configuration file has been updated (i.e. contains
-# server_id=SERVER_ID for the instance);
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns zero;
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check that internal cache of Instance Manager has not been affected
-# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-
-# * mysqld2
-
-SET mysqld2.server_id = 12;
-
-# - check that the configuration file has been updated (i.e. contains
-# server_id=SERVER_ID for the instance);
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - check that internal cache of Instance Manager has not been affected
-# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld2;
-
-###########################################################################
-#
-# 2. FLUSH INSTANCES;
-#
-###########################################################################
-
-FLUSH INSTANCES;
-
-# - check that the configuration file has not been updated;
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns zero value;
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check that internal cache of Instance Manager has been updated (i.e.
-# SHOW INSTANCE OPTIONS <instance> contains 'server_id=' line).
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-# SHOW INSTANCE OPTIONS mysqld2;
diff --git a/mysql-test/t/im_options_unset.imtest b/mysql-test/t/im_options_unset.imtest
deleted file mode 100644
index 40629805d45..00000000000
--- a/mysql-test/t/im_options_unset.imtest
+++ /dev/null
@@ -1,150 +0,0 @@
-###########################################################################
-#
-# This file contains test for (3) test suite.
-#
-# Consult WL#2789 for more information.
-#
-###########################################################################
-
-#
-# Check the options-management commands:
-# - UNSET;
-# - FLUSH INSTANCES;
-#
-# Let's test the commands on the option 'server_id'. It's expected that
-# originally the instances have the following server ids:
-# - mysqld1: 1
-# - mysqld2: 2
-#
-# The test case:
-#
-# 1. UNSET <instance_id>.server_id;
-#
-# Do the step for both instances.
-#
-# 1.1. check that the configuration file has been updated (i.e. does not
-# contain 'server_id=' line for the instance);
-# 1.2. (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns non-zero value;
-# 1.3. check that internal cache of Instance Manager is not affected (i.e.
-# SHOW INSTANCE OPTIONS <instance> contains non-zero value for server_id);
-#
-# 2. FLUSH INSTANCES;
-#
-# Do the step for both instances.
-#
-# 2.1. check that the configuration file has not been updated (i.e. does not
-# contain 'server_id=' for the instance);
-# 2.2. (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns non-zero value;
-# 2.3. check that internal cache of Instance Manager has been updated (i.e.
-# SHOW INSTANCE OPTIONS <instance> does not contain 'server_id=' line).
-#
-
-###########################################################################
-
---source include/im_check_os.inc
-
-###########################################################################
-#
-# 0. Check starting conditions.
-#
-###########################################################################
-
-# - check the configuration file;
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - check the running instances.
-
---connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check the internal cache.
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-# SHOW INSTANCE OPTIONS mysqld2;
-
-###########################################################################
-#
-# 1. UNSET <instance_id>.server_id;
-#
-###########################################################################
-
-# * mysqld1
-
-UNSET mysqld1.server_id;
-
-# - check that the configuration file has been updated (i.e. does not
-# contain 'server_id=' line for the instance);
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
-
-# - check that the running instance has not been affected: connect to the
-# instance and check that 'SHOW VARIABLES LIKE 'server_id'' returns non-zero
-# value;
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check that internal cache of Instance Manager is not affected (i.e. SHOW
-# INSTANCE OPTIONS <instance> contains non-zero value for server_id);
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-
-# * mysqld2
-
-UNSET mysqld2.server_id;
-
-# - check that the configuration file has been updated (i.e. does not
-# contain 'server_id=' line for the instance);
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf || true;
-
-# - check that internal cache of Instance Manager is not affected (i.e. SHOW
-# INSTANCE OPTIONS <instance> contains non-zero value for server_id);
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld2;
-
-###########################################################################
-#
-# 2. FLUSH INSTANCES;
-#
-###########################################################################
-
-FLUSH INSTANCES;
-
-# - check that the configuration file has not been updated (i.e. does not
-# contain 'server_id=' for the instance);
-
---exec grep server_id $MYSQLTEST_VARDIR/im.cnf || true;
-
-# - (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns non-zero value;
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check that internal cache of Instance Manager has been updated (i.e.
-# SHOW INSTANCE OPTIONS <instance> does not contain 'server_id=' line).
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld1;
-# SHOW INSTANCE OPTIONS mysqld2;
diff --git a/mysql-test/t/im_utils-im.opt b/mysql-test/t/im_utils-im.opt
new file mode 100644
index 00000000000..34b74ce0c95
--- /dev/null
+++ b/mysql-test/t/im_utils-im.opt
@@ -0,0 +1 @@
+--monitoring-interval=1
diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest
index dc6fb93c4ff..8e8d475cfee 100644
--- a/mysql-test/t/im_utils.imtest
+++ b/mysql-test/t/im_utils.imtest
@@ -17,6 +17,9 @@
# - the second instance is offline;
#
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
#
@@ -41,8 +44,9 @@ SHOW INSTANCE OPTIONS mysqld2;
START INSTANCE mysqld2;
-# FIXME
--- sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
STOP INSTANCE mysqld2;
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index c6dd9c7226d..acb877e1e74 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -1,8 +1,8 @@
# This test uses grants, which can't get tested for embedded server
-- source include/not_embedded.inc
-# check that CSV engine was compiled in, as the result of the test
-# depends on the presence of the log tables (which are CSV-based).
+# check that CSV engine was compiled in, as the result of the test depends
+# on the presence of the log tables (which are CSV-based).
--source include/have_csv.inc
# Test for information_schema.schemata &
@@ -794,15 +794,6 @@ DROP VIEW v1;
DROP FUNCTION func1;
DROP FUNCTION func2;
-#
-# Bug #15851 Unlistable directories yield no info from information_schema
-#
-create database mysqltest;
-create table mysqltest.t1(a int);
---exec chmod -r $MYSQLTEST_VARDIR/master-data/mysqltest
-select table_schema from information_schema.tables where table_schema='mysqltest';
---exec chmod +r $MYSQLTEST_VARDIR/master-data/mysqltest
-drop database mysqltest;
#
# Bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema
@@ -814,6 +805,26 @@ table_schema='information_schema' and
group by column_type order by num;
#
+# Bug#19236 bad COLUMNS.CHARACTER_MAXIMUM_LENGHT and CHARACTER_OCTET_LENGTH
+#
+create table t1(f1 char(1) not null, f2 char(9) not null)
+default character set utf8;
+select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from
+information_schema.columns where table_schema='test' and table_name = 't1';
+drop table t1;
+
+#
+# Bug#18177 any access to INFORMATION_SCHEMA.ROUTINES crashes
+#
+use mysql;
+INSERT INTO `proc` VALUES ('test','','PROCEDURE','','SQL','CONTAINS_SQL',
+'NO','DEFINER','','','BEGIN\r\n \r\nEND','root@%','2006-03-02 18:40:03',
+'2006-03-02 18:40:03','','');
+select routine_name from information_schema.routines;
+delete from proc where name='';
+use test;
+
+#
# End of 5.0 tests.
#
# Show engines
@@ -832,4 +843,22 @@ select user,db from information_schema.processlist;
connection default;
drop user user3148@localhost;
+#
+# Bug#16681 information_schema shows forbidden VIEW details
+#
+grant select on test.* to mysqltest_1@localhost;
+create table t1 (id int);
+create view v1 as select * from t1;
+create definer = mysqltest_1@localhost
+sql security definer view v2 as select 1;
+
+connect (con16681,localhost,mysqltest_1,,test);
+connection con16681;
+
+select * from information_schema.views
+where table_name='v1' or table_name='v2';
+connection default;
+drop view v1, v2;
+drop table t1;
+drop user mysqltest_1@localhost;
diff --git a/mysql-test/t/information_schema_chmod.test b/mysql-test/t/information_schema_chmod.test
new file mode 100644
index 00000000000..c7ea2b03890
--- /dev/null
+++ b/mysql-test/t/information_schema_chmod.test
@@ -0,0 +1,23 @@
+#
+# Due to "Bug#18474 Unlistable directories yield no info from
+# information_schema, part2" this test can't be run on Window with our
+# current test framework. When "chmod -r" is done within cygwin the
+# MySQL Server can still read the directory.
+# Manual testing shows the functionalty to skip unlistable directories
+# works on windows
+#
+--source include/not_windows.inc
+
+# This test uses chmod, can't be run with root permissions
+-- source include/not_as_root.inc
+
+
+#
+# Bug #15851 Unlistable directories yield no info from information_schema
+#
+create database mysqltest;
+create table mysqltest.t1(a int);
+--exec chmod -r $MYSQLTEST_VARDIR/master-data/mysqltest
+select table_schema from information_schema.tables where table_schema='mysqltest';
+--exec chmod +r $MYSQLTEST_VARDIR/master-data/mysqltest
+drop database mysqltest;
diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test
index 9cd64a54ad9..195bf57a880 100644
--- a/mysql-test/t/information_schema_inno.test
+++ b/mysql-test/t/information_schema_inno.test
@@ -21,3 +21,35 @@ select * from information_schema.KEY_COLUMN_USAGE where
TABLE_SCHEMA= "test";
drop table t3, t2, t1;
+
+#
+# Test for REFERENTIAL_CONSTRAINTS table
+#
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT NOT NULL,
+ PRIMARY KEY(a1, a2)) ENGINE=INNODB;
+CREATE TABLE t2(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A1
+ FOREIGN KEY (b1, b2) REFERENCES t1(a1, a2)
+ ON UPDATE CASCADE ON DELETE NO ACTION) ENGINE=INNODB;
+CREATE TABLE t3(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A2
+ FOREIGN KEY (b1, b2) REFERENCES t2(b1, b2)
+ ON UPDATE SET NULL ON DELETE RESTRICT) ENGINE=INNODB;
+CREATE TABLE t4(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A3
+ FOREIGN KEY (b1, b2) REFERENCES t3(b1, b2)
+ ON UPDATE NO ACTION ON DELETE SET NULL) ENGINE=INNODB;
+CREATE TABLE t5(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A4
+ FOREIGN KEY (b1, b2) REFERENCES t4(b1, b2)
+ ON UPDATE RESTRICT ON DELETE CASCADE) ENGINE=INNODB;
+
+
+select a.CONSTRAINT_SCHEMA, b.TABLE_NAME, CONSTRAINT_TYPE,
+ b.CONSTRAINT_NAME, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME,
+ MATCH_OPTION, UPDATE_RULE, DELETE_RULE
+from information_schema.TABLE_CONSTRAINTS a,
+ information_schema.REFERENTIAL_CONSTRAINTS b
+where a.CONSTRAINT_SCHEMA = 'test' and a.CONSTRAINT_SCHEMA = b.CONSTRAINT_SCHEMA and
+a.CONSTRAINT_NAME = b.CONSTRAINT_NAME;
+drop tables t5, t4, t3, t2, t1;
diff --git a/mysql-test/t/innodb-master.opt b/mysql-test/t/innodb-master.opt
index 4cb927540bf..4901efb416c 100644
--- a/mysql-test/t/innodb-master.opt
+++ b/mysql-test/t/innodb-master.opt
@@ -1 +1 @@
---binlog_cache_size=32768
+--binlog_cache_size=32768 --innodb_lock_wait_timeout=1
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index ab408e9b4a5..92e060eed92 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1,3 +1,16 @@
+#######################################################################
+# #
+# Please, DO NOT TOUCH this file as well as the innodb.result file. #
+# These files are to be modified ONLY BY INNOBASE guys. #
+# #
+# Use innodb_mysql.[test|result] files instead. #
+# #
+# If nevertheless you need to make some changes here, please, forward #
+# your commit message To: dev@innodb.com Cc: dev-innodb@mysql.com #
+# (otherwise your changes may be erased). #
+# #
+#######################################################################
+
-- source include/have_innodb.inc
#
@@ -901,10 +914,10 @@ insert into t2 (a) select b from t1;
insert into t1 (a) select b from t2;
select count(*) from t1;
--replace_column 9 #
-explain select * from t1 where c between 1 and 10000;
+explain select * from t1 where c between 1 and 2500;
update t1 set c=a;
--replace_column 9 #
-explain select * from t1 where c between 1 and 10000;
+explain select * from t1 where c between 1 and 2500;
drop table t1,t2;
#
@@ -2130,18 +2143,6 @@ disconnect a;
disconnect b;
#
-# Bug #14360: problem with intervals
-#
-
-create table t1(a date) engine=innodb;
-create table t2(a date, key(a)) engine=innodb;
-insert into t1 values('2005-10-01');
-insert into t2 values('2005-10-01');
-select * from t1, t2
- where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
-drop table t1, t2;
-
-#
# Test that cascading updates leading to duplicate keys give the correct
# error message (bug #9680)
#
@@ -2193,3 +2194,319 @@ alter table t1 drop foreign key c2_fk;
show create table t1;
#
drop table t1, t2;
+
+#
+# Bug #14360: problem with intervals
+#
+
+create table t1(a date) engine=innodb;
+create table t2(a date, key(a)) engine=innodb;
+insert into t1 values('2005-10-01');
+insert into t2 values('2005-10-01');
+select * from t1, t2
+ where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
+drop table t1, t2;
+
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+commit;
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
+where mm.id is null lock in share mode;
+drop table t1,t2;
+
+#
+# Test case where X-locks on unused rows should be released in a
+# update (because READ COMMITTED isolation level)
+#
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
+commit;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+update t1 set b = 5 where b = 1;
+connection b;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+#
+# X-lock to record (7,3) should be released in a update
+#
+select * from t1 where a = 7 and b = 3 for update;
+connection a;
+commit;
+connection b;
+commit;
+drop table t1;
+connection default;
+disconnect a;
+disconnect b;
+
+#
+# Test case where no locks should be released (because we are not
+# using READ COMMITTED isolation level)
+#
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
+commit;
+set autocommit = 0;
+select * from t1 lock in share mode;
+update t1 set b = 5 where b = 1;
+connection b;
+set autocommit = 0;
+#
+# S-lock to records (2,2),(4,2), and (6,2) should not be released in a update
+#
+--error 1205
+select * from t1 where a = 2 and b = 2 for update;
+#
+# X-lock to record (1,1),(3,1),(5,1) should not be released in a update
+#
+--error 1205
+connection a;
+commit;
+connection b;
+commit;
+connection default;
+disconnect a;
+disconnect b;
+drop table t1;
+
+#
+# Consistent read should be used in following selects
+#
+# 1) INSERT INTO ... SELECT
+# 2) UPDATE ... = ( SELECT ...)
+# 3) CREATE ... SELECT
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(d int not null, e int, primary key(d)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+connection b;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+insert into t1 select * from t2;
+update t1 set b = (select e from t2 where a = d);
+create table t3(d int not null, e int, primary key(d)) engine=innodb
+select * from t2;
+commit;
+connection a;
+commit;
+connection default;
+disconnect a;
+disconnect b;
+drop table t1, t2, t3;
+
+#
+# Consistent read should not be used if
+#
+# (a) isolation level is serializable OR
+# (b) select ... lock in share mode OR
+# (c) select ... for update
+#
+# in following queries:
+#
+# 1) INSERT INTO ... SELECT
+# 2) UPDATE ... = ( SELECT ...)
+# 3) CREATE ... SELECT
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connect (c,localhost,root,,);
+connect (d,localhost,root,,);
+connect (e,localhost,root,,);
+connect (f,localhost,root,,);
+connect (g,localhost,root,,);
+connect (h,localhost,root,,);
+connect (i,localhost,root,,);
+connect (j,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(a int not null, b int, primary key(a)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+create table t3(d int not null, b int, primary key(d)) engine=innodb;
+insert into t3 values (8,6),(12,1),(3,1);
+create table t5(a int not null, b int, primary key(a)) engine=innodb;
+insert into t5 values (1,2),(5,3),(4,2);
+create table t6(d int not null, e int, primary key(d)) engine=innodb;
+insert into t6 values (8,6),(12,1),(3,1);
+create table t8(a int not null, b int, primary key(a)) engine=innodb;
+insert into t8 values (1,2),(5,3),(4,2);
+create table t9(d int not null, e int, primary key(d)) engine=innodb;
+insert into t9 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+connection b;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+insert into t1 select * from t2;
+connection c;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+update t3 set b = (select b from t2 where a = d);
+connection d;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
+connection e;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+insert into t5 (select * from t2 lock in share mode);
+connection f;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+update t6 set e = (select b from t2 where a = d lock in share mode);
+connection g;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
+connection h;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+insert into t8 (select * from t2 for update);
+connection i;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+update t9 set e = (select b from t2 where a = d for update);
+connection j;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--send
+create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
+
+connection b;
+--error 1205
+reap;
+
+connection c;
+--error 1205
+reap;
+
+connection d;
+--error 1205
+reap;
+
+connection e;
+--error 1205
+reap;
+
+connection f;
+--error 1205
+reap;
+
+connection g;
+--error 1205
+reap;
+
+connection h;
+--error 1205
+reap;
+
+connection i;
+--error 1205
+reap;
+
+connection j;
+--error 1205
+reap;
+
+connection a;
+commit;
+
+connection default;
+disconnect a;
+disconnect b;
+disconnect c;
+disconnect d;
+disconnect e;
+disconnect f;
+disconnect g;
+disconnect h;
+disconnect i;
+disconnect j;
+drop table t1, t2, t3, t5, t6, t8, t9;
+
+# bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID"
+--error 1005
+CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
+
+#
+# Bug #17152: Wrong result with BINARY comparison on aliased column
+#
+
+CREATE TABLE t1 (
+ a BIGINT(20) NOT NULL,
+ PRIMARY KEY (a)
+ ) ENGINE=INNODB DEFAULT CHARSET=UTF8;
+
+CREATE TABLE t2 (
+ a BIGINT(20) NOT NULL,
+ b VARCHAR(128) NOT NULL,
+ c TEXT NOT NULL,
+ PRIMARY KEY (a,b),
+ KEY idx_t2_b_c (b,c(200)),
+ CONSTRAINT t_fk FOREIGN KEY (a) REFERENCES t1 (a)
+ ON DELETE CASCADE
+ ) ENGINE=INNODB DEFAULT CHARSET=UTF8;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1, 'bar', 'vbar');
+INSERT INTO t2 VALUES (1, 'BAR2', 'VBAR');
+INSERT INTO t2 VALUES (1, 'bar_bar', 'bibi');
+INSERT INTO t2 VALUES (1, 'customer_over', '1');
+
+SELECT * FROM t2 WHERE b = 'customer_over';
+SELECT * FROM t2 WHERE BINARY b = 'customer_over';
+SELECT DISTINCT p0.a FROM t2 p0 WHERE p0.b = 'customer_over';
+/* Bang: Empty result set, above was expected: */
+SELECT DISTINCT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
+SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
+
+drop table t2, t1;
+
+#
+# Bug #15680 (SPATIAL key in innodb)
+#
+--error ER_TABLE_CANT_HANDLE_SPKEYS
+create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
+
+#
+# Test optimize on table with open transaction
+#
+
+CREATE TABLE t1 ( a int ) ENGINE=innodb;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test
new file mode 100644
index 00000000000..3de55e1c403
--- /dev/null
+++ b/mysql-test/t/innodb_mysql.test
@@ -0,0 +1,131 @@
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+# BUG#16798: Uninitialized row buffer reads in ref-or-null optimizer
+# (repeatable only w/innodb).
+create table t1 (
+ c_id int(11) not null default '0',
+ org_id int(11) default null,
+ unique key contacts$c_id (c_id),
+ key contacts$org_id (org_id)
+) engine=innodb;
+insert into t1 values
+ (2,null),(120,null),(141,null),(218,7), (128,1),
+ (151,2),(234,2),(236,2),(243,2),(255,2),(259,2),(232,3),(235,3),(238,3),
+ (246,3),(253,3),(269,3),(285,3),(291,3),(293,3),(131,4),(230,4),(231,4);
+
+create table t2 (
+ slai_id int(11) not null default '0',
+ owner_tbl int(11) default null,
+ owner_id int(11) default null,
+ sla_id int(11) default null,
+ inc_web int(11) default null,
+ inc_email int(11) default null,
+ inc_chat int(11) default null,
+ inc_csr int(11) default null,
+ inc_total int(11) default null,
+ time_billed int(11) default null,
+ activedate timestamp null default null,
+ expiredate timestamp null default null,
+ state int(11) default null,
+ sla_set int(11) default null,
+ unique key t2$slai_id (slai_id),
+ key t2$owner_id (owner_id),
+ key t2$sla_id (sla_id)
+) engine=innodb;
+insert into t2(slai_id, owner_tbl, owner_id, sla_id) values
+ (1,3,1,1), (3,3,10,2), (4,3,3,6), (5,3,2,5), (6,3,8,3), (7,3,9,7),
+ (8,3,6,8), (9,3,4,9), (10,3,5,10), (11,3,11,11), (12,3,7,12);
+
+flush tables;
+select si.slai_id
+from t1 c join t2 si on
+ ((si.owner_tbl = 3 and si.owner_id = c.org_id) or
+ ( si.owner_tbl = 2 and si.owner_id = c.c_id))
+where
+ c.c_id = 218 and expiredate is null;
+
+select * from t1 where org_id is null;
+select si.slai_id
+from t1 c join t2 si on
+ ((si.owner_tbl = 3 and si.owner_id = c.org_id) or
+ ( si.owner_tbl = 2 and si.owner_id = c.c_id))
+where
+ c.c_id = 218 and expiredate is null;
+
+drop table t1, t2;
+
+#
+# Bug #12882 min/max inconsistent on empty table
+#
+
+--disable_warnings
+create table t1m (a int) engine=myisam;
+create table t1i (a int) engine=innodb;
+create table t2m (a int) engine=myisam;
+create table t2i (a int) engine=innodb;
+--enable_warnings
+insert into t2m values (5);
+insert into t2i values (5);
+
+# test with MyISAM
+select min(a) from t1m;
+select min(7) from t1m;
+select min(7) from DUAL;
+explain select min(7) from t2m join t1m;
+select min(7) from t2m join t1m;
+
+select max(a) from t1m;
+select max(7) from t1m;
+select max(7) from DUAL;
+explain select max(7) from t2m join t1m;
+select max(7) from t2m join t1m;
+
+select 1, min(a) from t1m where a=99;
+select 1, min(a) from t1m where 1=99;
+select 1, min(1) from t1m where a=99;
+select 1, min(1) from t1m where 1=99;
+
+select 1, max(a) from t1m where a=99;
+select 1, max(a) from t1m where 1=99;
+select 1, max(1) from t1m where a=99;
+select 1, max(1) from t1m where 1=99;
+
+# test with InnoDB
+select min(a) from t1i;
+select min(7) from t1i;
+select min(7) from DUAL;
+explain select min(7) from t2i join t1i;
+select min(7) from t2i join t1i;
+
+select max(a) from t1i;
+select max(7) from t1i;
+select max(7) from DUAL;
+explain select max(7) from t2i join t1i;
+select max(7) from t2i join t1i;
+
+select 1, min(a) from t1i where a=99;
+select 1, min(a) from t1i where 1=99;
+select 1, min(1) from t1i where a=99;
+select 1, min(1) from t1i where 1=99;
+
+select 1, max(a) from t1i where a=99;
+select 1, max(a) from t1i where 1=99;
+select 1, max(1) from t1i where a=99;
+select 1, max(1) from t1i where 1=99;
+
+# mixed MyISAM/InnoDB test
+explain select count(*), min(7), max(7) from t1m, t1i;
+select count(*), min(7), max(7) from t1m, t1i;
+
+explain select count(*), min(7), max(7) from t1m, t2i;
+select count(*), min(7), max(7) from t1m, t2i;
+
+explain select count(*), min(7), max(7) from t2m, t1i;
+select count(*), min(7), max(7) from t2m, t1i;
+
+drop table t1m, t1i, t2m, t2i;
+
diff --git a/mysql-test/t/innodb_unsafe_binlog-master.opt b/mysql-test/t/innodb_unsafe_binlog-master.opt
index 503c8457b2c..9581c225d6d 100644
--- a/mysql-test/t/innodb_unsafe_binlog-master.opt
+++ b/mysql-test/t/innodb_unsafe_binlog-master.opt
@@ -1 +1 @@
---innodb_locks_unsafe_for_binlog=true
+--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=1
diff --git a/mysql-test/t/innodb_unsafe_binlog.test b/mysql-test/t/innodb_unsafe_binlog.test
index e4cb683e59d..af1091e4421 100644
--- a/mysql-test/t/innodb_unsafe_binlog.test
+++ b/mysql-test/t/innodb_unsafe_binlog.test
@@ -1,7 +1,9 @@
-- source include/have_innodb.inc
#
-# Note that these tests uses a innodb_locks_unsafe_for_binlog option.
-#
+# Note that these tests uses options
+# innodb_locks_unsafe_for_binlog = true
+# innodb_lock_timeout = 5
+
#
# Test cases for a bug #15650
#
@@ -33,7 +35,7 @@ connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
create table t1(a int not null, b int, primary key(a)) engine=innodb;
-insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
commit;
set autocommit = 0;
select * from t1 lock in share mode;
@@ -50,6 +52,197 @@ commit;
connection b;
commit;
drop table t1;
+connection default;
+disconnect a;
+disconnect b;
+
+#
+# unlock row test
+#
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
+commit;
+set autocommit = 0;
+update t1 set b = 5 where b = 1;
+connection b;
+set autocommit = 0;
+#
+# X-lock to record (7,3) should be released in a update
+#
+select * from t1 where a = 7 and b = 3 for update;
+commit;
+connection a;
+commit;
+drop table t1;
+connection default;
+disconnect a;
+disconnect b;
+
+
+#
+# Consistent read should be used in following selects
+#
+# 1) INSERT INTO ... SELECT
+# 2) UPDATE ... = ( SELECT ...)
+# 3) CREATE ... SELECT
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(d int not null, e int, primary key(d)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+connection b;
+set autocommit = 0;
+insert into t1 select * from t2;
+update t1 set b = (select e from t2 where a = d);
+create table t3(d int not null, e int, primary key(d)) engine=innodb
+select * from t2;
+commit;
+connection a;
+commit;
+connection default;
disconnect a;
disconnect b;
+drop table t1, t2, t3;
+#
+# Consistent read should not be used if
+#
+# (a) isolation level is serializable OR
+# (b) select ... lock in share mode OR
+# (c) select ... for update
+#
+# in following queries:
+#
+# 1) INSERT INTO ... SELECT
+# 2) UPDATE ... = ( SELECT ...)
+# 3) CREATE ... SELECT
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connect (c,localhost,root,,);
+connect (d,localhost,root,,);
+connect (e,localhost,root,,);
+connect (f,localhost,root,,);
+connect (g,localhost,root,,);
+connect (h,localhost,root,,);
+connect (i,localhost,root,,);
+connect (j,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, primary key(a)) engine=innodb;
+insert into t1 values (1,2),(5,3),(4,2);
+create table t2(a int not null, b int, primary key(a)) engine=innodb;
+insert into t2 values (8,6),(12,1),(3,1);
+create table t3(d int not null, b int, primary key(d)) engine=innodb;
+insert into t3 values (8,6),(12,1),(3,1);
+create table t5(a int not null, b int, primary key(a)) engine=innodb;
+insert into t5 values (1,2),(5,3),(4,2);
+create table t6(d int not null, e int, primary key(d)) engine=innodb;
+insert into t6 values (8,6),(12,1),(3,1);
+create table t8(a int not null, b int, primary key(a)) engine=innodb;
+insert into t8 values (1,2),(5,3),(4,2);
+create table t9(d int not null, e int, primary key(d)) engine=innodb;
+insert into t9 values (8,6),(12,1),(3,1);
+commit;
+set autocommit = 0;
+select * from t2 for update;
+connection b;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+insert into t1 select * from t2;
+connection c;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+update t3 set b = (select b from t2 where a = d);
+connection d;
+set autocommit = 0;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+--send
+create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
+connection e;
+set autocommit = 0;
+--send
+insert into t5 (select * from t2 lock in share mode);
+connection f;
+set autocommit = 0;
+--send
+update t6 set e = (select b from t2 where a = d lock in share mode);
+connection g;
+set autocommit = 0;
+--send
+create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
+connection h;
+set autocommit = 0;
+--send
+insert into t8 (select * from t2 for update);
+connection i;
+set autocommit = 0;
+--send
+update t9 set e = (select b from t2 where a = d for update);
+connection j;
+set autocommit = 0;
+--send
+create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
+
+connection b;
+--error 1205
+reap;
+
+connection c;
+--error 1205
+reap;
+
+connection d;
+--error 1205
+reap;
+
+connection e;
+--error 1205
+reap;
+
+connection f;
+--error 1205
+reap;
+
+connection g;
+--error 1205
+reap;
+
+connection h;
+--error 1205
+reap;
+
+connection i;
+--error 1205
+reap;
+
+connection j;
+--error 1205
+reap;
+
+connection a;
+commit;
+
+connection default;
+disconnect a;
+disconnect b;
+disconnect c;
+disconnect d;
+disconnect e;
+disconnect f;
+disconnect g;
+disconnect h;
+disconnect i;
+disconnect j;
+drop table t1, t2, t3, t5, t6, t8, t9;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index c194213e0c9..dc4e240750c 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -779,3 +779,47 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%' OR FALSE;
DROP TABLE t1,t2;
+
+#
+# Bug 19396: LEFT OUTER JOIN over views in curly braces
+#
+--disable_warnings
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+
+CREATE TABLE t1 (a int);
+CREATE table t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3);
+INSERT INTO t2 VALUES (2), (3);
+
+CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b;
+CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a;
+
+SELECT v1.a, v2. b
+ FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3)
+ GROUP BY v1.a;
+SELECT v1.a, v2. b
+ FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) }
+ GROUP BY v1.a;
+
+DROP VIEW v1,v2;
+DROP TABLE t1,t2;
+
+#
+# Bug 19816: LEFT OUTER JOIN with constant ORed predicates in WHERE clause
+#
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (2), (3);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1 OR 1);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (0 OR 1);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 2=2);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 1=0);
+
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index df584021af1..4001e0df4af 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -149,6 +149,7 @@ show status like 'key_blocks_used';
--replace_result 1812 KEY_BLOCKS_UNUSED 1793 KEY_BLOCKS_UNUSED 1674 KEY_BLOCKS_UNUSED 1818 KEY_BLOCKS_UNUSED 1824 KEY_BLOCKS_UNUSED
show status like 'key_blocks_unused';
+
# Cleanup
# We don't reset keycache2 as we want to ensure that mysqld will reset it
set global keycache2.key_buffer_size=0;
@@ -157,7 +158,7 @@ set global keycache2.key_buffer_size=0;
set global keycache3.key_buffer_size=100;
set global keycache3.key_buffer_size=0;
-# Test case for buf 6447
+# Test case for bug 6447
create table t1 (mytext text, FULLTEXT (mytext));
insert t1 values ('aaabbb');
@@ -169,6 +170,44 @@ check table t1;
drop table t1;
#
+# Bug #19079: corrupted index when key_cache_block_size is not multiple of
+# myisam_block_size
+
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1);
+SELECT @@key_cache_block_size;
+CHECK TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1,0);
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+SELECT COUNT(*) FROM t1;
+SELECT @@key_cache_block_size;
+CHECK TABLE t1;
+DROP TABLE t1,t2;
+
+#
# Bug#10473 - Can't set 'key_buffer_size' system variable to ZERO
# (One cannot drop the default key cache.)
#
diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test
index 3b412d9e793..5b79e5e4625 100644
--- a/mysql-test/t/log_tables.test
+++ b/mysql-test/t/log_tables.test
@@ -16,10 +16,10 @@ use mysql;
#
truncate table general_log;
---replace_column 1 TIMESTAMP
+--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID
select * from general_log;
truncate table slow_log;
---replace_column 1 TIMESTAMP
+--replace_column 1 TIMESTAMP 2 USER_HOST
select * from slow_log;
#
@@ -31,7 +31,7 @@ select * from slow_log;
#
truncate table general_log;
---replace_column 1 TIMESTAMP
+--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID
select * from general_log where argument like '%general_log%';
@@ -47,6 +47,7 @@ insert into join_test values ("User performed a usual SQL query", "Query");
insert into join_test values ("New DB connection was registered", "Connect");
insert into join_test values ("Get the table info", "Field List");
+--replace_column 2 USER_HOST
select verbose_comment, user_host, argument
from mysql.general_log join join_test
on (mysql.general_log.command_type = join_test.command_type);
@@ -63,10 +64,10 @@ flush logs;
# check locking of the log tables
#
---error 1533
+--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.general_log WRITE;
---error 1533
+--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.slow_log WRITE;
#
@@ -75,10 +76,10 @@ lock tables mysql.slow_log WRITE;
# tables are always opened and locked by the logger.
#
---error 1534
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.general_log READ;
---error 1534
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.slow_log READ;
#
@@ -156,7 +157,7 @@ truncate table mysql.general_log;
set names utf8;
create table bug16905 (s char(15) character set utf8 default 'пуÑто');
insert into bug16905 values ('новое');
---replace_column 1 TIMESTAMP
+--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID
select * from mysql.general_log;
drop table bug16905;
@@ -167,7 +168,7 @@ drop table bug16905;
truncate table mysql.slow_log;
set session long_query_time=1;
select sleep(2);
---replace_column 1 TIMESTAMP, 3 USER_HOST, 4 QUERY_TIME
+--replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME
select * from mysql.slow_log;
# kill all connections
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 9fe7bb787cb..9fee4a03b81 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -382,3 +382,15 @@ check table t1, t2;
drop table t1, t2, t3;
# End of 4.1 tests
+
+#
+# BUG#10952 - alter table ... lost data without errors and warnings
+#
+drop table if exists t1;
+create table t1 (c char(20)) engine=MyISAM;
+insert into t1 values ("Monty"),("WAX"),("Walrus");
+--error 1031
+alter table t1 engine=MERGE;
+drop table t1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/myisam-system.test b/mysql-test/t/myisam-system.test
new file mode 100644
index 00000000000..43fbaabf698
--- /dev/null
+++ b/mysql-test/t/myisam-system.test
@@ -0,0 +1,21 @@
+#
+# Test how DROP TABLE works if the index or data file doesn't exists
+
+# Initialise
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
+drop table if exists t1;
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
+--error 1051,6
+drop table t1;
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYD ;
+--error 1105,6,29
+drop table t1;
+--error 1051
+drop table t1;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 15533ca00e6..a77537f3ff5 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -727,23 +727,6 @@ 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 $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
-drop table if exists t1;
-create table t1 (a int) engine=myisam;
-system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
---error 1051,6
-drop table t1;
-create table t1 (a int) engine=myisam;
-system rm $MYSQLTEST_VARDIR/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
#
@@ -824,3 +807,66 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
create table t4 (c1 int) engine=myisam pack_keys=2;
drop table t1, t2, t3;
+#
+# Test of key_block_size
+#
+
+create table t1 (a int not null, key `a` (a) key_block_size=1024);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, key `a` (a) key_block_size=2048);
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a));
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
+show create table t1;
+alter table t1 key_block_size=2048;
+show create table t1;
+alter table t1 add c int, add key (c);
+show create table t1;
+alter table t1 key_block_size=0;
+alter table t1 add d int, add key (d);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
+show create table t1;
+drop table t1;
+
+
+# Test limits and errors of key_block_size
+
+create table t1 (a int not null, key `a` (a) key_block_size=512);
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, key `a` (a) key_block_size=1025);
+show create table t1;
+drop table t1;
+
+--error 1064
+create table t1 (a int not null, key key_block_size=1024 (a));
+--error 1064
+create table t1 (a int not null, key `a` key_block_size=1024 (a));
+
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 95cba2743da..ac4c323f51e 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -67,3 +67,16 @@ drop table t1;
#
--exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int, k char(25) charset utf8); insert into t1 (i) values (1); insert into t1 (k) values ('<----------------------->'); insert into t1 (k) values ('<-----'); insert into t1 (k) values ('Τη γλώσσα'); insert into t1 (k) values ('á›–áš´ áš·á›–á›'); select * from t1; DROP TABLE t1;"
+#
+# "DESCRIBE" commands may return strange NULLness flags.
+#
+--exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;"
+
+#
+# Bug#19564: mysql displays NULL instead of space
+#
+--exec $MYSQL -t test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;"
+
+--echo End of 5.0 tests
+
+
diff --git a/mysql-test/t/mysql_client_test-master.opt b/mysql-test/t/mysql_client_test-master.opt
new file mode 100644
index 00000000000..3711946168d
--- /dev/null
+++ b/mysql-test/t/mysql_client_test-master.opt
@@ -0,0 +1 @@
+--log --log-output=FILE
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 1bede1d5c9a..b76a5103120 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -124,9 +124,22 @@ select HEX(f) from t3;
select HEX(f) from t04;
select HEX(f) from t4;
+#
+# BUG#14157: utf8 encoding in binlog without set character_set_client
+#
+# BUG:
+# This test only works on the MySQL-internal rpl machines.
+# Needs to be fixed. Problem is that koi8r is not installed
+# on many machines.
+#
+flush logs;
+# --exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t5 select * from `ÑÝÉË`'
+# resulted log is client charset insensitive (latin1 not koi8r) as it must be
+# --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1
+#select * from t5 /* must be (1),(1) */;
# clean up
drop table t1, t2, t03, t04, t3, t4;
-# End of 4.1 tests
+# End of 5.0 tests
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 5ba7838bb81..732a3ce89da 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -11,7 +11,7 @@ drop view if exists v1, v2, v3;
# XML output
-CREATE TABLE t1(a int);
+CREATE TABLE t1(a int, key (a)) key_block_size=1024;
INSERT INTO t1 VALUES (1), (2);
--exec $MYSQL_DUMP --skip-create --skip-comments -X test t1
DROP TABLE t1;
@@ -713,6 +713,35 @@ select * from t1;
drop table t1;
#
+# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]"
+#
+create table `t1` (
+ t1_name varchar(255) default null,
+ t1_id int(10) unsigned not null auto_increment,
+ key (t1_name),
+ primary key (t1_id)
+) auto_increment = 1000 default charset=latin1;
+
+insert into t1 (t1_name) values('bla');
+insert into t1 (t1_name) values('bla');
+insert into t1 (t1_name) values('bla');
+
+select * from t1;
+
+show create table `t1`;
+
+--exec $MYSQL_DUMP --skip-comments test t1 > $MYSQLTEST_VARDIR/tmp/bug19025.sql
+DROP TABLE `t1`;
+
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug19025.sql
+
+select * from t1;
+
+show create table `t1`;
+
+drop table `t1`;
+
+--echo End of 4.1 tests
# Bug #13318: Bad result with empty field and --hex-blob
#
create table t1 (a binary(1), b blob);
@@ -721,7 +750,6 @@ insert into t1 values ('','');
--exec $MYSQL_DUMP --skip-comments --hex-blob test t1
drop table t1;
-# End of 4.1 tests
#
# dump of view
@@ -1158,7 +1186,7 @@ select * from words2;
# Drop table "words" and run with threads, should fail
drop table words;
---replace_regex /.*mysqlimport/mysql-import/
+--replace_regex /.*mysqlimport(\.exe)*/mysql-import/
--error 1
--exec $MYSQL_IMPORT --silent --use-threads=2 test $MYSQLTEST_VARDIR/tmp/t1.txt $MYSQLTEST_VARDIR/tmp/t2.txt $MYSQLTEST_VARDIR/std_data_ln/words.dat $MYSQLTEST_VARDIR/std_data_ln/words2.dat 2>&1
@@ -1174,8 +1202,8 @@ create database first;
use first;
set time_zone = 'UTC';
-## prove one works
-create event ee1 on schedule at '2035-12-31 20:01:23' do set @a=5;
+## prove one works (with spaces and tabs on the end)
+create event ee1 on schedule at '2035-12-31 20:01:23' do set @a=5;
show events;
show create event ee1;
--exec $MYSQL_DUMP --events first > $MYSQLTEST_VARDIR/tmp/bug16853-1.sql
@@ -1187,10 +1215,10 @@ use second;
show events;
show create event ee1;
-## prove three works
+## prove three works (with spaces and tabs on the end)
# start with one from the previous restore
-create event ee2 on schedule at '2018-12-31 21:01:23' do set @a=5;
-create event ee3 on schedule at '2030-12-31 22:01:23' do set @a=5;
+create event ee2 on schedule at '2018-12-31 21:01:23' do set @a=5;
+create event ee3 on schedule at '2030-12-31 22:01:23' do set @a=5;
show events;
--exec $MYSQL_DUMP --events second > $MYSQLTEST_VARDIR/tmp/bug16853-2.sql
drop database second;
diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test
index a12ac20a259..8e3b4a6ca89 100644
--- a/mysql-test/t/ndb_alter_table.test
+++ b/mysql-test/t/ndb_alter_table.test
@@ -3,7 +3,7 @@
-- source include/not_embedded.inc
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
drop database if exists mysqltest;
--enable_warnings
@@ -327,3 +327,74 @@ drop table t1;
# End of 4.1 tests
+# On-line alter table
+
+
+CREATE TABLE t1 (
+ auto int(5) unsigned NOT NULL auto_increment,
+ string char(10),
+ vstring varchar(10),
+ bin binary(2),
+ 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;
+
+CREATE TEMPORARY TABLE ndb_show_tables (id INT, type VARCHAR(20), state VARCHAR(20), logging VARCHAR(20), _database VARCHAR(255), _schema VARCHAR(20), name VARCHAR(255));
+
+--disable_warnings
+--exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+--enable_warnings
+
+set @t1_id = (select id from ndb_show_tables where name like '%t1%');
+truncate ndb_show_tables;
+
+alter table t1 change tiny new_tiny tinyint(4) DEFAULT '0' NOT NULL;
+create index i1 on t1(medium);
+alter table t1 add index i2(long_int);
+drop index i1 on t1;
+
+--disable_warnings
+--exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+--enable_warnings
+
+select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%';
+
+DROP TABLE t1, ndb_show_tables;
+
+# simple test that auto incr is not lost at rename or alter
+create table t1 (a int primary key auto_increment, b int) engine=ndb;
+insert into t1 (b) values (101),(102),(103);
+select * from t1 where a = 3;
+alter table t1 rename t2;
+insert into t2 (b) values (201),(202),(203);
+select * from t2 where a = 6;
+alter table t2 add c int;
+insert into t2 (b) values (301),(302),(303);
+select * from t2 where a = 9;
+alter table t2 rename t1;
+insert into t1 (b) values (401),(402),(403);
+select * from t1 where a = 12;
+drop table t1;
diff --git a/mysql-test/t/ndb_alter_table_row.test b/mysql-test/t/ndb_alter_table3.test
index 9c834e0dd20..a5fe613adcf 100644
--- a/mysql-test/t/ndb_alter_table_row.test
+++ b/mysql-test/t/ndb_alter_table3.test
@@ -1,7 +1,6 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
--- source include/have_binlog_format_row.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/t/ndb_alter_table_stm.test b/mysql-test/t/ndb_alter_table_stm.test
deleted file mode 100644
index bf162dd0d50..00000000000
--- a/mysql-test/t/ndb_alter_table_stm.test
+++ /dev/null
@@ -1,55 +0,0 @@
--- source include/have_ndb.inc
--- source include/have_multi_ndb.inc
--- source include/not_embedded.inc
--- source include/have_binlog_format_statement.inc
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
-connection server1;
-create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
-engine=ndb;
-insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
-create index c on t1(c);
-connection server2;
-select * from t1 where c = 'two';
-connection server1;
-alter table t1 drop index c;
-connection server2;
-
---disable_result_log
---error 0,1412
-select * from t1 where c = 'two';
---enable_result_log
-
-select * from t1 where c = 'two';
-connection server1;
-drop table t1;
-
-connection server1;
-create table t3 (a int primary key) engine=ndbcluster;
-
-connection server2;
-begin;
-insert into t3 values (1);
-
-connection server1;
-alter table t3 rename t4;
-
-connection server2;
-# with rbr the below will not work as the "alter" event
-# explicitly invalidates the dictionary cache.
-# This should work as transaction is ongoing...
-delete from t3;
-insert into t3 values (1);
-commit;
-
-# This should fail as its a new transaction
---error 1015
-select * from t3;
-select * from t4;
-drop table t4;
-show tables;
-connection server1;
-
diff --git a/mysql-test/t/ndb_autodiscover3.test b/mysql-test/t/ndb_autodiscover3.test
new file mode 100644
index 00000000000..ed75c89cdd1
--- /dev/null
+++ b/mysql-test/t/ndb_autodiscover3.test
@@ -0,0 +1,76 @@
+-- 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
+
+#
+# Transaction ongoing while cluster is restarted
+#
+--connection server1
+create table t1 (a int key) engine=ndbcluster;
+
+begin;
+insert into t1 values (1);
+
+--exec $NDB_MGM --no-defaults -e "all restart" >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
+
+--error 1297
+insert into t1 values (2);
+--error 1296
+commit;
+
+drop table t1;
+
+#
+# Stale cache after restart -i
+#
+--connection server1
+create table t2 (a int, b int, primary key(a,b)) engine=ndbcluster;
+insert into t2 values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1);
+select * from t2 order by a limit 3;
+
+--exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
+# to ensure mysqld has connected again, and recreated system tables
+--exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -r 30 -d cluster apply_status >> $NDB_TOOLS_OUTPUT
+
+--connection server2
+--error ER_NO_SUCH_TABLE
+select * from t2;
+show tables like 't2';
+reset master;
+create table t2 (a int key) engine=ndbcluster;
+insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t2 order by a limit 3;
+
+# server 1 should have a stale cache, and in this case wrong frm, transaction must be retried
+--connection server1
+select * from t2 order by a limit 3;
+reset master;
+
+--exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
+# to ensure mysqld has connected again, and recreated system tables
+--exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -r 30 -d cluster apply_status >> $NDB_TOOLS_OUTPUT
+
+--connection server1
+--error ER_NO_SUCH_TABLE
+select * from t2;
+show tables like 't2';
+reset master;
+create table t2 (a int key) engine=ndbcluster;
+insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t2 order by a limit 3;
+
+# server 2 should have a stale cache, but with right frm, transaction need not be retried
+--connection server2
+select * from t2 order by a limit 3;
+reset master;
+
+drop table t2;
+# End of 4.1 tests
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index ab62e3dd13a..d11e30ae97d 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -6,6 +6,17 @@ DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;
drop database if exists mysqltest;
--enable_warnings
+## workaround for bug#16445
+## remove to reproduce bug and run tests from ndb start
+## and with ndb_autodiscover disabled. Fails on Linux 50 % of the times
+#CREATE TABLE t1 (
+# pk1 INT NOT NULL PRIMARY KEY,
+# attr1 INT NOT NULL,
+# attr2 INT,
+# attr3 VARCHAR(10)
+#) ENGINE=ndbcluster;
+#drop table t1;
+
#
# Basic test to show that the NDB
# table handler is working
diff --git a/mysql-test/t/ndb_binlog_discover.test b/mysql-test/t/ndb_binlog_discover.test
new file mode 100644
index 00000000000..e74bd3380bd
--- /dev/null
+++ b/mysql-test/t/ndb_binlog_discover.test
@@ -0,0 +1,19 @@
+-- source include/have_ndb.inc
+-- source include/have_binlog_format_row.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug #14516 Restart of cluster can cause NDB API replication failure
+#
+create table t1 (a int key) engine=ndb;
+reset master;
+--exec $NDB_MGM --no-defaults -e "all restart -n" > /dev/null
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults --not-started > /dev/null
+--exec $NDB_MGM --no-defaults -e "all start" > /dev/null
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults > /dev/null
+insert into t1 values(1);
+--source include/show_binlog_events.inc
+drop table t1;
diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test
index f80b7f71281..d6e0edc89f0 100644
--- a/mysql-test/t/ndb_blob.test
+++ b/mysql-test/t/ndb_blob.test
@@ -403,10 +403,85 @@ create table t1 (
insert into t1 (msg) values(
'Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
-so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).');
+so bad data will not crash kernel.');
select * from t1;
drop table t1;
+# -- bug #19201
+create table t1 (
+ a int primary key not null auto_increment,
+ b text
+) engine=ndbcluster;
+--disable_query_log
+set autocommit=1;
+# more rows than batch size (64)
+# for this bug no blob parts would be necessary
+let $1 = 500;
+while ($1)
+{
+ insert into t1 (b) values (repeat('x',4000));
+ dec $1;
+}
+--enable_query_log
+select count(*) from t1;
+truncate t1;
+select count(*) from t1;
+drop table t1;
+
+# -- bug#19956 - var* key, complex key
+
+create table t1 (
+ a varchar(40) not null,
+ b mediumint not null,
+ t text,
+ c varchar(2) not null,
+ d bigint not null,
+ primary key (a,b,c),
+ key (c,a),
+ unique key (d)
+) engine=ndb;
+
+--disable_query_log
+set @s1 = 'rggurloniukyehuxdbfkkyzlceixzrehqhvxvxbpwizzvjzpucqmzrhzxzfau';
+set @s2 = 'ykyymbzqgqlcjhlhmyqelfoaaohvtbekvifukdtnvcrrjveevfakxarxexomz';
+set @s3 = 'dbnfqyzgtqxalcrwtfsqabknvtfcbpoonxsjiqvmhnfikxxhcgoexlkoezvah';
+set @v1 = repeat(@s1,123);
+set @v2 = repeat(@s2,234);
+set @v3 = repeat(@s3,345);
+set @v4 = NULL;
+--enable_query_log
+
+insert into t1 (a,b,c,d,t) values ('a',1110,'a',1,@v1);
+insert into t1 (a,b,c,d,t) values ('b',1110,'a',2,@v2);
+insert into t1 (a,b,c,d,t) values ('a',1110,'b',3,@v3);
+insert into t1 (a,b,c,d,t) values ('b',1110,'b',4,@v4);
+select a,b,c,d,sha1(t) from t1 order by c,a;
+
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='a';
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='b';
+
+update t1 set t=@v4 where a='b' and b=1110 and c='a';
+update t1 set t=@v2 where a='b' and b=1110 and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+
+update t1 set t=@v2 where d=2;
+update t1 set t=@v4 where d=4;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+
+update t1 set t=@v4 where a='b' and c='a';
+update t1 set t=@v2 where a='b' and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+
+update t1 set t=@v2 where b+d=1112;
+update t1 set t=@v4 where b+d=1114;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+
+delete from t1 where a='a' and b=1110 and c='a';
+delete from t1 where a='b' and c='a';
+delete from t1 where d=3;
+delete from t1 where b+d=1114;
+select count(*) from t1;
+
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/ndb_blob_partition.test b/mysql-test/t/ndb_blob_partition.test
deleted file mode 100644
index a3948cc9491..00000000000
--- a/mysql-test/t/ndb_blob_partition.test
+++ /dev/null
@@ -1,93 +0,0 @@
---source include/have_ndb.inc
--- source include/not_embedded.inc
-
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
-#
-# Minimal NDB blobs test with range partitions.
-#
-
-create table t1 (
- a mediumint not null,
- b text not null,
- c int not null,
- d longblob,
- primary key using hash (a,c),
- unique key (c)
-)
- engine=ndb
- partition by range (c)
- partitions 3
- ( partition p1 values less than (200),
- partition p2 values less than (300),
- partition p3 values less than (400));
-
---disable_query_log
-sleep 1;
-
-# length 61
-set @s0 = 'rggurloniukyehuxdbfkkyzlceixzrehqhvxvxbpwizzvjzpucqmzrhzxzfau';
-set @s1 = 'ykyymbzqgqlcjhlhmyqelfoaaohvtbekvifukdtnvcrrjveevfakxarxexomz';
-set @s2 = 'dbnfqyzgtqxalcrwtfsqabknvtfcbpoonxsjiqvmhnfikxxhcgoexlkoezvah';
-
-set @v1 = repeat(@s0, 100); -- 1d42dd9090cf78314a06665d4ea938c35cc760f4
-set @v2 = repeat(@s1, 200); -- 10d3c783026b310218d10b7188da96a2401648c6
-set @v3 = repeat(@s2, 300); -- a33549d9844092289a58ac348dd59f09fc28406a
-set @v4 = repeat(@s0, 400); -- daa61c6de36a0526f0d47dc29d6b9de7e6d2630c
-set @v5 = repeat(@s1, 500); -- 70fc9a7d08beebc522258bfb02000a30c77a8f1d
-set @v6 = repeat(@s2, 600); -- 090565c580809efed3d369481a4bbb168b20713e
-set @v7 = repeat(@s0, 700); -- 1e0070bec426871a46291de27b9bd6e4255ab4e5
-set @v8 = repeat(@s1, 800); -- acbaba01bc2e682f015f40e79d9cbe475db3002e
-set @v9 = repeat(@s2, 900); -- 9ee30d99162574f79c66ae95cdf132dcf9cbc259
---enable_query_log
-
-# -- insert --
-insert into t1 values (1, @v1, 101, @v2);
-insert into t1 values (1, @v2, 102, @v3);
-insert into t1 values (1, @v3, 103, @v4);
-insert into t1 values (2, @v4, 201, @v5);
-insert into t1 values (2, @v5, 202, @v6);
-insert into t1 values (2, @v6, 203, @v7);
-insert into t1 values (3, @v7, 301, @v8);
-insert into t1 values (3, @v8, 302, @v9);
-insert into t1 values (3, @v9, 303, @v1);
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- pk read --
-select a, sha1(b), c, sha1(d) from t1 where a = 1 and c = 101;
-select a, sha1(b), c, sha1(d) from t1 where a = 2 and c = 201;
-select a, sha1(b), c, sha1(d) from t1 where a = 3 and c = 301;
-
-# -- pk update --
-update t1 set b = @v3, d = @v4 where a = 1 and c = 102;
-update t1 set b = @v6, d = @v7 where a = 2 and c = 202;
-update t1 set b = @v9, d = @v1 where a = 3 and c = 302;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- hash index update --
-update t1 set b = @v4, d = @v5 where c = 103;
-update t1 set b = @v7, d = @v8 where c = 203;
-update t1 set b = @v1, d = @v2 where c = 303;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- full scan update --
-update t1 set b = @v5, d = @v6;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- range scan update
-update t1 set b = @v1, d = @v2 where 100 < c and c < 200;
-update t1 set b = @v4, d = @v5 where 200 < c and c < 300;
-update t1 set b = @v7, d = @v8 where 300 < c and c < 400;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- delete --
-delete from t1 where a = 1 and c = 101;
-delete from t1 where c = 102;
-# delete from t1 where c < 300; # XXX coredump
-delete from t1;
-select a, sha1(b), c, sha1(d) from t1 order by a;
-
-# -- clean up --
-drop table t1;
diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test
index 44740c1a486..3b53f7b3431 100644
--- a/mysql-test/t/ndb_condition_pushdown.test
+++ b/mysql-test/t/ndb_condition_pushdown.test
@@ -1649,5 +1649,42 @@ set engine_condition_pushdown = on;
explain select * from t5 where b like '%jo%';
select * from t5 where b like '%jo%' order by a;
+# bug#17421 -1
+drop table t1;
+create table t1 (a int, b varchar(3), primary key using hash(a))
+engine=ndb;
+insert into t1 values (1,'a'), (2,'ab'), (3,'abc');
+# in TUP the constants 'ab' 'abc' were expected in varchar format
+# "like" returned error which became "false"
+# scan filter negates "or" which exposes the bug
+set engine_condition_pushdown = off;
+select * from t1 where b like 'ab';
+select * from t1 where b like 'ab' or b like 'ab';
+select * from t1 where b like 'abc';
+select * from t1 where b like 'abc' or b like 'abc';
+set engine_condition_pushdown = on;
+select * from t1 where b like 'ab';
+select * from t1 where b like 'ab' or b like 'ab';
+select * from t1 where b like 'abc';
+select * from t1 where b like 'abc' or b like 'abc';
+
+# bug#17421 -2
+drop table t1;
+create table t1 (a int, b char(3), primary key using hash(a))
+engine=ndb;
+insert into t1 values (1,'a'), (2,'ab'), (3,'abc');
+# test that incorrect MySQL behaviour is preserved
+# 'ab ' LIKE 'ab' is true in MySQL
+set engine_condition_pushdown = off;
+select * from t1 where b like 'ab';
+select * from t1 where b like 'ab' or b like 'ab';
+select * from t1 where b like 'abc';
+select * from t1 where b like 'abc' or b like 'abc';
+set engine_condition_pushdown = on;
+select * from t1 where b like 'ab';
+select * from t1 where b like 'ab' or b like 'ab';
+select * from t1 where b like 'abc';
+select * from t1 where b like 'abc' or b like 'abc';
+
set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5;
diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test
index 4787abe86e2..2fe54cac048 100644
--- a/mysql-test/t/ndb_config.test
+++ b/mysql-test/t/ndb_config.test
@@ -15,4 +15,3 @@
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster0 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster1 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
---exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
diff --git a/mysql-test/t/ndb_config2.test b/mysql-test/t/ndb_config2.test
new file mode 100644
index 00000000000..170f1b2e5e7
--- /dev/null
+++ b/mysql-test/t/ndb_config2.test
@@ -0,0 +1,7 @@
+-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
+-- source include/not_embedded.inc
+
+# Following doesn't work in all configurations (if shm is not defined)
+
+--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
diff --git a/mysql-test/t/ndb_dd_backuprestore.test b/mysql-test/t/ndb_dd_backuprestore.test
index be6d73e27b4..65f141288e7 100644
--- a/mysql-test/t/ndb_dd_backuprestore.test
+++ b/mysql-test/t/ndb_dd_backuprestore.test
@@ -159,185 +159,5 @@ DROP TABLE test.t1;
DROP TABLE test.t2;
DROP TABLE test.t3;
DROP TABLE test.t4;
-###################### Adding partition #################################
--- echo **** Test 3 Adding partition Test backup and restore ****
-
-CREATE TABLESPACE table_space2
-ADD DATAFILE './table_space2/datafile.dat'
-USE LOGFILE GROUP log_group1
-INITIAL_SIZE 12M
-ENGINE NDB;
-
-CREATE TABLE test.t1 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(150) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space1 STORAGE DISK ENGINE=NDB PARTITION BY HASH(c3) PARTITIONS 4;
-
-CREATE TABLE test.t4 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(180) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY HASH(c3) PARTITIONS 2;
-
-CREATE TABLE test.t2 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 TEXT NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space2 STORAGE DISK ENGINE=NDB PARTITION BY KEY(c3) (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-
-CREATE TABLE test.t5 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 TEXT NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY KEY(pk1) (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-
-CREATE TABLE test.t3 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(202) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))TABLESPACE table_space2 STORAGE DISK ENGINE=NDB PARTITION BY RANGE (c3) PARTITIONS 3 (PARTITION x1 VALUES LESS THAN (105), PARTITION x2 VALUES LESS THAN (333), PARTITION x3 VALUES LESS THAN (720));
-
-CREATE TABLE test.t6 (pk1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 VARCHAR(220) NOT NULL, c3 INT NOT NULL, c4 BIT NOT NULL, PRIMARY KEY(pk1,c3))ENGINE=NDB PARTITION BY RANGE (pk1) PARTITIONS 2 (PARTITION x1 VALUES LESS THAN (333), PARTITION x2 VALUES LESS THAN (720));
-
-SHOW CREATE TABLE test.t1;
-
-SHOW CREATE TABLE test.t2;
-
-SHOW CREATE TABLE test.t3;
-
-SHOW CREATE TABLE test.t4;
-
-SHOW CREATE TABLE test.t5;
-
-SHOW CREATE TABLE test.t6;
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't1';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't2';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't3';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't4';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't5';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't6';
-
-
-let $j= 500;
---disable_query_log
-while ($j)
-{
- eval INSERT INTO test.t1 VALUES (NULL, "Sweden, Texas", $j, b'0');
- eval INSERT INTO test.t4 VALUES (NULL, "Sweden, Texas", $j, b'0');
- dec $j;
- eval INSERT INTO test.t2 VALUES (NULL, "Sweden, Texas, ITALY, Kyle, JO, JBM,TU", $j, b'1');
- eval INSERT INTO test.t5 VALUES (NULL, "Sweden, Texas, ITALY, Kyle, JO, JBM,TU", $j, b'1');
- dec $j;
- eval INSERT INTO test.t3 VALUES (NULL, "TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU", $j, b'1');
- eval INSERT INTO test.t6 VALUES (NULL, "TEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXASTEXAS, ITALY, Kyle, JO, JBM,TU", $j, b'1'); } --enable_query_log
-
-SELECT COUNT(*) FROM test.t1;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t1 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t2;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t2 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t3;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t3 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t4;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t4 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t5;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t5 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t6;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t6 ORDER BY c3 LIMIT 5;
-
--- source include/ndb_backup.inc
-
-DROP TABLE test.t1;
-DROP TABLE test.t2;
-DROP TABLE test.t3;
-DROP TABLE test.t4;
-DROP TABLE test.t5;
-DROP TABLE test.t6;
-
-ALTER TABLESPACE table_space1
-DROP DATAFILE './table_space1/datafile.dat'
-ENGINE = NDB;
-
-ALTER TABLESPACE table_space2
-DROP DATAFILE './table_space2/datafile.dat'
-ENGINE = NDB;
-
-DROP TABLESPACE table_space1
-ENGINE = NDB;
-
-DROP TABLESPACE table_space2
-ENGINE = NDB;
-
-DROP LOGFILE GROUP log_group1
-ENGINE =NDB;
-
--- source include/ndb_restore_master.inc
-
-
-SHOW CREATE TABLE test.t1;
-
-SHOW CREATE TABLE test.t2;
-
-SHOW CREATE TABLE test.t3;
-
-SHOW CREATE TABLE test.t4;
-
-SHOW CREATE TABLE test.t5;
-
-SHOW CREATE TABLE test.t6;
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't1';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't2';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't3';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't4';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't5';
-
-SELECT * FROM information_schema.partitions WHERE table_name= 't6';
-
-SELECT COUNT(*) FROM test.t1;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t1 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t2;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t2 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t3;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t3 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t4;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t4 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t5;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t5 ORDER BY c3 LIMIT 5;
-
-SELECT COUNT(*) FROM test.t6;
-
-SELECT pk1, c2, c3, hex(c4) FROM test.t6 ORDER BY c3 LIMIT 5;
-
-# Cleanup
-
-DROP TABLE test.t1;
-DROP TABLE test.t2;
-DROP TABLE test.t3;
-DROP TABLE test.t4;
-DROP TABLE test.t5;
-DROP TABLE test.t6;
-
-ALTER TABLESPACE table_space1 DROP DATAFILE './table_space1/datafile.dat' ENGINE=NDB;
-
-ALTER TABLESPACE table_space2 DROP DATAFILE './table_space2/datafile.dat' ENGINE=NDB;
-
-DROP TABLESPACE table_space1 ENGINE = NDB;
-
-DROP TABLESPACE table_space2 ENGINE = NDB;
-
-DROP LOGFILE GROUP log_group1 ENGINE = NDB;
#End 5.1 test case
-
-
diff --git a/mysql-test/t/ndb_dd_basic.test b/mysql-test/t/ndb_dd_basic.test
index 0bc0e07fad8..9df2cfb0371 100644
--- a/mysql-test/t/ndb_dd_basic.test
+++ b/mysql-test/t/ndb_dd_basic.test
@@ -14,16 +14,33 @@
DROP TABLE IF EXISTS t1;
--enable_warnings
+# some negative tests
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 16M
+UNDO_BUFFER_SIZE = 1M
+ENGINE=MYISAM;
+
+ALTER LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile02.dat'
+INITIAL_SIZE = 4M
+ENGINE=XYZ;
+
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 12M;
+
##################################
# Basic test of disk tables for NDB
# Start by creating a logfile group
##################################
+set storage_engine=ndb;
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
-UNDO_BUFFER_SIZE = 1M
-ENGINE=NDB;
+UNDO_BUFFER_SIZE = 1M;
ALTER LOGFILE GROUP lg1
ADD UNDOFILE 'undofile02.dat'
@@ -34,6 +51,7 @@ ENGINE=NDB;
# Create a tablespace connected to the logfile group
###################################################
+set storage_engine=myisam;
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
index 4fb6422b359..a40efc8a40c 100644
--- a/mysql-test/t/ndb_index_unique.test
+++ b/mysql-test/t/ndb_index_unique.test
@@ -32,8 +32,8 @@ select * from t1 order by a;
alter table t1 drop index ib;
insert into t1 values(1, 2, 3);
# Bug# #18129
-#--error 1169
-#create unique index ib on t1(b);
+--error 1169
+create unique index ib on t1(b);
drop table t1;
@@ -72,7 +72,7 @@ CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
c int unsigned not null,
- UNIQUE USING HASH (b, c)
+ UNIQUE (b, c) USING HASH
) engine=ndbcluster;
insert t2 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
@@ -96,7 +96,7 @@ CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
c int unsigned,
- UNIQUE USING HASH (b, c)
+ UNIQUE (b, c) USING HASH
) engine=ndbcluster;
#
@@ -107,7 +107,7 @@ CREATE TABLE t3 (
a int unsigned NOT NULL,
b int unsigned not null,
c int unsigned,
- PRIMARY KEY USING HASH (a, b)
+ PRIMARY KEY (a, b) USING HASH
) engine=ndbcluster;
insert t3 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
diff --git a/mysql-test/t/ndb_partition_error.test b/mysql-test/t/ndb_partition_error.test
deleted file mode 100644
index 286c2216f70..00000000000
--- a/mysql-test/t/ndb_partition_error.test
+++ /dev/null
@@ -1,71 +0,0 @@
--- source include/have_ndb.inc
-#--disable_abort_on_error
-#
-# Simple test for the partition storage engine
-# Focuses on range partitioning tests
-#
-#-- source include/have_partition.inc
-
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
-#
-# Partition by range, generate node group error
-#
---error 1005
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a,b),
-index (a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5) nodegroup 12,
- partition x2 values less than (10) nodegroup 13,
- partition x3 values less than (20) nodegroup 14);
-show warnings;
-
-#
-# Partition by range, create normal valid table
-#
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5),
- partition x2 values less than (10),
- partition x3 values less than (20));
-
-drop table t1;
-
-#
-# Bug #17763 mysqld cores with list partitioning if update to missing partition
-#
-CREATE TABLE t1 (id INT) ENGINE=NDB
- PARTITION BY LIST(id)
- (PARTITION p0 VALUES IN (2, 4),
- PARTITION p1 VALUES IN (42, 142));
-INSERT INTO t1 VALUES (2);
---error ER_NO_PARTITION_FOR_GIVEN_VALUE
-UPDATE t1 SET id=5 WHERE id=2;
-DROP TABLE t1;
-
-#
-# NULL for LIST partition
-#
-create table t1 (a int,b int, c int)
-engine = ndb
-partition by list(a)
-partitions 2
-(partition x123 values in (11, 12),
- partition x234 values in (5, 1));
---error 1505
-insert into t1 values (NULL,1,1);
-drop table t1;
diff --git a/mysql-test/t/ndb_partition_key.test b/mysql-test/t/ndb_partition_key.test
deleted file mode 100644
index 87933671529..00000000000
--- a/mysql-test/t/ndb_partition_key.test
+++ /dev/null
@@ -1,180 +0,0 @@
--- source include/have_ndb.inc
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
-#
-# Basic syntax test
-#
-
-# Support for partition key verified
-CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b,c))
- ENGINE = NDB
- PARTITION BY KEY (a,b);
-
-insert into t1 values (1,1,1,1);
-select * from t1;
-update t1 set d = 2 where a = 1 and b = 1 and c = 1;
-select * from t1;
-delete from t1;
-select * from t1;
-
-drop table t1;
-
-# only support for partition key on primary key
---error ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF
-CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b))
- ENGINE = NDB
- PARTITION BY KEY (c);
-
-CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY(a,b))
- ENGINE = NDB
- PARTITION BY KEY (a);
-
-insert into t1 values
- (1,1,3),(1,2,3),(1,3,3),(1,4,3),(1,5,3),(1,6,3),
- (1,7,3),(1,8,3),(1,9,3),(1,10,3),(1,11,3),(1,12,3);
-
-select * from t1 order by b;
-
-DROP TABLE t1;
-
-#
-# Test partition and char support
-#
-
-CREATE TABLE t1 (a INT, b CHAR(10) COLLATE latin1_bin, c INT, d INT,
- PRIMARY KEY USING HASH (a,b,c))
- ENGINE=NDB
- DEFAULT CHARSET=latin1
- PARTITION BY KEY (b);
-
-insert into t1 values (1,"a",1,1),(2,"a",1,1),(3,"a",1,1);
-
-# should show only one attribute with DISTRIBUTION KEY
---exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -d test t1 | sed 's/Version: [0-9]*//' | sed 's/\(Length of frm data: \)[0-9]*/\1#/'
-
-#
-# Test that explicit partition info is not shown in show create table
-# result should not contain (PARTITION P0 ... etc) since this is what shows up in
-# mysqldump, and we don't want that info there
-#
-show create table t1;
-
-DROP TABLE t1;
-
-#
-# Bug #13155: Problem in Create Table using SHOW CREATE TABLE syntax
-#
-CREATE TABLE t1 (a int not null primary key)
-PARTITION BY KEY(a)
-(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-
-drop table t1;
-
-CREATE TABLE t1 (a int not null primary key);
-ALTER TABLE t1
-PARTITION BY KEY(a)
-(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
-
-drop table t1;
-
-#
-# Bug #17754 Improper handling of removal of partitioning in ALTER TABLE
-# Also added a number of general test cases in the same area
-#
-create table t1 (a int)
-engine=ndb
-partition by key(a)
-(partition p0, partition p1);
-show create table t1;
-
-alter table t1 engine=heap;
-show create table t1;
-
-alter table t1 engine=ndb;
-show create table t1;
-
-alter table t1 engine=heap remove partitioning;
-show create table t1;
-
-alter table t1 engine=ndb
-partition by key(a)
-(partition p0, partition p1 engine = ndb);
-show create table t1;
-
-alter table t1
-partition by key (a)
-(partition p0 engine=ndb, partition p1 engine=ndb);
-show create table t1;
-
-alter table t1 remove partitioning;
-show create table t1;
-
---error ER_MIX_HANDLER_ERROR
-alter table t1
-partition by key(a)
-(partition p0 engine=ndb, partition p1);
-
-alter table t1
-engine=ndb
-partition by key(a)
-(partition p0 engine=ndb, partition p1 engine = ndb);
-show create table t1;
-
-drop table t1;
-
-#
-# BUG 16810 Out of memory when coalesce partition
-#
-CREATE TABLE t1 (
- c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
- c2 TEXT NOT NULL,
- c3 INT NOT NULL,
- c4 BIT NOT NULL,
- c5 FLOAT,
- c6 VARCHAR(255),
- c7 TIMESTAMP,
- PRIMARY KEY(c1,c3))
- ENGINE=NDB
- PARTITION BY KEY(c3) PARTITIONS 5;
-
-let $j= 11;
---disable_query_log
-while ($j)
-{
- eval INSERT INTO t1 VALUES (NULL, "Tested Remotely from Texas, USA", $j,
-b'0',
- $j.00,"By JBM $j","2006-01-26");
- dec $j;
-}
---enable_query_log
-ALTER TABLE t1 COALESCE PARTITION 4;
-
-DROP TABLE t1;
-
-#
-# BUG 16806: ALTER TABLE fails
-#
-CREATE TABLE t1 (
- c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
- c2 TEXT NOT NULL,
- c3 INT NOT NULL,
- PRIMARY KEY(c1,c3))
- ENGINE=NDB
- PARTITION BY KEY(c3) PARTITIONS 5;
-
-ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1;
-DROP TABLE t1;
-
-CREATE TABLE t1 (
- c1 MEDIUMINT NOT NULL AUTO_INCREMENT,
- c2 TEXT NOT NULL,
- c3 INT NOT NULL,
- PRIMARY KEY(c1,c3))
- ENGINE=NDB
- PARTITION BY KEY(c3);
-
-ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1;
-DROP TABLE t1;
diff --git a/mysql-test/t/ndb_partition_list.test b/mysql-test/t/ndb_partition_list.test
deleted file mode 100644
index 2ad37b8768c..00000000000
--- a/mysql-test/t/ndb_partition_list.test
+++ /dev/null
@@ -1,64 +0,0 @@
---source include/have_ndb.inc
-#
-# Simple test for the partition storage engine
-# Focuses on range partitioning tests
-#
-#-- source include/have_partition.inc
-
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
-#
-# Partition by list, basic
-#
-
-CREATE TABLE t1 ( f_int1 INTEGER NOT NULL, f_int2 INTEGER NOT NULL,
- f_char1 CHAR(10),
- f_char2 CHAR(10), f_charbig VARCHAR(1000),
-PRIMARY KEY (f_int1,f_int2))
-ENGINE = NDB
-PARTITION BY LIST(MOD(f_int1 + f_int2,4))
-(PARTITION part_3 VALUES IN (-3),
- PARTITION part_2 VALUES IN (-2),
- PARTITION part_1 VALUES IN (-1),
- PARTITION part0 VALUES IN (0),
- PARTITION part1 VALUES IN (1),
- PARTITION part2 VALUES IN (2),
- PARTITION part3 VALUES IN (3,4,5));
-
-INSERT INTO t1 SET f_int1 = -2, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 1, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 2, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 3, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 4, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 5, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 20, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-
-SELECT * FROM t1 ORDER BY f_int1;
-
-DROP TABLE t1;
-
-#
-# Partition by list, no pk
-#
-
-CREATE TABLE t1 ( f_int1 INTEGER, f_int2 INTEGER, f_char1 CHAR(10),
- f_char2 CHAR(10), f_charbig VARCHAR(1000))
-ENGINE = NDB
-PARTITION BY LIST(f_int1)
-(PARTITION part_1 VALUES IN (-1),
- PARTITION part0 VALUES IN (0,1),
- PARTITION part1 VALUES IN (2));
-
-INSERT INTO t1 SET f_int1 = -1, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 0, f_int2 = 20, f_char1 = '20', f_char2 = '20', f_charbig = '===20===';
-INSERT INTO t1 SET f_int1 = 1, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-INSERT INTO t1 SET f_int1 = 2, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
---error ER_NO_PARTITION_FOR_GIVEN_VALUE
-INSERT INTO t1 SET f_int1 = 20, f_int2 = 1, f_char1 = '1', f_char2 = '1', f_charbig = '===1===';
-
-SELECT * FROM t1 ORDER BY f_int1;
-
-DROP TABLE t1;
-
diff --git a/mysql-test/t/ndb_partition_range.test b/mysql-test/t/ndb_partition_range.test
deleted file mode 100644
index 981467d4055..00000000000
--- a/mysql-test/t/ndb_partition_range.test
+++ /dev/null
@@ -1,260 +0,0 @@
--- source include/have_ndb.inc
-#--disable_abort_on_error
-#
-# Simple test for the partition storage engine
-# Focuses on range partitioning tests
-#
-#-- source include/have_partition.inc
-
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
-#
-# Partition by range, basic
-#
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(a,b),
-index (a))
-engine = ndb
-partition by range (a)
-partitions 3
-(partition x1 values less than (5),
- partition x2 values less than (10),
- partition x3 values less than (20));
-
-# Simple insert and verify test
-INSERT into t1 values (1, 1, 1);
-INSERT into t1 values (6, 1, 1);
-INSERT into t1 values (10, 1, 1);
-INSERT into t1 values (15, 1, 1);
-
---replace_column 16 # 19 # 20 #
-select * from information_schema.partitions where table_name= 't1';
-
-select * from t1 order by a;
-
-select * from t1 where a=1 order by a;
-select * from t1 where a=15 and b=1 order by a;
-select * from t1 where a=21 and b=1 order by a;
-select * from t1 where a=21 order by a;
-select * from t1 where a in (1,6,10,21) order by a;
-select * from t1 where b=1 and a in (1,6,10,21) order by a;
-
-drop table t1;
-
-#
-# Partition by range, basic
-#
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null,
-primary key(b),
-unique (a))
-engine = ndb
-partition by range (b)
-partitions 3
-(partition x1 values less than (5),
- partition x2 values less than (10),
- partition x3 values less than (20));
-
-# Simple insert and verify test
-INSERT into t1 values (1, 1, 1);
-INSERT into t1 values (2, 6, 1);
-INSERT into t1 values (3, 10, 1);
-INSERT into t1 values (4, 15, 1);
-
-select * from t1 order by a;
-UPDATE t1 set a = 5 WHERE b = 15;
-select * from t1 order by a;
-UPDATE t1 set a = 6 WHERE a = 5;
-select * from t1 order by a;
-
-select * from t1 where b=1 order by b;
-select * from t1 where b=15 and a=1 order by b;
-select * from t1 where b=21 and a=1 order by b;
-select * from t1 where b=21 order by b;
-select * from t1 where b in (1,6,10,21) order by b;
-select * from t1 where a in (1,2,5,6) order by b;
-select * from t1 where a=1 and b in (1,6,10,21) order by b;
-
-DELETE from t1 WHERE b = 6;
-DELETE from t1 WHERE a = 6;
-
-#
-# Test that explicit partition info _is_ shown in show create table
-# result _should_ contain (PARTITION x1 ... etc)
-#
-show create table t1;
-
-drop table t1;
-
-#
-# Bug #17499, #17687
-# Alter partitioned NDB table causes mysqld to core
-#
-
-CREATE TABLE t1
- (id MEDIUMINT NOT NULL,
- b1 BIT(8),
- vc VARCHAR(255),
- bc CHAR(255),
- d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0,
- total BIGINT UNSIGNED,
- y YEAR,
- t DATE) ENGINE=NDB
- PARTITION BY RANGE (YEAR(t))
- (PARTITION p0 VALUES LESS THAN (1901),
- PARTITION p1 VALUES LESS THAN (1946),
- PARTITION p2 VALUES LESS THAN (1966),
- PARTITION p3 VALUES LESS THAN (1986),
- PARTITION p4 VALUES LESS THAN (2005),
- PARTITION p5 VALUES LESS THAN MAXVALUE);
-
-INSERT INTO t1 VALUES (0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-SELECT * FROM t1;
-ALTER TABLE t1 ENGINE=MYISAM;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE LOGFILE GROUP lg1
- ADD UNDOFILE 'undofile.dat'
- INITIAL_SIZE 16M
- UNDO_BUFFER_SIZE=1M
- ENGINE=NDB;
-
-CREATE TABLESPACE ts1
- ADD DATAFILE 'datafile.dat'
- USE LOGFILE GROUP lg1
- INITIAL_SIZE 12M
- ENGINE NDB;
-
-CREATE TABLE test.t1 (
- a1 INT,
- a2 TEXT NOT NULL,
- a3 BIT NOT NULL,
- a4 DECIMAL(8,3),
- a5 INT NOT NULL,
- a6 INT,
- PRIMARY KEY(a1))
- TABLESPACE ts1 STORAGE DISK ENGINE=NDB
- PARTITION BY LIST (a1)
- (PARTITION p0 VALUES IN (1,2,3,4,5),
- PARTITION p1 VALUES IN (6,7,8,9, 10),
- PARTITION p2 VALUES IN (11, 12, 13, 14, 15));
-
-# Alter table directly without any statements inbetween
-ALTER TABLE test.t1 DROP COLUMN a6;
-ALTER TABLE test.t1 ADD COLUMN a6 VARCHAR(255);
-
-let $j= 15;
---disable_query_log
-while ($j)
-{
-eval INSERT INTO test.t1 VALUES ($j, "Tested Remotely from Texas, USA",
-b'1',$j.00,$j+1,"By NIK $j");
-dec $j;
-}
---enable_query_log
-SELECT COUNT(*) FROM test.t1;
-
-ALTER TABLE test.t1 DROP COLUMN a4;
-SELECT COUNT(*) FROM test.t1;
-
-DROP TABLE t1;
-
-CREATE TABLE test.t1 (
- a1 INT,
- a2 TEXT NOT NULL,
- a3 BIT NOT NULL,
- a4 DECIMAL(8,3),
- a5 INT NOT NULL,
- a6 VARCHAR(255),
- PRIMARY KEY(a1))
- TABLESPACE ts1 STORAGE DISK ENGINE=NDB
- PARTITION BY HASH(a1)
- PARTITIONS 4;
-
-let $j= 15;
---disable_query_log
-while ($j)
-{
-eval INSERT INTO test.t1 VALUES ($j, "Tested Remotely from Texas, USA",
-b'1',$j.00,$j+1,"By NIK $j");
-dec $j;
-}
---enable_query_log
-SELECT COUNT(*) FROM test.t1;
-
-ALTER TABLE test.t1 DROP COLUMN a4;
-SELECT COUNT(*) FROM test.t1;
-
-DROP TABLE t1;
-
-ALTER TABLESPACE ts1
- DROP DATAFILE 'datafile.dat'
- ENGINE=NDB;
-DROP TABLESPACE ts1 ENGINE=NDB;
-DROP LOGFILE GROUP lg1 ENGINE=NDB;
-
-
-#
-# Bug #17701 ALTER TABLE t1 ADD PARTITION for PARTITION BY LIST hangs test
-#
-
-CREATE TABLE t1
- (id MEDIUMINT NOT NULL,
- b1 BIT(8),
- vc VARCHAR(255),
- bc CHAR(255),
- d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0,
- total BIGINT UNSIGNED,
- y YEAR,
- t DATE) ENGINE=NDB
- PARTITION BY LIST(id)
- (PARTITION p0 VALUES IN (2, 4),
- PARTITION p1 VALUES IN (42, 142));
-
-INSERT INTO t1 VALUES (2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-SELECT * FROM t1;
-ALTER TABLE t1 ADD PARTITION
- (PARTITION p2 VALUES IN (412));
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
-# Bug #17806 Update on NDB table with list partition causes mysqld to core
-# Bug #16385 Partitions: crash when updating a range partitioned NDB table
-#
-CREATE TABLE t1 (
-a int not null,
-b int not null,
-c int not null)
-partition by list(a)
-partitions 2
-(partition x123 values in (1,5,6),
- partition x234 values in (4,7,8));
-INSERT into t1 VALUES (5,1,1);
-select * from t1;
-UPDATE t1 SET a=8 WHERE a=5 AND b=1;
-select * from t1;
-drop table t1;
-
-CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) engine=ndb
-PARTITION BY RANGE(f1)
-( PARTITION part1 VALUES LESS THAN (2),
-PARTITION part2 VALUES LESS THAN (1000));
-INSERT INTO t1 VALUES(1, '---1---');
-INSERT INTO t1 VALUES(2, '---2---');
-select * from t1 order by f1;
-UPDATE t1 SET f1 = f1 + 4 WHERE f1 = 2;
-select * from t1 order by f1;
-UPDATE t1 SET f1 = f1 + 4 WHERE f1 = 1;
-select * from t1 order by f1;
-drop table t1;
diff --git a/mysql-test/t/ndb_restore_compat.test b/mysql-test/t/ndb_restore_compat.test
new file mode 100644
index 00000000000..774011e362d
--- /dev/null
+++ b/mysql-test/t/ndb_restore_compat.test
@@ -0,0 +1,43 @@
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+-- source include/have_case_sensitive_file_system.inc
+
+# This test currently requires case sensitive file system as the tables
+# are originally stored with uppercase
+
+#
+# Bug #18594 ndb_restore log boken in 5.1
+#
+
+--disable_warnings
+DROP DATABASE IF EXISTS BANK;
+--enable_warnings
+CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
+USE BANK;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -p 1 -m -r $MYSQL_TEST_DIR/std_data/ndb_backup51 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -e -b 1 -n 2 -p 1 -r $MYSQL_TEST_DIR/std_data/ndb_backup51 >> $NDB_TOOLS_OUTPUT
+SHOW TABLES;
+SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE;
+SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID;
+SELECT COUNT(*) FROM TRANSACTION;
+SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID;
+SELECT * FROM cluster.apply_status WHERE server_id=0;
+
+#
+# verify restore of 5.0 backup
+# here we must use the already created tables as restoring the old
+# table definitions will not work
+#
+TRUNCATE GL;
+TRUNCATE ACCOUNT;
+TRUNCATE TRANSACTION;
+TRUNCATE SYSTEM_VALUES;
+TRUNCATE ACCOUNT_TYPE;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -p 1 -r $MYSQL_TEST_DIR/std_data/ndb_backup50 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -e -b 1 -n 2 -p 1 -r $MYSQL_TEST_DIR/std_data/ndb_backup50 >> $NDB_TOOLS_OUTPUT
+SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE;
+SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID;
+SELECT COUNT(*) FROM TRANSACTION;
+SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID;
+SELECT * FROM cluster.apply_status WHERE server_id=0;
+DROP DATABASE BANK;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 183308880ed..4aec745f3f7 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -190,4 +190,45 @@ select
# Restore charset to the default value.
set names latin1;
+#
+# Bug#19145: mysqld crashes if you set the default value of an enum field to NULL
+#
+create table bug19145a (e enum('a','b','c') default 'b' , s set('x', 'y', 'z') default 'y' ) engine=MyISAM;
+create table bug19145b (e enum('a','b','c') default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+
+create table bug19145c (e enum('a','b','c') not null default 'b' , s set('x', 'y', 'z') not null default 'y' ) engine=MyISAM;
+
+# Invalid default value for 's'
+--error 1067
+create table bug19145setnotnulldefaultnull (e enum('a','b','c') default null, s set('x', 'y', 'z') not null default null) engine=MyISAM;
+
+# Invalid default value for 'e'
+--error 1067
+create table bug19145enumnotnulldefaultnull (e enum('a','b','c') not null default null, s set('x', 'y', 'z') default null) engine=MyISAM;
+
+alter table bug19145a alter column e set default null;
+alter table bug19145a alter column s set default null;
+alter table bug19145a add column (i int);
+
+alter table bug19145b alter column e set default null;
+alter table bug19145b alter column s set default null;
+alter table bug19145b add column (i int);
+
+# Invalid default value for 'e'
+--error 1067
+alter table bug19145c alter column e set default null;
+
+# Invalid default value for 's'
+--error 1067
+alter table bug19145c alter column s set default null;
+alter table bug19145c add column (i int);
+
+show create table bug19145a;
+show create table bug19145b;
+show create table bug19145c;
+
+drop table bug19145a;
+drop table bug19145b;
+drop table bug19145c;
+
# End of 4.1 tests
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 359b8b69a4d..afee381f5b7 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -10,8 +10,8 @@ insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
-grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/emailAddress=abstract.mysql.developer@mysql.com";
flush privileges;
connect (con1,localhost,ssl_user1,,,,,SSL);
@@ -48,9 +48,47 @@ select * from t1;
delete from t1;
connection default;
-delete from mysql.user where user='ssl_user%';
-delete from mysql.db where user='ssl_user%';
-flush privileges;
+drop user ssl_user1@localhost, ssl_user2@localhost,
+ssl_user3@localhost, ssl_user4@localhost;
+
drop table t1;
# End of 4.1 tests
+
+#
+# Test that we can't open connection to server if we are using
+# a different cacert
+#
+--exec echo "this query should not execute;" > $MYSQLTEST_VARDIR/tmp/test.sql
+--error 1
+--exec $MYSQL_TEST --ssl-ca=$MYSQL_TEST_DIR/std_data/untrusted-cacert.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+
+#
+# Test that we can't open connection to server if we are using
+# a blank ca
+#
+--error 1
+--exec $MYSQL_TEST --ssl-ca= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+
+#
+# Test that we can't open connection to server if we are using
+# a nonexistent ca file
+#
+--error 1
+--exec $MYSQL_TEST --ssl-ca=nonexisting_file.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+
+#
+# Test that we can't open connection to server if we are using
+# a blank client-key
+#
+--error 1
+--exec $MYSQL_TEST --ssl-key= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+
+#
+# Test that we can't open connection to server if we are using
+# a blank client-cert
+#
+--error 1
+--exec $MYSQL_TEST --ssl-cert= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+
+
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index b1807579b20..98e542dac95 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -563,4 +563,18 @@ SELECT a FROM t1 ORDER BY a;
(SELECT a FROM t1) ORDER BY a;
DROP TABLE t1;
+#
+# Bug #18767: global ORDER BY applied to a SELECT with ORDER BY either was
+# ignored or 'concatened' to the latter.
+
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test
index d404a6fff9f..c48e6c9730d 100644
--- a/mysql-test/t/outfile.test
+++ b/mysql-test/t/outfile.test
@@ -40,7 +40,6 @@ eval select * into dumpfile "../tmp/outfile-test.2" from t1;
--error 1086
eval select * into dumpfile "../tmp/outfile-test.3" from t1;
enable_query_log;
---error 13,2
select load_file(concat(@tmpdir,"/outfile-test.not-exist"));
--exec rm $MYSQLTEST_VARDIR/tmp/outfile-test.1
--exec rm $MYSQLTEST_VARDIR/tmp/outfile-test.2
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index 272cdc27af6..a24124d3fb5 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -9,6 +9,11 @@
drop table if exists t1;
--enable_warnings
+create table t1 (a int)
+partition by key(a)
+(partition p0 engine = MEMORY);
+drop table t1;
+
#
# Partition by key no partition defined => OK
#
@@ -1009,4 +1014,67 @@ select auto_increment from information_schema.tables where table_name='t1';
select * from t1;
drop table t1;
+#
+# BUG 19140 Partitions: Create index for partitioned table crashes
+#
+create table t1 (a int) engine=memory
+partition by key(a);
+insert into t1 values (1);
+create index inx1 on t1(a);
+drop table t1;
+
+#
+# BUG 19304 Partitions: MERGE handler not allowed in partitioned tables
+#
+--error ER_PARTITION_MERGE_ERROR
+create table t1 (a int)
+partition by key (a)
+(partition p0 engine = MERGE);
+
+#
+# BUG 19062 Partition clause ignored if CREATE TABLE ... AS SELECT ...;
+#
+create table t1 (a varchar(1))
+partition by key (a)
+as select 'a';
+
+show create table t1;
+drop table t1;
+
+#
+# BUG 19501 Partitions: SHOW TABLE STATUS shows wrong Data_free
+#
+CREATE TABLE t1 (a int) ENGINE = MYISAM PARTITION BY KEY(a);
+INSERT into t1 values (1), (2);
+--replace_column 9 0 12 NULL 13 NULL 14 NULL
+SHOW TABLE STATUS;
+DELETE from t1 where a = 1;
+--replace_column 9 0 12 NULL 13 NULL 14 NULL
+SHOW TABLE STATUS;
+ALTER TABLE t1 OPTIMIZE PARTITION p0;
+--replace_column 12 NULL 13 NULL 14 NULL
+SHOW TABLE STATUS;
+DROP TABLE t1;
+
+#
+# BUG 19502: ENABLE/DISABLE Keys don't work for partitioned tables
+#
+CREATE TABLE t1 (a int, index(a)) PARTITION BY KEY(a);
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+DROP TABLE t1;
+
+#
+# Bug 17455 Partitions: Wrong message and error when using Repair/Optimize
+# table on partitioned table
+#
+create table t1 (a int)
+engine=MEMORY
+partition by key (a);
+
+REPAIR TABLE t1;
+OPTIMIZE TABLE t1;
+
+drop table t1;
+
--echo End of 5.1 tests
diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test
index a4d8c3740b7..ef539e2001f 100644
--- a/mysql-test/t/partition_range.test
+++ b/mysql-test/t/partition_range.test
@@ -388,3 +388,31 @@ SELECT COUNT(*) FROM t1 WHERE c3 BETWEEN '1996-12-31' AND '2000-12-31';
SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31';
DROP TABLE t1;
+#
+# BUG 18962 Errors in DROP PARTITION
+#
+create table t1 (a int)
+partition by range (MOD(a,3))
+subpartition by hash(a)
+subpartitions 2
+(partition p0 values less than (1),
+ partition p1 values less than (2),
+ partition p2 values less than (3),
+ partition p3 values less than (4));
+ALTER TABLE t1 DROP PARTITION p3;
+ALTER TABLE t1 DROP PARTITION p1;
+ALTER TABLE t1 DROP PARTITION p2;
+drop table t1;
+
+create table t1 (a int)
+partition by range (MOD(a,3))
+subpartition by hash(a)
+subpartitions 2
+(partition p0 values less than (1),
+ partition p1 values less than (2),
+ partition p2 values less than (3),
+ partition p3 values less than (4));
+ALTER TABLE t1 DROP PARTITION p0;
+ALTER TABLE t1 DROP PARTITION p1;
+ALTER TABLE t1 DROP PARTITION p2;
+drop table t1;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 9ffdb72ca22..639a576fb35 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -1110,4 +1110,40 @@ select * from t1 order by 1+1;
drop table t1;
+#
+# Bug#19308 "REPAIR/OPTIMIZE/ANALYZE supported in SP but not in PS".
+# Add test coverage for the added commands.
+#
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t2;
+prepare stmt from "repair table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "repair table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "repair table t1, t4, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1, t3, t4";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t4, t1";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
# End of 5.0 tests
diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test
index e214afeaaf3..ff1c87f3bd8 100644
--- a/mysql-test/t/ps_11bugs.test
+++ b/mysql-test/t/ps_11bugs.test
@@ -130,3 +130,17 @@ drop table t1, t2;
# end of bug#1676
# End of 4.1 tests
+
+# bug#18492: mysqld reports ER_ILLEGAL_REFERENCE in --ps-protocol
+
+create table t1 (a int primary key);
+insert into t1 values (1);
+
+explain select * from t1 where 3 in (select (1+1) union select 1);
+
+select * from t1 where 3 in (select (1+1) union select 1);
+
+prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)';
+execute st_18492;
+
+drop table t1;
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 6b168711de8..f61a7820afe 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -456,13 +456,10 @@ into table t1 fields terminated by ''\t'' ';
prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
execute stmt1 ;
##
---error 1295
prepare stmt1 from ' optimize table t1 ' ;
---error 1295
prepare stmt1 from ' analyze table t1 ' ;
--error 1295
prepare stmt1 from ' checksum table t1 ' ;
---error 1295
prepare stmt1 from ' repair table t1 ' ;
--error 1295
prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 7596a7ba708..e2ff20e6ecc 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -207,7 +207,7 @@ show status like "Qcache_queries_in_cache";
drop table t1;
#
-# Charset convertion (cp1251_koi8 always present)
+# Charset conversion (cp1251_koi8 always present)
#
create table t1 (a char(1) not null collate koi8r_general_ci);
insert into t1 values(_koi8r"á");
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index 5caecef176e..86e4b6eed0a 100644
--- a/mysql-test/t/rename.test
+++ b/mysql-test/t/rename.test
@@ -61,9 +61,15 @@ connection con2;
sleep 1;
show tables;
UNLOCK TABLES;
-sleep 1;
+connection con1;
+reap;
+connection con2;
show tables;
drop table t2, t4;
+disconnect con2;
+disconnect con1;
+connection default;
+
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_bit_npk.test b/mysql-test/t/rpl_bit_npk.test
index 07fc42b09ef..12b587919f9 100644
--- a/mysql-test/t/rpl_bit_npk.test
+++ b/mysql-test/t/rpl_bit_npk.test
@@ -70,18 +70,22 @@ UNLOCK TABLES;
UPDATE test.t1 set x034 = 50 where bit3 = b'000000';
UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0';
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
-SELECT hex(bit1) from test.t1;
-SELECT hex(bit2) from test.t1;
-SELECT hex(bit3) from test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
save_master_pos;
connection slave;
sync_with_master;
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
-SELECT hex(bit1) from test.t1;
-SELECT hex(bit2) from test.t1;
-SELECT hex(bit3) from test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
connection master;
CREATE TABLE test.t2 (a INT, b BIT(1));
@@ -94,14 +98,14 @@ INSERT INTO test.t3 VALUES (1, NULL);
INSERT INTO test.t3 VALUES (1, 0);
UPDATE test.t3 SET a = 2 WHERE b = 0;
-SELECT a, hex(b) FROM test.t2;
-SELECT * FROM test.t3;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
save_master_pos;
connection slave;
sync_with_master;
-SELECT a, hex(b) FROM test.t2;
-SELECT * FROM test.t3;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
connection master;
DROP TABLE IF EXISTS test.t1;
diff --git a/mysql-test/t/rpl_loaddatalocal.test b/mysql-test/t/rpl_loaddatalocal.test
index af4fd0106bd..758ac94af24 100644
--- a/mysql-test/t/rpl_loaddatalocal.test
+++ b/mysql-test/t/rpl_loaddatalocal.test
@@ -53,11 +53,11 @@ create table t1(a int primary key);
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1;
system rm $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile ;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
save_master_pos;
connection slave;
sync_with_master;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
connection master;
drop table t1;
save_master_pos;
diff --git a/mysql-test/t/rpl_multi_engine.test b/mysql-test/t/rpl_multi_engine.test
index 3f7b7b11c0d..10780c765f7 100644
--- a/mysql-test/t/rpl_multi_engine.test
+++ b/mysql-test/t/rpl_multi_engine.test
@@ -1,5 +1,9 @@
# See if replication between MyISAM, MEMORY and InnoDB works.
+#This test case is not written for NDB, result files do not
+#match when NDB is the default engine
+-- source include/not_ndb_default.inc
+
-- source include/master-slave.inc
connection slave;
diff --git a/mysql-test/t/rpl_ndb_basic.test b/mysql-test/t/rpl_ndb_basic.test
index d7d1d50d88f..c702908ed68 100644
--- a/mysql-test/t/rpl_ndb_basic.test
+++ b/mysql-test/t/rpl_ndb_basic.test
@@ -146,4 +146,35 @@ select * from t1 order by nid;
# cleanup
--connection master
DROP TABLE t1;
+
+
+#
+# BUG#18094
+# Slave caches invalid table definition after atlters causes select failure
+#
+--connection master
+CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB;
+
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+ALTER TABLE t1 ADD c2 INT;
+
+--sync_slave_with_master
+connection slave;
+SELECT * FROM t1 ORDER BY c1;
+
+connection master;
+ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8;
+ALTER TABLE t1 CHANGE c2 c2 BLOB;
+
+--sync_slave_with_master
+connection slave;
+# here we would get error 1412 prior to bug
+SELECT * FROM t1 ORDER BY c1 LIMIT 5;
+
+
+
+# cleanup
+--connection master
+DROP TABLE t1;
-- source include/master-slave-end.inc
diff --git a/mysql-test/t/rpl_ndb_dd_partitions.test b/mysql-test/t/rpl_ndb_dd_partitions.test
deleted file mode 100644
index 026c31bbdc7..00000000000
--- a/mysql-test/t/rpl_ndb_dd_partitions.test
+++ /dev/null
@@ -1,301 +0,0 @@
-#######################################
-# Author: JBM #
-# Date: 2006-03-09 #
-# Purpose: To test the replication of #
-# Cluster Disk Data using partitions #
-#######################################
-
---source include/have_ndb.inc
---source include/have_binlog_format_row.inc
---source include/master-slave.inc
-
---echo --- Doing pre test cleanup ---
-
-connection master;
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_query_log
-
-
-# Start by creating a logfile group
-##################################
-
-CREATE LOGFILE GROUP lg1
-ADD UNDOFILE 'undofile.dat'
-INITIAL_SIZE 16M
-UNDO_BUFFER_SIZE = 1M
-ENGINE=NDB;
-
-ALTER LOGFILE GROUP lg1
-ADD UNDOFILE 'undofile02.dat'
-INITIAL_SIZE = 4M
-ENGINE=NDB;
-
-###################################################
-# Create a tablespace connected to the logfile group
-###################################################
-
-CREATE TABLESPACE ts1
-ADD DATAFILE 'datafile.dat'
-USE LOGFILE GROUP lg1
-INITIAL_SIZE 12M
-ENGINE NDB;
-
-ALTER TABLESPACE ts1
-ADD DATAFILE 'datafile02.dat'
-INITIAL_SIZE = 4M
-ENGINE=NDB;
-
-#################################################################
-
---echo --- Start test 2 partition RANGE testing --
---echo --- Do setup --
-
-
-#################################################
-# Requirment: Create table that is partitioned #
-# by range on year i.e. year(t) and replicate #
-# basice operations such at insert, update #
-# delete between 2 different storage engines #
-# Alter table and ensure table is handled #
-# Correctly on the slave #
-#################################################
-
-CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(63),
- bc CHAR(63), d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
- y YEAR, t DATE)
- TABLESPACE ts1 STORAGE DISK
- ENGINE=NDB
- PARTITION BY RANGE (YEAR(t))
- (PARTITION p0 VALUES LESS THAN (1901),
- PARTITION p1 VALUES LESS THAN (1946),
- PARTITION p2 VALUES LESS THAN (1966),
- PARTITION p3 VALUES LESS THAN (1986),
- PARTITION p4 VALUES LESS THAN (2005),
- PARTITION p5 VALUES LESS THAN MAXVALUE);
-
---echo --- Show table on master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Show table on slave --
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- Check that simple Alter statements are replicated correctly ---
-
-ALTER TABLE t1 MODIFY vc VARCHAR(255);
-
---echo --- Show the new improved table on the master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Make sure that our tables on slave are still same engine ---
---echo --- and that the alter statements replicated correctly ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
---enable_query_log
-
---source include/rpl_multi_engine3.inc
-
---echo --- End test 2 partition RANGE testing ---
---echo --- Do Cleanup ---
-
-DROP TABLE IF EXISTS t1;
-
-########################################################
-
---echo --- Start test 3 partition LIST testing ---
---echo --- Do setup ---
-#################################################
-
-
-CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(63),
- bc CHAR(63), d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
- y YEAR, t DATE)
- TABLESPACE ts1 STORAGE DISK
- ENGINE=NDB
- PARTITION BY LIST(id)
- (PARTITION p0 VALUES IN (2, 4),
- PARTITION p1 VALUES IN (42, 142));
-
---echo --- Test 3 Alter to add partition ---
-
-ALTER TABLE t1 ADD PARTITION (PARTITION p2 VALUES IN (412));
-
---echo --- Show table on master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Show table on slave ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- Check that simple Alter statements are replicated correctly ---
-
-ALTER TABLE t1 MODIFY vc VARCHAR(255);
-
---echo --- Show the new improved table on the master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Make sure that our tables on slave are still same engine ---
---echo --- and that the alter statements replicated correctly ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- End test 3 partition LIST testing ---
---echo --- Do Cleanup --
-
-DROP TABLE IF EXISTS t1;
-
-########################################################
-
---echo --- Start test 4 partition HASH testing ---
---echo --- Do setup ---
-#################################################
-
-
-CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(63),
- bc CHAR(63), d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
- y YEAR, t DATE)
- TABLESPACE ts1 STORAGE DISK
- ENGINE=NDB
- PARTITION BY HASH( YEAR(t) )
- PARTITIONS 4;
-
---echo --- show that tables have been created correctly ---
-
-SHOW CREATE TABLE t1;
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- Check that simple Alter statements are replicated correctly ---
-
-ALTER TABLE t1 MODIFY vc VARCHAR(255);
-
---echo --- Show the new improved table on the master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Make sure that our tables on slave are still same engine ---
---echo --- and that the alter statements replicated correctly ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- End test 4 partition HASH testing ---
---echo --- Do Cleanup --
-
-DROP TABLE IF EXISTS t1;
-
-########################################################
-
---echo --- Start test 5 partition by key testing ---
---echo --- Create Table Section ---
-
-#################################################
-
-CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(63),
- bc CHAR(63), d DECIMAL(10,4) DEFAULT 0,
- f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
- y YEAR, t DATE,PRIMARY KEY(id))
- TABLESPACE ts1 STORAGE DISK
- ENGINE=NDB
- PARTITION BY KEY()
- PARTITIONS 4;
-
---echo --- Show that tables on master are ndbcluster tables ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Show that tables on slave ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
-# Okay lets see how it holds up to table changes
---echo --- Check that simple Alter statements are replicated correctly ---
-
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total);
-
---echo --- Show the new improved table on the master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Make sure that our tables on slave are still right type ---
---echo --- and that the alter statements replicated correctly ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- Check that simple Alter statements are replicated correctly ---
-
-ALTER TABLE t1 MODIFY vc VARCHAR(255);
-
---echo --- Show the new improved table on the master ---
-
-SHOW CREATE TABLE t1;
-
---echo --- Make sure that our tables on slave are still same engine ---
---echo --- and that the alter statements replicated correctly ---
-
-sync_slave_with_master;
-SHOW CREATE TABLE t1;
-
---echo --- Perform basic operation on master ---
---echo --- and ensure replicated correctly ---
-
---source include/rpl_multi_engine3.inc
-
---echo --- End test 5 key partition testing ---
---echo --- Do Cleanup ---
-
-DROP TABLE IF EXISTS t1;
-
-# End of 5.1 test case
diff --git a/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt b/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
index f47e5a7e98f..d6f11dcd7bc 100644
--- a/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
+++ b/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
@@ -1 +1 @@
---binlog-format=row --default-storage-engine=ndb
+--binlog-format=row --default-storage-engine=ndbcluster
diff --git a/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt b/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
index f31d53c3cb1..b7990823676 100644
--- a/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
+++ b/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
@@ -1 +1 @@
---default-storage-engine=ndb --binlog-format=row
+--default-storage-engine=ndbcluster --binlog-format=row
diff --git a/mysql-test/t/rpl_openssl.test b/mysql-test/t/rpl_openssl.test
index 8a85443e71f..00ae5c935bf 100644
--- a/mysql-test/t/rpl_openssl.test
+++ b/mysql-test/t/rpl_openssl.test
@@ -53,6 +53,7 @@ stop slave;
change master to master_user='root',master_password='', master_ssl=0;
start slave;
connection master;
+drop user replssl@localhost;
drop table t1;
save_master_pos;
connection slave;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index 7f76aaf3355..a5c8a87c74d 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -1,3 +1,6 @@
+# This test uses chmod, can't be run with root permissions
+-- source include/not_as_root.inc
+
#
# Test is run with max_binlog_size=2048 to force automatic rotation of the
# binary log
diff --git a/mysql-test/t/rpl_row_basic_11bugs.test b/mysql-test/t/rpl_row_basic_11bugs.test
index d098723644f..3a686ea6b3d 100644
--- a/mysql-test/t/rpl_row_basic_11bugs.test
+++ b/mysql-test/t/rpl_row_basic_11bugs.test
@@ -1,5 +1,11 @@
--source include/have_row_based.inc
--source include/have_binlog_format_row.inc
+
+
+#This test case is not written for NDB, the result files
+#will not match when NDB is the default engine
+-- source include/not_ndb_default.inc
+
--source include/master-slave.inc
# Bug#15942 (RBR ignores --binlog_ignore_db and tries to map to table
diff --git a/mysql-test/t/rpl_row_flsh_tbls.test b/mysql-test/t/rpl_row_flsh_tbls.test
index 1a81da39896..9e8efc1ac9c 100644
--- a/mysql-test/t/rpl_row_flsh_tbls.test
+++ b/mysql-test/t/rpl_row_flsh_tbls.test
@@ -6,6 +6,11 @@ let $rename_event_pos= 615;
# Bug#18326: Do not lock table for writing during prepare of statement
# The use of the ps protocol causes extra table maps in the binlog, so
# we disable the ps-protocol for this statement.
+
+# Merge tables are not supported in NDB
+-- source include/not_ndb_default.inc
+
+
--disable_ps_protocol
-- source extra/rpl_tests/rpl_flsh_tbls.test
--enable_ps_protocol
diff --git a/mysql-test/t/rpl_sp004.test b/mysql-test/t/rpl_sp004.test
index 335a17c7af0..055a13cc157 100644
--- a/mysql-test/t/rpl_sp004.test
+++ b/mysql-test/t/rpl_sp004.test
@@ -44,13 +44,13 @@ END|
delimiter ;|
CALL test.p1();
-SELECT * FROM test.t1;
-SELECT * FROM test.t2;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
save_master_pos;
connection slave;
sync_with_master;
-SELECT * FROM test.t1;
-SELECT * FROM test.t2;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
connection master;
CALL test.p2();
@@ -66,14 +66,14 @@ SHOW TABLES;
connection master;
CALL test.p1();
-SELECT * FROM test.t1;
-SELECT * FROM test.t2;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
#SELECT * FROM test.t3;
save_master_pos;
connection slave;
sync_with_master;
-SELECT * FROM test.t1;
-SELECT * FROM test.t2;
+SELECT * FROM test.t1 ORDER BY a;
+SELECT * FROM test.t2 ORDER BY a;
#SELECT * FROM test.t3;
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp004_master.sql
diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test
index c081f8e00c6..40c9a5d0b74 100644
--- a/mysql-test/t/rpl_sp_effects.test
+++ b/mysql-test/t/rpl_sp_effects.test
@@ -1,3 +1,9 @@
+##########################################
+# Change Author: JBM
+# Change Date: 2006-05-02
+# Change: Added Order By for NDB testing
+##########################################
+
# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
-- source include/master-slave.inc
@@ -30,9 +36,9 @@ call p1();
sync_slave_with_master;
connection slave;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
connection master;
-delete from t1;
+SELECT * FROM t1 ORDER BY a;
# 2. Test SP variable name
delimiter //;
@@ -44,10 +50,10 @@ end//
delimiter ;//
call p2();
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
sync_slave_with_master;
connection slave;
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
connection master;
drop procedure p1;
@@ -78,19 +84,19 @@ end//
delimiter ;//
call p1(f1(1), f1(2));
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
create table t2(a int);
insert into t2 values (10),(11);
-select a,f1(a) from t2;
+SELECT a,f1(a) FROM t2 ORDER BY a;
# This shouldn't put separate 'call f1(3)' into binlog:
insert into t2 select f1(3);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop procedure p1;
@@ -102,11 +108,11 @@ 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;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop view v1;
@@ -116,11 +122,11 @@ delete from t1;
prepare s1 from 'select f1(?)';
set @xx=123;
execute s1 using @xx;
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
delete from t1;
@@ -140,10 +146,10 @@ begin
end//
delimiter ;//
call p1(15);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop procedure p1;
@@ -188,10 +194,10 @@ select f1();
set @x=30;
call p1();
-select 'master', a from t1;
+SELECT 'master', a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave', a from t1;
+SELECT 'slave', a FROM t1 ORDER BY a;
connection master;
drop table t1;
diff --git a/mysql-test/t/rpl_stm_until.test b/mysql-test/t/rpl_stm_until.test
index 1bd87db88cb..9a4e4471fe1 100644
--- a/mysql-test/t/rpl_stm_until.test
+++ b/mysql-test/t/rpl_stm_until.test
@@ -32,7 +32,7 @@ wait_for_slave_to_stop;
select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# this should fail right after start
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
@@ -42,7 +42,7 @@ sleep 2;
wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# try replicate all up to and not including the second insert to t2;
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
@@ -51,7 +51,7 @@ wait_for_slave_to_stop;
select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# clean up
start slave;
@@ -68,7 +68,7 @@ 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 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
#testing various error conditions
--error 1277
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
index 7269b54556b..0d91a9f8e91 100644
--- a/mysql-test/t/rpl_temporary.test
+++ b/mysql-test/t/rpl_temporary.test
@@ -131,6 +131,8 @@ drop table t1,t2;
create temporary table t3 (f int);
sync_with_master;
+# The server will now close done
+
#
# Bug#17284 erroneous temp table cleanup on slave
#
@@ -156,5 +158,49 @@ connection master;
drop temporary table t4;
drop table t5;
-# The server will now close done
-# End of 5.1 tests
+#
+# BUG#17263 incorrect generation DROP temp tables
+# Temporary tables of connection are dropped in batches
+# where a batch correspond to pseudo_thread_id
+# value was set up at the moment of temp table creation
+#
+connection con1;
+set @@session.pseudo_thread_id=100;
+create temporary table t101 (id int);
+create temporary table t102 (id int);
+set @@session.pseudo_thread_id=200;
+create temporary table t201 (id int);
+#create temporary table `t``201` (id int);
+# emulate internal temp table not to come to binlog
+create temporary table `#sql_not_user_table202` (id int);
+set @@session.pseudo_thread_id=300;
+create temporary table t301 (id int);
+create temporary table t302 (id int);
+create temporary table `#sql_not_user_table303` (id int);
+disconnect con1;
+
+#now do something to show that slave is ok after DROP temp tables
+connection master;
+create table t1(f int);
+insert into t1 values (1);
+
+sync_slave_with_master;
+#connection slave;
+select * from t1 /* must be 1 */;
+
+connection master;
+drop table t1;
+
+#
+#14157: utf8 encoding in binlog without set character_set_client
+#
+--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test -e 'create table t1 (a int); set names latin1; create temporary table `äöüÄÖÜ` (a int); insert into `äöüÄÖÜ` values (1); insert into t1 select * from `äöüÄÖÜ`'
+
+sync_slave_with_master;
+#connection slave;
+select * from t1;
+
+connection master;
+drop table t1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test
index cb2a1e1d853..08717fce114 100644
--- a/mysql-test/t/rpl_user_variables.test
+++ b/mysql-test/t/rpl_user_variables.test
@@ -1,8 +1,4 @@
###################################
-# Change Author: JBM
-# Change Date: 2006-01-17
-# Change: Added order by
-###################################
#
# Test of replicating user variables
#
@@ -55,6 +51,7 @@ SELECT * FROM t1 ORDER BY n;
sync_slave_with_master;
SELECT * FROM t1 ORDER BY n;
connection master;
+insert into t1 select * FROM (select @var1 union select @var2) AS t2;
drop table t1;
sync_slave_with_master;
stop slave;
diff --git a/mysql-test/t/rpl_view-slave.opt b/mysql-test/t/rpl_view-slave.opt
new file mode 100644
index 00000000000..79b3bf6174b
--- /dev/null
+++ b/mysql-test/t/rpl_view-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=test.foo
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index c4fe1906cbc..4b6ae921b9b 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2871,3 +2871,52 @@ SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
DROP TABLE t1,t2;
+
+#
+# Bug#18712: Truncation problem (needs just documenting and test
+# cases to prevent fixing this accidently. It is intended behaviour)
+#
+
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+SELECT * FROM t1;
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+SELECT * FROM t1;
+UPDATE t1 SET i = i - 1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# BUG#17379
+
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, b int, c int, e int, primary key(a,b,c));
+insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C;
+analyze table t2;
+select 'In next EXPLAIN, B.rows must be exactly 10:' Z;
+
+explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
+ and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
+drop table t1, t2;
+
+#
+#Bug #18940: selection of optimal execution plan caused by equality
+# propagation (the bug was fixed by the patch for bug #17379)
+
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
+INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2),
+ (3,1), (5,1), (8,9), (2,2), (0,9);
+
+CREATE TABLE t2 (c int, d int, f int, INDEX(c,f));
+INSERT INTO t2 VALUES
+ (1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1),
+ (5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1),
+ (0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1);
+
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/sp-goto.test b/mysql-test/t/sp-goto.test
deleted file mode 100644
index e770dd285ff..00000000000
--- a/mysql-test/t/sp-goto.test
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-# 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-security.test b/mysql-test/t/sp-security.test
index f369dc64b0e..a8c3c0a22eb 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -545,6 +545,7 @@ GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
# Cleanup.
DROP DATABASE db_bug7787;
+drop user user_bug7787@localhost;
use test;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 29e657004ed..90d43bf7cc0 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -5705,6 +5705,151 @@ delete from t1|
#
+# BUG#15728: LAST_INSERT_ID function inside a stored function returns 0
+#
+# The solution is not to reset last_insert_id on enter to sub-statement.
+#
+--disable_warnings
+drop function if exists bug15728|
+drop table if exists t3|
+--enable_warnings
+
+create table t3 (
+ id int not null auto_increment,
+ primary key (id)
+)|
+create function bug15728() returns int(11)
+ return last_insert_id()|
+
+insert into t3 values (0)|
+select last_insert_id()|
+select bug15728()|
+
+drop function bug15728|
+drop table t3|
+
+
+#
+# BUG#18787: Server crashed when calling a stored procedure containing
+# a misnamed function
+#
+--disable_warnings
+drop procedure if exists bug18787|
+--enable_warnings
+create procedure bug18787()
+begin
+ declare continue handler for sqlexception begin end;
+
+ select no_such_function();
+end|
+
+call bug18787()|
+drop procedure bug18787|
+
+
+#
+# BUG#18344: DROP DATABASE does not drop associated routines
+# (... if the database name is longer than 21 characters)
+#
+# 1234567890123456789012
+create database bug18344_012345678901|
+use bug18344_012345678901|
+create procedure bug18344() begin end|
+create procedure bug18344_2() begin end|
+
+create database bug18344_0123456789012|
+use bug18344_0123456789012|
+create procedure bug18344() begin end|
+create procedure bug18344_2() begin end|
+
+use test|
+
+select schema_name from information_schema.schemata where
+ schema_name like 'bug18344%'|
+select routine_name,routine_schema from information_schema.routines where
+ routine_schema like 'bug18344%'|
+
+drop database bug18344_012345678901|
+drop database bug18344_0123456789012|
+
+# Should be nothing left.
+select schema_name from information_schema.schemata where
+ schema_name like 'bug18344%'|
+select routine_name,routine_schema from information_schema.routines where
+ routine_schema like 'bug18344%'|
+
+
+#
+# BUG#12472/BUG#15137 'CREATE TABLE ... SELECT ... which explicitly or
+# implicitly uses stored function gives "Table not locked" error'.
+#
+--disable_warnings
+drop function if exists bug12472|
+--enable_warnings
+create function bug12472() returns int return (select count(*) from t1)|
+# Check case when function is used directly
+create table t3 as select bug12472() as i|
+show create table t3|
+select * from t3|
+drop table t3|
+# Check case when function is used indirectly through view
+create view v1 as select bug12472() as j|
+create table t3 as select * from v1|
+show create table t3|
+select * from t3|
+drop table t3|
+drop view v1|
+drop function bug12472|
+
+
+#
+# BUG#18587: Function that accepts and returns TEXT garbles data if longer than
+# 766 chars
+#
+
+# Prepare.
+
+--disable_warnings
+DROP FUNCTION IF EXISTS bug18589_f1|
+DROP PROCEDURE IF EXISTS bug18589_p1|
+DROP PROCEDURE IF EXISTS bug18589_p2|
+--enable_warnings
+
+CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT
+BEGIN
+ RETURN CONCAT(arg, "");
+END|
+
+CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT)
+BEGIN
+ SET ret = CONCAT(arg, "");
+END|
+
+CREATE PROCEDURE bug18589_p2(arg TEXT)
+BEGIN
+ DECLARE v TEXT;
+ CALL bug18589_p1(arg, v);
+ SELECT v;
+END|
+
+# Test case.
+
+SELECT bug18589_f1(REPEAT("a", 767))|
+
+SET @bug18589_v1 = ""|
+CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)|
+SELECT @bug18589_v1|
+
+CALL bug18589_p2(REPEAT("a", 767))|
+
+# Cleanup.
+
+DROP FUNCTION bug18589_f1|
+DROP PROCEDURE bug18589_p1|
+DROP PROCEDURE bug18589_p2|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
index 3854297ec0c..0adbeb2d98b 100644
--- a/mysql-test/t/sp_notembedded.test
+++ b/mysql-test/t/sp_notembedded.test
@@ -1,6 +1,10 @@
# Can't test with embedded server
-- source include/not_embedded.inc
+--sleep 2
+--disable_warnings
+drop table if exists t1,t3;
+--enable_warnings
delimiter |;
#
@@ -258,5 +262,6 @@ drop procedure bug10100pv|
drop procedure bug10100pd|
drop procedure bug10100pc|
drop view v1|
+drop table t3|
delimiter ;|
diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test
index 929a0cb5877..1a71425d2a7 100644
--- a/mysql-test/t/status.test
+++ b/mysql-test/t/status.test
@@ -36,11 +36,111 @@ reap;
show status like 'Table_lock%';
drop table t1;
+disconnect con2;
+disconnect con1;
+connection default;
+
# End of 4.1 tests
#
-# lost_query_cost
+# last_query_cost
#
select 1;
show status like 'last_query_cost';
+
+#
+# Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS
+# if connections are cached
+#
+#
+# The first suggested fix from the bug report was chosen
+# (see http://bugs.mysql.com/bug.php?id=15933):
+#
+# a) On flushing the status, set max_used_connections to
+# threads_connected, not to 0.
+#
+# b) Check if it is necessary to increment max_used_connections when
+# taking a thread from the cache as well as when creating new threads
+#
+
+# Wait for at most $disconnect_timeout seconds for disconnects to finish.
+let $disconnect_timeout = 10;
+
+# Wait for any previous disconnects to finish.
+FLUSH STATUS;
+--disable_query_log
+--disable_result_log
+eval SET @wait_left = $disconnect_timeout;
+let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
+eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
+let $wait_more = `SELECT @max_used_connections != 1 && @wait_left > 0`;
+while ($wait_more)
+{
+ sleep 1;
+ FLUSH STATUS;
+ SET @wait_left = @wait_left - 1;
+ let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
+ eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
+ let $wait_more = `SELECT @max_used_connections != 1 && @wait_left > 0`;
+}
+--enable_query_log
+--enable_result_log
+
+# Prerequisite.
+SHOW STATUS LIKE 'max_used_connections';
+
+# Save original setting.
+SET @save_thread_cache_size=@@thread_cache_size;
+SET GLOBAL thread_cache_size=3;
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+connection con1;
+disconnect con2;
+
+# Check that max_used_connections still reflects maximum value.
+SHOW STATUS LIKE 'max_used_connections';
+
+# Check that after flush max_used_connections equals to current number
+# of connections. First wait for previous disconnect to finish.
+FLUSH STATUS;
+--disable_query_log
+--disable_result_log
+eval SET @wait_left = $disconnect_timeout;
+let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
+eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
+let $wait_more = `SELECT @max_used_connections != 2 && @wait_left > 0`;
+while ($wait_more)
+{
+ sleep 1;
+ FLUSH STATUS;
+ SET @wait_left = @wait_left - 1;
+ let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
+ eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
+ let $wait_more = `SELECT @max_used_connections != 2 && @wait_left > 0`;
+}
+--enable_query_log
+--enable_result_log
+# Check that we don't count disconnected thread any longer.
+SHOW STATUS LIKE 'max_used_connections';
+
+# Check that max_used_connections is updated when cached thread is
+# reused...
+connect (con2,localhost,root,,);
+SHOW STATUS LIKE 'max_used_connections';
+
+# ...and when new thread is created.
+connect (con3,localhost,root,,);
+SHOW STATUS LIKE 'max_used_connections';
+
+# Restore original setting.
+connection default;
+SET GLOBAL thread_cache_size=@save_thread_cache_size;
+
+disconnect con3;
+disconnect con2;
+disconnect con1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
index 54260b09331..212150e057c 100644
--- a/mysql-test/t/strict.test
+++ b/mysql-test/t/strict.test
@@ -1145,3 +1145,13 @@ create table t1(a bit(2));
insert into t1 values(b'101');
select * from t1;
drop table t1;
+
+#
+# Bug#17626 CREATE TABLE ... SELECT failure with TRADITIONAL SQL mode
+#
+set sql_mode='traditional';
+create table t1 (date date not null);
+create table t2 select date from t1;
+show create table t2;
+drop table t2,t1;
+set @@sql_mode= @org_mode;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 1ef80bdd7ac..3f48b648f40 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -2085,3 +2085,27 @@ create table t2 (a int, b int);
insert into t2 values (2, 1), (1, 0);
delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1;
drop table t1, t2;
+
+#
+# Bug #7549: Missing error message for invalid view selection with subquery
+#
+
+CREATE TABLE t1 (a INT);
+
+--error 1054
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+--error 1054
+CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1);
+--error 1054
+SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+
+DROP TABLE t1;
+
+#
+# Bug#19077: A nested materialized derived table is used before being populated.
+#
+create table t1 (i int, j bigint);
+insert into t1 values (1, 2), (2, 2), (3, 2);
+select * from (select min(i) from t1 where j=(select * from (select min(j) from t1) t2)) t3;
+drop table t1;
+
diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test
index 069c19341e4..bfc909d6995 100644
--- a/mysql-test/t/timezone2.test
+++ b/mysql-test/t/timezone2.test
@@ -3,6 +3,7 @@
# Preparing playground
--disable_warnings
drop table if exists t1, t2;
+drop function if exists f1;
--enable_warnings
@@ -222,3 +223,22 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Test for bug #11081 "Using a CONVERT_TZ function in a stored function
+# or trigger fails".
+#
+create table t1 (ldt datetime, udt datetime);
+create function f1(i datetime) returns datetime
+ return convert_tz(i, 'UTC', 'Europe/Moscow');
+create trigger t1_bi before insert on t1 for each row
+ set new.udt:= convert_tz(new.ldt, 'Europe/Moscow', 'UTC');
+# This should work without errors
+insert into t1 (ldt) values ('2006-04-19 16:30:00');
+select * from t1;
+# This should work without errors as well
+select ldt, f1(udt) as ldt2 from t1;
+drop table t1;
+drop function f1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/timezone_grant.test b/mysql-test/t/timezone_grant.test
index f94d86eb266..450c1edc47e 100644
--- a/mysql-test/t/timezone_grant.test
+++ b/mysql-test/t/timezone_grant.test
@@ -1,6 +1,11 @@
# Embedded server testing does not support grants
-- source include/not_embedded.inc
+--disable_warnings
+drop tables if exists t1, t2;
+drop view if exists v1;
+--enable_warnings
+
#
# Test for bug #6116 "SET time_zone := ... requires access to mysql.time_zone
# tables". We should allow implicit access to time zone description tables
@@ -82,3 +87,29 @@ flush privileges;
drop table t1, t2;
# End of 4.1 tests
+
+#
+# Additional test for bug #15153: CONVERT_TZ() is not allowed in all
+# places in views.
+#
+# Let us check that usage of CONVERT_TZ() function in view does not
+# require additional privileges.
+
+# Let us rely on that previous tests done proper cleanups
+create table t1 (a int, b datetime);
+insert into t1 values (1, 20010101000000), (2, 20020101000000);
+grant all privileges on test.* to mysqltest_1@localhost;
+connect (tzuser3, localhost, mysqltest_1,,);
+create view v1 as select a, convert_tz(b, 'UTC', 'Europe/Moscow') as lb from t1;
+select * from v1;
+# Of course we should not be able select from mysql.time_zone tables
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from v1, mysql.time_zone;
+drop view v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+create view v1 as select a, convert_tz(b, 'UTC', 'Europe/Moscow') as lb from t1, mysql.time_zone;
+connection default;
+drop table t1;
+drop user mysqltest_1@localhost;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test
index 67aec1496dd..8ca8ffe904b 100644
--- a/mysql-test/t/trigger-grant.test
+++ b/mysql-test/t/trigger-grant.test
@@ -690,3 +690,176 @@ SELECT @mysqltest_var;
DROP USER mysqltest_u1@localhost;
DROP DATABASE mysqltest_db1;
+
+
+#
+# Test for bug #14635 Accept NEW.x as INOUT parameters to stored
+# procedures from within triggers
+#
+# We require UPDATE privilege when NEW.x passed as OUT parameter, and
+# SELECT and UPDATE when NEW.x passed as INOUT parameter.
+#
+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;
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+
+CREATE TABLE t1 (i1 INT);
+CREATE TABLE t2 (i1 INT);
+
+CREATE USER mysqltest_dfn@localhost;
+CREATE USER mysqltest_inv@localhost;
+
+GRANT EXECUTE, CREATE ROUTINE, TRIGGER ON *.* TO mysqltest_dfn@localhost;
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost;
+
+connect (definer,localhost,mysqltest_dfn,,mysqltest_db1);
+connect (invoker,localhost,mysqltest_inv,,mysqltest_db1);
+
+connection definer;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3;
+CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5;
+
+# Check that having no privilege won't work.
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (7);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (11);
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having only SELECT privilege is not enough.
+connection default;
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (13);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (17);
+
+connection default;
+REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having only UPDATE privilege is enough for OUT parameter,
+# but not for INOUT parameter.
+connection default;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (19);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (23);
+
+connection default;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having SELECT and UPDATE privileges is enough.
+connection default;
+GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (29);
+INSERT INTO t2 VALUES (31);
+
+connection default;
+REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+connection default;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+# Check that late procedure redefining won't open a security hole.
+connection default;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (41);
+
+connection definer;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43;
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (47);
+
+connection definer;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51;
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (53);
+
+connection default;
+DROP PROCEDURE p1;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t1_bi;
+
+# Cleanup.
+disconnect definer;
+disconnect invoker;
+connection default;
+DROP USER mysqltest_inv@localhost;
+DROP USER mysqltest_dfn@localhost;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP DATABASE mysqltest_db1;
+USE test;
+
+--echo End of 5.0 tests.
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index c5925bbd9d5..a87f289e94e 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -1111,6 +1111,180 @@ insert into t1 values
create function f2() returns int return (select max(b) from t2);
insert into t2 select a, f2() from t1;
load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1();
-drop table t1;
drop function f1;
drop function f2;
+drop table t1, t2;
+
+#
+# Test for bug #16021 "Wrong index given to function in trigger" which
+# was caused by the same bulk insert optimization as bug #17764 but had
+# slightly different symptoms (instead of reporting table as crashed
+# storage engine reported error number 124)
+#
+create table t1(i int not null, j int not null, n numeric(15,2), primary key(i,j));
+create table t2(i int not null, n numeric(15,2), primary key(i));
+delimiter |;
+create trigger t1_ai after insert on t1 for each row
+begin
+ declare sn numeric(15,2);
+ select sum(n) into sn from t1 where i=new.i;
+ replace into t2 values(new.i, sn);
+end|
+delimiter ;|
+insert into t1 values
+ (1,1,10.00),(1,2,10.00),(1,3,10.00),(1,4,10.00),(1,5,10.00),
+ (1,6,10.00),(1,7,10.00),(1,8,10.00),(1,9,10.00),(1,10,10.00),
+ (1,11,10.00),(1,12,10.00),(1,13,10.00),(1,14,10.00),(1,15,10.00);
+select * from t1;
+select * from t2;
+drop tables t1, t2;
+
+#
+# Test for Bug #16461 connection_id() does not work properly inside trigger
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ conn_id INT,
+ trigger_conn_id INT
+);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ SET NEW.trigger_conn_id = CONNECTION_ID();
+
+INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
+
+connect (con1,localhost,root,,);
+INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
+connection default;
+disconnect con1;
+
+SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+
+#
+# Bug#6951: Triggers/Traditional: SET @ result wrong
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i1 INT);
+
+SET @save_sql_mode=@@sql_mode;
+
+SET SQL_MODE='';
+
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+ SET @x = 5/0;
+
+SET SQL_MODE='traditional';
+
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ SET @x = 5/0;
+
+SET @x=1;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+
+SET @x=2;
+--error 1365
+UPDATE t1 SET i1 = @x;
+SELECT @x;
+
+SET SQL_MODE='';
+
+SET @x=3;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+
+SET @x=4;
+--error 1365
+UPDATE t1 SET i1 = @x;
+SELECT @x;
+
+SET @@sql_mode=@save_sql_mode;
+
+DROP TRIGGER t1_ai;
+DROP TRIGGER t1_au;
+DROP TABLE t1;
+
+
+#
+# Test for bug #14635 Accept NEW.x as INOUT parameters to stored
+# procedures from within triggers
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+--enable_warnings
+
+CREATE TABLE t1 (i1 INT);
+
+# Check that NEW.x pseudo variable is accepted as INOUT and OUT
+# parameter to stored routine.
+INSERT INTO t1 VALUES (3);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5;
+CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7;
+delimiter //;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+ CALL p1(NEW.i1);
+ CALL p2(NEW.i1);
+END//
+delimiter ;//
+UPDATE t1 SET i1 = 11 WHERE i1 = 3;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+# Check that OLD.x pseudo variable is not accepted as INOUT and OUT
+# parameter to stored routine.
+INSERT INTO t1 VALUES (13);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+ CALL p1(OLD.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 19 WHERE i1 = 13;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+
+INSERT INTO t1 VALUES (23);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+ CALL p1(OLD.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 31 WHERE i1 = 23;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+
+# Check that NEW.x pseudo variable is read-only in the AFTER TRIGGER.
+INSERT INTO t1 VALUES (37);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 43 WHERE i1 = 37;
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+
+INSERT INTO t1 VALUES (47);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 51 WHERE i1 = 47;
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+
+# Post requisite.
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index c9f22cf410b..e2556692612 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -14,18 +14,26 @@ drop table if exists t1;
# Create the example functions from udf_example
#
-CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
-CREATE FUNCTION myfunc_double RETURNS REAL SONAME 'udf_example.so';
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
--error ER_CANT_FIND_DL_ENTRY
-CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME 'udf_example.so';
-CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME 'udf_example.so';
-CREATE FUNCTION sequence 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';
+eval CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION lookup RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION reverse_lookup
+ RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE AGGREGATE FUNCTION avgcost
+ RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
--error 0
select myfunc_double();
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 61861c26ea8..e1b23a1782f 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -143,8 +143,6 @@ select @@Max_Allowed_Packet;
select @@version;
--replace_column 1 #
select @@global.version;
---replace_column 1 #
-select @@session.VERSION;
# End of 4.1 tests
diff --git a/mysql-test/t/variables-master.opt b/mysql-test/t/variables-master.opt
deleted file mode 100644
index abd826bc7fa..00000000000
--- a/mysql-test/t/variables-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---max_join_size=100
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 649265dcc5e..7aa79f0eb40 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -5,6 +5,37 @@
drop table if exists t1,t2;
--enable_warnings
+#
+# Bug #19263: variables.test doesn't clean up after itself (I/II -- save)
+#
+set @my_binlog_cache_size =@@global.binlog_cache_size;
+set @my_connect_timeout =@@global.connect_timeout;
+set @my_delayed_insert_timeout =@@global.delayed_insert_timeout;
+set @my_delayed_queue_size =@@global.delayed_queue_size;
+set @my_flush =@@global.flush;
+set @my_flush_time =@@global.flush_time;
+set @my_key_buffer_size =@@global.key_buffer_size;
+set @my_max_binlog_cache_size =@@global.max_binlog_cache_size;
+set @my_max_binlog_size =@@global.max_binlog_size;
+set @my_max_connect_errors =@@global.max_connect_errors;
+set @my_max_delayed_threads =@@global.max_delayed_threads;
+set @my_max_heap_table_size =@@global.max_heap_table_size;
+set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
+set @my_max_join_size =@@global.max_join_size;
+set @my_max_user_connections =@@global.max_user_connections;
+set @my_max_write_lock_count =@@global.max_write_lock_count;
+set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
+set @my_net_buffer_length =@@global.net_buffer_length;
+set @my_net_write_timeout =@@global.net_write_timeout;
+set @my_net_read_timeout =@@global.net_read_timeout;
+set @my_query_cache_limit =@@global.query_cache_limit;
+set @my_query_cache_type =@@global.query_cache_type;
+set @my_rpl_recovery_rank =@@global.rpl_recovery_rank;
+set @my_server_id =@@global.server_id;
+set @my_slow_launch_time =@@global.slow_launch_time;
+set @my_storage_engine =@@global.storage_engine;
+set @my_thread_cache_size =@@global.thread_cache_size;
+
# case insensitivity tests (new in 5.0)
set @`test`=1;
select @test, @`test`, @TEST, @`TEST`, @"teSt";
@@ -169,7 +200,7 @@ set collation_connection=NULL;
set global autocommit=1;
--error 1238
select @@global.timestamp;
---error 1193
+--error 1238
set @@version='';
--error 1229
set @@concurrent_insert=1;
@@ -258,6 +289,8 @@ select @@sql_max_join_size,@@max_join_size;
set sql_quote_show_create=1;
set sql_safe_updates=1;
set sql_select_limit=1;
+# reset it, so later tests don't get confused
+set sql_select_limit=default;
set sql_warnings=1;
set global table_open_cache=100;
set storage_engine=myisam;
@@ -472,4 +505,102 @@ select @@character_set_filesystem;
set @@global.character_set_filesystem=default;
select @@global.character_set_filesystem;
-# End of 5.0 tests
+#
+# Bug #17849: Show sql_big_selects in SHOW VARIABLES
+#
+set @old_sql_big_selects = @@sql_big_selects;
+set @@sql_big_selects = 1;
+show variables like 'sql_big_selects';
+set @@sql_big_selects = @old_sql_big_selects;
+
+#
+# Bug #16195: SHOW VARIABLES doesn't report correctly sql_warnings and
+# sql_notes values
+#
+set @@sql_notes = 0, @@sql_warnings = 0;
+show variables like 'sql_notes';
+show variables like 'sql_warnings';
+set @@sql_notes = 1, @@sql_warnings = 1;
+show variables like 'sql_notes';
+show variables like 'sql_warnings';
+
+#
+# Bug #12792: @@system_time_zone is not SELECTable.
+#
+# Don't actually output, since it depends on the system
+--replace_column 1 #
+select @@system_time_zone;
+
+#
+# Bug #15684: system variables cannot be SELECTed (e.g. @@version_comment)
+#
+# Don't actually output, since it depends on the system
+--replace_column 1 # 2 # 3 # 4 #
+select @@version, @@version_comment, @@version_compile_machine,
+ @@version_compile_os;
+
+#
+# Bug #1039: make tmpdir and datadir available as @@variables (also included
+# basedir)
+#
+# Don't actually output, since it depends on the system
+--replace_column 1 # 2 # 3 #
+select @@basedir, @@datadir, @@tmpdir;
+--replace_column 2 #
+show variables like 'basedir';
+--replace_column 2 #
+show variables like 'datadir';
+--replace_column 2 #
+show variables like 'tmpdir';
+
+#
+# Bug #19606: make ssl settings available via SHOW VARIABLES and @@variables
+#
+# Don't actually output, since it depends on the system
+--replace_column 1 # 2 # 3 # 4 # 5 #
+select @@ssl_ca, @@ssl_capath, @@ssl_cert, @@ssl_cipher, @@ssl_key;
+--replace_column 2 #
+show variables like 'ssl%';
+
+#
+# Bug #19616: make log_queries_not_using_indexes available in SHOW VARIABLES
+# and as @@log_queries_not_using_indexes
+#
+select @@log_queries_not_using_indexes;
+show variables like 'log_queries_not_using_indexes';
+
+--echo End of 5.0 tests
+
+# This is at the very after the versioned tests, since it involves doing
+# cleanup
+#
+# Bug #19263: variables.test doesn't clean up after itself (II/II --
+# restore)
+#
+set global binlog_cache_size =@my_binlog_cache_size;
+set global connect_timeout =@my_connect_timeout;
+set global delayed_insert_timeout =@my_delayed_insert_timeout;
+set global delayed_queue_size =@my_delayed_queue_size;
+set global flush =@my_flush;
+set global flush_time =@my_flush_time;
+set global key_buffer_size =@my_key_buffer_size;
+set global max_binlog_cache_size =default; #@my_max_binlog_cache_size;
+set global max_binlog_size =@my_max_binlog_size;
+set global max_connect_errors =@my_max_connect_errors;
+set global max_delayed_threads =@my_max_delayed_threads;
+set global max_heap_table_size =@my_max_heap_table_size;
+set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
+set global max_join_size =@my_max_join_size;
+set global max_user_connections =@my_max_user_connections;
+set global max_write_lock_count =@my_max_write_lock_count;
+set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
+set global net_buffer_length =@my_net_buffer_length;
+set global net_write_timeout =@my_net_write_timeout;
+set global net_read_timeout =@my_net_read_timeout;
+set global query_cache_limit =@my_query_cache_limit;
+set global query_cache_type =@my_query_cache_type;
+set global rpl_recovery_rank =@my_rpl_recovery_rank;
+set global server_id =@my_server_id;
+set global slow_launch_time =@my_slow_launch_time;
+set global storage_engine =@my_storage_engine;
+set global thread_cache_size =@my_thread_cache_size;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 82f053fb223..535ba3da7fa 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -2459,3 +2459,145 @@ SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04';
DROP VIEW v1;
DROP TABLE t1;
+
+#
+# BUG#14308: Recursive view definitions
+#
+# using view only
+create table t1 (a int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+drop table t1;
+rename table v2 to t1;
+-- error ER_VIEW_RECURSIVE
+select * from v1;
+drop view t1, v1;
+# using SP function
+create table t1 (a int);
+delimiter //;
+create function f1() returns int
+begin
+ declare mx int;
+ select max(a) from t1 into mx;
+ return mx;
+end//
+delimiter ;//
+create view v1 as select f1() as a;
+create view v2 as select * from v1;
+drop table t1;
+rename table v2 to t1;
+-- error ER_SP_NO_RECURSION
+select * from v1;
+drop function f1;
+drop view t1, v1;
+
+#
+# Bug #15153: CONVERT_TZ() is not allowed in all places in VIEWs
+#
+# Error was reported when one tried to use CONVERT_TZ() function
+# select list of view which was processed using MERGE algorithm.
+# (Also see additional test in timezone_grant.test)
+create table t1 (dt datetime);
+insert into t1 values (20040101000000), (20050101000000), (20060101000000);
+# Let us test that convert_tz() can be used in view's select list
+create view v1 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from t1;
+select * from v1;
+drop view v1;
+# And in its where part
+create view v1 as select * from t1 where convert_tz(dt, 'UTC', 'Europe/Moscow') >= 20050101000000;
+select * from v1;
+# Other interesting case - a view which uses convert_tz() function
+# through other view.
+create view v2 as select * from v1 where dt < 20060101000000;
+select * from v2;
+drop view v2;
+# And even more interesting case when view uses convert_tz() both
+# directly and indirectly
+create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1;
+select * from v2;
+drop view v1, v2;
+drop table t1;
+
+#
+# Bug #19490: usage of view specified by a query with GROUP BY
+# an expression containing non-constant interval
+
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime);
+
+CREATE VIEW v1 AS
+SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*)
+ FROM t1 GROUP BY id, t;
+
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Bug#19077: A nested materialized view is used before being populated.
+#
+CREATE TABLE t1 (i INT, j BIGINT);
+INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
+CREATE VIEW v1 AS SELECT MIN(j) AS j FROM t1;
+CREATE VIEW v2 AS SELECT MIN(i) FROM t1 WHERE j = ( SELECT * FROM v1 );
+SELECT * FROM v2;
+DROP VIEW v2, v1;
+DROP TABLE t1;
+
+#
+# Bug #19573: VIEW with HAVING that refers an alias name
+#
+
+CREATE TABLE t1(
+ fName varchar(25) NOT NULL,
+ lName varchar(25) NOT NULL,
+ DOB date NOT NULL,
+ uID int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY);
+
+INSERT INTO t1(fName, lName, DOB) VALUES
+ ('Hank', 'Hill', '1964-09-29'),
+ ('Tom', 'Adams', '1908-02-14'),
+ ('Homer', 'Simpson', '1968-03-05');
+
+CREATE VIEW v1 AS
+ SELECT (year(now())-year(DOB)) AS Age
+ FROM t1 HAVING Age < 75;
+SHOW CREATE VIEW v1;
+
+SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Bug #19089: wrong inherited dafault values in temp table views
+#
+
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx');
+INSERT INTO t1(id) VALUES (1), (2), (3), (4);
+INSERT INTO t1 VALUES (5,'yyy'), (6,'yyy');
+SELECT * FROM t1;
+
+CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
+SELECT * FROM v1;
+
+CREATE TABLE t2 SELECT * FROM v1;
+INSERT INTO t2(m) VALUES (0);
+SELECT * FROM t2;
+
+DROP VIEW v1;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (id int PRIMARY KEY, e ENUM('a','b') NOT NULL DEFAULT 'b');
+INSERT INTO t1(id) VALUES (1), (2), (3);
+INSERT INTO t1 VALUES (4,'a');
+SELECT * FROM t1;
+
+CREATE VIEW v1(m, e) AS SELECT MIN(id), e FROM t1 GROUP BY e;
+CREATE TABLE t2 SELECT * FROM v1;
+SELECT * FROM t2;
+
+DROP VIEW v1;
+DROP TABLE IF EXISTS t1,t2;
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index 8335c1de20a..8deff474587 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -32,7 +32,7 @@ grant create view,select on test.* to mysqltest_1@localhost;
connect (user1,localhost,mysqltest_1,,test);
connection user1;
--- error ER_SPECIFIC_ACCESS_DENIED
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
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
diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index 1fef3deea3c..9310c3502b9 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -4,10 +4,41 @@
#
# Bug #8731: wait_timeout does not work on Mac OS X
#
+
+
+# Connect with another connection and reset counters
+--disable_query_log
+connect (wait_con,localhost,root,,test,,);
+flush status; # Reset counters
+connection wait_con;
+let $retries=300;
+let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`;
+set @aborted_clients= 0;
+--enable_query_log
+
+# Disable reconnect and do the query
+connection default;
--disable_reconnect
select 1;
-# wait_timeout is 1, so we should get disconnected now
---sleep 2
+
+# Switch to wait_con and wait until server has aborted the connection
+--disable_query_log
+connection wait_con;
+while (!`select @aborted_clients`)
+{
+ sleep 0.1;
+ let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`;
+ eval set @aborted_clients= SUBSTRING('$aborted_clients', 16)+0;
+
+ dec $retries;
+ if (!$retries)
+ {
+ Failed to detect that client has been aborted;
+ }
+}
+--enable_query_log
+
+connection default;
# When the connection is closed in this way, the error code should
# be consistent see bug#2845 for an explanation
--error 2006
@@ -15,12 +46,41 @@ select 2;
--enable_reconnect
select 3;
+#
# Do the same test as above on a TCP connection
+# (which we get by specifying a ip adress)
+
+# Connect with another connection and reset counters
+--disable_query_log
+connection wait_con;
+flush status; # Reset counters
+let $retries=300;
+let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`;
+set @aborted_clients= 0;
+--enable_query_log
+
connect (con1,127.0.0.1,root,,test,$MASTER_MYPORT,);
--disable_reconnect
select 1;
-# wait_timeout is 1, so we should get disconnected now
---sleep 2
+
+# Switch to wait_con and wait until server has aborted the connection
+--disable_query_log
+connection wait_con;
+while (!`select @aborted_clients`)
+{
+ sleep 0.1;
+ let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`;
+ eval set @aborted_clients= SUBSTRING('$aborted_clients', 16)+0;
+
+ dec $retries;
+ if (!$retries)
+ {
+ Failed to detect that client has been aborted;
+ }
+}
+--enable_query_log
+
+connection con1;
# When the connection is closed in this way, the error code should
# be consistent see bug#2845 for an explanation
--error 2006
diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test
index 8a12dbca51d..65d0a40291f 100644
--- a/mysql-test/t/xml.test
+++ b/mysql-test/t/xml.test
@@ -335,3 +335,11 @@ END//
DELIMITER ;//
CALL p2();
DROP PROCEDURE p2;
+
+#
+# Bug#18170: XML: ExtractValue():
+# XPath expression can't use QNames (colon in names)
+#
+select extractValue('<ns:element xmlns:ns="myns"/>','count(ns:element)');
+select extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element');
+select extractValue('<ns:element xmlns:ns="myns">a</ns:element>','/ns:element/@xmlns:ns');
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 69e4ee933b8..6939dd489cd 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -11,26 +11,65 @@
fun:calloc
fun:_dl_allocate_tls
fun:allocate_stack
+ fun:pthread_create*
+}
+
+{
+ pthread allocate_tls memory loss 2
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
fun:pthread_create@@GLIBC_2.1
}
{
- pthread allocate_dtv memory loss
+ pthead_exit memory loss 1
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+}
+
+{
+ pthread_exit memory loss 2
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object
+ fun:dl_open_worker
+}
+
+{
+ pthread_exit memory loss 3
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object_deps
+ fun:dl_open_worker
+}
+
+{
+ pthread_exit memory loss 4
Memcheck:Leak
fun:calloc
- fun:allocate_dtv
- fun:_dl_allocate_tls_storage
- fun:__GI__dl_allocate_tls
- fun:pthread_create
+ fun:_dl_check_map_versions
+ fun:dl_open_worker
}
{
- pthread allocate_dtv memory loss second
+ pthread_exit memory loss 5
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+}
+
+{
+ pthread allocate_dtv memory loss
Memcheck:Leak
fun:calloc
fun:allocate_dtv
- fun:_dl_allocate_tls
- fun:pthread_create*
+ fun:_dl_allocate_tls_storage
+ fun:__GI__dl_allocate_tls
+ fun:pthread_create
}
{
@@ -83,6 +122,15 @@
obj:/lib/ld-*.so
}
+{
+ strlen/_dl_init_paths/dl_main/_dl_sysdep_start(Cond)
+ Memcheck:Cond
+ fun:strlen
+ fun:_dl_init_paths
+ fun:dl_main
+ fun:_dl_sysdep_start
+}
+
{
pthread errno
Memcheck:Leak
@@ -135,6 +183,24 @@
}
{
+ libz longest_match3
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:azflush
+}
+
+{
+ libz longest_match3
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:azclose
+}
+
+{
libz deflate
Memcheck:Cond
obj:*/libz.so.*
@@ -173,3 +239,169 @@
fun:my_thread_init
fun:kill_server_thread
}
+
+# Red Hat AS 4 32 bit
+{
+ dl_relocate_object
+ Memcheck:Cond
+ fun:_dl_relocate_object
+}
+
+#
+# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2.
+#
+
+{
+ _dl_start invalid write8
+ Memcheck:Addr8
+ fun:_dl_start
+}
+
+{
+ _dl_start invalid write4
+ Memcheck:Addr4
+ fun:_dl_start
+}
+
+{
+ _dl_start/_dl_setup_hash invalid read8
+ Memcheck:Addr8
+ fun:_dl_setup_hash
+ fun:_dl_start
+}
+
+{
+ _dl_sysdep_start invalid write8
+ Memcheck:Addr8
+ fun:_dl_sysdep_start
+}
+
+{
+ _dl_init invalid write8
+ Memcheck:Addr8
+ fun:_dl_init
+}
+
+{
+ _dl_init invalid write4
+ Memcheck:Addr4
+ fun:_dl_init
+}
+
+{
+ _dl_init/_dl_init invalid read8
+ Memcheck:Addr8
+ fun:_dl_debug_initialize
+ fun:_dl_init
+}
+
+{
+ _dl_init/_dl_debug_state invalid read8
+ Memcheck:Addr8
+ fun:_dl_debug_state
+ fun:_dl_init
+}
+
+{
+ init invalid write8
+ Memcheck:Addr8
+ fun:init
+}
+
+{
+ fixup invalid write8
+ Memcheck:Addr8
+ fun:fixup
+}
+
+{
+ fixup/_dl_lookup_versioned_symbol invalid read8
+ Memcheck:Addr8
+ fun:_dl_lookup_versioned_symbol
+ fun:fixup
+}
+
+{
+ _dl_runtime_resolve invalid read8
+ Memcheck:Addr8
+ fun:_dl_runtime_resolve
+}
+
+{
+ __libc_start_main invalid write8
+ Memcheck:Addr8
+ fun:__libc_start_main
+}
+
+{
+ __libc_start_main/__sigjmp_save invalid write4
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+}
+
+#
+# These seem to be libc threading stuff, not related to MySQL code (allocations
+# during pthread_exit()). Googling shows other projects also using these
+# suppressions.
+#
+# Note that these all stem from pthread_exit() deeper in the call stack, but
+# Valgrind only allows the top four calls in the suppressions.
+#
+
+{
+ libc pthread_exit 1
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+ fun:_dl_map_object
+}
+
+{
+ libc pthread_exit 2
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 3
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object_deps
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 4
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_check_map_versions
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 5
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+ fun:_dl_map_object
+}
+
+
+#
+# This is seen internally in the system libraries on 64-bit RHAS3.
+#
+
+{
+ __lll_mutex_unlock_wake uninitialized
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
diff --git a/mysys/cmakelists.txt b/mysys/CMakeLists.txt
index 5a3b8f1657e..4aa99a70121 100644
--- a/mysys/cmakelists.txt
+++ b/mysys/CMakeLists.txt
@@ -26,4 +26,4 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
my_windac.c my_winsem.c my_winthread.c my_write.c ptr_cmp.c queues.c
rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
- thr_rwlock.c tree.c typelib.c my_vle.c base64.c)
+ thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c)
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 7a66164b775..1241e8cdded 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -53,10 +53,11 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.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_largepage.c \
+ my_memmem.c \
my_windac.c my_access.c base64.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c \
- cmakelists.txt mf_soundex.c \
+ CMakeLists.txt mf_soundex.c \
my_conio.c my_wincond.c my_winsem.c my_winthread.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
diff --git a/mysys/default.c b/mysys/default.c
index 580bcc19eca..3a80d7b37b9 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -244,7 +244,8 @@ err:
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)
+ prepared to be used in argv (has -- prefix). If it
+ is NULL, we are handling a new group (section).
DESCRIPTION
This handler checks whether a group is one of the listed and adds an option
@@ -263,6 +264,9 @@ static int handle_default_option(void *in_ctx, const char *group_name,
char *tmp;
struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
+ if (!option)
+ return 0;
+
if (find_type((char *)group_name, ctx->group, 3))
{
if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
@@ -719,6 +723,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
end[0]=0;
strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
+
+ /* signal that a new group is found */
+ opt_handler(handler_ctx, curr_gr, NULL);
+
continue;
}
if (!found_group)
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
index 0f58b8a930c..8dbcac699ea 100644
--- a/mysys/default_modify.c
+++ b/mysys/default_modify.c
@@ -40,11 +40,13 @@ static char *add_option(char *dst, const char *option_value,
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.
+ option The name of the option to look for (can be NULL)
+ option value The value of the option we would like to set (can be NULL)
+ section_name The name of the section (must be NOT NULL)
+ remove_option This defines what we want to remove:
+ - MY_REMOVE_NONE -- nothing to remove;
+ - MY_REMOVE_OPTION -- remove the specified option;
+ - MY_REMOVE_SECTION -- remove the specified section;
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
@@ -67,7 +69,9 @@ int modify_defaults_file(const char *file_location, const char *option,
FILE *cnf_file;
MY_STAT file_stat;
char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
- uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size;
+ uint opt_len= 0;
+ uint optval_len= 0;
+ uint sect_len, nr_newlines= 0, buffer_size;
my_bool in_section= FALSE, opt_applied= 0;
uint reserve_extended;
uint new_opt_len;
@@ -81,8 +85,11 @@ int modify_defaults_file(const char *file_location, const char *option,
if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
goto malloc_err;
- opt_len= (uint) strlen(option);
- optval_len= (uint) strlen(option_value);
+ if (option && option_value)
+ {
+ opt_len= (uint) strlen(option);
+ optval_len= (uint) strlen(option_value);
+ }
new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
@@ -119,8 +126,8 @@ int modify_defaults_file(const char *file_location, const char *option,
continue;
}
- /* correct the option */
- if (in_section && !strncmp(src_ptr, option, opt_len) &&
+ /* correct the option (if requested) */
+ if (option && 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'))
@@ -143,7 +150,12 @@ int modify_defaults_file(const char *file_location, const char *option,
}
else
{
- /* If going to new group and we have option to apply, do it now */
+ /*
+ If we are going to the new group and have an option to apply, do
+ it now. If we are removing a single option or the whole section
+ this will only trigger opt_applied flag.
+ */
+
if (in_section && !opt_applied && *src_ptr == '[')
{
dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
@@ -153,7 +165,10 @@ int modify_defaults_file(const char *file_location, const char *option,
for (; nr_newlines; nr_newlines--)
dst_ptr= strmov(dst_ptr, NEWLINE);
- dst_ptr= strmov(dst_ptr, linebuff);
+
+ /* Skip the section if MY_REMOVE_SECTION was given */
+ if (!in_section || remove_option != MY_REMOVE_SECTION)
+ dst_ptr= strmov(dst_ptr, linebuff);
}
/* Look for a section */
if (*src_ptr == '[')
@@ -167,18 +182,31 @@ int modify_defaults_file(const char *file_location, const char *option,
{}
if (*src_ptr != ']')
+ {
+ in_section= FALSE;
continue; /* Missing closing parenthesis. Assume this was no group */
+ }
+
+ if (remove_option == MY_REMOVE_SECTION)
+ dst_ptr= dst_ptr - strlen(linebuff);
+
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)
+
+ /*
+ File ended. Apply an option or set opt_applied flag (in case of
+ MY_REMOVE_SECTION) so that the changes are saved. Do not do anything
+ if we are removing non-existent option.
+ */
+
+ if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION))
{
/* New option still remains to apply at the end */
- if (*(dst_ptr - 1) != '\n')
+ if (!remove_option && *(dst_ptr - 1) != '\n')
dst_ptr= strmov(dst_ptr, NEWLINE);
dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
opt_applied= 1;
diff --git a/mysys/errors.c b/mysys/errors.c
index 4472b7173fa..5fe9eadb522 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -39,7 +39,7 @@ const char * NEAR globerrs[GLOBERRS]=
"Can't get working dirctory (Errcode: %d)",
"Can't change dir to '%s' (Errcode: %d)",
"Warning: '%s' had %d links",
- "%d files and %d streams is left open\n",
+ "Warning: %d files and %d streams is left open\n",
"Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... Retry in %d secs",
"Can't create directory '%s' (Errcode: %d)",
"Character set '%s' is not a compiled character set and is not specified in the '%s' file",
@@ -50,6 +50,7 @@ const char * NEAR globerrs[GLOBERRS]=
"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)",
+ "File '%s' (fileno: %d) was not closed"
};
void init_glob_errs(void)
@@ -78,7 +79,7 @@ void init_glob_errs()
EE(EE_GETWD) = "Can't get working dirctory (Errcode: %d)";
EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)";
EE(EE_LINK_WARNING) = "Warning: '%s' had %d links";
- EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n";
+ EE(EE_OPEN_WARNING) = "Warning: %d files and %d streams is left open\n";
EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space...";
EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)";
EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file";
@@ -89,5 +90,6 @@ void init_glob_errs()
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)";
+ EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed";
}
#endif
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index e181ccfb88d..f1ea21c2a47 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -252,37 +252,89 @@ uint my_b_printf(IO_CACHE *info, const char* fmt, ...)
uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
{
uint out_length=0;
+ uint minimum_width; /* as yet unimplemented */
+ uint minimum_width_sign;
+ uint precision; /* as yet unimplemented for anything but %b */
- for (; *fmt ; fmt++)
+ /*
+ Store the location of the beginning of a format directive, for the
+ case where we learn we shouldn't have been parsing a format string
+ at all, and we don't want to lose the flag/precision/width/size
+ information.
+ */
+ const char* backtrack;
+
+ for (; *fmt != '\0'; fmt++)
{
- if (*fmt++ != '%')
+ /* Copy everything until '%' or end of string */
+ const char *start=fmt;
+ uint length;
+
+ for (; (*fmt != '\0') && (*fmt != '%'); fmt++) ;
+
+ length= (uint) (fmt - start);
+ out_length+=length;
+ if (my_b_write(info, start, length))
+ goto err;
+
+ if (*fmt == '\0') /* End of format */
{
- /* Copy everything until '%' or end of string */
- const char *start=fmt-1;
- uint length;
- for (; *fmt && *fmt != '%' ; fmt++ ) ;
- length= (uint) (fmt - start);
- out_length+=length;
- if (my_b_write(info, start, length))
- goto err;
- if (!*fmt) /* End of format */
- {
- return out_length;
- }
- fmt++;
- /* Found one '%' */
+ return out_length;
}
+
+ /*
+ By this point, *fmt must be a percent; Keep track of this location and
+ skip over the percent character.
+ */
+ DBUG_ASSERT(*fmt == '%');
+ backtrack= fmt;
+ fmt++;
+
+ minimum_width= 0;
+ precision= 0;
+ minimum_width_sign= 1;
/* Skip if max size is used (to be compatible with printf) */
- while (my_isdigit(&my_charset_latin1, *fmt) || *fmt == '.' || *fmt == '-')
+ while (*fmt == '-') { fmt++; minimum_width_sign= -1; }
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
+ fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ minimum_width=(minimum_width * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ minimum_width*= minimum_width_sign;
+
+ if (*fmt == '.') {
fmt++;
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
+ fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ precision=(precision * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ }
+
if (*fmt == 's') /* String parameter */
{
reg2 char *par = va_arg(args, char *);
uint length = (uint) strlen(par);
+ /* TODO: implement minimum width and precision */
out_length+=length;
if (my_b_write(info, par, length))
goto err;
}
+ else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */
+ {
+ char *par = va_arg(args, char *);
+ out_length+= precision;
+ if (my_b_write(info, par, precision))
+ goto err;
+ }
else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
{
register int iarg;
@@ -317,9 +369,9 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
else
{
/* %% or unknown code */
- if (my_b_write(info, "%", 1))
- goto err;
- out_length++;
+ if (my_b_write(info, backtrack, fmt-backtrack))
+ goto err;
+ out_length+= fmt-backtrack;
}
}
return out_length;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index b8c74ddb86b..71d73048a7b 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -84,14 +84,6 @@
#define KEYCACHE_DEBUG_LOG "my_key_cache_debug.log"
*/
-#if defined(MSDOS) && !defined(M_IC80386)
-/* we nead much memory */
-#undef my_malloc_lock
-#undef my_free_lock
-#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE)
-#define my_free_lock(A,B) hfree(A)
-#endif /* defined(MSDOS) && !defined(M_IC80386) */
-
#define STRUCT_PTR(TYPE, MEMBER, a) \
(TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER))
@@ -262,15 +254,9 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond);
#define keycache_pthread_cond_signal pthread_cond_signal
#endif /* defined(KEYCACHE_DEBUG) */
-static uint next_power(uint value)
+static inline uint next_power(uint value)
{
- uint old_value= 1;
- while (value)
- {
- old_value= value;
- value&= value-1;
- }
- return (old_value << 1);
+ return (uint) my_round_up_to_next_power((uint32) value) << 1;
}
@@ -1805,6 +1791,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
uint status;
int page_st;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Read data in key_cache_block_size increments */
do
{
@@ -1814,7 +1801,6 @@ byte *key_cache_read(KEY_CACHE *keycache,
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
filepos-= offset;
read_length= length;
set_if_smaller(read_length, keycache->key_cache_block_size-offset);
@@ -1890,6 +1876,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
#endif
buff+= read_length;
filepos+= read_length+offset;
+ offset= 0;
} while ((length-= read_length));
DBUG_RETURN(start);
@@ -1941,17 +1928,17 @@ int key_cache_insert(KEY_CACHE *keycache,
uint read_length;
int page_st;
int error;
+ uint offset;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
do
{
- uint offset;
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (!keycache->can_be_used)
{
keycache_pthread_mutex_unlock(&keycache->cache_lock);
DBUG_RETURN(0);
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Read data into key cache from buff in key_cache_block_size incr. */
filepos-= offset;
read_length= length;
@@ -2009,6 +1996,7 @@ int key_cache_insert(KEY_CACHE *keycache,
buff+= read_length;
filepos+= read_length+offset;
+ offset= 0;
} while ((length-= read_length));
}
@@ -2075,17 +2063,17 @@ int key_cache_write(KEY_CACHE *keycache,
/* Key cache is used */
uint read_length;
int page_st;
+ uint offset;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
do
{
- uint offset;
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (!keycache->can_be_used)
{
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Write data in key_cache_block_size increments */
filepos-= offset;
read_length= length;
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index cdaee74dd2c..571c4aa9fba 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -73,7 +73,7 @@ my_string my_path(my_string to, const char *progname,
/* test if file without filename is found in path */
/* Returns to if found and to has dirpart if found, else NullS */
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#define F_OK 0
#define PATH_SEP ';'
#define PROGRAM_EXTENSION ".exe"
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index b079b9ec8e3..4f6cbd2f243 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -24,7 +24,7 @@
#endif
#ifdef HAVE_TEMPNAM
-#if !defined(MSDOS) && !defined(__NETWARE__)
+#if !defined(__NETWARE__)
extern char **environ;
#endif
#endif
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 871de8de0b8..9255d716919 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -156,7 +156,7 @@ int check_if_legal_tablename(const char *name)
}
-#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__)
+#if defined(__WIN__) || defined(__EMX__)
/*
@@ -199,4 +199,4 @@ int check_if_legal_filename(const char *path)
DBUG_RETURN(0);
}
-#endif /* defined(MSDOS) || defined(__WIN__) || defined(__EMX__) */
+#endif /* defined(__WIN__) || defined(__EMX__) */
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 01c9b5ea68d..6ef0e171695 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -76,3 +76,33 @@ uint my_count_bits_ushort(ushort v)
return nbits[v];
}
+
+/*
+ Next highest power of two
+
+ SYNOPSIS
+ my_round_up_to_next_power()
+ v Value to check
+
+ RETURN
+ Next or equal power of 2
+ Note: 0 will return 0
+
+ NOTES
+ Algorithm by Sean Anderson, according to:
+ http://graphics.stanford.edu/~seander/bithacks.html
+ (Orignal code public domain)
+
+ Comments shows how this works with 01100000000000000000000000001011
+*/
+
+uint32 my_round_up_to_next_power(uint32 v)
+{
+ v--; /* 01100000000000000000000000001010 */
+ v|= v >> 1; /* 01110000000000000000000000001111 */
+ v|= v >> 2; /* 01111100000000000000000000001111 */
+ v|= v >> 4; /* 01111111110000000000000000001111 */
+ v|= v >> 8; /* 01111111111111111100000000001111 */
+ v|= v >> 16; /* 01111111111111111111111111111111 */
+ return v+1; /* 10000000000000000000000000000000 */
+}
diff --git a/mysys/my_clock.c b/mysys/my_clock.c
index 384239bb2b2..41d659c0ffe 100644
--- a/mysys/my_clock.c
+++ b/mysys/my_clock.c
@@ -24,7 +24,7 @@
long my_clock(void)
{
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(__NETWARE__)
+#if !defined(__WIN__) && !defined(__NETWARE__)
struct tms tmsbuf;
VOID(times(&tmsbuf));
return (tmsbuf.tms_utime + tmsbuf.tms_stime);
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 342b1cdc104..a8a3a775040 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -95,7 +95,7 @@ int my_copy(const char *from, const char *to, myf MyFlags)
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(__NETWARE__)
+#if !defined(__WIN__) && !defined(__NETWARE__)
VOID(chown(to, stat_buff.st_uid,stat_buff.st_gid)); /* Copy ownership */
#endif
#if !defined(VMS) && !defined(__ZTC__)
diff --git a/mysys/my_create.c b/mysys/my_create.c
index d42e7e0db69..d27edb31d32 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -19,7 +19,7 @@
#include <my_dir.h>
#include "mysys_err.h"
#include <errno.h>
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#include <share.h>
#endif
@@ -47,13 +47,6 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
#elif defined(VMS)
fd = open((my_string) FileName, access_flags | O_CREAT, 0,
"ctx=stm","ctx=bin");
-#elif defined(MSDOS)
- if (access_flags & O_SHARE)
- fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
- SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
- else
- fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY,
- MY_S_IREAD | MY_S_IWRITE);
#elif defined(__WIN__)
fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
index f4c420eb459..9666f5b1858 100644
--- a/mysys/my_dup.c
+++ b/mysys/my_dup.c
@@ -19,7 +19,7 @@
#include "mysys_err.h"
#include <my_dir.h>
#include <errno.h>
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#include <share.h>
#endif
diff --git a/mysys/my_file.c b/mysys/my_file.c
index 4c333c7d7db..0abc031a195 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -107,7 +107,10 @@ uint my_set_max_open_files(uint files)
DBUG_RETURN(MY_NFILE);
/* Copy any initialized files */
- memcpy((char*) tmp, (char*) my_file_info, sizeof(*tmp) * my_file_limit);
+ memcpy((char*) tmp, (char*) my_file_info,
+ sizeof(*tmp) * min(my_file_limit, files));
+ bzero((char*) (tmp + my_file_limit),
+ max((int) (files- my_file_limit), 0)*sizeof(*tmp));
my_free_open_file_info(); /* Free if already allocated */
my_file_info= tmp;
my_file_limit= files;
@@ -121,8 +124,12 @@ void my_free_open_file_info()
DBUG_ENTER("my_free_file_info");
if (my_file_info != my_file_info_default)
{
+ /* Copy data back for my_print_open_files */
+ memcpy((char*) my_file_info_default, my_file_info,
+ sizeof(*my_file_info_default)* MY_NFILE);
my_free((char*) my_file_info, MYF(0));
my_file_info= my_file_info_default;
+ my_file_limit= MY_NFILE;
}
DBUG_VOID_RETURN;
}
diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c
index 27281f3489d..0644ba02bbd 100644
--- a/mysys/my_gethostbyname.c
+++ b/mysys/my_gethostbyname.c
@@ -18,7 +18,7 @@
/* Thread safe version of gethostbyname_r() */
#include "mysys_priv.h"
-#if !defined(MSDOS) && !defined(__WIN__)
+#if !defined(__WIN__)
#include <netdb.h>
#endif
#include <my_net.h>
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 95dc5afeae9..4de2984d9b9 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -486,7 +486,7 @@ invalid value '%s'\n",
}
get_one_option(optp->id, optp, argument);
- (*argc)--; /* option handled (short or long), decrease argument count */
+ (*argc)--; /* option handled (short or long), decrease argument count */
}
else /* non-option found */
(*argv)[argvpos++]= cur_arg;
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index 765c30bc281..de8ad108ba4 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -22,7 +22,7 @@
#ifdef HAVE_GETWD
#include <sys/param.h>
#endif
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#include <m_ctype.h>
#include <dos.h>
#include <direct.h>
@@ -39,11 +39,9 @@ int my_getwd(my_string buf, uint size, myf MyFlags)
DBUG_ENTER("my_getwd");
DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", buf,size,MyFlags));
-#if ! defined(MSDOS)
if (curr_dir[0]) /* Current pos is saved here */
VOID(strmake(buf,&curr_dir[0],size-1));
else
-#endif
{
#if defined(HAVE_GETCWD)
if (!getcwd(buf,size-2) && MyFlags & MY_WME)
@@ -87,43 +85,13 @@ int my_setwd(const char *dir, myf MyFlags)
int res;
size_s length;
my_string start,pos;
-#if defined(VMS) || defined(MSDOS)
+#if defined(VMS)
char buff[FN_REFLEN];
#endif
DBUG_ENTER("my_setwd");
DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags));
start=(my_string) dir;
-#if defined(MSDOS) /* MSDOS chdir can't change drive */
-#if !defined(_DDL) && !defined(WIN32)
- if ((pos=(char*) strchr(dir,FN_DEVCHAR)) != 0)
- {
- uint drive,drives;
-
- pos++; /* Skip FN_DEVCHAR */
- drive=(uint) (my_toupper(&my_charset_latin1,dir[0])-'A'+1);
- drives= (uint) -1;
- if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32)
- {
- _dos_setdrive(drive,&drives);
- _dos_getdrive(&drives);
- }
- if (drive != drives)
- {
- *pos='\0'; /* Dir is now only drive */
- my_errno=errno;
- my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),dir,ENOENT);
- DBUG_RETURN(-1);
- }
- dir=pos; /* drive changed, change now path */
- }
-#endif
- if (*((pos=strend(dir)-1)) == FN_LIBCHAR && pos != dir)
- {
- strmov(buff,dir)[-1]=0; /* Remove last '/' */
- dir=buff;
- }
-#endif /* MSDOS*/
if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0))
dir=FN_ROOTDIR;
#ifdef VMS
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 88b8e457bd6..588bb6f46d6 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -150,6 +150,7 @@ void my_end(int infoflag)
sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened);
(void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL);
DBUG_PRINT("error",("%s",errbuff[0]));
+ my_print_open_files();
}
}
free_charsets();
@@ -180,7 +181,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals,
rus.ru_nvcsw, rus.ru_nivcsw);
#endif
-#if ( defined(MSDOS) || defined(__NETWARE__) ) && !defined(__WIN__)
+#if defined(__NETWARE__) && !defined(__WIN__)
fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC);
#endif
#if defined(SAFEMALLOC)
@@ -196,8 +197,10 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
_CrtDumpMemoryLeaks();
#endif
}
+
+ if (!(infoflag & MY_DONT_FREE_DBUG))
+ DBUG_END(); /* Must be done before my_thread_end */
#ifdef THREAD
- DBUG_POP(); /* Must be done before my_thread_end */
my_thread_end();
my_thread_global_end();
#if defined(SAFE_MUTEX)
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index e96286a94a8..42c57e9d3c4 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* TODO: check for overun of memory for names. */
-/* Convert MSDOS-TIME to standar time_t */
+/* Convert MSDOS-TIME to standar time_t (still needed?) */
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
@@ -37,7 +37,7 @@
# if defined(HAVE_NDIR_H)
# include <ndir.h>
# endif
-# if defined(MSDOS) || defined(__WIN__)
+# if defined(__WIN__)
# include <dos.h>
# ifdef __BORLANDC__
# include <dir.h>
@@ -94,7 +94,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b)
} /* comp_names */
-#if !defined(MSDOS) && !defined(__WIN__)
+#if !defined(__WIN__)
MY_DIR *my_dir(const char *path, myf MyFlags)
{
@@ -347,7 +347,7 @@ my_string directory_file_name (my_string dst, const char *src)
#endif /* VMS */
} /* directory_file_name */
-#elif defined(WIN32)
+#else
/*
*****************************************************************************
@@ -386,7 +386,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
*tmp_file++= '.'; /* From current dev-dir */
if (tmp_file[-1] != FN_LIBCHAR)
*tmp_file++ =FN_LIBCHAR;
- tmp_file[0]='*'; /* MSDOS needs this !??? */
+ tmp_file[0]='*'; /* Windows needs this !??? */
tmp_file[1]='.';
tmp_file[2]='*';
tmp_file[3]='\0';
@@ -509,109 +509,7 @@ error:
DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
-#else /* MSDOS and not WIN32 */
-
-
-/******************************************************************************
-** At MSDOS you always get stat of files, but time is in packed MSDOS-format
-******************************************************************************/
-
-MY_DIR *my_dir(const char* path, myf MyFlags)
-{
- char *buffer;
- MY_DIR *result= 0;
- FILEINFO finfo;
- DYNAMIC_ARRAY *dir_entries_storage;
- MEM_ROOT *names_storage;
- struct find_t find;
- ushort mode;
- char tmp_path[FN_REFLEN],*tmp_file,attrib;
- DBUG_ENTER("my_dir");
- DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
-
- /* Put LIB-CHAR as last path-character if not there */
-
- tmp_file=tmp_path;
- if (!*path)
- *tmp_file++ ='.'; /* From current dir */
- tmp_file= strmov(tmp_file,path);
- if (tmp_file[-1] == FN_DEVCHAR)
- *tmp_file++= '.'; /* From current dev-dir */
- if (tmp_file[-1] != FN_LIBCHAR)
- *tmp_file++ =FN_LIBCHAR;
- tmp_file[0]='*'; /* MSDOS needs this !??? */
- tmp_file[1]='.';
- tmp_file[2]='*';
- tmp_file[3]='\0';
-
- if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
- goto error;
-
- if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
- sizeof(MEM_ROOT), MyFlags)))
- goto error;
-
- dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
- names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
-
- if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
- ENTRIES_START_SIZE, ENTRIES_INCREMENT))
- {
- my_free((gptr) buffer,MYF(0));
- goto error;
- }
- init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
-
- /* MY_DIR structure is allocated and completly initialized at this point */
- result= (MY_DIR*)buffer;
-
- do
- {
- if (!(finfo.name= strdup_root(names_storage, find.name)))
- goto error;
-
- if (MyFlags & MY_WANT_STAT)
- {
- if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
- sizeof(MY_STAT))))
- goto error;
-
- bzero(finfo.mystat, sizeof(MY_STAT));
- finfo.mystat->st_size= find.size;
- mode= MY_S_IREAD; attrib= find.attrib;
- if (!(attrib & _A_RDONLY))
- mode|= MY_S_IWRITE;
- if (attrib & _A_SUBDIR)
- mode|= MY_S_IFDIR;
- finfo.mystat->st_mode= mode;
- finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time;
- }
- else
- finfo.mystat= NULL;
-
- if (push_dynamic(dir_entries_storage, (gptr)&finfo))
- goto error;
-
- } while (_dos_findnext(&find) == 0);
-
- result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
- result->number_off_files= dir_entries_storage->elements;
-
- if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
- sizeof(FILEINFO), (qsort_cmp) comp_names);
- DBUG_RETURN(result);
-
-error:
- my_dirend(result);
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
- DBUG_RETURN((MY_DIR *) NULL);
-} /* my_dir */
-
-#endif /* WIN32 && MSDOS */
+#endif /* __WIN__ */
/****************************************************************************
** File status
diff --git a/mysys/my_memmem.c b/mysys/my_memmem.c
new file mode 100644
index 00000000000..682a1314f09
--- /dev/null
+++ b/mysys/my_memmem.c
@@ -0,0 +1,66 @@
+#include "my_base.h"
+
+/*
+ my_memmem, port of a GNU extension.
+
+ Returns a pointer to the beginning of the substring, needle, or NULL if the
+ substring is not found in haystack.
+*/
+void *my_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ const unsigned char *cursor;
+ const unsigned char *last_possible_needle_location =
+ (unsigned char *)haystack + haystacklen - needlelen;
+
+ /* Easy answers */
+ if (needlelen > haystacklen) return(NULL);
+ if (needle == NULL) return(NULL);
+ if (haystack == NULL) return(NULL);
+ if (needlelen == 0) return(NULL);
+ if (haystacklen == 0) return(NULL);
+
+ for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) {
+ if (memcmp(needle, cursor, needlelen) == 0) {
+ return((void *) cursor);
+ }
+ }
+ return(NULL);
+}
+
+
+
+#ifdef MAIN
+#include <assert.h>
+
+int main(int argc, char *argv[]) {
+ char haystack[10], needle[3];
+
+ memmove(haystack, "0123456789", 10);
+
+ memmove(needle, "no", 2);
+ assert(my_memmem(haystack, 10, needle, 2) == NULL);
+
+ memmove(needle, "345", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+
+ memmove(needle, "789", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(haystack, 9, needle, 3) == NULL);
+
+ memmove(needle, "012", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+ assert(my_memmem(haystack, 0, needle, 3) == NULL);
+ assert(my_memmem(haystack, 10, NULL, 3) == NULL);
+ assert(my_memmem(haystack, 10, needle, 0) == NULL);
+
+ assert(my_memmem(haystack, 1, needle, 3) == NULL);
+
+ printf("success\n");
+ return(0);
+}
+
+#endif
diff --git a/mysys/my_net.c b/mysys/my_net.c
index be92adae353..09c09b280d1 100644
--- a/mysys/my_net.c
+++ b/mysys/my_net.c
@@ -20,7 +20,7 @@
#include <m_string.h>
/* for thread safe my_inet_ntoa */
-#if !defined(MSDOS) && !defined(__WIN__)
+#if !defined(__WIN__)
#include <netdb.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -31,7 +31,7 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#endif /* !defined(MSDOS) && !defined(__WIN__) */
+#endif /* !defined(__WIN__) */
void my_inet_ntoa(struct in_addr in, char *buf)
{
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 098d410d8ce..6041ddde9fc 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -19,7 +19,7 @@
#include "mysys_err.h"
#include <my_dir.h>
#include <errno.h>
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
#include <share.h>
#endif
@@ -45,7 +45,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
DBUG_ENTER("my_open");
DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d",
FileName, Flags, MyFlags));
-#if defined(MSDOS) || defined(__WIN__)
+#if defined(__WIN__)
/*
Check that we don't try to open or create a file name that may
cause problems for us in the future (like PRN)
@@ -351,3 +351,24 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode)
return fh; /* return handle */
}
#endif /* __WIN__ */
+
+
+#ifdef EXTRA_DEBUG
+
+void my_print_open_files(void)
+{
+ if (my_file_opened | my_stream_opened)
+ {
+ uint i;
+ for (i= 0 ; i < my_file_limit ; i++)
+ {
+ if (my_file_info[i].type != UNOPEN)
+ {
+ fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i);
+ fputc('\n', stderr);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mysys/my_redel.c b/mysys/my_redel.c
index 02d3db8b860..abfe84102ef 100644
--- a/mysys/my_redel.c
+++ b/mysys/my_redel.c
@@ -90,14 +90,14 @@ int my_copystat(const char *from, const char *to, int MyFlags)
return 1;
VOID(chmod(to, statbuf.st_mode & 07777)); /* Copy modes */
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(__NETWARE__)
+#if !defined(__WIN__) && !defined(__NETWARE__)
if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING)
{
if (MyFlags & MY_LINK_WARNING)
my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink);
}
VOID(chown(to, statbuf.st_uid, statbuf.st_gid)); /* Copy ownership */
-#endif /* MSDOS */
+#endif /* !__WIN__ && !__NETWARE__ */
#ifndef VMS
#ifndef __ZTC__
diff --git a/mysys/tree.c b/mysys/tree.c
index 1780913961e..0c9c04919b0 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -271,7 +271,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
return element;
}
-int tree_delete(TREE *tree, void *key, void *custom_arg)
+int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg)
{
int cmp,remove_colour;
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
@@ -326,8 +326,7 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent);
if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
- /* This doesn't include key_size, but better than nothing */
- tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
+ tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size;
my_free((gptr) element,MYF(0));
tree->elements_in_tree--;
return 0;
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index d0f68a9c84b..6dee710103e 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -1,6 +1,28 @@
-SUBDIRS= fulltext
+# 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
+
+# Process this file with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
# extra plugin example files are listed here, to
# keep its Makefile.am cleaner as a template
-EXTRA_DIST= fulltext/configure.in
+EXTRA_DIST = fulltext/configure.in
+
+SUBDIRS = @mysql_pg_dirs@
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/plugin/fulltext/Makefile.am b/plugin/fulltext/Makefile.am
index 4df5a1dc78a..7b4ae22cbd2 100644
--- a/plugin/fulltext/Makefile.am
+++ b/plugin/fulltext/Makefile.am
@@ -6,4 +6,4 @@ noinst_LTLIBRARIES= mypluglib.la
#pkglib_LTLIBRARIES= mypluglib.la
mypluglib_la_SOURCES= plugin_example.c
mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir)
-
+mypluglib_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN
diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c
index cdf1527b310..9b937453ce4 100644
--- a/plugin/fulltext/plugin_example.c
+++ b/plugin/fulltext/plugin_example.c
@@ -216,7 +216,7 @@ static struct st_mysql_show_var simple_status[]=
Plugin library descriptor
*/
-mysql_declare_plugin
+mysql_declare_plugin(ftexample)
{
MYSQL_FTPARSER_PLUGIN, /* type */
&simple_parser_descriptor, /* descriptor */
diff --git a/regex/cmakelists.txt b/regex/CMakeLists.txt
index e00f339b3b9..e00f339b3b9 100644
--- a/regex/cmakelists.txt
+++ b/regex/CMakeLists.txt
diff --git a/regex/Makefile.am b/regex/Makefile.am
index 6fd5b1b57a2..1f496fcec62 100644
--- a/regex/Makefile.am
+++ b/regex/Makefile.am
@@ -25,7 +25,7 @@ re_SOURCES = split.c debug.c main.c
re_LDFLAGS= @NOINST_LDFLAGS@
EXTRA_DIST = tests CHANGES COPYRIGHT WHATSNEW regexp.c \
debug.ih engine.ih main.ih regcomp.ih regerror.ih \
- regex.3 regex.7 cmakelists.txt
+ regex.3 regex.7 CMakeLists.txt
test: re tests
./re < tests
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 56a2d4a7bc6..af3cbc19cb5 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -30,7 +30,6 @@ bin_SCRIPTS = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
- mysql_explain_log \
mysqld_multi \
mysql_create_system_tables
@@ -55,7 +54,6 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
mysql_find_rows.sh \
mysqlhotcopy.sh \
mysqldumpslow.sh \
- mysql_explain_log.sh \
mysqld_multi.sh \
mysqld_safe.sh \
mysql_create_system_tables.sh
@@ -83,7 +81,6 @@ CLEANFILES = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
- mysql_explain_log \
mysql_tableinfo \
mysqld_multi \
make_win_src_distribution \
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index aa29d48d50d..1b071a294ed 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -148,7 +148,7 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
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/init_db.sql netware/test_db.sql$BS \
netware/mysqlhotcopy$BS netware/libmysql$BS netware/init_secure_db.sql \
";
# For all other platforms:
diff --git a/scripts/mysql_explain_log.sh b/scripts/mysql_explain_log.sh
deleted file mode 100644
index 973d9e8a363..00000000000
--- a/scripts/mysql_explain_log.sh
+++ /dev/null
@@ -1,392 +0,0 @@
-#!@PERL@ -w
-use strict;
-use DBI;
-
-use Getopt::Long;
-$Getopt::Long::ignorecase=0;
-
-print "explain_log provided by http://www.mobile.de\n";
-print "=========== ================================\n";
-
-my $Param={};
-
-$Param->{host}='';
-$Param->{user}='';
-$Param->{password}='';
-$Param->{PrintError}=0;
-$Param->{socket}='';
-
-if (!GetOptions ('date|d:i' => \$Param->{ViewDate},
- 'host|h:s' => \$Param->{host},
- 'user|u:s' => \$Param->{user},
- 'password|p:s' => \$Param->{password},
- 'printerror|e:s' => \$Param->{PrintError},
- 'socket|s:s' => \$Param->{socket},
- )) {
- ShowOptions();
-}
-else {
- $Param->{UpdateCount} = 0;
- $Param->{SelectCount} = 0;
- $Param->{IdxUseCount} = 0;
- $Param->{LineCount} = 0;
-
- $Param->{Init} = 0;
- $Param->{Field} = 0;
- $Param->{Refresh} = 0;
- $Param->{QueryCount} = 0;
- $Param->{Statistics} =0;
-
- $Param->{Query} = undef;
- $Param->{ALL} = undef ;
- $Param->{Comment} = undef ;
-
- @{$Param->{Rows}} = (qw|possible_keys key type|);
-
- if ($Param->{ViewDate}) {
- $Param->{View} = 0;
- }
- else {
- $Param->{View} = 1;
- }
-
- #print "Date=$Param->{ViewDate}, host=$Param->{host}, user=$Param->{user}, password=$Param->{password}\n";
-
- $Param->{dbh}=DBI->connect("DBI:mysql:host=$Param->{host}".($Param->{socket}?";mysql_socket=$Param->{socket}":""),$Param->{user},$Param->{password},{PrintError=>0});
- if (DBI::err()) {
- print "Error: " . DBI::errstr() . "\n";
- }
- else {
- $Param->{Start} = time;
- while(<STDIN>) {
- $Param->{LineCount} ++ ;
-
- if ($Param->{ViewDate} ) {
- if (m/^(\d{6})\s+\d{1,2}:\d\d:\d\d\s.*$/) { # get date
- #print "# $1 #\n";
- if ($1 == $Param->{ViewDate}) {
- $Param->{View} = 1;
- }
- else {
- $Param->{View} = 0;
- }
- }
- }
- if ($Param->{View} ) {
- #print "->>>$_";
-
- if (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
- #print "C-$1--$2--$3------\n";
- RunQuery($Param);
- if (defined $3) {
- $Param->{CID}->{$2} = $3 ;
- #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
- }
- }
-
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+$/i) { # get connection ID($2) and database($3)
- #print "\n <<<<<<<<<<<<<<<<<<----------------------------<<<<<<<<<<<<<<<< \n";
- #print "Connect \n";
- RunQuery($Param);
- }
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Change user .*\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
- #print "C-$1--$2--$3------\n";
- RunQuery($Param);
- if (defined $3) {
- $Param->{CID}->{$2} = $3 ;
- #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
- }
- }
-
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Quit\s+$/i) { # remove connection ID($2) and querystring
- #print "Q-$1--$2--------\n";
- RunQuery($Param);
- delete $Param->{CID}->{$2} ;
- }
-
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(select.+)$/i) { # get connection ID($2) and querystring
- #print "S1-$1--$2--$3------\n";
- RunQuery($Param);
- unless ($Param->{CID}->{$2}) {
- #print "Error: No Database for Handle: $2 found\n";
- }
- else {
- $Param->{DB}=$Param->{CID}->{$2};
-
- my $s = "$3";
- $s =~ s/from\s/from $Param->{DB}./i;
- $Param->{Query}="EXPLAIN $s";
-
- #$s =~ m/from\s+(\w+[.]\w+)/i;
- #$Param->{tab} =$1;
- #print "-- $Param->{tab} -- $s --\n";
- }
- }
-
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(update.+)$/i) { # get connection ID($2) and querystring
- #print "S2--$1--$2--$3------\n";
- RunQuery($Param);
- unless ($Param->{CID}->{$2}) {
- #print "Error: No Database for Handle: $2 found\n";
- }
- else {
- $Param->{DB}=$Param->{CID}->{$2};
-
- my $ud = $3;
- $ud =~ m/^update\s+(\w+).+(where.+)$/i;
- $Param->{Query} ="EXPLAIN SELECT * FROM $1 $2";
- $Param->{Query} =~ s/from\s/from $Param->{DB}./i;
-
- #$Param->{Query} =~ m/from\s+(\w+[.]\w+)/i;
- #$Param->{tab} =$1;
- }
- }
-
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Statistics\s+(.*)$/i) { # get connection ID($2) and info?
- $Param->{Statistics} ++;
- #print "Statistics--$1--$2--$3------\n";
- RunQuery($Param);
- }
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(.+)$/i) { # get connection ID($2)
- $Param->{QueryCount} ++;
- #print "Query-NULL $3\n";
- RunQuery($Param);
- }
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Refresh\s+(.+)$/i) { # get connection ID($2)
- $Param->{Refresh} ++;
- #print "Refresh\n";
- RunQuery($Param);
- }
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Init\s+(.+)$/i) { # get connection ID($2)
- $Param->{Init} ++;
- #print "Init $3\n";
- RunQuery($Param);
- }
- elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Field\s+(.+)$/i) { # get connection ID($2)
- $Param->{Field} ++;
- #print "Field $3\n";
- RunQuery($Param);
- }
-
- elsif (m/^\s+(.+)$/ ) { # command could be some lines ...
- #print "multi-lined ($1)\n";
- my ($A)=$1;
- chomp $A;
- $Param->{Query} .= " $1";
- #print "multi-lined ($1)<<$Param->{Query}>>\n";
- }
-
-
- }
-
- }
-
- $Param->{dbh}->disconnect();
-
- if (1 == 0) {
- print "\nunclosed handles----------------------------------------\n";
- my $count=0;
- foreach (sort keys %{$Param->{CID}}) {
- print "$count | $_ : $Param->{CID}->{$_} \n";
- $count ++;
- }
- }
-
- print "\nIndex usage ------------------------------------\n";
- foreach my $t (sort keys %{$Param->{Data}}) {
- print "\nTable\t$t: ---\n";
- foreach my $k (sort keys %{$Param->{Data}->{$t}}) {
- print " count\t$k:\n";
- my %h = %{$Param->{Data}->{$t}->{$k}};
- foreach (sort {$h{$a} <=> $h{$b}} keys %h) {
- print " $Param->{Data}->{$t}->{$k}->{$_}\t$_\n";
- }
- }
- }
-
- $Param->{AllCount}=0;
- print "\nQueries causing table scans -------------------\n\n";
- foreach (@{$Param->{ALL}}) {
- $Param->{AllCount} ++;
- print "$_\n";
- }
- print "Sum: $Param->{AllCount} table scans\n";
-
- print "\nSummary ---------------------------------------\n\n";
- print "Select: \t$Param->{SelectCount} queries\n";
- print "Update: \t$Param->{UpdateCount} queries\n";
- print "\n";
-
- print "Init: \t$Param->{Init} times\n";
- print "Field: \t$Param->{Field} times\n";
- print "Refresh: \t$Param->{Refresh} times\n";
- print "Query: \t$Param->{QueryCount} times\n";
- print "Statistics:\t$Param->{Statistics} times\n";
- print "\n";
-
- print "Logfile: \t$Param->{LineCount} lines\n";
- print "Started: \t".localtime($Param->{Start})."\n";
- print "Finished: \t".localtime(time)."\n";
-
- }
-}
-
-
-###########################################################################
-#
-#
-#
-sub RunQuery {
- my $Param = shift ;
-
- if (defined $Param->{Query}) {
- if (defined $Param->{DB} ) {
-
- $Param->{Query} =~ m/from\s+(\w+[.]\w+|\w+)/i;
- $Param->{tab} =$1;
- #print "||$Param->{tab} -- $Param->{Query}\n";
-
- my $sth=$Param->{dbh}->prepare("USE $Param->{DB}");
- if (DBI::err()) {
- if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
- }
- else {
- $sth->execute();
- if (DBI::err()) {
- if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
- }
- else {
- $sth->finish();
-
- $sth=$Param->{dbh}->prepare($Param->{Query});
- if (DBI::err()) {
- if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
- }
- else {
- #print "$Param->{Query}\n";
- $sth->execute();
- if (DBI::err()) {
- if ($Param->{PrintError}) {print "[$Param->{LineCount}]<<$Param->{Query}>>\n";}
- if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
- }
- else {
- my $row = undef;
- while ($row = $sth->fetchrow_hashref()) {
- $Param->{SelectCount} ++;
-
- if (defined $row->{Comment}) {
- push (@{$Param->{Comment}}, "$row->{Comment}; $_; $Param->{DB}; $Param->{Query}");
- }
- foreach (@{$Param->{Rows}}) {
- if (defined $row->{$_}) {
- #if (($_ eq 'type' ) and ($row->{$_} eq 'ALL')) {
- if ($row->{type} eq 'ALL') {
- push (@{$Param->{ALL}}, "$Param->{Query}");
- #print ">> $row->{$_} $_ $Param->{DB} $Param->{Query}\n";
- }
- $Param->{IdxUseCount} ++;
- $Param->{Data}->{$Param->{tab}}->{$_}->{$row->{$_}} ++;
- }
- }
- }
- }
- }
- }
- }
- $sth->finish();
- }
- $Param->{Query} = undef ;
- }
-}
-
-###########################################################################
-#
-#
-#
-sub ShowOptions {
- print <<EOF;
-Usage: $0 [OPTIONS] < LOGFILE
-
---date=YYMMDD select only entrys of date
--d=YYMMDD
---host=HOSTNAME db-host to ask
--h=HOSTNAME
---user=USERNAME db-user
--u=USERNAME
---password=PASSWORD password of db-user
--p=PASSWORD
---socket=SOCKET mysqld socket file to connect
--s=SOCKET
-
-Read logfile from STDIN an try to EXPLAIN all SELECT statements. All UPDATE statements are rewritten to an EXPLAIN SELECT statement. The results of the EXPLAIN statement are collected and counted. All results with type=ALL are collected in an separete list. Results are printed to STDOUT.
-
-EOF
-}
-
-1;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-explain_log.pl
-
-Feed a mysqld general logfile (created with mysqld --log) back into mysql
-and collect statistics about index usage with EXPLAIN.
-
-=head1 DISCUSSION
-
-To optimize your indices, you have to know which ones are actually
-used and what kind of queries are causing table scans. Especially
-if you are generating your queries dynamically and you have a huge
-amount of queries going on, this isn't easy.
-
-Use this tool to take a look at the effects of your real life queries.
-Then add indices to avoid table scans and remove those which aren't used.
-
-=head1 USAGE
-
-explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] [--socket=/path/to/socket] < logfile
-
---date=YYMMDD select only entrys of date
-
--d=YYMMDD
-
---host=HOSTNAME db-host to ask
-
--h=HOSTNAME
-
---user=USERNAME db-user
-
--u=USERNAME
-
---password=PASSWORD password of db-user
-
--p=PASSWORD
-
---socket=SOCKET change path to the socket
-
--s=SOCKET
-
-=head1 EXAMPLE
-
-explain_log.pl --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log
-
-=head1 AUTHORS
-
- Stefan Nitz
- Jan Willamowius <jan@mobile.de>, http://www.mobile.de
- Dennis Haney <davh@davh.dk> (Added socket support)
-
-=head1 RECRUITING
-
-If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de
-and send me an email with your resume (you must be speaking German!).
-
-=head1 SEE ALSO
-
-mysql documentation
-
-=cut
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 5b3cab16db2..f3c0c7f13be 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -570,7 +570,7 @@ DROP PROCEDURE create_log_tables;
CREATE TABLE event (
db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- name char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
+ name char(64) CHARACTER SET utf8 NOT NULL default '',
body longblob NOT NULL,
definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
execute_at DATETIME default NULL,
@@ -636,7 +636,7 @@ SELECT @hadEventPriv :=1 FROM user WHERE Event_priv LIKE '%';
ALTER TABLE user add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv;
ALTER TABLE db add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL;
ALTER TABLE event DROP PRIMARY KEY;
-ALTER TABLE event ADD PRIMARY KEY(definer, db, name);
+ALTER TABLE event ADD PRIMARY KEY(db, name);
ALTER TABLE event ADD sql_mode
set('REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 83bc8ce8954..744a4791307 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -31,7 +31,6 @@ Usage: $0 [OPTIONS]
--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
@@ -46,6 +45,11 @@ EOF
exit 1
}
+shell_quote_string() {
+ # This sed command makes sure that any special chars are quoted,
+ # so the arg gets passed exactly to the server.
+ echo "$1" | sed -e 's,\([^a-zA-Z0-9/_.=-]\),\\\1,g'
+}
parse_arguments() {
# We only need to pass arguments through to the server if we don't
@@ -69,14 +73,14 @@ parse_arguments() {
--pid-file=*) pid_file=`echo "$arg" | sed -e "s;--pid-file=;;"` ;;
--user=*) user=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; SET_USER=1 ;;
- # these two might have been set in a [mysqld_safe] section of my.cnf
+ # these might have been set in a [mysqld_safe] section of my.cnf
# they are added to mysqld command line to override settings from my.cnf
+ --log-error=*) err_log=`echo "$arg" | sed -e "s;--log-error=;;"` ;;
--socket=*) mysql_unix_port=`echo "$arg" | sed -e "s;--socket=;;"` ;;
--port=*) mysql_tcp_port=`echo "$arg" | sed -e "s;--port=;;"` ;;
# mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
--ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
- --log-error=*) err_log=`echo "$arg" | sed -e "s;--log-error=;;"` ;;
--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; ;;
@@ -97,9 +101,7 @@ parse_arguments() {
*)
if test -n "$pick_args"
then
- # This sed command makes sure that any special chars are quoted,
- # so the arg gets passed exactly to the server.
- args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'`
+ append_arg_to_args "$arg"
fi
;;
esac
@@ -194,6 +196,10 @@ else
print_defaults="my_print_defaults"
fi
+append_arg_to_args () {
+ args="$args "`shell_quote_string "$1"`
+}
+
args=
SET_USER=2
parse_arguments `$print_defaults $defaults --loose-verbose mysqld server`
@@ -239,15 +245,39 @@ else
* ) pid_file="$DATADIR/$pid_file" ;;
esac
fi
-test -z "$err_log" && err_log=$DATADIR/`@HOSTNAME@`.err
+append_arg_to_args "--pid-file=$pid_file"
+
+if [ -n "$err_log" ]
+then
+ # mysqld adds ".err" if there is no extension on the --log-err
+ # argument; must match that here, or mysqld_safe will write to a
+ # different log file than mysqld
+
+ # mysqld does not add ".err" to "--log-error=foo."; it considers a
+ # trailing "." as an extension
+ if expr "$err_log" : '.*\.[^/]*$' > /dev/null
+ then
+ :
+ else
+ err_log="$err_log".err
+ fi
+
+ case "$err_log" in
+ /* ) ;;
+ * ) err_log="$DATADIR/$err_log" ;;
+ esac
+else
+ err_log=$DATADIR/`@HOSTNAME@`.err
+fi
+append_arg_to_args "--log-error=$err_log"
if test -n "$mysql_unix_port"
then
- args="--socket=$mysql_unix_port $args"
+ append_arg_to_args "--socket=$mysql_unix_port"
fi
if test -n "$mysql_tcp_port"
then
- args="--port=$mysql_tcp_port $args"
+ append_arg_to_args "--port=$mysql_tcp_port"
fi
if test $niceness -eq 0
@@ -314,7 +344,7 @@ then
if test -n "$open_files"
then
ulimit -n $open_files
- args="--open-files-limit=$open_files $args"
+ append_arg_to_args "--open-files-limit=$open_files"
fi
if test -n "$core_file_size"
then
@@ -372,12 +402,18 @@ echo "`date +'%y%m%d %H:%M:%S mysqld started'`" >> $err_log
while true
do
rm -f $safe_mysql_unix_port $pid_file # Some extra safety
- if test -z "$args"
- then
- $NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ >> $err_log 2>&1
- else
- eval "$NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ $args >> $err_log 2>&1"
- fi
+
+ cmd="$NOHUP_NICENESS"
+
+ for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \
+ "--datadir=$DATADIR" "$USER_OPTION"
+ do
+ cmd="$cmd "`shell_quote_string "$i"`
+ done
+ cmd="$cmd $args >> "`shell_quote_string "$err_log"`" 2>&1"
+ #echo "Running mysqld: [$cmd]"
+ eval "$cmd"
+
if test ! -f $pid_file # This is removed if normal shutdown
then
echo "STOPPING server from pid file $pid_file"
diff --git a/server-tools/instance-manager/cmakelists.txt b/server-tools/instance-manager/CMakeLists.txt
index c20b9c7f9df..1983d459ce2 100644
--- a/server-tools/instance-manager/cmakelists.txt
+++ b/server-tools/instance-manager/CMakeLists.txt
@@ -9,6 +9,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instanc
instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc
mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc
thread_registry.cc user_map.cc imservice.cpp windowsservice.cpp
+ user_management_commands.cc
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
../../libmysql/errmsg.c)
diff --git a/server-tools/instance-manager/IMService.cpp b/server-tools/instance-manager/IMService.cpp
index b7ea8e7eb81..f9ea7ee471d 100644
--- a/server-tools/instance-manager/IMService.cpp
+++ b/server-tools/instance-manager/IMService.cpp
@@ -20,7 +20,7 @@ IMService::~IMService(void)
void IMService::Stop()
{
ReportStatus(SERVICE_STOP_PENDING);
-
+
// stop the IM work
raise(SIGTERM);
}
@@ -30,15 +30,14 @@ 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);
-
+ Options::load(argc, argv);
+
// init goes here
ReportStatus((DWORD)SERVICE_RUNNING);
// wait for main loop to terminate
- manager(o);
- o.cleanup();
+ manager();
+ Options::cleanup();
}
void IMService::Log(const char *msg)
@@ -46,13 +45,13 @@ void IMService::Log(const char *msg)
log_info(msg);
}
-int HandleServiceOptions(Options options)
+int HandleServiceOptions()
{
int ret_val= 0;
IMService winService;
- if (options.install_as_service)
+ if (Options::Service::install_as_service)
{
if (winService.IsInstalled())
log_info("Service is already installed");
@@ -64,7 +63,7 @@ int HandleServiceOptions(Options options)
ret_val= 1;
}
}
- else if (options.remove_service)
+ else if (Options::Service::remove_service)
{
if (! winService.IsInstalled())
log_info("Service is not installed");
@@ -77,6 +76,19 @@ int HandleServiceOptions(Options options)
}
}
else
- ret_val= !winService.Init();
+ {
+ log_info("Initializing Instance Manager service...");
+
+ if (!winService.Init())
+ {
+ log_info("Service failed to initialize.");
+ fprintf(stderr,
+ "The service should be started by Windows Service Manager.\n"
+ "The MySQL Manager should be started with '--standalone'\n"
+ "to run from command line.");
+ ret_val= 1;
+ }
+ }
+
return ret_val;
}
diff --git a/server-tools/instance-manager/IMService.h b/server-tools/instance-manager/IMService.h
index cad38bebdaf..94d59c2af31 100644
--- a/server-tools/instance-manager/IMService.h
+++ b/server-tools/instance-manager/IMService.h
@@ -1,3 +1,21 @@
+/*
+ Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
#pragma once
#include "windowsservice.h"
@@ -12,3 +30,5 @@ protected:
void Stop();
void Run(DWORD argc, LPTSTR *argv);
};
+
+extern int HandleServiceOptions();
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am
index 462d7984aa4..4139bf2eb10 100644
--- a/server-tools/instance-manager/Makefile.am
+++ b/server-tools/instance-manager/Makefile.am
@@ -76,7 +76,10 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
guardian.cc guardian.h \
parse_output.cc parse_output.h \
mysql_manager_error.h \
- portability.h
+ portability.h \
+ exit_codes.h \
+ user_management_commands.h \
+ user_management_commands.cc
mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
liboptions.la \
@@ -88,7 +91,7 @@ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
@openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
EXTRA_DIST = WindowsService.cpp WindowsService.h IMService.cpp \
- IMService.h cmakelists.txt
+ IMService.h CMakeLists.txt
tags:
ctags -R *.h *.cc
diff --git a/server-tools/instance-manager/WindowsService.cpp b/server-tools/instance-manager/WindowsService.cpp
index 192045b7a4c..8a36a2f2fdd 100644
--- a/server-tools/instance-manager/WindowsService.cpp
+++ b/server-tools/instance-manager/WindowsService.cpp
@@ -7,9 +7,9 @@ static WindowsService *gService;
WindowsService::WindowsService(void) :
statusCheckpoint(0),
serviceName(NULL),
- inited(false),
+ inited(FALSE),
dwAcceptedControls(SERVICE_ACCEPT_STOP),
- debugging(false)
+ debugging(FALSE)
{
gService= this;
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
@@ -22,11 +22,12 @@ WindowsService::~WindowsService(void)
BOOL WindowsService::Install()
{
- bool ret_val= false;
+ bool ret_val= FALSE;
SC_HANDLE newService;
SC_HANDLE scm;
- if (IsInstalled()) return true;
+ if (IsInstalled())
+ return TRUE;
// determine the name of the currently executing file
char szFilePath[_MAX_PATH];
@@ -34,7 +35,7 @@ BOOL WindowsService::Install()
// open a connection to the SCM
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
- return false;
+ return FALSE;
newService= CreateService(scm, serviceName, displayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
@@ -45,7 +46,7 @@ BOOL WindowsService::Install()
if (newService)
{
CloseServiceHandle(newService);
- ret_val= true;
+ ret_val= TRUE;
}
CloseServiceHandle(scm);
@@ -56,34 +57,35 @@ BOOL WindowsService::Init()
{
assert(serviceName != NULL);
- if (inited) return true;
+ if (inited)
+ return TRUE;
SERVICE_TABLE_ENTRY stb[] =
{
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{ NULL, NULL }
};
- inited= true;
+ inited= TRUE;
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
}
BOOL WindowsService::Remove()
{
- bool ret_val= false;
+ bool ret_val= FALSE;
- if (! IsInstalled())
- return true;
+ if (!IsInstalled())
+ return TRUE;
// open a connection to the SCM
SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
- if (! scm)
- return false;
+ if (!scm)
+ return FALSE;
SC_HANDLE service= OpenService(scm, serviceName, DELETE);
if (service)
{
if (DeleteService(service))
- ret_val= true;
+ ret_val= TRUE;
DWORD dw= ::GetLastError();
CloseServiceHandle(service);
}
@@ -116,7 +118,8 @@ void WindowsService::SetAcceptedControls(DWORD acceptedControls)
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
DWORD dwError)
{
- if(debugging) return TRUE;
+ if (debugging)
+ return TRUE;
if(currentState == SERVICE_START_PENDING)
status.dwControlsAccepted= 0;
diff --git a/server-tools/instance-manager/WindowsService.h b/server-tools/instance-manager/WindowsService.h
index 1a034ce1351..3af7cdf39a7 100644
--- a/server-tools/instance-manager/WindowsService.h
+++ b/server-tools/instance-manager/WindowsService.h
@@ -1,3 +1,21 @@
+/*
+ Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
#pragma once
class WindowsService
diff --git a/server-tools/instance-manager/command.h b/server-tools/instance-manager/command.h
index b84cc6a8e9e..f31ea404867 100644
--- a/server-tools/instance-manager/command.h
+++ b/server-tools/instance-manager/command.h
@@ -22,10 +22,12 @@
#pragma interface
#endif
-/* Class responsible for allocation of im commands. */
+/* Class responsible for allocation of IM commands. */
class Instance_map;
+struct st_net;
+
/*
Command - entry point for any command.
GangOf4: 'Command' design pattern
@@ -37,8 +39,18 @@ public:
Command(Instance_map *instance_map_arg= 0);
virtual ~Command();
- /* method of executing: */
- virtual int execute(struct st_net *net, ulong connection_id) = 0;
+ /*
+ This operation incapsulates behaviour of the command.
+
+ SYNOPSYS
+ net The network connection to the client.
+ connection_id Client connection ID
+
+ RETURN
+ 0 On success
+ non 0 On error. Client error code is returned.
+ */
+ virtual int execute(st_net *net, ulong connection_id) = 0;
protected:
Instance_map *instance_map;
diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc
index 7b999f61503..07e1e9a18f3 100644
--- a/server-tools/instance-manager/commands.cc
+++ b/server-tools/instance-manager/commands.cc
@@ -14,36 +14,53 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
+#pragma implementation
+#endif
+
#include "commands.h"
+#include <my_global.h>
+#include <m_ctype.h>
+#include <mysql.h>
+#include <my_dir.h>
+
+#include "buffer.h"
+#include "guardian.h"
#include "instance_map.h"
+#include "log.h"
+#include "manager.h"
#include "messages.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
-#include "protocol.h"
-#include "buffer.h"
#include "options.h"
+#include "priv.h"
+#include "protocol.h"
-#include <m_string.h>
-#include <m_ctype.h>
-#include <mysql.h>
-#include <my_dir.h>
+
+/*
+ modify_defaults_to_im_error -- a map of error codes of
+ mysys::modify_defaults_file() into Instance Manager error codes.
+*/
+
+static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
+ ER_ACCESS_OPTION_FILE };
/*
- Add a string to a buffer
+ 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
+ position 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.
+ 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
@@ -51,7 +68,6 @@
1 - error occured
*/
-
static inline int put_to_buff(Buffer *buff, const char *str, uint *position)
{
uint len= strlen(str);
@@ -88,749 +104,1615 @@ static int parse_version_number(const char *version_str, char *version,
}
-/* implementation for Show_instances: */
+/**************************************************************************
+ Implementation of Instance_name.
+**************************************************************************/
+Instance_name::Instance_name(const LEX_STRING *name)
+{
+ str.str= str_buffer;
+ str.length= name->length;
-/*
- The method sends a list of instances in the instance map to the client.
+ if (str.length > MAX_INSTANCE_NAME_SIZE - 1)
+ str.length= MAX_INSTANCE_NAME_SIZE - 1;
- SYNOPSYS
- Show_instances::execute()
- net The network connection to the client.
- connection_id Client connection ID
+ strmake(str.str, name->str, str.length);
+}
- RETURN
- 0 - ok
- 1 - error occured
+/**************************************************************************
+ Implementation of Show_instances.
+**************************************************************************/
+
+/*
+ Implementation of SHOW INSTANCES statement.
+
+ Possible error codes:
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
*/
-int Show_instances::execute(struct st_net *net, ulong connection_id)
+int Show_instances::execute(st_net *net, ulong connection_id)
{
- Buffer send_buff; /* buffer for packets */
- LIST name, status;
- NAME_WITH_LENGTH name_field, status_field;
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net)))
+ return err_code;
+
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instances::write_header(st_net *net)
+{
+ LIST name, state;
+ LEX_STRING name_field, state_field;
LIST *field_list;
- uint position=0;
- name_field.name= (char*) "instance_name";
+ name_field.str= (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);
+
+ state_field.str= (char *) "state";
+ state_field.length= DEFAULT_FIELD_LENGTH;
+ state.data= &state_field;
+
+ field_list= list_add(NULL, &state);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
+
+int Show_instances::write_data(st_net *net)
+{
+ my_bool err_status= FALSE;
+
+ Instance *instance;
+ Instance_map::Iterator iterator(instance_map);
+
+ instance_map->guardian->lock();
+ instance_map->lock();
+
+ while ((instance= iterator.next()))
{
- Instance *instance;
- Instance_map::Iterator iterator(instance_map);
+ Buffer send_buf; /* buffer for packets */
+ uint pos= 0;
+
+ const char *instance_name= instance->options.instance_name.str;
+ const char *state_name= instance_map->get_instance_state_name(instance);
- instance_map->lock();
- while ((instance= iterator.next()))
+ if (store_to_protocol_packet(&send_buf, instance_name, &pos) ||
+ store_to_protocol_packet(&send_buf, state_name, &pos) ||
+ my_net_write(net, send_buf.buffer, pos))
{
- 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;
+ err_status= TRUE;
+ break;
}
- instance_map->unlock();
}
- if (send_eof(net))
- goto err;
- if (net_flush(net))
- goto err;
- return 0;
-err:
- return ER_OUT_OF_RESOURCES;
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+
+ return err_status ? ER_OUT_OF_RESOURCES : 0;
}
-/* implementation for Flush_instances: */
+/**************************************************************************
+ Implementation of Flush_instances.
+**************************************************************************/
-int Flush_instances::execute(struct st_net *net, ulong connection_id)
+/*
+ Implementation of FLUSH INSTANCES statement.
+
+ Possible error codes:
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+ ER_THERE_IS_ACTIVE_INSTACE If there is an active instance
+*/
+
+int Flush_instances::execute(st_net *net, ulong connection_id)
{
- if (instance_map->flush_instances() ||
- net_send_ok(net, connection_id, NULL))
+ instance_map->guardian->lock();
+ instance_map->lock();
+
+ if (instance_map->is_there_active_instance())
+ {
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+ return ER_THERE_IS_ACTIVE_INSTACE;
+ }
+
+ if (instance_map->flush_instances())
+ {
+ instance_map->unlock();
+ instance_map->guardian->unlock();
return ER_OUT_OF_RESOURCES;
+ }
- return 0;
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+
+ return net_send_ok(net, connection_id, NULL) ? ER_OUT_OF_RESOURCES : 0;
}
-/* implementation for Show_instance_status: */
+/**************************************************************************
+ Implementation of Abstract_instance_cmd.
+**************************************************************************/
-Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
- const char *name, uint len)
- :Command(instance_map_arg)
+Abstract_instance_cmd::Abstract_instance_cmd(
+ Instance_map *instance_map_arg, const LEX_STRING *instance_name_arg)
+ :Command(instance_map_arg),
+ instance_name(instance_name_arg)
{
- Instance *instance;
+ /*
+ MT-NOTE: we can not make a search for Instance object here,
+ because it can dissappear after releasing the lock.
+ */
+}
+
+
+int Abstract_instance_cmd::execute(st_net *net, ulong connection_id)
+{
+ int err_code;
+
+ instance_map->lock();
+
+ {
+ Instance *instance= instance_map->find(get_instance_name());
+
+ if (!instance)
+ {
+ instance_map->unlock();
+ return ER_BAD_INSTANCE_NAME;
+ }
+
+ err_code= execute_impl(net, instance);
+ }
+
+ instance_map->unlock();
+
+ if (!err_code)
+ err_code= send_ok_response(net, connection_id);
- /* 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;
+ return err_code;
}
-/*
- The method sends a table with a status of requested instance to the client.
+/**************************************************************************
+ Implementation of Show_instance_status.
+**************************************************************************/
- SYNOPSYS
- Show_instance_status::do_command()
- net The network connection to the client.
- instance_name The name of the instance.
+Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_arg)
+{
+}
- RETURN
- 0 - ok
- 1 - error occured
+
+/*
+ Implementation of SHOW INSTANCE STATUS statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
*/
+int Show_instance_status::execute_impl(st_net *net, Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
-int Show_instance_status::execute(struct st_net *net,
- ulong connection_id)
+ return 0;
+}
+
+
+int Show_instance_status::send_ok_response(st_net *net, ulong connection_id)
{
- enum { MAX_VERSION_LENGTH= 40 };
- Buffer send_buff; /* buffer for packets */
- LIST name, status, version, version_number;
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instance_status::write_header(st_net *net)
+{
+ LIST name, state, version, version_number, mysqld_compatible;
LIST *field_list;
- NAME_WITH_LENGTH name_field, status_field, version_field,
- version_number_field;
- uint position=0;
+ LEX_STRING name_field, state_field, version_field,
+ version_number_field, mysqld_compatible_field;
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
+ /* Create list of the fileds to be passed to send_fields(). */
- /* create list of the fileds to be passed to send_fields */
- name_field.name= (char*) "instance_name";
+ name_field.str= (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";
+
+ state_field.str= (char *) "state";
+ state_field.length= DEFAULT_FIELD_LENGTH;
+ state.data= &state_field;
+
+ version_field.str= (char *) "version";
version_field.length= MAX_VERSION_LENGTH;
version.data= &version_field;
- version_number_field.name= (char*) "version_number";
+
+ version_number_field.str= (char *) "version_number";
version_number_field.length= MAX_VERSION_LENGTH;
version_number.data= &version_number_field;
- field_list= list_add(NULL, &version);
+
+ mysqld_compatible_field.str= (char *) "mysqld_compatible";
+ mysqld_compatible_field.length= DEFAULT_FIELD_LENGTH;
+ mysqld_compatible.data= &mysqld_compatible_field;
+
+ field_list= list_add(NULL, &mysqld_compatible);
+ field_list= list_add(field_list, &version);
field_list= list_add(field_list, &version_number);
- field_list= list_add(field_list, &status);
+ field_list= list_add(field_list, &state);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- {
- 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);
+int Show_instance_status::write_data(st_net *net, Instance *instance)
+{
+ Buffer send_buf; /* buffer for packets */
+ char version_num_buf[MAX_VERSION_LENGTH];
+ uint pos= 0;
- if (instance->options.mysqld_version)
- {
- char parsed_version[MAX_VERSION_LENGTH];
+ const char *state_name;
+ const char *version_tag= "unknown";
+ const char *version_num= "unknown";
+ const char *mysqld_compatible_status;
- parse_version_number(instance->options.mysqld_version, parsed_version,
- sizeof(parsed_version));
- store_to_protocol_packet(&send_buff, parsed_version, &position);
+ instance_map->guardian->lock();
+ state_name= instance_map->get_instance_state_name(instance);
+ mysqld_compatible_status= instance->is_mysqld_compatible() ? "yes" : "no";
+ instance_map->guardian->unlock();
- store_to_protocol_packet(&send_buff, instance->options.mysqld_version,
- &position);
- }
- else
- {
- store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
- store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
- }
+ if (instance->options.mysqld_version)
+ {
+ if (parse_version_number(instance->options.mysqld_version, version_num_buf,
+ sizeof(version_num_buf)))
+ return ER_OUT_OF_RESOURCES;
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ version_num= version_num_buf;
+ version_tag= instance->options.mysqld_version;
}
- if (send_eof(net) || net_flush(net))
- goto err;
+ if (store_to_protocol_packet(&send_buf, get_instance_name()->str, &pos) ||
+ store_to_protocol_packet(&send_buf, state_name, &pos) ||
+ store_to_protocol_packet(&send_buf, version_num, &pos) ||
+ store_to_protocol_packet(&send_buf, version_tag, &pos) ||
+ store_to_protocol_packet(&send_buf, mysqld_compatible_status, &pos) ||
+ my_net_write(net, send_buf.buffer, (uint) pos))
+ {
+ return ER_OUT_OF_RESOURCES;
+ }
return 0;
+}
-err:
- return ER_OUT_OF_RESOURCES;
+
+/**************************************************************************
+ Implementation of Show_instance_options.
+**************************************************************************/
+
+Show_instance_options::Show_instance_options(
+ Instance_map *instance_map_arg, const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_arg)
+{
}
-/* Implementation for Show_instance_options */
+/*
+ Implementation of SHOW INSTANCE OPTIONS statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
-Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
- const char *name, uint len):
- Command(instance_map_arg)
+int Show_instance_options::execute_impl(st_net *net, Instance *instance)
{
- Instance *instance;
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
- /* 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;
+ return 0;
}
-int Show_instance_options::execute(struct st_net *net, ulong connection_id)
+int Show_instance_options::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instance_options::write_header(st_net *net)
{
- Buffer send_buff; /* buffer for packets */
LIST name, option;
LIST *field_list;
- NAME_WITH_LENGTH name_field, option_field;
- uint position=0;
+ LEX_STRING name_field, option_field;
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
+ /* Create list of the fileds to be passed to send_fields(). */
- /* create list of the fileds to be passed to send_fields */
- name_field.name= (char*) "option_name";
+ name_field.str= (char *) "option_name";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
- option_field.name= (char*) "value";
+
+ option_field.str= (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);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
+
+int Show_instance_options::write_data(st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+ uint pos= 0;
+
+ if (store_to_protocol_packet(&send_buff, "instance_name", &pos) ||
+ store_to_protocol_packet(&send_buff, get_instance_name()->str, &pos) ||
+ my_net_write(net, send_buff.buffer, pos))
{
- 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;
- }
+ return ER_OUT_OF_RESOURCES;
+ }
- if ((instance->options.nonguarded))
+ /* Loop through the options. */
+
+ for (int i= 0; i < instance->options.get_num_options(); i++)
+ {
+ Named_value option= instance->options.get_option(i);
+ const char *option_value= option.get_value()[0] ? option.get_value() : "";
+
+ pos= 0;
+
+ if (store_to_protocol_packet(&send_buff, option.get_name(), &pos) ||
+ store_to_protocol_packet(&send_buff, option_value, &pos) ||
+ my_net_write(net, send_buff.buffer, pos))
{
- 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;
+ return ER_OUT_OF_RESOURCES;
}
+ }
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation of Start_instance.
+**************************************************************************/
- /* loop through the options stored in DYNAMIC_ARRAY */
- for (uint i= 0; i < instance->options.options_array.elements; i++)
+Start_instance::Start_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_arg)
+{
+}
+
+
+/*
+ Implementation of START INSTANCE statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
+
+int Start_instance::execute_impl(st_net *net, Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= instance->start()))
+ return err_code;
+
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->guard(instance);
+
+ return 0;
+}
+
+
+int Start_instance::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (net_send_ok(net, connection_id, "Instance started"))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation of Stop_instance.
+**************************************************************************/
+
+Stop_instance::Stop_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_arg)
+{
+}
+
+
+/*
+ Implementation of STOP INSTANCE statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
+
+int Stop_instance::execute_impl(st_net *net, Instance *instance)
+{
+ int err_code;
+
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->stop_guard(instance);
+
+ if ((err_code= instance->stop()))
+ return err_code;
+
+ return 0;
+}
+
+
+int Stop_instance::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (net_send_ok(net, connection_id, NULL))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Create_instance.
+**************************************************************************/
+
+Create_instance::Create_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Command(instance_map_arg),
+ instance_name(instance_name_arg)
+{
+}
+
+
+/*
+ This operation initializes Create_instance object.
+
+ SYNOPSYS
+ text [IN/OUT] a pointer to the text containing instance options.
+
+ RETURN
+ FALSE On success.
+ TRUE On error.
+*/
+
+bool Create_instance::init(const char **text)
+{
+ return options.init() || parse_args(text);
+}
+
+
+/*
+ This operation parses CREATE INSTANCE options.
+
+ SYNOPSYS
+ text [IN/OUT] a pointer to the text containing instance options.
+
+ RETURN
+ FALSE On success.
+ TRUE On syntax error.
+*/
+
+bool Create_instance::parse_args(const char **text)
+{
+ uint len;
+
+ /* Check if we have something (and trim leading spaces). */
+
+ get_word(text, &len, NONSPACE);
+
+ if (len == 0)
+ return FALSE; /* OK: no option. */
+
+ /* Main parsing loop. */
+
+ while (TRUE)
+ {
+ LEX_STRING option_name;
+ char *option_name_str;
+ char *option_value_str= NULL;
+
+ /* Looking for option name. */
+
+ get_word(text, &option_name.length, OPTION_NAME);
+
+ if (option_name.length == 0)
+ return TRUE; /* Syntax error: option name expected. */
+
+ option_name.str= (char *) *text;
+ *text+= option_name.length;
+
+ /* Looking for equal sign. */
+
+ skip_spaces(text);
+
+ if (**text == '=')
{
- 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 */
+ ++(*text); /* Skip an equal sign. */
+
+ /* Looking for option value. */
- position= 0;
- if (option_value != NULL)
+ skip_spaces(text);
+
+ if (!**text)
+ return TRUE; /* Syntax error: EOS when option value expected. */
+
+ if (**text != '\'' && **text != '"')
{
- *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= '=';
+ /* Option value is a simple token. */
+
+ LEX_STRING option_value;
+
+ get_word(text, &option_value.length, ALPHANUM);
+
+ if (option_value.length == 0)
+ return TRUE; /* internal parser error. */
+
+ option_value.str= (char *) *text;
+ *text+= option_value.length;
+
+ if (!(option_value_str= Named_value::alloc_str(&option_value)))
+ return TRUE; /* out of memory during parsing. */
}
else
{
- store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
- store_to_protocol_packet(&send_buff, "", &position);
+ /* Option value is a string. */
+
+ if (parse_option_value(*text, &len, &option_value_str))
+ return TRUE; /* Syntax error: invalid string specification. */
+
+ *text+= len;
}
+ }
+
+ if (!option_value_str)
+ {
+ LEX_STRING empty_str= { C_STRING_WITH_SIZE("") };
+
+ if (!(option_value_str= Named_value::alloc_str(&empty_str)))
+ return TRUE; /* out of memory during parsing. */
+ }
+
+ if (!(option_name_str= Named_value::alloc_str(&option_name)))
+ {
+ Named_value::free_str(&option_value_str);
+ return TRUE; /* out of memory during parsing. */
+ }
+
+ {
+ Named_value option(option_name_str, option_value_str);
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ if (options.add_element(&option))
+ {
+ option.free();
+ return TRUE; /* out of memory during parsing. */
+ }
}
+
+ skip_spaces(text);
+
+ if (!**text)
+ return FALSE; /* OK: end of options. */
+
+ if (**text != ',')
+ return TRUE; /* Syntax error: comma expected. */
+
+ ++(*text);
}
+}
- if (send_eof(net) || net_flush(net))
- goto err;
- return 0;
+/*
+ Implementation of CREATE INSTANCE statement.
+
+ Possible error codes:
+ ER_MALFORMED_INSTANCE_NAME Instance name is malformed
+ ER_CREATE_EXISTING_INSTANCE There is an instance with the given name
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
+
+int Create_instance::execute(st_net *net, ulong connection_id)
+{
+ int err_code;
+
+ /* Check that the name is valid and there is no instance with such name. */
+
+ if (!Instance::is_name_valid(get_instance_name()))
+ return ER_MALFORMED_INSTANCE_NAME;
+
+ /*
+ NOTE: In order to prevent race condition, we should perform all operations
+ on under acquired lock.
+ */
+
+ instance_map->lock();
-err:
- return ER_OUT_OF_RESOURCES;
+ if (instance_map->find(get_instance_name()))
+ {
+ instance_map->unlock();
+ return ER_CREATE_EXISTING_INSTANCE;
+ }
+
+ if ((err_code= instance_map->create_instance(get_instance_name(), &options)))
+ {
+ instance_map->unlock();
+ return err_code;
+ }
+
+ if ((err_code= create_instance_in_file(get_instance_name(), &options)))
+ {
+ Instance *instance= instance_map->find(get_instance_name());
+
+ if (instance)
+ instance_map->remove_instance(instance); /* instance is deleted here. */
+
+ instance_map->unlock();
+ return err_code;
+ }
+
+ /* That's all. */
+
+ instance_map->unlock();
+
+ /* Send the result. */
+
+ if (net_send_ok(net, connection_id, NULL))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
}
-/* Implementation for Start_instance */
+/**************************************************************************
+ Implementation for Drop_instance.
+**************************************************************************/
-Start_instance::Start_instance(Instance_map *instance_map_arg,
- const char *name, uint len)
- :Command(instance_map_arg)
+Drop_instance::Drop_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_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)
+/*
+ Implementation of DROP INSTANCE statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_DROP_ACTIVE_INSTANCE The specified instance is active
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
+
+int Drop_instance::execute_impl(st_net *net, Instance *instance)
{
- 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;
+ int err_code;
+
+ /* Check that the instance is offline. */
+
+ if (instance_map->guardian->is_active(instance))
+ return ER_DROP_ACTIVE_INSTANCE;
- if (!(instance->options.nonguarded))
- instance_map->guardian->guard(instance);
+ err_code= modify_defaults_file(Options::Main::config_file, NULL, NULL,
+ get_instance_name()->str, MY_REMOVE_SECTION);
+ DBUG_ASSERT(err_code >= 0 && err_code <= 2);
- net_send_ok(net, connection_id, "Instance started");
- return 0;
+ if (err_code)
+ {
+ log_error("Can not remove instance '%s' from defaults file (%s). "
+ "Original error code: %d.",
+ (const char *) get_instance_name()->str,
+ (const char *) Options::Main::config_file,
+ (int) err_code);
}
+
+ if (err_code)
+ return modify_defaults_to_im_error[err_code];
+
+ /* Remove instance from the instance map hash and Guardian's list. */
+
+ if (!instance->options.nonguarded)
+ instance_map->guardian->stop_guard(instance);
+
+ if ((err_code= instance->stop()))
+ return err_code;
+
+ instance_map->remove_instance(instance);
+
+ return 0;
}
-/* implementation for Show_instance_log: */
+int Drop_instance::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (net_send_ok(net, connection_id, "Instance dropped"))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Show_instance_log.
+**************************************************************************/
Show_instance_log::Show_instance_log(Instance_map *instance_map_arg,
- const char *name, uint len,
+ const LEX_STRING *instance_name_arg,
Log_type log_type_arg,
- const char *size_arg,
- const char *offset_arg)
- :Command(instance_map_arg)
+ uint size_arg, uint offset_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_arg),
+ log_type(log_type_arg),
+ size(size_arg),
+ offset(offset_arg)
{
- Instance *instance;
+}
+
+
+/*
+ Implementation of SHOW INSTANCE LOG statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OFFSET_ERROR We were requested to read negative number of
+ bytes from the log
+ ER_NO_SUCH_LOG The specified type of log is not available for
+ the given 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 Not enough resources to complete the operation
+*/
+
+int Show_instance_log::execute_impl(st_net *net, Instance *instance)
+{
+ int err_code;
- if (offset_arg != NULL)
- offset= atoi(offset_arg);
- else
- offset= 0;
- size= atoi(size_arg);
- log_type= log_type_arg;
+ if ((err_code= check_params(instance)))
+ return err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
- /* 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;
+ return 0;
}
+int Show_instance_log::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
-/*
- Open the logfile, read requested part of the log and send the info
- to the client.
+ return 0;
+}
- SYNOPSYS
- Show_instance_log::execute()
- net The network connection to the client.
- connection_id Client connection ID
- DESCRIPTION
+int Show_instance_log::check_params(Instance *instance)
+{
+ const char *logpath= instance->options.logs[log_type];
- Send a table with the content of the log requested. The function also
- deals with errro handling, to be verbose.
+ /* Cannot read negative number of bytes. */
- 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
-*/
+ if (offset > size)
+ return ER_OFFSET_ERROR;
+
+ /* Instance has no such log. */
+
+ if (logpath == NULL)
+ return ER_NO_SUCH_LOG;
-int Show_instance_log::execute(struct st_net *net, ulong connection_id)
+ if (*logpath == '\0')
+ return ER_GUESS_LOGFILE;
+
+ return 0;
+}
+
+
+int Show_instance_log::write_header(st_net *net)
{
- Buffer send_buff; /* buffer for packets */
LIST name;
LIST *field_list;
- NAME_WITH_LENGTH name_field;
- uint position= 0;
+ LEX_STRING name_field;
- /* create list of the fileds to be passed to send_fields */
- name_field.name= (char*) "Log";
+ /* Create list of the fields to be passed to send_fields(). */
+
+ name_field.str= (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;
+ name.data= &name_field;
- /* cannot read negative number of bytes */
- if (offset > size)
- return ER_OFFSET_ERROR;
+ field_list= list_add(NULL, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- {
- Instance *instance;
- const char *logpath;
- File fd;
- if ((instance= instance_map->find(instance_name,
- strlen(instance_name))) == NULL)
- goto err;
+int Show_instance_log::write_data(st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+ uint pos= 0;
- logpath= instance->options.logs[log_type];
+ const char *logpath= instance->options.logs[log_type];
+ File fd;
- /* Instance has no such log */
- if (logpath == NULL)
- return ER_NO_SUCH_LOG;
+ size_t buff_size;
+ int read_len;
- if (*logpath == '\0')
- return ER_GUESS_LOGFILE;
+ MY_STAT file_stat;
+ Buffer read_buff;
+ if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) <= 0)
+ return ER_OPEN_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)))
+ {
+ close(fd);
+ return ER_OUT_OF_RESOURCES;
+ }
- /* my_fstat doesn't use the flag parameter */
- if (my_fstat(fd, &file_stat, MYF(0)))
- goto err;
+ /* calculate buffer size */
+ buff_size= (size - offset);
- buff_size= (size - offset);
+ read_buff.reserve(0, buff_size);
- read_buff.reserve(0, buff_size);
+ /* read in one chunk */
+ read_len= (int)my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
- /* read in one chunk */
- read_len= (int)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)
+ {
+ close(fd);
+ return ER_READ_FILE;
+ }
- 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;
+ close(fd);
- if (my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ if (store_to_protocol_packet(&send_buff, read_buff.buffer, &pos, read_len) ||
+ my_net_write(net, send_buff.buffer, pos))
+ {
+ return ER_OUT_OF_RESOURCES;
}
- if (send_eof(net) || net_flush(net))
- goto err;
-
return 0;
-
-err:
- return ER_OUT_OF_RESOURCES;
}
-/* implementation for Show_instance_log_files: */
+/**************************************************************************
+ Implementation of 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_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg)
+ :Abstract_instance_cmd(instance_map_arg, instance_name_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.
+ Implementation of SHOW INSTANCE LOG FILES statement.
- 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
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
*/
-int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
+int Show_instance_log_files::execute_impl(st_net *net, Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
+
+ return 0;
+}
+
+
+int Show_instance_log_files::send_ok_response(st_net *net, ulong connection_id)
+{
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instance_log_files::write_header(st_net *net)
{
- 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;
+ LEX_STRING name_field, path_field, size_field;
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
+ /* Create list of the fileds to be passed to send_fields(). */
- /* create list of the fileds to be passed to send_fields */
- name_field.name= (char*) "Logfile";
+ name_field.str= (char *) "Logfile";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
- path_field.name= (char*) "Path";
+
+ path_field.str= (char *) "Path";
path_field.length= DEFAULT_FIELD_LENGTH;
path.data= &path_field;
- size_field.name= (char*) "File size";
+
+ size_field.str= (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);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- Instance *instance;
- if ((instance= instance_map->
- find(instance_name, strlen(instance_name))) == NULL)
- goto err;
+int Show_instance_log_files::write_data(st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+ /*
+ 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)
+ continue;
+
+ struct stat file_stat;
/*
- 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.
+ Save some more space for the log file names. In fact all
+ we need is strlen("GENERAL_LOG") + 1
*/
- 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++)
+ enum { LOG_NAME_BUFFER_SIZE= 20 };
+ char buff[LOG_NAME_BUFFER_SIZE];
+
+ uint pos= 0;
+
+ const char *log_path= "";
+ const char *log_size= "0";
+
+ if (!stat(log_files->value, &file_stat) &&
+ MY_S_ISREG(file_stat.st_mode))
{
- 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;
- }
+ int10_to_str(file_stat.st_size, buff, 10);
+
+ log_path= log_files->value;
+ log_size= buff;
}
- }
- if (send_eof(net) || net_flush(net))
- goto err;
+ if (store_to_protocol_packet(&send_buff, log_files->name, &pos) ||
+ store_to_protocol_packet(&send_buff, log_path, &pos) ||
+ store_to_protocol_packet(&send_buff, log_size, &pos) ||
+ my_net_write(net, send_buff.buffer, pos))
+ return ER_OUT_OF_RESOURCES;
+ }
return 0;
-
-err:
- return ER_OUT_OF_RESOURCES;
}
-/* implementation for SET instance_name.option=option_value: */
+/**************************************************************************
+ Implementation of Abstract_option_cmd.
+**************************************************************************/
+
+/*
+ Instance_options_list -- a data class representing a list of options for
+ some instance.
+*/
-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)
+class Instance_options_list
{
- Instance *instance;
+public:
+ Instance_options_list(const LEX_STRING *instance_name_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;
+public:
+ bool init();
- /* 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
+ const LEX_STRING *get_instance_name() const
{
- instance_name= NULL;
- instance_name_len= 0;
+ return instance_name.get_str();
}
+
+public:
+ /*
+ This member is set and used only in Abstract_option_cmd::execute_impl().
+ Normally it is not used (and should not).
+
+ The problem is that construction and execution of commands are made not
+ in one transaction (not under one lock session). So, we can not initialize
+ instance in constructor and use it in execution.
+ */
+ Instance *instance;
+
+ Named_value_arr options;
+
+private:
+ Instance_name instance_name;
+};
+
+
+/**************************************************************************/
+
+Instance_options_list::Instance_options_list(
+ const LEX_STRING *instance_name_arg)
+ :instance(NULL),
+ instance_name(instance_name_arg)
+{
}
-/*
- The method sends a table with a list of log files
- used by the instance.
+bool Instance_options_list::init()
+{
+ return options.init();
+}
- SYNOPSYS
- Set_option::correct_file()
- skip Skip the option, being searched while writing the result file.
- That is, to delete it.
- DESCRIPTION
+/**************************************************************************/
+
+C_MODE_START
+
+static byte* get_item_key(const byte* item, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ const Instance_options_list *lst= (const Instance_options_list *) item;
+ *len= lst->get_instance_name()->length;
+ return (byte *) lst->get_instance_name()->str;
+}
+
+static void delete_item(void *item)
+{
+ delete (Instance_options_list *) item;
+}
+
+C_MODE_END
+
+
+/**************************************************************************/
+
+Abstract_option_cmd::Abstract_option_cmd(Instance_map *instance_map_arg)
+ :Command(instance_map_arg),
+ initialized(FALSE)
+{
+}
+
+
+Abstract_option_cmd::~Abstract_option_cmd()
+{
+ if (initialized)
+ hash_free(&instance_options_map);
+}
+
+
+bool Abstract_option_cmd::add_option(const LEX_STRING *instance_name,
+ Named_value *option)
+{
+ Instance_options_list *lst= get_instance_options_list(instance_name);
+
+ if (!lst)
+ return TRUE;
+ lst->options.add_element(option);
+
+ return FALSE;
+}
+
+
+bool Abstract_option_cmd::init(const char **text)
+{
+ static const int INITIAL_HASH_SIZE= 16;
+
+ if (hash_init(&instance_options_map, default_charset_info,
+ INITIAL_HASH_SIZE, 0, 0, get_item_key, delete_item, 0))
+ return TRUE;
+
+ if (parse_args(text))
+ return TRUE;
+
+ initialized= TRUE;
+
+ return FALSE;
+}
+
+
+/*
Correct the option file. The "skip" option is used to remove the found
option.
+ SYNOPSYS
+ Abstract_option_cmd::correct_file()
+ skip Skip the option, being searched while writing the result file.
+ That is, to delete it.
+
RETURN
- ER_OUT_OF_RESOURCES out of resources
+ 0 Success
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
ER_ACCESS_OPTION_FILE Cannot access the option file
- 0 - ok
*/
-int Set_option::correct_file(int skip)
+int Abstract_option_cmd::correct_file(Instance *instance, Named_value *option,
+ bool skip)
{
- static const int mysys_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
- ER_ACCESS_OPTION_FILE };
- int error;
+ int err_code= modify_defaults_file(Options::Main::config_file,
+ option->get_name(),
+ option->get_value(),
+ instance->get_name()->str,
+ skip);
+
+ DBUG_ASSERT(err_code >= 0 && err_code <= 2);
- error= modify_defaults_file(Options::config_file, option,
- option_value, instance_name, skip);
- DBUG_ASSERT(error >= 0 && error <= 2);
+ if (err_code)
+ {
+ log_error("Can not modify option (%s) in defaults file (%s). "
+ "Original error code: %d.",
+ (const char *) option->get_name(),
+ (const char *) Options::Main::config_file,
+ (int) err_code);
+ }
- return mysys_to_im_error[error];
+ return modify_defaults_to_im_error[err_code];
}
/*
- 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
+ Implementation of SET statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance with the given name does not exist
+ ER_INCOMPATIBLE_OPTION The specified option can not be set for
+ mysqld-compatible instance
+ ER_INSTANCE_IS_ACTIVE The specified instance is active
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
*/
-int Set_option::do_command(struct st_net *net)
+int Abstract_option_cmd::execute(st_net *net, ulong connection_id)
{
- int error;
+ int err_code;
- /* we must hold the instance_map mutex while changing config file */
instance_map->lock();
- error= correct_file(FALSE);
+
+ err_code= execute_impl(net, connection_id);
+
instance_map->unlock();
- return error;
+ return err_code;
+}
+
+
+Instance_options_list *
+Abstract_option_cmd::get_instance_options_list(const LEX_STRING *instance_name)
+{
+ Instance_options_list *lst=
+ (Instance_options_list *) hash_search(&instance_options_map,
+ (byte *) instance_name->str,
+ instance_name->length);
+
+ if (!lst)
+ {
+ lst= new Instance_options_list(instance_name);
+
+ if (!lst)
+ return NULL;
+
+ if (lst->init() || my_hash_insert(&instance_options_map, (byte *) lst))
+ {
+ delete lst;
+ return NULL;
+ }
+ }
+
+ return lst;
}
-int Set_option::execute(struct st_net *net, ulong connection_id)
+int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id)
{
- if (instance_name != NULL)
+ int err_code;
+
+ /* Check that all the specified instances exist and are offline. */
+
+ for (uint i= 0; i < instance_options_map.records; ++i)
{
- int val;
+ Instance_options_list *lst=
+ (Instance_options_list *) hash_element(&instance_options_map, i);
- val= do_command(net);
+ lst->instance= instance_map->find(lst->get_instance_name());
- if (val == 0)
- net_send_ok(net, connection_id, NULL);
+ if (!lst->instance)
+ return ER_BAD_INSTANCE_NAME;
- return val;
+ if (instance_map->guardian->is_active(lst->instance))
+ return ER_INSTANCE_IS_ACTIVE;
}
- return ER_BAD_INSTANCE_NAME;
+ /* Perform command-specific (SET/UNSET) actions. */
+
+ for (uint i= 0; i < instance_options_map.records; ++i)
+ {
+ Instance_options_list *lst=
+ (Instance_options_list *) hash_element(&instance_options_map, i);
+
+ for (int j= 0; j < lst->options.get_size(); ++j)
+ {
+ Named_value option= lst->options.get_element(j);
+ err_code= process_option(lst->instance, &option);
+
+ if (err_code)
+ break;
+ }
+
+ if (err_code)
+ break;
+ }
+
+ if (err_code == 0)
+ net_send_ok(net, connection_id, NULL);
+
+ return err_code;
}
-/* the only function from Unset_option we need to Implement */
+/**************************************************************************
+ Implementation of Set_option.
+**************************************************************************/
-int Unset_option::do_command(struct st_net *net)
+Set_option::Set_option(Instance_map *instance_map_arg)
+ :Abstract_option_cmd(instance_map_arg)
{
- return correct_file(TRUE);
}
-/* Implementation for Stop_instance: */
+/*
+ This operation parses SET options.
+
+ SYNOPSYS
+ text [IN/OUT] a pointer to the text containing options.
-Stop_instance::Stop_instance(Instance_map *instance_map_arg,
- const char *name, uint len)
- :Command(instance_map_arg)
+ RETURN
+ FALSE On success.
+ TRUE On syntax error.
+*/
+
+bool Set_option::parse_args(const char **text)
{
- /* 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;
+ uint len;
+
+ /* Check if we have something (and trim leading spaces). */
+
+ get_word(text, &len, NONSPACE);
+
+ if (len == 0)
+ return TRUE; /* Syntax error: no option. */
+
+ /* Main parsing loop. */
+
+ while (TRUE)
+ {
+ LEX_STRING instance_name;
+ LEX_STRING option_name;
+ char *option_name_str;
+ char *option_value_str= NULL;
+
+ /* Looking for instance name. */
+
+ get_word(text, &instance_name.length, ALPHANUM);
+
+ if (instance_name.length == 0)
+ return TRUE; /* Syntax error: instance name expected. */
+
+ instance_name.str= (char *) *text;
+ *text+= instance_name.length;
+
+ skip_spaces(text);
+
+ /* Check the the delimiter is a dot. */
+
+ if (**text != '.')
+ return TRUE; /* Syntax error: dot expected. */
+
+ ++(*text);
+
+ /* Looking for option name. */
+
+ get_word(text, &option_name.length, OPTION_NAME);
+
+ if (option_name.length == 0)
+ return TRUE; /* Syntax error: option name expected. */
+
+ option_name.str= (char *) *text;
+ *text+= option_name.length;
+
+ /* Looking for equal sign. */
+
+ skip_spaces(text);
+
+ if (**text == '=')
+ {
+ ++(*text); /* Skip an equal sign. */
+
+ /* Looking for option value. */
+
+ skip_spaces(text);
+
+ if (!**text)
+ return TRUE; /* Syntax error: EOS when option value expected. */
+
+ if (**text != '\'' && **text != '"')
+ {
+ /* Option value is a simple token. */
+
+ LEX_STRING option_value;
+
+ get_word(text, &option_value.length, ALPHANUM);
+
+ if (option_value.length == 0)
+ return TRUE; /* internal parser error. */
+
+ option_value.str= (char *) *text;
+ *text+= option_value.length;
+
+ if (!(option_value_str= Named_value::alloc_str(&option_value)))
+ return TRUE; /* out of memory during parsing. */
+ }
+ else
+ {
+ /* Option value is a string. */
+
+ if (parse_option_value(*text, &len, &option_value_str))
+ return TRUE; /* Syntax error: invalid string specification. */
+
+ *text+= len;
+ }
+ }
+
+ if (!option_value_str)
+ {
+ LEX_STRING empty_str= { C_STRING_WITH_SIZE("") };
+
+ if (!(option_value_str= Named_value::alloc_str(&empty_str)))
+ return TRUE; /* out of memory during parsing. */
+ }
+
+ if (!(option_name_str= Named_value::alloc_str(&option_name)))
+ {
+ Named_value::free_str(&option_name_str);
+ return TRUE; /* out of memory during parsing. */
+ }
+
+ {
+ Named_value option(option_name_str, option_value_str);
+
+ if (add_option(&instance_name, &option))
+ {
+ option.free();
+ return TRUE; /* out of memory during parsing. */
+ }
+ }
+
+ skip_spaces(text);
+
+ if (!**text)
+ return FALSE; /* OK: end of options. */
+
+ if (**text != ',')
+ return TRUE; /* Syntax error: comma expected. */
+
+ ++(*text); /* Skip a comma. */
+ }
}
-int Stop_instance::execute(struct st_net *net, ulong connection_id)
+int Set_option::process_option(Instance *instance, Named_value *option)
{
- uint err_code;
+ /* Check that the option is valid. */
+
+ if (instance->is_mysqld_compatible() &&
+ Instance_options::is_option_im_specific(option->get_name()))
+ {
+ log_error("Error: IM-option (%s) can not be used "
+ "in the configuration of mysqld-compatible instance (%s).",
+ (const char *) option->get_name(),
+ (const char *) instance->get_name()->str);
+ return ER_INCOMPATIBLE_OPTION;
+ }
- if (instance == 0)
- return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
+ /* Update the configuration file. */
- if (!(instance->options.nonguarded))
- instance_map->guardian->stop_guard(instance);
+ int err_code= correct_file(instance, option, FALSE);
- if ((err_code= instance->stop()))
+ if (err_code)
+ return err_code;
+
+ /* Update the internal cache. */
+
+ if (instance->options.set_option(option))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation of Unset_option.
+**************************************************************************/
+
+Unset_option::Unset_option(Instance_map *instance_map_arg)
+ :Abstract_option_cmd(instance_map_arg)
+{
+}
+
+
+/*
+ This operation parses UNSET options.
+
+ SYNOPSYS
+ text [IN/OUT] a pointer to the text containing options.
+
+ RETURN
+ FALSE On success.
+ TRUE On syntax error.
+*/
+
+bool Unset_option::parse_args(const char **text)
+{
+ uint len;
+
+ /* Check if we have something (and trim leading spaces). */
+
+ get_word(text, &len, NONSPACE);
+
+ if (len == 0)
+ return TRUE; /* Syntax error: no option. */
+
+ /* Main parsing loop. */
+
+ while (TRUE)
+ {
+ LEX_STRING instance_name;
+ LEX_STRING option_name;
+ char *option_name_str;
+ char *option_value_str;
+
+ /* Looking for instance name. */
+
+ get_word(text, &instance_name.length, ALPHANUM);
+
+ if (instance_name.length == 0)
+ return TRUE; /* Syntax error: instance name expected. */
+
+ instance_name.str= (char *) *text;
+ *text+= instance_name.length;
+
+ skip_spaces(text);
+
+ /* Check the the delimiter is a dot. */
+
+ if (**text != '.')
+ return TRUE; /* Syntax error: dot expected. */
+
+ ++(*text); /* Skip a dot. */
+
+ /* Looking for option name. */
+
+ get_word(text, &option_name.length, OPTION_NAME);
+
+ if (option_name.length == 0)
+ return TRUE; /* Syntax error: option name expected. */
+
+ option_name.str= (char *) *text;
+ *text+= option_name.length;
+
+ if (!(option_name_str= Named_value::alloc_str(&option_name)))
+ return TRUE; /* out of memory during parsing. */
+
+ {
+ LEX_STRING empty_str= { C_STRING_WITH_SIZE("") };
+
+ if (!(option_value_str= Named_value::alloc_str(&empty_str)))
+ {
+ Named_value::free_str(&option_name_str);
+ return TRUE;
+ }
+ }
+
+ {
+ Named_value option(option_name_str, option_value_str);
+
+ if (add_option(&instance_name, &option))
+ {
+ option.free();
+ return TRUE; /* out of memory during parsing. */
+ }
+ }
+
+ skip_spaces(text);
+
+ if (!**text)
+ return FALSE; /* OK: end of options. */
+
+ if (**text != ',')
+ return TRUE; /* Syntax error: comma expected. */
+
+ ++(*text); /* Skip a comma. */
+ }
+}
+
+
+/*
+ Implementation of UNSET statement.
+
+ Possible error codes:
+ ER_BAD_INSTANCE_NAME The instance name specified is not valid
+ ER_INSTANCE_IS_ACTIVE The specified instance is active
+ ER_OUT_OF_RESOURCES Not enough resources to complete the operation
+*/
+
+int Unset_option::process_option(Instance *instance, Named_value *option)
+{
+ /* Update the configuration file. */
+
+ int err_code= correct_file(instance, option, TRUE);
+
+ if (err_code)
return err_code;
- net_send_ok(net, connection_id, NULL);
+ /* Update the internal cache. */
+
+ instance->options.unset_option(option->get_name());
+
return 0;
}
-int Syntax_error::execute(struct st_net *net, ulong connection_id)
+/**************************************************************************
+ Implementation of Syntax_error.
+**************************************************************************/
+
+int Syntax_error::execute(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
index bfd38d34889..9a9911f2358 100644
--- a/server-tools/instance-manager/commands.h
+++ b/server-tools/instance-manager/commands.h
@@ -16,10 +16,20 @@
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 <m_string.h>
+#include <hash.h>
+
#include "command.h"
#include "instance.h"
#include "parse.h"
+#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
+#pragma interface
+#endif
+
+
/*
Print all instances of this instance manager.
Grammar: SHOW ISTANCES
@@ -31,12 +41,16 @@ public:
Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
{}
- int execute(struct st_net *net, ulong connection_id);
+ int execute(st_net *net, ulong connection_id);
+
+private:
+ int write_header(st_net *net);
+ int write_data(st_net *net);
};
/*
- Reread configuration file and refresh instance map.
+ Reread configuration file and refresh internal cache.
Grammar: FLUSH INSTANCES
*/
@@ -46,7 +60,43 @@ public:
Flush_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
{}
- int execute(struct st_net *net, ulong connection_id);
+ int execute(st_net *net, ulong connection_id);
+};
+
+
+/*
+ Abstract class for Instance-specific commands.
+*/
+
+class Abstract_instance_cmd : public Command
+{
+public:
+ Abstract_instance_cmd(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg);
+
+public:
+ virtual int execute(st_net *net, ulong connection_id);
+
+protected:
+ /* MT-NOTE: this operation is called under acquired Instance_map's lock. */
+ virtual int execute_impl(st_net *net, Instance *instance) = 0;
+
+ /*
+ This operation is invoked on successful return of execute_impl() and is
+ intended to send closing data.
+
+ MT-NOTE: this operation is called under released Instance_map's lock.
+ */
+ virtual int send_ok_response(st_net *net, ulong connection_id) = 0;
+
+protected:
+ inline const LEX_STRING *get_instance_name() const
+ {
+ return instance_name.get_str();
+ }
+
+private:
+ Instance_name instance_name;
};
@@ -55,31 +105,40 @@ public:
Grammar: SHOW ISTANCE STATUS <instance_name>
*/
-class Show_instance_status : public Command
+class Show_instance_status : public Abstract_instance_cmd
{
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;
+ const LEX_STRING *instance_name_arg);
+
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
+
+private:
+ int write_header(st_net *net);
+ int write_data(st_net *net, Instance *instance);
};
/*
- Print options if chosen instance.
+ Print options of chosen instance.
Grammar: SHOW INSTANCE OPTIONS <instance_name>
*/
-class Show_instance_options : public Command
+class Show_instance_options : public Abstract_instance_cmd
{
public:
-
Show_instance_options(Instance_map *instance_map_arg,
- const char *name, uint len);
+ const LEX_STRING *instance_name_arg);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
+
+private:
+ int write_header(st_net *net);
+ int write_data(st_net *net, Instance *instance);
};
@@ -88,14 +147,15 @@ public:
Grammar: START INSTANCE <instance_name>
*/
-class Start_instance : public Command
+class Start_instance : public Abstract_instance_cmd
{
public:
- Start_instance(Instance_map *instance_map_arg, const char *name, uint len);
+ Start_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
- Instance *instance;
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
};
@@ -104,33 +164,95 @@ public:
Grammar: STOP INSTANCE <instance_name>
*/
-class Stop_instance : public Command
+class Stop_instance : public Abstract_instance_cmd
{
public:
- Stop_instance(Instance_map *instance_map_arg, const char *name, uint len);
+ Stop_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg);
- Instance *instance;
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
};
/*
- Print requested part of the log
+ Create an instance.
+ Grammar: CREATE INSTANCE <instance_name> [<options>]
+*/
+
+class Create_instance : public Command
+{
+public:
+ Create_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg);
+
+public:
+ bool init(const char **text);
+
+protected:
+ virtual int execute(st_net *net, ulong connection_id);
+
+ inline const LEX_STRING *get_instance_name() const
+ {
+ return instance_name.get_str();
+ }
+
+private:
+ bool parse_args(const char **text);
+
+private:
+ Instance_name instance_name;
+
+ Named_value_arr options;
+};
+
+
+/*
+ Drop an instance.
+ Grammar: DROP INSTANCE <instance_name>
+
+ Operation is permitted only if the instance is stopped. On successful
+ completion the instance section is removed from config file and the instance
+ is removed from the instance map.
+*/
+
+class Drop_instance : public Abstract_instance_cmd
+{
+public:
+ Drop_instance(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg);
+
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
+};
+
+
+/*
+ Print requested part of the log.
Grammar:
- SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
+ SHOW <instance_name> LOG {ERROR | SLOW | GENERAL} size[, offset_from_end]
*/
-class Show_instance_log : public Command
+class Show_instance_log : public Abstract_instance_cmd
{
public:
+ Show_instance_log(Instance_map *instance_map_arg,
+ const LEX_STRING *instance_name_arg,
+ Log_type log_type_arg, uint size_arg, uint offset_arg);
+
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
+
+private:
+ int check_params(Instance *instance);
+ int write_header(st_net *net);
+ int write_data(st_net *net, Instance *instance);
- 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);
+private:
Log_type log_type;
- const char *instance_name;
uint size;
uint offset;
};
@@ -141,75 +263,112 @@ public:
Grammar: SHOW <instance_name> LOG FILES
*/
-class Show_instance_log_files : public Command
+class Show_instance_log_files : public Abstract_instance_cmd
{
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;
+ const LEX_STRING *instance_name_arg);
+
+protected:
+ virtual int execute_impl(st_net *net, Instance *instance);
+ virtual int send_ok_response(st_net *net, ulong connection_id);
+
+private:
+ int write_header(st_net *net);
+ int write_data(st_net *net, Instance *instance);
};
/*
- 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.
+ Abstract class for option-management commands.
*/
-class Syntax_error : public Command
+class Instance_options_list;
+
+class Abstract_option_cmd : public Command
{
public:
- int execute(struct st_net *net, ulong connection_id);
+ ~Abstract_option_cmd();
+
+public:
+ bool add_option(const LEX_STRING *instance_name, Named_value *option);
+
+public:
+ bool init(const char **text);
+
+ virtual int execute(st_net *net, ulong connection_id);
+
+protected:
+ Abstract_option_cmd(Instance_map *instance_map_arg);
+
+ int correct_file(Instance *instance, Named_value *option, bool skip);
+
+protected:
+ virtual bool parse_args(const char **text) = 0;
+ virtual int process_option(Instance *instance, Named_value *option) = 0;
+
+private:
+ Instance_options_list *
+ get_instance_options_list(const LEX_STRING *instance_name);
+
+ int execute_impl(st_net *net, ulong connection_id);
+
+private:
+ HASH instance_options_map;
+ bool initialized;
};
+
/*
Set an option for the instance.
- Grammar: SET instance_name.option=option_value
+ Grammar: SET instance_name.option[=option_value][, ...]
*/
-class Set_option : public Command
+class Set_option : public Abstract_option_cmd
{
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);
+ Set_option(Instance_map *instance_map_arg);
+
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];
+ virtual bool parse_args(const char **text);
+ virtual int process_option(Instance *instance, Named_value *option);
};
/*
- Remove option of the instance from config file
- Grammar: UNSET instance_name.option
+ Remove option of the instance.
+ Grammar: UNSET instance_name.option[, ...]
*/
-class Unset_option: public Set_option
+class Unset_option: public Abstract_option_cmd
{
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);
+ Unset_option(Instance_map *instance_map_arg);
+
+protected:
+ virtual bool parse_args(const char **text);
+ virtual int process_option(Instance *instance, Named_value *option);
};
+/*
+ Syntax error command.
+
+ This command is issued if parser reported a syntax error. We need it to
+ distinguish between syntax error and internal parser error. E.g. parsing
+ failed because we hadn't had enought memory. In the latter case the parser
+ just returns NULL.
+*/
+
+class Syntax_error : public Command
+{
+public:
+ /* This is just to avoid compiler warning. */
+ Syntax_error() :Command(NULL)
+ {}
+
+public:
+ int execute(st_net *net, ulong connection_id);
+};
+
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
diff --git a/server-tools/instance-manager/exit_codes.h b/server-tools/instance-manager/exit_codes.h
new file mode 100644
index 00000000000..560ce30b7aa
--- /dev/null
+++ b/server-tools/instance-manager/exit_codes.h
@@ -0,0 +1,41 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
+
+/*
+ Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 contains a list of exit codes, which are used when Instance
+ Manager is working in user-management mode.
+*/
+
+const int ERR_OK = 0;
+
+const int ERR_OUT_OF_MEMORY = 1;
+const int ERR_INVALID_USAGE = 2;
+const int ERR_INTERNAL_ERROR = 3;
+const int ERR_IO_ERROR = 4;
+const int ERR_PASSWORD_FILE_CORRUPTED = 5;
+const int ERR_PASSWORD_FILE_DOES_NOT_EXIST = 6;
+
+const int ERR_CAN_NOT_READ_USER_NAME = 10;
+const int ERR_CAN_NOT_READ_PASSWORD = 11;
+const int ERR_USER_ALREADY_EXISTS = 12;
+const int ERR_USER_NOT_FOUND = 13;
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
index 3be672cd71c..7a9ff3e8367 100644
--- a/server-tools/instance-manager/guardian.cc
+++ b/server-tools/instance-manager/guardian.cc
@@ -21,16 +21,14 @@
#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>
+#include "instance.h"
+#include "instance_map.h"
+#include "log.h"
+#include "mysql_manager_error.h"
pthread_handler_t guardian(void *arg)
@@ -40,6 +38,37 @@ pthread_handler_t guardian(void *arg)
return 0;
}
+
+const char *
+Guardian_thread::get_instance_state_name(enum_instance_state state)
+{
+ switch (state) {
+ case NOT_STARTED:
+ return "offline";
+
+ case STARTING:
+ return "starting";
+
+ case STARTED:
+ return "online";
+
+ case JUST_CRASHED:
+ return "failed";
+
+ case CRASHED:
+ return "crashed";
+
+ case CRASHED_AND_ABANDONED:
+ return "abandoned";
+
+ case STOPPING:
+ return "stopping";
+ }
+
+ return NULL; /* just to ignore compiler warning. */
+}
+
+
Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg,
uint monitoring_interval_arg) :
@@ -89,10 +118,17 @@ void Guardian_thread::process_instance(Instance *instance,
if (current_node->state == STOPPING)
{
/* this brach is executed during shutdown */
- if (instance->options.shutdown_delay_val)
+ if (instance->options.shutdown_delay)
+ {
+ /*
+ NOTE: it is important to check shutdown_delay here, but use
+ shutdown_delay_val. The idea is that if the option is unset,
+ shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
+ */
waitchild= instance->options.shutdown_delay_val;
+ }
- /* this returns true if and only if an instance was stopped for sure */
+ /* 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)
@@ -159,7 +195,11 @@ void Guardian_thread::process_instance(Instance *instance,
instance->options.instance_name);
}
else
+ {
+ log_info("guardian: cannot start instance %s. Abandoning attempts "
+ "to (re)start it", instance->options.instance_name);
current_node->state= CRASHED_AND_ABANDONED;
+ }
}
break;
case CRASHED_AND_ABANDONED:
@@ -242,7 +282,9 @@ int Guardian_thread::is_stopped()
SYNOPSYS
Guardian_thread::init()
- NOTE: One should always lock guardian before calling this routine.
+ NOTE: The operation should be invoked with the following locks acquired:
+ - Guardian_thread;
+ - Instance_map;
RETURN
0 - ok
@@ -261,12 +303,11 @@ int Guardian_thread::init()
while ((instance= iterator.next()))
{
- if (!(instance->options.nonguarded))
- if (guard(instance, TRUE)) /* do not lock guardian */
- {
- instance_map->unlock();
- return 1;
- }
+ if (instance->options.nonguarded)
+ continue;
+
+ if (guard(instance, TRUE)) /* do not lock guardian */
+ return 1;
}
return 0;
@@ -334,24 +375,14 @@ 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;
- }
+ node= find_instance_node(instance);
+
+ if (node != NULL)
+ guarded_instances= list_delete(guarded_instances, node);
+
pthread_mutex_unlock(&LOCK_guardian);
+
/* if there is nothing to delete it is also fine */
return 0;
}
@@ -420,7 +451,7 @@ int Guardian_thread::stop_instances(bool stop_instances_arg)
void Guardian_thread::lock()
{
- pthread_mutex_lock(&LOCK_guardian);
+ pthread_mutex_lock(&LOCK_guardian);
}
@@ -428,3 +459,41 @@ void Guardian_thread::unlock()
{
pthread_mutex_unlock(&LOCK_guardian);
}
+
+
+LIST *Guardian_thread::find_instance_node(Instance *instance)
+{
+ LIST *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)
+ return node;
+
+ node= node->next;
+ }
+
+ return NULL;
+}
+
+
+bool Guardian_thread::is_active(Instance *instance)
+{
+ bool guarded;
+
+ lock();
+
+ guarded= find_instance_node(instance) != NULL;
+
+ /* is_running() can take a long time, so let's unlock mutex first. */
+ unlock();
+
+ if (guarded)
+ return true;
+
+ return instance->is_running();
+}
diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h
index 16b4c373c91..6d3a2b222d7 100644
--- a/server-tools/instance-manager/guardian.h
+++ b/server-tools/instance-manager/guardian.h
@@ -17,11 +17,11 @@
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>
+#include "thread_registry.h"
+
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
@@ -79,6 +79,8 @@ public:
time_t last_checked;
};
+ /* Return client state name. */
+ static const char *get_instance_state_name(enum_instance_state state);
Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg,
@@ -94,11 +96,28 @@ public:
int guard(Instance *instance, bool nolock= FALSE);
/* Stop instance protection */
int stop_guard(Instance *instance);
- /* Returns true if guardian thread is stopped */
+ /* Returns TRUE if guardian thread is stopped */
int is_stopped();
void lock();
void unlock();
+ /*
+ Return an internal list node for the given instance if the instance is
+ managed by Guardian. Otherwise, return NULL.
+
+ MT-NOTE: must be called under acquired lock.
+ */
+ LIST *find_instance_node(Instance *instance);
+
+ /* The operation is used to check if the instance is active or not. */
+ bool is_active(Instance *instance);
+
+ /*
+ Return state of the given instance list node. The pointer must specify
+ a valid list node.
+ */
+ inline enum_instance_state get_instance_state(LIST *instance_node);
+
public:
pthread_cond_t COND_guardian;
@@ -108,6 +127,7 @@ private:
/* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem);
+
int stopped;
private:
@@ -115,9 +135,15 @@ private:
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;
};
+
+inline Guardian_thread::enum_instance_state
+Guardian_thread::get_instance_state(LIST *instance_node)
+{
+ return ((GUARD_NODE *) instance_node->data)->state;
+}
+
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc
index 39381b457ab..456052bf7e5 100644
--- a/server-tools/instance-manager/instance.cc
+++ b/server-tools/instance-manager/instance.cc
@@ -20,18 +20,27 @@
#include "instance.h"
-#include "mysql_manager_error.h"
-#include "log.h"
-#include "instance_map.h"
-#include "priv.h"
-#include "portability.h"
+#include <my_global.h>
+#include <mysql.h>
+
+#include <signal.h>
#ifndef __WIN__
#include <sys/wait.h>
#endif
-#include <my_sys.h>
-#include <signal.h>
-#include <m_string.h>
-#include <mysql.h>
+
+#include "guardian.h"
+#include "instance_map.h"
+#include "log.h"
+#include "mysql_manager_error.h"
+#include "portability.h"
+#include "priv.h"
+
+
+const LEX_STRING
+Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_SIZE("mysqld") };
+
+static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str;
+static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length;
static void start_and_monitor_instance(Instance_options *old_instance_options,
@@ -152,7 +161,7 @@ static int start_process(Instance_options *instance_options,
switch (*pi) {
case 0: /* never happens on QNX */
- execv(instance_options->mysqld_path, instance_options->argv);
+ execv(instance_options->mysqld_path.str, instance_options->argv);
/* exec never returns */
exit(1);
case -1:
@@ -180,7 +189,7 @@ static int start_process(Instance_options *instance_options,
char *cmdline= new char[cmdlen];
if (cmdline == NULL)
return 1;
-
+
cmdline[0]= 0;
for (int i= 0; instance_options->argv[i] != 0; i++)
{
@@ -232,9 +241,7 @@ static int start_process(Instance_options *instance_options,
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_name instance_name(&old_instance_options->instance_name);
Instance *current_instance;
My_process_info process_info;
@@ -248,11 +255,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
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);
+ log_info("starting instance %s", (const char *) instance_name.get_c_str());
if (start_process(old_instance_options, &process_info))
{
@@ -266,15 +270,36 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
/* don't check for return value */
wait_process(&process_info);
- current_instance= instance_map->find(instance_name_buff, instance_name_len);
+ instance_map->lock();
+
+ current_instance= instance_map->find(instance_name.get_str());
if (current_instance)
current_instance->set_crash_flag_n_wake_all();
+ instance_map->unlock();
+
return;
}
+bool Instance::is_name_valid(const LEX_STRING *name)
+{
+ const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN;
+
+ if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0)
+ return FALSE;
+
+ return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
+}
+
+
+bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
+{
+ return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0;
+}
+
+
Instance_map *Instance::get_map()
{
return instance_map;
@@ -309,11 +334,11 @@ int Instance::start()
{
/* clear crash flag */
pthread_mutex_lock(&LOCK_instance);
- crashed= 0;
+ crashed= FALSE;
pthread_mutex_unlock(&LOCK_instance);
- if (!is_running())
+ if (configured && !is_running())
{
remove_pid();
@@ -339,8 +364,8 @@ int Instance::start()
return 0;
}
- /* the instance is started already */
- return ER_INSTANCE_ALREADY_STARTED;
+ /* The instance is started already or misconfigured. */
+ return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
}
/*
@@ -363,7 +388,7 @@ void Instance::set_crash_flag_n_wake_all()
{
/* set instance state to crashed */
pthread_mutex_lock(&LOCK_instance);
- crashed= 1;
+ crashed= TRUE;
pthread_mutex_unlock(&LOCK_instance);
/*
@@ -378,7 +403,7 @@ void Instance::set_crash_flag_n_wake_all()
-Instance::Instance(): crashed(0)
+Instance::Instance(): crashed(FALSE), configured(FALSE)
{
pthread_mutex_init(&LOCK_instance, 0);
pthread_cond_init(&COND_instance_stopped, 0);
@@ -392,9 +417,9 @@ Instance::~Instance()
}
-int Instance::is_crashed()
+bool Instance::is_crashed()
{
- int val;
+ bool val;
pthread_mutex_lock(&LOCK_instance);
val= crashed;
pthread_mutex_unlock(&LOCK_instance);
@@ -413,10 +438,17 @@ bool Instance::is_running()
bool return_val;
if (options.mysqld_port)
+ {
+ /*
+ NOTE: it is important to check mysqld_port here, but use
+ mysqld_port_val. The idea is that if the option is unset, mysqld_port
+ will be NULL, but mysqld_port_val will not be reset.
+ */
port= options.mysqld_port_val;
+ }
if (options.mysqld_socket)
- socket= strchr(options.mysqld_socket, '=') + 1;
+ socket= options.mysqld_socket;
/* no port was specified => instance falled back to default value */
if (!options.mysqld_port && !options.mysqld_socket)
@@ -469,8 +501,15 @@ int Instance::stop()
struct timespec timeout;
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
- if (options.shutdown_delay_val)
+ if (options.shutdown_delay)
+ {
+ /*
+ NOTE: it is important to check shutdown_delay here, but use
+ shutdown_delay_val. The idea is that if the option is unset,
+ shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
+ */
waitchild= options.shutdown_delay_val;
+ }
kill_instance(SIGTERM);
/* sleep on condition to wait for SIGCHLD */
@@ -588,20 +627,33 @@ void Instance::kill_instance(int signum)
}
/*
- We execute this function to initialize instance parameters.
- Return value: 0 - ok. 1 - unable to init DYNAMIC_ARRAY.
+ Initialize instance parameters.
+
+ SYNOPSYS
+ Instance::init()
+ name_arg name of the instance
+
+ RETURN:
+ 0 ok
+ !0 error
*/
-int Instance::init(const char *name_arg)
+int Instance::init(const LEX_STRING *name_arg)
{
+ mysqld_compatible= is_mysqld_compatible_name(name_arg);
+
return options.init(name_arg);
}
int Instance::complete_initialization(Instance_map *instance_map_arg,
- const char *mysqld_path,
- uint instance_type)
+ const char *mysqld_path)
{
instance_map= instance_map_arg;
- return options.complete_initialization(mysqld_path, instance_type);
+ configured= !options.complete_initialization(mysqld_path);
+ return 0;
+ /*
+ TODO: return actual status (from
+ Instance_options::complete_initialization()) here.
+ */
}
diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h
index adb66991685..1f06cabebf7 100644
--- a/server-tools/instance-manager/instance.h
+++ b/server-tools/instance-manager/instance.h
@@ -17,7 +17,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
+#include <m_string.h>
+
#include "instance_options.h"
+#include "priv.h"
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
@@ -25,31 +28,120 @@
class Instance_map;
+
+/*
+ Instance_name -- the class represents instance name -- a string of length
+ less than MAX_INSTANCE_NAME_SIZE.
+
+ Generally, this is just a string with self-memory-management and should be
+ eliminated in the future.
+*/
+
+class Instance_name
+{
+public:
+ Instance_name(const LEX_STRING *name);
+
+public:
+ inline const LEX_STRING *get_str() const
+ {
+ return &str;
+ }
+
+ inline const char *get_c_str() const
+ {
+ return str.str;
+ }
+
+ inline uint get_length() const
+ {
+ return str.length;
+ }
+
+private:
+ LEX_STRING str;
+ char str_buffer[MAX_INSTANCE_NAME_SIZE];
+};
+
+
class Instance
{
public:
+ /*
+ The following two constants defines name of the default mysqld-instance
+ ("mysqld").
+ */
+ static const LEX_STRING DFLT_INSTANCE_NAME;
+
+public:
+ /*
+ The operation is intended to check whether string is a well-formed
+ instance name or not.
+ */
+ static bool is_name_valid(const LEX_STRING *name);
+
+ /*
+ The operation is intended to check if the given instance name is
+ mysqld-compatible or not.
+ */
+ static bool is_mysqld_compatible_name(const LEX_STRING *name);
+
+public:
Instance();
~Instance();
- int init(const char *name);
+ int init(const LEX_STRING *name_arg);
int complete_initialization(Instance_map *instance_map_arg,
- const char *mysqld_path, uint instance_type);
+ const char *mysqld_path);
bool is_running();
int start();
int stop();
/* send a signal to the instance */
void kill_instance(int signo);
- int is_crashed();
+ bool is_crashed();
void set_crash_flag_n_wake_all();
Instance_map *get_map();
+ /*
+ The operation is intended to check if the instance is mysqld-compatible
+ or not.
+ */
+ inline bool is_mysqld_compatible() const;
+
+ /*
+ The operation is intended to check if the instance is configured properly
+ or not. Misconfigured instances are not managed.
+ */
+ inline bool is_configured() const;
+
+ inline const LEX_STRING *get_name() const;
+
public:
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
Instance_options options;
private:
- int crashed;
+ /* This attributes is a flag, specifies if the instance has been crashed. */
+ bool crashed;
+
+ /*
+ This attribute specifies if the instance is configured properly or not.
+ Misconfigured instances are not managed.
+ */
+ bool configured;
+
+ /*
+ This attribute specifies whether the instance is mysqld-compatible or not.
+ Mysqld-compatible instances can contain only mysqld-specific options.
+ At the moment an instance is mysqld-compatible if its name is "mysqld".
+
+ The idea is that [mysqld] section should contain only mysqld-specific
+ options (no Instance Manager-specific options) to be readable by mysqld
+ program.
+ */
+ bool mysqld_compatible;
+
/*
Mutex protecting the instance. Currently we use it to avoid the
double start of the instance. This happens when the instance is starting
@@ -66,4 +158,22 @@ private:
void remove_pid();
};
+
+inline bool Instance::is_mysqld_compatible() const
+{
+ return mysqld_compatible;
+}
+
+
+inline bool Instance::is_configured() const
+{
+ return configured;
+}
+
+
+inline const LEX_STRING *Instance::get_name() const
+{
+ return &options.instance_name;
+}
+
#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
index 543c9c31bfa..c9608fa7c14 100644
--- a/server-tools/instance-manager/instance_map.cc
+++ b/server-tools/instance-manager/instance_map.cc
@@ -20,14 +20,19 @@
#include "instance_map.h"
+#include <my_global.h>
+#include <m_ctype.h>
+#include <mysql_com.h>
+
#include "buffer.h"
+#include "guardian.h"
#include "instance.h"
#include "log.h"
+#include "manager.h"
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
#include "options.h"
-
-#include <m_ctype.h>
-#include <mysql_com.h>
-#include <m_string.h>
+#include "priv.h"
/*
Note: As we are going to suppost different types of connections,
@@ -45,8 +50,8 @@ 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;
+ *len= instance->options.instance_name.length;
+ return (byte *) instance->options.instance_name.str;
}
static void delete_instance(void *u)
@@ -79,16 +84,60 @@ static void delete_instance(void *u)
static int process_option(void *ctx, const char *group, const char *option)
{
- Instance_map *map= NULL;
+ Instance_map *map= (Instance_map*) ctx;
+ LEX_STRING group_str;
- map = (Instance_map*) ctx;
- return map->process_one_option(group, option);
+ group_str.str= (char *) group;
+ group_str.length= strlen(group);
+
+ return map->process_one_option(&group_str, option);
}
C_MODE_END
/*
+ Parse option string.
+
+ SYNOPSIS
+ parse_option()
+ option_str [IN] option string (e.g. "--name=value")
+ option_name_buf [OUT] parsed name of the option.
+ Must be of (MAX_OPTION_LEN + 1) size.
+ option_value_buf [OUT] parsed value of the option.
+ Must be of (MAX_OPTION_LEN + 1) size.
+
+ DESCRIPTION
+ This is an auxiliary function and should not be used externally. It is
+ intended to parse whole option string into option name and option value.
+*/
+
+static void parse_option(const char *option_str,
+ char *option_name_buf,
+ char *option_value_buf)
+{
+ const char *eq_pos;
+ const char *ptr= option_str;
+
+ while (*ptr == '-')
+ ++ptr;
+
+ strmake(option_name_buf, ptr, MAX_OPTION_LEN + 1);
+
+ eq_pos= strchr(ptr, '=');
+ if (eq_pos)
+ {
+ option_name_buf[eq_pos - ptr]= 0;
+ strmake(option_value_buf, eq_pos + 1, MAX_OPTION_LEN + 1);
+ }
+ else
+ {
+ option_value_buf[0]= 0;
+ }
+}
+
+
+/*
Process one option from the configuration file.
SYNOPSIS
@@ -103,34 +152,64 @@ C_MODE_END
of the instance map object.
*/
-int Instance_map::process_one_option(const char *group, const char *option)
+int Instance_map::process_one_option(const LEX_STRING *group,
+ const char *option)
{
Instance *instance= NULL;
- static const char prefix[]= { 'm', 'y', 's', 'q', 'l', 'd' };
- if (strncmp(group, prefix, sizeof prefix) == 0 &&
- ((my_isdigit(default_charset_info, group[sizeof prefix]))
- || group[sizeof(prefix)] == '\0'))
+ if (!Instance::is_name_valid(group))
+ {
+ /*
+ Current section name is not a valid instance name.
+ We should skip it w/o error.
+ */
+ return 0;
+ }
+
+ if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str,
+ group->length)))
+ {
+ if (!(instance= new Instance()))
+ return 1;
+
+ if (instance->init(group) || add_instance(instance))
{
- if (!(instance= (Instance *) hash_search(&hash, (byte *) group,
- strlen(group))))
- {
- if (!(instance= new Instance))
- goto err;
- if (instance->init(group) || my_hash_insert(&hash, (byte *) instance))
- goto err_instance;
- }
-
- if (instance->options.add_option(option))
- goto err; /* the instance'll be deleted when we destroy the map */
+ delete instance;
+ return 1;
}
- return 0;
+ if (instance->is_mysqld_compatible())
+ log_info("Warning: instance name '%s' is mysqld-compatible.",
+ (const char *) group->str);
-err_instance:
- delete instance;
-err:
- return 1;
+ log_info("mysqld instance '%s' has been added successfully.",
+ (const char *) group->str);
+ }
+
+ if (option)
+ {
+ char option_name[MAX_OPTION_LEN + 1];
+ char option_value[MAX_OPTION_LEN + 1];
+
+ parse_option(option, option_name, option_value);
+
+ if (instance->is_mysqld_compatible() &&
+ Instance_options::is_option_im_specific(option_name))
+ {
+ log_info("Warning: configuration of mysqld-compatible instance '%s' "
+ "contains IM-specific option '%s'. "
+ "This breaks backward compatibility for the configuration file.",
+ (const char *) group->str,
+ (const char *) option_name);
+ }
+
+ Named_value option(option_name, option_value);
+
+ if (instance->options.set_option(&option))
+ return 1; /* the instance'll be deleted when we destroy the map */
+ }
+
+ return 0;
}
@@ -181,7 +260,7 @@ void Instance_map::unlock()
- pass on the new map to the guardian thread: it will start
all instances that are marked `guarded' and not yet started.
Note, as the check whether an instance is started is currently
- very simple (returns true if there is a MySQL server running
+ very simple (returns TRUE if there is a MySQL server running
at the given port), this function has some peculiar
side-effects:
* if the port number of a running instance was changed, the
@@ -194,9 +273,9 @@ void Instance_map::unlock()
In order to avoid such side effects one should never call
FLUSH INSTANCES without prior stop of all running instances.
- TODO
- FLUSH INSTANCES should return an error if it's called
- while there is a running instance.
+ NOTE: The operation should be invoked with the following locks acquired:
+ - Guardian_thread;
+ - Instance_map;
*/
int Instance_map::flush_instances()
@@ -209,67 +288,169 @@ int Instance_map::flush_instances()
guardian (2) reload the instance map (3) reinitialize the guardian
with new instances.
*/
- 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);
+
rc= load();
guardian->init();
- pthread_mutex_unlock(&LOCK_instance_map);
- guardian->unlock();
return rc;
}
-Instance *
-Instance_map::find(const char *name, uint name_len)
+bool Instance_map::is_there_active_instance()
{
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;
+ Iterator iterator(this);
+
+ while ((instance= iterator.next()))
+ {
+ if (guardian->find_instance_node(instance) != NULL ||
+ instance->is_running())
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
-int Instance_map::complete_initialization()
+int Instance_map::add_instance(Instance *instance)
{
- Instance *instance;
- uint i= 0;
+ return my_hash_insert(&hash, (byte *) instance);
+}
- if (hash.records == 0) /* no instances found */
- {
- if ((instance= new Instance) == 0)
- goto err;
+int Instance_map::remove_instance(Instance *instance)
+{
+ return hash_delete(&hash, (byte *) instance);
+}
- if (instance->init("mysqld") || my_hash_insert(&hash, (byte *) 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;
+int Instance_map::create_instance(const LEX_STRING *instance_name,
+ const Named_value_arr *options)
+{
+ Instance *instance= new Instance();
+
+ if (!instance)
+ {
+ log_error("Error: can not initialize (name: '%s').",
+ (const char *) instance_name->str);
+ return ER_OUT_OF_RESOURCES;
}
- else
- while (i < hash.records)
+
+ if (instance->init(instance_name))
+ {
+ log_error("Error: can not initialize (name: '%s').",
+ (const char *) instance_name->str);
+ delete instance;
+ return ER_OUT_OF_RESOURCES;
+ }
+
+ for (int i= 0; options && i < options->get_size(); ++i)
+ {
+ Named_value option= options->get_element(i);
+
+ if (instance->is_mysqld_compatible() &&
+ Instance_options::is_option_im_specific(option.get_name()))
{
- instance= (Instance *) hash_element(&hash, i);
- if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE))
- goto err;
- i++;
+ log_error("Error: IM-option (%s) can not be used "
+ "in configuration of mysqld-compatible instance (%s).",
+ (const char *) option.get_name(),
+ (const char *) instance_name->str);
+ delete instance;
+ return ER_INCOMPATIBLE_OPTION;
}
+ instance->options.set_option(&option);
+ }
+
+ if (instance->is_mysqld_compatible())
+ log_info("Warning: instance name '%s' is mysqld-compatible.",
+ (const char *) instance_name->str);
+
+ if (instance->complete_initialization(this, mysqld_path))
+ {
+ log_error("Error: can not complete initialization of instance (name: '%s').",
+ (const char *) instance_name->str);
+ delete instance;
+ return ER_OUT_OF_RESOURCES;
+ /* TODO: return more appropriate error code in this case. */
+ }
+
+ if (add_instance(instance))
+ {
+ log_error("Error: can not register instance (name: '%s').",
+ (const char *) instance_name->str);
+ delete instance;
+ return ER_OUT_OF_RESOURCES;
+ }
+
return 0;
-err_instance:
- delete instance;
-err:
- return 1;
+}
+
+
+Instance * Instance_map::find(const LEX_STRING *name)
+{
+ return (Instance *) hash_search(&hash, (byte *) name->str, name->length);
+}
+
+
+bool Instance_map::complete_initialization()
+{
+ bool mysqld_found;
+
+ /* Complete initialization of all registered instances. */
+
+ for (uint i= 0; i < hash.records; ++i)
+ {
+ Instance *instance= (Instance *) hash_element(&hash, i);
+
+ if (instance->complete_initialization(this, mysqld_path))
+ return TRUE;
+ }
+
+ /* That's all if we are runnning in an ordinary mode. */
+
+ if (!Options::Main::mysqld_safe_compatible)
+ return FALSE;
+
+ /* In mysqld-compatible mode we must ensure that there 'mysqld' instance. */
+
+ mysqld_found= find(&Instance::DFLT_INSTANCE_NAME) != NULL;
+
+ if (mysqld_found)
+ return FALSE;
+
+ if (create_instance(&Instance::DFLT_INSTANCE_NAME, NULL))
+ {
+ log_error("Error: could not create default instance.");
+ return TRUE;
+ }
+
+ switch (create_instance_in_file(&Instance::DFLT_INSTANCE_NAME, NULL))
+ {
+ case 0:
+ case ER_CONF_FILE_DOES_NOT_EXIST:
+ /*
+ Continue if the instance has been added to the config file
+ successfully, or the config file just does not exist.
+ */
+ break;
+
+ default:
+ log_error("Error: could not add default instance to the config file.");
+
+ Instance *instance= find(&Instance::DFLT_INSTANCE_NAME);
+
+ if (instance)
+ remove_instance(instance); /* instance is deleted here. */
+
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -297,10 +478,10 @@ int Instance_map::load()
name and start looking for files named "my.cnf.cnf" in all
default dirs. Which is not what we want.
*/
- if (Options::is_forced_default_file)
+ if (Options::Main::is_forced_default_file)
{
snprintf(defaults_file_arg, FN_REFLEN, "--defaults-file=%s",
- Options::config_file);
+ Options::Main::config_file);
argv_options[1]= defaults_file_arg;
argv_options[2]= '\0';
@@ -314,15 +495,12 @@ int Instance_map::load()
If the routine failed, we'll simply fallback to defaults in
complete_initialization().
*/
- if (my_search_option_files(Options::config_file, &argc,
+ if (my_search_option_files(Options::Main::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;
+ return complete_initialization();
}
@@ -343,3 +521,105 @@ Instance *Instance_map::Iterator::next()
return NULL;
}
+
+const char *Instance_map::get_instance_state_name(Instance *instance)
+{
+ LIST *instance_node;
+
+ if (!instance->is_configured())
+ return "misconfigured";
+
+ if ((instance_node= guardian->find_instance_node(instance)) != NULL)
+ {
+ /* The instance is managed by Guardian: we can report precise state. */
+
+ return Guardian_thread::get_instance_state_name(
+ guardian->get_instance_state(instance_node));
+ }
+
+ /* The instance is not managed by Guardian: we can report status only. */
+
+ return instance->is_running() ? "online" : "offline";
+}
+
+
+/*
+ Create a new configuration section for mysqld-instance in the config file.
+
+ SYNOPSYS
+ create_instance_in_file()
+ instance_name mysqld-instance name
+ options options for the new mysqld-instance
+
+ RETURN
+ 0 On success
+ ER_CONF_FILE_DOES_NOT_EXIST If config file does not exist
+ ER_ACCESS_OPTION_FILE If config file is not writable or some I/O
+ error ocurred during writing configuration
+*/
+
+int create_instance_in_file(const LEX_STRING *instance_name,
+ const Named_value_arr *options)
+{
+ File cnf_file;
+
+ if (my_access(Options::Main::config_file, W_OK))
+ {
+ log_error("Error: configuration file (%s) does not exist.",
+ (const char *) Options::Main::config_file);
+ return ER_CONF_FILE_DOES_NOT_EXIST;
+ }
+
+ cnf_file= my_open(Options::Main::config_file, O_WRONLY | O_APPEND, MYF(0));
+
+ if (cnf_file <= 0)
+ {
+ log_error("Error: can not open configuration file (%s): %s.",
+ (const char *) Options::Main::config_file,
+ (const char *) strerror(errno));
+ return ER_ACCESS_OPTION_FILE;
+ }
+
+ if (my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)"[", 1, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)instance_name->str, instance_name->length,
+ MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)"]", 1, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
+ {
+ log_error("Error: can not write to configuration file (%s): %s.",
+ (const char *) Options::Main::config_file,
+ (const char *) strerror(errno));
+ my_close(cnf_file, MYF(0));
+ return ER_ACCESS_OPTION_FILE;
+ }
+
+ for (int i= 0; options && i < options->get_size(); ++i)
+ {
+ char option_str[MAX_OPTION_STR_LEN];
+ char *ptr;
+ int option_str_len;
+ Named_value option= options->get_element(i);
+
+ ptr= strxnmov(option_str, MAX_OPTION_LEN + 1, option.get_name(), NullS);
+
+ if (option.get_value()[0])
+ ptr= strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
+
+ option_str_len= ptr - option_str;
+
+ if (my_write(cnf_file, (byte*)option_str, option_str_len, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
+ {
+ log_error("Error: can not write to configuration file (%s): %s.",
+ (const char *) Options::Main::config_file,
+ (const char *) strerror(errno));
+ my_close(cnf_file, MYF(0));
+ return ER_ACCESS_OPTION_FILE;
+ }
+ }
+
+ my_close(cnf_file, MYF(0));
+
+ return 0;
+}
diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h
index d3de42f4d80..8e6d2360652 100644
--- a/server-tools/instance-manager/instance_map.h
+++ b/server-tools/instance-manager/instance_map.h
@@ -17,21 +17,24 @@
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 <m_string.h>
#include <hash.h>
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
+class Guardian_thread;
class Instance;
+class Named_value_arr;
+
extern int load_all_groups(char ***groups, const char *filename);
extern void free_groups(char **groups);
+extern int create_instance_in_file(const LEX_STRING *instance_name,
+ const Named_value_arr *options);
+
/*
Instance_map - stores all existing instances
@@ -56,22 +59,64 @@ public:
};
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);
+ /*
+ Return a pointer to the instance or NULL, if there is no such instance.
+ MT-NOTE: must be called under acquired lock.
+ */
+ Instance *find(const LEX_STRING *name);
+ /* Clear the configuration cache and reload the configuration file. */
int flush_instances();
+
+ /* The operation is used to check if there is an active instance or not. */
+ bool is_there_active_instance();
+
void lock();
void unlock();
+
int init();
+
/*
Process a given option and assign it to appropricate instance. This is
required for the option handler, passed to my_search_option_files().
*/
- int process_one_option(const char *group, const char *option);
+ int process_one_option(const LEX_STRING *group, const char *option);
+
+ /*
+ Add an instance into the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int add_instance(Instance *instance);
+
+ /*
+ Remove instance from the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int remove_instance(Instance *instance);
+
+ /*
+ Create a new instance and register it in the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int create_instance(const LEX_STRING *instance_name,
+ const Named_value_arr *options);
Instance_map(const char *default_mysqld_path_arg);
~Instance_map();
+ /*
+ Retrieve client state name of the given instance.
+
+ MT-NOTE: the options must be called under acquired locks of the following
+ objects:
+ - Instance_map;
+ - Guardian_thread;
+ */
+ const char *get_instance_state_name(Instance *instance);
+
public:
const char *mysqld_path;
Guardian_thread *guardian;
@@ -80,7 +125,7 @@ private:
/* loads options from config files */
int load();
/* inits instances argv's after all options have been loaded */
- int complete_initialization();
+ bool complete_initialization();
private:
enum { START_HASH_SIZE = 16 };
pthread_mutex_t LOCK_instance_map;
diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc
index 06a6e1ebc63..b05e40734b7 100644
--- a/server-tools/instance-manager/instance_options.cc
+++ b/server-tools/instance-manager/instance_options.cc
@@ -20,27 +20,24 @@
#include "instance_options.h"
-#include "parse_output.h"
-#include "buffer.h"
-
+#include <my_global.h>
#include <my_sys.h>
-#include <signal.h>
#include <m_string.h>
-#ifdef __WIN__
-#define NEWLINE_LEN 2
-#else
-#define NEWLINE_LEN 1
-#endif
+#include <signal.h>
+
+#include "buffer.h"
+#include "instance.h"
+#include "log.h"
+#include "parse_output.h"
+#include "priv.h"
/* 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)
+ const LEX_STRING *mysqld_path,
+ const LEX_STRING *option)
{
int position= 0;
@@ -49,13 +46,13 @@ static inline int create_mysqld_command(Buffer *buf,
#ifdef __WIN__
buf->append(position++, "\"", 1);
#endif
- buf->append(position, mysqld_path_str, mysqld_path_len);
- position+= mysqld_path_len;
+ buf->append(position, mysqld_path->str, mysqld_path->length);
+ position+= mysqld_path->length;
#ifdef __WIN__
buf->append(position++, "\"", 1);
#endif
/* here the '\0' character is copied from the option string */
- buf->append(position, option, option_len);
+ buf->append(position, option->str, option->length + 1);
return buf->is_error();
}
@@ -63,6 +60,42 @@ static inline int create_mysqld_command(Buffer *buf,
}
+bool Instance_options::is_option_im_specific(const char *option_name)
+{
+ static const char *IM_SPECIFIC_OPTIONS[] =
+ {
+ "nonguarded",
+ "mysqld-path",
+ "shutdown-delay",
+ NULL
+ };
+
+ for (int i= 0; IM_SPECIFIC_OPTIONS[i]; ++i)
+ {
+ if (!strcmp(option_name, IM_SPECIFIC_OPTIONS[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+Instance_options::Instance_options()
+ :mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
+ mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0),
+ nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0),
+ filled_default_options(0)
+{
+ mysqld_path.str= NULL;
+ mysqld_path.length= 0;
+
+ mysqld_real_path.str= NULL;
+ mysqld_real_path.length= 0;
+
+ memset(logs, 0, sizeof(logs));
+}
+
+
/*
Get compiled-in value of default_option
@@ -86,13 +119,13 @@ 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";
+ LEX_STRING verbose_option=
+ { C_STRING_WITH_SIZE(" --no-defaults --verbose --help") };
- /* reserve space fot the path + option + final '\0' */
- Buffer cmd(mysqld_path_len + sizeof(verbose_option));
+ /* reserve space for the path + option + final '\0' */
+ Buffer cmd(mysqld_path.length + verbose_option.length + 1);
- if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
- verbose_option, sizeof(verbose_option)))
+ if (create_mysqld_command(&cmd, &mysqld_path, &verbose_option))
goto err;
/* +2 eats first "--" from the option string (E.g. "--datadir") */
@@ -120,21 +153,19 @@ err:
int Instance_options::fill_instance_version()
{
- enum { MAX_VERSION_STRING_LENGTH= 160 };
- char result[MAX_VERSION_STRING_LENGTH];
- char version_option[]= " --no-defaults --version";
+ char result[MAX_VERSION_LENGTH];
+ LEX_STRING version_option=
+ { C_STRING_WITH_SIZE(" --no-defaults --version") };
int rc= 1;
- Buffer cmd(mysqld_path_len + sizeof(version_option));
+ Buffer cmd(mysqld_path.length + version_option.length + 1);
- if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
- version_option, sizeof(version_option)))
+ if (create_mysqld_command(&cmd, &mysqld_path, &version_option))
goto err;
- bzero(result, MAX_VERSION_STRING_LENGTH);
+ bzero(result, MAX_VERSION_LENGTH);
- rc= parse_output_and_get_value(cmd.buffer, "Ver",
- result, MAX_VERSION_STRING_LENGTH,
- GET_LINE);
+ rc= parse_output_and_get_value(cmd.buffer, "Ver", result,
+ MAX_VERSION_LENGTH, GET_LINE);
if (*result != '\0')
{
@@ -145,9 +176,65 @@ int Instance_options::fill_instance_version()
start= result;
while (my_isspace(default_charset_info, *start))
++start;
+
mysqld_version= strdup_root(&alloc, start);
}
err:
+ if (rc)
+ log_error("fill_instance_version: Failed to get version of '%s'",
+ mysqld_path);
+ return rc;
+}
+
+
+/*
+ Fill mysqld_real_path
+
+ SYNOPSYS
+ fill_mysqld_real_path()
+
+ DESCRIPTION
+
+ Get the real path to mysqld from "mysqld --help" output.
+ Will print the realpath of mysqld between "Usage: " and "[OPTIONS]"
+
+ This is needed if the mysqld_path variable is pointing at a
+ script(for example libtool) or a symlink.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Instance_options::fill_mysqld_real_path()
+{
+ char result[FN_REFLEN];
+ LEX_STRING help_option=
+ { C_STRING_WITH_SIZE(" --no-defaults --help") };
+ int rc= 1;
+ Buffer cmd(mysqld_path.length + help_option.length);
+
+ if (create_mysqld_command(&cmd, &mysqld_path, &help_option))
+ goto err;
+
+ bzero(result, FN_REFLEN);
+
+ rc= parse_output_and_get_value(cmd.buffer, "Usage: ",
+ result, FN_REFLEN,
+ GET_LINE);
+
+ if (*result != '\0')
+ {
+ char* options_str;
+ /* chop the path of at [OPTIONS] */
+ if ((options_str= strstr(result, "[OPTIONS]")))
+ *options_str= '\0';
+ mysqld_real_path.str= strdup_root(&alloc, result);
+ mysqld_real_path.length= strlen(mysqld_real_path.str);
+ }
+err:
+ if (rc)
+ log_error("fill_mysqld_real_path: Failed to get real path of mysqld");
return rc;
}
@@ -200,8 +287,7 @@ int Instance_options::fill_log_options()
else
{
/* below is safe, as --datadir always has a value */
- strmake(datadir,
- strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
+ strmake(datadir, mysqld_datadir, MAX_LOG_OPTION_LENGTH - 1);
}
if (gethostname(hostname,sizeof(hostname)-1) < 0)
@@ -287,7 +373,6 @@ err:
int Instance_options::get_pid_filename(char *result)
{
- const char *pid_file= mysqld_pid_file;
char datadir[MAX_PATH_LEN];
if (mysqld_datadir == NULL)
@@ -297,14 +382,10 @@ int Instance_options::get_pid_filename(char *result)
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;
+ strxnmov(datadir, MAX_PATH_LEN - 1, mysqld_datadir, "/", NullS);
/* get the full path to the pidfile */
- my_load_path(result, pid_file, datadir);
+ my_load_path(result, mysqld_pid_file, datadir);
return 0;
}
@@ -333,23 +414,23 @@ pid_t Instance_options::get_pid()
}
-int Instance_options::complete_initialization(const char *default_path,
- uint instance_type)
+int Instance_options::complete_initialization(const char *default_path)
{
+ int arg_idx;
const char *tmp;
char *end;
- if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path)))
+ if (!mysqld_path.str && !(mysqld_path.str= strdup_root(&alloc, default_path)))
goto err;
// it's safe to cast this to char* since this is a buffer we are allocating
- end= convert_dirname((char*)mysqld_path, mysqld_path, NullS);
+ end= convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS);
end[-1]= 0;
- mysqld_path_len= strlen(mysqld_path);
+ mysqld_path.length= strlen(mysqld_path.str);
if (mysqld_port)
- mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1);
+ mysqld_port_val= atoi(mysqld_port);
if (shutdown_delay)
shutdown_delay_val= atoi(shutdown_delay);
@@ -357,7 +438,7 @@ int Instance_options::complete_initialization(const char *default_path,
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
goto err;
- if (!(mysqld_pid_file))
+ if (!mysqld_pid_file)
{
char pidfilename[MAX_PATH_LEN];
char hostname[MAX_PATH_LEN];
@@ -366,26 +447,27 @@ int Instance_options::complete_initialization(const char *default_path,
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);
+ if (Instance::is_mysqld_compatible_name(&instance_name))
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, hostname, ".pid", NullS);
else
- strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
- "-", hostname, ".pid", NullS);
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, "-",
+ hostname, ".pid", NullS);
}
else
{
- if (instance_type & DEFAULT_SINGLE_INSTANCE)
- strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql",
- ".pid", NullS);
+ if (Instance::is_mysqld_compatible_name(&instance_name))
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, "mysql", ".pid", NullS);
else
- strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
- ".pid", NullS);
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, ".pid",
+ NullS);
}
- add_option(pidfilename);
+ Named_value option((char *) "pid-file", pidfilename);
+
+ set_option(&option);
}
if (get_pid_filename(pid_file_with_path))
@@ -393,22 +475,39 @@ int Instance_options::complete_initialization(const char *default_path,
/* we need to reserve space for the final zero + possible default options */
if (!(argv= (char**)
- alloc_root(&alloc, (options_array.elements + 1
+ alloc_root(&alloc, (get_num_options() + 1
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
goto err;
+ filled_default_options= 0;
/* the path must be first in the argv */
- if (add_to_argv(mysqld_path))
+ if (add_to_argv(mysqld_path.str))
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;
+ arg_idx= filled_default_options;
+ for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
+ {
+ char option_str[MAX_OPTION_STR_LEN];
+ Named_value option= get_option(opt_idx);
+
+ if (is_option_im_specific(option.get_name()))
+ continue;
+
+ char *ptr= strxnmov(option_str, MAX_OPTION_LEN + 3, "--", option.get_name(),
+ NullS);
+
+ if (option.get_value()[0])
+ strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
+
+ argv[arg_idx++]= strdup_root(&alloc, option_str);
+ }
+
+ argv[arg_idx]= 0;
- if (fill_log_options() || fill_instance_version())
+ if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
goto err;
return 0;
@@ -418,75 +517,91 @@ err:
}
-/*
- Assigns given value to the appropriate option from the class.
+bool Instance_options::set_option(Named_value *option)
+{
+ bool err_status;
+ int idx= find_option(option->get_name());
+ char *option_name_str;
+ char *option_value_str;
- SYNOPSYS
- add_option()
- option string with the option prefixed by --
+ if (!(option_name_str= Named_value::alloc_str(option->get_name())))
+ return TRUE;
- DESCRIPTION
+ if (!(option_value_str= Named_value::alloc_str(option->get_value())))
+ {
+ Named_value::free_str(&option_name_str);
+ return TRUE;
+ }
- The method is called from the option handling routine.
+ Named_value option_copy(option_name_str, option_value_str);
- RETURN
- 0 - ok
- 1 - error occured
-*/
+ if (idx < 0)
+ err_status= options.add_element(&option_copy);
+ else
+ err_status= options.replace_element(idx, &option_copy);
+
+ if (!err_status)
+ update_var(option_copy.get_name(), option_copy.get_value());
+ else
+ option_copy.free();
-int Instance_options::add_option(const char* option)
+ return err_status;
+}
+
+
+void Instance_options::unset_option(const char *option_name)
{
- char *tmp;
- enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD };
- struct selected_options_st
+ int idx= find_option(option_name);
+
+ if (idx < 0)
+ return; /* the option has not been set. */
+
+ options.remove_element(idx);
+
+ update_var(option_name, NULL);
+}
+
+
+void Instance_options::update_var(const char *option_name,
+ const char *option_value)
+{
+ struct options_st
{
const char *name;
- uint length;
- const char **value;
- uint type;
- } options[]=
+ uint name_len;
+ const char **var;
+ } options_def[]=
{
- {"--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}
+ {"socket", 6, &mysqld_socket},
+ {"port", 4, &mysqld_port},
+ {"datadir", 7, &mysqld_datadir},
+ {"pid-file", 8, &mysqld_pid_file},
+ {"nonguarded", 10, &nonguarded},
+ {"mysqld-path", 11, (const char **) &mysqld_path.str},
+ {"shutdown-delay", 14, &shutdown_delay},
+ {NULL, 0, NULL}
};
- struct selected_options_st *selected_options;
- if (!(tmp= strdup_root(&alloc, option)))
- goto err;
+ for (options_st *opt= options_def; opt->name; ++opt)
+ {
+ if (!strncmp(opt->name, option_name, opt->name_len))
+ {
+ *(opt->var)= option_value;
+ break;
+ }
+ }
+}
- 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;
- default:
- break;
- }
- }
-
- /* if we haven't returned earlier we should just save the option */
- insert_dynamic(&options_array,(gptr) &tmp);
- return 0;
+int Instance_options::find_option(const char *option_name)
+{
+ for (int i= 0; i < get_num_options(); i++)
+ {
+ if (!strcmp(get_option(i).get_name(), option_name))
+ return i;
+ }
-err:
- return 1;
+ return -1;
}
@@ -504,7 +619,10 @@ int Instance_options::add_to_argv(const char* option)
void Instance_options::print_argv()
{
int i;
- printf("printing out an instance %s argv:\n", instance_name);
+
+ printf("printing out an instance %s argv:\n",
+ (const char *) instance_name.str);
+
for (i=0; argv[i] != NULL; i++)
printf("argv: %s\n", argv[i]);
}
@@ -515,17 +633,17 @@ void Instance_options::print_argv()
Return value: 0 - ok. 1 - unable to allocate memory.
*/
-int Instance_options::init(const char *instance_name_arg)
+int Instance_options::init(const LEX_STRING *instance_name_arg)
{
- instance_name_len= strlen(instance_name_arg);
+ instance_name.length= instance_name_arg->length;
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
- if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
+ if (options.init())
goto err;
- if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
- instance_name_len)))
+ if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
+ instance_name_arg->length)))
goto err;
return 0;
@@ -538,6 +656,4 @@ err:
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
index dae1c2695d1..c3b0a16a40d 100644
--- a/server-tools/instance-manager/instance_options.h
+++ b/server-tools/instance-manager/instance_options.h
@@ -18,8 +18,9 @@
#include <my_global.h>
#include <my_sys.h>
+
#include "parse.h"
-#include "portability.h"
+#include "portability.h" /* for pid_t on Win32 */
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
@@ -35,24 +36,26 @@
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)
- {}
+ /* The operation is used to check if the option is IM-specific or not. */
+ static bool is_option_im_specific(const char *option_name);
+
+public:
+ Instance_options();
~Instance_options();
/* fills in argv */
- int complete_initialization(const char *default_path, uint instance_type);
+ int complete_initialization(const char *default_path);
- int add_option(const char* option);
- int init(const char *instance_name_arg);
+ bool set_option(Named_value *option);
+ void unset_option(const char *option_name);
+
+ inline int get_num_options() const;
+ inline Named_value get_option(int idx) const;
+
+public:
+ int init(const LEX_STRING *instance_name_arg);
pid_t get_pid();
int get_pid_filename(char *result);
int unlink_pidfile();
@@ -65,7 +68,6 @@ public:
*/
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;
/*
@@ -76,31 +78,46 @@ public:
/* 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;
+ LEX_STRING instance_name;
+ LEX_STRING mysqld_path;
+ LEX_STRING mysqld_real_path;
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 fill_mysqld_real_path();
int add_to_argv(const char *option);
int get_default_option(char *result, size_t result_len,
const char *option_name);
+
+ void update_var(const char *option_name, const char *option_value);
+ int find_option(const char *option_name);
+
private:
uint filled_default_options;
MEM_ROOT alloc;
+
+ Named_value_arr options;
};
+
+inline int Instance_options::get_num_options() const
+{
+ return options.get_size();
+}
+
+
+inline Named_value Instance_options::get_option(int idx) const
+{
+ return options.get_element(idx);
+}
+
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */
diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc
index 500b25bec03..da9338e28c5 100644
--- a/server-tools/instance-manager/listener.cc
+++ b/server-tools/instance-manager/listener.cc
@@ -19,21 +19,23 @@
#endif
#include "listener.h"
-#include "priv.h"
-#include <m_string.h>
+
+#include <my_global.h>
#include <mysql.h>
#include <violite.h>
+
+#include <sys/stat.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 "options.h"
#include "portability.h"
+#include "priv.h"
+#include "thread_registry.h"
/*
@@ -62,8 +64,7 @@ private:
Listener_thread::Listener_thread(const Listener_thread_args &args) :
- Listener_thread_args(args.thread_registry, args.options, args.user_map,
- args.instance_map)
+ Listener_thread_args(args.thread_registry, args.user_map, args.instance_map)
,total_connection_count(0)
,thread_info(pthread_self())
,num_sockets(0)
@@ -234,14 +235,16 @@ int Listener_thread::create_tcp_socket()
bzero(&ip_socket_address, sizeof(ip_socket_address));
ulong im_bind_addr;
- if (options.bind_address != 0)
+ if (Options::Main::bind_address != 0)
{
- if ((im_bind_addr= (ulong) inet_addr(options.bind_address)) == INADDR_NONE)
+ im_bind_addr= (ulong) inet_addr(Options::Main::bind_address);
+
+ if (im_bind_addr == INADDR_NONE)
im_bind_addr= htonl(INADDR_ANY);
}
else
im_bind_addr= htonl(INADDR_ANY);
- uint im_port= options.port_number;
+ uint im_port= Options::Main::port_number;
ip_socket_address.sin_family= AF_INET;
ip_socket_address.sin_addr.s_addr= im_bind_addr;
@@ -295,7 +298,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
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,
+ strmake(unix_socket_address.sun_path, Options::Main::socket_file_name,
sizeof(unix_socket_address.sun_path));
unlink(unix_socket_address.sun_path); // in case we have stale socket file
diff --git a/server-tools/instance-manager/listener.h b/server-tools/instance-manager/listener.h
index 28ccbf91731..c28ab0649d7 100644
--- a/server-tools/instance-manager/listener.h
+++ b/server-tools/instance-manager/listener.h
@@ -27,23 +27,19 @@
pthread_handler_t listener(void *arg);
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)
{}
diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc
index 3f54bc0649a..a88344f0b91 100644
--- a/server-tools/instance-manager/log.cc
+++ b/server-tools/instance-manager/log.cc
@@ -14,14 +14,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <my_global.h>
-
#include "log.h"
-#include "portability.h"
-#include <stdarg.h>
+
+#include <my_global.h>
#include <m_string.h>
#include <my_sys.h>
+#include <stdarg.h>
+
+#include "portability.h" /* for vsnprintf() on Windows. */
+
/*
TODO:
- add flexible header support
@@ -71,7 +73,7 @@ static inline void log(FILE *file, const char *format, va_list args)
{
int size= sizeof(buff_stack) * 2;
buff_msg= (char*) my_malloc(size, MYF(0));
- while (true)
+ while (TRUE)
{
if (buff_msg == 0)
{
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 95f9029f648..e2bb09cb9fa 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -14,39 +14,55 @@
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 <my_global.h>
#include <m_string.h>
-#include <signal.h>
+#include <my_sys.h>
#include <thr_alarm.h>
+
+#include <signal.h>
#ifndef __WIN__
#include <sys/wait.h>
#endif
+#include "exit_codes.h"
+#include "guardian.h"
+#include "instance_map.h"
+#include "listener.h"
+#include "log.h"
+#include "options.h"
+#include "priv.h"
+#include "thread_registry.h"
+#include "user_map.h"
+
-static int create_pid_file(const char *pid_file_name)
+int create_pid_file(const char *pid_file_name, int pid)
{
- if (FILE *pid_file= my_fopen(pid_file_name,
- O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
+ FILE *pid_file;
+
+ if (!(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("Error: can not create pid file '%s': %s (errno: %d)",
+ (const char *) pid_file_name,
+ (const char *) strerror(errno),
+ (int) errno);
+ return 1;
}
- log_error("can't create pid file %s: errno=%d, %s",
- pid_file_name, errno, strerror(errno));
- return 1;
+
+ if (fprintf(pid_file, "%d\n", (int) pid) <= 0)
+ {
+ log_error("Error: can not write to pid file '%s': %s (errno: %d)",
+ (const char *) pid_file_name,
+ (const char *) strerror(errno),
+ (int) errno);
+ return 1;
+ }
+
+ my_fclose(pid_file, MYF(0));
+
+ return 0;
}
#ifndef __WIN__
@@ -82,14 +98,14 @@ bool have_signal;
void onsignal(int signo)
{
- have_signal= true;
+ have_signal= TRUE;
}
void set_signals(sigset_t *set)
{
signal(SIGINT, onsignal);
signal(SIGTERM, onsignal);
- have_signal= false;
+ have_signal= FALSE;
}
int my_sigwait(const sigset_t *set, int *sig)
@@ -109,10 +125,16 @@ int my_sigwait(const sigset_t *set, int *sig)
listener thread, write pid file and enter into signal handling.
See also comments in mysqlmanager.cc to picture general Instance Manager
architecture.
+
+ TODO: how about returning error status.
*/
-void manager(const Options &options)
+void manager()
{
+ int err_code;
+ const char *err_msg;
+ bool shutdown_complete= FALSE;
+
Thread_registry thread_registry;
/*
All objects created in the manager() function live as long as
@@ -121,26 +143,60 @@ void manager(const Options &options)
*/
User_map user_map;
- Instance_map instance_map(options.default_mysqld_path);
+ Instance_map instance_map(Options::Main::default_mysqld_path);
Guardian_thread guardian_thread(thread_registry,
&instance_map,
- options.monitoring_interval);
+ Options::Main::monitoring_interval);
- Listener_thread_args listener_args(thread_registry, options, user_map,
- instance_map);
+ Listener_thread_args listener_args(thread_registry, user_map, instance_map);
manager_pid= getpid();
instance_map.guardian= &guardian_thread;
- if (instance_map.init() || user_map.init())
- return;
+ /* Initialize instance map. */
- if (user_map.load(options.password_file_name))
+ if (instance_map.init())
+ {
+ log_error("Error: can not initialize instance list: out of memory.");
return;
+ }
+
+ /* Initialize user map and load password file. */
- /* write pid file */
- if (create_pid_file(options.pid_file_name))
+ if (user_map.init())
+ {
+ log_error("Error: can not initialize user list: out of memory.");
return;
+ }
+
+ if ((err_code= user_map.load(Options::Main::password_file_name, &err_msg)))
+ {
+ if (err_code == ERR_PASSWORD_FILE_DOES_NOT_EXIST &&
+ Options::Main::mysqld_safe_compatible)
+ {
+ /*
+ The password file does not exist, but we are running in
+ mysqld_safe-compatible mode. Continue, but complain in log.
+ */
+
+ log_error("Warning: password file does not exist, "
+ "nobody will be able to connect to Instance Manager.");
+ }
+ else
+ {
+ log_error("Error: %s.", (const char *) err_msg);
+ return;
+ }
+ }
+
+ /* write Instance Manager pid file */
+
+ log_info("IM pid file: '%s'; PID: %d.",
+ (const char *) Options::Main::pid_file_name,
+ (int) manager_pid);
+
+ if (create_pid_file(Options::Main::pid_file_name, manager_pid))
+ return; /* necessary logging has been already done. */
sigset_t mask;
set_signals(&mask);
@@ -193,17 +249,23 @@ void manager(const Options &options)
To work nicely with LinuxThreads, the signal thread is the first thread
in the process.
*/
- int signo;
- bool shutdown_complete;
-
- shutdown_complete= FALSE;
- if (instance_map.flush_instances())
{
- log_error("Cannot init instances repository. This might be caused by "
- "the wrong config file options. For instance, missing mysqld "
- "binary. Aborting.");
- return;
+ instance_map.guardian->lock();
+ instance_map.lock();
+
+ int flush_instances_status= instance_map.flush_instances();
+
+ instance_map.unlock();
+ instance_map.guardian->unlock();
+
+ if (flush_instances_status)
+ {
+ log_error("Cannot init instances repository. This might be caused by "
+ "the wrong config file options. For instance, missing mysqld "
+ "binary. Aborting.");
+ return;
+ }
}
/*
@@ -214,6 +276,7 @@ void manager(const Options &options)
while (!shutdown_complete)
{
+ int signo;
int status= 0;
if ((status= my_sigwait(&mask, &signo)) != 0)
@@ -240,7 +303,7 @@ void manager(const Options &options)
{
if (!guardian_thread.is_stopped())
{
- bool stop_instances= true;
+ bool stop_instances= TRUE;
guardian_thread.request_shutdown(stop_instances);
pthread_cond_signal(&guardian_thread.COND_guardian);
}
@@ -254,7 +317,7 @@ void manager(const Options &options)
err:
/* delete the pid file */
- my_delete(options.pid_file_name, MYF(0));
+ my_delete(Options::Main::pid_file_name, MYF(0));
#ifndef __WIN__
/* free alarm structures */
@@ -262,4 +325,3 @@ err:
/* don't pthread_exit to kill all threads who did not shut down in time */
#endif
}
-
diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h
index 12ed6b3b1ff..7aa4b3e1a96 100644
--- a/server-tools/instance-manager/manager.h
+++ b/server-tools/instance-manager/manager.h
@@ -16,8 +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 */
-struct Options;
+void manager();
-void manager(const Options &options);
+int create_pid_file(const char *pid_file_name, int pid);
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc
index a9b00b9e01f..af35af1e7b0 100644
--- a/server-tools/instance-manager/messages.cc
+++ b/server-tools/instance-manager/messages.cc
@@ -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 */
-#include <my_global.h>
#include "messages.h"
+#include <my_global.h>
+#include <mysql_com.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)
{
@@ -70,6 +69,23 @@ static const char *mysqld_error_message(unsigned sql_errno)
"in the instance options";
case ER_ACCESS_OPTION_FILE:
return "Cannot open the option file to edit. Check permissions";
+ case ER_DROP_ACTIVE_INSTANCE:
+ return "Cannot drop an active instance. You should stop it first";
+ case ER_CREATE_EXISTING_INSTANCE:
+ return "Instance already exists";
+ case ER_INSTANCE_MISCONFIGURED:
+ return "Instance is misconfigured. Cannot start it";
+ case ER_MALFORMED_INSTANCE_NAME:
+ return "Malformed instance name.";
+ case ER_INSTANCE_IS_ACTIVE:
+ return "The instance is active. Stop the instance first";
+ case ER_THERE_IS_ACTIVE_INSTACE:
+ return "At least one instance is active. Stop all instances first";
+ case ER_INCOMPATIBLE_OPTION:
+ return "Instance Manager-specific options are prohibited from being used "
+ "in the configuration of mysqld-compatible instances";
+ case ER_CONF_FILE_DOES_NOT_EXIST:
+ return "Configuration file does not exist";
default:
DBUG_ASSERT(0);
return 0;
diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc
index dcd1807701f..17cda3af704 100644
--- a/server-tools/instance-manager/mysql_connection.cc
+++ b/server-tools/instance-manager/mysql_connection.cc
@@ -20,22 +20,24 @@
#include "mysql_connection.h"
-#include "priv.h"
-#include "mysql_manager_error.h"
-#include "mysqld_error.h"
-#include "thread_registry.h"
+#include <m_string.h>
+#include <m_string.h>
+#include <my_global.h>
+#include <mysql_com.h>
+#include <mysql.h>
+#include <my_sys.h>
+#include <violite.h>
+
+#include "command.h"
#include "log.h"
-#include "user_map.h"
-#include "protocol.h"
#include "messages.h"
-#include "command.h"
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
#include "parse.h"
-
-#include <mysql.h>
-#include <violite.h>
-#include <mysql_com.h>
-#include <m_string.h>
-#include <my_sys.h>
+#include "priv.h"
+#include "protocol.h"
+#include "thread_registry.h"
+#include "user_map.h"
Mysql_connection_thread_args::Mysql_connection_thread_args(
@@ -56,7 +58,7 @@ Mysql_connection_thread_args::Mysql_connection_thread_args(
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,
+ 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().
*/
@@ -190,8 +192,6 @@ void Mysql_connection_thread::run()
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
@@ -202,8 +202,8 @@ int Mysql_connection_thread::check_connection()
char *pos= buff;
ulong server_flags;
- memcpy(pos, mysqlmanager_version, mysqlmanager_version_length + 1);
- pos+= mysqlmanager_version_length + 1;
+ memcpy(pos, mysqlmanager_version.str, mysqlmanager_version.length + 1);
+ pos+= mysqlmanager_version.length + 1;
int4store((uchar*) pos, connection_id);
pos+= 4;
@@ -271,12 +271,14 @@ int Mysql_connection_thread::check_connection()
const char *user= pos;
const char *password= strend(user)+1;
ulong password_len= *password++;
+ LEX_STRING user_name= { (char *) user, password - user - 2 };
+
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))
+ if (user_map.authenticate(&user_name, password, scramble))
{
net_send_error(&net, ER_ACCESS_DENIED_ERROR);
return 1;
@@ -312,7 +314,7 @@ int Mysql_connection_thread::do_command()
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",
+ log_info("connection %d: packet_length=%d, command=%d",
connection_id, packet_length, command);
return dispatch_command(command, packet + 1, packet_length - 1);
}
@@ -336,7 +338,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
if (Command *command= parse_command(&instance_map, packet))
{
int res= 0;
- log_info("query for connection %d successefully parsed",connection_id);
+ log_info("query for connection %d successfully parsed",connection_id);
res= command->execute(&net, connection_id);
delete command;
if (!res)
@@ -380,5 +382,5 @@ pthread_handler_t mysql_connection(void *arg)
}
/*
- vim: fdm=marker
+ vim: fdm=marker
*/
diff --git a/server-tools/instance-manager/mysql_manager_error.h b/server-tools/instance-manager/mysql_manager_error.h
index ff782923a8e..373c7d798a0 100644
--- a/server-tools/instance-manager/mysql_manager_error.h
+++ b/server-tools/instance-manager/mysql_manager_error.h
@@ -29,5 +29,13 @@
#define ER_ACCESS_OPTION_FILE 3008
#define ER_OFFSET_ERROR 3009
#define ER_READ_FILE 3010
+#define ER_DROP_ACTIVE_INSTANCE 3011
+#define ER_CREATE_EXISTING_INSTANCE 3012
+#define ER_INSTANCE_MISCONFIGURED 3013
+#define ER_MALFORMED_INSTANCE_NAME 3014
+#define ER_INSTANCE_IS_ACTIVE 3015
+#define ER_THERE_IS_ACTIVE_INSTACE 3016
+#define ER_INCOMPATIBLE_OPTION 3017
+#define ER_CONF_FILE_DOES_NOT_EXIST 3018
#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
index d0b2cf2666c..177b761b419 100644
--- a/server-tools/instance-manager/mysqlmanager.cc
+++ b/server-tools/instance-manager/mysqlmanager.cc
@@ -15,25 +15,30 @@
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>
+#include <sys/types.h>
+#include <sys/stat.h>
+
#ifndef __WIN__
#include <pwd.h>
#include <grp.h>
#include <sys/wait.h>
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
+
+#include "log.h"
+#include "manager.h"
+#include "options.h"
+#include "user_management_commands.h"
+
#ifdef __WIN__
-#include "windowsservice.h"
+#include "IMService.h"
+#include "WindowsService.h"
#endif
+
/*
Few notes about Instance Manager architecture:
Instance Manager consisits of two processes: the angel process, and the
@@ -59,13 +64,12 @@
*/
static void init_environment(char *progname);
+
#ifndef __WIN__
static void daemonize(const char *log_file_name);
-static void angel(const Options &options);
+static void angel();
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
@@ -81,41 +85,61 @@ int main(int argc, char *argv[])
{
int return_value= 1;
init_environment(argv[0]);
- Options options;
- if (options.load(argc, argv))
- goto err;
+ if ((return_value= Options::load(argc, argv)))
+ goto main_end;
+
+ if (Options::User_management::cmd)
+ {
+ return_value= Options::User_management::cmd->execute();
+
+ goto main_end;
+ }
#ifndef __WIN__
+
struct passwd *user_info;
- if ((user_info= check_user(options.user)))
+ if ((user_info= check_user(Options::Daemon::user)))
{
- if (set_user(options.user, user_info))
- goto err;
+ if (set_user(Options::Daemon::user, user_info))
+ {
+ return_value= 1;
+ goto main_end;
+ }
}
- if (options.run_as_service)
+ if (Options::Daemon::run_as_service)
{
/* forks, and returns only in child */
- daemonize(options.log_file_name);
+ daemonize(Options::Daemon::log_file_name);
/* forks again, and returns only in child: parent becomes angel */
- angel(options);
+ angel();
}
+
+ manager();
+
#else
- if (!options.stand_alone)
+
+ if (!Options::Service::stand_alone)
{
- if (HandleServiceOptions(options))
- goto err;
+ if (HandleServiceOptions())
+ {
+ return_value= 1;
+ goto main_end;
+ }
}
else
+ {
+ manager();
+ }
+
#endif
- manager(options);
return_value= 0;
-err:
- options.cleanup();
+main_end:
+ Options::cleanup();
my_end(0);
return return_value;
}
@@ -200,7 +224,7 @@ static void init_environment(char *progname)
MY_INIT(progname);
log_init();
umask(0117);
- srand(time(0));
+ srand((unsigned int) time(0));
}
@@ -298,7 +322,7 @@ void terminate(int signo)
Angel process will exit silently if mysqlmanager exits normally.
*/
-static void angel(const Options &options)
+static void angel()
{
/* install signal handlers */
sigset_t zeromask; // to sigsuspend in parent
@@ -338,6 +362,14 @@ spawn:
/* Here we return to main, and fall into manager */
break;
default: // parent, success
+ pid= getpid(); /* Get our pid. */
+
+ log_info("Angel pid file: '%s'; PID: %d.",
+ (const char *) Options::Daemon::angel_pid_file_name,
+ (int) pid);
+
+ create_pid_file(Options::Daemon::angel_pid_file_name, pid);
+
while (child_status == CHILD_OK && is_terminated == 0)
sigsuspend(&zeromask);
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc
index 85fea76c079..31ce5b00190 100644
--- a/server-tools/instance-manager/options.cc
+++ b/server-tools/instance-manager/options.cc
@@ -20,70 +20,128 @@
#include "options.h"
-#include "priv.h"
-#include "portability.h"
+#include <my_global.h>
#include <my_sys.h>
#include <my_getopt.h>
-#include <m_string.h>
#include <mysql_com.h>
+#include "exit_codes.h"
+#include "log.h"
+#include "portability.h"
+#include "priv.h"
+#include "user_management_commands.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);
+
+/* Define holders for default values. */
+
+static char win_dflt_config_file_name[FN_REFLEN];
+static char win_dflt_password_file_name[FN_REFLEN];
+static char win_dflt_pid_file_name[FN_REFLEN];
+static char win_dflt_socket_file_name[FN_REFLEN];
+
+static char win_dflt_mysqld_path[FN_REFLEN];
+
+/* Define and initialize Windows-specific options. */
+
+my_bool Options::Service::install_as_service;
+my_bool Options::Service::remove_service;
+my_bool Options::Service::stand_alone;
+
+const char *Options::Main::config_file= win_dflt_config_file_name;
+const char *Options::Main::password_file_name= win_dflt_password_file_name;
+const char *Options::Main::pid_file_name= win_dflt_pid_file_name;
+const char *Options::Main::socket_file_name= win_dflt_socket_file_name;
+
+const char *Options::Main::default_mysqld_path= win_dflt_mysqld_path;
+
+static int setup_windows_defaults();
+
+#else /* UNIX */
+
+/* Define and initialize UNIX-specific options. */
+
+my_bool Options::Daemon::run_as_service= FALSE;
+const char *Options::Daemon::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
+const char *Options::Daemon::user= NULL; /* No default value */
+const char *Options::Daemon::angel_pid_file_name= NULL;
+
+const char *Options::Main::config_file= QUOTE(DEFAULT_CONFIG_FILE);
+const char *
+Options::Main::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
+const char *Options::Main::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
+const char *Options::Main::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
+
+const char *Options::Main::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
+
#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 */
+
+/* Remember if the config file was forced. */
+
+bool Options::Main::is_forced_default_file= FALSE;
+
+/* Define and initialize common options. */
+
+const char *Options::Main::bind_address= NULL; /* No default value */
+uint Options::Main::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
+uint Options::Main::port_number= DEFAULT_PORT;
+my_bool Options::Main::mysqld_safe_compatible= FALSE;
+
+/* Options::User_management */
+
+char *Options::User_management::user_name= NULL;
+char *Options::User_management::password= NULL;
+
+User_management_cmd *Options::User_management::cmd= NULL;
+
+/* Private members. */
+
char **Options::saved_argv= NULL;
-/* Remember if the config file was forced */
-bool Options::is_forced_default_file= 0;
+
#ifndef DBUG_OFF
-const char *Options::default_dbug_option= "d:t:i:O,im.trace";
+const char *Options::Debug::config_str= "d:t:i:O,im.trace";
#endif
+static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid";
+static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX);
+
/*
List of options, accepted by the instance manager.
List must be closed with empty option.
*/
enum options {
+ OPT_PASSWD= 'P',
+ OPT_USERNAME= 'u',
+ OPT_PASSWORD= 'p',
OPT_LOG= 256,
OPT_PID_FILE,
OPT_SOCKET,
OPT_PASSWORD_FILE,
OPT_MYSQLD_PATH,
-#ifndef __WIN__
- OPT_RUN_AS_SERVICE,
- OPT_USER,
-#else
+#ifdef __WIN__
OPT_INSTALL_SERVICE,
OPT_REMOVE_SERVICE,
OPT_STAND_ALONE,
+#else
+ OPT_RUN_AS_SERVICE,
+ OPT_USER,
+ OPT_ANGEL_PID_FILE,
#endif
OPT_MONITORING_INTERVAL,
OPT_PORT,
OPT_WAIT_TIMEOUT,
- OPT_BIND_ADDRESS
+ OPT_BIND_ADDRESS,
+ OPT_ADD_USER,
+ OPT_DROP_USER,
+ OPT_EDIT_USER,
+ OPT_CLEAN_PASSWORD_FILE,
+ OPT_CHECK_PASSWORD_FILE,
+ OPT_LIST_USERS,
+ OPT_MYSQLD_SAFE_COMPATIBLE
};
static struct my_option my_long_options[] =
@@ -91,94 +149,158 @@ 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 },
+ { "add-user", OPT_ADD_USER,
+ "Add a user to the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+#ifndef __WIN__
+ { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.",
+ (gptr *) &Options::Daemon::angel_pid_file_name,
+ (gptr *) &Options::Daemon::angel_pid_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+#endif
+
{ "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
- (gptr *) &Options::bind_address, (gptr *) &Options::bind_address,
+ (gptr *) &Options::Main::bind_address,
+ (gptr *) &Options::Main::bind_address,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "check-password-file", OPT_CHECK_PASSWORD_FILE,
+ "Check the password file for consistency",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "clean-password-file", OPT_CLEAN_PASSWORD_FILE,
+ "Clean the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
#ifndef DBUG_OFF
{"debug", '#', "Debug log.",
- (gptr*) &Options::default_dbug_option, (gptr*) &Options::default_dbug_option,
+ (gptr *) &Options::Debug::config_str,
+ (gptr *) &Options::Debug::config_str,
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{ "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL"
" Server binary.",
- (gptr *) &Options::default_mysqld_path,
- (gptr *) &Options::default_mysqld_path,
+ (gptr *) &Options::Main::default_mysqld_path,
+ (gptr *) &Options::Main::default_mysqld_path,
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "drop-user", OPT_DROP_USER,
+ "Drop existing user from the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "edit-user", OPT_EDIT_USER,
+ "Edit existing user in the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 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,
+ (gptr *) &Options::Service::install_as_service,
+ (gptr *) &Options::Service::install_as_service,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
#endif
+ { "list-users", OPT_LIST_USERS,
+ "Print out a list of registered users",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+#ifndef __WIN__
{ "log", OPT_LOG, "Path to log file. Used only with --run-as-service.",
- (gptr *) &Options::log_file_name, (gptr *) &Options::log_file_name,
+ (gptr *) &Options::Daemon::log_file_name,
+ (gptr *) &Options::Daemon::log_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+#endif
{ "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor"
" instances in seconds.",
- (gptr *) &Options::monitoring_interval,
- (gptr *) &Options::monitoring_interval,
+ (gptr *) &Options::Main::monitoring_interval,
+ (gptr *) &Options::Main::monitoring_interval,
0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
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 },
+ { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE,
+ "Start Instance Manager in mysqld_safe compatible manner",
+ (gptr *) &Options::Main::mysqld_safe_compatible,
+ (gptr *) &Options::Main::mysqld_safe_compatible,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 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,
+ { "passwd", OPT_PASSWD,
+ "Prepare an entry for the password file and exit.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "password", OPT_PASSWORD, "Password to update the password file",
+ (gptr *) &Options::User_management::password,
+ (gptr *) &Options::User_management::password,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "password-file", OPT_PASSWORD_FILE,
+ "Look for Instance Manager users and passwords here.",
+ (gptr *) &Options::Main::password_file_name,
+ (gptr *) &Options::Main::password_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,
+ (gptr *) &Options::Main::pid_file_name,
+ (gptr *) &Options::Main::pid_file_name,
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,
+ (gptr *) &Options::Main::port_number,
+ (gptr *) &Options::Main::port_number,
0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
#ifdef __WIN__
{ "remove", OPT_REMOVE_SERVICE, "Remove system service.",
- (gptr *)&Options::remove_service, (gptr*) &Options::remove_service,
+ (gptr *) &Options::Service::remove_service,
+ (gptr *) &Options::Service::remove_service,
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,
+ "Daemonize and start angel process.",
+ (gptr *) &Options::Daemon::run_as_service,
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
#endif
{ "socket", OPT_SOCKET, "Socket file to use for connection.",
- (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
+ (gptr *) &Options::Main::socket_file_name,
+ (gptr *) &Options::Main::socket_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#ifdef __WIN__
{ "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.",
- (gptr *)&Options::stand_alone, (gptr*) &Options::stand_alone,
+ (gptr *) &Options::Service::stand_alone,
+ (gptr *) &Options::Service::stand_alone,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
#else
{ "user", OPT_USER, "Username to start mysqlmanager",
- (gptr *) &Options::user,
- (gptr *) &Options::user,
+ (gptr *) &Options::Daemon::user,
+ (gptr *) &Options::Daemon::user,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif
+ { "username", OPT_USERNAME,
+ "Username to update the password file",
+ (gptr *) &Options::User_management::user_name,
+ (gptr *) &Options::User_management::user_name,
+ 0, GET_STR, REQUIRED_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-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits "
"for activity on a connection before closing it.",
- (gptr *) &net_read_timeout, (gptr *) &net_read_timeout, 0, GET_ULONG,
- REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 },
+ (gptr *) &net_read_timeout,
+ (gptr *) &net_read_timeout,
+ 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 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,
+ printf("%s Ver %s for %s on %s\n", my_progname,
+ (const char *) mysqlmanager_version.str,
SYSTEM_TYPE, MACHINE_TYPE);
}
@@ -206,37 +328,6 @@ static void usage()
}
-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
@@ -248,16 +339,52 @@ get_one_option(int optid,
case 'V':
version();
exit(0);
- case 'P':
- passwd();
- exit(0);
+ case OPT_PASSWD:
+ case OPT_ADD_USER:
+ case OPT_DROP_USER:
+ case OPT_EDIT_USER:
+ case OPT_CLEAN_PASSWORD_FILE:
+ case OPT_CHECK_PASSWORD_FILE:
+ case OPT_LIST_USERS:
+ if (Options::User_management::cmd)
+ {
+ fprintf(stderr, "Error: only one password-management command "
+ "can be specified at a time.\n");
+ exit(ERR_INVALID_USAGE);
+ }
+
+ switch (optid) {
+ case OPT_PASSWD:
+ Options::User_management::cmd= new Passwd_cmd();
+ break;
+ case OPT_ADD_USER:
+ Options::User_management::cmd= new Add_user_cmd();
+ break;
+ case OPT_DROP_USER:
+ Options::User_management::cmd= new Drop_user_cmd();
+ break;
+ case OPT_EDIT_USER:
+ Options::User_management::cmd= new Edit_user_cmd();
+ break;
+ case OPT_CLEAN_PASSWORD_FILE:
+ Options::User_management::cmd= new Clean_db_cmd();
+ break;
+ case OPT_CHECK_PASSWORD_FILE:
+ Options::User_management::cmd= new Check_db_cmd();
+ break;
+ case OPT_LIST_USERS:
+ Options::User_management::cmd= new List_users_cmd();
+ break;
+ }
+
+ break;
case '?':
usage();
exit(0);
case '#':
#ifndef DBUG_OFF
- DBUG_SET(argument ? argument : Options::default_dbug_option);
- DBUG_SET_INITIAL(argument ? argument : Options::default_dbug_option);
+ DBUG_SET(argument ? argument : Options::Debug::config_str);
+ DBUG_SET_INITIAL(argument ? argument : Options::Debug::config_str);
#endif
break;
}
@@ -283,8 +410,8 @@ int Options::load(int argc, char **argv)
{
if (is_prefix(argv[1], "--defaults-file="))
{
- Options::config_file= strchr(argv[1], '=') + 1;
- Options::is_forced_default_file= 1;
+ Main::config_file= strchr(argv[1], '=') + 1;
+ Main::is_forced_default_file= TRUE;
}
if (is_prefix(argv[1], "--defaults-extra-file=") ||
is_prefix(argv[1], "--no-defaults"))
@@ -293,59 +420,139 @@ int Options::load(int argc, char **argv)
fprintf(stderr, "The --defaults-extra-file and --no-defaults options"
" are not supported by\n"
"Instance Manager. Program aborted.\n");
- goto err;
+ return ERR_INVALID_USAGE;
}
}
#ifdef __WIN__
if (setup_windows_defaults())
- goto err;
+ {
+ fprintf(stderr, "Internal error: could not setup default values.\n");
+ return ERR_OUT_OF_MEMORY;
+ }
#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;
+ log_info("Loading config file '%s'...",
+ (const char *) Main::config_file);
- return 0;
+ load_defaults(Main::config_file, default_groups, &argc, &saved_argv);
+
+ if ((handle_options(&argc, &saved_argv, my_long_options, get_one_option)))
+ return ERR_INVALID_USAGE;
+
+ if (!User_management::cmd &&
+ (User_management::user_name || User_management::password))
+ {
+ fprintf(stderr,
+ "--username and/or --password options have been specified, "
+ "but no password-management command has been given.\n");
+ return ERR_INVALID_USAGE;
+ }
+
+#ifndef __WIN__
+ if (Options::Daemon::run_as_service)
+ {
+ if (Options::Daemon::angel_pid_file_name == NULL)
+ {
+ /*
+ Calculate angel pid file on the IM pid file basis: replace the
+ extension (everything after the last dot) of the pid file basename to
+ '.angel.pid'.
+ */
+
+ char *angel_pid_file_name;
+ char *base_name_ptr;
+ char *ext_ptr;
+
+ angel_pid_file_name=
+ (char *) malloc(strlen(Options::Main::pid_file_name) +
+ ANGEL_PID_FILE_SUFFIX_LEN);
+
+ strcpy(angel_pid_file_name, Options::Main::pid_file_name);
+
+ base_name_ptr= strrchr(angel_pid_file_name, '/');
+
+ if (!base_name_ptr)
+ base_name_ptr= angel_pid_file_name + 1;
+
+ ext_ptr= strrchr(base_name_ptr, '.');
+ if (ext_ptr)
+ *ext_ptr= 0;
+
+ strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX);
-err:
- return 1;
+ Options::Daemon::angel_pid_file_name= angel_pid_file_name;
+ }
+ else
+ {
+ Options::Daemon::angel_pid_file_name=
+ strdup(Options::Daemon::angel_pid_file_name);
+ }
+ }
+#endif
+
+ return 0;
}
void Options::cleanup()
{
- /* free_defaults returns nothing */
- if (Options::saved_argv != NULL)
- free_defaults(Options::saved_argv);
+ if (saved_argv)
+ free_defaults(saved_argv);
+
+ delete User_management::cmd;
+
+#ifndef __WIN__
+ if (Options::Daemon::run_as_service)
+ free((void *) Options::Daemon::angel_pid_file_name);
+#endif
}
#ifdef __WIN__
-int Options::setup_windows_defaults()
+static int 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)))
+ char module_full_name[FN_REFLEN];
+ char dir_name[FN_REFLEN];
+ char base_name[FN_REFLEN];
+ char im_name[FN_REFLEN];
+ char *base_name_ptr;
+ char *ptr;
+
+ /* Determine dirname and basename. */
+
+ if (!GetModuleFileName(NULL, module_full_name, sizeof (module_full_name)) ||
+ !GetFullPathName(module_full_name, sizeof (dir_name), dir_name,
+ &base_name_ptr))
+ {
return 1;
- filename= strstr(default_log_file_name, ".exe");
- strcpy(filename, ".log");
+ }
+
+ strmake(base_name, base_name_ptr, FN_REFLEN);
+ *base_name_ptr= 0;
+
+ strmake(im_name, base_name, FN_REFLEN);
+ ptr= strrchr(im_name, '.');
+
+ if (!ptr)
+ return 1;
+
+ *ptr= 0;
+
+ /* Initialize the defaults. */
+
+ strxmov(win_dflt_config_file_name, dir_name, DFLT_CONFIG_FILE_NAME, NullS);
+ strxmov(win_dflt_mysqld_path, dir_name, DFLT_MYSQLD_PATH, NullS);
+ strxmov(win_dflt_password_file_name, dir_name, im_name, DFLT_PASSWD_FILE_EXT,
+ NullS);
+ strxmov(win_dflt_pid_file_name, dir_name, im_name, DFLT_PID_FILE_EXT, NullS);
+ strxmov(win_dflt_socket_file_name, dir_name, im_name, DFLT_SOCKET_FILE_EXT,
+ NullS);
- if (!GetModuleFileName(NULL, windows_config_file,
- sizeof(windows_config_file)))
- return 1;
- char *slash= strrchr(windows_config_file, '\\');
- strcpy(slash, "\\my.ini");
return 0;
}
diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h
index 06818288606..5c54ff201b2 100644
--- a/server-tools/instance-manager/options.h
+++ b/server-tools/instance-manager/options.h
@@ -17,49 +17,87 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
- Options - all possible options for the instance manager grouped in one
- struct.
+ Options - all possible command-line options for the Instance Manager grouped
+ in one struct.
*/
+
#include <my_global.h>
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
+class User_management_cmd;
+
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 bool is_forced_default_file;
- 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;
+ /*
+ NOTE: handle_options() expects value of my_bool type for GET_BOOL
+ accessor (i.e. bool must not be used).
+ */
- /* argv pointer returned by load_defaults() to be used by free_defaults() */
- static char **saved_argv;
+ struct User_management
+ {
+ static User_management_cmd *cmd;
+
+ static char *user_name;
+ static char *password;
+ };
+
+ struct Main
+ {
+ /* this is not an option parsed by handle_options(). */
+ static bool is_forced_default_file;
+
+ static const char *pid_file_name;
+ static const char *socket_file_name;
+ static const char *password_file_name;
+ static const char *default_mysqld_path;
+ static uint monitoring_interval;
+ static uint port_number;
+ static const char *bind_address;
+ static const char *config_file;
+ static my_bool mysqld_safe_compatible;
+ };
#ifndef DBUG_OFF
- static const char *default_dbug_option;
+ struct Debug
+ {
+ static const char *config_str;
+ };
#endif
- int load(int argc, char **argv);
- void cleanup();
-#ifdef __WIN__
- int setup_windows_defaults();
+#ifndef __WIN__
+
+ struct Daemon
+ {
+ static my_bool run_as_service;
+ static const char *log_file_name;
+ static const char *user;
+ static const char *angel_pid_file_name;
+ };
+
+#else
+
+ struct Service
+ {
+ static my_bool install_as_service;
+ static my_bool remove_service;
+ static my_bool stand_alone;
+ };
+
#endif
+
+public:
+ static int load(int argc, char **argv);
+ static void cleanup();
+
+private:
+ Options(); /* Deny instantiation of this class. */
+
+private:
+ /* argv pointer returned by load_defaults() to be used by free_defaults() */
+ static char **saved_argv;
};
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc
index 14b3db16b45..4e931488fce 100644
--- a/server-tools/instance-manager/parse.cc
+++ b/server-tools/instance-manager/parse.cc
@@ -17,12 +17,12 @@
#include "parse.h"
#include "commands.h"
-#include <string.h>
-
enum Token
{
- TOK_ERROR= 0, /* Encodes the "ERROR" word, it doesn't indicate error. */
+ TOK_CREATE= 0,
+ TOK_DROP,
+ TOK_ERROR, /* Encodes the "ERROR" word, it doesn't indicate error. */
TOK_FILES,
TOK_FLUSH,
TOK_GENERAL,
@@ -50,6 +50,8 @@ struct tokens_st
static struct tokens_st tokens[]= {
+ {6, "CREATE"},
+ {4, "DROP"},
{5, "ERROR"},
{5, "FILES"},
{5, "FLUSH"},
@@ -67,6 +69,37 @@ static struct tokens_st tokens[]= {
{5, "UNSET"}
};
+/************************************************************************/
+
+Named_value_arr::Named_value_arr() :
+ initialized(FALSE)
+{
+}
+
+
+bool Named_value_arr::init()
+{
+ if (my_init_dynamic_array(&arr, sizeof(Named_value), 0, 32))
+ return TRUE;
+
+ initialized= TRUE;
+
+ return FALSE;
+}
+
+
+Named_value_arr::~Named_value_arr()
+{
+ if (!initialized)
+ return;
+
+ for (int i= 0; i < get_size(); ++i)
+ get_element(i).free();
+
+ delete_dynamic(&arr);
+}
+
+/************************************************************************/
/*
Returns token no if word corresponds to some token, otherwise returns
@@ -104,53 +137,200 @@ Token shift_token(const char **text, uint *word_len)
}
-int get_text_id(const char **text, uint *word_len, const char **id)
+int get_text_id(const char **text, LEX_STRING *token)
{
- get_word(text, word_len);
- if (*word_len == 0)
+ get_word(text, &token->length);
+ if (token->length == 0)
return 1;
- *id= *text;
+ token->str= (char *) *text;
return 0;
}
+static bool parse_long(const LEX_STRING *token, long *value)
+{
+ int err_code;
+ char *end_ptr= token->str + token->length;
+
+ *value= my_strtoll10(token->str, &end_ptr, &err_code);
+
+ return err_code != 0;
+}
+
+
+bool parse_option_value(const char *text, uint *text_len, char **value)
+{
+ char beginning_quote;
+ const char *text_start_ptr;
+ char *v;
+ bool escape_mode= FALSE;
+
+ if (!*text || (*text != '\'' && *text != '"'))
+ return TRUE; /* syntax error: string expected. */
+
+ beginning_quote= *text;
+
+ ++text; /* skip the beginning quote. */
+
+ text_start_ptr= text;
+
+ if (!(v= Named_value::alloc_str(text)))
+ return TRUE;
+
+ *value= v;
+
+ while (TRUE)
+ {
+ if (!*text)
+ {
+ Named_value::free_str(value);
+ return TRUE; /* syntax error: missing terminating ' character. */
+ }
+
+ if (*text == '\n' || *text == '\r')
+ {
+ Named_value::free_str(value);
+ return TRUE; /* syntax error: option value should be a single line. */
+ }
+
+ if (!escape_mode && *text == beginning_quote)
+ break;
+
+ if (escape_mode)
+ {
+ switch (*text)
+ {
+ case 'b': /* \b -- backspace */
+ if (v > *value)
+ --v;
+ break;
+
+ case 't': /* \t -- tab */
+ *v= '\t';
+ ++v;
+ break;
+
+ case 'n': /* \n -- newline */
+ *v= '\n';
+ ++v;
+ break;
+
+ case 'r': /* \r -- carriage return */
+ *v= '\r';
+ ++v;
+ break;
+
+ case '\\': /* \\ -- back slash */
+ *v= '\\';
+ ++v;
+ break;
+
+ case 's': /* \s -- space */
+ *v= ' ';
+ ++v;
+ break;
+
+ default: /* Unknown escape sequence. Treat as error. */
+ Named_value::free_str(value);
+ return TRUE;
+ }
+
+ escape_mode= FALSE;
+ }
+ else
+ {
+ if (*text == '\\')
+ {
+ escape_mode= TRUE;
+ }
+ else
+ {
+ *v= *text;
+ ++v;
+ }
+ }
+
+ ++text;
+ }
+
+ *v= 0;
+
+ /* "2" below stands for beginning and ending quotes. */
+ *text_len= text - text_start_ptr + 2;
+
+ return FALSE;
+}
+
+
+void skip_spaces(const char **text)
+{
+ while (**text && my_isspace(default_charset_info, **text))
+ ++(*text);
+}
+
+
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;
+ LEX_STRING instance_name;
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:
+ case TOK_CREATE:
+ case TOK_DROP:
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;
+ instance_name.str= (char *) text;
+ instance_name.length= word_len;
text+= word_len;
- /* it should be the end of command */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
- if (tok1 == TOK_START)
- command= new Start_instance(map, instance_name, instance_name_len);
+ if (tok1 == TOK_CREATE)
+ {
+ Create_instance *cmd= new Create_instance(map, &instance_name);
+
+ if (!cmd)
+ return NULL; /* Report ER_OUT_OF_RESOURCES. */
+
+ if (cmd->init(&text))
+ {
+ delete cmd;
+ goto syntax_error;
+ }
+
+ command= cmd;
+ }
else
- command= new Stop_instance(map, instance_name, instance_name_len);
+ {
+ /* it should be the end of command */
+ get_word(&text, &word_len, NONSPACE);
+ if (word_len)
+ goto syntax_error;
+ }
+
+ switch (tok1) {
+ case TOK_START:
+ command= new Start_instance(map, &instance_name);
+ break;
+ case TOK_STOP:
+ command= new Stop_instance(map, &instance_name);
+ break;
+ case TOK_CREATE:
+ ; /* command already initialized. */
+ break;
+ case TOK_DROP:
+ command= new Drop_instance(map, &instance_name);
+ break;
+ default: /* this is impossible, but nevertheless... */
+ DBUG_ASSERT(0);
+ }
break;
case TOK_FLUSH:
if (shift_token(&text, &word_len) != TOK_INSTANCES)
@@ -163,53 +343,28 @@ Command *parse_command(Instance_map *map, const char *text)
command= new Flush_instances(map);
break;
case TOK_UNSET:
- skip= true;
case TOK_SET:
+ {
+ Abstract_option_cmd *cmd;
- if (get_text_id(&text, &instance_name_len, &instance_name))
- goto syntax_error;
- text+= instance_name_len;
-
- /* the next token should be a dot */
- get_word(&text, &word_len);
- if (*text != '.')
- goto syntax_error;
- text++;
+ if (tok1 == TOK_SET)
+ cmd= new Set_option(map);
+ else
+ cmd= new Unset_option(map);
- get_word(&text, &option_len, NONSPACE);
- option= text;
- if ((tmp= strchr(text, '=')) != NULL)
- option_len= tmp - text;
- text+= option_len;
+ if (!cmd)
+ return NULL; /* Report ER_OUT_OF_RESOURCES. */
- 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;
- }
+ if (cmd->init(&text))
+ {
+ delete cmd;
+ goto syntax_error;
+ }
- /* should be empty */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
+ command= cmd;
- 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;
+ break;
+ }
case TOK_SHOW:
switch (shift_token(&text, &word_len)) {
case TOK_INSTANCES:
@@ -222,30 +377,35 @@ Command *parse_command(Instance_map *map, const char *text)
switch (Token tok2= shift_token(&text, &word_len)) {
case TOK_OPTIONS:
case TOK_STATUS:
- if (get_text_id(&text, &instance_name_len, &instance_name))
+ if (get_text_id(&text, &instance_name))
goto syntax_error;
- text+= instance_name_len;
+ text+= instance_name.length;
/* check that this is the end of the command */
get_word(&text, &word_len, NONSPACE);
if (word_len)
goto syntax_error;
if (tok2 == TOK_STATUS)
- command= new Show_instance_status(map, instance_name,
- instance_name_len);
+ command= new Show_instance_status(map, &instance_name);
else
- command= new Show_instance_options(map, instance_name,
- instance_name_len);
+ command= new Show_instance_options(map, &instance_name);
break;
default:
goto syntax_error;
}
break;
default:
- instance_name= text - word_len;
- instance_name_len= word_len;
- if (instance_name_len)
+ instance_name.str= (char *) text - word_len;
+ instance_name.length= word_len;
+ if (instance_name.length)
{
Log_type log_type;
+
+ long log_size;
+ LEX_STRING log_size_str;
+
+ long log_offset= 0;
+ LEX_STRING log_offset_str= { NULL, 0 };
+
switch (shift_token(&text, &word_len)) {
case TOK_LOG:
switch (Token tok3= shift_token(&text, &word_len)) {
@@ -254,8 +414,7 @@ Command *parse_command(Instance_map *map, const char *text)
/* 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);
+ command= new Show_instance_log_files(map, &instance_name);
break;
case TOK_ERROR:
case TOK_GENERAL:
@@ -275,12 +434,14 @@ Command *parse_command(Instance_map *map, const char *text)
goto syntax_error;
}
/* get the size of the log we want to retrieve */
- if (get_text_id(&text, &word_len, &log_size))
+ if (get_text_id(&text, &log_size_str))
goto syntax_error;
- text+= word_len;
+ text+= log_size_str.length;
+
/* this parameter is required */
- if (!word_len)
+ if (!log_size_str.length)
goto syntax_error;
+
/* the next token should be comma, or nothing */
get_word(&text, &word_len);
switch (*text) {
@@ -290,23 +451,41 @@ Command *parse_command(Instance_map *map, const char *text)
get_word(&text, &word_len);
if (!word_len)
goto syntax_error;
+ log_offset_str.str= (char *) text;
+ log_offset_str.length= word_len;
text+= word_len;
- command= new Show_instance_log(map, instance_name,
- instance_name_len, log_type,
- log_size, text);
get_word(&text, &word_len, NONSPACE);
/* check that this is the end of the command */
if (word_len)
goto syntax_error;
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;
+ }
+
+ /* Parse size parameter. */
+
+ if (parse_long(&log_size_str, &log_size))
+ goto syntax_error;
+
+ if (log_size <= 0)
goto syntax_error;
+
+ /* Parse offset parameter (if specified). */
+
+ if (log_offset_str.length)
+ {
+ if (parse_long(&log_offset_str, &log_offset))
+ goto syntax_error;
+
+ if (log_offset <= 0)
+ goto syntax_error;
}
+
+ command= new Show_instance_log(map, &instance_name,
+ log_type, log_size, log_offset);
break;
default:
goto syntax_error;
diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h
index 3da53e3a61e..ae29c7eb64a 100644
--- a/server-tools/instance-manager/parse.h
+++ b/server-tools/instance-manager/parse.h
@@ -18,6 +18,7 @@
#include <my_global.h>
#include <my_sys.h>
+#include <m_string.h>
class Command;
class Instance_map;
@@ -29,10 +30,148 @@ enum Log_type
IM_LOG_SLOW
};
-Command *parse_command(Instance_map *instance_map, const char *text);
+Command *parse_command(Instance_map *map, const char *text);
+
+bool parse_option_value(const char *text, uint *text_len, char **value);
+
+void skip_spaces(const char **text);
/* define kinds of the word seek method */
-enum { ALPHANUM= 1, NONSPACE };
+enum enum_seek_method { ALPHANUM= 1, NONSPACE, OPTION_NAME };
+
+/************************************************************************/
+
+class Named_value
+{
+public:
+ /*
+ The purpose of these methods is just to have one method for
+ allocating/deallocating memory for strings for Named_value.
+ */
+
+ static inline char *alloc_str(const LEX_STRING *str);
+ static inline char *alloc_str(const char *str);
+ static inline void free_str(char **str);
+
+public:
+ inline Named_value();
+ inline Named_value(char *name_arg, char *value_arg);
+
+ inline char *get_name();
+ inline char *get_value();
+
+ inline void free();
+
+private:
+ char *name;
+ char *value;
+};
+
+inline char *Named_value::alloc_str(const LEX_STRING *str)
+{
+ return my_strndup((const byte *) str->str, str->length, MYF(0));
+}
+
+inline char *Named_value::alloc_str(const char *str)
+{
+ return my_strdup(str, MYF(0));
+}
+
+inline void Named_value::free_str(char **str)
+{
+ my_free(*str, MYF(MY_ALLOW_ZERO_PTR));
+ *str= NULL;
+}
+
+inline Named_value::Named_value()
+ :name(NULL), value(NULL)
+{ }
+
+inline Named_value::Named_value(char *name_arg, char *value_arg)
+ :name(name_arg), value(value_arg)
+{ }
+
+inline char *Named_value::get_name()
+{
+ return name;
+}
+
+inline char *Named_value::get_value()
+{
+ return value;
+}
+
+void Named_value::free()
+{
+ free_str(&name);
+ free_str(&value);
+}
+
+/************************************************************************/
+
+class Named_value_arr
+{
+public:
+ Named_value_arr();
+ ~Named_value_arr();
+
+ bool init();
+
+ inline int get_size() const;
+ inline Named_value get_element(int idx) const;
+ inline void remove_element(int idx);
+ inline bool add_element(Named_value *option);
+ inline bool replace_element(int idx, Named_value *option);
+
+private:
+ bool initialized;
+ DYNAMIC_ARRAY arr;
+};
+
+
+inline int Named_value_arr::get_size() const
+{
+ return arr.elements;
+}
+
+
+inline Named_value Named_value_arr::get_element(int idx) const
+{
+ DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
+
+ Named_value option;
+ get_dynamic((DYNAMIC_ARRAY *) &arr, (gptr) &option, idx);
+
+ return option;
+}
+
+
+inline void Named_value_arr::remove_element(int idx)
+{
+ DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
+
+ get_element(idx).free();
+
+ delete_dynamic_element(&arr, idx);
+}
+
+
+inline bool Named_value_arr::add_element(Named_value *option)
+{
+ return insert_dynamic(&arr, (gptr) option);
+}
+
+
+inline bool Named_value_arr::replace_element(int idx, Named_value *option)
+{
+ DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
+
+ get_element(idx).free();
+
+ return set_dynamic(&arr, (gptr) option, idx);
+}
+
+/************************************************************************/
/*
tries to find next word in the text
@@ -41,7 +180,7 @@ enum { ALPHANUM= 1, NONSPACE };
*/
inline void get_word(const char **text, uint *word_len,
- int seek_method= ALPHANUM)
+ enum_seek_method seek_method= ALPHANUM)
{
const char *word_end;
@@ -51,13 +190,23 @@ inline void get_word(const char **text, uint *word_len,
word_end= *text;
- if (seek_method == ALPHANUM)
+ switch (seek_method) {
+ case ALPHANUM:
while (my_isalnum(default_charset_info, *word_end))
++word_end;
- else
+ break;
+ case NONSPACE:
while (!my_isspace(default_charset_info, *word_end) &&
(*word_end != '\0'))
++word_end;
+ break;
+ case OPTION_NAME:
+ while (my_isalnum(default_charset_info, *word_end) ||
+ *word_end == '-' ||
+ *word_end == '_')
+ ++word_end;
+ break;
+ }
*word_len= word_end - *text;
}
diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc
index 64bb6a6485f..643a50625a1 100644
--- a/server-tools/instance-manager/parse_output.cc
+++ b/server-tools/instance-manager/parse_output.cc
@@ -14,13 +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 */
-#include <my_global.h>
-#include "parse.h"
#include "parse_output.h"
-#include <stdio.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
+
+#include <stdio.h>
+
+#include "parse.h"
#include "portability.h"
diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h
index 6a84fabbf17..b86363a4452 100644
--- a/server-tools/instance-manager/parse_output.h
+++ b/server-tools/instance-manager/parse_output.h
@@ -16,6 +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 */
+#include <my_global.h>
+
#define GET_VALUE 1
#define GET_LINE 2
diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h
index 1a3be5705e3..a76cff58893 100644
--- a/server-tools/instance-manager/portability.h
+++ b/server-tools/instance-manager/portability.h
@@ -16,11 +16,25 @@
/*TODO: fix this */
#define PROTOCOL_VERSION 10
+#define DFLT_CONFIG_FILE_NAME "my.ini"
+#define DFLT_MYSQLD_PATH "mysqld"
+#define DFLT_PASSWD_FILE_EXT ".passwd"
+#define DFLT_PID_FILE_EXT ".pid"
+#define DFLT_SOCKET_FILE_EXT ".sock"
+
typedef int pid_t;
#undef popen
#define popen(A,B) _popen(A,B)
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+
+#else /* ! __WIN__ */
+
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+
#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
index d2d6a3f636c..d3cc52ec638 100644
--- a/server-tools/instance-manager/priv.cc
+++ b/server-tools/instance-manager/priv.cc
@@ -14,10 +14,10 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "priv.h"
+
#include <my_global.h>
#include <mysql_com.h>
-#include "priv.h"
-#include "portability.h"
#if defined(__ia64__) || defined(__ia64)
/*
@@ -43,9 +43,7 @@ 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 LEX_STRING mysqlmanager_version= { C_STRING_WITH_SIZE("1.0-beta") };
const unsigned char protocol_version= PROTOCOL_VERSION;
diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h
index 52d7aa1d23d..0b393c17ac2 100644
--- a/server-tools/instance-manager/priv.h
+++ b/server-tools/instance-manager/priv.h
@@ -16,13 +16,17 @@
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 <m_string.h>
+#include <my_pthread.h>
+
#include <sys/types.h>
-#ifdef __WIN__
-#include "portability.h"
-#else
+
+#ifndef __WIN__
#include <unistd.h>
#endif
-#include "my_pthread.h"
+
+#include "portability.h"
/* IM-wide platform-independent defines */
#define SERVER_DEFAULT_PORT 3306
@@ -31,6 +35,21 @@
/* three-week timeout should be enough */
#define LONG_TIMEOUT ((ulong) 3600L*24L*21L)
+const int MEM_ROOT_BLOCK_SIZE= 512;
+
+/* The maximal length of option name and option value. */
+const int MAX_OPTION_LEN= 1024;
+
+/*
+ The maximal length of whole option string:
+ --<option name>=<option value>
+*/
+const int MAX_OPTION_STR_LEN= 2 + MAX_OPTION_LEN + 1 + MAX_OPTION_LEN + 1;
+
+const int MAX_VERSION_LENGTH= 160;
+
+const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN;
+
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
extern pid_t manager_pid;
@@ -42,8 +61,7 @@ extern pid_t manager_pid;
extern bool linuxthreads;
#endif
-extern const char mysqlmanager_version[];
-extern const int mysqlmanager_version_length;
+extern const LEX_STRING mysqlmanager_version;
/* MySQL client-server protocol version: substituted from configure */
extern const unsigned char protocol_version;
diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc
index 73e07f993ae..4a8c4d0b88d 100644
--- a/server-tools/instance-manager/protocol.cc
+++ b/server-tools/instance-manager/protocol.cc
@@ -163,7 +163,7 @@ int send_fields(struct st_net *net, LIST *fields)
Buffer send_buff;
char small_buff[4];
uint position= 0;
- NAME_WITH_LENGTH *field;
+ LEX_STRING *field;
/* send the number of fileds */
net_store_length(small_buff, (uint) list_length(fields));
@@ -173,7 +173,7 @@ int send_fields(struct st_net *net, LIST *fields)
while (tmp)
{
position= 0;
- field= (NAME_WITH_LENGTH *) tmp->data;
+ field= (LEX_STRING *) tmp->data;
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* catalog name */
@@ -184,9 +184,9 @@ int send_fields(struct st_net *net, LIST *fields)
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* table name alias */
store_to_protocol_packet(&send_buff,
- field->name, &position); /* column name */
+ field->str, &position); /* column name */
store_to_protocol_packet(&send_buff,
- field->name, &position); /* column name alias */
+ field->str, &position); /* column name alias */
send_buff.reserve(position, 12);
if (send_buff.is_error())
goto err;
diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h
index f38eac6b079..2c84ad394b4 100644
--- a/server-tools/instance-manager/protocol.h
+++ b/server-tools/instance-manager/protocol.h
@@ -20,11 +20,6 @@
#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 };
diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc
index 0091d713a91..a424860548d 100644
--- a/server-tools/instance-manager/thread_registry.cc
+++ b/server-tools/instance-manager/thread_registry.cc
@@ -20,11 +20,12 @@
#include "thread_registry.h"
-#include "log.h"
+#include <my_global.h>
+#include <thr_alarm.h>
-#include <assert.h>
#include <signal.h>
-#include <thr_alarm.h>
+
+#include "log.h"
#ifndef __WIN__
@@ -52,7 +53,7 @@ Thread_info::Thread_info(pthread_t thread_id_arg) :
*/
Thread_registry::Thread_registry() :
- shutdown_in_progress(false)
+ shutdown_in_progress(FALSE)
,sigwait_thread_pid(pthread_self())
{
pthread_mutex_init(&LOCK_thread_registry, 0);
@@ -186,7 +187,7 @@ void Thread_registry::deliver_shutdown()
set_timespec(shutdown_time, 1);
pthread_mutex_lock(&LOCK_thread_registry);
- shutdown_in_progress= true;
+ shutdown_in_progress= TRUE;
#ifndef __WIN__
/* to stop reading from the network we need to flush alarm queue */
diff --git a/server-tools/instance-manager/user_management_commands.cc b/server-tools/instance-manager/user_management_commands.cc
new file mode 100644
index 00000000000..03a3f9814e3
--- /dev/null
+++ b/server-tools/instance-manager/user_management_commands.cc
@@ -0,0 +1,406 @@
+#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
+#pragma implementation
+#endif
+
+#include "user_management_commands.h"
+
+#include "exit_codes.h"
+#include "options.h"
+#include "user_map.h"
+
+/*************************************************************************
+ Module-specific (internal) functions.
+*************************************************************************/
+
+/*
+ The function returns user name. The user name is retrieved from command-line
+ options (if specified) or from console.
+
+ NOTE
+ This function must not be used in user-management command implementations.
+ Use get_user_name() instead.
+
+ SYNOPSYS
+ get_user_name_impl()
+
+ RETURN
+ NULL on error
+ valid pointer on success
+*/
+
+static char *get_user_name_impl()
+{
+ static char user_name_buf[1024];
+ char *ptr;
+
+ if (Options::User_management::user_name)
+ return Options::User_management::user_name;
+
+ printf("Enter user name: ");
+ fflush(stdout);
+
+ if (!fgets(user_name_buf, sizeof (user_name_buf), stdin))
+ return NULL;
+
+ if ((ptr= strchr(user_name_buf, '\n')))
+ *ptr= 0;
+
+ if ((ptr= strchr(user_name_buf, '\r')))
+ *ptr= 0;
+
+ return user_name_buf;
+}
+
+
+/*
+ The function is intended to provide user name for user-management
+ operations. It also checks that length of the specified user name is correct
+ (not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
+ wrong.
+
+ SYNOPSYS
+ get_user_name()
+ user_name [OUT] on success contains user name
+
+ RETURN
+ TRUE on error
+ FALSE on success
+*/
+
+static bool get_user_name(LEX_STRING *user_name)
+{
+ char *user_name_str= get_user_name_impl();
+
+ if (!user_name_str)
+ {
+ fprintf(stderr, "Error: unable to read user name from stdin.\n");
+ return TRUE;
+ }
+
+ user_name->str= user_name_str;
+ user_name->length= strlen(user_name->str);
+
+ if (user_name->length == 0)
+ {
+ fprintf(stderr, "Error: user name can not be empty.\n");
+ return TRUE;
+ }
+
+ if (user_name->length > USERNAME_LENGTH)
+ {
+ fprintf(stderr, "Error: user name must not exceed %d characters.\n",
+ (int) USERNAME_LENGTH);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ The function is intended to provide password for user-management operations.
+ The password is retrieved from command-line options (if specified) or from
+ console.
+
+ SYNOPSYS
+ get_password()
+
+ RETURN
+ NULL on error
+ valid pointer on success
+*/
+
+static const char *get_password()
+{
+ if (Options::User_management::password)
+ return Options::User_management::password;
+
+ const char *passwd1= get_tty_password("Enter password: ");
+ const char *passwd2= get_tty_password("Re-type password: ");
+
+ if (strcmp(passwd1, passwd2))
+ {
+ fprintf(stderr, "Error: passwords do not match.\n");
+ return 0;
+ }
+
+ return passwd1;
+}
+
+
+/*
+ Load password file into user map.
+
+ SYNOPSYS
+ load_password_file()
+ user_map target user map
+
+ RETURN
+ See exit_codes.h for possible values.
+*/
+
+static int load_password_file(User_map *user_map)
+{
+ int err_code;
+ const char *err_msg;
+
+ if (user_map->init())
+ {
+ fprintf(stderr, "Error: can not initialize user map.\n");
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ if ((err_code= user_map->load(Options::Main::password_file_name, &err_msg)))
+ fprintf(stderr, "Error: %s.\n", (const char *) err_msg);
+
+ return err_code;
+}
+
+
+/*
+ Save user map into password file.
+
+ SYNOPSYS
+ save_password_file()
+ user_map user map
+
+ RETURN
+ See exit_codes.h for possible values.
+*/
+
+static int save_password_file(User_map *user_map)
+{
+ int err_code;
+ const char *err_msg;
+
+ if ((err_code= user_map->save(Options::Main::password_file_name, &err_msg)))
+ fprintf(stderr, "Error: %s.\n", (const char *) err_msg);
+
+ return err_code;
+}
+
+/*************************************************************************
+ Passwd_cmd
+*************************************************************************/
+
+int Passwd_cmd::execute()
+{
+ LEX_STRING user_name;
+ const char *password;
+
+ printf("Creating record for new user.\n");
+
+ if (get_user_name(&user_name))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ {
+ User user(&user_name, password);
+
+ printf("%s:%s\n",
+ (const char *) user.user,
+ (const char *) user.scrambled_password);
+ }
+
+ return ERR_OK;
+}
+
+
+/*************************************************************************
+ Add_user_cmd
+*************************************************************************/
+
+int Add_user_cmd::execute()
+{
+ LEX_STRING user_name;
+ const char *password;
+
+ User_map user_map;
+ User *new_user;
+
+ int err_code;
+
+ if (get_user_name(&user_name))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ /* Load the password file. */
+
+ if ((err_code= load_password_file(&user_map)) != ERR_OK)
+ return err_code;
+
+ /* Check that the user does not exist. */
+
+ if (user_map.find_user(&user_name))
+ {
+ fprintf(stderr, "Error: user '%s' already exists.\n",
+ (const char *) user_name.str);
+ return ERR_USER_ALREADY_EXISTS;
+ }
+
+ /* Add the user. */
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ if (!(new_user= new User(&user_name, password)))
+ return ERR_OUT_OF_MEMORY;
+
+ if (user_map.add_user(new_user))
+ {
+ delete new_user;
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ /* Save the password file. */
+
+ return save_password_file(&user_map);
+}
+
+
+/*************************************************************************
+ Drop_user_cmd
+*************************************************************************/
+
+int Drop_user_cmd::execute()
+{
+ LEX_STRING user_name;
+
+ User_map user_map;
+ User *user;
+
+ int err_code;
+
+ if (get_user_name(&user_name))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ /* Load the password file. */
+
+ if ((err_code= load_password_file(&user_map)) != ERR_OK)
+ return err_code;
+
+ /* Find the user. */
+
+ user= user_map.find_user(&user_name);
+
+ if (!user)
+ {
+ fprintf(stderr, "Error: user '%s' does not exist.\n",
+ (const char *) user_name.str);
+ return ERR_USER_NOT_FOUND;
+ }
+
+ /* Remove the user (ignore possible errors). */
+
+ user_map.remove_user(user);
+
+ /* Save the password file. */
+
+ return save_password_file(&user_map);
+}
+
+
+/*************************************************************************
+ Edit_user_cmd
+*************************************************************************/
+
+int Edit_user_cmd::execute()
+{
+ LEX_STRING user_name;
+ const char *password;
+
+ User_map user_map;
+ User *user;
+
+ int err_code;
+
+ if (get_user_name(&user_name))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ /* Load the password file. */
+
+ if ((err_code= load_password_file(&user_map)) != ERR_OK)
+ return err_code;
+
+ /* Find the user. */
+
+ user= user_map.find_user(&user_name);
+
+ if (!user)
+ {
+ fprintf(stderr, "Error: user '%s' does not exist.\n",
+ (const char *) user_name.str);
+ return ERR_USER_NOT_FOUND;
+ }
+
+ /* Modify user's password. */
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ user->set_password(password);
+
+ /* Save the password file. */
+
+ return save_password_file(&user_map);
+}
+
+
+/*************************************************************************
+ Clean_db_cmd
+*************************************************************************/
+
+int Clean_db_cmd::execute()
+{
+ User_map user_map;
+
+ if (user_map.init())
+ {
+ fprintf(stderr, "Error: can not initialize user map.\n");
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ return save_password_file(&user_map);
+}
+
+
+/*************************************************************************
+ Check_db_cmd
+*************************************************************************/
+
+int Check_db_cmd::execute()
+{
+ User_map user_map;
+
+ return load_password_file(&user_map);
+}
+
+
+/*************************************************************************
+ List_users_cmd
+*************************************************************************/
+
+int List_users_cmd::execute()
+{
+ User_map user_map;
+
+ int err_code;
+
+ /* Load the password file. */
+
+ if ((err_code= load_password_file(&user_map)))
+ return err_code;
+
+ /* Print out registered users. */
+
+ {
+ User_map::Iterator it(&user_map);
+ User *user;
+
+ while ((user= it.next()))
+ fprintf(stderr, "%s\n", (const char *) user->user);
+ }
+
+ return ERR_OK;
+}
diff --git a/server-tools/instance-manager/user_management_commands.h b/server-tools/instance-manager/user_management_commands.h
new file mode 100644
index 00000000000..4bf3546f0a6
--- /dev/null
+++ b/server-tools/instance-manager/user_management_commands.h
@@ -0,0 +1,167 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
+
+/*
+ Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 header contains declarations of classes inteded to support
+ user-management commands (such as add user, get list of users, etc).
+
+ The general idea is to have one interface (pure abstract class) for such a
+ command. Each concrete user-management command is implemented in concrete
+ class, derived from the common interface.
+*/
+
+#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
+#pragma interface
+#endif
+
+/*************************************************************************
+ User_management_cmd -- base class for User-management commands.
+*************************************************************************/
+
+class User_management_cmd
+{
+public:
+ User_management_cmd()
+ { }
+
+ virtual ~User_management_cmd()
+ { }
+
+public:
+ /*
+ Executes user-management command.
+
+ SYNOPSYS
+ execute()
+
+ RETURN
+ See exit_codes.h for possible values.
+ */
+
+ virtual int execute() = 0;
+};
+
+
+/*************************************************************************
+ Passwd_cmd: support for --passwd command-line option.
+*************************************************************************/
+
+class Passwd_cmd : public User_management_cmd
+{
+public:
+ Passwd_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ Add_user_cmd: support for --add-user command-line option.
+*************************************************************************/
+
+class Add_user_cmd : public User_management_cmd
+{
+public:
+ Add_user_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ Drop_user_cmd: support for --drop-user command-line option.
+*************************************************************************/
+
+class Drop_user_cmd : public User_management_cmd
+{
+public:
+ Drop_user_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ Edit_user_cmd: support for --edit-user command-line option.
+*************************************************************************/
+
+class Edit_user_cmd : public User_management_cmd
+{
+public:
+ Edit_user_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ Clean_db_cmd: support for --clean-db command-line option.
+*************************************************************************/
+
+class Clean_db_cmd : public User_management_cmd
+{
+public:
+ Clean_db_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ Check_db_cmd: support for --check-db command-line option.
+*************************************************************************/
+
+class Check_db_cmd : public User_management_cmd
+{
+public:
+ Check_db_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+
+/*************************************************************************
+ List_users_cmd: support for --list-users command-line option.
+*************************************************************************/
+
+class List_users_cmd : public User_management_cmd
+{
+public:
+ List_users_cmd()
+ { }
+
+public:
+ virtual int execute();
+};
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc
index 9cb15307131..e8128cf015b 100644
--- a/server-tools/instance-manager/user_map.cc
+++ b/server-tools/instance-manager/user_map.cc
@@ -19,32 +19,32 @@
#endif
#include "user_map.h"
-
-#include <mysql_com.h>
-#include <m_string.h>
-
+#include "exit_codes.h"
#include "log.h"
+#include "portability.h"
-struct User
+User::User(const LEX_STRING *user_name_arg, const char *password)
{
- char user[USERNAME_LENGTH + 1];
- uint8 user_length;
- uint8 salt[SCRAMBLE_LENGTH];
- int init(const char *line);
-};
+ user_length= strmake(user, user_name_arg->str, USERNAME_LENGTH + 1) - user;
+ set_password(password);
+}
int User::init(const char *line)
{
const char *name_begin, *name_end, *password;
- int line_ending_len= 1;
+ int password_length;
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;
+ {
+ log_info("Error: invalid format (unmatched quote) of user line (%s).",
+ (const char *) line);
+ return 1;
+ }
password= name_end + 2;
}
else
@@ -52,33 +52,47 @@ int User::init(const char *line)
name_begin= line;
name_end= strchr(name_begin, ':');
if (name_end == 0)
- goto err;
+ {
+ log_info("Error: invalid format (no delimiter) of user line (%s).",
+ (const char *) line);
+ return 1;
+ }
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) != (uint) (SCRAMBLED_PASSWORD_CHAR_LENGTH +
- line_ending_len))
- goto err;
+ {
+ log_info("Error: user name is too long (%d). Max length: %d. "
+ "User line: '%s'.",
+ (int) user_length,
+ (int) USERNAME_LENGTH,
+ (const char *) line);
+ return 1;
+ }
+
+ password_length= strlen(password);
+ if (password_length > SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ {
+ log_info("Error: password is too long (%d). Max length: %d. ",
+ "User line: '%s'.",
+ (int) password_length,
+ (int) SCRAMBLED_PASSWORD_CHAR_LENGTH,
+ (const char *) line);
+ return 1;
+ }
memcpy(user, name_begin, user_length);
user[user_length]= 0;
+
+ memcpy(scrambled_password, password, password_length);
+ scrambled_password[password_length]= 0;
+
get_salt_from_password(salt, password);
- log_info("loaded user %s", user);
+
+ log_info("loaded user '%s'.", user);
return 0;
-err:
- log_error("error parsing user and password at line %s", line);
- return 1;
}
@@ -101,30 +115,70 @@ static void delete_user(void *u)
C_MODE_END
+void User_map::Iterator::reset()
+{
+ cur_idx= 0;
+}
+
+
+User *User_map::Iterator::next()
+{
+ if (cur_idx < user_map->hash.records)
+ return (User *) hash_element(&user_map->hash, cur_idx++);
+
+ return NULL;
+}
+
+
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;
+
+ initialized= TRUE;
+
return 0;
}
+User_map::User_map()
+ :initialized(FALSE)
+{
+}
+
+
User_map::~User_map()
{
- hash_free(&hash);
+ if (initialized)
+ 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
+ Load password database.
+
+ SYNOPSYS
+ load()
+ password_file_name [IN] password file path
+ err_msg [OUT] error message
+
+ DESCRIPTION
+ 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 specific error code.
+
+ RETURN
+ 0 on success
+ !0 on error
*/
-int User_map::load(const char *password_file_name)
+int User_map::load(const char *password_file_name, const char **err_msg)
{
+ static const int ERR_MSG_BUF_SIZE = 255;
+ static char err_msg_buf[ERR_MSG_BUF_SIZE];
+
FILE *file;
char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
2 + /* for possible quotes */
@@ -134,33 +188,172 @@ int User_map::load(const char *password_file_name)
User *user;
int rc= 1;
+ if (my_access(password_file_name, F_OK) != 0)
+ {
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "password file (%s) does not exist",
+ (const char *) password_file_name);
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_PASSWORD_FILE_DOES_NOT_EXIST;
+ }
+
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;
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "can not open password file (%s): %s",
+ (const char *) password_file_name,
+ (const char *) strerror(errno));
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_IO_ERROR;
}
+ log_info("loading the password database...");
+
while (fgets(line, sizeof(line), file))
{
+ char *user_line= line;
+
+ /*
+ We need to skip EOL-symbols also from the beginning of the line, because
+ if the previous line was ended by \n\r sequence, we get \r in our line.
+ */
+
+ while (user_line[0] == '\r' || user_line[0] == '\n')
+ ++user_line;
+
+ /* Skip EOL-symbols in the end of the line. */
+
+ {
+ char *ptr;
+
+ if ((ptr= strchr(user_line, '\n')))
+ *ptr= 0;
+
+ if ((ptr= strchr(user_line, '\r')))
+ *ptr= 0;
+ }
+
/* skip comments and empty lines */
- if (line[0] == '#' || line[0] == '\n' &&
- (line[1] == '\0' || line[1] == '\r'))
+ if (!user_line[0] || user_line[0] == '#')
continue;
+
if ((user= new User) == 0)
- goto done;
- if (user->init(line) || my_hash_insert(&hash, (byte *) user))
- goto err_init_user;
+ {
+ my_fclose(file, MYF(0));
+
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "out of memory while parsing password file (%s)",
+ (const char *) password_file_name);
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ if (user->init(user_line))
+ {
+ delete user;
+ my_fclose(file, MYF(0));
+
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "password file (%s) corrupted",
+ (const char *) password_file_name);
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_PASSWORD_FILE_CORRUPTED;
+ }
+
+ if (my_hash_insert(&hash, (byte *) user))
+ {
+ delete user;
+ my_fclose(file, MYF(0));
+
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "out of memory while parsing password file (%s)",
+ (const char *) password_file_name);
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_OUT_OF_MEMORY;
+ }
}
- if (feof(file))
- rc= 0;
- goto done;
-err_init_user:
- delete user;
-done:
+
+ log_info("the password database loaded successfully.");
+
my_fclose(file, MYF(0));
- return rc;
+
+ if (err_msg)
+ *err_msg= NULL;
+
+ return ERR_OK;
+}
+
+
+int User_map::save(const char *password_file_name, const char **err_msg)
+{
+ static const int ERR_MSG_BUF_SIZE = 255;
+ static char err_msg_buf[ERR_MSG_BUF_SIZE];
+
+ FILE *file;
+
+ if ((file= my_fopen(password_file_name, O_WRONLY | O_TRUNC | O_BINARY,
+ MYF(0))) == 0)
+ {
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "can not open password file (%s) for writing: %s",
+ (const char *) password_file_name,
+ (const char *) strerror(errno));
+ *err_msg= err_msg_buf;
+ }
+
+ return ERR_IO_ERROR;
+ }
+
+ {
+ User_map::Iterator it(this);
+ User *user;
+
+ while ((user= it.next()))
+ {
+ if (fprintf(file, "%s:%s\n", (const char *) user->user,
+ (const char *) user->scrambled_password) < 0)
+ {
+ if (err_msg)
+ {
+ snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
+ "can not write to password file (%s): %s",
+ (const char *) password_file_name,
+ (const char *) strerror(errno));
+ *err_msg= err_msg_buf;
+ }
+
+ my_fclose(file, MYF(0));
+
+ return ERR_IO_ERROR;
+ }
+ }
+ }
+
+ my_fclose(file, MYF(0));
+
+ return ERR_OK;
}
@@ -172,13 +365,33 @@ done:
2 - user not found
*/
-int User_map::authenticate(const char *user_name, uint length,
+int User_map::authenticate(const LEX_STRING *user_name,
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;
+ const User *user= find_user(user_name);
+ return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
+}
+
+
+User *User_map::find_user(const LEX_STRING *user_name)
+{
+ return (User*) hash_search(&hash, (byte*) user_name->str, user_name->length);
+}
+
+const User *User_map::find_user(const LEX_STRING *user_name) const
+{
+ return const_cast<User_map *> (this)->find_user(user_name);
+}
+
+
+bool User_map::add_user(User *user)
+{
+ return my_hash_insert(&hash, (byte*) user) == 0 ? FALSE : TRUE;
+}
+
+
+bool User_map::remove_user(User *user)
+{
+ return hash_delete(&hash, (byte*) user) == 0 ? FALSE : TRUE;
}
diff --git a/server-tools/instance-manager/user_map.h b/server-tools/instance-manager/user_map.h
index 4134017dd9b..de207c11e65 100644
--- a/server-tools/instance-manager/user_map.h
+++ b/server-tools/instance-manager/user_map.h
@@ -18,14 +18,35 @@
#include <my_global.h>
-
#include <my_sys.h>
+#include <mysql_com.h>
+#include <m_string.h>
#include <hash.h>
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
+struct User
+{
+ User()
+ {}
+
+ User(const LEX_STRING *user_name_arg, const char *password);
+
+ int init(const char *line);
+
+ inline void set_password(const char *password)
+ {
+ make_scrambled_password(scrambled_password, password);
+ }
+
+ char user[USERNAME_LENGTH + 1];
+ char scrambled_password[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+ uint8 user_length;
+ uint8 salt[SCRAMBLE_LENGTH];
+};
+
/*
User_map -- all users and passwords
*/
@@ -33,15 +54,51 @@
class User_map
{
public:
+ /* User_map iterator */
+
+ class Iterator
+ {
+ public:
+ Iterator(User_map *user_map_arg) :
+ cur_idx(0), user_map(user_map_arg)
+ { }
+
+ public:
+ void reset();
+
+ User *next();
+
+ private:
+ User_map *user_map;
+ uint cur_idx;
+ };
+
+public:
+ User_map();
~User_map();
int init();
- int load(const char *password_file_name);
- int authenticate(const char *user_name, uint length,
+ int load(const char *password_file_name, const char **err_msg);
+ int save(const char *password_file_name, const char **err_msg);
+ int authenticate(const LEX_STRING *user_name,
const char *scrambled_password,
const char *scramble) const;
+
+ const User *find_user(const LEX_STRING *user_name) const;
+ User *find_user(const LEX_STRING *user_name);
+
+ bool add_user(User *user);
+ bool remove_user(User *user);
+
+private:
+ User_map(const User_map &);
+ User_map &operator =(const User_map &);
+
private:
HASH hash;
+ bool initialized;
+
+ friend class Iterator;
};
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
diff --git a/sql-common/client.c b/sql-common/client.c
index 32672ce1201..08d87f9d083 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1495,6 +1495,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
mysql->options.ssl_ca= strdup_if_not_null(ca);
mysql->options.ssl_capath= strdup_if_not_null(capath);
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
+ mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */
#endif /* HAVE_OPENSSL */
DBUG_RETURN(0);
}
@@ -1509,17 +1510,16 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
{
- struct st_VioSSLConnectorFd *st=
- (struct st_VioSSLConnectorFd*) mysql->connector_fd;
+ struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd;
DBUG_ENTER("mysql_ssl_free");
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
- if (st)
- SSL_CTX_free(st->ssl_context);
+ my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
+ if (ssl_fd)
+ SSL_CTX_free(ssl_fd->ssl_context);
my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
mysql->options.ssl_key = 0;
mysql->options.ssl_cert = 0;
@@ -1551,6 +1551,77 @@ mysql_get_ssl_cipher(MYSQL *mysql)
DBUG_RETURN(NULL);
}
+
+/*
+ Check the server's (subject) Common Name against the
+ hostname we connected to
+
+ SYNOPSIS
+ ssl_verify_server_cert()
+ vio pointer to a SSL connected vio
+ server_hostname name of the server that we connected to
+
+ RETURN VALUES
+ 0 Success
+ 1 Failed to validate server
+
+ */
+static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
+{
+ SSL *ssl;
+ X509 *server_cert;
+ char *cp1, *cp2;
+ char buf[256];
+ DBUG_ENTER("ssl_verify_server_cert");
+ DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
+
+ if (!(ssl= (SSL*)vio->ssl_arg))
+ {
+ DBUG_PRINT("error", ("No SSL pointer found"));
+ DBUG_RETURN(1);
+ }
+
+ if (!server_hostname)
+ {
+ DBUG_PRINT("error", ("No server hostname supplied"));
+ DBUG_RETURN(1);
+ }
+
+ if (!(server_cert= SSL_get_peer_certificate(ssl)))
+ {
+ DBUG_PRINT("error", ("Could not get server certificate"));
+ DBUG_RETURN(1);
+ }
+
+ /*
+ We already know that the certificate exchanged was valid; the SSL library
+ handled that. Now we need to verify that the contents of the certificate
+ are what we expect.
+ */
+
+ X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf));
+ X509_free (server_cert);
+
+ DBUG_PRINT("info", ("hostname in cert: %s", buf));
+ cp1= strstr(buf, "/CN=");
+ if (cp1)
+ {
+ cp1+= 4; /* Skip the "/CN=" that we found */
+ /* Search for next / which might be the delimiter for email */
+ cp2= strchr(cp1, '/');
+ if (cp2)
+ *cp2= '\0';
+ DBUG_PRINT("info", ("Server hostname in cert: %s", cp1));
+ if (!strcmp(cp1, server_hostname))
+ {
+ /* Success */
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_PRINT("error", ("SSL certificate validation failure"));
+ DBUG_RETURN(1);
+}
+
#endif /* HAVE_OPENSSL */
@@ -1584,7 +1655,6 @@ static MYSQL_METHODS client_methods=
#endif
};
-
MYSQL *
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
@@ -2029,37 +2099,52 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->client_flag=client_flag;
#ifdef HAVE_OPENSSL
- /*
- Oops.. are we careful enough to not send ANY information without
- encryption?
- */
if (client_flag & CLIENT_SSL)
{
+ /* Do the SSL layering. */
struct st_mysql_options *options= &mysql->options;
+ struct st_VioSSLFd *ssl_fd;
+
+ /*
+ Send client_flag, max_packet_size - unencrypted otherwise
+ the server does not know we want to do SSL
+ */
if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net))
{
set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error;
}
- /* Do the SSL layering. */
- if (!(mysql->connector_fd=
- (gptr) new_VioSSLConnectorFd(options->ssl_key,
- options->ssl_cert,
- options->ssl_ca,
- options->ssl_capath,
- options->ssl_cipher)))
+
+ /* Create the VioSSLConnectorFd - init SSL and load certs */
+ if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
+ options->ssl_cert,
+ options->ssl_ca,
+ options->ssl_capath,
+ options->ssl_cipher)))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
+ mysql->connector_fd= (void*)ssl_fd;
+
+ /* Connect to the server */
DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
- mysql->net.vio, (long) (mysql->options.connect_timeout)))
+ if (sslconnect(ssl_fd, mysql->net.vio,
+ (long) (mysql->options.connect_timeout)))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
DBUG_PRINT("info", ("IO layer change done!"));
+
+ /* Verify server cert */
+ if (mysql->options.ssl_verify_server_cert &&
+ ssl_verify_server_cert(mysql->net.vio, mysql->host))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+
}
#endif /* HAVE_OPENSSL */
@@ -2799,6 +2884,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_OPT_RECONNECT:
mysql->reconnect= *(my_bool *) arg;
break;
+ case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+ mysql->options.ssl_verify_server_cert= *(my_bool *) arg;
+ break;
default:
DBUG_RETURN(1);
}
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index c9d39260761..f75298e4f5d 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -689,7 +689,7 @@ long calc_daynr(uint year,uint month,uint day)
if (year == 0 && month == 0 && day == 0)
DBUG_RETURN(0); /* Skip errors */
- if (year < 200)
+ if (year < YY_MAGIC_BELOW)
{
if ((year=year+1900) < 1900+YY_PART_YEAR)
year+=100;
diff --git a/sql/cmakelists.txt b/sql/CMakeLists.txt
index 381d22c605c..2b44fbdcc79 100644
--- a/sql/cmakelists.txt
+++ b/sql/CMakeLists.txt
@@ -16,7 +16,7 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/message.rc
${CMAKE_SOURCE_DIR}/sql/sql_yacc.h
${CMAKE_SOURCE_DIR}/sql/sql_yacc.cc
${CMAKE_SOURCE_DIR}/include/mysql_version.h
- ${CMAKE_SOURCE_DIR}/sql/handlerton.cc
+ ${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc
${CMAKE_SOURCE_DIR}/sql/lex_hash.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
${PROJECT_SOURCE_DIR}/include/mysqld_ername.h
@@ -29,7 +29,8 @@ ADD_DEFINITIONS(-DHAVE_ROW_BASED_REPLICATION -DMYSQL_SERVER
ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
filesort.cc gstream.cc ha_heap.cc ha_myisam.cc ha_myisammrg.cc
- ${mysql_se_ha_src} handler.cc hash_filo.cc hash_filo.h
+ ha_innodb.cc ha_partition.cc ha_federated.cc ha_berkeley.cc
+ handler.cc hash_filo.cc hash_filo.h
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
item_create.cc item_func.cc item_geofunc.cc item_row.cc
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
@@ -50,7 +51,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc
- rpl_tblmap.cc sql_binlog.cc event_executor.cc event_timed.cc
+ rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc
sql_tablespace.cc event.cc ../sql-common/my_user.c
partition_info.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
@@ -59,13 +60,19 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
${PROJECT_SOURCE_DIR}/include/mysqld_ername.h
${PROJECT_SOURCE_DIR}/include/sql_state.h
${PROJECT_SOURCE_DIR}/include/mysql_version.h
- ${PROJECT_SOURCE_DIR}/sql/handlerton.cc
+ ${PROJECT_SOURCE_DIR}/sql/sql_builtin.cc
${PROJECT_SOURCE_DIR}/sql/lex_hash.h)
TARGET_LINK_LIBRARIES(mysqld heap myisam myisammrg mysys yassl zlib dbug yassl
taocrypt strings vio regex wsock32)
IF(WITH_ARCHIVE_STORAGE_ENGINE)
TARGET_LINK_LIBRARIES(mysqld archive)
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
+IF(WITH_BLACKHOLE_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld blackhole)
+ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
+IF(WITH_CSV_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld csv)
+ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
TARGET_LINK_LIBRARIES(mysqld example)
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 60e7891931f..7f711a1e212 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -30,10 +30,7 @@ libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
- $(top_builddir)/storage/myisammrg/libmyisammrg.a \
- $(top_builddir)/storage/heap/libheap.a \
- $(top_builddir)/vio/libvio.a \
+LDADD = $(top_builddir)/vio/libvio.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/regex/libregex.a \
@@ -41,7 +38,7 @@ LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
@pstack_libs@ \
- @mysql_se_objs@ @mysql_se_libs@ \
+ @mysql_plugin_libs@ \
$(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \
@yassl_libs@ @openssl_libs@
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
@@ -53,20 +50,24 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
sql_error.h field.h handler.h mysqld_suffix.h \
ha_heap.h ha_myisam.h ha_myisammrg.h ha_partition.h \
+ ha_innodb.h ha_berkeley.h ha_federated.h \
+ ha_ndbcluster.h ha_ndbcluster_binlog.h \
+ ha_ndbcluster_tables.h \
opt_range.h protocol.h rpl_tblmap.h \
log.h sql_show.h rpl_rli.h \
- sql_select.h structs.h table.h sql_udf.h hash_filo.h\
+ sql_select.h structs.h table.h sql_udf.h hash_filo.h \
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h sql_repl.h slave.h rpl_filter.h \
rpl_injector.h \
stacktrace.h sql_sort.h sql_cache.h set_var.h \
spatial.h gstream.h client_settings.h tzfile.h \
- tztime.h my_decimal.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 sql_cursor.h event.h event_priv.h \
sql_plugin.h authors.h sql_partition.h \
- partition_info.h partition_element.h
+ partition_info.h partition_element.h event_scheduler.h \
+ contributors.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -79,7 +80,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
set_var.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
- sql_prepare.cc sql_error.cc \
+ sql_prepare.cc sql_error.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
@@ -87,6 +88,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
discover.cc time.cc opt_range.cc opt_sum.cc \
records.cc filesort.cc handler.cc \
ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
+ ha_partition.cc ha_innodb.cc ha_berkeley.cc \
+ ha_federated.cc \
+ ha_ndbcluster.cc ha_ndbcluster_binlog.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 \
@@ -100,17 +104,11 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
tztime.cc my_time.c my_user.c my_decimal.cc\
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \
- event_executor.cc event.cc event_timed.cc \
+ event_scheduler.cc event.cc event_timed.cc \
sql_plugin.cc sql_binlog.cc \
- handlerton.cc sql_tablespace.cc partition_info.cc
-EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
- ha_innodb.h ha_berkeley.h ha_archive.h \
- ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
- ha_blackhole.h ha_federated.h ha_ndbcluster.h \
- ha_ndbcluster_binlog.cc ha_ndbcluster_binlog.h \
- ha_ndbcluster_tables.h \
- ha_partition.cc ha_partition.h
-mysqld_DEPENDENCIES = @mysql_se_objs@
+ sql_builtin.cc sql_tablespace.cc partition_info.cc
+
+
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysql_tzinfo_to_sql_SOURCES = mysql_tzinfo_to_sql.cc
@@ -125,7 +123,7 @@ DEFS = -DMYSQL_SERVER \
BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES) \
- nt_servc.cc nt_servc.h message.mc cmakelists.txt
+ nt_servc.cc nt_servc.h message.mc CMakeLists.txt
CLEANFILES = lex_hash.h sql_yacc.cc sql_yacc.h
AM_YFLAGS = -d
@@ -162,6 +160,7 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
lex_hash.h: gen_lex_hash$(EXEEXT)
./gen_lex_hash$(EXEEXT) > $@
+# the following three should eventually be moved out of this directory
ha_berkeley.o: ha_berkeley.cc ha_berkeley.h
$(CXXCOMPILE) @bdb_includes@ $(LM_CFLAGS) -c $<
diff --git a/sql/authors.h b/sql/authors.h
index 595d14c6e0b..618c6305f6b 100644
--- a/sql/authors.h
+++ b/sql/authors.h
@@ -57,7 +57,8 @@ struct show_table_authors_st show_table_authors[]= {
{ "Yves Carlier", "", "mysqlaccess" },
{ "Joshua Chamas", "Cupertino, CA, USA",
"Concurrent insert, extended date syntax" },
- { "Petr Chardin", "Moscow, Russia", "Instance Manager (5.0)" },
+ { "Petr Chardin", "Moscow, Russia",
+ "Instance Manager (5.0), Server log tables (5.1)" },
{ "Wei-Jou Chen", "", "Chinese (Big5) character set" },
{ "Albert Chin-A-Young", "",
"Tru64 port, large file support, better TCP wrappers support" },
@@ -73,6 +74,7 @@ struct show_table_authors_st show_table_authors[]= {
{ "Nikolay Grishakin", "Austin, TX, USA", "Testing - Server" },
{ "Wei He", "", "Chinese (GBK) character set" },
{ "Eric Herman", "Amsterdam, Netherlands", "Bug fixing - federated" },
+ { "Andrey Hristov", "Walldorf, Germany", "Event scheduler (5.1)" },
{ "Alexander (Alexi) Ivanov", "St. Petersburg, Russia", "Replication" },
{ "Alexander (Salle) Keremidarski", "Sofia, Bulgaria",
"Bug fixing" },
diff --git a/sql/contributors.h b/sql/contributors.h
new file mode 100644
index 00000000000..dca232b9b69
--- /dev/null
+++ b/sql/contributors.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2005 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 */
+
+/* Structure of the name list */
+
+struct show_table_contributors_st {
+ const char *name;
+ const char *location;
+ const char *comment;
+};
+
+/*
+ Output from "SHOW CONTRIBUTORS"
+
+ Get permission before editing.
+
+ IMPORTANT: Names should be left in historical order.
+
+ Names should be encoded using UTF-8.
+*/
+
+struct show_table_contributors_st show_table_contributors[]= {
+ {"Ronald Bradford", "Brisbane, Australia", "EFF contribution for UC2006 Auction"},
+ {"Sheeri Kritzer", "Boston, Mass. USA", "EFF contribution for UC2006 Auction"},
+ {"Mark Shuttleworth", "London, UK.", "EFF contribution for UC2006 Auction"},
+ {NULL, NULL, NULL}
+};
diff --git a/sql/event.cc b/sql/event.cc
index 4a3c6aad30c..5273394640c 100644
--- a/sql/event.cc
+++ b/sql/event.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2005 MySQL AB
+/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,13 +16,12 @@
#include "event_priv.h"
#include "event.h"
+#include "event_scheduler.h"
#include "sp.h"
+#include "sp_head.h"
/*
TODO list :
- - The default value of created/modified should not be 0000-00-00 because of
- STRICT mode restricions.
-
- CREATE EVENT should not go into binary log! Does it now? The SQL statements
issued by the EVENT are replicated.
I have an idea how to solve the problem at failover. So the status field
@@ -38,23 +37,8 @@
ENABLED to DISABLED status change and this is safe for replicating. As well
an event may be deleted which is also safe for RBR.
- - Maybe move all allocations during parsing to evex_mem_root thus saving
- double parsing in evex_create_event!
-
- - If the server is killed (stopping) try to kill executing events?
-
- - What happens if one renames an event in the DB while it is in memory?
- Or even deleting it?
-
- - Consider using conditional variable when doing shutdown instead of
- waiting till all worker threads end.
-
- - Make Event_timed::get_show_create_event() work
-
- Add logging to file
- - Move comparison code to class Event_timed
-
Warning:
- For now parallel execution is not possible because the same sp_head cannot be
executed few times!!! There is still no lock attached to particular event.
@@ -62,12 +46,26 @@ Warning:
*/
-QUEUE EVEX_EQ_NAME;
MEM_ROOT evex_mem_root;
time_t mysql_event_last_create_time= 0L;
-static TABLE_FIELD_W_TYPE event_table_fields[EVEX_FIELD_COUNT] = {
+const char *event_scheduler_state_names[]=
+ { "OFF", "0", "ON", "1", "SUSPEND", "2", NullS };
+
+TYPELIB Events::opt_typelib=
+{
+ array_elements(event_scheduler_state_names)-1,
+ "",
+ event_scheduler_state_names,
+ NULL
+};
+
+
+ulong Events::opt_event_scheduler= 2;
+
+static
+TABLE_FIELD_W_TYPE event_table_fields[Events::FIELD_COUNT] = {
{
{(char *) STRING_WITH_LEN("db")},
{(char *) STRING_WITH_LEN("char(64)")},
@@ -186,41 +184,17 @@ LEX_STRING interval_type_to_name[] = {
};
-
-/*
- Inits the scheduler queue - prioritized queue from mysys/queue.c
-
- Synopsis
- evex_queue_init()
-
- queue - pointer the the memory to be initialized as queue. has to be
- allocated from the caller
-
- Notes
- During initialization the queue is sized for 30 events, and when is full
- will auto extent with 30.
-*/
-
-void
-evex_queue_init(EVEX_QUEUE_TYPE *queue)
-{
- if (init_queue_ex(queue, 30 /*num_el*/, 0 /*offset*/, 0 /*smallest_on_top*/,
- event_timed_compare_q, NULL, 30 /*auto_extent*/))
- sql_print_error("Insufficient memory to initialize executing queue.");
-}
-
-
/*
Compares 2 LEX strings regarding case.
- Synopsis
+ SYNOPSIS
my_time_compare()
s - first LEX_STRING
t - second LEX_STRING
cs - charset
- RETURNS:
+ RETURN VALUE
-1 - s < t
0 - s == t
1 - s > t
@@ -239,32 +213,26 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
/*
Compares 2 TIME structures
- Synopsis
+ SYNOPSIS
my_time_compare()
a - first TIME
b - second time
- RETURNS:
+ RETURN VALUE
-1 - a < b
0 - a == b
1 - a > b
- Notes
+ NOTES
TIME.second_part is not considered during comparison
*/
int
my_time_compare(TIME *a, TIME *b)
{
-
-#ifdef ENABLE_WHEN_WE_HAVE_MILLISECOND_IN_TIMESTAMPS
- my_ulonglong a_t= TIME_to_ulonglong_datetime(a)*100L + a->second_part;
- my_ulonglong b_t= TIME_to_ulonglong_datetime(b)*100L + b->second_part;
-#else
my_ulonglong a_t= TIME_to_ulonglong_datetime(a);
my_ulonglong b_t= TIME_to_ulonglong_datetime(b);
-#endif
if (a_t > b_t)
return 1;
@@ -276,36 +244,11 @@ my_time_compare(TIME *a, TIME *b)
/*
- Compares the execute_at members of 2 Event_timed instances
-
- Synopsis
- event_timed_compare()
-
- a - first Event_timed object
- b - second Event_timed object
-
- RETURNS:
- -1 - a->execute_at < b->execute_at
- 0 - a->execute_at == b->execute_at
- 1 - a->execute_at > b->execute_at
-
- Notes
- execute_at.second_part is not considered during comparison
-*/
-
-int
-event_timed_compare(Event_timed *a, Event_timed *b)
-{
- return my_time_compare(&a->execute_at, &b->execute_at);
-}
-
-
-/*
Compares the execute_at members of 2 Event_timed instances.
Used as callback for the prioritized queue when shifting
elements inside.
- Synopsis
+ SYNOPSIS
event_timed_compare()
vptr - not used (set it to NULL)
@@ -324,7 +267,8 @@ event_timed_compare(Event_timed *a, Event_timed *b)
int
event_timed_compare_q(void *vptr, byte* a, byte *b)
{
- return event_timed_compare((Event_timed *)a, (Event_timed *)b);
+ return my_time_compare(&((Event_timed *)a)->execute_at,
+ &((Event_timed *)b)->execute_at);
}
@@ -335,8 +279,8 @@ event_timed_compare_q(void *vptr, byte* a, byte *b)
YEAR_MONTH - expression is in months
DAY_MINUTE - expression is in minutes
- Synopsis
- event_reconstruct_interval_expression()
+ SYNOPSIS
+ Events::reconstruct_interval_expression()
buf - preallocated String buffer to add the value to
interval - the interval type (for instance YEAR_MONTH)
expression - the value in the lowest entity
@@ -347,9 +291,9 @@ event_timed_compare_q(void *vptr, byte* a, byte *b)
*/
int
-event_reconstruct_interval_expression(String *buf,
- interval_type interval,
- longlong expression)
+Events::reconstruct_interval_expression(String *buf,
+ interval_type interval,
+ longlong expression)
{
ulonglong expr= expression;
char tmp_buff[128], *end;
@@ -466,19 +410,20 @@ common_1_lev_code:
Open mysql.event table for read
SYNOPSIS
- evex_open_event_table_for_read()
+ Events::open_event_table()
thd Thread context
lock_type How to lock the table
table The table pointer
- RETURN
+ RETURN VALUE
1 Cannot lock table
2 The table is corrupted - different number of fields
0 OK
*/
int
-evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
+Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
+ TABLE **table)
{
TABLE_LIST tables;
DBUG_ENTER("open_proc_table");
@@ -491,7 +436,8 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
if (simple_open_n_lock_tables(thd, &tables))
DBUG_RETURN(1);
- if (table_check_intact(tables.table, EVEX_FIELD_COUNT, event_table_fields,
+ if (table_check_intact(tables.table, Events::FIELD_COUNT,
+ event_table_fields,
&mysql_event_last_create_time,
ER_CANNOT_LOAD_FROM_TABLE))
{
@@ -510,7 +456,7 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
SYNOPSIS
evex_db_find_event_aux()
thd Thread context
- et evet_timed object containing dbname, name & definer
+ et event_timed object containing dbname & name
table TABLE object for open mysql.event table.
RETURN VALUE
@@ -521,8 +467,7 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
inline int
evex_db_find_event_aux(THD *thd, Event_timed *et, TABLE *table)
{
- return evex_db_find_event_by_name(thd, et->dbname, et->name,
- et->definer, table);
+ return evex_db_find_event_by_name(thd, et->dbname, et->name, table);
}
@@ -544,7 +489,6 @@ evex_db_find_event_aux(THD *thd, Event_timed *et, TABLE *table)
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
- const LEX_STRING user_name,
TABLE *table)
{
byte key[MAX_KEY_LENGTH];
@@ -558,50 +502,53 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
'db' and 'name' and the first key is the primary key over the
same fields.
*/
- if (dbname.length > table->field[EVEX_FIELD_DB]->field_length ||
- ev_name.length > table->field[EVEX_FIELD_NAME]->field_length ||
- user_name.length > table->field[EVEX_FIELD_DEFINER]->field_length)
+ if (dbname.length > table->field[Events::FIELD_DB]->field_length ||
+ ev_name.length > table->field[Events::FIELD_NAME]->field_length)
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
- table->field[EVEX_FIELD_DB]->store(dbname.str, dbname.length, &my_charset_bin);
- table->field[EVEX_FIELD_NAME]->store(ev_name.str, ev_name.length,
- &my_charset_bin);
- table->field[EVEX_FIELD_DEFINER]->store(user_name.str, user_name.length,
+ table->field[Events::FIELD_DB]->store(dbname.str, dbname.length,
+ &my_charset_bin);
+ table->field[Events::FIELD_NAME]->store(ev_name.str, ev_name.length,
&my_charset_bin);
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_PRINT("info", ("Row not fonud"));
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
+ }
+ DBUG_PRINT("info", ("Row found!"));
DBUG_RETURN(0);
}
/*
- Puts some data common to CREATE and ALTER EVENT into a row.
+ Puts some data common to CREATE and ALTER EVENT into a row.
- SYNOPSIS
- evex_fill_row()
- thd THD
- table the row to fill out
- et Event's data
+ SYNOPSIS
+ evex_fill_row()
+ thd THD
+ table the row to fill out
+ et Event's data
- Returns
- 0 - ok
- EVEX_GENERAL_ERROR - bad data
- EVEX_GET_FIELD_FAILED - field count does not match. table corrupted?
+ RETURN VALUE
+ 0 - OK
+ EVEX_GENERAL_ERROR - bad data
+ EVEX_GET_FIELD_FAILED - field count does not match. table corrupted?
- DESCRIPTION
- Used both when an event is created and when it is altered.
+ DESCRIPTION
+ Used both when an event is created and when it is altered.
*/
static int
evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
{
- enum evex_table_field field_num;
+ CHARSET_INFO *scs= system_charset_info;
+ enum Events::enum_table_field field_num;
DBUG_ENTER("evex_fill_row");
@@ -609,19 +556,23 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
DBUG_PRINT("info", ("name =[%s]", et->name.str));
DBUG_PRINT("info", ("body =[%s]", et->body.str));
- if (table->field[field_num= EVEX_FIELD_DB]->
- store(et->dbname.str, et->dbname.length, system_charset_info))
- goto trunc_err;
+ if (table->field[field_num= Events::FIELD_DEFINER]->
+ store(et->definer.str, et->definer.length, scs))
+ goto err_truncate;
+
+ if (table->field[field_num= Events::FIELD_DB]->
+ store(et->dbname.str, et->dbname.length, scs))
+ goto err_truncate;
- if (table->field[field_num= EVEX_FIELD_NAME]->
- store(et->name.str, et->name.length, system_charset_info))
- goto trunc_err;
+ if (table->field[field_num= Events::FIELD_NAME]->
+ store(et->name.str, et->name.length, scs))
+ goto err_truncate;
- /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull() */
- table->field[EVEX_FIELD_ON_COMPLETION]->store((longlong)et->on_completion,
- true);
+ /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
+ table->field[Events::FIELD_ON_COMPLETION]->
+ store((longlong)et->on_completion, true);
- table->field[EVEX_FIELD_STATUS]->store((longlong)et->status, true);
+ table->field[Events::FIELD_STATUS]->store((longlong)et->status, true);
/*
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
@@ -629,53 +580,54 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
*/
if (et->body.str)
{
- table->field[EVEX_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode,
- true);
+ table->field[Events::FIELD_SQL_MODE]->
+ store((longlong)thd->variables.sql_mode, true);
- if (table->field[field_num= EVEX_FIELD_BODY]->
- store(et->body.str, et->body.length, system_charset_info))
- goto trunc_err;
+ if (table->field[field_num= Events::FIELD_BODY]->
+ store(et->body.str, et->body.length, scs))
+ goto err_truncate;
}
if (et->expression)
{
- table->field[EVEX_FIELD_INTERVAL_EXPR]->set_notnull();
- table->field[EVEX_FIELD_INTERVAL_EXPR]->store((longlong)et->expression,true);
+ table->field[Events::FIELD_INTERVAL_EXPR]->set_notnull();
+ table->field[Events::FIELD_INTERVAL_EXPR]->
+ store((longlong)et->expression, true);
- table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_notnull();
+ table->field[Events::FIELD_TRANSIENT_INTERVAL]->set_notnull();
/*
In the enum (C) intervals start from 0 but in mysql enum valid values start
from 1. Thus +1 offset is needed!
*/
- table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1,
- true);
+ table->field[Events::FIELD_TRANSIENT_INTERVAL]->
+ store((longlong)et->interval+1, true);
- table->field[EVEX_FIELD_EXECUTE_AT]->set_null();
+ table->field[Events::FIELD_EXECUTE_AT]->set_null();
if (!et->starts_null)
{
- table->field[EVEX_FIELD_STARTS]->set_notnull();
- table->field[EVEX_FIELD_STARTS]->
+ table->field[Events::FIELD_STARTS]->set_notnull();
+ table->field[Events::FIELD_STARTS]->
store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
}
if (!et->ends_null)
{
- table->field[EVEX_FIELD_ENDS]->set_notnull();
- table->field[EVEX_FIELD_ENDS]->
+ table->field[Events::FIELD_ENDS]->set_notnull();
+ table->field[Events::FIELD_ENDS]->
store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
}
}
else if (et->execute_at.year)
{
- table->field[EVEX_FIELD_INTERVAL_EXPR]->set_null();
- table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null();
- table->field[EVEX_FIELD_STARTS]->set_null();
- table->field[EVEX_FIELD_ENDS]->set_null();
+ table->field[Events::FIELD_INTERVAL_EXPR]->set_null();
+ table->field[Events::FIELD_TRANSIENT_INTERVAL]->set_null();
+ table->field[Events::FIELD_STARTS]->set_null();
+ table->field[Events::FIELD_ENDS]->set_null();
- table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull();
- table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->execute_at,
- MYSQL_TIMESTAMP_DATETIME);
+ table->field[Events::FIELD_EXECUTE_AT]->set_notnull();
+ table->field[Events::FIELD_EXECUTE_AT]->
+ store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME);
}
else
{
@@ -686,46 +638,47 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
*/
}
- ((Field_timestamp *)table->field[EVEX_FIELD_MODIFIED])->set_time();
+ ((Field_timestamp *)table->field[Events::FIELD_MODIFIED])->set_time();
if (et->comment.str)
{
- if (table->field[field_num= EVEX_FIELD_COMMENT]->store(et->comment.str,
- et->comment.length,
- system_charset_info))
- goto trunc_err;
+ if (table->field[field_num= Events::FIELD_COMMENT]->
+ store(et->comment.str, et->comment.length, scs))
+ goto err_truncate;
}
DBUG_RETURN(0);
-trunc_err:
+err_truncate:
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
DBUG_RETURN(EVEX_GENERAL_ERROR);
}
/*
- Creates an event in mysql.event
-
- SYNOPSIS
- db_create_event()
- thd THD
- et Event_timed object containing information for the event
- create_if_not - if an warning should be generated in case event exists
- rows_affected - how many rows were affected
-
- Return value
- 0 - OK
- EVEX_GENERAL_ERROR - Failure
- DESCRIPTION
- Creates an event. Relies on evex_fill_row which is shared with
- db_update_event. The name of the event is inside "et".
+ Creates an event in mysql.event
+
+ SYNOPSIS
+ db_create_event()
+ thd THD
+ et Event_timed object containing information for the event
+ create_if_not If an warning should be generated in case event exists
+ rows_affected How many rows were affected
+
+ RETURN VALUE
+ 0 - OK
+ EVEX_GENERAL_ERROR - Failure
+
+ DESCRIPTION
+ Creates an event. Relies on evex_fill_row which is shared with
+ db_update_event. The name of the event is inside "et".
*/
-static int
+int
db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected)
{
int ret= 0;
+ CHARSET_INFO *scs= system_charset_info;
TABLE *table;
char olddb[128];
bool dbchanged= false;
@@ -734,7 +687,7 @@ db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
*rows_affected= 0;
DBUG_PRINT("info", ("open mysql.event for update"));
- if (evex_open_event_table(thd, TL_WRITE, &table))
+ if (Events::open_event_table(thd, TL_WRITE, &table))
{
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto err;
@@ -778,7 +731,7 @@ db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
goto err;
}
- if (et->body.length > table->field[EVEX_FIELD_BODY]->field_length)
+ if (et->body.length > table->field[Events::FIELD_BODY]->field_length)
{
my_error(ER_TOO_LONG_BODY, MYF(0), et->name.str);
goto err;
@@ -791,15 +744,7 @@ db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
goto err;
}
- if ((ret=table->field[EVEX_FIELD_DEFINER]->store(et->definer.str,
- et->definer.length,
- system_charset_info)))
- {
- my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
- goto err;
- }
-
- ((Field_timestamp *)table->field[EVEX_FIELD_CREATED])->set_time();
+ ((Field_timestamp *)table->field[Events::FIELD_CREATED])->set_time();
/*
evex_fill_row() calls my_error() in case of error so no need to
@@ -819,8 +764,8 @@ db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
{
thd->clear_error();
/* Such a statement can always go directly to binlog, no trans cache */
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length,
+ FALSE, FALSE);
}
#endif
@@ -842,33 +787,38 @@ err:
/*
- Used to execute ALTER EVENT. Pendant to evex_update_event().
+ Used to execute ALTER EVENT. Pendant to Events::update_event().
- SYNOPSIS
- db_update_event()
- thd THD
- sp_name the name of the event to alter
- et event's data
+ SYNOPSIS
+ db_update_event()
+ thd THD
+ sp_name the name of the event to alter
+ et event's data
+
+ RETURN VALUE
+ 0 OK
+ EVEX_GENERAL_ERROR Error occured (my_error() called)
- NOTES
- sp_name is passed since this is the name of the event to
- alter in case of RENAME TO.
+ NOTES
+ sp_name is passed since this is the name of the event to
+ alter in case of RENAME TO.
*/
static int
db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
{
+ CHARSET_INFO *scs= system_charset_info;
TABLE *table;
int ret= EVEX_OPEN_TABLE_FAILED;
DBUG_ENTER("db_update_event");
DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str));
DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
- DBUG_PRINT("enter", ("user: %.*s", et->name.length, et->name.str));
+ DBUG_PRINT("enter", ("user: %.*s", et->definer.length, et->definer.str));
if (new_name)
DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
new_name->m_name.str));
- if (evex_open_event_table(thd, TL_WRITE, &table))
+ if (Events::open_event_table(thd, TL_WRITE, &table))
{
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto err;
@@ -877,22 +827,21 @@ db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
/* first look whether we overwrite */
if (new_name)
{
- if (!sortcmp_lex_string(et->name, new_name->m_name, system_charset_info) &&
- !sortcmp_lex_string(et->dbname, new_name->m_db, system_charset_info))
+ if (!sortcmp_lex_string(et->name, new_name->m_name, scs) &&
+ !sortcmp_lex_string(et->dbname, new_name->m_db, scs))
{
my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
goto err;
}
- if (!evex_db_find_event_by_name(thd, new_name->m_db, new_name->m_name,
- et->definer, table))
+ if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table))
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
goto err;
}
}
/*
- ...and then whether there is such an event. don't exchange the blocks
+ ...and then if there is such an event. Don't exchange the blocks
because you will get error 120 from table handler because new_name will
overwrite the key and SE will tell us that it cannot find the already found
row (copied into record[1] later
@@ -908,16 +857,19 @@ db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- /* evex_fill_row() calls my_error() in case of error so no need to handle it here */
+ /*
+ evex_fill_row() calls my_error() in case of error so no need to
+ handle it here
+ */
if ((ret= evex_fill_row(thd, table, et, true)))
goto err;
if (new_name)
{
- table->field[EVEX_FIELD_DB]->
- store(new_name->m_db.str, new_name->m_db.length, system_charset_info);
- table->field[EVEX_FIELD_NAME]->
- store(new_name->m_name.str, new_name->m_name.length, system_charset_info);
+ table->field[Events::FIELD_DB]->
+ store(new_name->m_db.str, new_name->m_db.length, scs);
+ table->field[Events::FIELD_NAME]->
+ store(new_name->m_name.str, new_name->m_name.length, scs);
}
if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
@@ -938,33 +890,32 @@ err:
/*
- Looks for a named event in mysql.event and in case of success returns
- an object will data loaded from the table.
-
- SYNOPSIS
- db_find_event()
- thd THD
- name the name of the event to find
- definer who owns the event
- ett event's data if event is found
- tbl TABLE object to use when not NULL
-
- NOTES
- 1) Use sp_name for look up, return in **ett if found
- 2) tbl is not closed at exit
-
- RETURN
- 0 ok In this case *ett is set to the event
- # error *ett == 0
+ Looks for a named event in mysql.event and in case of success returns
+ an object will data loaded from the table.
+
+ SYNOPSIS
+ db_find_event()
+ thd THD
+ name the name of the event to find
+ ett event's data if event is found
+ tbl TABLE object to use when not NULL
+
+ NOTES
+ 1) Use sp_name for look up, return in **ett if found
+ 2) tbl is not closed at exit
+
+ RETURN VALUE
+ 0 ok In this case *ett is set to the event
+ # error *ett == 0
*/
-static int
-db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
- TABLE *tbl, MEM_ROOT *root)
+int
+db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
+ MEM_ROOT *root)
{
TABLE *table;
int ret;
- Event_timed *et= 0;
+ Event_timed *et= NULL;
DBUG_ENTER("db_find_event");
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
@@ -973,15 +924,14 @@ db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
if (tbl)
table= tbl;
- else if (evex_open_event_table(thd, TL_READ, &table))
+ else if (Events::open_event_table(thd, TL_READ, &table))
{
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
ret= EVEX_GENERAL_ERROR;
goto done;
}
- if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, *definer,
- table)))
+ if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, table)))
{
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
goto done;
@@ -1015,179 +965,43 @@ done:
/*
- Looks for a named event in mysql.event and then loads it from
- the table, compiles it and insert it into the cache.
-
- SYNOPSIS
- evex_load_and_compile_event()
- thd THD
- spn the name of the event to alter
- definer who is the owner
- use_lock whether to obtain a lock on LOCK_event_arrays or not
-
- RETURN VALUE
- 0 - OK
- < 0 - error (in this case underlying functions call my_error()).
-*/
-
-static int
-evex_load_and_compile_event(THD * thd, sp_name *spn, LEX_STRING definer,
- bool use_lock)
-{
- int ret= 0;
- MEM_ROOT *tmp_mem_root;
- Event_timed *ett;
- Open_tables_state backup;
-
- DBUG_ENTER("db_load_and_compile_event");
- DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
+ The function exported to the world for creating of events.
- tmp_mem_root= thd->mem_root;
- thd->mem_root= &evex_mem_root;
-
- thd->reset_n_backup_open_tables_state(&backup);
- /* no need to use my_error() here because db_find_event() has done it */
- ret= db_find_event(thd, spn, &definer, &ett, NULL, NULL);
- thd->restore_backup_open_tables_state(&backup);
- if (ret)
- goto done;
-
- ett->compute_next_execution_time();
- if (use_lock)
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
-
- evex_queue_insert(&EVEX_EQ_NAME, (EVEX_PTOQEL) ett);
-
- /*
- There is a copy in the array which we don't need. sphead won't be
- destroyed.
- */
-
- if (use_lock)
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
-
-done:
- if (thd->mem_root != tmp_mem_root)
- thd->mem_root= tmp_mem_root;
-
- DBUG_RETURN(ret);
-}
-
-
-/*
- Removes from queue in memory the event which is identified by the tupple
- (db, name).
-
- SYNOPSIS
- evex_remove_from_cache()
-
- db - db name
- name - event name
- use_lock - whether to lock the mutex LOCK_event_arrays or not in case it
- has been already locked outside
- is_drop - if an event is currently being executed then we can also delete
- the Event_timed instance, so we alarm the event that it should
- drop itself if this parameter is set to TRUE. It's false on
- ALTER EVENT.
-
- RETURNS
- 0 OK (always)
-*/
-
-static int
-evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
- bool is_drop)
-{
- //ToDo : Add definer to the tuple (db, name) to become triple
- uint i;
- int ret= 0;
-
- DBUG_ENTER("evex_remove_from_cache");
- /*
- It is possible that 2 (or 1) pass(es) won't find the event in memory.
- The reason is that DISABLED events are not cached.
- */
-
- if (use_lock)
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
-
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
- {
- Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
- DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?",db->str,name->str, et->dbname.str,
- et->name.str));
- if (!sortcmp_lex_string(*name, et->name, system_charset_info) &&
- !sortcmp_lex_string(*db, et->dbname, system_charset_info))
- {
- if (et->can_spawn_now())
- {
- DBUG_PRINT("evex_remove_from_cache", ("not running - free and delete"));
- et->free_sp();
- delete et;
- }
- else
- {
- DBUG_PRINT("evex_remove_from_cache",
- ("running.defer mem free. is_drop=%d", is_drop));
- et->flags|= EVENT_EXEC_NO_MORE;
- et->dropped= is_drop;
- }
- DBUG_PRINT("evex_remove_from_cache", ("delete from queue"));
- evex_queue_delete_element(&EVEX_EQ_NAME, i);
- /* ok, we have cleaned */
- ret= 0;
- goto done;
- }
- }
-
-done:
- if (use_lock)
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
-
- DBUG_RETURN(ret);
-}
+ SYNOPSIS
+ Events::create_event()
+ thd THD
+ et event's data
+ create_options Options specified when in the query. We are
+ interested whether there is IF NOT EXISTS
+ rows_affected How many rows were affected
+ RETURN VALUE
+ 0 OK
+ !0 Error
-/*
- The function exported to the world for creating of events.
-
- SYNOPSIS
- evex_create_event()
- thd THD
- et event's data
- create_options Options specified when in the query. We are
- interested whether there is IF NOT EXISTS
- rows_affected How many rows were affected
-
- NOTES
- - in case there is an event with the same name (db) and
- IF NOT EXISTS is specified, an warning is put into the W stack.
+ NOTES
+ - in case there is an event with the same name (db) and
+ IF NOT EXISTS is specified, an warning is put into the W stack.
*/
int
-evex_create_event(THD *thd, Event_timed *et, uint create_options,
- uint *rows_affected)
+Events::create_event(THD *thd, Event_timed *et, uint create_options,
+ uint *rows_affected)
{
- int ret = 0;
+ int ret;
- DBUG_ENTER("evex_create_event");
+ DBUG_ENTER("Events::create_event");
DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length,
et->name.str, create_options));
- if ((ret = db_create_event(thd, et,
+ if (!(ret = db_create_event(thd, et,
create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
rows_affected)))
- goto done;
-
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- if (evex_is_running && et->status == MYSQL_EVENT_ENABLED)
{
- sp_name spn(et->dbname, et->name);
- ret= evex_load_and_compile_event(thd, &spn, et->definer, true);
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ if (scheduler->initialized() && (ret= scheduler->add_event(thd, et, true)))
+ my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
}
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
-done:
/* No need to close the table, it will be closed in sql_parse::do_command */
DBUG_RETURN(ret);
@@ -1195,73 +1009,63 @@ done:
/*
- The function exported to the world for alteration of events.
-
- SYNOPSIS
- evex_update_event()
- thd THD
- et event's data
- new_name set in case of RENAME TO.
-
- NOTES
- et contains data about dbname and event name.
- new_name is the new name of the event, if not null (this means
- that RENAME TO was specified in the query)
+ The function exported to the world for alteration of events.
+
+ SYNOPSIS
+ Events::update_event()
+ thd THD
+ et event's data
+ new_name set in case of RENAME TO.
+
+ RETURN VALUE
+ 0 OK
+ !0 Error
+
+ NOTES
+ et contains data about dbname and event name.
+ new_name is the new name of the event, if not null (this means
+ that RENAME TO was specified in the query)
*/
int
-evex_update_event(THD *thd, Event_timed *et, sp_name *new_name,
- uint *rows_affected)
+Events::update_event(THD *thd, Event_timed *et, sp_name *new_name,
+ uint *rows_affected)
{
int ret;
- bool need_second_pass= true;
- DBUG_ENTER("evex_update_event");
+ DBUG_ENTER("Events::update_event");
DBUG_PRINT("enter", ("name: %*s", et->name.length, et->name.str));
-
/*
db_update_event() opens & closes the table to prevent
crash later in the code when loading and compiling the new definition.
Also on error conditions my_error() is called so no need to handle here
*/
- if ((ret= db_update_event(thd, et, new_name)))
- goto done;
-
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- if (!evex_is_running)
- UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, done);
-
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
- evex_remove_from_cache(&et->dbname, &et->name, false, false);
- if (et->status == MYSQL_EVENT_ENABLED)
+ if (!(ret= db_update_event(thd, et, new_name)))
{
- if (new_name)
- ret= evex_load_and_compile_event(thd, new_name, et->definer, false);
- else
- {
- sp_name spn(et->dbname, et->name);
- ret= evex_load_and_compile_event(thd, &spn, et->definer, false);
- }
- if (ret == EVEX_COMPILE_ERROR)
- my_error(ER_EVENT_COMPILE_ERROR, MYF(0));
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ if (scheduler->initialized() &&
+ (ret= scheduler->replace_event(thd, et,
+ new_name? &new_name->m_db: NULL,
+ new_name? &new_name->m_name: NULL)))
+ my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
}
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
-done:
DBUG_RETURN(ret);
}
/*
- Drops an event
-
- SYNOPSIS
- db_drop_event()
- thd THD
- et event's name
- drop_if_exists if set and the event not existing => warning onto the stack
- rows_affected affected number of rows is returned heres
+ Drops an event
+
+ SYNOPSIS
+ db_drop_event()
+ thd THD
+ et event's name
+ drop_if_exists if set and the event not existing => warning onto the stack
+ rows_affected affected number of rows is returned heres
+
+ RETURN VALUE
+ 0 OK
+ !0 Error (my_error() called)
*/
int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
@@ -1275,7 +1079,7 @@ int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
ret= EVEX_OPEN_TABLE_FAILED;
thd->reset_n_backup_open_tables_state(&backup);
- if (evex_open_event_table(thd, TL_WRITE, &table))
+ if (Events::open_event_table(thd, TL_WRITE, &table))
{
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto done;
@@ -1315,58 +1119,53 @@ done:
/*
- Drops an event
-
- SYNOPSIS
- evex_drop_event()
- thd THD
- et event's name
- drop_if_exists if set and the event not existing => warning onto the stack
- rows_affected affected number of rows is returned heres
-
+ Drops an event
+
+ SYNOPSIS
+ Events::drop_event()
+ thd THD
+ et event's name
+ drop_if_exists if set and the event not existing => warning onto the stack
+ rows_affected affected number of rows is returned heres
+
+ RETURN VALUE
+ 0 OK
+ !0 Error (reported)
*/
int
-evex_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
- uint *rows_affected)
+Events::drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
+ uint *rows_affected)
{
- int ret= 0;
-
- DBUG_ENTER("evex_drop_event");
-
-
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- if (evex_is_running)
- ret= evex_remove_from_cache(&et->dbname, &et->name, true, true);
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
+ int ret;
- if (ret == 1)
- ret= 0;
- else if (ret == 0)
- ret= db_drop_event(thd, et, drop_if_exists, rows_affected);
- else
- my_error(ER_UNKNOWN_ERROR, MYF(0));
+ DBUG_ENTER("Events::drop_event");
+ if (!(ret= db_drop_event(thd, et, drop_if_exists, rows_affected)))
+ {
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ if (scheduler->initialized() && (ret= scheduler->drop_event(thd, et)))
+ my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
+ }
DBUG_RETURN(ret);
}
/*
- SHOW CREATE EVENT
+ SHOW CREATE EVENT
- SYNOPSIS
- evex_show_create_event()
- thd THD
- spn the name of the event (db, name)
- definer the definer of the event
+ SYNOPSIS
+ Events::show_create_event()
+ thd THD
+ spn the name of the event (db, name)
- RETURNS
- 0 - OK
- 1 - Error during writing to the wire
+ RETURN VALUE
+ 0 OK
+ 1 Error during writing to the wire
*/
int
-evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
+Events::show_create_event(THD *thd, sp_name *spn)
{
int ret;
Event_timed *et= NULL;
@@ -1376,10 +1175,10 @@ evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
thd->reset_n_backup_open_tables_state(&backup);
- ret= db_find_event(thd, spn, &definer, &et, NULL, thd->mem_root);
+ ret= db_find_event(thd, spn, &et, NULL, thd->mem_root);
thd->restore_backup_open_tables_state(&backup);
- if (et)
+ if (!ret)
{
Protocol *protocol= thd->protocol;
char show_str_buf[768];
@@ -1389,12 +1188,10 @@ evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
ulong sql_mode_len=0;
show_str.length(0);
+ show_str.set_charset(system_charset_info);
if (et->get_create_event(thd, &show_str))
- {
- delete et;
- DBUG_RETURN(1);
- }
+ goto err;
field_list.push_back(new Item_empty_string("Event", NAME_LEN));
@@ -1408,201 +1205,216 @@ evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
show_str.length()));
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
- {
- delete et;
- DBUG_RETURN(1);
- }
+ goto err;
+
protocol->prepare_for_resend();
protocol->store(et->name.str, et->name.length, system_charset_info);
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
- protocol->store(show_str.ptr(), show_str.length(), system_charset_info);
+ protocol->store(show_str.c_ptr(), show_str.length(), system_charset_info);
ret= protocol->write();
send_eof(thd);
- delete et;
}
-
+ delete et;
DBUG_RETURN(ret);
+err:
+ delete et;
+ DBUG_RETURN(1);
}
/*
- evex_drop_db_events - Drops all events in the selected database
+ Drops all events from a schema
- thd - Thread
- db - ASCIIZ the name of the database
-
- Returns:
- 0 - OK
- 1 - Failed to delete a specific row
- 2 - Got NULL while reading db name from a row
-
- Note:
- The algo is the following
- 1. Go through the in-memory cache, if the scheduler is working
- and for every event whose dbname matches the database we drop
- check whether is currently in execution:
- - Event_timed::can_spawn() returns true -> the event is not
- being executed in a child thread. The reason not to use
- Event_timed::is_running() is that the latter shows only if
- it is being executed, which is 99% of the time in the thread
- but there are some initiliazations before and after the
- anonymous SP is being called. So if we delete in this moment
- -=> *boom*, so we have to check whether the thread has been
- spawned and can_spawn() is the right method.
- - Event_timed::can_spawn() returns false -> being runned ATM
- just set the flags so it should drop itself.
+ SYNOPSIS
+ Events::drop_schema_events()
+ thd Thread
+ db ASCIIZ schema name
+
+ RETURN VALUE
+ 0 OK
+ !0 Error
*/
int
-evex_drop_db_events(THD *thd, char *db)
+Events::drop_schema_events(THD *thd, char *db)
{
- TABLE *table;
- READ_RECORD read_record_info;
int ret= 0;
- uint i;
LEX_STRING db_lex= {db, strlen(db)};
DBUG_ENTER("evex_drop_db_events");
- DBUG_PRINT("info",("dropping events from %s", db));
+ DBUG_PRINT("enter", ("dropping events from %s", db));
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ if (scheduler->initialized())
+ ret= scheduler->drop_schema_events(thd, &db_lex);
+ else
+ ret= db_drop_events_from_table(thd, &db_lex);
- if ((ret= evex_open_event_table(thd, TL_WRITE, &table)))
- {
- sql_print_error("Table mysql.event is damaged.");
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
- }
+ DBUG_RETURN(ret);
+}
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- if (!evex_is_running)
- goto skip_memory;
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
- {
- Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
- if (sortcmp_lex_string(et->dbname, db_lex, system_charset_info))
- continue;
+/*
+ Drops all events in the selected database, from mysql.event.
- if (et->can_spawn_now_n_lock(thd))
- {
- DBUG_PRINT("info",("event %s not running - direct delete", et->name.str));
- if (!(ret= evex_db_find_event_aux(thd, et, table)))
- {
- DBUG_PRINT("info",("event %s found on disk", et->name.str));
- if ((ret= table->file->ha_delete_row(table->record[0])))
- {
- sql_print_error("Error while deleting a row - dropping "
- "a database. Skipping the rest.");
- my_error(ER_EVENT_DROP_FAILED, MYF(0), et->name.str);
- goto end;
- }
- DBUG_PRINT("info",("deleted event [%s] num [%d]. Time to free mem",
- et->name.str, i));
- }
- else if (ret == EVEX_KEY_NOT_FOUND)
- {
- sql_print_error("Expected to find event %s.%s of %s on disk-not there.",
- et->dbname.str, et->name.str, et->definer.str);
- }
- et->free_sp();
- delete et;
- et= 0;
- /* no need to call et->spawn_unlock because we already cleaned et */
- }
- else
- {
- DBUG_PRINT("info",("event %s is running. setting exec_no_more and dropped",
- et->name.str));
- et->flags|= EVENT_EXEC_NO_MORE;
- et->dropped= TRUE;
- }
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
- evex_queue_delete_element(&EVEX_EQ_NAME, i);// 0 is top
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
- /*
- decrease so we start at the same position, there will be
- less elements in the queue, it will still be ordered so on
- next iteration it will be again i the current element or if
- no more we finish.
- */
- --i;
- }
+ SYNOPSIS
+ evex_drop_db_events_from_table()
+ thd Thread
+ db Schema name
-skip_memory:
- /*
- The reasoning behind having two loops is the following:
- If there was only one loop, the table-scan, then for every element which
- matches, the queue in memory has to be searched to remove the element.
- While if we go first over the queue and remove what's in there we have only
- one pass over it and after finishing it, moving to table-scan for the disabled
- events. This needs quite less time and means quite less locking on
- LOCK_event_arrays.
- */
- DBUG_PRINT("info",("Mem-cache checked, now going to db for disabled events"));
+ RETURN VALUE
+ 0 OK
+ !0 Error from ha_delete_row
+*/
+
+int
+db_drop_events_from_table(THD *thd, LEX_STRING *db)
+{
+ int ret;
+ TABLE *table;
+ READ_RECORD read_record_info;
+ DBUG_ENTER("db_drop_events_from_table");
+ DBUG_PRINT("info", ("dropping events from %s", db->str));
+
+ if ((ret= Events::open_event_table(thd, TL_WRITE, &table)))
+ {
+ sql_print_error("Table mysql.event is damaged.");
+ DBUG_RETURN(ret);
+ }
/* only enabled events are in memory, so we go now and delete the rest */
- init_read_record(&read_record_info, thd, table ,NULL,1,0);
+ init_read_record(&read_record_info, thd, table, NULL, 1, 0);
while (!(read_record_info.read_record(&read_record_info)) && !ret)
{
- char *et_db;
+ char *et_db= get_field(thd->mem_root,
+ table->field[Events::FIELD_DB]);
- if ((et_db= get_field(thd->mem_root, table->field[EVEX_FIELD_DB])) == NULL)
- {
- ret= 2;
- break;
- }
-
LEX_STRING et_db_lex= {et_db, strlen(et_db)};
- if (!sortcmp_lex_string(et_db_lex, db_lex, system_charset_info))
+ DBUG_PRINT("info", ("Current event %s.%s", et_db,
+ get_field(thd->mem_root,
+ table->field[Events::FIELD_NAME])));
+
+ if (!sortcmp_lex_string(et_db_lex, *db, system_charset_info))
{
- Event_timed ett;
- char *ptr;
-
- if ((ptr= get_field(thd->mem_root, table->field[EVEX_FIELD_STATUS]))
- == NullS)
- {
- sql_print_error("Error while loading from mysql.event. "
- "Table probably corrupted");
- goto end;
- }
- /*
- When not running nothing is in memory so we have to clean
- everything.
- We don't delete EVENT_ENABLED events when the scheduler is running
- because maybe this is an event which we asked to drop itself when
- it is finished and it hasn't finished yet, so we don't touch it.
- It will drop itself. The not running ENABLED events has been already
- deleted from ha_delete_row() above in the loop over the QUEUE
- (in case the executor is running).
- 'D' stands for DISABLED, 'E' for ENABLED - it's an enum
- */
- if ((evex_is_running && ptr[0] == 'D') || !evex_is_running)
- {
- DBUG_PRINT("info", ("Dropping %s.%s", et_db, ett.name.str));
- if ((ret= table->file->ha_delete_row(table->record[0])))
- {
- my_error(ER_EVENT_DROP_FAILED, MYF(0), ett.name.str);
- goto end;
- }
- }
+ DBUG_PRINT("info", ("Dropping"));
+ if ((ret= table->file->ha_delete_row(table->record[0])))
+ my_error(ER_EVENT_DROP_FAILED, MYF(0),
+ get_field(thd->mem_root,
+ table->field[Events::FIELD_NAME]));
}
}
- DBUG_PRINT("info",("Disk checked for disabled events. Finishing."));
-
-end:
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
end_read_record(&read_record_info);
-
thd->version--; /* Force close to free memory */
close_thread_tables(thd);
DBUG_RETURN(ret);
}
+
+
+
+/*
+ Inits the scheduler's structures.
+
+ SYNOPSIS
+ Events::init()
+
+ NOTES
+ This function is not synchronized.
+
+ RETURN VALUE
+ 0 OK
+ 1 Error
+*/
+
+int
+Events::init()
+{
+ int ret= 0;
+ DBUG_ENTER("Events::init");
+
+ /* it should be an assignment! */
+ if (opt_event_scheduler)
+ {
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ DBUG_ASSERT(opt_event_scheduler == 1 || opt_event_scheduler == 2);
+ DBUG_RETURN(scheduler->init() ||
+ (opt_event_scheduler == 1? scheduler->start():
+ scheduler->start_suspended()));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Cleans up scheduler's resources. Called at server shutdown.
+
+ SYNOPSIS
+ Events::shutdown()
+
+ NOTES
+ This function is not synchronized.
+*/
+
+void
+Events::shutdown()
+{
+ DBUG_ENTER("Events::shutdown");
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ if (scheduler->initialized())
+ {
+ scheduler->stop();
+ scheduler->destroy();
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Proxy for Event_scheduler::dump_internal_status
+
+ SYNOPSIS
+ Events::dump_internal_status()
+ thd Thread
+
+ RETURN VALUE
+ 0 OK
+ !0 Error
+*/
+
+int
+Events::dump_internal_status(THD *thd)
+{
+ return Event_scheduler::dump_internal_status(thd);
+}
+
+
+/*
+ Inits Events mutexes
+
+ SYNOPSIS
+ Events::init_mutexes()
+ thd Thread
+*/
+
+void
+Events::init_mutexes()
+{
+ Event_scheduler::init_mutexes();
+}
+
+
+/*
+ Destroys Events mutexes
+
+ SYNOPSIS
+ Events::destroy_mutexes()
+*/
+
+void
+Events::destroy_mutexes()
+{
+ Event_scheduler::destroy_mutexes();
+}
diff --git a/sql/event.h b/sql/event.h
index 27de8b46e32..02c5fa78150 100644
--- a/sql/event.h
+++ b/sql/event.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2004-2005 MySQL AB
+#ifndef _EVENT_H_
+#define _EVENT_H_
+/* Copyright (C) 2004-2006 MySQL AB
This 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,66 +16,109 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef _EVENT_H_
-#define _EVENT_H_
-#include "sp.h"
-#include "sp_head.h"
-
-#define EVEX_OK SP_OK
-#define EVEX_KEY_NOT_FOUND SP_KEY_NOT_FOUND
-#define EVEX_OPEN_TABLE_FAILED SP_OPEN_TABLE_FAILED
-#define EVEX_WRITE_ROW_FAILED SP_WRITE_ROW_FAILED
-#define EVEX_DELETE_ROW_FAILED SP_DELETE_ROW_FAILED
-#define EVEX_GET_FIELD_FAILED SP_GET_FIELD_FAILED
-#define EVEX_PARSE_ERROR SP_PARSE_ERROR
-#define EVEX_INTERNAL_ERROR SP_INTERNAL_ERROR
-#define EVEX_NO_DB_ERROR SP_NO_DB_ERROR
+
+#define EVEX_OK 0
+#define EVEX_KEY_NOT_FOUND -1
+#define EVEX_OPEN_TABLE_FAILED -2
+#define EVEX_WRITE_ROW_FAILED -3
+#define EVEX_DELETE_ROW_FAILED -4
+#define EVEX_GET_FIELD_FAILED -5
+#define EVEX_PARSE_ERROR -6
+#define EVEX_INTERNAL_ERROR -7
+#define EVEX_NO_DB_ERROR -8
#define EVEX_COMPILE_ERROR -19
#define EVEX_GENERAL_ERROR -20
-#define EVEX_BAD_IDENTIFIER SP_BAD_IDENTIFIER
-#define EVEX_BODY_TOO_LONG SP_BODY_TOO_LONG
-#define EVEX_BAD_PARAMS -21
-#define EVEX_NOT_RUNNING -22
-#define EVEX_MICROSECOND_UNSUP -23
+#define EVEX_BAD_IDENTIFIER -21
+#define EVEX_BODY_TOO_LONG -22
+#define EVEX_BAD_PARAMS -23
+#define EVEX_NOT_RUNNING -24
+#define EVEX_MICROSECOND_UNSUP -25
+#define EVEX_CANT_KILL -26
#define EVENT_EXEC_NO_MORE (1L << 0)
#define EVENT_NOT_USED (1L << 1)
+#define EVENT_FREE_WHEN_FINISHED (1L << 2)
-extern ulong opt_event_executor;
+class Event_timed;
-enum enum_event_on_completion
+class Events
{
- MYSQL_EVENT_ON_COMPLETION_DROP = 1,
- MYSQL_EVENT_ON_COMPLETION_PRESERVE
-};
+public:
+ static ulong opt_event_scheduler;
+ static TYPELIB opt_typelib;
-enum enum_event_status
-{
- MYSQL_EVENT_ENABLED = 1,
- MYSQL_EVENT_DISABLED
+ enum enum_table_field
+ {
+ FIELD_DB = 0,
+ FIELD_NAME,
+ FIELD_BODY,
+ FIELD_DEFINER,
+ FIELD_EXECUTE_AT,
+ FIELD_INTERVAL_EXPR,
+ FIELD_TRANSIENT_INTERVAL,
+ FIELD_CREATED,
+ FIELD_MODIFIED,
+ FIELD_LAST_EXECUTED,
+ FIELD_STARTS,
+ FIELD_ENDS,
+ FIELD_STATUS,
+ FIELD_ON_COMPLETION,
+ FIELD_SQL_MODE,
+ FIELD_COMMENT,
+ FIELD_COUNT /* a cool trick to count the number of fields :) */
+ };
+
+ static int
+ create_event(THD *thd, Event_timed *et, uint create_options,
+ uint *rows_affected);
+
+ static int
+ update_event(THD *thd, Event_timed *et, sp_name *new_name,
+ uint *rows_affected);
+
+ static int
+ drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
+ uint *rows_affected);
+
+ static int
+ open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
+
+ static int
+ show_create_event(THD *thd, sp_name *spn);
+
+ static int
+ reconstruct_interval_expression(String *buf, interval_type interval,
+ longlong expression);
+
+ static int
+ drop_schema_events(THD *thd, char *db);
+
+ static int
+ dump_internal_status(THD *thd);
+
+ static int
+ init();
+
+ static void
+ shutdown();
+
+ static void
+ init_mutexes();
+
+ static void
+ destroy_mutexes();
+
+
+private:
+ /* Prevent use of these */
+ Events(const Events &);
+ void operator=(Events &);
};
-enum evex_table_field
-{
- EVEX_FIELD_DB = 0,
- EVEX_FIELD_NAME,
- EVEX_FIELD_BODY,
- EVEX_FIELD_DEFINER,
- EVEX_FIELD_EXECUTE_AT,
- EVEX_FIELD_INTERVAL_EXPR,
- EVEX_FIELD_TRANSIENT_INTERVAL,
- EVEX_FIELD_CREATED,
- EVEX_FIELD_MODIFIED,
- EVEX_FIELD_LAST_EXECUTED,
- EVEX_FIELD_STARTS,
- EVEX_FIELD_ENDS,
- EVEX_FIELD_STATUS,
- EVEX_FIELD_ON_COMPLETION,
- EVEX_FIELD_SQL_MODE,
- EVEX_FIELD_COMMENT,
- EVEX_FIELD_COUNT /* a cool trick to count the number of fields :) */
-} ;
+
+
+class sp_head;
class Event_timed
{
@@ -82,12 +127,26 @@ class Event_timed
my_bool in_spawned_thread;
ulong locked_by_thread_id;
my_bool running;
+ ulong thread_id;
pthread_mutex_t LOCK_running;
+ pthread_cond_t COND_finished;
bool status_changed;
bool last_executed_changed;
public:
+ enum enum_status
+ {
+ ENABLED = 1,
+ DISABLED
+ };
+
+ enum enum_on_completion
+ {
+ ON_COMPLETION_DROP = 1,
+ ON_COMPLETION_PRESERVE
+ };
+
TIME last_executed;
LEX_STRING dbname;
@@ -111,8 +170,8 @@ public:
ulonglong created;
ulonglong modified;
- enum enum_event_on_completion on_completion;
- enum enum_event_status status;
+ enum enum_on_completion on_completion;
+ enum enum_status status;
sp_head *sphead;
ulong sql_mode;
const uchar *body_begin;
@@ -153,36 +212,15 @@ public:
DBUG_ASSERT(0);
}
+ Event_timed();
- Event_timed():in_spawned_thread(0),locked_by_thread_id(0),
- running(0), status_changed(false),
- last_executed_changed(false), expression(0), created(0),
- modified(0), on_completion(MYSQL_EVENT_ON_COMPLETION_DROP),
- status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0),
- body_begin(0), dropped(false),
- free_sphead_on_delete(true), flags(0)
-
- {
- pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
- init();
- }
-
- ~Event_timed()
- {
- deinit_mutexes();
-
- if (free_sphead_on_delete)
- free_sp();
- }
+ ~Event_timed();
void
init();
-
+
void
- deinit_mutexes()
- {
- pthread_mutex_destroy(&this->LOCK_running);
- }
+ deinit_mutexes();
int
init_definer(THD *thd);
@@ -214,12 +252,12 @@ public:
bool
compute_next_execution_time();
- void
- mark_last_executed(THD *thd);
-
int
drop(THD *thd);
+ void
+ mark_last_executed(THD *thd);
+
bool
update_fields(THD *thd);
@@ -227,142 +265,32 @@ public:
get_create_event(THD *thd, String *buf);
int
- execute(THD *thd, MEM_ROOT *mem_root= NULL);
+ execute(THD *thd, MEM_ROOT *mem_root);
int
- compile(THD *thd, MEM_ROOT *mem_root= NULL);
-
- my_bool
- is_running()
- {
- my_bool ret;
-
- VOID(pthread_mutex_lock(&this->LOCK_running));
- ret= running;
- VOID(pthread_mutex_unlock(&this->LOCK_running));
-
- return ret;
- }
-
- /*
- Checks whether the object is being used in a spawned thread.
- This method is for very basic checking. Use ::can_spawn_now_n_lock()
- for most of the cases.
- */
-
- my_bool
- can_spawn_now()
- {
- my_bool ret;
- VOID(pthread_mutex_lock(&this->LOCK_running));
- ret= !in_spawned_thread;
- VOID(pthread_mutex_unlock(&this->LOCK_running));
- return ret;
- }
+ compile(THD *thd, MEM_ROOT *mem_root);
- /*
- Checks whether this thread can lock the object for modification ->
- preventing being spawned for execution, and locks if possible.
- use ::can_spawn_now() only for basic checking because a race
- condition may occur between the check and eventual modification (deletion)
- of the object.
- */
-
- my_bool
- can_spawn_now_n_lock(THD *thd);
-
- int
- spawn_unlock(THD *thd);
+ bool
+ is_running();
int
- spawn_now(void * (*thread_func)(void*));
+ spawn_now(void * (*thread_func)(void*), void *arg);
- void
+ bool
spawn_thread_finish(THD *thd);
void
- free_sp()
- {
- delete sphead;
- sphead= 0;
- }
-protected:
+ free_sp();
+
bool
- change_security_context(THD *thd, Security_context *s_ctx,
- Security_context **backup);
+ has_equal_db(Event_timed *etn);
+
+ int
+ kill_thread(THD *thd);
void
- restore_security_context(THD *thd, Security_context *backup);
+ set_thread_id(ulong tid) { thread_id= tid; }
};
-int
-evex_create_event(THD *thd, Event_timed *et, uint create_options,
- uint *rows_affected);
-
-int
-evex_update_event(THD *thd, Event_timed *et, sp_name *new_name,
- uint *rows_affected);
-
-int
-evex_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
- uint *rows_affected);
-
-int
-evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
-
-int
-evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
-
-int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
-
-int
-event_reconstruct_interval_expression(String *buf,
- interval_type interval,
- longlong expression);
-
-int
-evex_drop_db_events(THD *thd, char *db);
-
-
-int
-init_events();
-
-void
-shutdown_events();
-
-
-// auxiliary
-int
-event_timed_compare(Event_timed **a, Event_timed **b);
-
-
-
-/*
-CREATE TABLE event (
- db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- name char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- body longblob NOT NULL,
- definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- execute_at DATETIME default NULL,
- interval_value int(11) default NULL,
- interval_field ENUM('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') default NULL,
- created TIMESTAMP NOT NULL,
- modified TIMESTAMP NOT NULL,
- last_executed DATETIME default NULL,
- starts DATETIME default NULL,
- ends DATETIME default NULL,
- status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
- on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
- comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
- PRIMARY KEY (definer,db,name)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
-*/
-
#endif /* _EVENT_H_ */
diff --git a/sql/event_executor.cc b/sql/event_executor.cc
index 21464dd777b..f236fb47771 100644
--- a/sql/event_executor.cc
+++ b/sql/event_executor.cc
@@ -13,998 +13,3 @@
You should have received a copy of the GNU General Public 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 "event_priv.h"
-#include "event.h"
-#include "sp.h"
-
-#define WAIT_STATUS_READY 0
-#define WAIT_STATUS_EMPTY_QUEUE 1
-#define WAIT_STATUS_NEW_TOP_EVENT 2
-#define WAIT_STATUS_STOP_EXECUTOR 3
-
-
-/*
- Make this define DBUG_FAULTY_THR to be able to put breakpoints inside
- code used by the scheduler's thread(s). In this case user connections
- are not possible because the scheduler thread code is ran inside the
- main thread (no spawning takes place. If you want to debug client
- connection then start with --one-thread and make the define
- DBUG_FAULTY_THR !
-*/
-#define DBUG_FAULTY_THR2
-
-extern ulong thread_created;
-extern const char *my_localhost;
-extern pthread_attr_t connection_attrib;
-
-pthread_mutex_t LOCK_event_arrays, // mutex for when working with the queue
- LOCK_workers_count, // mutex for when inc/dec uint workers_count
- LOCK_evex_running; // mutes for managing bool evex_is_running
-
-static pthread_mutex_t LOCK_evex_main_thread; // mutex for when working with the queue
-bool scheduler_main_thread_running= false;
-
-bool evex_is_running= false;
-
-ulonglong evex_main_thread_id= 0;
-ulong opt_event_executor;
-my_bool event_executor_running_global_var;
-static my_bool evex_mutexes_initted= FALSE;
-static uint workers_count;
-
-static int
-evex_load_events_from_db(THD *thd);
-
-bool
-evex_print_warnings(THD *thd, Event_timed *et);
-
-/*
- TODO Andrey: Check for command line option whether to start
- the main thread or not.
-*/
-
-pthread_handler_t
-event_executor_worker(void *arg);
-
-pthread_handler_t
-event_executor_main(void *arg);
-
-
-/*
- Returns the seconds difference of 2 TIME structs
-
- SYNOPSIS
- evex_time_diff()
- a - TIME struct 1
- b - TIME struct 2
-
- Returns:
- the seconds difference
-*/
-
-static int
-evex_time_diff(TIME *a, TIME *b)
-{
- return sec_since_epoch_TIME(a) - sec_since_epoch_TIME(b);
-}
-
-
-/*
- Inits the mutexes used by the scheduler module
-
- SYNOPSIS
- evex_init_mutexes()
-
- NOTES
- The mutexes are :
- LOCK_event_arrays
- LOCK_workers_count
- LOCK_evex_running
-*/
-
-static void
-evex_init_mutexes()
-{
- if (evex_mutexes_initted)
- return;
-
- evex_mutexes_initted= TRUE;
- pthread_mutex_init(&LOCK_event_arrays, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_workers_count, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_evex_running, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_evex_main_thread, MY_MUTEX_INIT_FAST);
-
- event_executor_running_global_var= opt_event_executor;
-}
-
-extern TABLE_FIELD_W_TYPE mysql_db_table_fields[];
-extern time_t mysql_db_table_last_check;
-
-/*
- Opens mysql.db and mysql.user and checks whether
- 1. mysql.db has column Event_priv at column 20 (0 based);
- 2. mysql.user has column Event_priv at column 29 (0 based);
-
- Synopsis
- evex_check_system_tables()
-*/
-
-void
-evex_check_system_tables()
-{
- THD *thd= current_thd;
- TABLE_LIST tables;
- Open_tables_state backup;
-
- /* thd is 0x0 during boot of the server. Later it's !=0x0 */
- if (!thd)
- return;
-
- thd->reset_n_backup_open_tables_state(&backup);
-
- bzero((char*) &tables, sizeof(tables));
- tables.db= (char*) "mysql";
- tables.table_name= tables.alias= (char*) "db";
- tables.lock_type= TL_READ;
-
- if (simple_open_n_lock_tables(thd, &tables))
- sql_print_error("Cannot open mysql.db");
- else
- {
- table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT, mysql_db_table_fields,
- &mysql_db_table_last_check,ER_CANNOT_LOAD_FROM_TABLE);
- close_thread_tables(thd);
- }
-
- bzero((char*) &tables, sizeof(tables));
- tables.db= (char*) "mysql";
- tables.table_name= tables.alias= (char*) "user";
- tables.lock_type= TL_READ;
-
- if (simple_open_n_lock_tables(thd, &tables))
- sql_print_error("Cannot open mysql.db");
- else
- {
- if (tables.table->s->fields < 29 ||
- strncmp(tables.table->field[29]->field_name,
- STRING_WITH_LEN("Event_priv")))
- sql_print_error("mysql.user has no `Event_priv` column at position 29");
-
- close_thread_tables(thd);
- }
-
- thd->restore_backup_open_tables_state(&backup);
-}
-
-
-/*
- Inits the scheduler. Called on server start and every time the scheduler
- is started with switching the event_scheduler global variable to TRUE
-
- SYNOPSIS
- init_events()
-
- NOTES
- Inits the mutexes used by the scheduler. Done at server start.
-*/
-
-int
-init_events()
-{
- pthread_t th;
- DBUG_ENTER("init_events");
-
- DBUG_PRINT("info",("Starting events main thread"));
-
- evex_check_system_tables();
-
- evex_init_mutexes();
-
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- evex_is_running= false;
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- if (event_executor_running_global_var)
- {
-#ifndef DBUG_FAULTY_THR
- /* TODO Andrey: Change the error code returned! */
- if (pthread_create(&th, &connection_attrib, event_executor_main,(void*)NULL))
- DBUG_RETURN(ER_SLAVE_THREAD);
-#else
- event_executor_main(NULL);
-#endif
- }
-
- DBUG_RETURN(0);
-}
-
-
-/*
- Cleans up scheduler memory. Called on server shutdown.
-
- SYNOPSIS
- shutdown_events()
-
- NOTES
- Destroys the mutexes.
-*/
-
-void
-shutdown_events()
-{
- DBUG_ENTER("shutdown_events");
-
- if (evex_mutexes_initted)
- {
- evex_mutexes_initted= FALSE;
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- pthread_mutex_destroy(&LOCK_event_arrays);
- pthread_mutex_destroy(&LOCK_workers_count);
- pthread_mutex_destroy(&LOCK_evex_running);
- pthread_mutex_destroy(&LOCK_evex_main_thread);
- }
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Inits an scheduler thread handler, both the main and a worker
-
- SYNOPSIS
- init_event_thread()
- thd - the THD of the thread. Has to be allocated by the caller.
-
- NOTES
- 1. The host of the thead is my_localhost
- 2. thd->net is initted with NULL - no communication.
-
- Returns
- 0 - OK
- -1 - Error
-*/
-
-static int
-init_event_thread(THD* thd)
-{
- DBUG_ENTER("init_event_thread");
- thd->client_capabilities= 0;
- thd->security_ctx->master_access= 0;
- thd->security_ctx->db_access= 0;
- thd->security_ctx->host_or_ip= (char*)my_localhost;
- my_net_init(&thd->net, 0);
- thd->net.read_timeout = slave_net_timeout;
- thd->slave_thread= 0;
- thd->options|= OPTION_AUTO_IS_NULL;
- thd->client_capabilities= CLIENT_LOCAL_FILES;
- thd->real_id=pthread_self();
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->thread_id= thread_id++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
- if (init_thr_lock() || thd->store_globals())
- {
- thd->cleanup();
- delete thd;
- DBUG_RETURN(-1);
- }
-
-#if !defined(__WIN__) && !defined(__NETWARE__)
- sigset_t set;
- VOID(sigemptyset(&set)); // Get mask in use
- VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
-
- thd->proc_info= "Initialized";
- thd->version= refresh_version;
- thd->set_time();
- DBUG_RETURN(0);
-}
-
-
-/*
- This function waits till the time next event in the queue should be
- executed.
-
- Returns
- WAIT_STATUS_READY There is an event to be executed right now
- WAIT_STATUS_EMPTY_QUEUE No events or the last event was dropped.
- WAIT_STATUS_NEW_TOP_EVENT New event has entered the queue and scheduled
- on top. Restart ticking.
- WAIT_STATUS_STOP_EXECUTOR The thread was killed or SET global event_scheduler=0;
-*/
-
-static int
-executor_wait_till_next_event_exec(THD *thd)
-{
- Event_timed *et;
- TIME time_now;
- int t2sleep;
-
- DBUG_ENTER("executor_wait_till_next_event_exec");
- /*
- now let's see how much time to sleep, we know there is at least 1
- element in the queue.
- */
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
- {
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- DBUG_RETURN(WAIT_STATUS_EMPTY_QUEUE);
- }
- et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
- DBUG_ASSERT(et);
- if (et->status == MYSQL_EVENT_DISABLED)
- {
- DBUG_PRINT("evex main thread",("Now it is disabled-exec no more"));
- if (et->dropped)
- et->drop(thd);
- delete et;
- evex_queue_delete_element(&EVEX_EQ_NAME, 0);// 0 is top, internally 1
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- sql_print_information("Event found disabled, dropping.");
- DBUG_RETURN(1);
- }
-
- DBUG_PRINT("evex main thread",("computing time to sleep till next exec"));
- /* set the internal clock of thd */
- thd->end_time();
- my_tz_UTC->gmt_sec_to_TIME(&time_now, thd->query_start());
- t2sleep= evex_time_diff(&et->execute_at, &time_now);
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
-
- t2sleep*=20;
- DBUG_PRINT("evex main thread",("unlocked LOCK_event_arrays"));
- if (t2sleep > 0)
- {
- ulonglong modified= et->modified;
- /*
- We sleep t2sleep seconds but we check every second whether this thread
- has been killed, or there is a new candidate
- */
- while (t2sleep-- && !thd->killed && event_executor_running_global_var &&
- evex_queue_num_elements(EVEX_EQ_NAME) &&
- (evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*) == et &&
- evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*)->modified ==
- modified))
- {
- DBUG_PRINT("evex main thread",("will sleep a bit more."));
- my_sleep(50000);
- }
- DBUG_PRINT("info",("saved_modified=%llu current=%llu", modified,
- evex_queue_num_elements(EVEX_EQ_NAME)?
- evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*)->modified:
- (ulonglong)~0));
- }
-
- int ret= WAIT_STATUS_READY;
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
- ret= WAIT_STATUS_EMPTY_QUEUE;
- else if (evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*) != et)
- ret= WAIT_STATUS_NEW_TOP_EVENT;
- if (thd->killed && event_executor_running_global_var)
- ret= WAIT_STATUS_STOP_EXECUTOR;
-
- DBUG_RETURN(ret);
-}
-
-
-/*
- The main scheduler thread. Inits the priority queue on start and
- destroys it on thread shutdown. Forks child threads for every event
- execution. Sleeps between thread forking and does not do a busy wait.
-
- SYNOPSIS
- event_executor_main()
- arg unused
-
- NOTES
- 1. The host of the thead is my_localhost
- 2. thd->net is initted with NULL - no communication.
-
-*/
-
-pthread_handler_t
-event_executor_main(void *arg)
-{
- THD *thd; /* needs to be first for thread_stack */
- uint i=0, j=0;
- my_ulonglong cnt= 0;
-
- DBUG_ENTER("event_executor_main");
- DBUG_PRINT("event_executor_main", ("EVEX thread started"));
-
- pthread_mutex_lock(&LOCK_evex_main_thread);
- if (!scheduler_main_thread_running)
- scheduler_main_thread_running= true;
- else
- {
- DBUG_PRINT("event_executor_main", ("already running. thd_id=%d",
- evex_main_thread_id));
- pthread_mutex_unlock(&LOCK_evex_main_thread);
- my_thread_end();
- pthread_exit(0);
- DBUG_RETURN(0); // Can't return anything here
- }
- pthread_mutex_unlock(&LOCK_evex_main_thread);
-
- /* init memory root */
- init_alloc_root(&evex_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
-
- /* needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff*/
- my_thread_init();
-
- if (sizeof(my_time_t) != sizeof(time_t))
- {
- sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
- "The scheduler will not work correctly. Stopping.");
- DBUG_ASSERT(0);
- goto err_no_thd;
- }
-
- /* note that contructor of THD uses DBUG_ ! */
- if (!(thd = new THD))
- {
- sql_print_error("SCHEDULER: Cannot create THD for the main thread.");
- goto err_no_thd;
- }
- thd->thread_stack = (char*)&thd; // remember where our stack is
-
- pthread_detach_this_thread();
-
- if (init_event_thread(thd))
- goto finish;
-
- /*
- make this thread visible it has no vio -> show processlist won't see it
- unless it's marked as system thread
- */
- thd->system_thread= 1;
-
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- threads.append(thd);
- thread_count++;
- thread_running++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
- DBUG_PRINT("EVEX main thread", ("Initing events_queue"));
-
- /*
- eventually manifest that we are running, not to crashe because of
- usage of non-initialized memory structures.
- */
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
- evex_queue_init(&EVEX_EQ_NAME);
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- evex_is_running= true;
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- thd->security_ctx->user= my_strdup("event_scheduler", MYF(0));
-
- if (evex_load_events_from_db(thd))
- goto finish;
-
- evex_main_thread_id= thd->thread_id;
-
- sql_print_information("SCHEDULER: Main thread started");
- while (!thd->killed)
- {
- TIME time_now;
- Event_timed *et;
-
- cnt++;
- DBUG_PRINT("info", ("EVEX External Loop %d thd->k", cnt));
-
- thd->proc_info = "Sleeping";
- if (!event_executor_running_global_var)
- {
- sql_print_information("SCHEDULER: Asked to stop.");
- break;
- }
-
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
- {
- my_sleep(100000);// sleep 0.1s
- continue;
- }
-
-restart_ticking:
- switch (executor_wait_till_next_event_exec(thd)) {
- case WAIT_STATUS_READY: // time to execute the event on top
- DBUG_PRINT("evex main thread",("time to execute an event"));
- break;
- case WAIT_STATUS_EMPTY_QUEUE: // no more events
- DBUG_PRINT("evex main thread",("no more events"));
- continue;
- break;
- case WAIT_STATUS_NEW_TOP_EVENT: // new event on top in the queue
- DBUG_PRINT("evex main thread",("restart ticking"));
- goto restart_ticking;
- case WAIT_STATUS_STOP_EXECUTOR:
- sql_print_information("SCHEDULER: Asked to stop.");
- goto finish;
- break;
- default:
- DBUG_ASSERT(0);
- }
-
-
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
- thd->end_time();
- my_tz_UTC->gmt_sec_to_TIME(&time_now, thd->query_start());
-
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
- {
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- DBUG_PRINT("evex main thread",("empty queue"));
- continue;
- }
- et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
- DBUG_PRINT("evex main thread",("got event from the queue"));
-
- if (!et->execute_at_null && my_time_compare(&time_now,&et->execute_at) == -1)
- {
- DBUG_PRINT("evex main thread",("still not the time for execution"));
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- continue;
- }
-
- DBUG_PRINT("evex main thread",("it's right time"));
- if (et->status == MYSQL_EVENT_ENABLED)
- {
- int fork_ret_code;
-
- DBUG_PRINT("evex main thread", ("[%10s] this exec at [%llu]", et->name.str,
- TIME_to_ulonglong_datetime(&et->execute_at)));
- et->mark_last_executed(thd);
- if (et->compute_next_execution_time())
- {
- sql_print_error("SCHEDULER: Error while computing time of %s.%s . "
- "Disabling after execution.",
- et->dbname.str, et->name.str);
- et->status= MYSQL_EVENT_DISABLED;
- }
- DBUG_PRINT("evex main thread", ("[%10s] next exec at [%llu]", et->name.str,
- TIME_to_ulonglong_datetime(&et->execute_at)));
-
- et->update_fields(thd);
-#ifndef DBUG_FAULTY_THR
- thread_safe_increment(workers_count, &LOCK_workers_count);
- switch ((fork_ret_code= et->spawn_now(event_executor_worker))) {
- case EVENT_EXEC_CANT_FORK:
- thread_safe_decrement(workers_count, &LOCK_workers_count);
- sql_print_error("SCHEDULER: Problem while trying to create a thread");
- UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_event_arrays, finish);
- case EVENT_EXEC_ALREADY_EXEC:
- thread_safe_decrement(workers_count, &LOCK_workers_count);
- sql_print_information("SCHEDULER: %s.%s in execution. Skip this time.",
- et->dbname.str, et->name.str);
- break;
- default:
- DBUG_ASSERT(!fork_ret_code);
- if (fork_ret_code)
- thread_safe_decrement(workers_count, &LOCK_workers_count);
- break;
- }
-#else
- event_executor_worker((void *) et);
-#endif
- /*
- 1. For one-time event : year is > 0 and expression is 0
- 2. For recurring, expression is != -=> check execute_at_null in this case
- */
- if ((et->execute_at.year && !et->expression) || et->execute_at_null)
- et->flags |= EVENT_EXEC_NO_MORE;
-
- if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == MYSQL_EVENT_DISABLED)
- evex_queue_delete_element(&EVEX_EQ_NAME, 0);// 0 is top, internally 1
- else
- evex_queue_first_updated(&EVEX_EQ_NAME);
- }
- DBUG_PRINT("evex main thread",("unlocking"));
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- }/* while */
-finish:
-
- /* First manifest that this thread does not work and then destroy */
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- evex_is_running= false;
- evex_main_thread_id= 0;
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
-
- /*
- TODO: A better will be with a conditional variable
- */
- /*
- Read workers_count without lock, no need for locking.
- In the worst case we have to wait 1sec more.
- */
- sql_print_information("SCHEDULER: Stopping. Waiting for worker threads to finish.");
- while (1)
- {
- VOID(pthread_mutex_lock(&LOCK_workers_count));
- if (!workers_count)
- {
- VOID(pthread_mutex_unlock(&LOCK_workers_count));
- break;
- }
- VOID(pthread_mutex_unlock(&LOCK_workers_count));
- my_sleep(1000000);// 1s
- }
-
- /*
- First we free all objects ...
- Lock because a DROP DATABASE could be running in parallel and it locks on these
- */
- sql_print_information("SCHEDULER: Emptying the queue.");
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
- {
- Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
- et->free_sp();
- delete et;
- }
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- /* ... then we can thrash the whole queue at once */
- evex_queue_destroy(&EVEX_EQ_NAME);
-
- thd->proc_info = "Clearing";
- DBUG_ASSERT(thd->net.buff != 0);
- net_end(&thd->net); // destructor will not free it, because we are weird
- THD_CHECK_SENTRY(thd);
-
- pthread_mutex_lock(&LOCK_thread_count);
- thread_count--;
- thread_running--;
-#ifndef DBUG_FAULTY_THR
- THD_CHECK_SENTRY(thd);
- delete thd;
-#endif
- pthread_mutex_unlock(&LOCK_thread_count);
-
-
-err_no_thd:
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- evex_is_running= false;
- event_executor_running_global_var= false;
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- free_root(&evex_mem_root, MYF(0));
- sql_print_information("SCHEDULER: Stopped.");
-
-#ifndef DBUG_FAULTY_THR
- pthread_mutex_lock(&LOCK_evex_main_thread);
- scheduler_main_thread_running= false;
- pthread_mutex_unlock(&LOCK_evex_main_thread);
-
- my_thread_end();
- pthread_exit(0);
-#endif
- DBUG_RETURN(0); // Can't return anything here
-}
-
-
-/*
- Function that executes an event in a child thread. Setups the
- environment for the event execution and cleans after that.
-
- SYNOPSIS
- event_executor_worker()
- arg The Event_timed object to be processed
-*/
-
-pthread_handler_t
-event_executor_worker(void *event_void)
-{
- THD *thd; /* needs to be first for thread_stack */
- Event_timed *event = (Event_timed *) event_void;
- MEM_ROOT worker_mem_root;
-
- DBUG_ENTER("event_executor_worker");
-
- init_alloc_root(&worker_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
-
-#ifndef DBUG_FAULTY_THR
- my_thread_init();
-
- if (!(thd = new THD)) /* note that contructor of THD uses DBUG_ ! */
- {
- sql_print_error("SCHEDULER: Cannot create a THD structure in an worker.");
- goto err_no_thd;
- }
- thd->thread_stack = (char*)&thd; // remember where our stack is
- thd->mem_root= &worker_mem_root;
-
- pthread_detach_this_thread();
-
- if (init_event_thread(thd))
- goto err;
-
- thd->init_for_queries();
-
- /* make this thread visible it has no vio -> show processlist needs this flag */
- thd->system_thread= 1;
-
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- threads.append(thd);
- thread_count++;
- thread_running++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-#else
- thd= current_thd;
-#endif
-
- thd->enable_slow_log= TRUE;
- {
- int ret;
- sql_print_information("SCHEDULER: Executing event %s.%s of %s [EXPR:%d]",
- event->dbname.str, event->name.str,
- event->definer.str, (int) event->expression);
-
- ret= event->execute(thd, &worker_mem_root);
-
- evex_print_warnings(thd, event);
- sql_print_information("SCHEDULER: Executed event %s.%s of %s [EXPR:%d]. "
- "RetCode=%d", event->dbname.str, event->name.str,
- event->definer.str, (int) event->expression, ret);
- if (ret == EVEX_COMPILE_ERROR)
- sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of",
- event->dbname.str, event->name.str,
- event->definer.str);
- else if (ret == EVEX_MICROSECOND_UNSUP)
- sql_print_information("SCHEDULER: MICROSECOND is not supported");
- }
- event->spawn_thread_finish(thd);
-
-
-err:
- VOID(pthread_mutex_lock(&LOCK_thread_count));
-#ifndef DBUG_FAULTY_THR
- thread_count--;
- thread_running--;
- /*
- 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)).
- */
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
- thd->proc_info = "Clearing";
- DBUG_ASSERT(thd->net.buff != 0);
- net_end(&thd->net); // destructor will not free it, because we are weird
- THD_CHECK_SENTRY(thd);
-
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- THD_CHECK_SENTRY(thd);
- delete thd;
-#endif
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
-err_no_thd:
-
- free_root(&worker_mem_root, MYF(0));
- thread_safe_decrement(workers_count, &LOCK_workers_count);
-
-#ifndef DBUG_FAULTY_THR
- my_thread_end();
- pthread_exit(0);
-#endif
- DBUG_RETURN(0); // Can't return anything here
-}
-
-
-/*
- Loads all ENABLED events from mysql.event into the prioritized
- queue. Called during scheduler main thread initialization. Compiles
- the events. Creates Event_timed instances for every ENABLED event
- from mysql.event.
-
- SYNOPSIS
- evex_load_events_from_db()
- thd - Thread context. Used for memory allocation in some cases.
-
- RETURNS
- 0 OK
- !0 Error
-
- NOTES
- Reports the error to the console
-*/
-
-static int
-evex_load_events_from_db(THD *thd)
-{
- TABLE *table;
- READ_RECORD read_record_info;
- int ret= -1;
- uint count= 0;
-
- DBUG_ENTER("evex_load_events_from_db");
-
- if ((ret= evex_open_event_table(thd, TL_READ, &table)))
- {
- sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
- }
-
- VOID(pthread_mutex_lock(&LOCK_event_arrays));
-
- init_read_record(&read_record_info, thd, table ,NULL,1,0);
- while (!(read_record_info.read_record(&read_record_info)))
- {
- Event_timed *et;
- if (!(et= new Event_timed))
- {
- DBUG_PRINT("evex_load_events_from_db", ("Out of memory"));
- ret= -1;
- goto end;
- }
- DBUG_PRINT("evex_load_events_from_db", ("Loading event from row."));
-
- if ((ret= et->load_from_row(&evex_mem_root, table)))
- {
- sql_print_error("SCHEDULER: Error while loading from mysql.event. "
- "Table probably corrupted");
- goto end;
- }
- if (et->status != MYSQL_EVENT_ENABLED)
- {
- DBUG_PRINT("evex_load_events_from_db",("%s is disabled",et->name.str));
- delete et;
- continue;
- }
-
- DBUG_PRINT("evex_load_events_from_db",
- ("Event %s loaded from row. Time to compile", et->name.str));
-
- switch (ret= et->compile(thd, &evex_mem_root)) {
- case EVEX_MICROSECOND_UNSUP:
- sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
- "supported but found in mysql.event");
- goto end;
- case EVEX_COMPILE_ERROR:
- sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
- et->dbname.str, et->name.str);
- goto end;
- default:
- break;
- }
-
- /* let's find when to be executed */
- if (et->compute_next_execution_time())
- {
- sql_print_error("SCHEDULER: Error while computing execution time of %s.%s."
- " Skipping", et->dbname.str, et->name.str);
- continue;
- }
-
- DBUG_PRINT("evex_load_events_from_db", ("Adding to the exec list."));
-
- evex_queue_insert(&EVEX_EQ_NAME, (EVEX_PTOQEL) et);
- DBUG_PRINT("evex_load_events_from_db", ("%p %*s",
- et, et->name.length,et->name.str));
- count++;
- }
-
- ret= 0;
-
-end:
- VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- end_read_record(&read_record_info);
-
- /* Force close to free memory */
- thd->version--;
-
- close_thread_tables(thd);
- if (!ret)
- sql_print_information("SCHEDULER: Loaded %d event%s", count, (count == 1)?"":"s");
- DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
-
- DBUG_RETURN(ret);
-}
-
-
-/*
- The update method of the global variable event_scheduler.
- If event_scheduler is switched from 0 to 1 then the scheduler main
- thread is started.
-
- SYNOPSIS
- event_executor_worker()
- thd - Thread context (unused)
- car - the new value
-
- Returns
- 0 OK (always)
-*/
-
-bool
-sys_var_event_executor::update(THD *thd, set_var *var)
-{
- /* here start the thread if not running. */
- DBUG_ENTER("sys_var_event_executor::update");
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- *value= var->save_result.ulong_value;
-
- DBUG_PRINT("new_value", ("%d", *value));
- if ((my_bool) *value && !evex_is_running)
- {
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
- init_events();
- } else
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- DBUG_RETURN(0);
-}
-
-
-extern LEX_STRING warning_level_names[];
-
-typedef void (*sql_print_xxx_func)(const char *format, ...);
-static sql_print_xxx_func sql_print_xxx_handlers[3] =
-{
- sql_print_information,
- sql_print_warning,
- sql_print_error
-};
-
-
-/*
- Prints the stack of infos, warnings, errors from thd to
- the console so it can be fetched by the logs-into-tables and
- checked later.
-
- Synopsis
- evex_print_warnings
- thd - thread used during the execution of the event
- et - the event itself
-
- Returns
- 0 - OK (always)
-
-*/
-
-bool
-evex_print_warnings(THD *thd, Event_timed *et)
-{
- MYSQL_ERROR *err;
- DBUG_ENTER("evex_show_warnings");
- char msg_buf[1024];
- char prefix_buf[512];
- String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
- prefix.length(0);
-
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
- while ((err= it++))
- {
- String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
- /* set it to 0 or we start adding at the end. That's the trick ;) */
- err_msg.length(0);
- if (!prefix.length())
- {
- prefix.append("SCHEDULER: [");
-
- append_identifier(thd,&prefix,et->definer_user.str,et->definer_user.length);
- prefix.append('@');
- append_identifier(thd,&prefix,et->definer_host.str,et->definer_host.length);
- prefix.append("][", 2);
- append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
- prefix.append('.');
- append_identifier(thd,&prefix, et->name.str, et->name.length);
- prefix.append("] ", 2);
- }
-
- err_msg.append(prefix);
- err_msg.append(err->msg, strlen(err->msg), system_charset_info);
- err_msg.append("]");
- DBUG_ASSERT(err->level < 3);
- (sql_print_xxx_handlers[err->level])("%*s", err_msg.length(), err_msg.c_ptr());
- }
-
-
- DBUG_RETURN(FALSE);
-}
diff --git a/sql/event_priv.h b/sql/event_priv.h
index 6b23136847e..43ef30a659f 100644
--- a/sql/event_priv.h
+++ b/sql/event_priv.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2004-2005 MySQL AB
+#ifndef _EVENT_PRIV_H_
+#define _EVENT_PRIV_H_
+/* Copyright (C) 2004-2006 MySQL AB
This 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,8 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef _EVENT_PRIV_H_
-#define _EVENT_PRIV_H_
#include "mysql_priv.h"
@@ -23,11 +23,6 @@
#define EVENT_EXEC_ALREADY_EXEC 1
#define EVENT_EXEC_CANT_FORK 2
-#define EVEX_USE_QUEUE
-
-#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
- { VOID(pthread_mutex_unlock(&__mutex)); goto __label; }
-
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
@@ -38,45 +33,54 @@ my_time_compare(TIME *a, TIME *b);
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
- const LEX_STRING user_name,
TABLE *table);
int
event_timed_compare_q(void *vptr, byte* a, byte *b);
-int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
- uint *rows_affected);
-
+int
+db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
+ uint *rows_affected);
+int
+db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
+ MEM_ROOT *root);
-#define EXEC_QUEUE_QUEUE_NAME executing_queue
-#define EXEC_QUEUE_DARR_NAME evex_executing_queue
+int
+db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
+ uint *rows_affected);
+int
+db_drop_events_from_table(THD *thd, LEX_STRING *db);
-#define EVEX_QUEUE_TYPE QUEUE
-#define EVEX_PTOQEL byte *
+int
+sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
-#define EVEX_EQ_NAME executing_queue
-#define evex_queue_first_element(queue, __cast) ((__cast)queue_top(queue))
-#define evex_queue_element(queue, idx, __cast) ((__cast)queue_element(queue, idx))
-#define evex_queue_delete_element(queue, idx) queue_remove(queue, idx)
-#define evex_queue_destroy(queue) delete_queue(queue)
-#define evex_queue_first_updated(queue) queue_replaced(queue)
-#define evex_queue_insert(queue, element) queue_insert_safe(queue, element);
+/* Compares only the name part of the identifier */
+bool
+event_timed_name_equal(Event_timed *et, LEX_STRING *name);
+/* Compares only the schema part of the identifier */
+bool
+event_timed_db_equal(Event_timed *et, LEX_STRING *db);
+/*
+ Compares only the definer part of the identifier. Use during DROP USER
+ to drop user's events. (Still not implemented)
+*/
+bool
+event_timed_definer_equal(Event_timed *et, LEX_STRING *definer);
-void
-evex_queue_init(EVEX_QUEUE_TYPE *queue);
+/* Compares the whole identifier*/
+bool
+event_timed_identifier_equal(Event_timed *a, Event_timed *b);
-#define evex_queue_num_elements(queue) queue.elements
+bool
+change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
+ LEX_STRING db, Security_context *s_ctx,
+ Security_context **backup);
-extern bool evex_is_running;
-extern MEM_ROOT evex_mem_root;
-extern pthread_mutex_t LOCK_event_arrays,
- LOCK_workers_count,
- LOCK_evex_running;
-extern ulonglong evex_main_thread_id;
-extern QUEUE EVEX_EQ_NAME;
+void
+restore_security_context(THD *thd, Security_context *backup);
#endif /* _EVENT_PRIV_H_ */
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
new file mode 100644
index 00000000000..e360254fdd2
--- /dev/null
+++ b/sql/event_scheduler.cc
@@ -0,0 +1,2426 @@
+/* Copyright (C) 2004-2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 "event_priv.h"
+#include "event.h"
+#include "event_scheduler.h"
+#include "sp_head.h"
+
+/*
+ ToDo:
+ 1. Talk to Alik to get a check for configure.in for my_time_t and time_t
+ 2. Look at guardian.h|cc to see its life cycle, has similarities.
+*/
+
+
+/*
+ The scheduler is implemented as class Event_scheduler. Only one instance is
+ kept during the runtime of the server, by implementing the Singleton DP.
+ Object instance is always there because the memory is allocated statically
+ and initialized when the OS loader loads mysqld. This initialization is
+ bare. Extended initialization is done during the call to
+ Event_scheduler::init() in Events::init(). The reason for that late initialization
+ is that some subsystems needed to boot the Scheduler are not available at
+ earlier stages of the mysqld boot procedure. Events::init() is called in
+ mysqld.cc . If the mysqld is started with --event-scheduler=0 then
+ no initialization takes place and the scheduler is unavailable during this
+ server run. The server should be started with --event-scheduler=1 to have
+ the scheduler initialized and able to execute jobs. This starting alwa
+ s implies that the jobs execution will start immediately. If the server
+ is started with --event-scheduler=2 then the scheduler is started in suspended
+ state. Default state, if --event-scheduler is not specified is 2.
+
+ The scheduler only manages execution of the events. Their creation,
+ alteration and deletion is delegated to other routines found in event.cc .
+ These routines interact with the scheduler :
+ - CREATE EVENT -> Event_scheduler::add_event()
+ - ALTER EVENT -> Event_scheduler::replace_event()
+ - DROP EVENT -> Event_scheduler::drop_event()
+
+ There is one mutex in the single Event_scheduler object which controls
+ the simultaneous access to the objects invariants. Using one lock makes
+ it easy to follow the workflow. This mutex is LOCK_scheduler_data. It is
+ initialized in Event_scheduler::init(). Which in turn is called by the
+ Facade class Events in event.cc, coming from init_thread_environment() from
+ mysqld.cc -> no concurrency at this point. It's destroyed in
+ Events::destroy_mutexes() called from clean_up_mutexes() in mysqld.cc .
+
+ The full initialization is done in Event_scheduler::init() called from
+ Events::init(). It's done before any requests coming in, so this is a
+ guarantee for not having concurrency.
+
+ The scheduler is started with Event_scheduler::start() and stopped with
+ Event_scheduler::stop(). When the scheduler starts it loads all events
+ from mysql.event table. Unfortunately, there is a race condition between
+ the event disk management functions and the scheduler ones
+ (add/replace/drop_event & load_events_from_db()), because the operations
+ do not happen under one global lock but the disk operations are guarded
+ by the MYISAM lock on mysql.event. In the same time, the queue operations
+ are guarded by LOCK_scheduler_data. If the scheduler is start()-ed during
+ server startup and stopped()-ed during server shutdown (in Events::shutdown()
+ called by kill_server() in mysqld.cc) these races does not exist.
+
+ Since the user may want to temporarily inhibit execution of events the
+ scheduler can be suspended and then it can be forced to resume its
+ operations. The API call to perform these is
+ Event_scheduler::suspend_or_resume(enum enum_suspend_or_resume) .
+ When the scheduler is suspended the main scheduler thread, which ATM
+ happens to have thread_id 1, locks on a condition COND_suspend_or_resume.
+ When this is signal is sent for the reverse operation the main scheduler
+ loops continues to roll and execute events.
+
+ When the scheduler is suspended all add/replace/drop_event() operations
+ work as expected and the modify the queue but no events execution takes
+ place.
+
+ In contrast to the previous scheduler implementation, found in
+ event_executor.cc, the start, shutdown, suspend and resume are synchronous
+ operations. As a whole all operations are synchronized and no busy waits
+ are used except in stop_all_running_events(), which waits until all
+ running event worker threads have finished. It would have been nice to
+ use a conditional on which this method will wait and the last thread to
+ finish would signal it but this implies subclassing THD.
+
+ The scheduler does not keep a counter of how many event worker threads are
+ running, at any specific moment, because this will copy functionality
+ already existing in the server. Namely, all THDs are registered in the
+ global `threads` array. THD has member variable system_thread which
+ identifies the type of thread. Connection threads being NON_SYSTEM_THREAD,
+ all other have their enum value. Important for the scheduler are
+ SYSTEM_THREAD_EVENT_SCHEDULER and SYSTEM_THREAD_EVENT_WORKER.
+
+ Class THD subclasses class ilink, which is the linked list of all threads.
+ When a THD instance is destroyed it's being removed from threads, thus
+ no manual intervention is needed. On the contrary registering is manual
+ with threads.append() . Traversing the threads array every time a subclass
+ of THD, for instance if we would have had THD_scheduler_worker to see
+ how many events we have and whether the scheduler is shutting down will
+ take much time and lead to a deadlock. stop_all_running_events() is called
+ under LOCK_scheduler_data. If the THD_scheduler_worker was aware of
+ the single Event_scheduler instance it will try to check
+ Event_scheduler::state but for this it would need to acquire
+ LOCK_scheduler_data => deadlock. Thus stop_all_running_events() uses a
+ busy wait.
+
+ DROP DATABASE DDL should drop all events defined in a specific schema.
+ DROP USER also should drop all events who has as definer the user being
+ dropped (this one is not addressed at the moment but a hook exists). For
+ this specific needs Event_scheduler::drop_matching_events() is
+ implemented. Which expects a callback to be applied on every object in
+ the queue. Thus events that match specific schema or user, will be
+ removed from the queue. The exposed interface is :
+ - Event_scheduler::drop_schema_events()
+ - Event_scheduler::drop_user_events()
+
+ This bulk dropping happens under LOCK_scheduler_data, thus no two or
+ more threads can execute it in parallel. However, DROP DATABASE is also
+ synchronized, currently, in the server thus this does not impact the
+ overall performance. In addition, DROP DATABASE is not that often
+ executed DDL.
+
+ Though the interface to the scheduler is only through the public methods
+ of class Event_scheduler, there are currently few functions which are
+ used during its operations. Namely :
+ - static evex_print_warnings()
+ After every event execution all errors/warnings are dumped, so the user
+ can see in case of a problem what the problem was.
+
+ - static init_event_thread()
+ This function is both used by event_scheduler_thread() and
+ event_worker_thread(). It initializes the THD structure. The
+ initialization looks pretty similar to the one in slave.cc done for the
+ replication threads. However, though the similarities it cannot be
+ factored out to have one routine.
+
+ - static event_scheduler_thread()
+ Because our way to register functions to be used by the threading library
+ does not allow usage of static methods this function is used to start the
+ scheduler in it. It does THD initialization and then calls
+ Event_scheduler::run().
+
+ - static event_worker_thread()
+ With already stated the reason for not being able to use methods, this
+ function executes the worker threads.
+
+ The execution of events is, to some extent, synchronized to inhibit race
+ conditions when Event_timed::thread_id is being updated with the thread_id of
+ the THD in which the event is being executed. The thread_id is in the
+ Event_timed object because we need to be able to kill quickly a specific
+ event during ALTER/DROP EVENT without traversing the global `threads` array.
+ However, this makes the scheduler's code more complicated. The event worker
+ thread is started by Event_timed::spawn_now(), which in turn calls
+ pthread_create(). The thread_id which will be associated in init_event_thread
+ is not known in advance thus the registering takes place in
+ event_worker_thread(). This registering has to be synchronized under
+ LOCK_scheduler_data, so no kill_event() on a object in
+ replace_event/drop_event/drop_matching_events() could take place.
+
+ This synchronization is done through class Worker_thread_param that is
+ local to this file. Event_scheduler::execute_top() is called under
+ LOCK_scheduler_data. This method :
+ 1. Creates an instance of Worker_thread_param on the stack
+ 2. Locks Worker_thread_param::LOCK_started
+ 3. Calls Event_timed::spawn_now() which in turn creates a new thread.
+ 4. Locks on Worker_thread_param::COND_started_or_stopped and waits till the
+ worker thread send signal. The code is spurious wake-up safe because
+ Worker_thread_param::started is checked.
+ 5. The worker thread initializes its THD, then sets Event_timed::thread_id,
+ sets Worker_thread_param::started to TRUE and sends back
+ Worker_thread_param::COND_started. From this moment on, the event
+ is being executed and could be killed by using Event_timed::thread_id.
+ When Event_timed::spawn_thread_finish() is called in the worker thread,
+ it sets thread_id to 0. From this moment on, the worker thread should not
+ touch the Event_timed instance.
+
+
+ The life-cycle of the server is a FSA.
+ enum enum_state Event_scheduler::state keeps the state of the scheduler.
+
+ The states are:
+
+ |---UNINITIALIZED
+ |
+ | |------------------> IN_SHUTDOWN
+ --> INITIALIZED -> COMMENCING ---> RUNNING ----------|
+ ^ ^ | | ^ |
+ | |- CANTSTART <--| | |- SUSPENDED <-|
+ |______________________________|
+
+ - UNINITIALIZED :The object is created and only the mutex is initialized
+ - INITIALIZED :All member variables are initialized
+ - COMMENCING :The scheduler is starting, no other attempt to start
+ should succeed before the state is back to INITIALIZED.
+ - CANTSTART :Set by the ::run() method in case it can't start for some
+ reason. In this case the connection thread that tries to
+ start the scheduler sees that some error has occurred and
+ returns an error to the user. Finally, the connection
+ thread sets the state to INITIALIZED, so further attempts
+ to start the scheduler could be made.
+ - RUNNING :The scheduler is running. New events could be added,
+ dropped, altered. The scheduler could be stopped.
+ - SUSPENDED :Like RUNNING but execution of events does not take place.
+ Operations on the memory queue are possible.
+ - IN_SHUTDOWN :The scheduler is shutting down, due to request by setting
+ the global event_scheduler to 0/FALSE, or because of a
+ KILL command sent by a user to the master thread.
+
+ In every method the macros LOCK_SCHEDULER_DATA() and UNLOCK_SCHEDULER_DATA()
+ are used for (un)locking purposes. They are used to save the programmer
+ from typing everytime
+ lock_data(__FUNCTION__, __LINE__);
+ All locking goes through Event_scheduler::lock_data() and ::unlock_data().
+ These two functions then record in variables where for last time
+ LOCK_scheduler_data was locked and unlocked (two different variables). In
+ multithreaded environment, in some cases they make no sense but are useful for
+ inspecting deadlocks without having the server debug log turned on and the
+ server is still running.
+
+ The same strategy is used for conditional variables.
+ Event_scheduler::cond_wait() is invoked from all places with parameter
+ an enum enum_cond_vars. In this manner, it's possible to inspect the last
+ on which condition the last call to cond_wait() was waiting. If the server
+ was started with debug trace switched on, the trace file also holds information
+ about conditional variables used.
+*/
+
+#ifdef __GNUC__
+#if __GNUC__ >= 2
+#define SCHED_FUNC __FUNCTION__
+#endif
+#else
+#define SCHED_FUNC "<unknown>"
+#endif
+
+#define LOCK_SCHEDULER_DATA() lock_data(SCHED_FUNC, __LINE__)
+#define UNLOCK_SCHEDULER_DATA() unlock_data(SCHED_FUNC, __LINE__)
+
+
+#ifndef DBUG_OFF
+static
+LEX_STRING states_names[] =
+{
+ {(char*) STRING_WITH_LEN("UNINITIALIZED")},
+ {(char*) STRING_WITH_LEN("INITIALIZED")},
+ {(char*) STRING_WITH_LEN("COMMENCING")},
+ {(char*) STRING_WITH_LEN("CANTSTART")},
+ {(char*) STRING_WITH_LEN("RUNNING")},
+ {(char*) STRING_WITH_LEN("SUSPENDED")},
+ {(char*) STRING_WITH_LEN("IN_SHUTDOWN")}
+};
+#endif
+
+
+Event_scheduler
+Event_scheduler::singleton;
+
+
+const char * const
+Event_scheduler::cond_vars_names[Event_scheduler::COND_LAST] =
+{
+ "new work",
+ "started or stopped",
+ "suspend or resume"
+};
+
+
+class Worker_thread_param
+{
+public:
+ Event_timed *et;
+ pthread_mutex_t LOCK_started;
+ pthread_cond_t COND_started;
+ bool started;
+
+ Worker_thread_param(Event_timed *etn):et(etn), started(FALSE)
+ {
+ pthread_mutex_init(&LOCK_started, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_started, NULL);
+ }
+
+ ~Worker_thread_param()
+ {
+ pthread_mutex_destroy(&LOCK_started);
+ pthread_cond_destroy(&COND_started);
+ }
+};
+
+
+/*
+ Prints the stack of infos, warnings, errors from thd to
+ the console so it can be fetched by the logs-into-tables and
+ checked later.
+
+ SYNOPSIS
+ evex_print_warnings
+ thd - thread used during the execution of the event
+ et - the event itself
+*/
+
+static void
+evex_print_warnings(THD *thd, Event_timed *et)
+{
+ MYSQL_ERROR *err;
+ DBUG_ENTER("evex_print_warnings");
+ if (!thd->warn_list.elements)
+ DBUG_VOID_RETURN;
+
+ char msg_buf[10 * STRING_BUFFER_USUAL_SIZE];
+ char prefix_buf[5 * STRING_BUFFER_USUAL_SIZE];
+ String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
+ prefix.length(0);
+ prefix.append("SCHEDULER: [");
+
+ append_identifier(thd, &prefix, et->definer_user.str, et->definer_user.length);
+ prefix.append('@');
+ append_identifier(thd, &prefix, et->definer_host.str, et->definer_host.length);
+ prefix.append("][", 2);
+ append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
+ prefix.append('.');
+ append_identifier(thd,&prefix, et->name.str, et->name.length);
+ prefix.append("] ", 2);
+
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ while ((err= it++))
+ {
+ String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
+ /* set it to 0 or we start adding at the end. That's the trick ;) */
+ err_msg.length(0);
+ err_msg.append(prefix);
+ err_msg.append(err->msg, strlen(err->msg), system_charset_info);
+ err_msg.append("]");
+ DBUG_ASSERT(err->level < 3);
+ (sql_print_message_handlers[err->level])("%*s", err_msg.length(),
+ err_msg.c_ptr());
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Inits an scheduler thread handler, both the main and a worker
+
+ SYNOPSIS
+ init_event_thread()
+ thd - the THD of the thread. Has to be allocated by the caller.
+
+ NOTES
+ 1. The host of the thead is my_localhost
+ 2. thd->net is initted with NULL - no communication.
+
+ RETURN VALUE
+ 0 OK
+ -1 Error
+*/
+
+static int
+init_event_thread(THD** t, enum enum_thread_type thread_type)
+{
+ THD *thd= *t;
+ thd->thread_stack= (char*)t; // remember where our stack is
+ DBUG_ENTER("init_event_thread");
+ thd->client_capabilities= 0;
+ thd->security_ctx->master_access= 0;
+ thd->security_ctx->db_access= 0;
+ thd->security_ctx->host_or_ip= (char*)my_localhost;
+ my_net_init(&thd->net, 0);
+ thd->net.read_timeout= slave_net_timeout;
+ thd->slave_thread= 0;
+ thd->options|= OPTION_AUTO_IS_NULL;
+ thd->client_capabilities|= CLIENT_MULTI_RESULTS;
+ thd->real_id=pthread_self();
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->thread_id= thread_id++;
+ threads.append(thd);
+ thread_count++;
+ thread_running++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+
+ if (init_thr_lock() || thd->store_globals())
+ {
+ thd->cleanup();
+ DBUG_RETURN(-1);
+ }
+
+#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
+ sigset_t set;
+ VOID(sigemptyset(&set)); // Get mask in use
+ VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
+#endif
+
+ /*
+ Guarantees that we will see the thread in SHOW PROCESSLIST though its
+ vio is NULL.
+ */
+ thd->system_thread= thread_type;
+
+ thd->proc_info= "Initialized";
+ thd->version= refresh_version;
+ thd->set_time();
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Inits the main scheduler thread and then calls Event_scheduler::run()
+ of arg.
+
+ SYNOPSIS
+ event_scheduler_thread()
+ arg void* ptr to Event_scheduler
+
+ NOTES
+ 1. The host of the thead is my_localhost
+ 2. thd->net is initted with NULL - no communication.
+ 3. The reason to have a proxy function is that it's not possible to
+ use a method as function to be executed in a spawned thread:
+ - our pthread_hander_t macro uses extern "C"
+ - separating thread setup from the real execution loop is also to be
+ considered good.
+
+ RETURN VALUE
+ 0 OK
+*/
+
+pthread_handler_t
+event_scheduler_thread(void *arg)
+{
+ /* needs to be first for thread_stack */
+ THD *thd= NULL;
+ Event_scheduler *scheduler= (Event_scheduler *) arg;
+
+ DBUG_ENTER("event_scheduler_thread");
+
+ my_thread_init();
+ pthread_detach_this_thread();
+
+ /* note that constructor of THD uses DBUG_ ! */
+ if (!(thd= new THD) || init_event_thread(&thd, SYSTEM_THREAD_EVENT_SCHEDULER))
+ {
+ sql_print_error("SCHEDULER: Cannot init manager event thread.");
+ scheduler->report_error_during_start();
+ }
+ else
+ {
+ thd->security_ctx->set_user((char*)"event_scheduler");
+
+ sql_print_information("SCHEDULER: Manager thread booting");
+ if (Event_scheduler::check_system_tables(thd))
+ scheduler->report_error_during_start();
+ else
+ scheduler->run(thd);
+
+ /*
+ NOTE: Don't touch `scheduler` after this point because we have notified
+ the
+ thread which shuts us down that we have finished cleaning. In this
+ very moment a new scheduler thread could be started and a crash is
+ not welcome.
+ */
+ }
+
+ /*
+ If we cannot create THD then don't decrease because we haven't touched
+ thread_count and thread_running in init_event_thread() which was never
+ called. In init_event_thread() thread_count and thread_running are
+ always increased even in the case the method returns an error.
+ */
+ if (thd)
+ {
+ thd->proc_info= "Clearing";
+ DBUG_ASSERT(thd->net.buff != 0);
+ net_end(&thd->net);
+ pthread_mutex_lock(&LOCK_thread_count);
+ thread_count--;
+ thread_running--;
+ delete thd;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ }
+ my_thread_end();
+ DBUG_RETURN(0); // Can't return anything here
+}
+
+
+/*
+ Function that executes an event in a child thread. Setups the
+ environment for the event execution and cleans after that.
+
+ SYNOPSIS
+ event_worker_thread()
+ arg The Event_timed object to be processed
+
+ RETURN VALUE
+ 0 OK
+*/
+
+pthread_handler_t
+event_worker_thread(void *arg)
+{
+ THD *thd; /* needs to be first for thread_stack */
+ Worker_thread_param *param= (Worker_thread_param *) arg;
+ Event_timed *event= param->et;
+ int ret;
+ bool startup_error= FALSE;
+ Security_context *save_ctx;
+ /* this one is local and not needed after exec */
+ Security_context security_ctx;
+
+ DBUG_ENTER("event_worker_thread");
+ DBUG_PRINT("enter", ("event=[%s.%s]", event->dbname.str, event->name.str));
+
+ my_thread_init();
+ pthread_detach_this_thread();
+
+ if (!(thd= new THD) || init_event_thread(&thd, SYSTEM_THREAD_EVENT_WORKER))
+ {
+ sql_print_error("SCHEDULER: Startup failure.");
+ startup_error= TRUE;
+ event->spawn_thread_finish(thd);
+ }
+ else
+ event->set_thread_id(thd->thread_id);
+
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+ /*
+ If we don't change it before we send the signal back, then an intermittent
+ DROP EVENT will take LOCK_scheduler_data and try to kill this thread, because
+ event->thread_id is already real. However, because thd->security_ctx->user
+ is not initialized then a crash occurs in kill_one_thread(). Thus, we have
+ to change the context before sending the signal. We are under
+ LOCK_scheduler_data being held by Event_scheduler::run() -> ::execute_top().
+ */
+ change_security_context(thd, event->definer_user, event->definer_host,
+ event->dbname, &security_ctx, &save_ctx);
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+
+ /* Signal the scheduler thread that we have started successfully */
+ pthread_mutex_lock(&param->LOCK_started);
+ param->started= TRUE;
+ pthread_cond_signal(&param->COND_started);
+ pthread_mutex_unlock(&param->LOCK_started);
+
+ if (!startup_error)
+ {
+ thd->init_for_queries();
+ thd->enable_slow_log= TRUE;
+
+ event->set_thread_id(thd->thread_id);
+ sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu",
+ event->dbname.str, event->name.str,
+ event->definer.str, thd->thread_id);
+
+ ret= event->execute(thd, thd->mem_root);
+ evex_print_warnings(thd, event);
+ sql_print_information("SCHEDULER: [%s.%s of %s] executed. RetCode=%d",
+ event->dbname.str, event->name.str,
+ event->definer.str, ret);
+ if (ret == EVEX_COMPILE_ERROR)
+ sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of %s",
+ event->dbname.str, event->name.str,
+ event->definer.str);
+ else if (ret == EVEX_MICROSECOND_UNSUP)
+ sql_print_information("SCHEDULER: MICROSECOND is not supported");
+
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+
+ /* If true is returned, we are expected to free it */
+ if (event->spawn_thread_finish(thd))
+ {
+ DBUG_PRINT("info", ("Freeing object pointer"));
+ delete event;
+ }
+ }
+
+ if (thd)
+ {
+ thd->proc_info= "Clearing";
+ DBUG_ASSERT(thd->net.buff != 0);
+ /*
+ Free it here because net.vio is NULL for us => THD::~THD will check it
+ and won't call net_end(&net); See also replication code.
+ */
+ net_end(&thd->net);
+ DBUG_PRINT("info", ("Worker thread %lu exiting", thd->thread_id));
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thread_count--;
+ thread_running--;
+ delete thd;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ }
+
+ my_thread_end();
+ DBUG_RETURN(0); // Can't return anything here
+}
+
+
+/*
+ Constructor of class Event_scheduler.
+
+ SYNOPSIS
+ Event_scheduler::Event_scheduler()
+*/
+
+Event_scheduler::Event_scheduler()
+ :state(UNINITIALIZED), start_scheduler_suspended(FALSE),
+ thread_id(0), mutex_last_locked_at_line(0),
+ mutex_last_unlocked_at_line(0), mutex_last_locked_in_func(""),
+ mutex_last_unlocked_in_func(""), cond_waiting_on(COND_NONE),
+ mutex_scheduler_data_locked(FALSE)
+{
+}
+
+
+/*
+ Returns the singleton instance of the class.
+
+ SYNOPSIS
+ Event_scheduler::get_instance()
+
+ RETURN VALUE
+ address
+*/
+
+Event_scheduler*
+Event_scheduler::get_instance()
+{
+ DBUG_ENTER("Event_scheduler::get_instance");
+ DBUG_RETURN(&singleton);
+}
+
+
+/*
+ The implementation of full-fledged initialization.
+
+ SYNOPSIS
+ Event_scheduler::init()
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+*/
+
+bool
+Event_scheduler::init()
+{
+ int i= 0;
+ bool ret= FALSE;
+ DBUG_ENTER("Event_scheduler::init");
+ DBUG_PRINT("enter", ("this=%p", this));
+
+ LOCK_SCHEDULER_DATA();
+ for (;i < COND_LAST; i++)
+ if (pthread_cond_init(&cond_vars[i], NULL))
+ {
+ sql_print_error("SCHEDULER: Unable to initalize conditions");
+ ret= TRUE;
+ goto end;
+ }
+
+ /* init memory root */
+ init_alloc_root(&scheduler_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+
+ if (init_queue_ex(&queue, 30 /*num_el*/, 0 /*offset*/, 0 /*smallest_on_top*/,
+ event_timed_compare_q, NULL, 30 /*auto_extent*/))
+ {
+ sql_print_error("SCHEDULER: Can't initialize the execution queue");
+ ret= TRUE;
+ goto end;
+ }
+
+ if (sizeof(my_time_t) != sizeof(time_t))
+ {
+ sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
+ "The scheduler may not work correctly. Stopping.");
+ DBUG_ASSERT(0);
+ ret= TRUE;
+ goto end;
+ }
+
+ state= INITIALIZED;
+end:
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Frees all memory allocated by the scheduler object.
+
+ SYNOPSIS
+ Event_scheduler::destroy()
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+*/
+
+void
+Event_scheduler::destroy()
+{
+ DBUG_ENTER("Event_scheduler");
+
+ LOCK_SCHEDULER_DATA();
+ switch (state) {
+ case UNINITIALIZED:
+ break;
+ case INITIALIZED:
+ delete_queue(&queue);
+ free_root(&scheduler_root, MYF(0));
+ int i;
+ for (i= 0; i < COND_LAST; i++)
+ pthread_cond_destroy(&cond_vars[i]);
+ state= UNINITIALIZED;
+ break;
+ default:
+ sql_print_error("SCHEDULER: Destroying while state is %d", state);
+ /* I trust my code but ::safe() > ::sorry() */
+ DBUG_ASSERT(0);
+ break;
+ }
+ UNLOCK_SCHEDULER_DATA();
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Adds an event to the scheduler queue
+
+ SYNOPSIS
+ Event_scheduler::add_event()
+ et The event to add
+ check_existence Whether to check if already loaded.
+
+ RETURN VALUE
+ OP_OK OK or scheduler not working
+ OP_LOAD_ERROR Error during loading from disk
+*/
+
+enum Event_scheduler::enum_error_code
+Event_scheduler::add_event(THD *thd, Event_timed *et, bool check_existence)
+{
+ enum enum_error_code res;
+ Event_timed *et_new;
+ DBUG_ENTER("Event_scheduler::add_event");
+ DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data));
+
+ LOCK_SCHEDULER_DATA();
+ if (!is_running_or_suspended())
+ {
+ DBUG_PRINT("info", ("scheduler not running but %d. doing nothing", state));
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(OP_OK);
+ }
+ if (check_existence && find_event(et, FALSE))
+ {
+ res= OP_ALREADY_EXISTS;
+ goto end;
+ }
+
+ /* We need to load the event on scheduler_root */
+ if (!(res= load_named_event(thd, et, &et_new)))
+ {
+ queue_insert_safe(&queue, (byte *) et_new);
+ DBUG_PRINT("info", ("Sending COND_new_work"));
+ pthread_cond_signal(&cond_vars[COND_new_work]);
+ }
+ else if (res == OP_DISABLED_EVENT)
+ res= OP_OK;
+end:
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Drops an event from the scheduler queue
+
+ SYNOPSIS
+ Event_scheduler::drop_event()
+ etn The event to drop
+ state Wait the event or kill&drop
+
+ RETURN VALUE
+ FALSE OK (replaced or scheduler not working)
+ TRUE Failure
+*/
+
+bool
+Event_scheduler::drop_event(THD *thd, Event_timed *et)
+{
+ int res;
+ Event_timed *et_old;
+ DBUG_ENTER("Event_scheduler::drop_event");
+ DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data));
+
+ LOCK_SCHEDULER_DATA();
+ if (!is_running_or_suspended())
+ {
+ DBUG_PRINT("info", ("scheduler not running but %d. doing nothing", state));
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(OP_OK);
+ }
+
+ if (!(et_old= find_event(et, TRUE)))
+ DBUG_PRINT("info", ("No such event found, probably DISABLED"));
+
+ UNLOCK_SCHEDULER_DATA();
+
+ /* See comments in ::replace_event() why this is split in two parts. */
+ if (et_old)
+ {
+ switch ((res= et_old->kill_thread(thd))) {
+ case EVEX_CANT_KILL:
+ /* Don't delete but continue */
+ et_old->flags |= EVENT_FREE_WHEN_FINISHED;
+ break;
+ case 0:
+ /*
+ kill_thread() waits till the spawned thread finishes after it's
+ killed. Hence, we delete here memory which is no more referenced from
+ a running thread.
+ */
+ delete et_old;
+ /*
+ We don't signal COND_new_work here because:
+ 1. Even if the dropped event is on top of the queue this will not
+ move another one to be executed before the time the one on the
+ top (but could be at the same second as the dropped one)
+ 2. If this was the last event on the queue, then pthread_cond_timedwait
+ in ::run() will finish and then see that the queue is empty and
+ call cond_wait(). Hence, no need to interrupt the blocked
+ ::run() thread.
+ */
+ break;
+ default:
+ sql_print_error("SCHEDULER: Got unexpected error %d", res);
+ DBUG_ASSERT(0);
+ }
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Replaces an event in the scheduler queue
+
+ SYNOPSIS
+ Event_scheduler::replace_event()
+ et The event to replace(add) into the queue
+ state Async or sync stopping
+
+ RETURN VALUE
+ OP_OK OK or scheduler not working
+ OP_LOAD_ERROR Error during loading from disk
+ OP_ALREADY_EXISTS Event already in the queue
+*/
+
+enum Event_scheduler::enum_error_code
+Event_scheduler::replace_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
+ LEX_STRING *new_name)
+{
+ enum enum_error_code res;
+ Event_timed *et_old, *et_new= NULL;
+ LEX_STRING old_schema, old_name;
+
+ DBUG_ENTER("Event_scheduler::replace_event");
+ DBUG_PRINT("enter", ("thd=%p et=%p et=[%s.%s] lock=%p",
+ thd, et, et->dbname.str, et->name.str, &LOCK_scheduler_data));
+
+ LOCK_SCHEDULER_DATA();
+ if (!is_running_or_suspended())
+ {
+ DBUG_PRINT("info", ("scheduler not running but %d. doing nothing", state));
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(OP_OK);
+ }
+
+ if (!(et_old= find_event(et, TRUE)))
+ DBUG_PRINT("info", ("%s.%s not found cached, probably was DISABLED",
+ et->dbname.str, et->name.str));
+
+ if (new_schema && new_name)
+ {
+ old_schema= et->dbname;
+ old_name= et->name;
+ et->dbname= *new_schema;
+ et->name= *new_name;
+ }
+ /*
+ We need to load the event (it's strings but on the object itself)
+ on scheduler_root. et_new could be NULL :
+ 1. Error occured
+ 2. If the replace is DISABLED, we don't load it into the queue.
+ */
+ if (!(res= load_named_event(thd, et, &et_new)))
+ {
+ queue_insert_safe(&queue, (byte *) et_new);
+ DBUG_PRINT("info", ("Sending COND_new_work"));
+ pthread_cond_signal(&cond_vars[COND_new_work]);
+ }
+ else if (res == OP_DISABLED_EVENT)
+ res= OP_OK;
+
+ if (new_schema && new_name)
+ {
+ et->dbname= old_schema;
+ et->name= old_name;
+ }
+
+ UNLOCK_SCHEDULER_DATA();
+ /*
+ Andrey: Is this comment still truthful ???
+
+ We don't move this code above because a potential kill_thread will call
+ THD::awake(). Which in turn will try to acqure mysys_var->current_mutex,
+ which is LOCK_scheduler_data on which the COND_new_work in ::run() locks.
+ Hence, we try to acquire a lock which we have already acquired and we run
+ into an assert. Holding LOCK_scheduler_data however is not needed because
+ we don't touch any invariant of the scheduler anymore. ::drop_event() does
+ the same.
+ */
+ if (et_old)
+ {
+ switch (et_old->kill_thread(thd)) {
+ case EVEX_CANT_KILL:
+ /* Don't delete but continue */
+ et_old->flags |= EVENT_FREE_WHEN_FINISHED;
+ break;
+ case 0:
+ /*
+ kill_thread() waits till the spawned thread finishes after it's
+ killed. Hence, we delete here memory which is no more referenced from
+ a running thread.
+ */
+ delete et_old;
+ /*
+ We don't signal COND_new_work here because:
+ 1. Even if the dropped event is on top of the queue this will not
+ move another one to be executed before the time the one on the
+ top (but could be at the same second as the dropped one)
+ 2. If this was the last event on the queue, then pthread_cond_timedwait
+ in ::run() will finish and then see that the queue is empty and
+ call cond_wait(). Hence, no need to interrupt the blocked
+ ::run() thread.
+ */
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Searches for an event in the scheduler queue
+
+ SYNOPSIS
+ Event_scheduler::find_event()
+ etn The event to find
+ comparator The function to use for comparing
+ remove_from_q If found whether to remove from the Q
+
+ RETURN VALUE
+ NULL Not found
+ otherwise Address
+
+ NOTE
+ The caller should do the locking also the caller is responsible for
+ actual signalling in case an event is removed from the queue
+ (signalling COND_new_work for instance).
+*/
+
+Event_timed *
+Event_scheduler::find_event(Event_timed *etn, bool remove_from_q)
+{
+ uint i;
+ DBUG_ENTER("Event_scheduler::find_event");
+
+ for (i= 0; i < queue.elements; ++i)
+ {
+ Event_timed *et= (Event_timed *) queue_element(&queue, i);
+ DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", etn->dbname.str, etn->name.str,
+ et->dbname.str, et->name.str));
+ if (event_timed_identifier_equal(etn, et))
+ {
+ if (remove_from_q)
+ queue_remove(&queue, i);
+ DBUG_RETURN(et);
+ }
+ }
+
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Drops all events from the in-memory queue and disk that match
+ certain pattern evaluated by a comparator function
+
+ SYNOPSIS
+ Event_scheduler::drop_matching_events()
+ thd THD
+ pattern A pattern string
+ comparator The function to use for comparing
+
+ RETURN VALUE
+ -1 Scheduler not working
+ >=0 Number of dropped events
+
+ NOTE
+ Expected is the caller to acquire lock on LOCK_scheduler_data
+*/
+
+void
+Event_scheduler::drop_matching_events(THD *thd, LEX_STRING *pattern,
+ bool (*comparator)(Event_timed *,LEX_STRING *))
+{
+ DBUG_ENTER("Event_scheduler::drop_matching_events");
+ DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern->length, pattern->str,
+ state));
+ if (is_running_or_suspended())
+ {
+ uint i= 0, dropped= 0;
+ while (i < queue.elements)
+ {
+ Event_timed *et= (Event_timed *) queue_element(&queue, i);
+ DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
+ if (comparator(et, pattern))
+ {
+ /*
+ The queue is ordered. If we remove an element, then all elements after
+ it will shift one position to the left, if we imagine it as an array
+ from left to the right. In this case we should not increment the
+ counter and the (i < queue.elements) condition is ok.
+ */
+ queue_remove(&queue, i);
+
+ /* See replace_event() */
+ switch (et->kill_thread(thd)) {
+ case EVEX_CANT_KILL:
+ /* Don't delete but continue */
+ et->flags |= EVENT_FREE_WHEN_FINISHED;
+ ++dropped;
+ break;
+ case 0:
+ delete et;
+ ++dropped;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ else
+ i++;
+ }
+ DBUG_PRINT("info", ("Dropped %lu", dropped));
+ }
+ /*
+ Don't send COND_new_work because no need to wake up the scheduler thread.
+ When it wakes next time up it will recalculate how much more it should
+ sleep if the top of the queue has been changed by this method.
+ */
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Drops all events from the in-memory queue and disk that are from
+ certain schema.
+
+ SYNOPSIS
+ Event_scheduler::drop_schema_events()
+ thd THD
+ db The schema name
+
+ RETURN VALUE
+ -1 Scheduler not working
+ >=0 Number of dropped events
+*/
+
+int
+Event_scheduler::drop_schema_events(THD *thd, LEX_STRING *schema)
+{
+ int ret;
+ DBUG_ENTER("Event_scheduler::drop_schema_events");
+ LOCK_SCHEDULER_DATA();
+ if (is_running_or_suspended())
+ drop_matching_events(thd, schema, event_timed_db_equal);
+
+ ret= db_drop_events_from_table(thd, schema);
+ UNLOCK_SCHEDULER_DATA();
+
+ DBUG_RETURN(ret);
+}
+
+
+extern pthread_attr_t connection_attrib;
+
+
+/*
+ Starts the event scheduler
+
+ SYNOPSIS
+ Event_scheduler::start()
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+*/
+
+bool
+Event_scheduler::start()
+{
+ bool ret= FALSE;
+ pthread_t th;
+ DBUG_ENTER("Event_scheduler::start");
+
+ LOCK_SCHEDULER_DATA();
+ /* If already working or starting don't make another attempt */
+ DBUG_ASSERT(state == INITIALIZED);
+ if (state > INITIALIZED)
+ {
+ DBUG_PRINT("info", ("scheduler is already running or starting"));
+ ret= TRUE;
+ goto end;
+ }
+
+ /*
+ Now if another thread calls start it will bail-out because the branch
+ above will be executed. Thus no two or more child threads will be forked.
+ If the child thread cannot start for some reason then `state` is set
+ to CANTSTART and COND_started is also signaled. In this case we
+ set `state` back to INITIALIZED so another attempt to start the scheduler
+ can be made.
+ */
+ state= COMMENCING;
+ /* Fork */
+ if (pthread_create(&th, &connection_attrib, event_scheduler_thread,
+ (void*)this))
+ {
+ DBUG_PRINT("error", ("cannot create a new thread"));
+ state= INITIALIZED;
+ ret= TRUE;
+ goto end;
+ }
+
+ /* Wait till the child thread has booted (w/ or wo success) */
+ while (!is_running_or_suspended() && state != CANTSTART)
+ cond_wait(COND_started_or_stopped, &LOCK_scheduler_data);
+
+ /*
+ If we cannot start for some reason then don't prohibit further attempts.
+ Set back to INITIALIZED.
+ */
+ if (state == CANTSTART)
+ {
+ state= INITIALIZED;
+ ret= TRUE;
+ goto end;
+ }
+
+end:
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Starts the event scheduler in suspended mode.
+
+ SYNOPSIS
+ Event_scheduler::start_suspended()
+
+ RETURN VALUE
+ TRUE OK
+ FALSE Error
+*/
+
+bool
+Event_scheduler::start_suspended()
+{
+ DBUG_ENTER("Event_scheduler::start_suspended");
+ start_scheduler_suspended= TRUE;
+ DBUG_RETURN(start());
+}
+
+
+
+/*
+ Report back that we cannot start. Used for ocasions where
+ we can't go into ::run() and have to report externally.
+
+ SYNOPSIS
+ Event_scheduler::report_error_during_start()
+*/
+
+inline void
+Event_scheduler::report_error_during_start()
+{
+ DBUG_ENTER("Event_scheduler::report_error_during_start");
+
+ LOCK_SCHEDULER_DATA();
+ state= CANTSTART;
+ DBUG_PRINT("info", ("Sending back COND_started_or_stopped"));
+ pthread_cond_signal(&cond_vars[COND_started_or_stopped]);
+ UNLOCK_SCHEDULER_DATA();
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ The internal loop of the event scheduler
+
+ SYNOPSIS
+ Event_scheduler::run()
+ thd Thread
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Failure
+*/
+
+bool
+Event_scheduler::run(THD *thd)
+{
+ int ret;
+ struct timespec abstime;
+ DBUG_ENTER("Event_scheduler::run");
+ DBUG_PRINT("enter", ("thd=%p", thd));
+
+ LOCK_SCHEDULER_DATA();
+ ret= load_events_from_db(thd);
+
+ if (!ret)
+ {
+ thread_id= thd->thread_id;
+ state= start_scheduler_suspended? SUSPENDED:RUNNING;
+ start_scheduler_suspended= FALSE;
+ }
+ else
+ state= CANTSTART;
+
+ DBUG_PRINT("info", ("Sending back COND_started_or_stopped"));
+ pthread_cond_signal(&cond_vars[COND_started_or_stopped]);
+ if (ret)
+ {
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(TRUE);
+ }
+ if (!check_n_suspend_if_needed(thd))
+ UNLOCK_SCHEDULER_DATA();
+
+ sql_print_information("SCHEDULER: Manager thread started with id %lu",
+ thd->thread_id);
+ abstime.tv_nsec= 0;
+ while (is_running_or_suspended())
+ {
+ Event_timed *et;
+
+ LOCK_SCHEDULER_DATA();
+ if (check_n_wait_for_non_empty_queue(thd))
+ continue;
+
+ /* On TRUE data is unlocked, go back to the beginning */
+ if (check_n_suspend_if_needed(thd))
+ continue;
+
+ /* Guaranteed locked here */
+ if (state == IN_SHUTDOWN || shutdown_in_progress)
+ {
+ UNLOCK_SCHEDULER_DATA();
+ break;
+ }
+ DBUG_ASSERT(state == RUNNING);
+
+ et= (Event_timed *)queue_top(&queue);
+
+ /* Skip disabled events */
+ if (et->status != Event_timed::ENABLED)
+ {
+ /*
+ It could be a one-timer scheduled for a time, already in the past when the
+ scheduler was suspended.
+ */
+ sql_print_information("SCHEDULER: Found a disabled event %*s.%*s in the queue",
+ et->dbname.length, et->dbname.str, et->name.length,
+ et->name.str);
+ queue_remove(&queue, 0);
+ /* ToDo: check this again */
+ if (et->dropped)
+ et->drop(thd);
+ delete et;
+ UNLOCK_SCHEDULER_DATA();
+ continue;
+ }
+ thd->proc_info= (char *)"Computing";
+ DBUG_PRINT("evex manager",("computing time to sleep till next exec"));
+ /* Timestamp is in UTC */
+ abstime.tv_sec= sec_since_epoch_TIME(&et->execute_at);
+
+ thd->end_time();
+ if (abstime.tv_sec > thd->query_start())
+ {
+ /* Event trigger time is in the future */
+ thd->proc_info= (char *)"Sleep";
+ DBUG_PRINT("info", ("Going to sleep. Should wakeup after approx %d secs",
+ abstime.tv_sec - thd->query_start()));
+ DBUG_PRINT("info", ("Entering condition because waiting for activation"));
+ /*
+ Use THD::enter_cond()/exit_cond() or we won't be able to kill a
+ sleeping thread. Though ::stop() can do it by sending COND_new_work
+ an user can't by just issuing 'KILL x'; . In the latter case
+ pthread_cond_timedwait() will wait till `abstime`.
+ "Sleeping until next time"
+ */
+ thd->enter_cond(&cond_vars[COND_new_work],&LOCK_scheduler_data,"Sleeping");
+
+ pthread_cond_timedwait(&cond_vars[COND_new_work], &LOCK_scheduler_data,
+ &abstime);
+
+ DBUG_PRINT("info", ("Manager woke up. state is %d", state));
+ /*
+ If we get signal we should recalculate the whether it's the right time
+ because there could be :
+ 1. Spurious wake-up
+ 2. The top of the queue was changed (new one becase of add/drop/replace)
+ */
+ /* This will do implicit UNLOCK_SCHEDULER_DATA() */
+ thd->exit_cond("");
+ }
+ else
+ {
+ thd->proc_info= (char *)"Executing";
+ /*
+ Execute the event. An error may occur if a thread cannot be forked.
+ In this case stop the manager.
+ We should enter ::execute_top() with locked LOCK_scheduler_data.
+ */
+ int ret= execute_top(thd);
+ UNLOCK_SCHEDULER_DATA();
+ if (ret)
+ break;
+ }
+ }
+
+ thd->proc_info= (char *)"Cleaning";
+
+ LOCK_SCHEDULER_DATA();
+ /*
+ It's possible that a user has used (SQL)COM_KILL. Hence set the appropriate
+ state because it is only set by ::stop().
+ */
+ if (state != IN_SHUTDOWN)
+ {
+ DBUG_PRINT("info", ("We got KILL but the but not from ::stop()"));
+ state= IN_SHUTDOWN;
+ }
+ UNLOCK_SCHEDULER_DATA();
+
+ sql_print_information("SCHEDULER: Shutting down");
+
+ thd->proc_info= (char *)"Cleaning queue";
+ clean_queue(thd);
+ THD_CHECK_SENTRY(thd);
+
+ /* free mamager_root memory but don't destroy the root */
+ thd->proc_info= (char *)"Cleaning memory root";
+ free_root(&scheduler_root, MYF(0));
+ THD_CHECK_SENTRY(thd);
+
+ /*
+ We notify the waiting thread which shutdowns us that we have cleaned.
+ There are few more instructions to be executed in this pthread but
+ they don't affect manager structures thus it's safe to signal already
+ at this point.
+ */
+ LOCK_SCHEDULER_DATA();
+ thd->proc_info= (char *)"Sending shutdown signal";
+ DBUG_PRINT("info", ("Sending COND_started_or_stopped"));
+ if (state == IN_SHUTDOWN)
+ pthread_cond_signal(&cond_vars[COND_started_or_stopped]);
+
+ state= INITIALIZED;
+ /*
+ We set it here because ::run() can stop not only because of ::stop()
+ call but also because of `KILL x`
+ */
+ thread_id= 0;
+ sql_print_information("SCHEDULER: Stopped");
+ UNLOCK_SCHEDULER_DATA();
+
+ /* We have modified, we set back */
+ thd->query= NULL;
+ thd->query_length= 0;
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Executes the top element of the queue. Auxiliary method for ::run().
+
+ SYNOPSIS
+ Event_scheduler::execute_top()
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Failure
+
+ NOTE
+ NO locking is done. EXPECTED is that the caller should have locked
+ the queue (w/ LOCK_scheduler_data).
+*/
+
+bool
+Event_scheduler::execute_top(THD *thd)
+{
+ int spawn_ret_code;
+ bool ret= FALSE;
+ DBUG_ENTER("Event_scheduler::execute_top");
+ DBUG_PRINT("enter", ("thd=%p", thd));
+
+ Event_timed *et= (Event_timed *)queue_top(&queue);
+
+ /* Is it good idea to pass a stack address ?*/
+ Worker_thread_param param(et);
+
+ pthread_mutex_lock(&param.LOCK_started);
+ /*
+ We don't lock LOCK_scheduler_data fpr workers_increment() because it's a
+ pre-requisite for calling the current_method.
+ */
+ switch ((spawn_ret_code= et->spawn_now(event_worker_thread, &param))) {
+ case EVENT_EXEC_CANT_FORK:
+ /*
+ We don't lock LOCK_scheduler_data here because it's a pre-requisite
+ for calling the current_method.
+ */
+ sql_print_error("SCHEDULER: Problem while trying to create a thread");
+ ret= TRUE;
+ break;
+ case EVENT_EXEC_ALREADY_EXEC:
+ /*
+ We don't lock LOCK_scheduler_data here because it's a pre-requisite
+ for calling the current_method.
+ */
+ sql_print_information("SCHEDULER: %s.%s in execution. Skip this time.",
+ et->dbname.str, et->name.str);
+ if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == Event_timed::DISABLED)
+ queue_remove(&queue, 0);// 0 is top, internally 1
+ else
+ queue_replaced(&queue);
+ break;
+ default:
+ DBUG_ASSERT(!spawn_ret_code);
+ if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == Event_timed::DISABLED)
+ queue_remove(&queue, 0);// 0 is top, internally 1
+ else
+ queue_replaced(&queue);
+ /*
+ We don't lock LOCK_scheduler_data here because it's a pre-requisite
+ for calling the current_method.
+ */
+ if (likely(!spawn_ret_code))
+ {
+ /* Wait the forked thread to start */
+ do {
+ pthread_cond_wait(&param.COND_started, &param.LOCK_started);
+ } while (!param.started);
+ }
+ /*
+ param was allocated on the stack so no explicit delete as well as
+ in this moment it's no more used in the spawned thread so it's safe
+ to be deleted.
+ */
+ break;
+ }
+ pthread_mutex_unlock(&param.LOCK_started);
+ /* `param` is on the stack and will be destructed by the compiler */
+
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Cleans the scheduler's queue. Auxiliary method for ::run().
+
+ SYNOPSIS
+ Event_scheduler::clean_queue()
+ thd Thread
+*/
+
+void
+Event_scheduler::clean_queue(THD *thd)
+{
+ CHARSET_INFO *scs= system_charset_info;
+ uint i;
+ DBUG_ENTER("Event_scheduler::clean_queue");
+ DBUG_PRINT("enter", ("thd=%p", thd));
+
+ LOCK_SCHEDULER_DATA();
+ stop_all_running_events(thd);
+ UNLOCK_SCHEDULER_DATA();
+
+ sql_print_information("SCHEDULER: Emptying the queue");
+
+ /* empty the queue */
+ for (i= 0; i < queue.elements; ++i)
+ {
+ Event_timed *et= (Event_timed *) queue_element(&queue, i);
+ et->free_sp();
+ delete et;
+ }
+ resize_queue(&queue, 0);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Stops all running events
+
+ SYNOPSIS
+ Event_scheduler::stop_all_running_events()
+ thd Thread
+
+ NOTE
+ LOCK_scheduler data must be acquired prior to call to this method
+*/
+
+void
+Event_scheduler::stop_all_running_events(THD *thd)
+{
+ CHARSET_INFO *scs= system_charset_info;
+ uint i;
+ DYNAMIC_ARRAY running_threads;
+ THD *tmp;
+ DBUG_ENTER("Event_scheduler::stop_all_running_events");
+ DBUG_PRINT("enter", ("workers_count=%d", workers_count()));
+
+ my_init_dynamic_array(&running_threads, sizeof(ulong), 10, 10);
+
+ bool had_super= FALSE;
+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+ I_List_iterator<THD> it(threads);
+ while ((tmp=it++))
+ {
+ if (tmp->command == COM_DAEMON)
+ continue;
+ if (tmp->system_thread == SYSTEM_THREAD_EVENT_WORKER)
+ push_dynamic(&running_threads, (gptr) &tmp->thread_id);
+ }
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+
+ /* We need temporarily SUPER_ACL to be able to kill our offsprings */
+ if (!(thd->security_ctx->master_access & SUPER_ACL))
+ thd->security_ctx->master_access|= SUPER_ACL;
+ else
+ had_super= TRUE;
+
+ char tmp_buff[10*STRING_BUFFER_USUAL_SIZE];
+ char int_buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp_string(tmp_buff, sizeof(tmp_buff), scs);
+ String int_string(int_buff, sizeof(int_buff), scs);
+ tmp_string.length(0);
+
+ for (i= 0; i < running_threads.elements; ++i)
+ {
+ int ret;
+ ulong thd_id= *dynamic_element(&running_threads, i, ulong*);
+
+ int_string.set((longlong) thd_id,scs);
+ tmp_string.append(int_string);
+ if (i < running_threads.elements - 1)
+ tmp_string.append(' ');
+
+ if ((ret= kill_one_thread(thd, thd_id, FALSE)))
+ {
+ sql_print_error("SCHEDULER: Error killing %lu code=%d", thd_id, ret);
+ break;
+ }
+ }
+ if (running_threads.elements)
+ sql_print_information("SCHEDULER: Killing workers :%s", tmp_string.c_ptr());
+
+ if (!had_super)
+ thd->security_ctx->master_access &= ~SUPER_ACL;
+
+ delete_dynamic(&running_threads);
+
+ sql_print_information("SCHEDULER: Waiting for worker threads to finish");
+
+ while (workers_count())
+ my_sleep(100000);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Stops the event scheduler
+
+ SYNOPSIS
+ Event_scheduler::stop()
+
+ RETURN VALUE
+ OP_OK OK
+ OP_CANT_KILL Error during stopping of manager thread
+ OP_NOT_RUNNING Manager not working
+
+ NOTE
+ The caller must have acquited LOCK_scheduler_data.
+*/
+
+enum Event_scheduler::enum_error_code
+Event_scheduler::stop()
+{
+ THD *thd= current_thd;
+ DBUG_ENTER("Event_scheduler::stop");
+ DBUG_PRINT("enter", ("thd=%p", current_thd));
+
+ LOCK_SCHEDULER_DATA();
+ if (!is_running_or_suspended())
+ {
+ /*
+ One situation to be here is if there was a start that forked a new
+ thread but the new thread did not acquire yet LOCK_scheduler_data.
+ Hence, in this case return an error.
+ */
+ DBUG_PRINT("info", ("manager not running but %d. doing nothing", state));
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(OP_NOT_RUNNING);
+ }
+ state= IN_SHUTDOWN;
+
+ DBUG_PRINT("info", ("Manager thread has id %d", thread_id));
+ sql_print_information("SCHEDULER: Killing manager thread %lu", thread_id);
+
+ /*
+ Sending the COND_new_work to ::run() is a way to get this working without
+ race conditions. If we use kill_one_thread() it will call THD::awake() and
+ because in ::run() both THD::enter_cond()/::exit_cond() are used,
+ THD::awake() will try to lock LOCK_scheduler_data. If we UNLOCK it before,
+ then the pthread_cond_signal(COND_started_or_stopped) could be signaled in
+ ::run() and we can miss the signal before we relock. A way is to use
+ another mutex for this shutdown procedure but better not.
+ */
+ pthread_cond_signal(&cond_vars[COND_new_work]);
+ /* Or we are suspended - then we should wake up */
+ pthread_cond_signal(&cond_vars[COND_suspend_or_resume]);
+
+ /* Guarantee we don't catch spurious signals */
+ sql_print_information("SCHEDULER: Waiting the manager thread to reply");
+ while (state != INITIALIZED)
+ {
+ DBUG_PRINT("info", ("Waiting for COND_started_or_stopped from the manager "
+ "thread. Current value of state is %d . "
+ "workers count=%d", state, workers_count()));
+ cond_wait(COND_started_or_stopped, &LOCK_scheduler_data);
+ }
+ DBUG_PRINT("info", ("Manager thread has cleaned up. Set state to INIT"));
+ UNLOCK_SCHEDULER_DATA();
+
+ DBUG_RETURN(OP_OK);
+}
+
+
+/*
+ Suspends or resumes the scheduler.
+ SUSPEND - it won't execute any event till resumed.
+ RESUME - it will resume if suspended.
+
+ SYNOPSIS
+ Event_scheduler::suspend_or_resume()
+
+ RETURN VALUE
+ OP_OK OK
+*/
+
+enum Event_scheduler::enum_error_code
+Event_scheduler::suspend_or_resume(
+ enum Event_scheduler::enum_suspend_or_resume action)
+{
+ DBUG_ENTER("Event_scheduler::suspend_or_resume");
+ DBUG_PRINT("enter", ("action=%d", action));
+
+ LOCK_SCHEDULER_DATA();
+
+ if ((action == SUSPEND && state == SUSPENDED) ||
+ (action == RESUME && state == RUNNING))
+ {
+ DBUG_PRINT("info", ("Either trying to suspend suspended or resume "
+ "running scheduler. Doing nothing."));
+ }
+ else
+ {
+ /* Wake the main thread up if he is asleep */
+ DBUG_PRINT("info", ("Sending signal"));
+ if (action==SUSPEND)
+ {
+ state= SUSPENDED;
+ pthread_cond_signal(&cond_vars[COND_new_work]);
+ }
+ else
+ {
+ state= RUNNING;
+ pthread_cond_signal(&cond_vars[COND_suspend_or_resume]);
+ }
+ DBUG_PRINT("info", ("Waiting on COND_suspend_or_resume"));
+ cond_wait(COND_suspend_or_resume, &LOCK_scheduler_data);
+ DBUG_PRINT("info", ("Got response"));
+ }
+ UNLOCK_SCHEDULER_DATA();
+ DBUG_RETURN(OP_OK);
+}
+
+
+/*
+ Returns the number of executing events.
+
+ SYNOPSIS
+ Event_scheduler::workers_count()
+*/
+
+uint
+Event_scheduler::workers_count()
+{
+ THD *tmp;
+ uint count= 0;
+
+ DBUG_ENTER("Event_scheduler::workers_count");
+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+ I_List_iterator<THD> it(threads);
+ while ((tmp=it++))
+ {
+ if (tmp->command == COM_DAEMON)
+ continue;
+ if (tmp->system_thread == SYSTEM_THREAD_EVENT_WORKER)
+ ++count;
+ }
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ DBUG_PRINT("exit", ("%d", count));
+ DBUG_RETURN(count);
+}
+
+
+/*
+ Checks and suspends if needed
+
+ SYNOPSIS
+ Event_scheduler::check_n_suspend_if_needed()
+ thd Thread
+
+ RETURN VALUE
+ FALSE Not suspended, we haven't slept
+ TRUE We were suspended. LOCK_scheduler_data is unlocked.
+
+ NOTE
+ The caller should have locked LOCK_scheduler_data!
+ The mutex will be unlocked in case this function returns TRUE
+*/
+
+bool
+Event_scheduler::check_n_suspend_if_needed(THD *thd)
+{
+ bool was_suspended= FALSE;
+ DBUG_ENTER("Event_scheduler::check_n_suspend_if_needed");
+ if (thd->killed && !shutdown_in_progress)
+ {
+ state= SUSPENDED;
+ thd->killed= THD::NOT_KILLED;
+ }
+ if (state == SUSPENDED)
+ {
+ thd->enter_cond(&cond_vars[COND_suspend_or_resume], &LOCK_scheduler_data,
+ "Suspended");
+ /* Send back signal to the thread that asked us to suspend operations */
+ pthread_cond_signal(&cond_vars[COND_suspend_or_resume]);
+ sql_print_information("SCHEDULER: Suspending operations");
+ was_suspended= TRUE;
+ }
+ while (state == SUSPENDED)
+ {
+ cond_wait(COND_suspend_or_resume, &LOCK_scheduler_data);
+ DBUG_PRINT("info", ("Woke up after waiting on COND_suspend_or_resume"));
+ if (state != SUSPENDED)
+ {
+ pthread_cond_signal(&cond_vars[COND_suspend_or_resume]);
+ sql_print_information("SCHEDULER: Resuming operations");
+ }
+ }
+ if (was_suspended)
+ {
+ if (queue.elements)
+ {
+ uint i;
+ DBUG_PRINT("info", ("We have to recompute the execution times"));
+
+ for (i= 0; i < queue.elements; i++)
+ {
+ ((Event_timed*)queue_element(&queue, i))->compute_next_execution_time();
+ ((Event_timed*)queue_element(&queue, i))->update_fields(thd);
+ }
+ queue_fix(&queue);
+ }
+ /* This will implicitly unlock LOCK_scheduler_data */
+ thd->exit_cond("");
+ }
+ DBUG_RETURN(was_suspended);
+}
+
+
+/*
+ Checks for empty queue and waits till new element gets in
+
+ SYNOPSIS
+ Event_scheduler::check_n_wait_for_non_empty_queue()
+ thd Thread
+
+ RETURN VALUE
+ FALSE Did not wait - LOCK_scheduler_data still locked.
+ TRUE Waited - LOCK_scheduler_data unlocked.
+
+ NOTE
+ The caller should have locked LOCK_scheduler_data!
+*/
+
+bool
+Event_scheduler::check_n_wait_for_non_empty_queue(THD *thd)
+{
+ bool slept= FALSE;
+ DBUG_ENTER("Event_scheduler::check_n_wait_for_non_empty_queue");
+ DBUG_PRINT("enter", ("q.elements=%lu state=%s",
+ queue.elements, states_names[state]));
+
+ if (!queue.elements)
+ thd->enter_cond(&cond_vars[COND_new_work], &LOCK_scheduler_data,
+ "Empty queue, sleeping");
+
+ /* Wait in a loop protecting against catching spurious signals */
+ while (!queue.elements && state == RUNNING)
+ {
+ slept= TRUE;
+ DBUG_PRINT("info", ("Entering condition because of empty queue"));
+ cond_wait(COND_new_work, &LOCK_scheduler_data);
+ DBUG_PRINT("info", ("Manager woke up. Hope we have events now. state=%d",
+ state));
+ /*
+ exit_cond does implicit mutex_UNLOCK, we needed it locked if
+ 1. we loop again
+ 2. end the current loop and start doing calculations
+ */
+ }
+ if (slept)
+ thd->exit_cond("");
+
+ DBUG_PRINT("exit", ("q.elements=%lu state=%s thd->killed=%d",
+ queue.elements, states_names[state], thd->killed));
+
+ DBUG_RETURN(slept);
+}
+
+
+/*
+ Wrapper for pthread_mutex_lock
+
+ SYNOPSIS
+ Event_scheduler::lock_data()
+ mutex Mutex to lock
+ line The line number on which the lock is done
+
+ RETURN VALUE
+ Error code of pthread_mutex_lock()
+*/
+
+inline void
+Event_scheduler::lock_data(const char *func, uint line)
+{
+ DBUG_ENTER("Event_scheduler::lock_mutex");
+ DBUG_PRINT("enter", ("mutex_lock=%p func=%s line=%u",
+ &LOCK_scheduler_data, func, line));
+ pthread_mutex_lock(&LOCK_scheduler_data);
+ mutex_last_locked_in_func= func;
+ mutex_last_locked_at_line= line;
+ mutex_scheduler_data_locked= TRUE;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Wrapper for pthread_mutex_unlock
+
+ SYNOPSIS
+ Event_scheduler::unlock_data()
+ mutex Mutex to unlock
+ line The line number on which the unlock is done
+*/
+
+inline void
+Event_scheduler::unlock_data(const char *func, uint line)
+{
+ DBUG_ENTER("Event_scheduler::UNLOCK_mutex");
+ DBUG_PRINT("enter", ("mutex_unlock=%p func=%s line=%u",
+ &LOCK_scheduler_data, func, line));
+ mutex_last_unlocked_at_line= line;
+ mutex_scheduler_data_locked= FALSE;
+ mutex_last_unlocked_in_func= func;
+ pthread_mutex_unlock(&LOCK_scheduler_data);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Wrapper for pthread_cond_wait
+
+ SYNOPSIS
+ Event_scheduler::cond_wait()
+ cond Conditional to wait for
+ mutex Mutex of the conditional
+
+ RETURN VALUE
+ Error code of pthread_cond_wait()
+*/
+
+inline int
+Event_scheduler::cond_wait(enum Event_scheduler::enum_cond_vars cond,
+ pthread_mutex_t *mutex)
+{
+ int ret;
+ DBUG_ENTER("Event_scheduler::cond_wait");
+ DBUG_PRINT("enter", ("cond=%s mutex=%p", cond_vars_names[cond], mutex));
+ ret= pthread_cond_wait(&cond_vars[cond_waiting_on=cond], mutex);
+ cond_waiting_on= COND_NONE;
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Checks whether the scheduler is in a running or suspended state.
+
+ SYNOPSIS
+ Event_scheduler::is_running_or_suspended()
+
+ RETURN VALUE
+ TRUE Either running or suspended
+ FALSE IN_SHUTDOWN, not started, etc.
+*/
+
+inline bool
+Event_scheduler::is_running_or_suspended()
+{
+ return (state == SUSPENDED || state == RUNNING);
+}
+
+
+/*
+ Returns the current state of the scheduler
+
+ SYNOPSIS
+ Event_scheduler::get_state()
+*/
+
+enum Event_scheduler::enum_state
+Event_scheduler::get_state()
+{
+ enum Event_scheduler::enum_state ret;
+ DBUG_ENTER("Event_scheduler::get_state");
+ /* lock_data & unlock_data are not static */
+ pthread_mutex_lock(&singleton.LOCK_scheduler_data);
+ ret= singleton.state;
+ pthread_mutex_unlock(&singleton.LOCK_scheduler_data);
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Returns whether the scheduler was initialized.
+
+ SYNOPSIS
+ Event_scheduler::initialized()
+
+ RETURN VALUE
+ FALSE Was not initialized so far
+ TRUE Was initialized
+*/
+
+bool
+Event_scheduler::initialized()
+{
+ DBUG_ENTER("Event_scheduler::initialized");
+ DBUG_RETURN(Event_scheduler::get_state() != UNINITIALIZED);
+}
+
+
+/*
+ Returns the number of elements in the queue
+
+ SYNOPSIS
+ Event_scheduler::events_count()
+
+ RETURN VALUE
+ 0 Number of Event_timed objects in the queue
+*/
+
+uint
+Event_scheduler::events_count()
+{
+ uint n;
+ DBUG_ENTER("Event_scheduler::events_count");
+ LOCK_SCHEDULER_DATA();
+ n= queue.elements;
+ UNLOCK_SCHEDULER_DATA();
+
+ DBUG_RETURN(n);
+}
+
+
+/*
+ Looks for a named event in mysql.event and then loads it from
+ the table, compiles and inserts it into the cache.
+
+ SYNOPSIS
+ Event_scheduler::load_named_event()
+ thd THD
+ etn The name of the event to load and compile on scheduler's root
+ etn_new The loaded event
+
+ RETURN VALUE
+ NULL Error during compile or the event is non-enabled.
+ otherwise Address
+*/
+
+enum Event_scheduler::enum_error_code
+Event_scheduler::load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new)
+{
+ int ret= 0;
+ MEM_ROOT *tmp_mem_root;
+ Event_timed *et_loaded= NULL;
+ Open_tables_state backup;
+
+ DBUG_ENTER("Event_scheduler::load_and_compile_event");
+ DBUG_PRINT("enter",("thd=%p name:%*s",thd, etn->name.length, etn->name.str));
+
+ thd->reset_n_backup_open_tables_state(&backup);
+ /* No need to use my_error() here because db_find_event() has done it */
+ {
+ sp_name spn(etn->dbname, etn->name);
+ ret= db_find_event(thd, &spn, &et_loaded, NULL, &scheduler_root);
+ }
+ thd->restore_backup_open_tables_state(&backup);
+ /* In this case no memory was allocated so we don't need to clean */
+ if (ret)
+ DBUG_RETURN(OP_LOAD_ERROR);
+
+ if (et_loaded->status != Event_timed::ENABLED)
+ {
+ /*
+ We don't load non-enabled events.
+ In db_find_event() `et_new` was allocated on the heap and not on
+ scheduler_root therefore we delete it here.
+ */
+ delete et_loaded;
+ DBUG_RETURN(OP_DISABLED_EVENT);
+ }
+
+ et_loaded->compute_next_execution_time();
+ *etn_new= et_loaded;
+
+ DBUG_RETURN(OP_OK);
+}
+
+
+/*
+ Loads all ENABLED events from mysql.event into the prioritized
+ queue. Called during scheduler main thread initialization. Compiles
+ the events. Creates Event_timed instances for every ENABLED event
+ from mysql.event.
+
+ SYNOPSIS
+ Event_scheduler::load_events_from_db()
+ thd - Thread context. Used for memory allocation in some cases.
+
+ RETURN VALUE
+ 0 OK
+ !0 Error (EVEX_OPEN_TABLE_FAILED, EVEX_MICROSECOND_UNSUP,
+ EVEX_COMPILE_ERROR) - in all these cases mysql.event was
+ tampered.
+
+ NOTES
+ Reports the error to the console
+*/
+
+int
+Event_scheduler::load_events_from_db(THD *thd)
+{
+ TABLE *table;
+ READ_RECORD read_record_info;
+ int ret= -1;
+ uint count= 0;
+ bool clean_the_queue= FALSE;
+ /* Compile the events on this root but only for syntax check, then discard */
+ MEM_ROOT boot_root;
+
+ DBUG_ENTER("Event_scheduler::load_events_from_db");
+ DBUG_PRINT("enter", ("thd=%p", thd));
+
+ if (state > COMMENCING)
+ {
+ DBUG_ASSERT(0);
+ sql_print_error("SCHEDULER: Trying to load events while already running.");
+ DBUG_RETURN(EVEX_GENERAL_ERROR);
+ }
+
+ if ((ret= Events::open_event_table(thd, TL_READ, &table)))
+ {
+ sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
+ DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
+ }
+
+ init_alloc_root(&boot_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+ init_read_record(&read_record_info, thd, table ,NULL,1,0);
+ while (!(read_record_info.read_record(&read_record_info)))
+ {
+ Event_timed *et;
+ if (!(et= new Event_timed))
+ {
+ DBUG_PRINT("info", ("Out of memory"));
+ clean_the_queue= TRUE;
+ break;
+ }
+ DBUG_PRINT("info", ("Loading event from row."));
+
+ if ((ret= et->load_from_row(&scheduler_root, table)))
+ {
+ clean_the_queue= TRUE;
+ sql_print_error("SCHEDULER: Error while loading from mysql.event. "
+ "Table probably corrupted");
+ break;
+ }
+ if (et->status != Event_timed::ENABLED)
+ {
+ DBUG_PRINT("info",("%s is disabled",et->name.str));
+ delete et;
+ continue;
+ }
+
+ DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str));
+
+ /* We load only on scheduler root just to check whether the body compiles */
+ switch (ret= et->compile(thd, &boot_root)) {
+ case EVEX_MICROSECOND_UNSUP:
+ et->free_sp();
+ sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
+ "supported but found in mysql.event");
+ goto end;
+ case EVEX_COMPILE_ERROR:
+ sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
+ et->dbname.str, et->name.str);
+ goto end;
+ default:
+ /* Free it, it will be compiled again on the worker thread */
+ et->free_sp();
+ break;
+ }
+
+ /* let's find when to be executed */
+ if (et->compute_next_execution_time())
+ {
+ sql_print_error("SCHEDULER: Error while computing execution time of %s.%s."
+ " Skipping", et->dbname.str, et->name.str);
+ continue;
+ }
+
+ DBUG_PRINT("load_events_from_db", ("Adding %p to the exec list."));
+ queue_insert_safe(&queue, (byte *) et);
+ count++;
+ }
+end:
+ end_read_record(&read_record_info);
+ free_root(&boot_root, MYF(0));
+
+ if (clean_the_queue)
+ {
+ for (count= 0; count < queue.elements; ++count)
+ queue_remove(&queue, 0);
+ ret= -1;
+ }
+ else
+ {
+ ret= 0;
+ sql_print_information("SCHEDULER: Loaded %d event%s", count, (count == 1)?"":"s");
+ }
+
+ /* Force close to free memory */
+ thd->version--;
+
+ close_thread_tables(thd);
+
+ DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Opens mysql.db and mysql.user and checks whether:
+ 1. mysql.db has column Event_priv at column 20 (0 based);
+ 2. mysql.user has column Event_priv at column 29 (0 based);
+
+ SYNOPSIS
+ Event_scheduler::check_system_tables()
+*/
+
+bool
+Event_scheduler::check_system_tables(THD *thd)
+{
+ TABLE_LIST tables;
+ bool not_used;
+ Open_tables_state backup;
+ bool ret;
+
+ DBUG_ENTER("Event_scheduler::check_system_tables");
+ DBUG_PRINT("enter", ("thd=%p", thd));
+
+ thd->reset_n_backup_open_tables_state(&backup);
+
+ bzero((char*) &tables, sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*) "db";
+ tables.lock_type= TL_READ;
+
+ if ((ret= simple_open_n_lock_tables(thd, &tables)))
+ sql_print_error("Cannot open mysql.db");
+ else
+ {
+ ret= table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
+ mysql_db_table_fields, &mysql_db_table_last_check,
+ ER_CANNOT_LOAD_FROM_TABLE);
+ close_thread_tables(thd);
+ }
+ if (ret)
+ DBUG_RETURN(TRUE);
+
+ bzero((char*) &tables, sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*) "user";
+ tables.lock_type= TL_READ;
+
+ if ((ret= simple_open_n_lock_tables(thd, &tables)))
+ sql_print_error("Cannot open mysql.db");
+ else
+ {
+ if (tables.table->s->fields < 29 ||
+ strncmp(tables.table->field[29]->field_name,
+ STRING_WITH_LEN("Event_priv")))
+ {
+ sql_print_error("mysql.user has no `Event_priv` column at position 29");
+ ret= TRUE;
+ }
+ close_thread_tables(thd);
+ }
+
+ thd->restore_backup_open_tables_state(&backup);
+
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Inits mutexes.
+
+ SYNOPSIS
+ Event_scheduler::init_mutexes()
+*/
+
+void
+Event_scheduler::init_mutexes()
+{
+ pthread_mutex_init(&singleton.LOCK_scheduler_data, MY_MUTEX_INIT_FAST);
+}
+
+
+/*
+ Destroys mutexes.
+
+ SYNOPSIS
+ Event_scheduler::destroy_mutexes()
+*/
+
+void
+Event_scheduler::destroy_mutexes()
+{
+ pthread_mutex_destroy(&singleton.LOCK_scheduler_data);
+}
+
+
+/*
+ Dumps some data about the internal status of the scheduler.
+
+ SYNOPSIS
+ Event_scheduler::dump_internal_status()
+ thd THD
+
+ RETURN VALUE
+ 0 OK
+ 1 Error
+*/
+
+int
+Event_scheduler::dump_internal_status(THD *thd)
+{
+ DBUG_ENTER("dump_internal_status");
+#ifndef DBUG_OFF
+ CHARSET_INFO *scs= system_charset_info;
+ Protocol *protocol= thd->protocol;
+ List<Item> field_list;
+ int ret;
+ char tmp_buff[5*STRING_BUFFER_USUAL_SIZE];
+ char int_buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp_string(tmp_buff, sizeof(tmp_buff), scs);
+ String int_string(int_buff, sizeof(int_buff), scs);
+ tmp_string.length(0);
+ int_string.length(0);
+
+ field_list.push_back(new Item_empty_string("Name", 20));
+ field_list.push_back(new Item_empty_string("Value",20));
+ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ DBUG_RETURN(1);
+
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("state"), scs);
+ protocol->store(states_names[singleton.state].str,
+ states_names[singleton.state].length,
+ scs);
+
+ ret= protocol->write();
+ /*
+ If not initialized - don't show anything else. get_instance()
+ will otherwise implicitly initialize it. We don't want that.
+ */
+ if (singleton.state >= INITIALIZED)
+ {
+ /* last locked at*/
+ /*
+ The first thing to do, or get_instance() will overwrite the values.
+ mutex_last_locked_at_line / mutex_last_unlocked_at_line
+ */
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("last locked at"), scs);
+ tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+ tmp_string.alloced_length(), "%s::%d",
+ singleton.mutex_last_locked_in_func,
+ singleton.mutex_last_locked_at_line));
+ protocol->store(&tmp_string);
+ ret= protocol->write();
+
+ /* last unlocked at*/
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("last unlocked at"), scs);
+ tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+ tmp_string.alloced_length(), "%s::%d",
+ singleton.mutex_last_unlocked_in_func,
+ singleton.mutex_last_unlocked_at_line));
+ protocol->store(&tmp_string);
+ ret= protocol->write();
+
+ /* waiting on */
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("waiting on condition"), scs);
+ tmp_string.length(scs->cset->
+ snprintf(scs, (char*) tmp_string.ptr(),
+ tmp_string.alloced_length(), "%s",
+ (singleton.cond_waiting_on != COND_NONE) ?
+ cond_vars_names[singleton.cond_waiting_on]:
+ "NONE"));
+ protocol->store(&tmp_string);
+ ret= protocol->write();
+
+ Event_scheduler *scheduler= get_instance();
+
+ /* workers_count */
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("workers_count"), scs);
+ int_string.set((longlong) scheduler->workers_count(), scs);
+ protocol->store(&int_string);
+ ret= protocol->write();
+
+ /* queue.elements */
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("queue.elements"), scs);
+ int_string.set((longlong) scheduler->queue.elements, scs);
+ protocol->store(&int_string);
+ ret= protocol->write();
+
+ /* scheduler_data_locked */
+ protocol->prepare_for_resend();
+ protocol->store(STRING_WITH_LEN("scheduler data locked"), scs);
+ int_string.set((longlong) scheduler->mutex_scheduler_data_locked, scs);
+ protocol->store(&int_string);
+ ret= protocol->write();
+ }
+ send_eof(thd);
+#endif
+ DBUG_RETURN(0);
+}
diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h
new file mode 100644
index 00000000000..dffd47539fa
--- /dev/null
+++ b/sql/event_scheduler.h
@@ -0,0 +1,254 @@
+#ifndef _EVENT_SCHEDULER_H_
+#define _EVENT_SCHEDULER_H_
+/* Copyright (C) 2004-2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 THD;
+typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
+
+int
+events_init();
+
+void
+events_shutdown();
+
+
+class Event_scheduler
+{
+public:
+ /* Return codes */
+ enum enum_error_code
+ {
+ OP_OK= 0,
+ OP_NOT_RUNNING,
+ OP_CANT_KILL,
+ OP_CANT_INIT,
+ OP_DISABLED_EVENT,
+ OP_LOAD_ERROR,
+ OP_ALREADY_EXISTS
+ };
+
+ enum enum_state
+ {
+ UNINITIALIZED= 0,
+ INITIALIZED,
+ COMMENCING,
+ CANTSTART,
+ RUNNING,
+ SUSPENDED,
+ IN_SHUTDOWN
+ };
+
+ enum enum_suspend_or_resume
+ {
+ SUSPEND= 1,
+ RESUME= 2
+ };
+
+ /* Singleton access */
+ static Event_scheduler*
+ get_instance();
+
+ /* Methods for queue management follow */
+
+ enum enum_error_code
+ add_event(THD *thd, Event_timed *et, bool check_existence);
+
+ bool
+ drop_event(THD *thd, Event_timed *et);
+
+ enum enum_error_code
+ replace_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
+ LEX_STRING *new_name);
+
+ int
+ drop_schema_events(THD *thd, LEX_STRING *schema);
+
+ int
+ drop_user_events(THD *thd, LEX_STRING *definer, uint *dropped_num)
+ { DBUG_ASSERT(0); return 0;}
+
+ uint
+ events_count();
+
+ /* State changing methods follow */
+
+ bool
+ start();
+
+ enum enum_error_code
+ stop();
+
+ bool
+ start_suspended();
+
+ bool
+ run(THD *thd);
+
+ enum enum_error_code
+ suspend_or_resume(enum enum_suspend_or_resume action);
+
+ bool
+ init();
+
+ void
+ destroy();
+
+ static void
+ init_mutexes();
+
+ static void
+ destroy_mutexes();
+
+ void
+ report_error_during_start();
+
+ /* Information retrieving methods follow */
+
+ enum enum_state
+ get_state();
+
+ bool
+ initialized();
+
+ static int
+ dump_internal_status(THD *thd);
+
+ static bool
+ check_system_tables(THD *thd);
+
+private:
+ Event_timed *
+ find_event(Event_timed *etn, bool remove_from_q);
+
+ uint
+ workers_count();
+
+ bool
+ is_running_or_suspended();
+
+ /* helper functions */
+ bool
+ execute_top(THD *thd);
+
+ void
+ clean_queue(THD *thd);
+
+ void
+ stop_all_running_events(THD *thd);
+
+ enum enum_error_code
+ load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
+
+ int
+ load_events_from_db(THD *thd);
+
+ void
+ drop_matching_events(THD *thd, LEX_STRING *pattern,
+ bool (*)(Event_timed *,LEX_STRING *));
+
+ bool
+ check_n_suspend_if_needed(THD *thd);
+
+ bool
+ check_n_wait_for_non_empty_queue(THD *thd);
+
+ /* Singleton DP is used */
+ Event_scheduler();
+
+ enum enum_cond_vars
+ {
+ COND_NONE= -1,
+ /*
+ COND_new_work is a conditional used to signal that there is a change
+ of the queue that should inform the executor thread that new event should
+ be executed sooner than previously expected, because of add/replace event.
+ */
+ COND_new_work= 0,
+ /*
+ COND_started is a conditional used to synchronize the thread in which
+ ::start() was called and the spawned thread. ::start() spawns a new thread
+ and then waits on COND_started but also checks when awaken that `state` is
+ either RUNNING or CANTSTART. Then it returns back.
+ */
+ COND_started_or_stopped,
+ /*
+ Conditional used for signalling from the scheduler thread back to the
+ thread that calls ::suspend() or ::resume. Synchronizing the calls.
+ */
+ COND_suspend_or_resume,
+ /* Must be always last */
+ COND_LAST
+ };
+
+ /* Singleton instance */
+ static Event_scheduler singleton;
+
+ /* This is the current status of the life-cycle of the manager. */
+ enum enum_state state;
+
+ /* Set to start the scheduler in suspended state */
+ bool start_scheduler_suspended;
+
+ /*
+ LOCK_scheduler_data is the mutex which protects the access to the
+ manager's queue as well as used when signalling COND_new_work,
+ COND_started and COND_shutdown.
+ */
+ pthread_mutex_t LOCK_scheduler_data;
+
+ /*
+ Holds the thread id of the executor thread or 0 if the executor is not
+ running. It is used by ::shutdown() to know which thread to kill with
+ kill_one_thread(). The latter wake ups a thread if it is waiting on a
+ conditional variable and sets thd->killed to non-zero.
+ */
+ ulong thread_id;
+
+ pthread_cond_t cond_vars[COND_LAST];
+ static const char * const cond_vars_names[COND_LAST];
+
+ /* The MEM_ROOT of the object */
+ MEM_ROOT scheduler_root;
+
+ /* The sorted queue with the Event_timed objects */
+ QUEUE queue;
+
+ uint mutex_last_locked_at_line;
+ uint mutex_last_unlocked_at_line;
+ const char* mutex_last_locked_in_func;
+ const char* mutex_last_unlocked_in_func;
+ enum enum_cond_vars cond_waiting_on;
+ bool mutex_scheduler_data_locked;
+
+ /* helper functions for working with mutexes & conditionals */
+ void
+ lock_data(const char *func, uint line);
+
+ void
+ unlock_data(const char *func, uint line);
+
+ int
+ cond_wait(enum enum_cond_vars, pthread_mutex_t *mutex);
+
+private:
+ /* Prevent use of these */
+ Event_scheduler(const Event_scheduler &);
+ void operator=(Event_scheduler &);
+};
+
+#endif /* _EVENT_SCHEDULER_H_ */
diff --git a/sql/event_timed.cc b/sql/event_timed.cc
index a47446b7270..d6d6dddf971 100644
--- a/sql/event_timed.cc
+++ b/sql/event_timed.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2005 MySQL AB
+/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,11 +17,82 @@
#define MYSQL_LEX 1
#include "event_priv.h"
#include "event.h"
-#include "sp.h"
+#include "sp_head.h"
+/*
+ Constructor
+
+ SYNOPSIS
+ Event_timed::Event_timed()
+*/
+
+Event_timed::Event_timed():in_spawned_thread(0),locked_by_thread_id(0),
+ running(0), thread_id(0), status_changed(false),
+ last_executed_changed(false), expression(0),
+ created(0), modified(0),
+ on_completion(Event_timed::ON_COMPLETION_DROP),
+ status(Event_timed::ENABLED), sphead(0),
+ sql_mode(0), body_begin(0), dropped(false),
+ free_sphead_on_delete(true), flags(0)
+
+{
+ pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&this->COND_finished, NULL);
+ init();
+}
+
+
+/*
+ Destructor
+
+ SYNOPSIS
+ Event_timed::~Event_timed()
+*/
+
+Event_timed::~Event_timed()
+{
+ deinit_mutexes();
+
+ if (free_sphead_on_delete)
+ free_sp();
+}
+
+
+/*
+ Destructor
+
+ SYNOPSIS
+ Event_timed::~deinit_mutexes()
+*/
+
+void
+Event_timed::deinit_mutexes()
+{
+ pthread_mutex_destroy(&this->LOCK_running);
+ pthread_cond_destroy(&this->COND_finished);
+}
+
+
+/*
+ Checks whether the event is running
+
+ SYNOPSIS
+ Event_timed::is_running()
+*/
+
+bool
+Event_timed::is_running()
+{
+ bool ret;
+
+ VOID(pthread_mutex_lock(&this->LOCK_running));
+ ret= running;
+ VOID(pthread_mutex_unlock(&this->LOCK_running));
+
+ return ret;
+}
-extern int MYSQLparse(void *thd);
/*
Init all member variables
@@ -106,6 +177,9 @@ Event_timed::init_name(THD *thd, sp_name *spn)
NOTE
The body is extracted by copying all data between the
start of the body set by another method and the current pointer in Lex.
+
+ Some questionable removal of characters is done in here, and that part
+ should be refactored when the parser is smarter.
*/
void
@@ -116,9 +190,46 @@ Event_timed::init_body(THD *thd)
body_begin, thd->lex->ptr));
body.length= thd->lex->ptr - body_begin;
- /* Trim nuls at the end */
- while (body.length && body_begin[body.length-1] == '\0')
- body.length--;
+ const uchar *body_end= body_begin + body.length - 1;
+
+ /* Trim nuls or close-comments ('*'+'/') or spaces at the end */
+ while (body_begin < body_end)
+ {
+
+ if ((*body_end == '\0') ||
+ (my_isspace(thd->variables.character_set_client, *body_end)))
+ { /* consume NULs and meaningless whitespace */
+ --body.length;
+ --body_end;
+ continue;
+ }
+
+ /*
+ consume closing comments
+
+ This is arguably wrong, but it's the best we have until the parser is
+ changed to be smarter. FIXME PARSER
+
+ See also the sp_head code, where something like this is done also.
+
+ One idea is to keep in the lexer structure the count of the number of
+ open-comments we've entered, and scan left-to-right looking for a
+ closing comment IFF the count is greater than zero.
+
+ Another idea is to remove the closing comment-characters wholly in the
+ parser, since that's where it "removes" the opening characters.
+ */
+ if ((*(body_end - 1) == '*') && (*body_end == '/'))
+ {
+ DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'",
+ body_begin));
+ body.length-= 2;
+ body_end-= 2;
+ continue;
+ }
+
+ break; /* none were found, so we have excised all we can. */
+ }
/* the first is always whitespace which I cannot skip in the parser */
while (my_isspace(thd->variables.character_set_client, *body_begin))
@@ -202,7 +313,7 @@ Event_timed::init_execute_at(THD *thd, Item *expr)
expr how much?
new_interval what is the interval
- RETURNS
+ RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed
EVEX_BAD_PARAMS Interval is not positive
@@ -213,7 +324,7 @@ int
Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
{
String value;
- INTERVAL interval;
+ INTERVAL interval_tmp;
DBUG_ENTER("Event_timed::init_interval");
@@ -221,71 +332,74 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
DBUG_RETURN(EVEX_PARSE_ERROR);
value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
- if (get_interval_value(expr, new_interval, &value, &interval))
+ if (get_interval_value(expr, new_interval, &value, &interval_tmp))
DBUG_RETURN(EVEX_PARSE_ERROR);
expression= 0;
switch (new_interval) {
case INTERVAL_YEAR:
- expression= interval.year;
+ expression= interval_tmp.year;
break;
case INTERVAL_QUARTER:
case INTERVAL_MONTH:
- expression= interval.month;
+ expression= interval_tmp.month;
break;
case INTERVAL_WEEK:
case INTERVAL_DAY:
- expression= interval.day;
+ expression= interval_tmp.day;
break;
case INTERVAL_HOUR:
- expression= interval.hour;
+ expression= interval_tmp.hour;
break;
case INTERVAL_MINUTE:
- expression= interval.minute;
+ expression= interval_tmp.minute;
break;
case INTERVAL_SECOND:
- expression= interval.second;
+ expression= interval_tmp.second;
break;
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
- expression= interval.year* 12 + interval.month;
+ expression= interval_tmp.year* 12 + interval_tmp.month;
break;
case INTERVAL_DAY_HOUR:
- expression= interval.day* 24 + interval.hour;
+ expression= interval_tmp.day* 24 + interval_tmp.hour;
break;
case INTERVAL_DAY_MINUTE:
- expression= (interval.day* 24 + interval.hour) * 60 + interval.minute;
+ expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute;
break;
case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
case INTERVAL_DAY_SECOND:
/* DAY_SECOND having problems because of leap seconds? */
- expression= ((interval.day* 24 + interval.hour) * 60 + interval.minute)*60
- + interval.second;
+ expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute)*60
+ + interval_tmp.second;
break;
case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */
case INTERVAL_HOUR_MICROSECOND: /* day is anyway 0 */
case INTERVAL_DAY_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
- expression= ((((interval.day*24) + interval.hour)*60+interval.minute)*60 +
- interval.second) * 1000000L + interval.second_part;
+ expression= ((((interval_tmp.day*24) + interval_tmp.hour)*60+
+ interval_tmp.minute)*60 +
+ interval_tmp.second) * 1000000L + interval_tmp.second_part;
break;
case INTERVAL_HOUR_MINUTE:
- expression= interval.hour * 60 + interval.minute;
+ expression= interval_tmp.hour * 60 + interval_tmp.minute;
break;
case INTERVAL_MINUTE_SECOND:
- expression= interval.minute * 60 + interval.second;
+ expression= interval_tmp.minute * 60 + interval_tmp.second;
break;
case INTERVAL_SECOND_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
- expression= interval.second * 1000000L + interval.second_part;
+ expression= interval_tmp.second * 1000000L + interval_tmp.second_part;
break;
case INTERVAL_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
}
- if (interval.neg || expression > EVEX_MAX_INTERVAL_VALUE)
+ if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE)
DBUG_RETURN(EVEX_BAD_PARAMS);
- this->interval= new_interval;
+ interval= new_interval;
DBUG_RETURN(0);
}
@@ -306,7 +420,7 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
DATE_ADD(NOW(), INTERVAL 1 DAY) -- start tommorow at
same time.
- RETURNS
+ RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed
EVEX_BAD_PARAMS starts before now
@@ -372,7 +486,7 @@ Event_timed::init_starts(THD *thd, Item *new_starts)
DATE_ADD(NOW(), INTERVAL 1 DAY) -- end tommorow at
same time.
- RETURNS
+ RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed
ER_WRONG_VALUE starts distant date (after year 2037)
@@ -456,6 +570,9 @@ Event_timed::init_comment(THD *thd, LEX_STRING *set_comment)
SYNOPSIS
Event_timed::init_definer()
+
+ RETURN VALUE
+ 0 OK
*/
int
@@ -498,6 +615,10 @@ Event_timed::init_definer(THD *thd)
SYNOPSIS
Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
+ RETURN VALUE
+ 0 OK
+ EVEX_GET_FIELD_FAILED Error
+
NOTES
This method is silent on errors and should behave like that. Callers
should handle throwing of error messages. The reason is that the class
@@ -519,29 +640,29 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et= this;
- if (table->s->fields != EVEX_FIELD_COUNT)
+ if (table->s->fields != Events::FIELD_COUNT)
goto error;
if ((et->dbname.str= get_field(mem_root,
- table->field[EVEX_FIELD_DB])) == NULL)
+ table->field[Events::FIELD_DB])) == NULL)
goto error;
et->dbname.length= strlen(et->dbname.str);
if ((et->name.str= get_field(mem_root,
- table->field[EVEX_FIELD_NAME])) == NULL)
+ table->field[Events::FIELD_NAME])) == NULL)
goto error;
et->name.length= strlen(et->name.str);
if ((et->body.str= get_field(mem_root,
- table->field[EVEX_FIELD_BODY])) == NULL)
+ table->field[Events::FIELD_BODY])) == NULL)
goto error;
et->body.length= strlen(et->body.str);
if ((et->definer.str= get_field(mem_root,
- table->field[EVEX_FIELD_DEFINER])) == NullS)
+ table->field[Events::FIELD_DEFINER])) == NullS)
goto error;
et->definer.length= strlen(et->definer.str);
@@ -558,69 +679,71 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);/* 1:because of @*/
et->definer_host.length= len;
- et->starts_null= table->field[EVEX_FIELD_STARTS]->is_null();
- res1= table->field[EVEX_FIELD_STARTS]->get_date(&et->starts,TIME_NO_ZERO_DATE);
+ et->starts_null= table->field[Events::FIELD_STARTS]->is_null();
+ res1= table->field[Events::FIELD_STARTS]->
+ get_date(&et->starts,TIME_NO_ZERO_DATE);
- et->ends_null= table->field[EVEX_FIELD_ENDS]->is_null();
- res2= table->field[EVEX_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
+ et->ends_null= table->field[Events::FIELD_ENDS]->is_null();
+ res2= table->field[Events::FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
- if (!table->field[EVEX_FIELD_INTERVAL_EXPR]->is_null())
- et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int();
+ if (!table->field[Events::FIELD_INTERVAL_EXPR]->is_null())
+ et->expression= table->field[Events::FIELD_INTERVAL_EXPR]->val_int();
else
et->expression= 0;
/*
If res1 and res2 are true then both fields are empty.
- Hence if EVEX_FIELD_EXECUTE_AT is empty there is an error.
+ Hence if Events::FIELD_EXECUTE_AT is empty there is an error.
*/
- et->execute_at_null= table->field[EVEX_FIELD_EXECUTE_AT]->is_null();
+ et->execute_at_null=
+ table->field[Events::FIELD_EXECUTE_AT]->is_null();
DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
et->execute_at_null));
if (!et->expression &&
- table->field[EVEX_FIELD_EXECUTE_AT]->get_date(&et->execute_at,
- TIME_NO_ZERO_DATE))
+ table->field[Events::FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
+ TIME_NO_ZERO_DATE))
goto error;
/*
In DB the values start from 1 but enum interval_type starts
from 0
*/
- if (!table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->is_null())
- et->interval= (interval_type)
- ((ulonglong) table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
+ if (!table->field[Events::FIELD_TRANSIENT_INTERVAL]->is_null())
+ et->interval= (interval_type) ((ulonglong)
+ table->field[Events::FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
else
et->interval= (interval_type) 0;
- et->created= table->field[EVEX_FIELD_CREATED]->val_int();
- et->modified= table->field[EVEX_FIELD_MODIFIED]->val_int();
+ et->created= table->field[Events::FIELD_CREATED]->val_int();
+ et->modified= table->field[Events::FIELD_MODIFIED]->val_int();
- table->field[EVEX_FIELD_LAST_EXECUTED]->
+ table->field[Events::FIELD_LAST_EXECUTED]->
get_date(&et->last_executed, TIME_NO_ZERO_DATE);
last_executed_changed= false;
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
- if ((ptr= get_field(mem_root, table->field[EVEX_FIELD_STATUS])) == NullS)
+ if ((ptr= get_field(mem_root, table->field[Events::FIELD_STATUS])) == NullS)
goto error;
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
- et->status= (ptr[0]=='E'? MYSQL_EVENT_ENABLED:MYSQL_EVENT_DISABLED);
+ et->status= (ptr[0]=='E'? Event_timed::ENABLED:Event_timed::DISABLED);
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(mem_root,
- table->field[EVEX_FIELD_ON_COMPLETION])) == NullS)
+ table->field[Events::FIELD_ON_COMPLETION])) == NullS)
goto error;
- et->on_completion= (ptr[0]=='D'? MYSQL_EVENT_ON_COMPLETION_DROP:
- MYSQL_EVENT_ON_COMPLETION_PRESERVE);
+ et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP:
+ Event_timed::ON_COMPLETION_PRESERVE);
- et->comment.str= get_field(mem_root, table->field[EVEX_FIELD_COMMENT]);
+ et->comment.str= get_field(mem_root, table->field[Events::FIELD_COMMENT]);
if (et->comment.str != NullS)
et->comment.length= strlen(et->comment.str);
else
et->comment.length= 0;
- et->sql_mode= (ulong) table->field[EVEX_FIELD_SQL_MODE]->val_int();
+ et->sql_mode= (ulong) table->field[Events::FIELD_SQL_MODE]->val_int();
DBUG_RETURN(0);
error:
@@ -640,7 +763,7 @@ error:
i_value quantity of time type interval to add
i_type type of interval to add (SECOND, MINUTE, HOUR, WEEK ...)
- RETURNS
+ RETURN VALUE
0 OK
1 Error
@@ -731,7 +854,9 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
get the next exec if the modulus is not
*/
DBUG_PRINT("info", ("multiplier=%d", multiplier));
- if (seconds_diff % seconds || (!seconds_diff && last_exec->year))
+ if (seconds_diff % seconds || (!seconds_diff && last_exec->year) ||
+ TIME_to_ulonglong_datetime(time_now) ==
+ TIME_to_ulonglong_datetime(last_exec))
++multiplier;
interval.second= seconds * multiplier;
DBUG_PRINT("info", ("multiplier=%u interval.second=%u", multiplier,
@@ -796,6 +921,10 @@ done:
SYNOPSIS
Event_timed::compute_next_execution_time()
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+
NOTES
The time is set in execute_at, if no more executions the latter is set to
0000-00-00.
@@ -805,7 +934,6 @@ bool
Event_timed::compute_next_execution_time()
{
TIME time_now;
- my_time_t now;
int tmp;
DBUG_ENTER("Event_timed::compute_next_execution_time");
@@ -814,7 +942,7 @@ Event_timed::compute_next_execution_time()
TIME_to_ulonglong_datetime(&ends),
TIME_to_ulonglong_datetime(&last_executed)));
- if (status == MYSQL_EVENT_DISABLED)
+ if (status == Event_timed::DISABLED)
{
DBUG_PRINT("compute_next_execution_time",
("Event %s is DISABLED", name.str));
@@ -828,14 +956,15 @@ Event_timed::compute_next_execution_time()
{
DBUG_PRINT("info",("One-time event %s.%s of was already executed",
dbname.str, name.str, definer.str));
- dropped= (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP);
+ dropped= (on_completion == Event_timed::ON_COMPLETION_DROP);
DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped));
- status= MYSQL_EVENT_DISABLED;
+ status= Event_timed::DISABLED;
status_changed= true;
}
goto ret;
}
+
my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start());
DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now)));
@@ -847,9 +976,10 @@ Event_timed::compute_next_execution_time()
/* time_now is after ends. don't execute anymore */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
- if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
+ if (on_completion == Event_timed::ON_COMPLETION_DROP)
dropped= true;
- status= MYSQL_EVENT_DISABLED;
+ DBUG_PRINT("info", ("Dropped=%d", dropped));
+ status= Event_timed::DISABLED;
status_changed= true;
goto ret;
@@ -893,28 +1023,29 @@ Event_timed::compute_next_execution_time()
DBUG_PRINT("info", ("Both STARTS & ENDS are set"));
if (!last_executed.year)
{
- DBUG_PRINT("info", ("Not executed so far. Execute NOW."));
- execute_at= time_now;
- execute_at_null= FALSE;
+ DBUG_PRINT("info", ("Not executed so far."));
}
- else
+
{
TIME next_exec;
- DBUG_PRINT("info", ("Executed at least once"));
- if (get_next_time(&next_exec, &starts, &time_now, &last_executed,
+ if (get_next_time(&next_exec, &starts, &time_now,
+ last_executed.year? &last_executed:&starts,
expression, interval))
goto err;
/* There was previous execution */
if (my_time_compare(&ends, &next_exec) == -1)
{
- DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
+ DBUG_PRINT("info", ("Next execution of %s after ENDS. Stop executing.",
+ name.str));
/* Next execution after ends. No more executions */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
- if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
+ if (on_completion == Event_timed::ON_COMPLETION_DROP)
dropped= true;
+ status= Event_timed::DISABLED;
+ status_changed= true;
}
else
{
@@ -925,8 +1056,9 @@ Event_timed::compute_next_execution_time()
}
goto ret;
}
- else if (starts_null && ends_null)
+ else if (starts_null && ends_null)
{
+ /* starts is always set, so this is a dead branch !! */
DBUG_PRINT("info", ("Neither STARTS nor ENDS are set"));
/*
Both starts and m_ends are not set, so we schedule for the next
@@ -961,25 +1093,25 @@ Event_timed::compute_next_execution_time()
Hence schedule for starts + m_expression in case last_executed
is not set, otherwise to last_executed + m_expression
*/
- if (last_executed.year)
+ if (!last_executed.year)
+ {
+ DBUG_PRINT("info", ("Not executed so far."));
+ }
+
{
TIME next_exec;
- DBUG_PRINT("info", ("Executed at least once."));
- if (get_next_time(&next_exec, &starts, &time_now, &last_executed,
+ if (get_next_time(&next_exec, &starts, &time_now,
+ last_executed.year? &last_executed:&starts,
expression, interval))
goto err;
execute_at= next_exec;
DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec)));
}
- else
- {
- DBUG_PRINT("info", ("Not executed so far. Execute at STARTS"));
- execute_at= starts;
- }
execute_at_null= FALSE;
}
else
{
+ /* this is a dead branch, because starts is always set !!! */
DBUG_PRINT("info", ("STARTS is not set. ENDS is set"));
/*
- m_ends is set
@@ -1003,7 +1135,9 @@ Event_timed::compute_next_execution_time()
DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
- if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
+ status= Event_timed::DISABLED;
+ status_changed= true;
+ if (on_completion == Event_timed::ON_COMPLETION_DROP)
dropped= true;
}
else
@@ -1044,9 +1178,6 @@ Event_timed::mark_last_executed(THD *thd)
my_tz_UTC->gmt_sec_to_TIME(&time_now, (my_time_t) thd->query_start());
last_executed= time_now; /* was execute_at */
-#ifdef ANDREY_0
- last_executed= execute_at;
-#endif
last_executed_changed= true;
}
@@ -1086,7 +1217,7 @@ Event_timed::drop(THD *thd)
RETURN VALUE
0 OK
- SP_OPEN_TABLE_FAILED Error while opening mysql.event for writing
+ EVEX_OPEN_TABLE_FAILED Error while opening mysql.event for writing
EVEX_WRITE_ROW_FAILED On error to write to disk
others return code from SE in case deletion of the event
@@ -1098,7 +1229,7 @@ Event_timed::update_fields(THD *thd)
{
TABLE *table;
Open_tables_state backup;
- int ret= 0;
+ int ret;
DBUG_ENTER("Event_timed::update_time_fields");
@@ -1106,18 +1237,18 @@ Event_timed::update_fields(THD *thd)
/* No need to update if nothing has changed */
if (!(status_changed || last_executed_changed))
- goto done;
+ DBUG_RETURN(0);
thd->reset_n_backup_open_tables_state(&backup);
- if (evex_open_event_table(thd, TL_WRITE, &table))
+ if (Events::open_event_table(thd, TL_WRITE, &table))
{
- ret= SP_OPEN_TABLE_FAILED;
+ ret= EVEX_OPEN_TABLE_FAILED;
goto done;
}
- if ((ret= evex_db_find_event_by_name(thd, dbname, name, definer, table)))
+ if ((ret= evex_db_find_event_by_name(thd, dbname, name, table)))
goto done;
store_record(table,record[1]);
@@ -1126,15 +1257,15 @@ Event_timed::update_fields(THD *thd)
if (last_executed_changed)
{
- table->field[EVEX_FIELD_LAST_EXECUTED]->set_notnull();
- table->field[EVEX_FIELD_LAST_EXECUTED]->store_time(&last_executed,
- MYSQL_TIMESTAMP_DATETIME);
+ table->field[Events::FIELD_LAST_EXECUTED]->set_notnull();
+ table->field[Events::FIELD_LAST_EXECUTED]->store_time(&last_executed,
+ MYSQL_TIMESTAMP_DATETIME);
last_executed_changed= false;
}
if (status_changed)
{
- table->field[EVEX_FIELD_STATUS]->set_notnull();
- table->field[EVEX_FIELD_STATUS]->store((longlong)status, true);
+ table->field[Events::FIELD_STATUS]->set_notnull();
+ table->field[Events::FIELD_STATUS]->store((longlong)status, true);
status_changed= false;
}
@@ -1176,8 +1307,8 @@ Event_timed::get_create_event(THD *thd, String *buf)
DBUG_ENTER("get_create_event");
DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str));
- if (expression &&
- event_reconstruct_interval_expression(&expr_buf, interval, expression))
+ if (expression && Events::reconstruct_interval_expression(&expr_buf, interval,
+ expression))
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
buf->append(STRING_WITH_LEN("CREATE EVENT "));
@@ -1204,12 +1335,12 @@ Event_timed::get_create_event(THD *thd, String *buf)
buf->append(STRING_WITH_LEN("'"));
}
- if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
+ if (on_completion == Event_timed::ON_COMPLETION_DROP)
buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE "));
else
buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE "));
- if (status == MYSQL_EVENT_ENABLED)
+ if (status == Event_timed::ENABLED)
buf->append(STRING_WITH_LEN("ENABLE"));
else
buf->append(STRING_WITH_LEN("DISABLE"));
@@ -1234,7 +1365,7 @@ Event_timed::get_create_event(THD *thd, String *buf)
thd THD
mem_root If != NULL use it to compile the event on it
- RETURNS
+ RETURN VALUE
0 success
-99 No rights on this.dbname.str
-100 event in execution (parallel execution is impossible)
@@ -1244,7 +1375,6 @@ Event_timed::get_create_event(THD *thd, String *buf)
int
Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
{
- Security_context *save_ctx;
/* this one is local and not needed after exec */
Security_context security_ctx;
int ret= 0;
@@ -1262,16 +1392,8 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
running= true;
VOID(pthread_mutex_unlock(&this->LOCK_running));
- DBUG_PRINT("info", ("master_access=%d db_access=%d",
- thd->security_ctx->master_access, thd->security_ctx->db_access));
- change_security_context(thd, &security_ctx, &save_ctx);
- DBUG_PRINT("info", ("master_access=%d db_access=%d",
- thd->security_ctx->master_access, thd->security_ctx->db_access));
-
if (!sphead && (ret= compile(thd, mem_root)))
goto done;
- /* Now we are sure we have valid this->sphead so we can copy the context */
- sphead->m_security_ctx= security_ctx;
/*
THD::~THD will clean this or if there is DROP DATABASE in the SP then
it will be free there. It should not point to our buffer which is allocated
@@ -1295,12 +1417,11 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
definer_host.str, dbname.str));
ret= -99;
}
- restore_security_context(thd, save_ctx);
- DBUG_PRINT("info", ("master_access=%d db_access=%d",
- thd->security_ctx->master_access, thd->security_ctx->db_access));
VOID(pthread_mutex_lock(&this->LOCK_running));
running= false;
+ /* Will compile every time a new sp_head on different root */
+ free_sp();
VOID(pthread_mutex_unlock(&this->LOCK_running));
done:
@@ -1322,55 +1443,16 @@ done:
/*
- Switches the security context
- Synopsis
- Event_timed::change_security_context()
- thd - thread
- backup - where to store the old context
-
- RETURN
- 0 - OK
- 1 - Error (generates error too)
-*/
-bool
-Event_timed::change_security_context(THD *thd, Security_context *s_ctx,
- Security_context **backup)
-{
- DBUG_ENTER("Event_timed::change_security_context");
- DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str));
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- s_ctx->init();
- *backup= 0;
- if (acl_getroot_no_password(s_ctx, definer_user.str, definer_host.str,
- definer_host.str, dbname.str))
- {
- my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
- DBUG_RETURN(true);
- }
- *backup= thd->security_ctx;
- thd->security_ctx= s_ctx;
-#endif
- DBUG_RETURN(false);
-}
-
-
-/*
- Restores the security context
- Synopsis
- Event_timed::restore_security_context()
- thd - thread
- backup - switch to this context
+ Frees the memory of the sp_head object we hold
+ SYNOPSIS
+ Event_timed::free_sp()
*/
void
-Event_timed::restore_security_context(THD *thd, Security_context *backup)
+Event_timed::free_sp()
{
- DBUG_ENTER("Event_timed::restore_security_context");
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (backup)
- thd->security_ctx= backup;
-#endif
- DBUG_VOID_RETURN;
+ delete sphead;
+ sphead= 0;
}
@@ -1406,6 +1488,9 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
CHARSET_INFO *old_character_set_client,
*old_collation_connection,
*old_character_set_results;
+ Security_context *save_ctx;
+ /* this one is local and not needed after exec */
+ Security_context security_ctx;
DBUG_ENTER("Event_timed::compile");
@@ -1449,8 +1534,10 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
thd->query= show_create.c_ptr();
thd->query_length= show_create.length();
- DBUG_PRINT("Event_timed::compile", ("query:%s",thd->query));
+ DBUG_PRINT("info", ("query:%s",thd->query));
+ change_security_context(thd, definer_user, definer_host, dbname,
+ &security_ctx, &save_ctx);
thd->lex= &lex;
lex_start(thd, (uchar*)thd->query, thd->query_length);
lex.et_compile_phase= TRUE;
@@ -1488,6 +1575,7 @@ done:
lex.et->deinit_mutexes();
lex_end(&lex);
+ restore_security_context(thd, save_ctx);
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
thd->lex= old_lex;
@@ -1509,72 +1597,63 @@ done:
}
-/*
- Checks whether this thread can lock the object for modification ->
- preventing being spawned for execution, and locks if possible.
- use ::can_spawn_now() only for basic checking because a race
- condition may occur between the check and eventual modification (deletion)
- of the object.
-
- Returns
- true - locked
- false - cannot lock
-*/
-
-my_bool
-Event_timed::can_spawn_now_n_lock(THD *thd)
-{
- my_bool ret= FALSE;
- VOID(pthread_mutex_lock(&this->LOCK_running));
- if (!in_spawned_thread)
- {
- in_spawned_thread= TRUE;
- ret= TRUE;
- locked_by_thread_id= thd->thread_id;
- }
- VOID(pthread_mutex_unlock(&this->LOCK_running));
- return ret;
-}
-
-
extern pthread_attr_t connection_attrib;
/*
Checks whether is possible and forks a thread. Passes self as argument.
- Returns
- EVENT_EXEC_STARTED - OK
- EVENT_EXEC_ALREADY_EXEC - Thread not forked, already working
- EVENT_EXEC_CANT_FORK - Unable to spawn thread (error)
+ RETURN VALUE
+ EVENT_EXEC_STARTED OK
+ EVENT_EXEC_ALREADY_EXEC Thread not forked, already working
+ EVENT_EXEC_CANT_FORK Unable to spawn thread (error)
*/
int
-Event_timed::spawn_now(void * (*thread_func)(void*))
+Event_timed::spawn_now(void * (*thread_func)(void*), void *arg)
{
+ THD *thd= current_thd;
int ret= EVENT_EXEC_STARTED;
- static uint exec_num= 0;
DBUG_ENTER("Event_timed::spawn_now");
- DBUG_PRINT("info", ("this=0x%lx", this));
DBUG_PRINT("info", ("[%s.%s]", dbname.str, name.str));
VOID(pthread_mutex_lock(&this->LOCK_running));
+
+ DBUG_PRINT("info", ("SCHEDULER: execute_at of %s is %lld", name.str,
+ TIME_to_ulonglong_datetime(&execute_at)));
+ mark_last_executed(thd);
+ if (compute_next_execution_time())
+ {
+ sql_print_error("SCHEDULER: Error while computing time of %s.%s . "
+ "Disabling after execution.", dbname.str, name.str);
+ status= DISABLED;
+ }
+ DBUG_PRINT("evex manager", ("[%10s] next exec at [%llu]", name.str,
+ TIME_to_ulonglong_datetime(&execute_at)));
+ /*
+ 1. For one-time event : year is > 0 and expression is 0
+ 2. For recurring, expression is != -=> check execute_at_null in this case
+ */
+ if ((execute_at.year && !expression) || execute_at_null)
+ {
+ sql_print_information("SCHEDULER: [%s.%s of %s] no more executions "
+ "after this one", dbname.str, name.str,
+ definer.str);
+ flags |= EVENT_EXEC_NO_MORE | EVENT_FREE_WHEN_FINISHED;
+ }
+
+ update_fields(thd);
+
if (!in_spawned_thread)
{
pthread_t th;
in_spawned_thread= true;
- if (pthread_create(&th, &connection_attrib, thread_func, (void*)this))
+
+ if (pthread_create(&th, &connection_attrib, thread_func, arg))
{
DBUG_PRINT("info", ("problem while spawning thread"));
ret= EVENT_EXEC_CANT_FORK;
in_spawned_thread= false;
}
-#ifndef DBUG_OFF
- else
- {
- sql_print_information("SCHEDULER: Started thread %d", ++exec_num);
- DBUG_PRINT("info", ("thread spawned"));
- }
-#endif
}
else
{
@@ -1587,55 +1666,207 @@ Event_timed::spawn_now(void * (*thread_func)(void*))
}
-void
+bool
Event_timed::spawn_thread_finish(THD *thd)
{
+ bool should_free;
DBUG_ENTER("Event_timed::spawn_thread_finish");
- VOID(pthread_mutex_lock(&this->LOCK_running));
+ VOID(pthread_mutex_lock(&LOCK_running));
in_spawned_thread= false;
- if ((flags & EVENT_EXEC_NO_MORE) || status == MYSQL_EVENT_DISABLED)
+ DBUG_PRINT("info", ("Sending COND_finished for thread %d", thread_id));
+ thread_id= 0;
+ if (dropped)
+ drop(thd);
+ pthread_cond_broadcast(&COND_finished);
+ should_free= flags & EVENT_FREE_WHEN_FINISHED;
+ VOID(pthread_mutex_unlock(&LOCK_running));
+ DBUG_RETURN(should_free);
+}
+
+
+/*
+ Kills a running event
+ SYNOPSIS
+ Event_timed::kill_thread()
+
+ RETURN VALUE
+ 0 OK
+ -1 EVEX_CANT_KILL
+ !0 Error
+*/
+
+int
+Event_timed::kill_thread(THD *thd)
+{
+ int ret= 0;
+ DBUG_ENTER("Event_timed::kill_thread");
+ pthread_mutex_lock(&LOCK_running);
+ DBUG_PRINT("info", ("thread_id=%lu", thread_id));
+
+ if (thread_id == thd->thread_id)
{
- DBUG_PRINT("info", ("%s exec no more. to drop=%d", name.str, dropped));
- if (dropped)
- drop(thd);
- VOID(pthread_mutex_unlock(&this->LOCK_running));
- delete this;
- DBUG_VOID_RETURN;
+ /*
+ We don't kill ourselves in cases like :
+ alter event e_43 do alter event e_43 do set @a = 4 because
+ we will never receive COND_finished.
+ */
+ DBUG_PRINT("info", ("It's not safe to kill ourselves in self altering queries"));
+ ret= EVEX_CANT_KILL;
}
- VOID(pthread_mutex_unlock(&this->LOCK_running));
- DBUG_VOID_RETURN;
+ else if (thread_id && !(ret= kill_one_thread(thd, thread_id, false)))
+ {
+ thd->enter_cond(&COND_finished, &LOCK_running, "Waiting for finished");
+ DBUG_PRINT("info", ("Waiting for COND_finished from thread %d", thread_id));
+ while (thread_id)
+ pthread_cond_wait(&COND_finished, &LOCK_running);
+
+ DBUG_PRINT("info", ("Got COND_finished"));
+ /* This will implicitly unlock LOCK_running. Hence we return before that */
+ thd->exit_cond("");
+
+ DBUG_RETURN(0);
+ }
+ else if (!thread_id && in_spawned_thread)
+ {
+ /*
+ Because the manager thread waits for the forked thread to update thread_id
+ this situation is impossible.
+ */
+ DBUG_ASSERT(0);
+ }
+ pthread_mutex_unlock(&LOCK_running);
+ DBUG_PRINT("exit", ("%d", ret));
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Checks whether two events have the same name
+
+ SYNOPSIS
+ event_timed_name_equal()
+
+ RETURN VALUE
+ TRUE names are equal
+ FALSE names are not equal
+*/
+
+bool
+event_timed_name_equal(Event_timed *et, LEX_STRING *name)
+{
+ return !sortcmp_lex_string(et->name, *name, system_charset_info);
+}
+
+
+/*
+ Checks whether two events are in the same schema
+
+ SYNOPSIS
+ event_timed_db_equal()
+
+ RETURN VALUE
+ TRUE schemas are equal
+ FALSE schemas are not equal
+*/
+
+bool
+event_timed_db_equal(Event_timed *et, LEX_STRING *db)
+{
+ return !sortcmp_lex_string(et->dbname, *db, system_charset_info);
}
/*
- Unlocks the object after it has been locked with ::can_spawn_now_n_lock()
+ Checks whether two events have the same definer
+
+ SYNOPSIS
+ event_timed_definer_equal()
Returns
- 0 - ok
- 1 - not locked by this thread
+ TRUE definers are equal
+ FALSE definers are not equal
*/
-int
-Event_timed::spawn_unlock(THD *thd)
+bool
+event_timed_definer_equal(Event_timed *et, LEX_STRING *definer)
{
- int ret= 0;
- VOID(pthread_mutex_lock(&this->LOCK_running));
- if (!in_spawned_thread)
+ return !sortcmp_lex_string(et->definer, *definer, system_charset_info);
+}
+
+
+/*
+ Checks whether two events are equal by identifiers
+
+ SYNOPSIS
+ event_timed_identifier_equal()
+
+ RETURN VALUE
+ TRUE equal
+ FALSE not equal
+*/
+
+bool
+event_timed_identifier_equal(Event_timed *a, Event_timed *b)
+{
+ return event_timed_name_equal(a, &b->name) &&
+ event_timed_db_equal(a, &b->dbname) &&
+ event_timed_definer_equal(a, &b->definer);
+}
+
+
+/*
+ Switches the security context
+ SYNOPSIS
+ change_security_context()
+ thd Thread
+ user The user
+ host The host of the user
+ db The schema for which the security_ctx will be loaded
+ s_ctx Security context to load state into
+ backup Where to store the old context
+
+ RETURN VALUE
+ 0 - OK
+ 1 - Error (generates error too)
+*/
+
+bool
+change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
+ LEX_STRING db, Security_context *s_ctx,
+ Security_context **backup)
+{
+ DBUG_ENTER("change_security_context");
+ DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ s_ctx->init();
+ *backup= 0;
+ if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str))
{
- if (locked_by_thread_id == thd->thread_id)
- {
- in_spawned_thread= FALSE;
- locked_by_thread_id= 0;
- }
- else
- {
- sql_print_error("A thread tries to unlock when he hasn't locked. "
- "thread_id=%ld locked by %ld",
- thd->thread_id, locked_by_thread_id);
- DBUG_ASSERT(0);
- ret= 1;
- }
+ my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
+ DBUG_RETURN(TRUE);
}
- VOID(pthread_mutex_unlock(&this->LOCK_running));
- return ret;
+ *backup= thd->security_ctx;
+ thd->security_ctx= s_ctx;
+#endif
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Restores the security context
+ SYNOPSIS
+ restore_security_context()
+ thd - thread
+ backup - switch to this context
+*/
+
+void
+restore_security_context(THD *thd, Security_context *backup)
+{
+ DBUG_ENTER("restore_security_context");
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (backup)
+ thd->security_ctx= backup;
+#endif
+ DBUG_VOID_RETURN;
}
diff --git a/sql/field.cc b/sql/field.cc
index 9c504f186b3..e1d7aaf6343 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1223,7 +1223,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
field_name(field_name_arg),
query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
unireg_check(unireg_check_arg),
- field_length(length_arg),null_bit(null_bit_arg)
+ field_length(length_arg), null_bit(null_bit_arg), dflt_field(0)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
diff --git a/sql/field.h b/sql/field.h
index b473100eaab..602b4ea779d 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -55,6 +55,12 @@ public:
char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
/*
+ dflt_field is used only for the fields of temporary tables.
+ It points to the default value of the field in another table
+ from which this field has been created.
+ */
+ Field *dflt_field; // Field to copy default value from
+ /*
Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index f718a3d778c..3eab782d167 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -641,7 +641,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
void field_conv(Field *to,Field *from)
{
- if (to->real_type() == from->real_type())
+ if (to->real_type() == from->real_type() &&
+ !(to->type() == FIELD_TYPE_BLOB && to->table->copy_blobs))
{
if (to->pack_length() == from->pack_length() &&
!(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 6ea4cc9aeb5..473fb149871 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -56,10 +56,14 @@
#include <m_ctype.h>
#include <myisampack.h>
#include <hash.h>
+
+#ifdef WITH_BERKELEY_STORAGE_ENGINE
#include "ha_berkeley.h"
#include "sql_manager.h"
#include <stdarg.h>
+#include <mysql/plugin.h>
+
#define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_BERKELEY_RANGE_COUNT 100
#define HA_BERKELEY_MAX_ROWS 10000000 /* Max rows in table */
@@ -121,11 +125,15 @@ static int berkeley_savepoint(THD* thd, void *savepoint);
static int berkeley_release_savepoint(THD* thd, void *savepoint);
static handler *berkeley_create_handler(TABLE_SHARE *table);
+static const char berkeley_hton_name[]= "BerkeleyDB";
+static const char berkeley_hton_comment[]=
+ "Supports transactions and page-level locking";
+
handlerton berkeley_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "BerkeleyDB",
+ berkeley_hton_name,
SHOW_OPTION_YES,
- "Supports transactions and page-level locking",
+ berkeley_hton_comment,
DB_TYPE_BERKELEY_DB,
berkeley_init,
0, /* slot */
@@ -2725,3 +2733,18 @@ bool ha_berkeley::check_if_incompatible_data(HA_CREATE_INFO *info,
}
+mysql_declare_plugin(berkeley)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &berkeley_hton,
+ berkeley_hton_name,
+ "Sleepycat Software",
+ berkeley_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 129a44b5721..f4fc5f47193 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -351,9 +351,13 @@
#pragma implementation // gcc: Class implementation
#endif
+#ifdef WITH_FEDERATED_STORAGE_ENGINE
#include "ha_federated.h"
#include "m_string.h"
+
+#include <mysql/plugin.h>
+
/* Variables for federated share methods */
static HASH federated_open_tables; // To track open tables
pthread_mutex_t federated_mutex; // To init the hash
@@ -366,11 +370,14 @@ static int federated_rollback(THD *thd, bool all);
/* Federated storage engine handlerton */
+static const char federated_hton_name[]= "FEDERATED";
+static const char federated_hton_comment[]= "Federated MySQL storage engine";
+
handlerton federated_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "FEDERATED",
+ federated_hton_name,
SHOW_OPTION_YES,
- "Federated MySQL storage engine",
+ federated_hton_comment,
DB_TYPE_FEDERATED_DB,
federated_db_init,
0, /* slot */
@@ -2804,3 +2811,18 @@ int ha_federated::execute_simple_query(const char *query, int len)
DBUG_RETURN(0);
}
+
+mysql_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_hton,
+ federated_hton_name,
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ federated_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index f20dfe259fb..1a7efb42748 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -26,11 +26,15 @@
static handler *heap_create_handler(TABLE_SHARE *table);
+static const char heap_hton_name[]= "MEMORY";
+static const char heap_hton_comment[]=
+ "Hash based, stored in memory, useful for temporary tables";
+
handlerton heap_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MEMORY",
+ heap_hton_name,
SHOW_OPTION_YES,
- "Hash based, stored in memory, useful for temporary tables",
+ heap_hton_comment,
DB_TYPE_HEAP,
NULL,
0, /* slot */
@@ -706,3 +710,17 @@ bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_NO;
return COMPATIBLE_DATA_YES;
}
+
+mysql_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_hton,
+ heap_hton_name,
+ "MySQL AB",
+ heap_hton_comment,
+ NULL,
+ NULL,
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 1b0f4c34acc..0b2f561e8c9 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -42,6 +42,7 @@ have disables the InnoDB inlining in this file. */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
#include "ha_innodb.h"
pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
@@ -132,6 +133,7 @@ extern "C" {
#include "../storage/innobase/include/sync0sync.h"
#include "../storage/innobase/include/fil0fil.h"
#include "../storage/innobase/include/trx0xa.h"
+#include "../storage/innobase/include/thr0loc.h"
}
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
@@ -203,11 +205,15 @@ static int innobase_savepoint(THD* thd, void *savepoint);
static int innobase_release_savepoint(THD* thd, void *savepoint);
static handler *innobase_create_handler(TABLE_SHARE *table);
+static const char innobase_hton_name[]= "InnoDB";
+static const char innobase_hton_comment[]=
+ "Supports transactions, row-level locking, and foreign keys";
+
handlerton innobase_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "InnoDB",
+ innobase_hton_name,
SHOW_OPTION_YES,
- "Supports transactions, row-level locking, and foreign keys",
+ innobase_hton_comment,
DB_TYPE_INNODB,
innobase_init,
0, /* slot */
@@ -237,7 +243,7 @@ handlerton innobase_hton = {
NULL, /* Fill FILES table */
HTON_NO_FLAGS,
NULL, /* binlog_func */
- NULL, /* binlog_log_query */
+ NULL, /* binlog_log_query */
innobase_release_temporary_latches
};
@@ -535,18 +541,18 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_CORRUPTION) {
- return(HA_ERR_CRASHED);
- } else if (error == (int) DB_NO_SAVEPOINT) {
+ return(HA_ERR_CRASHED);
+ } else if (error == (int) DB_NO_SAVEPOINT) {
- return(HA_ERR_NO_SAVEPOINT);
- } else if (error == (int) DB_LOCK_TABLE_FULL) {
- /* 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 */
+ return(HA_ERR_NO_SAVEPOINT);
+ } else if (error == (int) DB_LOCK_TABLE_FULL) {
+ /* 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);
- }
+ if (thd) {
+ ha_rollback(thd);
+ }
return(HA_ERR_LOCK_TABLE_FULL);
} else {
@@ -1014,7 +1020,6 @@ innobase_query_caching_of_table_permitted(
mutex_enter_noninline(&kernel_mutex);
trx_print(stderr, trx, 1024);
mutex_exit_noninline(&kernel_mutex);
- ut_error;
}
innobase_release_stat_resources(trx);
@@ -1769,25 +1774,6 @@ innobase_report_binlog_offset_and_commit(
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, TRUE);
@@ -1856,121 +1842,9 @@ innobase_commit_complete(
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);
- }
-
- /* 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);
}
-
/*********************************************************************
Rolls back a transaction or the latest SQL statement. */
@@ -2196,6 +2070,7 @@ innobase_close_connection(
innobase_rollback_trx(trx);
+ thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx);
return(0);
@@ -2216,7 +2091,7 @@ ha_innobase::get_row_type() const
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
if (prebuilt && prebuilt->table) {
- if (innodb_dict_table_is_comp(prebuilt->table)) {
+ if (dict_table_is_comp_noninline(prebuilt->table)) {
return(ROW_TYPE_COMPACT);
} else {
return(ROW_TYPE_REDUNDANT);
@@ -3609,7 +3484,8 @@ calc_row_difference(
TRUE,
new_mysql_row_col,
col_pack_len,
- innodb_dict_table_is_comp(prebuilt->table));
+ dict_table_is_comp_noninline(
+ prebuilt->table));
ufield->new_val.data = dfield.data;
ufield->new_val.len = dfield.len;
} else {
@@ -3769,9 +3645,17 @@ ha_innobase::unlock_row(void)
ut_error;
}
+ /* Consistent read does not take any locks, thus there is
+ nothing to unlock. */
+
+ if (prebuilt->select_lock_type == LOCK_NONE) {
+ DBUG_VOID_RETURN;
+ }
+
switch (prebuilt->row_read_type) {
case ROW_READ_WITH_LOCKS:
- if (!srv_locks_unsafe_for_binlog) {
+ if (!srv_locks_unsafe_for_binlog
+ || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
break;
}
/* fall through */
@@ -3803,7 +3687,13 @@ ha_innobase::try_semi_consistent_read(bool yes)
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- if (yes && srv_locks_unsafe_for_binlog) {
+ /* Row read type is set to semi consistent read if this was
+ requested by the MySQL and either innodb_locks_unsafe_for_binlog
+ option is used or this session is using READ COMMITTED isolation
+ level. */
+
+ if (yes && (srv_locks_unsafe_for_binlog
+ || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
} else {
prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
@@ -5942,34 +5832,55 @@ ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
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);
+ ulong length;
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
+ {
+ length=7;
+ tmp_buff= "CASCADE";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ {
+ length=8;
+ tmp_buff= "SET NULL";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
+ {
+ length=9;
+ tmp_buff= "NO ACTION";
+ }
+ else
+ {
+ length=8;
+ tmp_buff= "RESTRICT";
+ }
+ f_key_info.delete_method= make_lex_string(thd, f_key_info.delete_method,
+ tmp_buff, length, 1);
+
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
+ {
+ length=7;
+ tmp_buff= "CASCADE";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
+ {
+ length=8;
+ tmp_buff= "SET NULL";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+ {
+ length=9;
+ tmp_buff= "NO ACTION";
+ }
+ else
+ {
+ length=8;
+ tmp_buff= "RESTRICT";
+ }
+ f_key_info.update_method= make_lex_string(thd, f_key_info.update_method,
+ tmp_buff, length, 1);
+
+
FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
thd->memdup((gptr) &f_key_info,
@@ -6286,12 +6197,6 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
- if (trx->n_mysql_tables_in_use == 1) {
- trx->isolation_level = innobase_map_isolation_level(
- (enum_tx_isolation)
- thd->variables.tx_isolation);
- }
-
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE
&& (thd->options
@@ -6765,11 +6670,22 @@ ha_innobase::store_lock(
TL_IGNORE */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ trx_t* trx = prebuilt->trx;
/* 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 no MySQL tables is use we need to set isolation level
+ of the transaction. */
+
+ if (lock_type != TL_IGNORE
+ && trx->n_mysql_tables_in_use == 0) {
+ trx->isolation_level = innobase_map_isolation_level(
+ (enum_tx_isolation)
+ thd->variables.tx_isolation);
+ }
+
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 ||
@@ -6794,18 +6710,26 @@ ha_innobase::store_lock(
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_INSERT_SELECT ||
- thd->lex->sql_command == SQLCOM_UPDATE)) {
+ ulint isolation_level;
+
+ isolation_level = trx->isolation_level;
+
+ if ((srv_locks_unsafe_for_binlog
+ || isolation_level == TRX_ISO_READ_COMMITTED)
+ && isolation_level != TRX_ISO_SERIALIZABLE
+ && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
+ && (thd->lex->sql_command == SQLCOM_INSERT_SELECT
+ || thd->lex->sql_command == SQLCOM_UPDATE
+ || thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
- /* In case we have innobase_locks_unsafe_for_binlog
- option set and isolation level of the transaction
+ /* If we either have innobase_locks_unsafe_for_binlog
+ option set or this session is using READ COMMITTED
+ isolation level and isolation level of the transaction
is not set to serializable and MySQL is doing
- INSERT INTO...SELECT or UPDATE ... = (SELECT ...)
- without FOR UPDATE or IN SHARE MODE in select, then
- we use consistent read for select. */
+ INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
+ CREATE ... SELECT... without FOR UPDATE or
+ IN SHARE MODE in select, then we use consistent
+ read for select. */
prebuilt->select_lock_type = LOCK_NONE;
prebuilt->stored_select_lock_type = LOCK_NONE;
@@ -6854,25 +6778,26 @@ ha_innobase::store_lock(
}
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
- TABLESPACE or TRUNCATE TABLE then allow multiple
+ TABLESPACE or TRUNCATE TABLE then allow multiple
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
< TL_WRITE_CONCURRENT_INSERT.
- We especially allow multiple writers if MySQL is at the
- start of a stored procedure call (SQLCOM_CALL)
- (MySQL does have thd->in_lock_tables TRUE there). */
+ We especially allow multiple writers if MySQL is at the
+ start of a stored procedure call (SQLCOM_CALL) or a
+ stored function call (MySQL does have thd->in_lock_tables
+ TRUE there). */
- if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
- && lock_type <= TL_WRITE)
- && !(thd->in_lock_tables
- && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
- && !thd->tablespace_op
- && thd->lex->sql_command != SQLCOM_TRUNCATE
- && thd->lex->sql_command != SQLCOM_OPTIMIZE
- && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
+ && lock_type <= TL_WRITE)
+ && !(thd->in_lock_tables
+ && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
+ && !thd->tablespace_op
+ && thd->lex->sql_command != SQLCOM_TRUNCATE
+ && thd->lex->sql_command != SQLCOM_OPTIMIZE
+ && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
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
@@ -7533,3 +7458,20 @@ bool ha_innobase::check_if_incompatible_data(
return COMPATIBLE_DATA_YES;
}
+
+
+mysql_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_hton,
+ innobase_hton_name,
+ "Innobase OY",
+ innobase_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 6bbe3a562d7..4f0c9eb151b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -316,9 +316,6 @@ int innobase_rollback_by_xid(
XID *xid); /* in : X/Open XA Transaction Identification */
-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.
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index ec39ee00efc..40081c975c8 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -31,6 +31,8 @@
#include "../storage/myisam/rt_index.h"
#endif
+#include <mysql/plugin.h>
+
ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */
@@ -54,11 +56,15 @@ static handler *myisam_create_handler(TABLE_SHARE *table);
/* MyISAM handlerton */
+static const char myisam_hton_name[]= "MyISAM";
+static const char myisam_hton_comment[]=
+ "Default engine as of MySQL 3.23 with great performance";
+
handlerton myisam_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MyISAM",
+ myisam_hton_name,
SHOW_OPTION_YES,
- "Default engine as of MySQL 3.23 with great performance",
+ myisam_hton_comment,
DB_TYPE_MYISAM,
NULL,
0, /* slot */
@@ -188,7 +194,7 @@ ha_myisam::ha_myisam(TABLE_SHARE *table_arg)
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),
+ HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS),
can_enable_indexes(1)
{}
@@ -350,6 +356,7 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
if (table->key_info[i].flags & HA_USES_PARSER)
file->s->keyinfo[i].parser=
(struct st_mysql_ftparser *)parser->plugin->info;
+ table->key_info[i].block_size= file->s->keyinfo[i].block_length;
}
return (0);
}
@@ -1368,7 +1375,7 @@ void ha_myisam::info(uint flag)
sortkey= info.sortkey;
ref_length= info.reflength;
share->db_options_in_use= info.options;
- block_size= myisam_block_size;
+ block_size= myisam_block_size; /* record block size */
/* Update share */
if (share->tmp_table == NO_TMP_TABLE)
@@ -1501,6 +1508,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
(pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
pos->algorithm;
+ keydef[i].block_length= pos->block_size;
+
keydef[i].seg=keyseg;
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
@@ -1777,7 +1786,8 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
if (info->auto_increment_value != auto_increment_value ||
info->data_file_name != data_file_name ||
info->index_file_name != index_file_name ||
- table_changes == IS_EQUAL_NO)
+ table_changes == IS_EQUAL_NO ||
+ table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
return COMPATIBLE_DATA_NO;
if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
@@ -1787,3 +1797,18 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_NO;
return COMPATIBLE_DATA_YES;
}
+
+
+mysql_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_hton,
+ myisam_hton_name,
+ "MySQL AB",
+ myisam_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 0ce4e1d8bcb..f4a052cea8a 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -28,6 +28,8 @@
#include "../storage/myisammrg/myrg_def.h"
#endif
+#include <mysql/plugin.h>
+
/*****************************************************************************
** MyISAM MERGE tables
*****************************************************************************/
@@ -36,11 +38,15 @@ static handler *myisammrg_create_handler(TABLE_SHARE *table);
/* MyISAM MERGE handlerton */
+static const char myisammrg_hton_name[]= "MRG_MYISAM";
+static const char myisammrg_hton_comment[]=
+ "Collection of identical MyISAM tables";
+
handlerton myisammrg_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MRG_MYISAM",
+ myisammrg_hton_name,
SHOW_OPTION_YES,
- "Collection of identical MyISAM tables",
+ myisammrg_hton_comment,
DB_TYPE_MRG_MYISAM,
NULL,
0, /* slot */
@@ -68,7 +74,7 @@ handlerton myisammrg_hton= {
NULL, /* Alter table flags */
NULL, /* Alter Tablespace */
NULL, /* Fill Files Table */
- HTON_CAN_RECREATE,
+ HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE,
NULL, /* binlog_func */
NULL, /* binlog_log_query */
NULL /* release_temporary_latches */
@@ -573,3 +579,17 @@ bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info,
*/
return COMPATIBLE_DATA_NO;
}
+
+mysql_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_hton,
+ myisammrg_hton_name,
+ "MySQL AB",
+ myisammrg_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 587eabb82d2..3425c638005 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -27,6 +27,7 @@
#include "mysql_priv.h"
#include <my_dir.h>
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
#include "ha_ndbcluster.h"
#include <ndbapi/NdbApi.hpp>
#include <ndbapi/NdbScanFilter.hpp>
@@ -36,6 +37,8 @@
#include "ha_ndbcluster_binlog.h"
#include "ha_ndbcluster_tables.h"
+#include <mysql/plugin.h>
+
#ifdef ndb_dynamite
#undef assert
#define assert(x) do { if(x) break; ::printf("%s %d: assert failed: %s\n", __FILE__, __LINE__, #x); ::fflush(stdout); ::signal(SIGABRT,SIG_DFL); ::abort(); ::kill(::getpid(),6); ::kill(::getpid(),9); } while (0)
@@ -66,6 +69,9 @@ static bool ndbcluster_show_status(THD*,stat_print_fn *,enum ha_stat_type);
static int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info);
static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond);
+static const char ndbcluster_hton_name[]= "ndbcluster";
+static const char ndbcluster_hton_comment[]= "Clustered, fault-tolerant tables";
+
handlerton ndbcluster_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
"ndbcluster",
@@ -100,7 +106,6 @@ static uint ndbcluster_alter_table_flags(uint flags)
}
-#define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0
#define NDB_AUTO_INCREMENT_RETRIES 10
#define ERR_PRINT(err) \
@@ -141,7 +146,7 @@ static int rename_share(NDB_SHARE *share, const char *new_key);
#endif
static void ndb_set_fragmentation(NDBTAB &tab, TABLE *table, uint pk_len);
-static int ndb_get_table_statistics(Ndb*, const char *,
+static int ndb_get_table_statistics(Ndb*, const NDBTAB *,
struct Ndb_statistics *);
@@ -176,6 +181,8 @@ static const char * ndb_connected_host= 0;
static long ndb_connected_port= 0;
static long ndb_number_of_replicas= 0;
long ndb_number_of_storage_nodes= 0;
+long ndb_number_of_ready_storage_nodes= 0;
+long ndb_connect_count= 0;
static int update_status_variables(Ndb_cluster_connection *c)
{
@@ -184,6 +191,8 @@ static int update_status_variables(Ndb_cluster_connection *c)
ndb_connected_host= c->get_connected_host();
ndb_number_of_replicas= 0;
ndb_number_of_storage_nodes= c->no_db_nodes();
+ ndb_number_of_ready_storage_nodes= c->get_no_ready();
+ ndb_connect_count= c->get_connect_count();
return 0;
}
@@ -315,6 +324,14 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans)
/*
Place holder for ha_ndbcluster thread specific data
*/
+static
+byte *thd_ndb_share_get_key(THD_NDB_SHARE *thd_ndb_share, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= sizeof(thd_ndb_share->key);
+ return (byte*) thd_ndb_share->key;
+}
+
Thd_ndb::Thd_ndb()
{
ndb= new Ndb(g_ndb_cluster_connection, "");
@@ -324,6 +341,8 @@ Thd_ndb::Thd_ndb()
stmt= NULL;
error= 0;
options= 0;
+ (void) hash_init(&open_tables, &my_charset_bin, 5, 0, 0,
+ (hash_get_key)thd_ndb_share_get_key, 0, 0);
}
Thd_ndb::~Thd_ndb()
@@ -347,6 +366,44 @@ Thd_ndb::~Thd_ndb()
ndb= NULL;
}
changed_tables.empty();
+ hash_free(&open_tables);
+}
+
+void
+Thd_ndb::init_open_tables()
+{
+ count= 0;
+ error= 0;
+ my_hash_reset(&open_tables);
+}
+
+THD_NDB_SHARE *
+Thd_ndb::get_open_table(THD *thd, const void *key)
+{
+ DBUG_ENTER("Thd_ndb::get_open_table");
+ HASH_SEARCH_STATE state;
+ THD_NDB_SHARE *thd_ndb_share=
+ (THD_NDB_SHARE*)hash_first(&open_tables, (byte *)key, sizeof(key), &state);
+ while (thd_ndb_share && thd_ndb_share->key != key)
+ thd_ndb_share= (THD_NDB_SHARE*)hash_next(&open_tables, (byte *)key, sizeof(key), &state);
+ if (thd_ndb_share == 0)
+ {
+ thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root,
+ sizeof(THD_NDB_SHARE));
+ thd_ndb_share->key= key;
+ thd_ndb_share->stat.last_count= count;
+ thd_ndb_share->stat.no_uncommitted_rows_count= 0;
+ thd_ndb_share->stat.records= ~(ha_rows)0;
+ my_hash_insert(&open_tables, (byte *)thd_ndb_share);
+ }
+ else if (thd_ndb_share->stat.last_count != count)
+ {
+ thd_ndb_share->stat.last_count= count;
+ thd_ndb_share->stat.no_uncommitted_rows_count= 0;
+ thd_ndb_share->stat.records= ~(ha_rows)0;
+ }
+ DBUG_PRINT("exit", ("thd_ndb_share: 0x%x key: 0x%x", thd_ndb_share, key));
+ DBUG_RETURN(thd_ndb_share);
}
inline
@@ -359,12 +416,6 @@ Ndb *ha_ndbcluster::get_ndb()
* manage uncommitted insert/deletes during transactio to get records correct
*/
-struct Ndb_local_table_statistics {
- int no_uncommitted_rows_count;
- ulong last_count;
- ha_rows records;
-};
-
void ha_ndbcluster::set_rec_per_key()
{
DBUG_ENTER("ha_ndbcluster::get_status_const");
@@ -380,16 +431,16 @@ void ha_ndbcluster::records_update()
if (m_ha_not_exact_count)
return;
DBUG_ENTER("ha_ndbcluster::records_update");
- struct Ndb_local_table_statistics *info=
- (struct Ndb_local_table_statistics *)m_table_info;
+ struct Ndb_local_table_statistics *info= m_table_info;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
((const NDBTAB *)m_table)->getTableId(),
info->no_uncommitted_rows_count));
// if (info->records == ~(ha_rows)0)
{
Ndb *ndb= get_ndb();
+ ndb->setDatabaseName(m_dbname);
struct Ndb_statistics stat;
- if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
+ if (ndb_get_table_statistics(ndb, m_table, &stat) == 0){
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
info->records= stat.row_count;
@@ -413,33 +464,12 @@ void ha_ndbcluster::no_uncommitted_rows_execute_failure()
DBUG_VOID_RETURN;
}
-void ha_ndbcluster::no_uncommitted_rows_init(THD *thd)
-{
- if (m_ha_not_exact_count)
- return;
- 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= get_thd_ndb(thd);
- if (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));
- }
- DBUG_VOID_RETURN;
-}
-
void ha_ndbcluster::no_uncommitted_rows_update(int c)
{
if (m_ha_not_exact_count)
return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_update");
- struct Ndb_local_table_statistics *info=
- (struct Ndb_local_table_statistics *)m_table_info;
+ struct Ndb_local_table_statistics *info= m_table_info;
info->no_uncommitted_rows_count+= c;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
((const NDBTAB *)m_table)->getTableId(),
@@ -458,95 +488,6 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
DBUG_VOID_RETURN;
}
-/*
- Take care of the error that occured in NDB
-
- RETURN
- 0 No error
- # The mapped error code
-*/
-
-int ha_ndbcluster::invalidate_dictionary_cache(bool global)
-{
- NDBDICT *dict= get_ndb()->getDictionary();
- DBUG_ENTER("invalidate_dictionary_cache");
- DBUG_PRINT("info", ("m_tabname: %s global: %d", m_tabname, global));
-
- if (global)
- {
-#ifdef HAVE_NDB_BINLOG
- if (current_thd != injector_thd)
- {
- char key[FN_REFLEN];
- build_table_filename(key, sizeof(key), m_dbname, m_tabname, "");
- DBUG_PRINT("info", ("Getting ndbcluster mutex"));
- pthread_mutex_lock(&ndbcluster_mutex);
- NDB_SHARE *ndb_share= (NDB_SHARE*)hash_search(&ndbcluster_open_tables,
- (byte*) key, strlen(key));
- // Only binlog_thread is allowed to globally invalidate a table
- if (ndb_share && ndb_share->op)
- {
- pthread_mutex_unlock(&ndbcluster_mutex);
- DBUG_PRINT("info", ("Released ndbcluster mutex"));
- DBUG_RETURN(1);
- }
- pthread_mutex_unlock(&ndbcluster_mutex);
- DBUG_PRINT("info", ("Released ndbcluster mutex"));
- }
-#endif
- const NDBTAB *tab= dict->getTable(m_tabname);
- if (!tab)
- DBUG_RETURN(1);
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- // Global cache has already been invalidated
- dict->removeCachedTable(m_tabname);
- global= FALSE;
- DBUG_PRINT("info", ("global: %d", global));
- }
- else
- dict->invalidateTable(m_tabname);
- table_share->version= 0L; /* Free when thread is ready */
- }
- else
- dict->removeCachedTable(m_tabname);
-
- /* Invalidate indexes */
- for (uint i= 0; i < table_share->keys; i++)
- {
- NDBINDEX *index = (NDBINDEX *) m_index[i].index;
- NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
- if (!index && !unique_index)
- continue;
- NDB_INDEX_TYPE idx_type= m_index[i].type;
-
- 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:
- if (global)
- dict->invalidateIndex(index->getName(), m_tabname);
- else
- dict->removeCachedIndex(index->getName(), m_tabname);
- 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:
- break;
- }
- }
- DBUG_RETURN(0);
-}
-
int ha_ndbcluster::ndb_err(NdbTransaction *trans)
{
int res;
@@ -557,32 +498,14 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
switch (err.classification) {
case NdbError::SchemaError:
{
+ // TODO perhaps we need to do more here, invalidate also in the cache
+ m_table->setStatusInvalid();
/* Close other open handlers not used by any thread */
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= m_dbname;
table_list.alias= table_list.table_name= m_tabname;
close_cached_tables(current_thd, 0, &table_list);
-
- invalidate_dictionary_cache(TRUE);
-
- if (err.code==284)
- {
- /*
- Check if the table is _really_ gone or if the table has
- been alterend and thus changed table id
- */
- NDBDICT *dict= get_ndb()->getDictionary();
- DBUG_PRINT("info", ("Check if table %s is really gone", m_tabname));
- if (!(dict->getTable(m_tabname)))
- {
- err= dict->getNdbError();
- DBUG_PRINT("info", ("Table not found, error: %d", err.code));
- if (err.code != 709 && err.code != 723)
- DBUG_RETURN(1);
- }
- DBUG_PRINT("info", ("Table exists but must have changed"));
- }
break;
}
default:
@@ -1028,73 +951,59 @@ int ha_ndbcluster::get_metadata(const char *path)
NDBDICT *dict= ndb->getDictionary();
const NDBTAB *tab;
int error;
- bool invalidating_ndb_table= FALSE;
DBUG_ENTER("get_metadata");
DBUG_PRINT("enter", ("m_tabname: %s, path: %s", m_tabname, path));
- do {
- const void *data, *pack_data;
- uint length, pack_length;
+ DBUG_ASSERT(m_table == NULL);
+ DBUG_ASSERT(m_table_info == NULL);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
- }
- /*
- Compare FrmData in NDB with frm file from disk.
- */
- error= 0;
- if (readfrm(path, &data, &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));
- DBUG_RETURN(1);
- }
+ const void *data, *pack_data;
+ uint length, pack_length;
+
+ /*
+ Compare FrmData in NDB with frm file from disk.
+ */
+ error= 0;
+ if (readfrm(path, &data, &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));
+ DBUG_RETURN(1);
+ }
- if (get_ndb_share_state(m_share) != NSS_ALTERED
- && cmp_frm(tab, pack_data, pack_length))
- {
- if (!invalidating_ndb_table)
- {
- DBUG_PRINT("info", ("Invalidating table"));
- invalidate_dictionary_cache(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= HA_ERR_TABLE_DEF_CHANGED;
- invalidating_ndb_table= FALSE;
- }
- }
- else
- {
- invalidating_ndb_table= FALSE;
- }
- my_free((char*)data, MYF(0));
- my_free((char*)pack_data, MYF(0));
- } while (invalidating_ndb_table);
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ if (!(tab= ndbtab_g.get_table()))
+ ERR_RETURN(dict->getNdbError());
+
+ if (get_ndb_share_state(m_share) != NSS_ALTERED
+ && cmp_frm(tab, pack_data, pack_length))
+ {
+ 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= HA_ERR_TABLE_DEF_CHANGED;
+ }
+ my_free((char*)data, MYF(0));
+ my_free((char*)pack_data, MYF(0));
if (error)
- DBUG_RETURN(error);
-
- m_table_version= tab->getObjectVersion();
- m_table= (void *)tab;
- m_table_info= NULL; // Set in external lock
-
- DBUG_RETURN(open_indexes(ndb, table, FALSE));
+ goto err;
+
+ DBUG_PRINT("info", ("fetched table %s", tab->getName()));
+ m_table= tab;
+ if ((error= open_indexes(ndb, table, FALSE)) == 0)
+ {
+ ndbtab_g.release();
+ DBUG_RETURN(0);
+ }
+err:
+ ndbtab_g.invalidate();
+ m_table= NULL;
+ DBUG_RETURN(error);
}
static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
@@ -1131,36 +1040,6 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
DBUG_RETURN(0);
}
-int ha_ndbcluster::table_changed(const void *pack_frm_data, uint pack_frm_len)
-{
- Ndb *ndb;
- NDBDICT *dict;
- const NDBTAB *orig_tab;
- NdbDictionary::Table new_tab;
- int result;
- DBUG_ENTER("ha_ndbcluster::table_changed");
- DBUG_PRINT("info", ("Modifying frm for table %s", m_tabname));
- if (check_ndb_connection())
- DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION);
-
- ndb= get_ndb();
- dict= ndb->getDictionary();
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- dict->removeCachedTable(m_tabname);
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- }
- new_tab= *orig_tab;
- new_tab.setFrm(pack_frm_data, pack_frm_len);
- if (dict->alterTable(new_tab) != 0)
- ERR_RETURN(dict->getNdbError());
- DBUG_RETURN(0);
-}
-
/*
Create all the indexes for a table.
If any index should fail to be created,
@@ -1191,22 +1070,30 @@ int ha_ndbcluster::create_indexes(Ndb *ndb, TABLE *tab)
DBUG_RETURN(error);
}
-void ha_ndbcluster::clear_index(int i)
+static void ndb_init_index(NDB_INDEX_DATA &data)
{
- m_index[i].type= UNDEFINED_INDEX;
- m_index[i].status= UNDEFINED;
- m_index[i].unique_index= NULL;
- m_index[i].index= NULL;
- m_index[i].unique_index_attrid_map= NULL;
- m_index[i].index_stat=NULL;
- m_index[i].index_stat_cache_entries=0;
- m_index[i].index_stat_update_freq=0;
- m_index[i].index_stat_query_count=0;
+ data.type= UNDEFINED_INDEX;
+ data.status= UNDEFINED;
+ data.unique_index= NULL;
+ data.index= NULL;
+ data.unique_index_attrid_map= NULL;
+ data.index_stat=NULL;
+ data.index_stat_cache_entries=0;
+ data.index_stat_update_freq=0;
+ data.index_stat_query_count=0;
}
-void ha_ndbcluster::clear_indexes()
+static void ndb_clear_index(NDB_INDEX_DATA &data)
{
- for (int i= 0; i < MAX_KEY; i++) clear_index(i);
+ if (data.unique_index_attrid_map)
+ {
+ my_free((char*)data.unique_index_attrid_map, MYF(0));
+ }
+ if (data.index_stat)
+ {
+ delete data.index_stat;
+ }
+ ndb_init_index(data);
}
/*
@@ -1219,14 +1106,29 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
int error= 0;
NDB_INDEX_TYPE idx_type= get_index_type_from_table(index_no);
m_index[index_no].type= idx_type;
- DBUG_ENTER("ha_ndbcluster::get_index_handle");
+ DBUG_ENTER("ha_ndbcluster::add_index_handle");
+ DBUG_PRINT("enter", ("table %s", m_tabname));
if (idx_type != PRIMARY_KEY_INDEX && idx_type != UNIQUE_INDEX)
{
DBUG_PRINT("info", ("Get handle to index %s", index_name));
- const NDBINDEX *index= dict->getIndex(index_name, m_tabname);
- if (!index) ERR_RETURN(dict->getNdbError());
- m_index[index_no].index= (void *) index;
+ const NDBINDEX *index;
+ do
+ {
+ index= dict->getIndexGlobal(index_name, *m_table);
+ if (!index)
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
+ index,
+ index->getObjectId(),
+ index->getObjectVersion() & 0xFFFFFF,
+ index->getObjectVersion() >> 24,
+ index->getObjectStatus()));
+ DBUG_ASSERT(index->getObjectStatus() ==
+ NdbDictionary::Object::Retrieved);
+ break;
+ } while (1);
+ m_index[index_no].index= index;
// ordered index - add stats
NDB_INDEX_DATA& d=m_index[index_no];
delete d.index_stat;
@@ -1254,9 +1156,23 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
m_has_unique_index= TRUE;
strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name));
- const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname);
- if (!index) ERR_RETURN(dict->getNdbError());
- m_index[index_no].unique_index= (void *) index;
+ const NDBINDEX *index;
+ do
+ {
+ index= dict->getIndexGlobal(unique_index_name, *m_table);
+ if (!index)
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
+ index,
+ index->getObjectId(),
+ index->getObjectVersion() & 0xFFFFFF,
+ index->getObjectVersion() >> 24,
+ index->getObjectStatus()));
+ DBUG_ASSERT(index->getObjectStatus() ==
+ NdbDictionary::Object::Retrieved);
+ break;
+ } while (1);
+ m_index[index_no].unique_index= index;
error= fix_unique_index_attr_order(m_index[index_no], index, key_info);
}
if (!error)
@@ -1287,7 +1203,27 @@ int ha_ndbcluster::open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error)
else
break;
}
-
+
+ if (error && !ignore_error)
+ {
+ while (i > 0)
+ {
+ i--;
+ if (m_index[i].index)
+ {
+ dict->removeIndexGlobal(*m_index[i].index, 1);
+ m_index[i].index= NULL;
+ }
+ if (m_index[i].unique_index)
+ {
+ dict->removeIndexGlobal(*m_index[i].unique_index, 1);
+ m_index[i].unique_index= NULL;
+ }
+ }
+ }
+
+ DBUG_ASSERT(error == 0 || error == 4243);
+
DBUG_RETURN(error);
}
@@ -1347,30 +1283,36 @@ int ha_ndbcluster::drop_indexes(Ndb *ndb, TABLE *tab)
m_index[i].type= idx_type;
if (m_index[i].status == TO_BE_DROPPED)
{
- NdbDictionary::Index *index=
- (NdbDictionary::Index *) m_index[i].index;
- NdbDictionary::Index *unique_index=
- (NdbDictionary::Index *) m_index[i].unique_index;
+ const NdbDictionary::Index *index= m_index[i].index;
+ const NdbDictionary::Index *unique_index= m_index[i].unique_index;
if (index)
{
index_name= index->getName();
DBUG_PRINT("info", ("Dropping index %u: %s", i, index_name));
// Drop ordered index from ndb
- error= drop_ndb_index(index_name);
+ error= dict->dropIndexGlobal(*index);
+ if (!error)
+ {
+ dict->removeIndexGlobal(*index, 1);
+ m_index[i].index= NULL;
+ }
}
- if (!error)
- m_index[i].index= NULL;
if (!error && unique_index)
{
index_name= unique_index->getName();
DBUG_PRINT("info", ("Dropping unique index %u: %s", i, index_name));
// Drop unique index from ndb
- error= drop_ndb_index(index_name);
+ error= dict->dropIndexGlobal(*unique_index);
+ if (!error)
+ {
+ dict->removeIndexGlobal(*unique_index, 1);
+ m_index[i].unique_index= NULL;
+ }
}
if (error)
DBUG_RETURN(error);
- clear_index(i);
+ ndb_clear_index(m_index[i]);
continue;
}
}
@@ -1423,30 +1365,46 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx)
DBUG_RETURN(0);
}
-void ha_ndbcluster::release_metadata()
+void ha_ndbcluster::release_metadata(THD *thd, Ndb *ndb)
{
uint i;
DBUG_ENTER("release_metadata");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
- m_table= NULL;
+ NDBDICT *dict= ndb->getDictionary();
+ int invalidate_indexes= 0;
+ if (thd && thd->lex && thd->lex->sql_command == SQLCOM_FLUSH)
+ {
+ invalidate_indexes = 1;
+ }
+ if (m_table != NULL)
+ {
+ if (m_table->getObjectStatus() == NdbDictionary::Object::Invalid)
+ invalidate_indexes= 1;
+ dict->removeTableGlobal(*m_table, invalidate_indexes);
+ }
+ // TODO investigate
+ DBUG_ASSERT(m_table_info == NULL);
m_table_info= NULL;
// Release index list
for (i= 0; i < MAX_KEY; i++)
{
- m_index[i].unique_index= NULL;
- m_index[i].index= NULL;
- if (m_index[i].unique_index_attrid_map)
+ if (m_index[i].unique_index)
{
- my_free((char *)m_index[i].unique_index_attrid_map, MYF(0));
- m_index[i].unique_index_attrid_map= NULL;
+ DBUG_ASSERT(m_table != NULL);
+ dict->removeIndexGlobal(*m_index[i].unique_index, invalidate_indexes);
}
- delete m_index[i].index_stat;
- m_index[i].index_stat=NULL;
+ if (m_index[i].index)
+ {
+ DBUG_ASSERT(m_table != NULL);
+ dict->removeIndexGlobal(*m_index[i].index, invalidate_indexes);
+ }
+ ndb_clear_index(m_index[i]);
}
+ m_table= NULL;
DBUG_VOID_RETURN;
}
@@ -1918,11 +1876,10 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record)
{
// A unique index is defined on table
NdbIndexOperation *iop;
- NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
+ const NDBINDEX *unique_index = m_index[i].unique_index;
key_part= key_info->key_part;
end= key_part + key_info->key_parts;
- if (!(iop= trans->getNdbIndexOperation(unique_index,
- (const NDBTAB *) m_table)) ||
+ if (!(iop= trans->getNdbIndexOperation(unique_index, m_table)) ||
iop->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
@@ -1971,9 +1928,8 @@ int ha_ndbcluster::unique_index_read(const byte *key,
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op= trans->getNdbIndexOperation((NDBINDEX *)
- m_index[active_index].unique_index,
- (const NDBTAB *) m_table)) ||
+ if (!(op= trans->getNdbIndexOperation(m_index[active_index].unique_index,
+ m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
@@ -2312,9 +2268,8 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
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)) ||
+ if (!(op= trans->getNdbIndexScanOperation(m_index[active_index].index,
+ m_table)) ||
op->readTuples(lm, 0, parallelism, sorted, descending))
ERR_RETURN(trans->getNdbError());
if (m_use_partition_function && part_spec != NULL &&
@@ -2384,7 +2339,7 @@ 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)) ||
+ if (!(op=trans->getNdbScanOperation(m_table)) ||
op->readTuples(lm, 0, parallelism))
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
@@ -2486,7 +2441,7 @@ int ha_ndbcluster::write_row(byte *record)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
- if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
+ if (!(op= trans->getNdbOperation(m_table)))
ERR_RETURN(trans->getNdbError());
res= (m_use_write) ? op->writeTuple() :op->insertTuple();
@@ -2509,14 +2464,16 @@ int ha_ndbcluster::write_row(byte *record)
{
// Table has hidden primary key
Ndb *ndb= get_ndb();
- Uint64 auto_value= NDB_FAILED_AUTO_INCREMENT;
+ int ret;
+ Uint64 auto_value;
uint retries= NDB_AUTO_INCREMENT_RETRIES;
do {
- auto_value= ndb->getAutoIncrementValue((const NDBTAB *) m_table);
- } while (auto_value == NDB_FAILED_AUTO_INCREMENT &&
+ Ndb_tuple_id_range_guard g(m_share);
+ ret= ndb->getAutoIncrementValue(m_table, g.range, auto_value, 1);
+ } while (ret == -1 &&
--retries &&
ndb->getNdbError().status == NdbError::TemporaryError);
- if (auto_value == NDB_FAILED_AUTO_INCREMENT)
+ if (ret == -1)
ERR_RETURN(ndb->getNdbError());
if (set_hidden_key(op, table_share->fields, (const byte*)&auto_value))
ERR_RETURN(op->getNdbError());
@@ -2611,11 +2568,12 @@ 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",
- (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));
+ ("Trying to set next auto increment value to %llu",
+ (ulonglong) next_val));
+ Ndb_tuple_id_range_guard g(m_share);
+ if (ndb->setAutoIncrementValue(m_table, g.range, next_val, TRUE)
+ == -1)
+ ERR_RETURN(ndb->getNdbError());
}
m_skip_auto_increment= TRUE;
@@ -2763,7 +2721,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
}
else
{
- if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
+ if (!(op= trans->getNdbOperation(m_table)) ||
op->updateTuple() != 0)
ERR_RETURN(trans->getNdbError());
@@ -2872,7 +2830,7 @@ int ha_ndbcluster::delete_row(const byte *record)
else
{
- if (!(op=trans->getNdbOperation((const NDBTAB *) m_table)) ||
+ if (!(op=trans->getNdbOperation(m_table)) ||
op->deleteTuple() != 0)
ERR_RETURN(trans->getNdbError());
@@ -2923,7 +2881,7 @@ void ndb_unpack_record(TABLE *table, NdbValue *value,
MY_BITMAP *defined, byte *buf)
{
Field **p_field= table->field, *field= *p_field;
- uint row_offset= (uint) (buf - table->record[0]);
+ my_ptrdiff_t row_offset= buf - table->record[0];
DBUG_ENTER("ndb_unpack_record");
// Set null flag(s)
@@ -2954,24 +2912,34 @@ void ndb_unpack_record(TABLE *table, NdbValue *value,
}
else if (field->type() == MYSQL_TYPE_BIT)
{
- byte *save_field_ptr= field->ptr;
- field->ptr= save_field_ptr + row_offset;
+ Field_bit *field_bit= static_cast<Field_bit*>(field);
+
+ /*
+ Move internal field pointer to point to 'buf'. Calling
+ the correct member function directly since we know the
+ type of the object.
+ */
+ field_bit->Field_bit::move_field_offset(row_offset);
if (field->pack_length() < 5)
{
DBUG_PRINT("info", ("bit field H'%.8X",
(*value).rec->u_32_value()));
- ((Field_bit*) field)->store((longlong)
- (*value).rec->u_32_value(), FALSE);
+ field_bit->Field_bit::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);
+ field_bit->Field_bit::store((longlong) (*value).rec->u_64_value(),
+ TRUE);
}
- field->ptr= save_field_ptr;
+ /*
+ Move back internal field pointer to point to original
+ value (usually record[0]).
+ */
+ field_bit->Field_bit::move_field_offset(-row_offset);
DBUG_PRINT("info",("[%u] SET",
(*value).rec->getColumn()->getColumnNo()));
DBUG_DUMP("info", (const char*) field->ptr, field->field_length);
@@ -3025,7 +2993,7 @@ void ha_ndbcluster::unpack_record(byte *buf)
{
// Table with hidden primary key
int hidden_no= table_share->fields;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec);
@@ -3501,7 +3469,7 @@ void ha_ndbcluster::position(const byte *record)
key_length= ref_length;
#ifndef DBUG_OFF
int hidden_no= table->s->fields;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
DBUG_ASSERT(hidden_col->getPrimaryKey() &&
hidden_col->getAutoIncrement() &&
@@ -3544,9 +3512,10 @@ void ha_ndbcluster::info(uint flag)
if ((my_errno= check_ndb_connection()))
DBUG_VOID_RETURN;
Ndb *ndb= get_ndb();
+ ndb->setDatabaseName(m_dbname);
struct Ndb_statistics stat;
if (current_thd->variables.ndb_use_exact_count &&
- ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
+ ndb_get_table_statistics(ndb, m_table, &stat) == 0)
{
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
@@ -3575,9 +3544,19 @@ void ha_ndbcluster::info(uint flag)
if (m_table)
{
Ndb *ndb= get_ndb();
+ Ndb_tuple_id_range_guard g(m_share);
- auto_increment_value=
- ndb->readAutoIncrementValue((const NDBTAB *) m_table);
+ Uint64 auto_increment_value64;
+ if (ndb->readAutoIncrementValue(m_table, g.range,
+ auto_increment_value64) == -1)
+ {
+ const NdbError err= ndb->getNdbError();
+ sql_print_error("Error %lu in readAutoIncrementValue(): %s",
+ (ulong) err.code, err.message);
+ auto_increment_value= ~(Uint64)0;
+ }
+ else
+ auto_increment_value= (ulonglong)auto_increment_value64;
}
}
DBUG_VOID_RETURN;
@@ -3661,7 +3640,7 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
void ha_ndbcluster::start_bulk_insert(ha_rows rows)
{
int bytes, batch;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
DBUG_ENTER("start_bulk_insert");
DBUG_PRINT("enter", ("rows: %d", (int)rows));
@@ -3883,7 +3862,7 @@ 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);
+ thd_ndb->init_open_tables();
thd_ndb->stmt= trans;
trans_register_ha(thd, FALSE, &ndbcluster_hton);
}
@@ -3898,7 +3877,7 @@ 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);
+ thd_ndb->init_open_tables();
thd_ndb->all= trans;
trans_register_ha(thd, TRUE, &ndbcluster_hton);
@@ -3940,44 +3919,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
// Start of transaction
m_rows_changed= 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());
- DBUG_PRINT("info", ("Table schema version: %d",
- tab->getObjectVersion()));
- // Check if thread has stale local cache
- // New transaction must not use old tables... (trans != 0)
- // Running might...
- if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved)
- || tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE);
- if (!(tab= dict->getTable(m_tabname, &tab_info)))
- ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d",
- tab->getObjectVersion()));
- }
- if (m_table_version < tab->getObjectVersion())
- {
- /*
- The table has been altered, caller has to retry
- */
- NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT);
- DBUG_RETURN(ndb_to_mysql_error(&err));
- }
- if (m_table != (void *)tab)
- {
- m_table= (void *)tab;
- m_table_version = tab->getObjectVersion();
- if (!(my_errno= open_indexes(ndb, table, FALSE)))
- DBUG_RETURN(my_errno);
- }
- m_table_info= tab_info;
- }
- no_uncommitted_rows_init(thd);
+
+ // TODO remove double pointers...
+ m_thd_ndb_share= thd_ndb->get_open_table(thd, m_table);
+ m_table_info= &m_thd_ndb_share->stat;
}
else
{
@@ -4512,8 +4457,11 @@ int ha_ndbcluster::create(const char *name,
if (readfrm(name, &data, &length))
DBUG_RETURN(1);
if (packfrm(data, length, &pack_data, &pack_length))
+ {
+ my_free((char*)data, MYF(0));
DBUG_RETURN(2);
-
+ }
+
DBUG_PRINT("info", ("setFrm data=%lx len=%d", pack_data, pack_length));
tab.setFrm(pack_data, pack_length);
my_free((char*)data, MYF(0));
@@ -4620,6 +4568,14 @@ int ha_ndbcluster::create(const char *name,
my_errno= ndb_to_mysql_error(&err);
DBUG_RETURN(my_errno);
}
+
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ // temporary set m_table during create
+ // reset at return
+ m_table= ndbtab_g.get_table();
+ // TODO check also that we have the same frm...
+ DBUG_ASSERT(m_table != 0);
+
DBUG_PRINT("info", ("Table %s/%s created successfully",
m_dbname, m_tabname));
@@ -4634,7 +4590,10 @@ int ha_ndbcluster::create(const char *name,
Failed to create an index,
drop the table (and all it's indexes)
*/
- drop_ndb_table();
+ if (dict->dropTableGlobal(*m_table) == 0)
+ {
+ m_table = 0;
+ }
}
#ifdef HAVE_NDB_BINLOG
@@ -4664,7 +4623,6 @@ int ha_ndbcluster::create(const char *name,
while (!IS_TMP_PREFIX(m_tabname))
{
- const NDBTAB *t= dict->getTable(m_tabname);
String event_name(INJECTOR_EVENT_LEN);
ndb_rep_event_name(&event_name,m_dbname,m_tabname);
int do_event_op= ndb_binlog_running;
@@ -4678,14 +4636,14 @@ int ha_ndbcluster::create(const char *name,
Always create an event for the table, as other mysql servers
expect it to be there.
*/
- if (!ndbcluster_create_event(ndb, t, event_name.c_ptr(), share,
+ if (!ndbcluster_create_event(ndb, m_table, event_name.c_ptr(), share,
share && do_event_op /* push warning */))
{
if (ndb_extra_logging)
sql_print_information("NDB Binlog: CREATE TABLE Event: %s",
event_name.c_ptr());
if (share && do_event_op &&
- ndbcluster_create_event_ops(share, t, event_name.c_ptr()))
+ ndbcluster_create_event_ops(share, m_table, event_name.c_ptr()))
{
sql_print_error("NDB Binlog: FAILED CREATE TABLE event operations."
" Event: %s", name);
@@ -4701,17 +4659,22 @@ int ha_ndbcluster::create(const char *name,
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
share->db, share->table_name,
- 0, 0,
+ m_table->getObjectId(),
+ m_table->getObjectVersion(),
SOT_CREATE_TABLE);
break;
}
}
#endif /* HAVE_NDB_BINLOG */
+ m_table= 0;
DBUG_RETURN(my_errno);
}
-int ha_ndbcluster::create_handler_files(const char *file, HA_CREATE_INFO *info)
+int ha_ndbcluster::create_handler_files(const char *file,
+ const char *old_name,
+ int action_flag,
+ HA_CREATE_INFO *info)
{
char path[FN_REFLEN];
const char *name;
@@ -4723,6 +4686,10 @@ int ha_ndbcluster::create_handler_files(const char *file, HA_CREATE_INFO *info)
DBUG_ENTER("create_handler_files");
+ if (action_flag != CHF_INDEX_FLAG)
+ {
+ DBUG_RETURN(FALSE);
+ }
DBUG_PRINT("enter", ("file: %s", file));
if (!(ndb= get_ndb()))
DBUG_RETURN(HA_ERR_NO_CONNECTION);
@@ -4730,10 +4697,15 @@ int ha_ndbcluster::create_handler_files(const char *file, HA_CREATE_INFO *info)
NDBDICT *dict= ndb->getDictionary();
if (!info->frm_only)
DBUG_RETURN(0); // Must be a create, ignore since frm is saved in create
+
+ // TODO handle this
+ DBUG_ASSERT(m_table != 0);
+
set_dbname(file);
set_tabname(file);
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
DBUG_PRINT("info", ("m_dbname: %s, m_tabname: %s", m_dbname, m_tabname));
- if (!(tab= dict->getTable(m_tabname)))
+ if (!(tab= ndbtab_g.get_table()))
DBUG_RETURN(0); // Unkown table, must be temporary table
DBUG_ASSERT(get_ndb_share_state(m_share) == NSS_ALTERED);
@@ -4749,7 +4721,12 @@ int ha_ndbcluster::create_handler_files(const char *file, HA_CREATE_INFO *info)
{
DBUG_PRINT("info", ("Table %s has changed, altering frm in ndb",
m_tabname));
- error= table_changed(pack_data, pack_length);
+ NdbDictionary::Table new_tab= *tab;
+ new_tab.setFrm(pack_data, pack_length);
+ if (dict->alterTableGlobal(*tab, new_tab))
+ {
+ error= ndb_to_mysql_error(&dict->getNdbError());
+ }
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
}
@@ -4852,7 +4829,7 @@ int ha_ndbcluster::create_ndb_index(const char *name,
ndb_index.addColumnName(field->field_name);
}
- if (dict->createIndex(ndb_index))
+ if (dict->createIndex(ndb_index, *m_table))
ERR_RETURN(dict->getNdbError());
// Success
@@ -4906,18 +4883,6 @@ int ha_ndbcluster::add_index(TABLE *table_arg,
}
/*
- Drop an index in ndb
- */
-int ha_ndbcluster::drop_ndb_index(const char *name)
-{
- DBUG_ENTER("ha_ndbcluster::drop_index");
- DBUG_PRINT("enter", ("name: %s ", name));
- Ndb *ndb= get_ndb();
- NdbDictionary::Dictionary *dict= ndb->getDictionary();
- DBUG_RETURN(dict->dropIndex(name, m_tabname));
-}
-
-/*
Mark one or several indexes for deletion. and
renumber the remaining indexes
*/
@@ -4985,16 +4950,14 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
Ndb *ndb= get_ndb();
ndb->setDatabaseName(old_dbname);
dict= ndb->getDictionary();
- if (!(orig_tab= dict->getTable(m_tabname)))
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ if (!(orig_tab= ndbtab_g.get_table()))
ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- dict->removeCachedTable(m_tabname);
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- }
+
#ifdef HAVE_NDB_BINLOG
+ int ndb_table_id= orig_tab->getObjectId();
+ int ndb_table_version= orig_tab->getObjectVersion();
+
NDB_SHARE *share= get_share(from, 0, false);
if (share)
{
@@ -5002,13 +4965,15 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
DBUG_ASSERT(r == 0);
}
#endif
- m_table= (void *)orig_tab;
// Change current database to that of target table
set_dbname(to);
ndb->setDatabaseName(m_dbname);
- if ((result= alter_table_name(new_tabname)))
+ NdbDictionary::Table new_tab= *orig_tab;
+ new_tab.setName(new_tabname);
+ if (dict->alterTableGlobal(*orig_tab, new_tab) != 0)
{
+ NdbError ndb_error= dict->getNdbError();
#ifdef HAVE_NDB_BINLOG
if (share)
{
@@ -5017,7 +4982,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
free_share(&share);
}
#endif
- DBUG_RETURN(result);
+ ERR_RETURN(ndb_error);
}
// Rename .ndb file
@@ -5051,7 +5016,8 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
/* always create an event for the table */
String event_name(INJECTOR_EVENT_LEN);
ndb_rep_event_name(&event_name, to + sizeof(share_prefix) - 1, 0);
- const NDBTAB *ndbtab= dict->getTable(new_tabname);
+ Ndb_table_guard ndbtab_g2(dict, new_tabname);
+ const NDBTAB *ndbtab= ndbtab_g2.get_table();
if (!ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share,
share && ndb_binlog_running /* push warning */))
@@ -5074,10 +5040,10 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
if (!is_old_table_tmpfile)
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
- m_dbname, new_tabname,
- 0, 0,
+ old_dbname, m_tabname,
+ ndb_table_id, ndb_table_version,
SOT_RENAME_TABLE,
- old_dbname, m_tabname);
+ m_dbname, new_tabname);
}
if (share)
free_share(&share);
@@ -5088,30 +5054,6 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
/*
- Rename a table in NDB Cluster using alter table
- */
-
-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;
- DBUG_ENTER("alter_table_name");
- DBUG_PRINT("info", ("from: %s to: %s", orig_tab->getName(), to));
-
- NdbDictionary::Table new_tab= *orig_tab;
- new_tab.setName(to);
- if (dict->alterTable(new_tab) != 0)
- ERR_RETURN(dict->getNdbError());
-
- m_table= NULL;
- m_table_info= NULL;
-
- DBUG_RETURN(0);
-}
-
-
-/*
Delete table from NDB Cluster
*/
@@ -5127,6 +5069,8 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
DBUG_ENTER("ha_ndbcluster::ndbcluster_delete_table");
NDBDICT *dict= ndb->getDictionary();
#ifdef HAVE_NDB_BINLOG
+ int ndb_table_id= 0;
+ int ndb_table_version= 0;
/*
Don't allow drop table unless
schema distribution table is setup
@@ -5142,14 +5086,45 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
/* Drop the table from NDB */
int res;
- if (h)
+ if (h && h->m_table)
{
- res= h->drop_ndb_table();
+ if (dict->dropTableGlobal(*h->m_table))
+ res= ndb_to_mysql_error(&dict->getNdbError());
+#ifdef HAVE_NDB_BINLOG
+ if (res == 0)
+ {
+ ndb_table_id= h->m_table->getObjectId();
+ ndb_table_version= h->m_table->getObjectVersion();
+ }
+#endif
+ h->release_metadata(current_thd, ndb);
}
else
{
ndb->setDatabaseName(db);
- res= dict->dropTable(table_name);
+ while (1)
+ {
+ Ndb_table_guard ndbtab_g(dict, table_name);
+ if (ndbtab_g.get_table())
+ {
+ if (dict->dropTableGlobal(*ndbtab_g.get_table()) == 0)
+ {
+#ifdef HAVE_NDB_BINLOG
+ ndb_table_id= ndbtab_g.get_table()->getObjectId();
+ ndb_table_version= ndbtab_g.get_table()->getObjectVersion();
+#endif
+ res= 0;
+ }
+ else if (dict->getNdbError().code == NDB_INVALID_SCHEMA_OBJECT)
+ {
+ ndbtab_g.invalidate();
+ continue;
+ }
+ }
+ else
+ res= ndb_to_mysql_error(&dict->getNdbError());
+ break;
+ }
}
if (res)
@@ -5191,7 +5166,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
share->db, share->table_name,
- 0, 0,
+ ndb_table_id, ndb_table_version,
SOT_DROP_TABLE);
}
else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op
@@ -5255,24 +5230,6 @@ int ha_ndbcluster::delete_table(const char *name)
}
-/*
- Drop table in NDB Cluster
- */
-
-int ha_ndbcluster::drop_ndb_table()
-{
- Ndb *ndb= get_ndb();
- NdbDictionary::Dictionary *dict= ndb->getDictionary();
-
- DBUG_ENTER("intern_drop_table");
- DBUG_PRINT("enter", ("Deleting %s", m_tabname));
- release_metadata();
- if (dict->dropTable(m_tabname))
- ERR_RETURN(dict->getNdbError());
- DBUG_RETURN(0);
-}
-
-
ulonglong ha_ndbcluster::get_auto_increment()
{
int cache_size;
@@ -5291,17 +5248,18 @@ ulonglong ha_ndbcluster::get_auto_increment()
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;
+ int ret;
uint retries= NDB_AUTO_INCREMENT_RETRIES;
do {
- auto_value=
- (m_skip_auto_increment) ?
- ndb->readAutoIncrementValue((const NDBTAB *) m_table)
- : ndb->getAutoIncrementValue((const NDBTAB *) m_table, cache_size);
- } while (auto_value == NDB_FAILED_AUTO_INCREMENT &&
+ Ndb_tuple_id_range_guard g(m_share);
+ ret=
+ m_skip_auto_increment ?
+ ndb->readAutoIncrementValue(m_table, g.range, auto_value) :
+ ndb->getAutoIncrementValue(m_table, g.range, auto_value, cache_size);
+ } while (ret == -1 &&
--retries &&
ndb->getNdbError().status == NdbError::TemporaryError);
- if (auto_value == NDB_FAILED_AUTO_INCREMENT)
+ if (ret == -1)
{
const NdbError err= ndb->getNdbError();
sql_print_error("Error %lu in ::get_auto_increment(): %s",
@@ -5331,7 +5289,6 @@ ha_ndbcluster::ha_ndbcluster(TABLE_SHARE *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_NDBCLUSTER_TABLE_FLAGS),
m_share(0),
@@ -5371,25 +5328,38 @@ ha_ndbcluster::ha_ndbcluster(TABLE_SHARE *table_arg):
records= ~(ha_rows)0; // uninitialized
block_size= 1024;
- clear_indexes();
+ for (i= 0; i < MAX_KEY; i++)
+ ndb_init_index(m_index[i]);
DBUG_VOID_RETURN;
}
+int ha_ndbcluster::ha_initialise()
+{
+ DBUG_ENTER("ha_ndbcluster::ha_initialise");
+ if (check_ndb_in_thd(current_thd))
+ {
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+}
+
/*
Destructor for NDB Cluster table handler
*/
ha_ndbcluster::~ha_ndbcluster()
{
+ THD *thd= current_thd;
+ Ndb *ndb= thd ? check_ndb_in_thd(thd) : g_ndb;
DBUG_ENTER("~ha_ndbcluster");
if (m_share)
{
free_share(&m_share);
}
- release_metadata();
+ release_metadata(thd, ndb);
my_free(m_blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
m_blobs_buffer= 0;
@@ -5504,10 +5474,12 @@ void ha_ndbcluster::set_part_info(partition_info *part_info)
int ha_ndbcluster::close(void)
{
- DBUG_ENTER("close");
+ DBUG_ENTER("close");
+ THD *thd= current_thd;
+ Ndb *ndb= thd ? check_ndb_in_thd(thd) : g_ndb;
free_share(&m_share);
m_share= 0;
- release_metadata();
+ release_metadata(thd, ndb);
DBUG_RETURN(0);
}
@@ -5518,9 +5490,6 @@ Thd_ndb* ha_ndbcluster::seize_thd_ndb()
DBUG_ENTER("seize_thd_ndb");
thd_ndb= new Thd_ndb();
- thd_ndb->ndb->getDictionary()->set_local_table_data_size(
- sizeof(Ndb_local_table_statistics)
- );
if (thd_ndb->ndb->init(max_transactions) != 0)
{
ERR_PRINT(thd_ndb->ndb->getNdbError());
@@ -5598,9 +5567,10 @@ static int ndbcluster_close_connection(THD *thd)
int ndbcluster_discover(THD* thd, const char *db, const char *name,
const void** frmblob, uint* frmlen)
{
+ int error= 0;
+ NdbError ndb_error;
uint len;
const void* data;
- const NDBTAB* tab;
Ndb* ndb;
char key[FN_REFLEN];
DBUG_ENTER("ndbcluster_discover");
@@ -5610,8 +5580,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
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);
build_table_filename(key, sizeof(key), db, name, "");
NDB_SHARE *share= get_share(key, 0, false);
if (share && get_ndb_share_state(share) == NSS_ALTERED)
@@ -5620,21 +5588,22 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
if (readfrm(key, &data, &len))
{
DBUG_PRINT("error", ("Could not read frm"));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
}
else
{
- if (!(tab= dict->getTable(name)))
- {
+ Ndb_table_guard ndbtab_g(dict, name);
+ const NDBTAB *tab= ndbtab_g.get_table();
+ if (!tab)
+ {
const NdbError err= dict->getNdbError();
- if (share)
- free_share(&share);
if (err.code == 709 || err.code == 723)
- DBUG_RETURN(-1);
- ERR_RETURN(err);
+ error= -1;
+ else
+ ndb_error= err;
+ goto err;
}
DBUG_PRINT("info", ("Found table %s", tab->getName()));
@@ -5642,17 +5611,15 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
if (len == 0 || tab->getFrmData() == NULL)
{
DBUG_PRINT("error", ("No frm data found."));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
if (unpackfrm(&data, &len, tab->getFrmData()))
{
DBUG_PRINT("error", ("Could not unpack table"));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
}
@@ -5663,6 +5630,14 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
free_share(&share);
DBUG_RETURN(0);
+err:
+ if (share)
+ free_share(&share);
+ if (ndb_error.code)
+ {
+ ERR_RETURN(ndb_error);
+ }
+ DBUG_RETURN(error);
}
/*
@@ -5670,30 +5645,32 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
*/
-int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name)
+int ndbcluster_table_exists_in_engine(THD* thd, const char *db,
+ const char *name)
{
- const NDBTAB* tab;
Ndb* ndb;
DBUG_ENTER("ndbcluster_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
if (!(ndb= check_ndb_in_thd(thd)))
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)))
+ NdbDictionary::Dictionary::List list;
+ if (dict->listObjects(list, NdbDictionary::Object::UserTable) != 0)
+ ERR_RETURN(dict->getNdbError());
+ for (int i= 0 ; i < list.count ; i++)
{
- const NdbError err= dict->getNdbError();
- if (err.code == 709 || err.code == 723)
- DBUG_RETURN(0);
- ERR_RETURN(err);
+ NdbDictionary::Dictionary::List::Element& elmt= list.elements[i];
+ if (my_strcasecmp(system_charset_info, elmt.database, db))
+ continue;
+ if (my_strcasecmp(system_charset_info, elmt.name, name))
+ continue;
+ // table found
+ DBUG_PRINT("info", ("Found table"));
+ DBUG_RETURN(1);
}
-
- DBUG_PRINT("info", ("Found table %s", tab->getName()));
- DBUG_RETURN(1);
+ DBUG_RETURN(0);
}
@@ -5847,9 +5824,9 @@ int ndbcluster_find_all_files(THD *thd)
}
ndb->setDatabaseName(elmt.database);
- const NDBTAB *ndbtab;
-
- if (!(ndbtab= dict->getTable(elmt.name)))
+ Ndb_table_guard ndbtab_g(dict, elmt.name);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
+ if (!ndbtab)
{
if (retries == 0)
sql_print_error("NDB: failed to setup table %s.%s, error: %d, %s",
@@ -6129,11 +6106,13 @@ static int connect_callback()
return 0;
}
+extern int ndb_dictionary_is_mysqld;
static bool ndbcluster_init()
{
int res;
DBUG_ENTER("ndbcluster_init");
+ ndb_dictionary_is_mysqld= 1;
if (have_ndbcluster != SHOW_OPTION_YES)
goto ndbcluster_init_error;
@@ -6180,7 +6159,6 @@ static bool ndbcluster_init()
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)
{
ERR_PRINT (g_ndb->getNdbError());
@@ -6266,6 +6244,24 @@ static int ndbcluster_end(ha_panic_function type)
if (!ndbcluster_inited)
DBUG_RETURN(0);
+#ifdef HAVE_NDB_BINLOG
+ {
+ pthread_mutex_lock(&ndbcluster_mutex);
+ while (ndbcluster_open_tables.records)
+ {
+ NDB_SHARE *share=
+ (NDB_SHARE*) hash_element(&ndbcluster_open_tables, 0);
+#ifndef DBUG_OFF
+ fprintf(stderr, "NDB: table share %s with use_count %d not freed\n",
+ share->key, share->use_count);
+#endif
+ real_free_share(&share);
+ }
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ }
+#endif
+ hash_free(&ndbcluster_open_tables);
+
if (g_ndb)
{
#ifndef DBUG_OFF
@@ -6287,23 +6283,6 @@ static int ndbcluster_end(ha_panic_function type)
delete g_ndb_cluster_connection;
g_ndb_cluster_connection= NULL;
-#ifdef HAVE_NDB_BINLOG
- {
- pthread_mutex_lock(&ndbcluster_mutex);
- for (uint i= 0; i < ndbcluster_open_tables.records; i++)
- {
- NDB_SHARE *share=
- (NDB_SHARE*) hash_element(&ndbcluster_open_tables, i);
-#ifndef DBUG_OFF
- fprintf(stderr, "NDB: table share %s with use_count %d not freed\n",
- share->key, share->use_count);
-#endif
- real_free_share(&share);
- }
- pthread_mutex_unlock(&ndbcluster_mutex);
- }
-#endif
- hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
pthread_mutex_destroy(&LOCK_ndb_util_thread);
pthread_cond_destroy(&COND_ndb_util_thread);
@@ -6464,7 +6443,7 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
m_index[inx].index_stat != NULL)
{
NDB_INDEX_DATA& d=m_index[inx];
- NDBINDEX* index=(NDBINDEX*)d.index;
+ const NDBINDEX* index= d.index;
Ndb* ndb=get_ndb();
NdbTransaction* trans=NULL;
NdbIndexScanOperation* op=NULL;
@@ -6475,8 +6454,7 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
{
// We must provide approx table rows
Uint64 table_rows=0;
- Ndb_local_table_statistics *info=
- (Ndb_local_table_statistics *)m_table_info;
+ Ndb_local_table_statistics *info= m_table_info;
if (info->records != ~(ha_rows)0 && info->records != 0)
{
table_rows = info->records;
@@ -6485,7 +6463,7 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
else
{
Ndb_statistics stat;
- if ((res=ndb_get_table_statistics(ndb, m_tabname, &stat)) != 0)
+ if ((res=ndb_get_table_statistics(ndb, m_table, &stat)) != 0)
break;
table_rows=stat.row_count;
DBUG_PRINT("info", ("use db row_count: %llu", table_rows));
@@ -6499,7 +6477,8 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
}
// Define scan op for the range
- if ((trans=m_active_trans) == NULL)
+ if ((trans=m_active_trans) == NULL ||
+ trans->commitStatus() != NdbTransaction::Started)
{
DBUG_PRINT("info", ("no active trans"));
if (! (trans=ndb->startTransaction()))
@@ -6646,10 +6625,14 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
pthread_mutex_unlock(&share->mutex);
struct Ndb_statistics stat;
- if (ndb_get_table_statistics(ndb, tabname, &stat))
{
- free_share(&share);
- DBUG_RETURN(1);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), tabname);
+ if (ndbtab_g.get_table() == 0
+ || ndb_get_table_statistics(ndb, ndbtab_g.get_table(), &stat))
+ {
+ free_share(&share);
+ DBUG_RETURN(1);
+ }
}
pthread_mutex_lock(&share->mutex);
@@ -6863,7 +6846,11 @@ int handle_trailing_share(NDB_SHARE *share)
++share->use_count;
pthread_mutex_unlock(&ndbcluster_mutex);
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, TRUE);
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= share->db;
+ table_list.alias= table_list.table_name= share->table_name;
+ close_cached_tables(current_thd, 0, &table_list, TRUE);
pthread_mutex_lock(&ndbcluster_mutex);
if (!--share->use_count)
@@ -7158,10 +7145,6 @@ void ndbcluster_real_free_share(NDB_SHARE **share)
#ifndef DBUG_OFF
bzero((gptr)(*share)->table_share, sizeof(*(*share)->table_share));
bzero((gptr)(*share)->table, sizeof(*(*share)->table));
-#endif
- my_free((gptr) (*share)->table_share, MYF(0));
- my_free((gptr) (*share)->table, MYF(0));
-#ifndef DBUG_OFF
(*share)->table_share= 0;
(*share)->table= 0;
#endif
@@ -7209,17 +7192,32 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock)
static
int
-ndb_get_table_statistics(Ndb* ndb, const char * table,
+ndb_get_table_statistics(Ndb* ndb, const NDBTAB *ndbtab,
struct Ndb_statistics * ndbstat)
{
DBUG_ENTER("ndb_get_table_statistics");
- DBUG_PRINT("enter", ("table: %s", table));
- NdbTransaction* pTrans= ndb->startTransaction();
- if (pTrans == NULL)
- ERR_RETURN(ndb->getNdbError());
- do
+ DBUG_PRINT("enter", ("table: %s", ndbtab->getName()));
+ NdbTransaction* pTrans;
+ int retries= 10;
+ int retry_sleep= 30 * 1000; /* 30 milliseconds */
+
+ DBUG_ASSERT(ndbtab != 0);
+
+ do
{
- NdbScanOperation* pOp= pTrans->getNdbScanOperation(table);
+ pTrans= ndb->startTransaction();
+ if (pTrans == NULL)
+ {
+ if (ndb->getNdbError().status == NdbError::TemporaryError &&
+ retries--)
+ {
+ my_sleep(retry_sleep);
+ continue;
+ }
+ ERR_RETURN(ndb->getNdbError());
+ }
+
+ NdbScanOperation* pOp= pTrans->getNdbScanOperation(ndbtab);
if (pOp == NULL)
break;
@@ -7241,8 +7239,18 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
NdbTransaction::AbortOnError,
TRUE);
if (check == -1)
+ {
+ if (pTrans->getNdbError().status == NdbError::TemporaryError &&
+ retries--)
+ {
+ ndb->closeTransaction(pTrans);
+ pTrans= 0;
+ my_sleep(retry_sleep);
+ continue;
+ }
break;
-
+ }
+
Uint32 count= 0;
Uint64 sum_rows= 0;
Uint64 sum_commits= 0;
@@ -7276,7 +7284,7 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
sum_mem, count));
DBUG_RETURN(0);
- } while (0);
+ } while(1);
if (pTrans)
ndb->closeTransaction(pTrans);
@@ -7370,9 +7378,9 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
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 NDBTAB *tab= m_table;
+ const NDBINDEX *unique_idx= m_index[active_index].unique_index;
+ const NDBINDEX *idx= 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;
@@ -7721,11 +7729,8 @@ ha_ndbcluster::update_table_comment(
ndb->setDatabaseName(m_dbname);
NDBDICT* dict= ndb->getDictionary();
- const NDBTAB* tab;
- if (!(tab= dict->getTable(m_tabname)))
- {
- return((char*)comment);
- }
+ const NDBTAB* tab= m_table;
+ DBUG_ASSERT(tab != NULL);
char *str;
const char *fmt="%s%snumber_of_replicas: %d";
@@ -7911,18 +7916,22 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
lock= share->commit_count_lock;
pthread_mutex_unlock(&share->mutex);
- if (ndb_get_table_statistics(ndb, share->table_name, &stat) == 0)
{
- DBUG_PRINT("ndb_util_thread",
- ("Table: %s, commit_count: %llu, rows: %llu",
- share->key, stat.commit_count, stat.row_count));
- }
- else
- {
- DBUG_PRINT("ndb_util_thread",
- ("Error: Could not get commit count for table %s",
- share->key));
- stat.commit_count= 0;
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), share->table_name);
+ if (ndbtab_g.get_table() &&
+ ndb_get_table_statistics(ndb, ndbtab_g.get_table(), &stat) == 0)
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Table: %s, commit_count: %llu, rows: %llu",
+ share->key, stat.commit_count, stat.row_count));
+ }
+ else
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Error: Could not get commit count for table %s",
+ share->key));
+ stat.commit_count= 0;
+ }
}
pthread_mutex_lock(&share->mutex);
@@ -8895,7 +8904,9 @@ void ndb_serialize_cond(const Item *item, void *arg)
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;
+ context->rewrite_stack= rewrite_context->next;
+ rewrite_context->next= NULL;
+ delete(rewrite_context);
}
}
}
@@ -9312,12 +9323,8 @@ char* ha_ndbcluster::get_tablespace_name(THD *thd)
NdbError ndberr;
Uint32 id;
ndb->setDatabaseName(m_dbname);
- const NDBTAB *ndbtab= ndbdict->getTable(m_tabname);
- if (ndbtab == 0)
- {
- ndberr= ndbdict->getNdbError();
- goto err;
- }
+ const NDBTAB *ndbtab= m_table;
+ DBUG_ASSERT(ndbtab != NULL);
if (!ndbtab->getTablespace(&id))
{
return 0;
@@ -9367,11 +9374,15 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print,
"cluster_node_id=%u, "
"connected_host=%s, "
"connected_port=%u, "
- "number_of_storage_nodes=%u",
+ "number_of_storage_nodes=%u, "
+ "number_of_ready_storage_nodes=%u, "
+ "connect_count=%u",
ndb_cluster_node_id,
ndb_connected_host,
ndb_connected_port,
- ndb_number_of_storage_nodes);
+ ndb_number_of_storage_nodes,
+ ndb_number_of_ready_storage_nodes,
+ ndb_connect_count);
if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name),
"connection", strlen("connection"),
buf, buflen))
@@ -9982,17 +9993,10 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
}
ndb= get_ndb();
ndb->setDatabaseName(m_dbname);
- dict= ndb->getDictionary();
- if (!(tab= dict->getTable(m_tabname)))
+ Ndb_table_guard ndbtab_g(dict= ndb->getDictionary(), m_tabname);
+ if (!ndbtab_g.get_table())
ERR_BREAK(dict->getNdbError(), err);
- // Check if thread has stale local cache
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_BREAK(dict->getNdbError(), err);
- }
- *no_parts= tab->getFragmentCount();
+ *no_parts= ndbtab_g.get_table()->getFragmentCount();
DBUG_RETURN(FALSE);
} while (1);
@@ -10200,3 +10204,20 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond)
}
DBUG_RETURN(0);
}
+
+
+mysql_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_hton,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ ndbcluster_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index b375e30338f..badca69941a 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -70,8 +70,8 @@ typedef enum ndb_index_status {
typedef struct ndb_index_data {
NDB_INDEX_TYPE type;
NDB_INDEX_STATUS status;
- void *index;
- void *unique_index;
+ const NdbDictionary::Index *index;
+ const NdbDictionary::Index *unique_index;
unsigned char *unique_index_attrid_map;
// In this version stats are not shared between threads
NdbIndexStat* index_stat;
@@ -106,6 +106,7 @@ typedef struct st_ndbcluster_share {
ulonglong commit_count;
char *db;
char *table_name;
+ Ndb::TupleIdRange tuple_id_range;
#ifdef HAVE_NDB_BINLOG
uint32 flags;
NdbEventOperation *op;
@@ -113,6 +114,7 @@ typedef struct st_ndbcluster_share {
char *old_names; // for rename table
TABLE_SHARE *table_share;
TABLE *table;
+ byte *record[2]; // pointer to allocated records for receiving data
NdbValue *ndb_value[2];
MY_BITMAP *subscriber_bitmap;
#endif
@@ -138,6 +140,19 @@ set_ndb_share_state(NDB_SHARE *share, NDB_SHARE_STATE state)
pthread_mutex_unlock(&share->mutex);
}
+struct Ndb_tuple_id_range_guard {
+ Ndb_tuple_id_range_guard(NDB_SHARE* _share) :
+ share(_share),
+ range(share->tuple_id_range) {
+ pthread_mutex_lock(&share->mutex);
+ }
+ ~Ndb_tuple_id_range_guard() {
+ pthread_mutex_unlock(&share->mutex);
+ }
+ NDB_SHARE* share;
+ Ndb::TupleIdRange& range;
+};
+
#ifdef HAVE_NDB_BINLOG
/* NDB_SHARE.flags */
#define NSF_HIDDEN_PK 1 /* table has hidden primary key */
@@ -523,11 +538,26 @@ enum THD_NDB_OPTIONS
TNO_NO_LOG_SCHEMA_OP= 1 << 0
};
+struct Ndb_local_table_statistics {
+ int no_uncommitted_rows_count;
+ ulong last_count;
+ ha_rows records;
+};
+
+typedef struct st_thd_ndb_share {
+ const void *key;
+ struct Ndb_local_table_statistics stat;
+} THD_NDB_SHARE;
+
class Thd_ndb
{
public:
Thd_ndb();
~Thd_ndb();
+
+ void init_open_tables();
+ THD_NDB_SHARE *get_open_table(THD *thd, const void *key);
+
Ndb *ndb;
ulong count;
uint lock_count;
@@ -536,6 +566,7 @@ class Thd_ndb
int error;
uint32 options;
List<NDB_SHARE> changed_tables;
+ HASH open_tables;
};
class ha_ndbcluster: public handler
@@ -544,6 +575,7 @@ class ha_ndbcluster: public handler
ha_ndbcluster(TABLE_SHARE *table);
~ha_ndbcluster();
+ int ha_initialise();
int open(const char *name, int mode, uint test_if_locked);
int close(void);
@@ -610,7 +642,8 @@ class ha_ndbcluster: public handler
int rename_table(const char *from, const char *to);
int delete_table(const char *name);
int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
- int create_handler_files(const char *file, HA_CREATE_INFO *info);
+ int create_handler_files(const char *file, const char *old_name,
+ int action_flag, HA_CREATE_INFO *info);
int get_default_no_partitions(ulonglong max_rows);
bool get_no_parts(const char *name, uint *no_parts);
void set_auto_partitions(partition_info *part_info);
@@ -691,31 +724,24 @@ private:
Ndb *ndb, NdbEventOperation *pOp,
NDB_SHARE *share);
- int alter_table_name(const char *to);
static int delete_table(ha_ndbcluster *h, Ndb *ndb,
const char *path,
const char *db,
const char *table_name);
- int drop_ndb_table();
int create_ndb_index(const char *name, KEY *key_info, bool unique);
int create_ordered_index(const char *name, KEY *key_info);
int create_unique_index(const char *name, KEY *key_info);
int create_index(const char *name, KEY *key_info,
NDB_INDEX_TYPE idx_type, uint idx_no);
- int drop_ndb_index(const char *name);
- int table_changed(const void *pack_frm_data, uint pack_frm_len);
// Index list management
int create_indexes(Ndb *ndb, TABLE *tab);
- void clear_index(int i);
- void clear_indexes();
int open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error);
void renumber_indexes(Ndb *ndb, TABLE *tab);
int drop_indexes(Ndb *ndb, TABLE *tab);
int add_index_handle(THD *thd, NdbDictionary::Dictionary *dict,
KEY *key_info, const char *index_name, uint index_no);
- int initialize_autoincrement(const void *table);
int get_metadata(const char* path);
- void release_metadata();
+ void release_metadata(THD *thd, Ndb *ndb);
NDB_INDEX_TYPE get_index_type(uint idx_no) const;
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
NDB_INDEX_TYPE get_index_type_from_key(uint index_no, KEY *key_info,
@@ -778,7 +804,6 @@ private:
void print_results();
ulonglong get_auto_increment();
- int invalidate_dictionary_cache(bool global);
int ndb_err(NdbTransaction*);
bool uses_blob_value();
@@ -792,7 +817,6 @@ private:
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 *);
/*
@@ -816,9 +840,8 @@ private:
NdbTransaction *m_active_trans;
NdbScanOperation *m_active_cursor;
- void *m_table;
- int m_table_version;
- void *m_table_info;
+ const NdbDictionary::Table *m_table;
+ struct Ndb_local_table_statistics *m_table_info;
char m_dbname[FN_HEADLEN];
//char m_schemaname[FN_HEADLEN];
char m_tabname[FN_HEADLEN];
@@ -826,6 +849,7 @@ private:
THR_LOCK_DATA m_lock;
NDB_SHARE *m_share;
NDB_INDEX_DATA m_index[MAX_KEY];
+ THD_NDB_SHARE *m_thd_ndb_share;
// NdbRecAttr has no reference to blob
NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
byte m_ref[NDB_HIDDEN_PRIMARY_KEY_LENGTH];
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index ec5b5858f5c..144c073d565 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -16,6 +16,7 @@
*/
#include "mysql_priv.h"
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
#include "ha_ndbcluster.h"
#ifdef HAVE_NDB_BINLOG
@@ -24,6 +25,7 @@
#include "slave.h"
#include "ha_ndbcluster_binlog.h"
#include "NdbDictionary.hpp"
+#include <util/NdbAutoPtr.hpp>
#ifdef ndb_dynamite
#undef assert
@@ -254,7 +256,7 @@ ndbcluster_binlog_close_table(THD *thd, NDB_SHARE *share)
DBUG_ENTER("ndbcluster_binlog_close_table");
if (share->table_share)
{
- free_table_share(share->table_share);
+ closefrm(share->table, 1);
share->table_share= 0;
share->table= 0;
}
@@ -264,7 +266,8 @@ ndbcluster_binlog_close_table(THD *thd, NDB_SHARE *share)
static int
ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share,
- TABLE_SHARE *table_share, TABLE *table)
+ TABLE_SHARE *table_share, TABLE *table,
+ int reopen)
{
int error;
DBUG_ENTER("ndbcluster_binlog_open_table");
@@ -277,27 +280,34 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share,
share->key, error);
DBUG_PRINT("error", ("open_table_def failed %d", error));
free_table_share(table_share);
- my_free((gptr) table_share, MYF(0));
- my_free((gptr) table, MYF(0));
DBUG_RETURN(error);
}
- if ((error= open_table_from_share(thd, table_share, "", 0,
+ if ((error= open_table_from_share(thd, table_share, "", 0 /* fon't allocate buffers */,
(uint) READ_ALL, 0, table, FALSE)))
{
sql_print_error("Unable to open table for %s, error=%d(%d)",
share->key, error, my_errno);
DBUG_PRINT("error", ("open_table_from_share failed %d", error));
free_table_share(table_share);
- my_free((gptr) table_share, MYF(0));
- my_free((gptr) table, MYF(0));
DBUG_RETURN(error);
}
assign_new_table_id(table_share);
- if (!table->record[1] || table->record[1] == table->record[0])
+
+ if (!reopen)
+ {
+ // allocate memory on ndb share so it can be reused after online alter table
+ share->record[0]= (byte*) alloc_root(&share->mem_root, table->s->rec_buff_length);
+ share->record[1]= (byte*) alloc_root(&share->mem_root, table->s->rec_buff_length);
+ }
{
- table->record[1]= alloc_root(&table->mem_root,
- table->s->rec_buff_length);
+ my_ptrdiff_t row_offset= share->record[0] - table->record[0];
+ Field **p_field;
+ for (p_field= table->field; *p_field; p_field++)
+ (*p_field)->move_field_offset(row_offset);
+ table->record[0]= share->record[0];
+ table->record[1]= share->record[1];
}
+
table->in_use= injector_thd;
table->s->db.str= share->db;
@@ -365,10 +375,9 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table)
while (1)
{
int error;
- TABLE_SHARE *table_share=
- (TABLE_SHARE *) my_malloc(sizeof(*table_share), MYF(MY_WME));
- TABLE *table= (TABLE*) my_malloc(sizeof(*table), MYF(MY_WME));
- if ((error= ndbcluster_binlog_open_table(thd, share, table_share, table)))
+ TABLE_SHARE *table_share= (TABLE_SHARE *) alloc_root(mem_root, sizeof(*table_share));
+ TABLE *table= (TABLE*) alloc_root(mem_root, sizeof(*table));
+ if ((error= ndbcluster_binlog_open_table(thd, share, table_share, table, 0)))
break;
/*
! do not touch the contents of the table
@@ -986,7 +995,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
uint32 ndb_table_id,
uint32 ndb_table_version,
enum SCHEMA_OP_TYPE type,
- const char *old_db, const char *old_table_name)
+ const char *new_db, const char *new_table_name)
{
DBUG_ENTER("ndbcluster_log_schema_op");
Thd_ndb *thd_ndb= get_thd_ndb(thd);
@@ -1026,8 +1035,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
/* redo the rename table query as is may contain several tables */
query= tmp_buf2;
query_length= (uint) (strxmov(tmp_buf2, "rename table `",
- old_db, ".", old_table_name, "` to `",
- db, ".", table_name, "`", NullS) - tmp_buf2);
+ db, ".", table_name, "` to `",
+ new_db, ".", new_table_name, "`", NullS) - tmp_buf2);
type_str= "rename table";
break;
case SOT_CREATE_TABLE:
@@ -1067,21 +1076,30 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
Uint64 epoch= 0;
MY_BITMAP schema_subscribers;
uint32 bitbuf[sizeof(ndb_schema_object->slock)/4];
+ uint32 bitbuf_e[sizeof(bitbuf)];
+ bzero((char *)bitbuf_e, sizeof(bitbuf_e));
{
- int i;
+ int i, updated= 0;
+ int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes();
bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false);
bitmap_set_all(&schema_subscribers);
(void) pthread_mutex_lock(&schema_share->mutex);
- for (i= 0; i < ndb_number_of_storage_nodes; i++)
+ for (i= 0; i < no_storage_nodes; i++)
{
MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i];
if (!bitmap_is_clear_all(table_subscribers))
+ {
bitmap_intersect(&schema_subscribers,
table_subscribers);
+ updated= 1;
+ }
}
(void) pthread_mutex_unlock(&schema_share->mutex);
- bitmap_clear_bit(&schema_subscribers, node_id);
-
+ if (updated)
+ bitmap_clear_bit(&schema_subscribers, node_id);
+ else
+ bitmap_clear_all(&schema_subscribers);
+
if (ndb_schema_object)
{
(void) pthread_mutex_lock(&ndb_schema_object->mutex);
@@ -1103,7 +1121,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
char tmp_buf[FN_REFLEN];
NDBDICT *dict= ndb->getDictionary();
ndb->setDatabaseName(NDB_REP_DB);
- const NDBTAB *ndbtab= dict->getTable(NDB_SCHEMA_TABLE);
+ Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
NdbTransaction *trans= 0;
int retries= 100;
const NDBCOL *col[SCHEMA_SIZE];
@@ -1134,8 +1153,13 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
while (1)
{
+ const char *log_db= db;
+ const char *log_tab= table_name;
+ const char *log_subscribers= (char*)schema_subscribers.bitmap;
+ uint32 log_type= (uint32)type;
if ((trans= ndb->startTransaction()) == 0)
goto err;
+ while (1)
{
NdbOperation *op= 0;
int r= 0;
@@ -1145,17 +1169,17 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
DBUG_ASSERT(r == 0);
/* db */
- ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, db, strlen(db));
+ ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db));
r|= op->equal(SCHEMA_DB_I, tmp_buf);
DBUG_ASSERT(r == 0);
/* name */
- ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, table_name,
- strlen(table_name));
+ ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab,
+ strlen(log_tab));
r|= op->equal(SCHEMA_NAME_I, tmp_buf);
DBUG_ASSERT(r == 0);
/* slock */
DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf));
- r|= op->setValue(SCHEMA_SLOCK_I, (char*)schema_subscribers.bitmap);
+ r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers);
DBUG_ASSERT(r == 0);
/* query */
{
@@ -1179,8 +1203,17 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version);
DBUG_ASSERT(r == 0);
/* type */
- r|= op->setValue(SCHEMA_TYPE_I, (uint32)type);
+ r|= op->setValue(SCHEMA_TYPE_I, log_type);
DBUG_ASSERT(r == 0);
+ if (log_db != new_db && new_db && new_table_name)
+ {
+ log_db= new_db;
+ log_tab= new_table_name;
+ log_subscribers= (const char *)bitbuf_e; // no ack expected on this
+ log_type= (uint32)SOT_RENAME_TABLE_NEW;
+ continue;
+ }
+ break;
}
if (trans->execute(NdbTransaction::Commit) == 0)
{
@@ -1227,13 +1260,14 @@ end:
{
struct timespec abstime;
int i;
+ int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes();
set_timespec(abstime, 1);
int ret= pthread_cond_timedwait(&injector_cond,
&ndb_schema_object->mutex,
&abstime);
(void) pthread_mutex_lock(&schema_share->mutex);
- for (i= 0; i < ndb_number_of_storage_nodes; i++)
+ for (i= 0; i < no_storage_nodes; i++)
{
/* remove any unsubscribed from schema_subscribers */
MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i];
@@ -1298,7 +1332,8 @@ ndbcluster_update_slock(THD *thd,
char tmp_buf[FN_REFLEN];
NDBDICT *dict= ndb->getDictionary();
ndb->setDatabaseName(NDB_REP_DB);
- const NDBTAB *ndbtab= dict->getTable(NDB_SCHEMA_TABLE);
+ Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
NdbTransaction *trans= 0;
int retries= 100;
const NDBCOL *col[SCHEMA_SIZE];
@@ -1431,7 +1466,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
{
DBUG_ENTER("ndb_handle_schema_change");
TABLE* table= share->table;
- TABLE_SHARE *table_share= table->s;
+ TABLE_SHARE *table_share= share->table_share;
const char *dbname= table_share->db.str;
const char *tabname= table_share->table_name.str;
bool do_close_cached_tables= FALSE;
@@ -1444,31 +1479,28 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
{
if (pOp->tableFrmChanged())
{
+ DBUG_PRINT("info", ("NDBEVENT::TE_ALTER: table frm changed"));
is_online_alter_table= TRUE;
}
else
{
+ DBUG_PRINT("info", ("NDBEVENT::TE_ALTER: name changed"));
DBUG_ASSERT(pOp->tableNameChanged());
is_rename_table= TRUE;
}
}
- /*
- Refresh local dictionary cache by
- invalidating table and all it's indexes
- */
- ndb->setDatabaseName(dbname);
- Thd_ndb *thd_ndb= get_thd_ndb(thd);
- DBUG_ASSERT(thd_ndb != NULL);
- Ndb* old_ndb= thd_ndb->ndb;
- thd_ndb->ndb= ndb;
- ha_ndbcluster table_handler(table_share);
- (void)strxmov(table_handler.m_dbname, dbname, NullS);
- (void)strxmov(table_handler.m_tabname, tabname, NullS);
- table_handler.open_indexes(ndb, table, TRUE);
- table_handler.invalidate_dictionary_cache(TRUE);
- thd_ndb->ndb= old_ndb;
-
+ {
+ ndb->setDatabaseName(dbname);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), tabname);
+ const NDBTAB *ev_tab= pOp->getTable();
+ const NDBTAB *cache_tab= ndbtab_g.get_table();
+ if (cache_tab &&
+ cache_tab->getObjectId() == ev_tab->getObjectId() &&
+ cache_tab->getObjectVersion() <= ev_tab->getObjectVersion())
+ ndbtab_g.invalidate();
+ }
+
/*
Refresh local frm file and dictionary cache if
remote on-line alter table
@@ -1497,25 +1529,46 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
DBUG_DUMP("frm", (char*)altered_table->getFrmData(),
altered_table->getFrmLength());
pthread_mutex_lock(&LOCK_open);
- const NDBTAB *old= dict->getTable(tabname);
+ Ndb_table_guard ndbtab_g(dict, tabname);
+ const NDBTAB *old= ndbtab_g.get_table();
if (!old &&
old->getObjectVersion() != altered_table->getObjectVersion())
dict->putTable(altered_table);
+ my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
+ data= NULL;
if ((error= unpackfrm(&data, &length, altered_table->getFrmData())) ||
(error= writefrm(key, data, length)))
{
sql_print_information("NDB: Failed write frm for %s.%s, error %d",
dbname, tabname, error);
}
+
+ // copy names as memory will be freed
+ NdbAutoPtr<char> a1((char *)(dbname= strdup(dbname)));
+ NdbAutoPtr<char> a2((char *)(tabname= strdup(tabname)));
ndbcluster_binlog_close_table(thd, share);
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, TRUE);
- if ((error= ndbcluster_binlog_open_table(thd, share,
- table_share, table)))
+
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= (char *)dbname;
+ table_list.alias= table_list.table_name= (char *)tabname;
+ close_cached_tables(thd, 0, &table_list, TRUE);
+
+ if ((error= ndbcluster_binlog_open_table(thd, share,
+ table_share, table, 1)))
sql_print_information("NDB: Failed to re-open table %s.%s",
dbname, tabname);
+
+ table= share->table;
+ table_share= share->table_share;
+ dbname= table_share->db.str;
+ tabname= table_share->table_name.str;
+
pthread_mutex_unlock(&LOCK_open);
}
+ my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
}
// If only frm was changed continue replicating
@@ -1537,26 +1590,22 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
share_prefix, share->table->s->db.str,
share->table->s->table_name.str,
share->key);
+ {
+ ndb->setDatabaseName(share->table->s->db.str);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(),
+ share->table->s->table_name.str);
+ const NDBTAB *ev_tab= pOp->getTable();
+ const NDBTAB *cache_tab= ndbtab_g.get_table();
+ if (cache_tab &&
+ cache_tab->getObjectId() == ev_tab->getObjectId() &&
+ cache_tab->getObjectVersion() <= ev_tab->getObjectVersion())
+ ndbtab_g.invalidate();
+ }
/* do the rename of the table in the share */
share->table->s->db.str= share->db;
share->table->s->db.length= strlen(share->db);
share->table->s->table_name.str= share->table_name;
share->table->s->table_name.length= strlen(share->table_name);
- /*
- Refresh local dictionary cache by invalidating any
- old table with same name and all it's indexes
- */
- ndb->setDatabaseName(dbname);
- Thd_ndb *thd_ndb= get_thd_ndb(thd);
- DBUG_ASSERT(thd_ndb != NULL);
- Ndb* old_ndb= thd_ndb->ndb;
- thd_ndb->ndb= ndb;
- ha_ndbcluster table_handler(table_share);
- table_handler.set_dbname(share->key);
- table_handler.set_tabname(share->key);
- table_handler.open_indexes(ndb, table, TRUE);
- table_handler.invalidate_dictionary_cache(TRUE);
- thd_ndb->ndb= old_ndb;
}
DBUG_ASSERT(share->op == pOp || share->op_old == pOp);
if (share->op_old == pOp)
@@ -1574,14 +1623,19 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
if (is_remote_change && share && share->state != NSS_DROPPED)
{
DBUG_PRINT("info", ("remote change"));
+ share->state= NSS_DROPPED;
if (share->use_count != 1)
do_close_cached_tables= TRUE;
- share->state= NSS_DROPPED;
- free_share(&share, TRUE);
+ else
+ {
+ free_share(&share, TRUE);
+ share= 0;
+ }
}
+ else
+ share= 0;
pthread_mutex_unlock(&ndbcluster_mutex);
- share= 0;
pOp->setCustomData(0);
pthread_mutex_lock(&injector_mutex);
@@ -1590,7 +1644,14 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
pthread_mutex_unlock(&injector_mutex);
if (do_close_cached_tables)
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0);
+ {
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= (char *)dbname;
+ table_list.alias= table_list.table_name= (char *)tabname;
+ close_cached_tables(thd, 0, &table_list);
+ free_share(&share);
+ }
DBUG_RETURN(0);
}
@@ -1622,60 +1683,39 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
if (schema->node_id != node_id)
{
int log_query= 0, post_epoch_unlock= 0;
- DBUG_PRINT("info", ("log query_length: %d query: '%s'",
- schema->query_length, schema->query));
+ DBUG_PRINT("info",
+ ("%s.%s: log query_length: %d query: '%s' type: %d",
+ schema->db, schema->name,
+ schema->query_length, schema->query,
+ schema->type));
char key[FN_REFLEN];
build_table_filename(key, sizeof(key), schema->db, schema->name, "");
- NDB_SHARE *share= get_share(key, 0, false, false);
switch ((enum SCHEMA_OP_TYPE)schema->type)
{
case SOT_DROP_TABLE:
- /* binlog dropping table after any table operations */
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- }
- /* table is either ignored or logging is postponed to later */
- log_query= 0;
- break;
+ // fall through
case SOT_RENAME_TABLE:
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- break; /* discovery will be handled by binlog */
- }
- goto sot_create_table;
+ // fall through
+ case SOT_RENAME_TABLE_NEW:
+ // fall through
case SOT_ALTER_TABLE:
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- break; /* discovery will be handled by binlog */
- }
- goto sot_create_table;
+ post_epoch_log_list->push_back(schema, mem_root);
+ /* acknowledge this query _after_ epoch completion */
+ post_epoch_unlock= 1;
+ break;
case SOT_CREATE_TABLE:
- sot_create_table:
- /*
- we need to free any share here as command below
- may need to call handle_trailing_share
- */
- if (share)
- {
- free_share(&share);
- share= 0;
- }
pthread_mutex_lock(&LOCK_open);
if (ndb_create_table_from_engine(thd, schema->db, schema->name))
{
- sql_print_error("Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d",
+ sql_print_error("NDB binlog: Could not discover table '%s.%s' from "
+ "binlog schema event '%s' from node %d. "
+ "my_errno: %d",
schema->db, schema->name, schema->query,
- schema->node_id);
+ schema->node_id, my_errno);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ MYSQL_ERROR *err;
+ while ((err= it++))
+ sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg);
}
pthread_mutex_unlock(&LOCK_open);
log_query= 1;
@@ -1686,12 +1726,9 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
TRUE, /* print error */
TRUE); /* don't binlog the query */
/* binlog dropping database after any table operations */
- if (ndb_binlog_running)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- }
+ post_epoch_log_list->push_back(schema, mem_root);
+ /* acknowledge this query _after_ epoch completion */
+ post_epoch_unlock= 1;
break;
case SOT_CREATE_DB:
/* fall through */
@@ -1718,8 +1755,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
pthread_mutex_unlock(&ndb_schema_object->mutex);
pthread_cond_signal(&injector_cond);
}
- if (share)
- free_share(&share, TRUE);
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_RETURN(0);
}
@@ -1728,11 +1763,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
log_query= 1;
break;
}
- if (share)
- {
- free_share(&share);
- share= 0;
- }
if (log_query && ndb_binlog_running)
{
char *thd_db_save= thd->db;
@@ -1763,6 +1793,9 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
// skip
break;
case NDBEVENT::TE_CLUSTER_FAILURE:
+ if (ndb_extra_logging)
+ sql_print_information("NDB Binlog: cluster failure for %s at epoch %u.",
+ schema_share->key, (unsigned) pOp->getGCI());
// fall through
case NDBEVENT::TE_DROP:
if (ndb_extra_logging &&
@@ -1771,7 +1804,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
"read only on reconnect.");
free_share(&schema_share);
schema_share= 0;
- ndb_binlog_tables_inited= FALSE;
+ close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, FALSE);
// fall through
case NDBEVENT::TE_ALTER:
ndb_handle_schema_change(thd, ndb, pOp, tmp_share);
@@ -1856,36 +1889,85 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
List<Cluster_schema>
*post_epoch_unlock_list)
{
+ if (post_epoch_log_list->elements == 0)
+ return;
DBUG_ENTER("ndb_binlog_thread_handle_schema_event_post_epoch");
Cluster_schema *schema;
while ((schema= post_epoch_log_list->pop()))
{
- DBUG_PRINT("info", ("log query_length: %d query: '%s'",
- schema->query_length, schema->query));
+ DBUG_PRINT("info",
+ ("%s.%s: log query_length: %d query: '%s' type: %d",
+ schema->db, schema->name,
+ schema->query_length, schema->query,
+ schema->type));
+ int log_query= 0;
{
char key[FN_REFLEN];
build_table_filename(key, sizeof(key), schema->db, schema->name, "");
NDB_SHARE *share= get_share(key, 0, false, false);
- switch ((enum SCHEMA_OP_TYPE)schema->type)
+ enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type;
+ switch (schema_type)
{
case SOT_DROP_DB:
- case SOT_DROP_TABLE:
+ log_query= 1;
break;
+ case SOT_DROP_TABLE:
+ // invalidation already handled by binlog thread
+ if (share && share->op)
+ {
+ log_query= 1;
+ break;
+ }
+ // fall through
case SOT_RENAME_TABLE:
+ // fall through
case SOT_ALTER_TABLE:
- if (share && share->op)
+ // invalidation already handled by binlog thread
+ if (!share || !share->op)
{
- break; /* discovery handled by binlog */
+ {
+ injector_ndb->setDatabaseName(schema->db);
+ Ndb_table_guard ndbtab_g(injector_ndb->getDictionary(),
+ schema->name);
+ ndbtab_g.invalidate();
+ }
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= schema->db;
+ table_list.alias= table_list.table_name= schema->name;
+ close_cached_tables(thd, 0, &table_list, FALSE);
}
- pthread_mutex_lock(&LOCK_open);
- if (ndb_create_table_from_engine(thd, schema->db, schema->name))
+ if (schema_type != SOT_ALTER_TABLE)
+ break;
+ // fall through
+ case SOT_RENAME_TABLE_NEW:
+ log_query= 1;
+ if (ndb_binlog_running && (!share || !share->op))
{
- sql_print_error("Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d",
- schema->db, schema->name, schema->query,
- schema->node_id);
+ /*
+ we need to free any share here as command below
+ may need to call handle_trailing_share
+ */
+ if (share)
+ {
+ free_share(&share);
+ share= 0;
+ }
+ pthread_mutex_lock(&LOCK_open);
+ if (ndb_create_table_from_engine(thd, schema->db, schema->name))
+ {
+ sql_print_error("NDB binlog: Could not discover table '%s.%s' from "
+ "binlog schema event '%s' from node %d. my_errno: %d",
+ schema->db, schema->name, schema->query,
+ schema->node_id, my_errno);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ MYSQL_ERROR *err;
+ while ((err= it++))
+ sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg);
+ }
+ pthread_mutex_unlock(&LOCK_open);
}
- pthread_mutex_unlock(&LOCK_open);
+ break;
default:
DBUG_ASSERT(false);
}
@@ -1895,6 +1977,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
share= 0;
}
}
+ if (ndb_binlog_running && log_query)
{
char *thd_db_save= thd->db;
thd->db= schema->db;
@@ -2039,7 +2122,14 @@ add_binlog_index_err:
Functions for start, stop, wait for ndbcluster binlog thread
*********************************************************************/
-static int do_ndbcluster_binlog_close_connection= 0;
+enum Binlog_thread_state
+{
+ BCCC_running= 0,
+ BCCC_exit= 1,
+ BCCC_restart= 2
+};
+
+static enum Binlog_thread_state do_ndbcluster_binlog_close_connection= BCCC_restart;
int ndbcluster_binlog_start()
{
@@ -2077,7 +2167,7 @@ static void ndbcluster_binlog_close_connection(THD *thd)
DBUG_ENTER("ndbcluster_binlog_close_connection");
const char *save_info= thd->proc_info;
thd->proc_info= "ndbcluster_binlog_close_connection";
- do_ndbcluster_binlog_close_connection= 1;
+ do_ndbcluster_binlog_close_connection= BCCC_exit;
while (ndb_binlog_thread_running > 0)
sleep(1);
thd->proc_info= save_info;
@@ -2178,7 +2268,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
ndb->setDatabaseName(db);
NDBDICT *dict= ndb->getDictionary();
- const NDBTAB *ndbtab= dict->getTable(table_name);
+ Ndb_table_guard ndbtab_g(dict, table_name);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
if (ndbtab == 0)
{
if (ndb_extra_logging)
@@ -2193,7 +2284,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
event should have been created by someone else,
but let's make sure, and create if it doesn't exist
*/
- if (!dict->getEvent(event_name.c_ptr()))
+ const NDBEVENT *ev= dict->getEvent(event_name.c_ptr());
+ if (!ev)
{
if (ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share))
{
@@ -2208,9 +2300,12 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
event_name.c_ptr());
}
else
+ {
+ delete ev;
if (ndb_extra_logging)
sql_print_information("NDB Binlog: DISCOVER TABLE Event: %s",
event_name.c_ptr());
+ }
/*
create the event operations for receiving logging events
@@ -2320,8 +2415,10 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
try retrieving the event, if table version/id matches, we will get
a valid event. Otherwise we have a trailing event from before
*/
- if (dict->getEvent(event_name))
+ const NDBEVENT *ev;
+ if ((ev= dict->getEvent(event_name)))
{
+ delete ev;
DBUG_RETURN(0);
}
@@ -2411,7 +2508,14 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
DBUG_RETURN(0);
}
- if (!binlog_filter->db_ok(share->db))
+ int do_schema_share= 0, do_apply_status_share= 0;
+ if (!schema_share && strcmp(share->db, NDB_REP_DB) == 0 &&
+ strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
+ do_schema_share= 1;
+ else if (!apply_status_share && strcmp(share->db, NDB_REP_DB) == 0 &&
+ strcmp(share->table_name, NDB_APPLY_TABLE) == 0)
+ do_apply_status_share= 1;
+ else if (!binlog_filter->db_ok(share->db))
{
share->flags|= NSF_NO_BINLOG;
DBUG_RETURN(0);
@@ -2429,15 +2533,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
TABLE *table= share->table;
- int do_schema_share= 0, do_apply_status_share= 0;
int retries= 100;
- if (!schema_share && strcmp(share->db, NDB_REP_DB) == 0 &&
- strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
- do_schema_share= 1;
- else if (!apply_status_share && strcmp(share->db, NDB_REP_DB) == 0 &&
- strcmp(share->table_name, NDB_APPLY_TABLE) == 0)
- do_apply_status_share= 1;
-
while (1)
{
pthread_mutex_lock(&injector_mutex);
@@ -2751,7 +2847,8 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb,
{
case NDBEVENT::TE_CLUSTER_FAILURE:
if (ndb_extra_logging)
- sql_print_information("NDB Binlog: cluster failure for %s.", share->key);
+ sql_print_information("NDB Binlog: cluster failure for %s at epoch %u.",
+ share->key, (unsigned) pOp->getGCI());
if (apply_status_share == share)
{
if (ndb_extra_logging &&
@@ -2760,7 +2857,6 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb,
"read only on reconnect.");
free_share(&apply_status_share);
apply_status_share= 0;
- ndb_binlog_tables_inited= FALSE;
}
DBUG_PRINT("info", ("CLUSTER FAILURE EVENT: "
"%s received share: 0x%lx op: %lx share op: %lx "
@@ -2776,7 +2872,6 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb,
"read only on reconnect.");
free_share(&apply_status_share);
apply_status_share= 0;
- ndb_binlog_tables_inited= FALSE;
}
/* ToDo: remove printout */
if (ndb_extra_logging)
@@ -3087,6 +3182,9 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
Thd_ndb *thd_ndb=0;
int ndb_update_binlog_index= 1;
injector *inj= injector::instance();
+#ifdef RUN_NDB_BINLOG_TIMER
+ Timer main_timer;
+#endif
pthread_mutex_lock(&injector_mutex);
/*
@@ -3186,36 +3284,73 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
pthread_mutex_unlock(&injector_mutex);
pthread_cond_signal(&injector_cond);
- thd->proc_info= "Waiting for ndbcluster to start";
-
- pthread_mutex_lock(&injector_mutex);
- while (!schema_share || !apply_status_share)
+restart:
+ /*
+ Main NDB Injector loop
+ */
{
- /* ndb not connected yet */
- struct timespec abstime;
- set_timespec(abstime, 1);
- pthread_cond_timedwait(&injector_cond, &injector_mutex, &abstime);
- if (abort_loop)
+ thd->proc_info= "Waiting for ndbcluster to start";
+
+ pthread_mutex_lock(&injector_mutex);
+ while (!schema_share ||
+ (ndb_binlog_running && !apply_status_share))
{
- pthread_mutex_unlock(&injector_mutex);
- goto err;
+ /* ndb not connected yet */
+ struct timespec abstime;
+ set_timespec(abstime, 1);
+ pthread_cond_timedwait(&injector_cond, &injector_mutex, &abstime);
+ if (abort_loop)
+ {
+ pthread_mutex_unlock(&injector_mutex);
+ goto err;
+ }
}
- }
- pthread_mutex_unlock(&injector_mutex);
+ pthread_mutex_unlock(&injector_mutex);
- /*
- Main NDB Injector loop
- */
+ if (thd_ndb == NULL)
+ {
+ DBUG_ASSERT(ndbcluster_hton.slot != ~(uint)0);
+ if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
+ {
+ sql_print_error("Could not allocate Thd_ndb object");
+ goto err;
+ }
+ set_thd_ndb(thd, thd_ndb);
+ thd_ndb->options|= TNO_NO_LOG_SCHEMA_OP;
+ thd->query_id= 0; // to keep valgrind quiet
+ }
+ }
- DBUG_ASSERT(ndbcluster_hton.slot != ~(uint)0);
- if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
{
- sql_print_error("Could not allocate Thd_ndb object");
- goto err;
+ // wait for the first event
+ thd->proc_info= "Waiting for first event from ndbcluster";
+ DBUG_PRINT("info", ("Waiting for the first event"));
+ int schema_res= 0;
+ Uint64 schema_gci= 0;
+ while (schema_res == 0 && !abort_loop)
+ {
+ schema_res= s_ndb->pollEvents(100, &schema_gci);
+ }
+ // now check that we have epochs consistant with what we had before the restart
+ DBUG_PRINT("info", ("schema_res: %d schema_gci: %d", schema_res, schema_gci));
+ if (schema_res > 0)
+ {
+ i_ndb->pollEvents(0);
+ i_ndb->flushIncompleteEvents(schema_gci);
+ s_ndb->flushIncompleteEvents(schema_gci);
+ if (schema_gci < ndb_latest_handled_binlog_epoch)
+ {
+ sql_print_error("NDB Binlog: cluster has been restarted --initial or with older filesystem. "
+ "ndb_latest_handled_binlog_epoch: %u, while current epoch: %u. "
+ "RESET MASTER should be issued. Resetting ndb_latest_handled_binlog_epoch.",
+ (unsigned) ndb_latest_handled_binlog_epoch, (unsigned) schema_gci);
+ g_latest_trans_gci= 0;
+ ndb_latest_handled_binlog_epoch= 0;
+ ndb_latest_applied_binlog_epoch= 0;
+ ndb_latest_received_binlog_epoch= 0;
+ }
+ }
}
- set_thd_ndb(thd, thd_ndb);
- thd_ndb->options|= TNO_NO_LOG_SCHEMA_OP;
- thd->query_id= 0; // to keep valgrind quiet
{
static char db[]= "";
thd->db= db;
@@ -3223,14 +3358,20 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
open_binlog_index(thd, &binlog_tables, &binlog_index);
thd->db= db;
}
-
-#ifdef RUN_NDB_BINLOG_TIMER
- Timer main_timer;
-#endif
+ do_ndbcluster_binlog_close_connection= BCCC_running;
for ( ; !((abort_loop || do_ndbcluster_binlog_close_connection) &&
- ndb_latest_handled_binlog_epoch >= g_latest_trans_gci); )
+ ndb_latest_handled_binlog_epoch >= g_latest_trans_gci) &&
+ do_ndbcluster_binlog_close_connection != BCCC_restart; )
{
-
+#ifndef DBUG_OFF
+ if (do_ndbcluster_binlog_close_connection)
+ {
+ DBUG_PRINT("info", ("do_ndbcluster_binlog_close_connection: %d, "
+ "ndb_latest_handled_binlog_epoch: %llu, "
+ "g_latest_trans_gci: %llu", do_ndbcluster_binlog_close_connection,
+ ndb_latest_handled_binlog_epoch, g_latest_trans_gci));
+ }
+#endif
#ifdef RUN_NDB_BINLOG_TIMER
main_timer.stop();
sql_print_information("main_timer %ld ms", main_timer.elapsed_ms());
@@ -3255,7 +3396,13 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
ndb_latest_received_binlog_epoch= gci;
while (gci > schema_gci && schema_res >= 0)
+ {
+ static char buf[64];
+ thd->proc_info= "Waiting for schema epoch";
+ my_snprintf(buf, sizeof(buf), "%s %u(%u)", thd->proc_info, (unsigned) schema_gci, (unsigned) gci);
+ thd->proc_info= buf;
schema_res= s_ndb->pollEvents(10, &schema_gci);
+ }
if ((abort_loop || do_ndbcluster_binlog_close_connection) &&
(ndb_latest_handled_binlog_epoch >= g_latest_trans_gci ||
@@ -3291,10 +3438,31 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
while (pOp != NULL)
{
if (!pOp->hasError())
+ {
ndb_binlog_thread_handle_schema_event(thd, s_ndb, pOp,
&post_epoch_log_list,
&post_epoch_unlock_list,
&mem_root);
+ DBUG_PRINT("info", ("s_ndb first: %s", s_ndb->getEventOperation() ?
+ s_ndb->getEventOperation()->getEvent()->getTable()->getName() :
+ "<empty>"));
+ DBUG_PRINT("info", ("i_ndb first: %s", i_ndb->getEventOperation() ?
+ i_ndb->getEventOperation()->getEvent()->getTable()->getName() :
+ "<empty>"));
+ if (i_ndb->getEventOperation() == NULL &&
+ s_ndb->getEventOperation() == NULL &&
+ do_ndbcluster_binlog_close_connection == BCCC_running)
+ {
+ DBUG_PRINT("info", ("do_ndbcluster_binlog_close_connection= BCCC_restart"));
+ do_ndbcluster_binlog_close_connection= BCCC_restart;
+ if (ndb_latest_received_binlog_epoch < g_latest_trans_gci && ndb_binlog_running)
+ {
+ sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog "
+ "as latest received epoch is %lld",
+ g_latest_trans_gci, ndb_latest_received_binlog_epoch);
+ }
+ }
+ }
else
sql_print_error("NDB: error %lu (%s) on handling "
"binlog schema event",
@@ -3307,15 +3475,16 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
if (res > 0)
{
DBUG_PRINT("info", ("pollEvents res: %d", res));
-#ifdef RUN_NDB_BINLOG_TIMER
- Timer gci_timer, write_timer;
- int event_count= 0;
-#endif
thd->proc_info= "Processing events";
NdbEventOperation *pOp= i_ndb->nextEvent();
Binlog_index_row row;
while (pOp != NULL)
{
+#ifdef RUN_NDB_BINLOG_TIMER
+ Timer gci_timer, write_timer;
+ int event_count= 0;
+ gci_timer.start();
+#endif
gci= pOp->getGCI();
DBUG_PRINT("info", ("Handling gci: %d", (unsigned)gci));
// sometimes get TE_ALTER with invalid table
@@ -3462,6 +3631,25 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
ndb_binlog_thread_handle_non_data_event(thd, i_ndb, pOp, row);
// reset to catch errors
i_ndb->setDatabaseName("");
+ DBUG_PRINT("info", ("s_ndb first: %s", s_ndb->getEventOperation() ?
+ s_ndb->getEventOperation()->getEvent()->getTable()->getName() :
+ "<empty>"));
+ DBUG_PRINT("info", ("i_ndb first: %s", i_ndb->getEventOperation() ?
+ i_ndb->getEventOperation()->getEvent()->getTable()->getName() :
+ "<empty>"));
+ if (i_ndb->getEventOperation() == NULL &&
+ s_ndb->getEventOperation() == NULL &&
+ do_ndbcluster_binlog_close_connection == BCCC_running)
+ {
+ DBUG_PRINT("info", ("do_ndbcluster_binlog_close_connection= BCCC_restart"));
+ do_ndbcluster_binlog_close_connection= BCCC_restart;
+ if (ndb_latest_received_binlog_epoch < g_latest_trans_gci && ndb_binlog_running)
+ {
+ sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog "
+ "as latest received epoch is %lld",
+ g_latest_trans_gci, ndb_latest_received_binlog_epoch);
+ }
+ }
}
pOp= i_ndb->nextEvent();
@@ -3494,6 +3682,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
DBUG_PRINT("info", ("COMMIT gci: %lld", gci));
if (ndb_update_binlog_index)
ndb_add_binlog_index(thd, &row);
+ ndb_latest_applied_binlog_epoch= gci;
}
ndb_latest_handled_binlog_epoch= gci;
#ifdef RUN_NDB_BINLOG_TIMER
@@ -3516,6 +3705,13 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
*root_ptr= old_root;
ndb_latest_handled_binlog_epoch= ndb_latest_received_binlog_epoch;
}
+ if (do_ndbcluster_binlog_close_connection == BCCC_restart)
+ {
+ ndb_binlog_tables_inited= FALSE;
+ close_thread_tables(thd);
+ binlog_index= 0;
+ goto restart;
+ }
err:
DBUG_PRINT("info",("Shutting down cluster binlog thread"));
thd->proc_info= "Shutting down";
@@ -3637,3 +3833,4 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print,
}
#endif /* HAVE_NDB_BINLOG */
+#endif
diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h
index 9d15016568b..d82cdccb1b9 100644
--- a/sql/ha_ndbcluster_binlog.h
+++ b/sql/ha_ndbcluster_binlog.h
@@ -41,14 +41,15 @@ enum SCHEMA_OP_TYPE
{
SOT_DROP_TABLE= 0,
SOT_CREATE_TABLE= 1,
- SOT_RENAME_TABLE= 2,
+ SOT_RENAME_TABLE_NEW= 2,
SOT_ALTER_TABLE= 3,
SOT_DROP_DB= 4,
SOT_CREATE_DB= 5,
SOT_ALTER_DB= 6,
SOT_CLEAR_SLOCK= 7,
SOT_TABLESPACE= 8,
- SOT_LOGFILE_GROUP= 9
+ SOT_LOGFILE_GROUP= 9,
+ SOT_RENAME_TABLE= 10
};
const uint max_ndb_nodes= 64; /* multiple of 32 */
@@ -56,6 +57,45 @@ const uint max_ndb_nodes= 64; /* multiple of 32 */
static const char *ha_ndb_ext=".ndb";
static const char share_prefix[]= "./";
+class Ndb_table_guard
+{
+public:
+ Ndb_table_guard(NDBDICT *dict, const char *tabname)
+ : m_dict(dict)
+ {
+ DBUG_ENTER("Ndb_table_guard");
+ m_ndbtab= m_dict->getTableGlobal(tabname);
+ m_invalidate= 0;
+ DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+ DBUG_VOID_RETURN;
+ }
+ ~Ndb_table_guard()
+ {
+ DBUG_ENTER("~Ndb_table_guard");
+ if (m_ndbtab)
+ {
+ DBUG_PRINT("info", ("m_ndbtab: %p m_invalidate: %d",
+ m_ndbtab, m_invalidate));
+ m_dict->removeTableGlobal(*m_ndbtab, m_invalidate);
+ }
+ DBUG_VOID_RETURN;
+ }
+ const NDBTAB *get_table() { return m_ndbtab; }
+ void invalidate() { m_invalidate= 1; }
+ const NDBTAB *release()
+ {
+ DBUG_ENTER("Ndb_table_guard::release");
+ const NDBTAB *tmp= m_ndbtab;
+ DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+ m_ndbtab = 0;
+ DBUG_RETURN(tmp);
+ }
+private:
+ const NDBTAB *m_ndbtab;
+ NDBDICT *m_dict;
+ int m_invalidate;
+};
+
#ifdef HAVE_NDB_BINLOG
extern pthread_t ndb_binlog_thread;
extern pthread_mutex_t injector_mutex;
@@ -98,8 +138,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
uint32 ndb_table_id,
uint32 ndb_table_version,
enum SCHEMA_OP_TYPE type,
- const char *old_db= 0,
- const char *old_table_name= 0);
+ const char *new_db= 0,
+ const char *new_table_name= 0);
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
NDB_SHARE *share,
const char *type_str);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 3ee9a2954eb..af0556f1e6f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -54,8 +54,11 @@
#include "mysql_priv.h"
+#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
+#include <mysql/plugin.h>
+
static const char *ha_par_ext= ".par";
#ifdef NOT_USED
static int free_share(PARTITION_SHARE * share);
@@ -70,11 +73,14 @@ static handler *partition_create_handler(TABLE_SHARE *share);
static uint partition_flags();
static uint alter_table_flags(uint flags);
+static const char partition_hton_name[]= "partition";
+static const char partition_hton_comment[]= "Partition Storage Engine Helper";
+
handlerton partition_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "partition",
+ partition_hton_name,
SHOW_OPTION_YES,
- "Partition Storage Engine Helper", /* A comment used by SHOW to describe an engine */
+ partition_hton_comment, /* A comment used by SHOW to describe an engine */
DB_TYPE_PARTITION_DB,
0, /* Method that initializes a storage engine */
0, /* slot */
@@ -404,88 +410,6 @@ int ha_partition::ha_initialise()
MODULE meta data changes
****************************************************************************/
/*
- Create partition names
-
- SYNOPSIS
- create_partition_name()
- out:out Created partition name string
- in1 First part
- in2 Second part
- name_variant Normal, temporary or renamed partition name
-
- RETURN VALUE
- NONE
-
- DESCRIPTION
- This method is used to calculate the partition name, service routine to
- the del_ren_cre_table method.
-*/
-
-#define NORMAL_PART_NAME 0
-#define TEMP_PART_NAME 1
-#define RENAMED_PART_NAME 2
-static void create_partition_name(char *out, const char *in1,
- const char *in2, uint name_variant,
- bool translate)
-{
- char transl_part_name[FN_REFLEN];
- const char *transl_part;
-
- if (translate)
- {
- tablename_to_filename(in2, transl_part_name, FN_REFLEN);
- transl_part= transl_part_name;
- }
- else
- transl_part= in2;
- if (name_variant == NORMAL_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, NullS);
- else if (name_variant == TEMP_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS);
- else if (name_variant == RENAMED_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, "#REN#", NullS);
-}
-
-/*
- Create subpartition name
-
- SYNOPSIS
- create_subpartition_name()
- out:out Created partition name string
- in1 First part
- in2 Second part
- in3 Third part
- name_variant Normal, temporary or renamed partition name
-
- RETURN VALUE
- NONE
-
- DESCRIPTION
- This method is used to calculate the subpartition name, service routine to
- the del_ren_cre_table method.
-*/
-
-static void create_subpartition_name(char *out, const char *in1,
- const char *in2, const char *in3,
- uint name_variant)
-{
- char transl_part_name[FN_REFLEN], transl_subpart_name[FN_REFLEN];
-
- tablename_to_filename(in2, transl_part_name, FN_REFLEN);
- tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
- if (name_variant == NORMAL_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
- "#SP#", transl_subpart_name, NullS);
- else if (name_variant == TEMP_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
- "#SP#", transl_subpart_name, "#TMP#", NullS);
- else if (name_variant == RENAMED_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
- "#SP#", transl_subpart_name, "#REN#", NullS);
-}
-
-
-/*
Delete a table
SYNOPSIS
@@ -576,7 +500,9 @@ int ha_partition::rename_table(const char *from, const char *to)
and types of engines in the partitions.
*/
-int ha_partition::create_handler_files(const char *name,
+int ha_partition::create_handler_files(const char *path,
+ const char *old_path,
+ int action_flag,
HA_CREATE_INFO *create_info)
{
DBUG_ENTER("ha_partition::create_handler_files()");
@@ -585,10 +511,29 @@ int ha_partition::create_handler_files(const char *name,
We need to update total number of parts since we might write the handler
file as part of a partition management command
*/
- if (create_handler_file(name))
+ if (action_flag == CHF_DELETE_FLAG ||
+ action_flag == CHF_RENAME_FLAG)
{
- my_error(ER_CANT_CREATE_HANDLER_FILE, MYF(0));
- DBUG_RETURN(1);
+ char name[FN_REFLEN];
+ char old_name[FN_REFLEN];
+
+ strxmov(name, path, ha_par_ext, NullS);
+ strxmov(old_name, old_path, ha_par_ext, NullS);
+ if ((action_flag == CHF_DELETE_FLAG &&
+ my_delete(name, MYF(MY_WME))) ||
+ (action_flag == CHF_RENAME_FLAG &&
+ my_rename(old_name, name, MYF(MY_WME))))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else if (action_flag == CHF_CREATE_FLAG)
+ {
+ if (create_handler_file(path))
+ {
+ my_error(ER_CANT_CREATE_HANDLER_FILE, MYF(0));
+ DBUG_RETURN(1);
+ }
}
DBUG_RETURN(0);
}
@@ -654,45 +599,26 @@ int ha_partition::create(const char *name, TABLE *table_arg,
int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
- List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
uint no_parts= m_part_info->partitions.elements;
uint part_count= 0;
uint no_subparts= m_part_info->no_subparts;
uint i= 0;
uint name_variant;
- int error= 1;
- bool reorged_parts= (m_reorged_parts > 0);
- bool temp_partitions= (m_part_info->temp_partitions.elements > 0);
+ int ret_error;
+ int error= 0;
DBUG_ENTER("ha_partition::drop_partitions");
- if (temp_partitions)
- no_parts= m_part_info->temp_partitions.elements;
do
{
- partition_element *part_elem;
- if (temp_partitions)
- {
- /*
- We need to remove the reorganised partitions that were put in the
- temp_partitions-list.
- */
- part_elem= temp_it++;
- DBUG_ASSERT(part_elem->part_state == PART_TO_BE_DROPPED);
- }
- else
- part_elem= part_it++;
- if (part_elem->part_state == PART_TO_BE_DROPPED ||
- part_elem->part_state == PART_IS_CHANGED)
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_TO_BE_DROPPED)
{
handler *file;
/*
This part is to be dropped, meaning the part or all its subparts.
*/
name_variant= NORMAL_PART_NAME;
- if (part_elem->part_state == PART_IS_CHANGED ||
- (part_elem->part_state == PART_TO_BE_DROPPED && temp_partitions))
- name_variant= RENAMED_PART_NAME;
if (m_is_sub_partitioned)
{
List_iterator<partition_element> sub_it(part_elem->subpartitions);
@@ -704,12 +630,10 @@ int ha_partition::drop_partitions(const char *path)
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name, name_variant);
- if (reorged_parts)
- file= m_reorged_file[part_count++];
- else
- file= m_file[part];
+ file= m_file[part];
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
- error= file->delete_table((const char *) part_name_buff);
+ if ((ret_error= file->delete_table((const char *) part_name_buff)))
+ error= ret_error;
} while (++j < no_subparts);
}
else
@@ -717,12 +641,10 @@ int ha_partition::drop_partitions(const char *path)
create_partition_name(part_name_buff, path,
part_elem->partition_name, name_variant,
TRUE);
- if (reorged_parts)
- file= m_reorged_file[part_count++];
- else
- file= m_file[i];
+ file= m_file[i];
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
- error= file->delete_table((const char *) part_name_buff);
+ if ((ret_error= file->delete_table((const char *) part_name_buff)))
+ error= ret_error;
}
if (part_elem->part_state == PART_IS_CHANGED)
part_elem->part_state= PART_NORMAL;
@@ -764,7 +686,8 @@ int ha_partition::rename_partitions(const char *path)
uint no_subparts= m_part_info->no_subparts;
uint i= 0;
uint j= 0;
- int error= 1;
+ int error= 0;
+ int ret_error;
uint temp_partitions= m_part_info->temp_partitions.elements;
handler *file;
partition_element *part_elem, *sub_elem;
@@ -772,6 +695,14 @@ int ha_partition::rename_partitions(const char *path)
if (temp_partitions)
{
+ /*
+ These are the reorganised partitions that have already been copied.
+ We delete the partitions and log the delete by inactivating the
+ delete log entry in the table log. We only need to synchronise
+ these writes before moving to the next loop since there is no
+ interaction among reorganised partitions, they cannot have the
+ same name.
+ */
do
{
part_elem= temp_it++;
@@ -782,39 +713,59 @@ int ha_partition::rename_partitions(const char *path)
{
sub_elem= sub_it++;
file= m_reorged_file[part_count++];
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- RENAMED_PART_NAME);
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
NORMAL_PART_NAME);
- DBUG_PRINT("info", ("Rename subpartition from %s to %s",
- norm_name_buff, part_name_buff));
- error= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
+ if ((ret_error= file->delete_table((const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ sub_elem->log_entry= NULL; /* Indicate success */
} while (++j < no_subparts);
}
else
{
file= m_reorged_file[part_count++];
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, RENAMED_PART_NAME,
- TRUE);
create_partition_name(norm_name_buff, path,
part_elem->partition_name, NORMAL_PART_NAME,
TRUE);
- DBUG_PRINT("info", ("Rename partition from %s to %s",
- norm_name_buff, part_name_buff));
- error= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
+ if ((ret_error= file->delete_table((const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ part_elem->log_entry= NULL; /* Indicate success */
}
} while (++i < temp_partitions);
+ VOID(sync_ddl_log());
}
i= 0;
do
{
+ /*
+ When state is PART_IS_CHANGED it means that we have created a new
+ TEMP partition that is to be renamed to normal partition name and
+ we are to delete the old partition with currently the normal name.
+
+ We perform this operation by
+ 1) Delete old partition with normal partition name
+ 2) Signal this in table log entry
+ 3) Synch table log to ensure we have consistency in crashes
+ 4) Rename temporary partition name to normal partition name
+ 5) Signal this to table log entry
+ It is not necessary to synch the last state since a new rename
+ should not corrupt things if there was no temporary partition.
+
+ The only other parts we need to cater for are new parts that
+ replace reorganised parts. The reorganised parts were deleted
+ by the code above that goes through the temp_partitions list.
+ Thus the synch above makes it safe to simply perform step 4 and 5
+ for those entries.
+ */
part_elem= part_it++;
if (part_elem->part_state == PART_IS_CHANGED ||
(part_elem->part_state == PART_IS_ADDED && temp_partitions))
@@ -836,14 +787,12 @@ int ha_partition::rename_partitions(const char *path)
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- RENAMED_PART_NAME);
- DBUG_PRINT("info", ("Rename subpartition from %s to %s",
- norm_name_buff, part_name_buff));
- error= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
+ if ((ret_error= file->delete_table((const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ VOID(sync_ddl_log());
}
file= m_new_file[part];
create_subpartition_name(part_name_buff, path,
@@ -852,8 +801,13 @@ int ha_partition::rename_partitions(const char *path)
TEMP_PART_NAME);
DBUG_PRINT("info", ("Rename subpartition from %s to %s",
part_name_buff, norm_name_buff));
- error= file->rename_table((const char *) part_name_buff,
- (const char *) norm_name_buff);
+ if ((ret_error= file->rename_table((const char *) part_name_buff,
+ (const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ sub_elem->log_entry= NULL;
} while (++j < no_subparts);
}
else
@@ -864,13 +818,12 @@ int ha_partition::rename_partitions(const char *path)
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, RENAMED_PART_NAME,
- TRUE);
- DBUG_PRINT("info", ("Rename partition from %s to %s",
- norm_name_buff, part_name_buff));
- error= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
+ if ((ret_error= file->delete_table((const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
+ error= 1;
+ VOID(sync_ddl_log());
}
file= m_new_file[i];
create_partition_name(part_name_buff, path,
@@ -878,11 +831,17 @@ int ha_partition::rename_partitions(const char *path)
TRUE);
DBUG_PRINT("info", ("Rename partition from %s to %s",
part_name_buff, norm_name_buff));
- error= file->rename_table((const char *) part_name_buff,
- (const char *) norm_name_buff);
+ if ((ret_error= file->rename_table((const char *) part_name_buff,
+ (const char *) norm_name_buff)))
+ error= ret_error;
+ else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ part_elem->log_entry= NULL;
}
}
} while (++i < no_parts);
+ VOID(sync_ddl_log());
DBUG_RETURN(error);
}
@@ -1149,8 +1108,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
part));
if ((error= handle_opt_part(thd, check_opt, m_file[part], flag)))
{
- my_error(ER_GET_ERRNO, MYF(0), error);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(error);
}
} while (++j < no_subparts);
}
@@ -1159,8 +1117,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
DBUG_PRINT("info", ("Optimize partition %u", i));
if ((error= handle_opt_part(thd, check_opt, m_file[i], flag)))
{
- my_error(ER_GET_ERRNO, MYF(0), error);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(error);
}
}
}
@@ -1204,7 +1161,6 @@ int ha_partition::prepare_new_partition(TABLE *table,
error:
if (create_flag)
VOID(file->delete_table(part_name));
- print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -1331,7 +1287,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
(m_reorged_parts + 1))))
{
mem_alloc_error(sizeof(partition_element*)*(m_reorged_parts+1));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_OUTOFMEMORY);
}
/*
@@ -1363,7 +1319,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
(2*(no_remain_partitions + 1)))))
{
mem_alloc_error(sizeof(handler*)*2*(no_remain_partitions+1));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_OUTOFMEMORY);
}
m_added_file= &new_file_array[no_remain_partitions + 1];
@@ -1435,7 +1391,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->engine_type)))
{
mem_alloc_error(sizeof(handler));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_OUTOFMEMORY);
}
} while (++j < no_subparts);
}
@@ -1483,7 +1439,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
(const char *)part_name_buff)))
{
cleanup_new_partition(part_count);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(error);
}
m_added_file[part_count++]= new_file_array[part];
} while (++j < no_subparts);
@@ -1499,7 +1455,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
(const char *)part_name_buff)))
{
cleanup_new_partition(part_count);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(error);
}
m_added_file[part_count++]= new_file_array[i];
}
@@ -1605,8 +1561,7 @@ int ha_partition::copy_partitions(ulonglong *copied, ulonglong *deleted)
}
DBUG_RETURN(FALSE);
error:
- print_error(result, MYF(0));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(result);
}
@@ -1873,8 +1828,8 @@ bool ha_partition::create_handler_file(const char *name)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
- part_elem->part_state != PART_IS_ADDED &&
- part_elem->part_state != PART_IS_CHANGED)
+ part_elem->part_state != PART_TO_BE_ADDED &&
+ part_elem->part_state != PART_CHANGED)
continue;
tablename_to_filename(part_elem->partition_name, part_name,
FN_REFLEN);
@@ -1925,8 +1880,8 @@ bool ha_partition::create_handler_file(const char *name)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
- part_elem->part_state != PART_IS_ADDED &&
- part_elem->part_state != PART_IS_CHANGED)
+ part_elem->part_state != PART_TO_BE_ADDED &&
+ part_elem->part_state != PART_CHANGED)
continue;
if (!m_is_sub_partitioned)
{
@@ -4218,6 +4173,8 @@ void ha_partition::info(uint flag)
index_file_length: Length of index file, in principle bytes in
indexes in the table
We report sum
+ delete_length: Length of free space easily used by new records in table
+ We report sum
mean_record_length:Mean record length in the table
We calculate this
check_time: Time of last check (only applicable to MyISAM)
@@ -4227,6 +4184,7 @@ void ha_partition::info(uint flag)
deleted= 0;
data_file_length= 0;
index_file_length= 0;
+ delete_length= 0;
check_time= 0;
file_array= m_file;
do
@@ -4239,6 +4197,7 @@ void ha_partition::info(uint flag)
deleted+= file->deleted;
data_file_length+= file->data_file_length;
index_file_length+= file->index_file_length;
+ delete_length+= file->delete_length;
if (file->check_time > check_time)
check_time= file->check_time;
}
@@ -5368,6 +5327,82 @@ void ha_partition::init_table_handle_for_HANDLER()
/****************************************************************************
+ MODULE enable/disable indexes
+****************************************************************************/
+
+/*
+ Disable indexes for a while
+ SYNOPSIS
+ disable_indexes()
+ mode Mode
+ RETURN VALUES
+ 0 Success
+ != 0 Error
+*/
+
+int ha_partition::disable_indexes(uint mode)
+{
+ handler **file;
+ int error= 0;
+
+ for (file= m_file; *file; file++)
+ {
+ if ((error= (*file)->disable_indexes(mode)))
+ break;
+ }
+ return error;
+}
+
+
+/*
+ Enable indexes again
+ SYNOPSIS
+ enable_indexes()
+ mode Mode
+ RETURN VALUES
+ 0 Success
+ != 0 Error
+*/
+
+int ha_partition::enable_indexes(uint mode)
+{
+ handler **file;
+ int error= 0;
+
+ for (file= m_file; *file; file++)
+ {
+ if ((error= (*file)->enable_indexes(mode)))
+ break;
+ }
+ return error;
+}
+
+
+/*
+ Check if indexes are disabled
+ SYNOPSIS
+ indexes_are_disabled()
+
+ RETURN VALUES
+ 0 Indexes are enabled
+ != 0 Indexes are disabled
+*/
+
+int ha_partition::indexes_are_disabled(void)
+{
+ handler **file;
+ int error= 0;
+
+ for (file= m_file; *file; file++)
+ {
+ if ((error= (*file)->indexes_are_disabled()))
+ break;
+ }
+ return error;
+}
+
+
+/****************************************************************************
MODULE Partition Share
****************************************************************************/
/*
@@ -5487,3 +5522,20 @@ static int free_share(PARTITION_SHARE *share)
return 0;
}
#endif /* NOT_USED */
+
+
+mysql_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_hton,
+ partition_hton_name,
+ "Mikael Ronstrom, MySQL AB",
+ partition_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index ecaa7e1e8fa..1443a20133c 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -179,7 +179,8 @@ public:
virtual int rename_table(const char *from, const char *to);
virtual int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info);
- virtual int create_handler_files(const char *name,
+ virtual int create_handler_files(const char *name,
+ const char *old_name, int action_flag,
HA_CREATE_INFO *create_info);
virtual void update_create_info(HA_CREATE_INFO *create_info);
virtual char *update_table_comment(const char *comment);
@@ -937,17 +938,18 @@ public:
virtual uint checksum() const;
virtual bool is_crashed() const;
virtual bool auto_repair() const;
+ */
+ /*
-------------------------------------------------------------------------
MODULE enable/disable indexes
-------------------------------------------------------------------------
- Enable/Disable Indexes are not supported currently (Heap, MyISAM)
- This means that the following methods are not implemented:
+ Enable/Disable Indexes are only supported by HEAP and MyISAM.
-------------------------------------------------------------------------
+ */
virtual int disable_indexes(uint mode);
virtual int enable_indexes(uint mode);
virtual int indexes_are_disabled(void);
- */
/*
-------------------------------------------------------------------------
diff --git a/sql/handler.cc b/sql/handler.cc
index 808dd0841c5..f51e91f1882 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -35,6 +35,7 @@
#define NDB_MAX_ATTRIBUTES_IN_TABLE 128
#include "ha_ndbcluster.h"
#endif
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
#endif
@@ -43,10 +44,15 @@
#include "ha_innodb.h"
#endif
-extern handlerton *sys_table_types[];
+/* While we have legacy_db_type, we have this array to
+ check for dups and to find handlerton from legacy_db_type.
+ Remove when legacy_db_type is finally gone */
+static handlerton *installed_htons[128];
#define BITMAP_STACKBUF_SIZE (128/8)
+KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} };
+
/* static functions defined in this file */
static handler *create_default(TABLE_SHARE *table);
@@ -138,30 +144,8 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name)
}
-struct plugin_find_dbtype_st
-{
- enum legacy_db_type db_type;
- handlerton *hton;
-};
-
-
-static my_bool plugin_find_dbtype(THD *unused, st_plugin_int *plugin,
- void *arg)
-{
- handlerton *types= (handlerton *) plugin->plugin->info;
- if (types->db_type == ((struct plugin_find_dbtype_st *)arg)->db_type)
- {
- ((struct plugin_find_dbtype_st *)arg)->hton= types;
- return TRUE;
- }
- return FALSE;
-}
-
-
const char *ha_get_storage_engine(enum legacy_db_type db_type)
{
- struct plugin_find_dbtype_st info;
-
switch (db_type)
{
case DB_TYPE_DEFAULT:
@@ -169,13 +153,10 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type)
case DB_TYPE_UNKNOWN:
return "UNKNOWN";
default:
- info.db_type= db_type;
-
- if (!plugin_foreach(NULL, plugin_find_dbtype,
- MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
+ installed_htons[db_type])
+ return installed_htons[db_type]->name;
return "*NONE*";
-
- return info.hton->name;
}
}
@@ -190,8 +171,6 @@ static handler *create_default(TABLE_SHARE *table)
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
{
- struct plugin_find_dbtype_st info;
-
switch (db_type)
{
case DB_TYPE_DEFAULT:
@@ -202,12 +181,9 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
case DB_TYPE_UNKNOWN:
return NULL;
default:
- info.db_type= db_type;
- if (!plugin_foreach(NULL, plugin_find_dbtype,
- MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT)
+ return installed_htons[db_type];
return NULL;
-
- return info.hton;
}
}
@@ -394,32 +370,77 @@ static int ha_finish_errors(void)
}
-static void ha_was_inited_ok(handlerton *ht)
+int ha_finalize_handlerton(st_plugin_int *plugin)
{
- 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++;
+ handlerton *hton;
+ DBUG_ENTER("ha_finalize_handlerton");
+
+ if (!(hton= (handlerton *) plugin->plugin->info))
+ DBUG_RETURN(1);
+
+ switch (hton->state)
+ {
+ case SHOW_OPTION_NO:
+ case SHOW_OPTION_DISABLED:
+ break;
+ case SHOW_OPTION_YES:
+ if (hton->panic && hton->panic(HA_PANIC_CLOSE))
+ DBUG_RETURN(1);
+ if (installed_htons[hton->db_type] == hton)
+ installed_htons[hton->db_type]= NULL;
+ break;
+ };
+ DBUG_RETURN(0);
}
-int ha_initialize_handlerton(handlerton *hton)
+int ha_initialize_handlerton(st_plugin_int *plugin)
{
+ handlerton *hton;
DBUG_ENTER("ha_initialize_handlerton");
- if (hton == NULL)
+ if (!(hton= (handlerton *) plugin->plugin->info))
DBUG_RETURN(1);
- switch (hton->state)
- {
+ /* for the sake of sanity, we set the handlerton name to be the
+ same as the plugin name */
+ hton->name= plugin->name.str;
+
+
+ switch (hton->state) {
case SHOW_OPTION_NO:
break;
case SHOW_OPTION_YES:
if (!hton->init || !hton->init())
{
- ha_was_inited_ok(hton);
+ uint tmp= hton->savepoint_offset;
+ hton->savepoint_offset= savepoint_alloc_size;
+ savepoint_alloc_size+= tmp;
+ hton->slot= total_ha++;
+ if (hton->prepare)
+ total_ha_2pc++;
+
+ /* now check the db_type for conflict */
+ if (hton->db_type <= DB_TYPE_UNKNOWN ||
+ hton->db_type >= DB_TYPE_DEFAULT ||
+ installed_htons[hton->db_type])
+ {
+ int idx= (int) DB_TYPE_FIRST_DYNAMIC;
+
+ while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
+ idx++;
+
+ if (idx == (int) DB_TYPE_DEFAULT)
+ {
+ sql_print_warning("Too many storage engines!");
+ DBUG_RETURN(1);
+ }
+ if (hton->db_type != DB_TYPE_UNKNOWN)
+ sql_print_warning("Storage engine '%s' has conflicting typecode. "
+ "Assigning value %d.", hton->name, idx);
+ hton->db_type= (enum legacy_db_type) idx;
+ }
+ installed_htons[hton->db_type]= hton;
break;
}
/* fall through */
@@ -436,7 +457,7 @@ static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin,
{
if (plugin->state == PLUGIN_IS_UNINITIALIZED)
{
- ha_initialize_handlerton((handlerton *) plugin->plugin->info);
+ ha_initialize_handlerton(plugin);
plugin->state= PLUGIN_IS_READY;
}
return FALSE;
@@ -447,12 +468,15 @@ int ha_init()
{
int error= 0;
total_ha= savepoint_alloc_size= 0;
+ DBUG_ENTER("ha_init");
+
+ bzero(installed_htons, sizeof(installed_htons));
if (ha_init_errors())
- return 1;
+ DBUG_RETURN(1);
if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0))
- return 1;
+ DBUG_RETURN(1);
DBUG_ASSERT(total_ha < MAX_HA);
/*
@@ -462,37 +486,7 @@ int ha_init()
*/
opt_using_transactions= total_ha>(ulong)opt_bin_log;
savepoint_alloc_size+= sizeof(SAVEPOINT);
- return error;
-}
-
-
-int ha_register_builtin_plugins()
-{
- handlerton **hton;
- uint size= 0;
- struct st_mysql_plugin *plugin;
- DBUG_ENTER("ha_register_builtin_plugins");
-
- for (hton= sys_table_types; *hton; hton++)
- size+= sizeof(struct st_mysql_plugin);
-
- if (!(plugin= (struct st_mysql_plugin *)
- my_once_alloc(size, MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(1);
-
- for (hton= sys_table_types; *hton; hton++, plugin++)
- {
- plugin->type= MYSQL_STORAGE_ENGINE_PLUGIN;
- plugin->info= *hton;
- plugin->version= 0;
- plugin->name= (*hton)->name;
- plugin->author= NULL;
- plugin->descr= (*hton)->comment;
-
- if (plugin_register_builtin(plugin))
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
@@ -1824,6 +1818,24 @@ ulonglong handler::get_auto_increment()
}
+void handler::print_keydupp_error(uint key_nr, const char *msg)
+{
+ /* Write the duplicated key in the error message */
+ char key[MAX_KEY_LENGTH];
+ String str(key,sizeof(key),system_charset_info);
+ /* Table is opened and defined at this point */
+ key_unpack(&str,table,(uint) key_nr);
+ uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(msg);
+ if (str.length() >= max_length)
+ {
+ str.length(max_length-4);
+ str.append(STRING_WITH_LEN("..."));
+ }
+ my_printf_error(ER_DUP_ENTRY, msg,
+ MYF(0), str.c_ptr(), table->key_info[key_nr].name);
+}
+
+
/*
Print error that we got from handler function
@@ -1863,18 +1875,7 @@ void handler::print_error(int error, myf errflag)
uint key_nr=get_dup_key(error);
if ((int) key_nr >= 0)
{
- /* Write the duplicated key in the error message */
- char key[MAX_KEY_LENGTH];
- String str(key,sizeof(key),system_charset_info);
- /* Table is opened and defined at this point */
- key_unpack(&str,table,(uint) key_nr);
- uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
- if (str.length() >= max_length)
- {
- str.length(max_length-4);
- str.append(STRING_WITH_LEN("..."));
- }
- my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), table->key_info[key_nr].name);
+ print_keydupp_error(key_nr, ER(ER_DUP_ENTRY));
DBUG_VOID_RETURN;
}
textno=ER_DUP_KEY;
@@ -3270,10 +3271,11 @@ int handler::ha_external_lock(THD *thd, int lock_type)
locking combined with row-based replication needs to be looked
over. Ideally, no such special handling should be needed.
*/
- switch (thd->lex->sql_command)
- {
+ switch (thd->lex->sql_command) {
case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_OPTIMIZE:
+ case SQLCOM_REPAIR:
DBUG_RETURN(0);
default:
break;
diff --git a/sql/handler.h b/sql/handler.h
index e93fdfe67e3..9a5a3b04823 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -84,6 +84,7 @@
access on the table based on a given record.
*/
#define HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS (1 << 16)
+#define HA_CAN_RTREEKEYS (1 << 17)
#define HA_NOT_DELETE_WITH_CACHE (1 << 18)
#define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
#define HA_CAN_FULLTEXT (1 << 21)
@@ -233,6 +234,7 @@ enum legacy_db_type
DB_TYPE_BLACKHOLE_DB,
DB_TYPE_PARTITION_DB,
DB_TYPE_BINLOG,
+ DB_TYPE_FIRST_DYNAMIC=32,
DB_TYPE_DEFAULT=127 // Must be last
};
@@ -280,6 +282,7 @@ enum enum_binlog_command {
#define HA_CREATE_USED_COMMENT (1L << 16)
#define HA_CREATE_USED_PASSWORD (1L << 17)
#define HA_CREATE_USED_CONNECTION (1L << 18)
+#define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19)
typedef ulonglong my_xid; // this line is the same as in log_event.h
#define MYSQL_XID_PREFIX "MySQLXid"
@@ -402,6 +405,7 @@ enum tablespace_access_mode
TS_NOT_ACCESSIBLE = 2
};
+struct handlerton;
class st_alter_tablespace : public Sql_alloc
{
public:
@@ -419,7 +423,7 @@ class st_alter_tablespace : public Sql_alloc
ulonglong autoextend_size;
ulonglong max_size;
uint nodegroup_id;
- enum legacy_db_type storage_engine;
+ const handlerton *storage_engine;
bool wait_until_completed;
const char *ts_comment;
enum tablespace_access_mode ts_access_mode;
@@ -437,7 +441,7 @@ class st_alter_tablespace : public Sql_alloc
initial_size= 128*1024*1024; //Default 128 MByte
autoextend_size= 0; //No autoextension as default
max_size= 0; //Max size == initial size => no extension
- storage_engine= DB_TYPE_UNKNOWN;
+ storage_engine= NULL;
nodegroup_id= UNDEF_NODEGROUP;
wait_until_completed= TRUE;
ts_comment= NULL;
@@ -468,7 +472,7 @@ enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
savepoint_*, prepare, recover, and *_by_xid pointers can be 0.
*/
-typedef struct
+struct handlerton
{
/*
handlerton structure version
@@ -581,7 +585,7 @@ typedef struct
const char *query, uint query_length,
const char *db, const char *table_name);
int (*release_temporary_latches)(THD *thd);
-} handlerton;
+};
extern const handlerton default_hton;
@@ -599,6 +603,7 @@ struct show_table_alias_st {
#define HTON_FLUSH_AFTER_RENAME (1 << 4)
#define HTON_NOT_USER_SELECTABLE (1 << 5)
#define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
+#define HTON_ALTER_CANNOT_CREATE (1 << 7) //Cannot use alter to create
typedef struct st_thd_trans
{
@@ -632,6 +637,7 @@ typedef struct {
#define UNDEF_NODEGROUP 65535
class Item;
+struct st_table_log_memory_entry;
class partition_info;
@@ -639,7 +645,6 @@ struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)
-
typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset, *default_table_charset;
@@ -652,6 +657,7 @@ typedef struct st_ha_create_information
ulong table_options;
ulong avg_row_length;
ulong used_fields;
+ ulong key_block_size;
SQL_LIST merge_list;
handlerton *db_type;
enum row_type row_type;
@@ -665,6 +671,15 @@ typedef struct st_ha_create_information
bool store_on_disk; /* 1 if table stored on disk */
} HA_CREATE_INFO;
+
+typedef struct st_key_create_information
+{
+ enum ha_key_alg algorithm;
+ ulong block_size;
+ LEX_STRING parser_name;
+} KEY_CREATE_INFO;
+
+
/*
Class for maintaining hooks used inside operations on tables such
as: create table functions, delete table functions, and alter table
@@ -699,6 +714,7 @@ private:
typedef struct st_savepoint SAVEPOINT;
extern ulong savepoint_alloc_size;
+extern KEY_CREATE_INFO default_key_create_info;
/* Forward declaration for condition pushdown to storage engine */
typedef class Item COND;
@@ -849,6 +865,7 @@ public:
virtual int ha_initialise();
int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
bool update_auto_increment();
+ void print_keydupp_error(uint key_nr, const char *msg);
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
@@ -1379,8 +1396,15 @@ public:
virtual void drop_table(const char *name);
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
- virtual int create_handler_files(const char *name, HA_CREATE_INFO *info)
- { return FALSE;}
+
+#define CHF_CREATE_FLAG 0
+#define CHF_DELETE_FLAG 1
+#define CHF_RENAME_FLAG 2
+#define CHF_INDEX_FLAG 3
+
+ virtual int create_handler_files(const char *name, const char *old_name,
+ int action_flag, HA_CREATE_INFO *info)
+ { return FALSE; }
virtual int change_partitions(HA_CREATE_INFO *create_info,
const char *path,
@@ -1545,8 +1569,8 @@ static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
/* basic stuff */
int ha_init(void);
-int ha_register_builtin_plugins();
-int ha_initialize_handlerton(handlerton *hton);
+int ha_initialize_handlerton(st_plugin_int *plugin);
+int ha_finalize_handlerton(st_plugin_int *plugin);
TYPELIB *ha_known_exts(void);
int ha_panic(enum ha_panic_function flag);
diff --git a/sql/handlerton-win.cc b/sql/handlerton-win.cc
deleted file mode 100644
index 9ce4eab2444..00000000000
--- a/sql/handlerton-win.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "mysql_priv.h"
-
-extern handlerton heap_hton;
-extern handlerton myisam_hton;
-extern handlerton myisammrg_hton;
-extern handlerton binlog_hton;
-#ifdef WITH_INNOBASE_STORAGE_ENGINE
-extern handlerton innobase_hton;
-#endif
-#ifdef WITH_BERKELEY_STORAGE_ENGINE
-extern handlerton berkeley_hton;
-#endif
-#ifdef WITH_EXAMPLE_STORAGE_ENGINE
-extern handlerton example_hton;
-#endif
-#ifdef WITH_ARCHIVE_STORAGE_ENGINE
-extern handlerton archive_hton;
-#endif
-#ifdef WITH_CSV_STORAGE_ENGINE
-extern handlerton tina_hton;
-#endif
-#ifdef WITH_BLACKHOLE_STORAGE_ENGINE
-extern handlerton blackhole_hton;
-#endif
-#ifdef WITH_FEDERATED_STORAGE_ENGINE
-extern handlerton federated_hton;
-#endif
-#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
-extern handlerton ndbcluster_hton;
-#endif
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-extern handlerton partition_hton;
-#endif
-
-/*
- This array is used for processing compiled in engines.
-*/
-handlerton *sys_table_types[]=
-{
- &heap_hton,
- &myisam_hton,
-#ifdef WITH_INNOBASE_STORAGE_ENGINE
- &innobase_hton,
-#endif
-#ifdef WITH_BERKELEY_STORAGE_ENGINE
- &berkeley_hton,
-#endif
-#ifdef WITH_EXAMPLE_STORAGE_ENGINE
- &example_hton,
-#endif
-#ifdef WITH_ARCHIVE_STORAGE_ENGINE
- &archive_hton,
-#endif
-#ifdef WITH_CSV_STORAGE_ENGINE
- &tina_hton,
-#endif
-#ifdef WITH_BLACKHOLE_STORAGE_ENGINE
- &blackhole_hton,
-#endif
-#ifdef WITH_FEDERATED_STORAGE_ENGINE
- &federated_hton,
-#endif
-#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
- &ndbcluster_hton,
-#endif
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- &partition_hton,
-#endif
- &myisammrg_hton,
- &binlog_hton,
- NULL
-};
diff --git a/sql/handlerton.cc.in b/sql/handlerton.cc.in
deleted file mode 100644
index 55af8cdd8cf..00000000000
--- a/sql/handlerton.cc.in
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "mysql_priv.h"
-
-extern handlerton heap_hton,myisam_hton,myisammrg_hton,
- binlog_hton@mysql_se_decls@;
-
-/*
- This array is used for processing compiled in engines.
-*/
-handlerton *sys_table_types[]=
-{
- &heap_hton,&myisam_hton@mysql_se_htons@,&myisammrg_hton,&binlog_hton,NULL
-};
-
diff --git a/sql/item.cc b/sql/item.cc
index 787dc22365e..d596699dd30 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -304,6 +304,7 @@ Item::Item():
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
decimals= 0; max_length= 0;
+ with_subselect= 0;
/* Put item in free list so that we can free all items at end */
THD *thd= current_thd;
@@ -644,22 +645,6 @@ Item *Item_num::safe_charset_converter(CHARSET_INFO *tocs)
}
-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;
@@ -977,6 +962,12 @@ void Item_splocal::print(String *str)
}
+bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ return ctx->set_variable(thd, get_var_idx(), it);
+}
+
+
/*****************************************************************************
Item_case_expr methods
*****************************************************************************/
@@ -1906,7 +1897,6 @@ Item_decimal::Item_decimal(const char *str_arg, uint length,
name= (char*) str_arg;
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1916,7 +1906,6 @@ 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;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1927,7 +1916,6 @@ 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;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1940,7 +1928,6 @@ Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg,
name= (char*) str;
decimals= (uint8) decimal_par;
max_length= length;
- unsigned_flag= !decimal_value.sign();
fixed= 1;
}
@@ -1950,7 +1937,6 @@ Item_decimal::Item_decimal(my_decimal *value_par)
my_decimal2decimal(value_par, &decimal_value);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1962,7 +1948,6 @@ Item_decimal::Item_decimal(const char *bin, int precision, int scale)
&decimal_value, precision, scale);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(precision, decimals,
unsigned_flag);
}
@@ -2014,6 +1999,16 @@ bool Item_decimal::eq(const Item *item, bool binary_cmp) const
}
+void Item_decimal::set_decimal_value(my_decimal *value_par)
+{
+ my_decimal2decimal(value_par, &decimal_value);
+ decimals= (uint8) decimal_value.frac;
+ unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
+
+
String *Item_float::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
@@ -3160,7 +3155,8 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
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.
+ derived SELECT column. This extension is allowed only if the
+ MODE_ONLY_FULL_GROUP_BY sql mode isn't enabled.
NOTES
The resolution procedure is:
@@ -3170,7 +3166,9 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
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.
+ - otherwise
+ - if the MODE_ONLY_FULL_GROUP_BY mode is enabled return error
+ - else return the found SELECT column.
RETURN
@@ -3215,6 +3213,17 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
}
}
+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
+ select_ref != not_found_item && !group_by_ref)
+ {
+ /*
+ Report the error if fields was found only in the SELECT item list and
+ the strict mode is enabled.
+ */
+ my_error(ER_NON_GROUPING_FIELD_USED, MYF(0),
+ ref->name, "HAVING");
+ return NULL;
+ }
if (select_ref != not_found_item || group_by_ref)
{
if (select_ref != not_found_item && !ambiguous_fields)
@@ -4873,7 +4882,16 @@ void Item_ref::cleanup()
void Item_ref::print(String *str)
{
if (ref)
- (*ref)->print(str);
+ {
+ if ((*ref)->type() != Item::CACHE_ITEM && ref_type() != VIEW_REF &&
+ name && alias_name_used)
+ {
+ THD *thd= current_thd;
+ append_identifier(thd, str, name, (uint) strlen(name));
+ }
+ else
+ (*ref)->print(str);
+ }
else
Item_ident::print(str);
}
@@ -5184,14 +5202,6 @@ bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const
return FALSE;
}
-void Item_null_helper::print(String *str)
-{
- str->append(STRING_WITH_LEN("<null_helper>("));
- store->print(str);
- str->append(')');
-}
-
-
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
@@ -5413,6 +5423,25 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
}
+void Item_trigger_field::set_required_privilege(bool rw)
+{
+ /*
+ Require SELECT and UPDATE privilege if this field will be read and
+ set, and only UPDATE privilege for setting the field.
+ */
+ want_privilege= (rw ? SELECT_ACL | UPDATE_ACL : UPDATE_ACL);
+}
+
+
+bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it)
+{
+ Item *item= sp_prepare_func_item(thd, it);
+
+ return (!item || (!fixed && fix_fields(thd, 0)) ||
+ (item->save_in_field(field, 0) < 0));
+}
+
+
bool Item_trigger_field::fix_fields(THD *thd, Item **items)
{
/*
@@ -5435,8 +5464,7 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items)
if (table_grants)
{
- table_grants->want_privilege=
- access_type == AT_READ ? SELECT_ACL : UPDATE_ACL;
+ table_grants->want_privilege= want_privilege;
if (check_grant_column(thd, table_grants, triggers->table->s->db.str,
triggers->table->s->table_name.str, field_name,
@@ -5468,6 +5496,7 @@ void Item_trigger_field::print(String *str)
void Item_trigger_field::cleanup()
{
+ want_privilege= original_privilege;
/*
Since special nature of Item_trigger_field we should not do most of
things from Item_field::cleanup() or Item_ident::cleanup() here.
diff --git a/sql/item.h b/sql/item.h
index ea68bfa9a17..685da3014ef 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -401,6 +401,42 @@ typedef enum monotonicity_info
/*************************************************************************/
+class sp_rcontext;
+
+
+class Settable_routine_parameter
+{
+public:
+ /*
+ Set required privileges for accessing the parameter.
+
+ SYNOPSIS
+ set_required_privilege()
+ rw if 'rw' is true then we are going to read and set the
+ parameter, so SELECT and UPDATE privileges might be
+ required, otherwise we only reading it and SELECT
+ privilege might be required.
+ */
+ virtual void set_required_privilege(bool rw) {};
+
+ /*
+ Set parameter value.
+
+ SYNOPSIS
+ set_value()
+ thd thread handle
+ ctx context to which parameter belongs (if it is local
+ variable).
+ it item which represents new value
+
+ RETURN
+ FALSE if parameter value has been set,
+ TRUE if error has occured.
+ */
+ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0;
+};
+
+
typedef bool (Item::*Item_processor)(byte *arg);
typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
@@ -454,6 +490,9 @@ public:
my_bool is_autogenerated_name; /* indicate was name of this Item
autogenerated or set by user */
DTCollation collation;
+ my_bool with_subselect; /* If this item is a subselect or some
+ of its arguments is or contains a
+ subselect */
// alloc & destruct is done as start of select using sql_alloc
Item();
@@ -807,6 +846,15 @@ public:
}
virtual bool is_splocal() { return 0; } /* Needed for error checking */
+
+ /*
+ Return Settable_routine_parameter interface of the Item. Return 0
+ if this Item is not Settable_routine_parameter.
+ */
+ virtual Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return 0;
+ }
};
@@ -905,7 +953,8 @@ inline bool Item_sp_variable::send(Protocol *protocol, String *str)
runtime.
*****************************************************************************/
-class Item_splocal :public Item_sp_variable
+class Item_splocal :public Item_sp_variable,
+ private Settable_routine_parameter
{
uint m_var_idx;
@@ -943,6 +992,15 @@ public:
inline enum Type type() const;
inline Item_result result_type() const;
+
+private:
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return this;
+ }
};
/*****************************************************************************
@@ -1460,20 +1518,6 @@ public:
};
-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); }
- bool check_partition_func_processor(byte *bool_arg)
- { *(bool *)bool_arg= FALSE; return 0; }
-};
-
-
class Item_uint :public Item_int
{
public:
@@ -1529,6 +1573,7 @@ public:
}
uint decimal_precision() const { return decimal_value.precision(); }
bool eq(const Item *, bool binary_cmp) const;
+ void set_decimal_value(my_decimal *value_par);
};
@@ -1945,21 +1990,6 @@ public:
}
};
-class Item_null_helper :public Item_ref_null_helper
-{
- Item *store;
-public:
- 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);
-};
-
-
/*
The following class is used to optimize comparing of date and bigint columns
We need to save the original item ('ref') to be able to call
@@ -2215,14 +2245,13 @@ class Table_triggers_list;
two Field instances representing either OLD or NEW version of this
field.
*/
-class Item_trigger_field : public Item_field
+class Item_trigger_field : public Item_field,
+ private Settable_routine_parameter
{
public:
/* Is this item represents row from NEW or OLD row ? */
enum row_version_type {OLD_ROW, NEW_ROW};
row_version_type row_version;
- /* Is this item used for reading or updating the value? */
- enum access_types { AT_READ = 0x1, AT_UPDATE = 0x2 };
/* 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 */
@@ -2233,11 +2262,11 @@ public:
Item_trigger_field(Name_resolution_context *context_arg,
row_version_type row_ver_arg,
const char *field_name_arg,
- access_types access_type_arg)
+ ulong priv, const bool ro)
:Item_field(context_arg,
(const char *)NULL, (const char *)NULL, field_name_arg),
- row_version(row_ver_arg), field_idx((uint)-1),
- access_type(access_type_arg), table_grants(NULL)
+ row_version(row_ver_arg), field_idx((uint)-1), original_privilege(priv),
+ want_privilege(priv), table_grants(NULL), read_only (ro)
{}
void setup_field(THD *thd, TABLE *table, GRANT_INFO *table_grant_info);
enum Type type() const { return TRIGGER_FIELD_ITEM; }
@@ -2248,8 +2277,39 @@ public:
void cleanup();
private:
- access_types access_type;
+ void set_required_privilege(bool rw);
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return (read_only ? 0 : this);
+ }
+
+ bool set_value(THD *thd, Item **it)
+ {
+ return set_value(thd, NULL, it);
+ }
+
+private:
+ /*
+ 'want_privilege' holds privileges required to perform operation on
+ this trigger field (SELECT_ACL if we are going to read it and
+ UPDATE_ACL if we are going to update it). It is initialized at
+ parse time but can be updated later if this trigger field is used
+ as OUT or INOUT parameter of stored routine (in this case
+ set_required_privilege() is called to appropriately update
+ want_privilege and cleanup() is responsible for restoring of
+ original want_privilege once parameter's value is updated).
+ */
+ ulong original_privilege;
+ ulong want_privilege;
GRANT_INFO *table_grants;
+ /*
+ Trigger field is read-only unless it belongs to the NEW row in a
+ BEFORE INSERT of BEFORE UPDATE trigger.
+ */
+ bool read_only;
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index acee912c912..0552e8b6336 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -41,10 +41,25 @@ static Item_result item_store_type(Item_result a,Item_result b)
static void agg_result_type(Item_result *type, Item **items, uint nitems)
{
- uint i;
- type[0]= items[0]->result_type();
- for (i=1 ; i < nitems ; i++)
- type[0]= item_store_type(type[0], items[i]->result_type());
+ Item **item, **item_end;
+
+ *type= STRING_RESULT;
+ /* Skip beginning NULL items */
+ for (item= items, item_end= item + nitems; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ {
+ *type= (*item)->result_type();
+ item++;
+ break;
+ }
+ }
+ /* Combine result types. Note: NULL items don't affect the result */
+ for (; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ *type= item_store_type(type[0], (*item)->result_type());
+ }
}
@@ -189,10 +204,28 @@ longlong Item_func_nop_all::val_int()
/*
- Convert a constant expression or string to an integer.
- This is done when comparing DATE's of different formats and
- also when comparing bigint to strings (in which case the string
- is converted once to a bigint).
+ Convert a constant item to an int and replace the original item
+
+ SYNOPSIS
+ convert_constant_item()
+ thd thread handle
+ field item will be converted using the type of this field
+ item [in/out] reference to the item to convert
+
+ DESCRIPTION
+ The function converts a constant expression or string to an integer.
+ On successful conversion the original item is substituted for the
+ result of the item evaluation.
+ This is done when comparing DATE/TIME of different formats and
+ also when comparing bigint to strings (in which case strings
+ are converted to bigints).
+
+ NOTES
+ This function is called only at prepare stage.
+ As all derived tables are filled only after all derived tables
+ are prepared we do not evaluate items with subselects here because
+ they can contain derived tables and thus we may attempt to use a
+ table that has not been populated yet.
RESULT VALUES
0 Can't convert item
@@ -201,7 +234,7 @@ longlong Item_func_nop_all::val_int()
static bool convert_constant_item(THD *thd, Field *field, Item **item)
{
- if ((*item)->const_item())
+ if (!(*item)->with_subselect && (*item)->const_item())
{
/* For comparison purposes allow invalid dates like 2000-01-32 */
ulong orig_sql_mode= field->table->in_use->variables.sql_mode;
@@ -2555,7 +2588,9 @@ Item_cond::fix_fields(THD *thd, Item **ref)
(item= *li.ref())->check_cols(1))
return TRUE; /* purecov: inspected */
used_tables_cache|= item->used_tables();
- if (!item->const_item())
+ if (item->const_item())
+ and_tables_cache= (table_map) 0;
+ else
{
tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
@@ -2563,6 +2598,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
const_item_cache= FALSE;
}
with_sum_func= with_sum_func || item->with_sum_func;
+ with_subselect|= item->with_subselect;
if (item->maybe_null)
maybe_null=1;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 1a289c05006..f7da1e5e297 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -630,15 +630,17 @@ public:
/* Functions to handle the optimized IN */
+
+/* A vector of values of some type */
+
class in_vector :public Sql_alloc
{
- protected:
+public:
char *base;
uint size;
qsort2_cmp compare;
CHARSET_INFO *collation;
uint count;
-public:
uint used_count;
in_vector() {}
in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
@@ -654,6 +656,32 @@ public:
qsort2(base,used_count,size,compare,collation);
}
int find(Item *item);
+
+ /*
+ Create an instance of Item_{type} (e.g. Item_decimal) constant object
+ which type allows it to hold an element of this vector without any
+ conversions.
+ The purpose of this function is to be able to get elements of this
+ vector in form of Item_xxx constants without creating Item_xxx object
+ for every array element you get (i.e. this implements "FlyWeight" pattern)
+ */
+ virtual Item* create_item() { return NULL; }
+
+ /*
+ Store the value at position #pos into provided item object
+ SYNOPSIS
+ value_to_item()
+ pos Index of value to store
+ item Constant item to store value into. The item must be of the same
+ type that create_item() returns.
+ */
+ virtual void value_to_item(uint pos, Item *item) { }
+
+ /* Compare values number pos1 and pos2 for equality */
+ bool compare_elems(uint pos1, uint pos2)
+ {
+ return test(compare(collation, base + pos1*size, base + pos2*size));
+ }
};
class in_string :public in_vector
@@ -665,6 +693,16 @@ public:
~in_string();
void set(uint pos,Item *item);
byte *get_value(Item *item);
+ Item* create_item()
+ {
+ return new Item_string(collation);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ String *str=((String*) base)+pos;
+ Item_string *to= (Item_string*)item;
+ to->str_value= *str;
+ }
};
class in_longlong :public in_vector
@@ -674,6 +712,19 @@ public:
in_longlong(uint elements);
void set(uint pos,Item *item);
byte *get_value(Item *item);
+
+ Item* create_item()
+ {
+ /*
+ We're created a signed INT, this may not be correct in
+ general case (see BUG#19342).
+ */
+ return new Item_int((longlong)0);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ ((Item_int*)item)->value= ((longlong*)base)[pos];
+ }
};
class in_double :public in_vector
@@ -683,6 +734,15 @@ public:
in_double(uint elements);
void set(uint pos,Item *item);
byte *get_value(Item *item);
+ Item *create_item()
+ {
+ return new Item_float(0.0);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ ((Item_float*)item)->value= ((double*) base)[pos];
+ }
+
};
class in_decimal :public in_vector
@@ -692,6 +752,16 @@ public:
in_decimal(uint elements);
void set(uint pos, Item *item);
byte *get_value(Item *item);
+ Item *create_item()
+ {
+ return new Item_decimal(0, FALSE);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ my_decimal *dec= ((my_decimal *)base) + pos;
+ Item_decimal *item_dec= (Item_decimal*)item;
+ item_dec->set_decimal_value(dec);
+ }
};
@@ -871,12 +941,13 @@ public:
class Item_func_in :public Item_func_opt_neg
{
+public:
Item_result cmp_type;
in_vector *array;
cmp_item *in_item;
bool have_null;
DTCollation cmp_collation;
- public:
+
Item_func_in(List<Item> &list)
:Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
{
diff --git a/sql/item_create.cc b/sql/item_create.cc
index fb1ef0ee9bc..6eca6209438 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -71,14 +71,8 @@ Item *create_func_ceiling(Item* a)
Item *create_func_connection_id(void)
{
- THD *thd=current_thd;
- thd->lex->safe_to_cache_query= 0;
- return new Item_static_int_func("connection_id()",
- (longlong)
- ((thd->slave_thread) ?
- thd->variables.pseudo_thread_id :
- thd->thread_id),
- 10);
+ current_thd->lex->safe_to_cache_query= 0;
+ return new Item_func_connection_id();
}
Item *create_func_conv(Item* a, Item *b, Item *c)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 99b49d5686e..acdaa4b246d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -184,6 +184,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
used_tables_cache|= item->used_tables();
not_null_tables_cache|= item->not_null_tables();
const_item_cache&= item->const_item();
+ with_subselect|= item->with_subselect;
}
}
fix_length_and_dec();
@@ -561,6 +562,31 @@ String *Item_int_func::val_str(String *str)
}
+void Item_func_connection_id::fix_length_and_dec()
+{
+ Item_int_func::fix_length_and_dec();
+ max_length= 10;
+}
+
+
+bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
+{
+ if (Item_int_func::fix_fields(thd, ref))
+ return TRUE;
+
+ /*
+ To replicate CONNECTION_ID() properly we should use
+ pseudo_thread_id on slave, which contains the value of thread_id
+ on master.
+ */
+ value= ((thd->slave_thread) ?
+ thd->variables.pseudo_thread_id :
+ thd->thread_id);
+
+ return FALSE;
+}
+
+
/*
Check arguments here to determine result's type for a numeric
function of two arguments.
@@ -2464,11 +2490,8 @@ longlong Item_func_bit_count::val_int()
{
DBUG_ASSERT(fixed == 1);
ulonglong value= (ulonglong) args[0]->val_int();
- if (args[0]->null_value)
- {
- null_value=1; /* purecov: inspected */
+ if ((null_value= args[0]->null_value))
return 0; /* purecov: inspected */
- }
return (longlong) my_count_bits(value);
}
@@ -2714,9 +2737,10 @@ String *udf_handler::val_str(String *str,String *save_str)
{
uchar is_null_tmp=0;
ulong res_length;
+ DBUG_ENTER("udf_handler::val_str");
if (get_arguments())
- return 0;
+ DBUG_RETURN(0);
char * (*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
(char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
u_d->func;
@@ -2726,22 +2750,26 @@ String *udf_handler::val_str(String *str,String *save_str)
if (str->alloc(MAX_FIELD_WIDTH))
{
error=1;
- return 0;
+ DBUG_RETURN(0);
}
}
char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
&is_null_tmp, &error);
+ DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
if (is_null_tmp || !res || error) // The !res is for safety
{
- return 0;
+ DBUG_PRINT("info", ("Null or error"));
+ DBUG_RETURN(0);
}
if (res == str->ptr())
{
str->length(res_length);
- return str;
+ DBUG_PRINT("exit", ("str: %s", str->ptr()));
+ DBUG_RETURN(str);
}
save_str->set(res, res_length, str->charset());
- return save_str;
+ DBUG_PRINT("exit", ("save_str: %s", save_str->ptr()));
+ DBUG_RETURN(save_str);
}
@@ -2991,6 +3019,7 @@ void item_user_lock_free(void)
void item_user_lock_release(User_level_lock *ull)
{
ull->locked=0;
+ ull->thread_id= 0;
if (--ull->count)
pthread_cond_signal(&ull->cond);
else
@@ -3198,6 +3227,7 @@ longlong Item_func_get_lock::val_int()
{
ull->locked=1;
ull->thread=thd->real_id;
+ ull->thread_id= thd->thread_id;
thd->ull=ull;
error=0;
}
@@ -3924,14 +3954,24 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
sql_set_variables(), we could instead manually call check() and update();
this would save memory and time; but calling sql_set_variables() makes
one unique place to maintain (sql_set_variables()).
+
+ Manipulation with lex is necessary since free_underlaid_joins
+ is going to release memory belonging to the main query.
*/
List<set_var_base> tmp_var_list;
+ LEX *sav_lex= thd->lex, lex_tmp;
+ thd->lex= &lex_tmp;
+ lex_start(thd, NULL, 0);
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
new Item_null())));
/* Create the variable */
if (sql_set_variables(thd, &tmp_var_list))
+ {
+ thd->lex= sav_lex;
goto err;
+ }
+ thd->lex= sav_lex;
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
goto err;
}
@@ -4083,6 +4123,18 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
}
+bool Item_func_get_user_var::set_value(THD *thd,
+ sp_rcontext */*ctx*/, Item **it)
+{
+ Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
+ /*
+ Item_func_set_user_var is not fixed after construction, call
+ fix_fields().
+ */
+ return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
+}
+
+
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
@@ -4537,12 +4589,6 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
sys_var *var;
LEX_STRING *base_name, *component_name;
- if (component.str == 0 &&
- !my_strcasecmp(system_charset_info, name.str, "VERSION"))
- return new Item_string(NULL, server_version,
- (uint) strlen(server_version),
- system_charset_info, DERIVATION_SYSCONST);
-
if (component.str)
{
base_name= &component;
@@ -4721,11 +4767,14 @@ Item_func_sp::sp_result_field(void) const
dummy_table->alias= empty_name;
dummy_table->maybe_null= maybe_null;
dummy_table->in_use= current_thd;
+ dummy_table->copy_blobs= TRUE;
dummy_table->s->table_cache_key.str = empty_name;
dummy_table->s->table_name.str= empty_name;
dummy_table->s->db.str= empty_name;
}
- field= m_sp->create_result_field(max_length, name, dummy_table);
+ if (!(field= m_sp->create_result_field(max_length, name, dummy_table)))
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+
DBUG_RETURN(field);
}
@@ -4751,8 +4800,14 @@ Item_func_sp::execute(Field **flp)
if (!(f= *flp))
{
- *flp= f= sp_result_field();
- f->move_field((f->pack_length() > sizeof(result_buf)) ?
+ if (!(*flp= f= sp_result_field()))
+ {
+ /* Error set by sp_result_field() */
+ null_value= 1;
+ return TRUE;
+ }
+
+ 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;
@@ -4904,16 +4959,19 @@ longlong Item_func_found_rows::val_int()
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
- Field *res= 0;
+ Field *field= 0;
DBUG_ENTER("Item_func_sp::tmp_table_field");
if (m_sp)
- res= m_sp->create_result_field(max_length, (const char*) name, t_arg);
+ field= m_sp->create_result_field(max_length, (const char*) name, t_arg);
- if (!res)
- res= Item_func::tmp_table_field(t_arg);
+ if (!field)
+ field= Item_func::tmp_table_field(t_arg);
- DBUG_RETURN(res);
+ if (!field)
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+
+ DBUG_RETURN(field);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 4d942bf8775..9d31b57838c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -281,6 +281,19 @@ public:
};
+class Item_func_connection_id :public Item_int_func
+{
+ longlong value;
+
+public:
+ Item_func_connection_id() {}
+ const char *func_name() const { return "connection_id"; }
+ void fix_length_and_dec();
+ bool fix_fields(THD *thd, Item **ref);
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+};
+
+
class Item_func_signed :public Item_int_func
{
public:
@@ -1195,7 +1208,8 @@ public:
};
-class Item_func_get_user_var :public Item_func
+class Item_func_get_user_var :public Item_func,
+ private Settable_routine_parameter
{
user_var_entry *var_entry;
@@ -1222,6 +1236,15 @@ public:
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
+
+private:
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return this;
+ }
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index dc14bd93136..eb1fbf4855d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -80,6 +80,20 @@ String *Item_str_func::check_well_formed_result(String *str)
}
+my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ char buff[64];
+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
+ res= val_str(&tmp);
+ if (!res)
+ return 0;
+ (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
+ res->length(), res->charset(), decimal_value);
+ return decimal_value;
+}
+
+
double Item_str_func::val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -2565,7 +2579,7 @@ String *Item_load_file::val_str(String *str)
(void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "",
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
- if (!my_stat(path, &stat_info, MYF(MY_WME)))
+ if (!my_stat(path, &stat_info, MYF(0)))
goto err;
if (!(stat_info.st_mode & S_IROTH))
@@ -2927,6 +2941,7 @@ String *Item_func_uncompress::val_str(String *str)
if (!res)
goto err;
+ null_value= 0;
if (res->is_empty())
return res;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 2b244347876..212c06c45ff 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -33,6 +33,7 @@ public:
Item_str_func(List<Item> &list) :Item_func(list) {decimals=NOT_FIXED_DEC; }
longlong val_int();
double val_real();
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
String *check_well_formed_result(String *str);
@@ -552,7 +553,7 @@ public:
void fix_length_and_dec()
{
collation.set(default_charset());
- decimals=0; max_length=64;
+ max_length= 64;
}
bool check_partition_func_processor(byte *bool_arg) { return 0;}
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 68f189ccf8c..5280dbf6813 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -39,6 +39,7 @@ Item_subselect::Item_subselect():
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
const_item_cache(1), engine_changed(0), changed(0)
{
+ with_subselect= 1;
reset();
/*
item value is NULL if select_subselect not changed this value
@@ -931,14 +932,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
{
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;
+ 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();
item= func->create(expr, item);
if (!abort_on_null && orig_item->maybe_null)
{
@@ -993,17 +994,15 @@ Item_in_subselect::single_value_transformer(JOIN *join,
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()
- */
- 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=
+ join->having=
+ func->create(expr,
+ new Item_ref_null_helper(&select_lex->context, this,
+ select_lex->ref_pointer_array,
+ (char *)"<no matter>",
+ (char *)"<result>"));
+
select_lex->having_fix_field= 1;
/*
we do not check join->having->fixed, because comparison function
@@ -1356,6 +1355,17 @@ void Item_in_subselect::print(String *str)
}
+bool Item_in_subselect::fix_fields(THD *thd, Item **ref)
+{
+ bool result = 0;
+
+ if(thd->lex->view_prepare_mode && left_expr && !left_expr->fixed)
+ result = left_expr->fix_fields(thd, &left_expr);
+
+ return result || Item_subselect::fix_fields(thd, ref);
+}
+
+
Item_subselect::trans_res
Item_allany_subselect::select_transformer(JOIN *join)
{
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index a4dac5bda87..293408dc09e 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -258,6 +258,7 @@ public:
void top_level_item() { abort_on_null=1; }
bool test_limit(st_select_lex_unit *unit);
void print(String *str);
+ bool fix_fields(THD *thd, Item **ref);
friend class Item_ref_null_helper;
friend class Item_is_not_null_test;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index bb919bd1f13..50c22495463 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -380,7 +380,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
field= new Field_longlong(max_length, maybe_null, name, unsigned_flag);
break;
case STRING_RESULT:
- if (max_length <= 255 || !convert_blob_length)
+ if (max_length/collation.collation->mbmaxlen <= 255 || !convert_blob_length)
return make_string_field(table);
field= new Field_varstring(convert_blob_length, maybe_null,
name, table->s, collation.collation);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 328f8dd8400..f4ff257aa4e 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -1121,7 +1121,7 @@ public:
virtual Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const
{
- if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
+ if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB )
return FIELD_TYPE_BLOB;
else
return MYSQL_TYPE_VARCHAR;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 6fbd6db1a89..9d98e446c84 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -631,7 +631,8 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'r':
length= my_sprintf(intbuff,
(intbuff,
- (l_time->hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
+ ((l_time->hour % 24) < 12) ?
+ "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
(l_time->hour+11)%12+1,
l_time->minute,
l_time->second));
@@ -869,9 +870,9 @@ String* Item_func_monthname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
const char *month_name;
- uint month=(uint) Item_func_month::val_int();
+ uint month= (uint) val_int();
- if (!month) // This is also true for NULL
+ if (null_value || !month)
{
null_value=1;
return (String*) 0;
@@ -1962,6 +1963,9 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
if (date_sub_interval)
interval.neg = !interval.neg;
+ if (ltime->year < YY_MAGIC_BELOW)
+ return (null_value=1);
+
return (null_value= date_add_interval(ltime, int_type, interval));
}
@@ -2020,8 +2024,13 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
Item_date_add_interval *other= (Item_date_add_interval*) item;
if ((int_type != other->int_type) ||
- (!args[0]->eq(other->args[0], binary_cmp)) ||
- (get_interval_value(args[1], int_type, &val, &interval)))
+ (!args[0]->eq(other->args[0], binary_cmp)))
+ return FALSE;
+
+ if (!args[1]->const_item() || !other->args[1]->const_item())
+ return (args[1]->eq(other->args[1], binary_cmp));
+
+ if (get_interval_value(args[1], int_type, &val, &interval))
return FALSE;
val= other->value;
@@ -2255,8 +2264,8 @@ String *Item_char_typecast::val_str(String *str)
// Convert character set if differ
uint dummy_errors;
if (!(res= args[0]->val_str(&tmp_value)) ||
- str->copy(res->ptr(), res->length(), res->charset(),
- cast_cs, &dummy_errors))
+ str->copy(res->ptr(), res->length(), from_cs,
+ cast_cs, &dummy_errors))
{
null_value= 1;
return 0;
@@ -2311,21 +2320,40 @@ String *Item_char_typecast::val_str(String *str)
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.
+
+ There is a special trick to convert form a number to ucs2.
+ As numbers have my_charset_bin as their character set,
+ it wouldn't do conversion to ucs2 without an additional action.
+ To force conversion, we should pretend to be non-binary.
+ Let's choose from_cs this way:
+ - If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
+ then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
+ - If the argument is a number and cast_cs is ASCII-compatible
+ (i.e. mbminlen == 1), then from_cs is set to cast_cs,
+ which allows just to take over the args[0]->val_str() result
+ and thus avoid unnecessary character set conversion.
+ - If the argument is not a number, then from_cs is set to
+ the argument's charset.
*/
- 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);
+ from_cs= (args[0]->result_type() == INT_RESULT ||
+ args[0]->result_type() == DECIMAL_RESULT ||
+ args[0]->result_type() == REAL_RESULT) ?
+ (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
+ args[0]->collation.collation;
+ charset_conversion= (cast_cs->mbmaxlen > 1) ||
+ !my_charset_same(from_cs, cast_cs) &&
+ from_cs != &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;
+ args[0]->max_length/from_cs->mbmaxlen;
max_length= char_length * cast_cs->mbmaxlen;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index cbac0564faf..69c8ec5959a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -731,7 +731,7 @@ public:
class Item_char_typecast :public Item_typecast
{
int cast_length;
- CHARSET_INFO *cast_cs;
+ CHARSET_INFO *cast_cs, *from_cs;
bool charset_conversion;
String tmp_value;
public:
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index a245e3b1b33..17e8db90dc7 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -2281,6 +2281,30 @@ static int my_xpath_parse_Number(MY_XPATH *xpath)
/*
+ QName grammar can be found in a separate document
+ http://www.w3.org/TR/REC-xml-names/#NT-QName
+
+ [6] QName ::= (Prefix ':')? LocalPart
+ [7] Prefix ::= NCName
+ [8] LocalPart ::= NCName
+*/
+static int
+my_xpath_parse_QName(MY_XPATH *xpath)
+{
+ const char *beg;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ return 0;
+ beg= xpath->prevtok.beg;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
+ return 1; /* Non qualified name */
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ return 0;
+ xpath->prevtok.beg= beg;
+ return 1;
+}
+
+
+/*
Scan Variable reference
SYNOPSYS
@@ -2313,7 +2337,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
static int
my_xpath_parse_NodeTest_QName(MY_XPATH *xpath)
{
- if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ if (!my_xpath_parse_QName(xpath))
return 0;
DBUG_ASSERT(xpath->context);
uint len= xpath->prevtok.end - xpath->prevtok.beg;
diff --git a/sql/lex.h b/sql/lex.h
index d22a56034c5..67daf4566f8 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -133,6 +133,7 @@ static SYMBOL symbols[] = {
{ "CONSTRAINT", SYM(CONSTRAINT)},
{ "CONTAINS", SYM(CONTAINS_SYM)},
{ "CONTINUE", SYM(CONTINUE_SYM)},
+ { "CONTRIBUTORS", SYM(CONTRIBUTORS_SYM)},
{ "CONVERT", SYM(CONVERT_SYM)},
{ "CREATE", SYM(CREATE)},
{ "CROSS", SYM(CROSS)},
@@ -227,9 +228,6 @@ static SYMBOL symbols[] = {
{ "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)},
@@ -278,11 +276,8 @@ static SYMBOL symbols[] = {
{ "JOIN", SYM(JOIN_SYM)},
{ "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)},
+ { "KEY_BLOCK_SIZE", SYM(KEY_BLOCK_SIZE)},
{ "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)},
@@ -459,6 +454,7 @@ static SYMBOL symbols[] = {
{ "RTREE", SYM(RTREE_SYM)},
{ "SAVEPOINT", SYM(SAVEPOINT_SYM)},
{ "SCHEDULE", SYM(SCHEDULE_SYM)},
+ { "SCHEDULER", SYM(SCHEDULER_SYM)},
{ "SCHEMA", SYM(DATABASE)},
{ "SCHEMAS", SYM(DATABASES)},
{ "SECOND", SYM(SECOND_SYM)},
diff --git a/sql/lock.cc b/sql/lock.cc
index 24a6e23e7ad..5a6cd58dd56 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -78,6 +78,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
uint flags, TABLE **write_locked);
+static void reset_lock_data(MYSQL_LOCK *sql_lock);
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, const char *);
@@ -135,12 +136,16 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
*/
if (wait_if_global_read_lock(thd, 1, 1))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
- }
+ }
if (thd->version != refresh_version)
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
goto retry;
}
@@ -150,6 +155,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
if (lock_external(thd, tables, count))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
@@ -720,7 +727,10 @@ 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->alias);
+ my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
+ /* Clear the lock type of the lock data that are stored already. */
+ sql_lock->lock_count= locks - sql_lock->locks;
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
DBUG_RETURN(0);
}
@@ -745,6 +755,48 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
}
+/*
+ Reset lock type in lock data.
+
+ SYNOPSIS
+ reset_lock_data()
+ sql_lock The MySQL lock.
+
+ DESCRIPTION
+
+ After a locking error we want to quit the locking of the table(s).
+ The test case in the bug report for Bug #18544 has the following
+ cases: 1. Locking error in lock_external() due to InnoDB timeout.
+ 2. Locking error in get_lock_data() due to missing write permission.
+ 3. Locking error in wait_if_global_read_lock() due to lock conflict.
+
+ In all these cases we have already set the lock type into the lock
+ data of the open table(s). If the table(s) are in the open table
+ cache, they could be reused with the non-zero lock type set. This
+ could lead to ignoring a different lock type with the next lock.
+
+ Clear the lock type of all lock data. This ensures that the next
+ lock request will set its lock type properly.
+
+ RETURN
+ void
+*/
+
+static void reset_lock_data(MYSQL_LOCK *sql_lock)
+{
+ THR_LOCK_DATA **ldata;
+ THR_LOCK_DATA **ldata_end;
+
+ for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
+ ldata < ldata_end;
+ ldata++)
+ {
+ /* Reset lock type. */
+ (*ldata)->type= TL_UNLOCK;
+ }
+}
+
+
/*****************************************************************************
Lock table based on the name.
This is used when we need total access to a closed, not open table
diff --git a/sql/log.cc b/sql/log.cc
index 818abe89e02..31133a71757 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -30,6 +30,8 @@
#include "message.h"
#endif
+#include <mysql/plugin.h>
+
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_USER_HOST_SIZE 512
@@ -53,6 +55,14 @@ static int binlog_commit(THD *thd, bool all);
static int binlog_rollback(THD *thd, bool all);
static int binlog_prepare(THD *thd, bool all);
+sql_print_message_func sql_print_message_handlers[3] =
+{
+ sql_print_information,
+ sql_print_warning,
+ sql_print_error
+};
+
+
/*
This is a POD. Please keep it that way!
@@ -68,11 +78,15 @@ struct binlog_trx_data {
Rows_log_event *pending; // The pending binrows event
};
+static const char binlog_hton_name[]= "binlog";
+static const char binlog_hton_comment[]=
+ "This is a meta storage engine to represent the binlog in a transaction";
+
handlerton binlog_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "binlog",
+ binlog_hton_name,
SHOW_OPTION_YES,
- "This is a meta storage engine to represent the binlog in a transaction",
+ binlog_hton_comment,
DB_TYPE_BINLOG, /* IGNORE for now */
binlog_init,
0,
@@ -1084,12 +1098,16 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, Log_event *end_ev)
were, we would have to ensure that we're not ending a statement
inside a stored function.
*/
- thd->binlog_flush_pending_rows_event(true);
+#ifdef HAVE_ROW_BASED_REPLICATION
+ thd->binlog_flush_pending_rows_event(TRUE);
+#endif
error= mysql_bin_log.write(thd, trans_log, end_ev);
}
else
{
+#ifdef HAVE_ROW_BASED_REPLICATION
thd->binlog_delete_pending_rows_event();
+#endif
}
/*
@@ -1480,6 +1498,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
return log_name;
}
+
bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
const char *log_name)
{
@@ -2613,6 +2632,7 @@ bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
}
+#ifdef HAVE_ROW_BASED_REPLICATION
/*
These functions are placed in this file since they need access to
binlog_hton, which has internal linkage.
@@ -2790,6 +2810,7 @@ int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
DBUG_RETURN(error);
}
+#endif /*HAVE_ROW_BASED_REPLICATION*/
/*
Write an event to the binary log
@@ -2824,7 +2845,9 @@ bool MYSQL_LOG::write(Log_event *event_info)
*/
bool const end_stmt=
thd->prelocked_mode && thd->lex->requires_prelocking();
+#ifdef HAVE_ROW_BASED_REPLICATION
thd->binlog_flush_pending_rows_event(end_stmt);
+#endif /*HAVE_ROW_BASED_REPLICATION*/
pthread_mutex_lock(&LOCK_log);
@@ -2866,29 +2889,35 @@ bool MYSQL_LOG::write(Log_event *event_info)
*/
if (opt_using_transactions && thd)
{
+#ifdef HAVE_ROW_BASED_REPLICATION
if (thd->binlog_setup_trx_data())
goto err;
+#endif /*HAVE_ROW_BASED_REPLICATION*/
binlog_trx_data *const trx_data=
(binlog_trx_data*) thd->ha_data[binlog_hton.slot];
IO_CACHE *trans_log= &trx_data->trans_log;
+ bool trans_log_in_use= my_b_tell(trans_log) != 0;
- if (event_info->get_cache_stmt() && !my_b_tell(trans_log))
+ if (event_info->get_cache_stmt() && !trans_log_in_use)
trans_register_ha(thd,
- thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN),
+ (thd->options &
+ (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)),
&binlog_hton);
-
- if (event_info->get_cache_stmt() || my_b_tell(trans_log))
+ if (event_info->get_cache_stmt() || trans_log_in_use)
+ {
+ DBUG_PRINT("info", ("Using trans_log"));
file= trans_log;
+ }
/*
- Note: as Mats suggested, for all the cases above where we write to
+ TODO as Mats suggested, for all the cases above where we write to
trans_log, it sounds unnecessary to lock LOCK_log. We should rather
test first if we want to write to trans_log, and if not, lock
- LOCK_log. TODO.
+ LOCK_log.
*/
}
#endif
- DBUG_PRINT("info",("event type=%d",event_info->get_type_code()));
+ DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
/*
No check for auto events flag here - this write method should
@@ -4343,3 +4372,16 @@ err1:
return 1;
}
+
+mysql_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_hton,
+ binlog_hton_name,
+ "MySQL AB",
+ binlog_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d51a0ef4c9f..cbf1875c9ec 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3481,24 +3481,12 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
Xid_log_event methods
**************************************************************************/
-#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
-/*
- This static class member could be removed when mysqltest is made to support
- a --replace-regex command: then tests which have XIDs in their output can
- use this command to suppress non-deterministic XID values.
-*/
-my_bool Xid_log_event::show_xid;
-#endif
-
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Xid_log_event::pack_info(Protocol *protocol)
{
char buf[128], *pos;
pos= strmov(buf, "COMMIT /* xid=");
-#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
- if (show_xid)
-#endif
- pos= longlong10_to_str(xid, pos, 10);
+ pos= longlong10_to_str(xid, pos, 10);
pos= strmov(pos, " */");
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
}
@@ -5350,6 +5338,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
slave_print_msg(ERROR_LEVEL, rli, error,
"Error in %s event: when locking tables",
get_type_str());
+ rli->clear_tables_to_lock();
DBUG_RETURN(error);
}
@@ -5385,6 +5374,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
"unexpected success or fatal error"));
thd->query_error= 1;
}
+ rli->clear_tables_to_lock();
DBUG_RETURN(error);
}
}
@@ -5393,19 +5383,17 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
the table map and remove them from tables to lock.
*/
- TABLE_LIST *ptr= rli->tables_to_lock;
- while (ptr)
+ TABLE_LIST *ptr;
+ for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
{
rli->m_table_map.set_table(ptr->table_id, ptr->table);
rli->touching_table(ptr->db, ptr->table_name, ptr->table_id);
- char *to_free= reinterpret_cast<char*>(ptr);
- ptr= ptr->next_global;
- my_free(to_free, MYF(MY_WME));
}
- rli->tables_to_lock= 0;
- rli->tables_to_lock_count= 0;
+ rli->clear_tables_to_lock();
}
+ DBUG_ASSERT(rli->tables_to_lock == NULL && rli->tables_to_lock_count == 0);
+
TABLE* table= rli->m_table_map.get_table(m_table_id);
if (table)
@@ -5816,12 +5804,8 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
&tname_mem, NAME_LEN + 1,
NULL);
- /*
- If memory is allocated, it the pointer to it should be stored in
- table_list. If this is not true, the memory will not be correctly
- free:ed later.
- */
- DBUG_ASSERT(memory == NULL || memory == table_list);
+ if (memory == NULL)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
uint32 dummy_len;
bzero(table_list, sizeof(*table_list));
@@ -5836,8 +5820,12 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
int error= 0;
- if (rpl_filter->db_ok(table_list->db) &&
- (!rpl_filter->is_on() || rpl_filter->tables_ok("", table_list)))
+ if (!rpl_filter->db_ok(table_list->db) ||
+ (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list)))
+ {
+ my_free((gptr) memory, MYF(MY_WME));
+ }
+ else
{
/*
Check if the slave is set to use SBR. If so, it should switch
@@ -6416,12 +6404,17 @@ static int find_and_fetch_row(TABLE *table, byte *key)
if (table->s->keys > 0)
{
int error;
- /*
- We need to set the null bytes to ensure that the filler bit
- are all set when returning. There are storage engines that
- just set the necessary bits on the bytes and don't set the
- filler bits correctly.
- */
+ /* We have a key: search the table using the index */
+ if (!table->file->inited)
+ if ((error= table->file->ha_index_init(0, FALSE)))
+ return error;
+
+ /*
+ We need to set the null bytes to ensure that the filler bit are
+ all set when returning. There are storage engines that just set
+ the necessary bits on the bytes and don't set the filler bits
+ correctly.
+ */
my_ptrdiff_t const pos=
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
table->record[1][pos]= 0xFF;
@@ -6430,6 +6423,7 @@ static int find_and_fetch_row(TABLE *table, byte *key)
HA_READ_KEY_EXACT)))
{
table->file->print_error(error, MYF(0));
+ table->file->ha_index_end();
DBUG_RETURN(error);
}
@@ -6448,7 +6442,10 @@ static int find_and_fetch_row(TABLE *table, byte *key)
chose the row to change only using a PK or an UNNI.
*/
if (table->key_info->flags & HA_NOSAME)
+ {
+ table->file->ha_index_end();
DBUG_RETURN(0);
+ }
while (record_compare(table))
{
@@ -6465,15 +6462,26 @@ static int find_and_fetch_row(TABLE *table, byte *key)
if ((error= table->file->index_next(table->record[1])))
{
table->file->print_error(error, MYF(0));
+ table->file->ha_index_end();
DBUG_RETURN(error);
}
}
+
+ /*
+ Have to restart the scan to be able to fetch the next row.
+ */
+ table->file->ha_index_end();
}
else
{
- /* Continue until we find the right record or have made a full loop */
int restart_count= 0; // Number of times scanning has restarted from top
- int error= 0;
+ int error;
+
+ /* We don't have a key: search the table using rnd_next() */
+ if ((error= table->file->ha_rnd_init(1)))
+ return error;
+
+ /* Continue until we find the right record or have made a full loop */
do
{
/*
@@ -6499,11 +6507,17 @@ static int find_and_fetch_row(TABLE *table, byte *key)
default:
table->file->print_error(error, MYF(0));
+ table->file->ha_rnd_end();
DBUG_RETURN(error);
}
}
while (restart_count < 2 && record_compare(table));
+ /*
+ Have to restart the scan to be able to fetch the next row.
+ */
+ table->file->ha_rnd_end();
+
DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
DBUG_RETURN(error);
}
@@ -6626,20 +6640,6 @@ int Delete_rows_log_event::do_exec_row(TABLE *table)
{
DBUG_ASSERT(table != NULL);
- if (table->s->keys > 0)
- {
- /* We have a key: search the table using the index */
- if (!table->file->inited)
- if (int error= table->file->ha_index_init(0, FALSE))
- return error;
- }
- else
- {
- /* We doesn't have a key: search the table using rnd_next() */
- if (int error= table->file->ha_rnd_init(1))
- return error;
- }
-
int error= find_and_fetch_row(table, m_key);
if (error)
return error;
@@ -6651,11 +6651,6 @@ int Delete_rows_log_event::do_exec_row(TABLE *table)
*/
error= table->file->ha_delete_row(table->record[0]);
- /*
- Have to restart the scan to be able to fetch the next row.
- */
- table->file->ha_index_or_rnd_end();
-
return error;
}
@@ -6736,17 +6731,6 @@ int Update_rows_log_event::do_before_row_operations(TABLE *table)
if (!m_memory)
return HA_ERR_OUT_OF_MEM;
- if (table->s->keys > 0)
- {
- /* We have a key: search the table using the index */
- if (!table->file->inited)
- error= table->file->ha_index_init(0, FALSE);
- }
- else
- {
- /* We doesn't have a key: search the table using rnd_next() */
- error= table->file->ha_rnd_init(1);
- }
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
diff --git a/sql/log_event.h b/sql/log_event.h
index b24686514e3..cd58dacf147 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1221,9 +1221,6 @@ class Xid_log_event: public Log_event
bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; }
-#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
- static my_bool show_xid;
-#endif
};
/*****************************************************************************
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 5773f0476a9..e3db96be2e7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -79,7 +79,8 @@ 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, bool only_kill_query);
+uint kill_one_thread(THD *thd, ulong id, bool only_kill_query);
+void sql_kill(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);
@@ -92,7 +93,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
do { \
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) >= 0); \
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
- ER_WARN_DEPRECATED, ER(ER_WARN_DEPRECATED), \
+ ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
(Old), (Ver), (New)); \
} while(0)
@@ -177,6 +178,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/* Characters shown for the command in 'show processlist' */
#define PROCESS_LIST_WIDTH 100
+/* Characters shown for the command in 'information_schema.processlist' */
+#define PROCESS_LIST_INFO_WIDTH 65535
/* Time handling defaults */
#define TIMESTAMP_MAX_YEAR 2038
@@ -486,6 +489,7 @@ inline THD *_current_thd(void)
my_bool thd_in_lock_tables(const THD *thd);
my_bool thd_tablespace_op(const THD *thd);
const char *thd_proc_info(THD *thd, const char *info);
+void **thd_ha_data(const THD *thd, const struct handlerton *hton);
/*
External variables
@@ -556,6 +560,7 @@ enum enum_mysql_completiontype {
};
bool begin_trans(THD *thd);
+bool end_active_trans(THD *thd);
int end_trans(THD *thd, enum enum_mysql_completiontype completion);
Item *negate_expression(THD *thd, Item *expr);
@@ -613,6 +618,100 @@ struct Query_cache_query_flags
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/
+/*
+ Error injector Macros to enable easy testing of recovery after failures
+ in various error cases.
+*/
+#ifndef ERROR_INJECT_SUPPORT
+
+#define ERROR_INJECT(x) 0
+#define ERROR_INJECT_ACTION(x,action) 0
+#define ERROR_INJECT_CRASH(x) 0
+#define ERROR_INJECT_VALUE(x) 0
+#define ERROR_INJECT_VALUE_ACTION(x,action) 0
+#define ERROR_INJECT_VALUE_CRASH(x) 0
+#define SET_ERROR_INJECT_VALUE(x)
+
+#else
+
+inline bool check_and_unset_keyword(const char *dbug_str)
+{
+ const char *extra_str= "-d,";
+ char total_str[200];
+ if (_db_strict_keyword_ (dbug_str))
+ {
+ strxmov(total_str, extra_str, dbug_str, NullS);
+ DBUG_SET(total_str);
+ return 1;
+ }
+ return 0;
+}
+
+
+inline bool
+check_and_unset_inject_value(int value)
+{
+ THD *thd= current_thd;
+ if (thd->error_inject_value == (uint)value)
+ {
+ thd->error_inject_value= 0;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ ERROR INJECT MODULE:
+ --------------------
+ These macros are used to insert macros from the application code.
+ The event that activates those error injections can be activated
+ from SQL by using:
+ SET SESSION dbug=+d,code;
+
+ After the error has been injected, the macros will automatically
+ remove the debug code, thus similar to using:
+ SET SESSION dbug=-d,code
+ from SQL.
+
+ ERROR_INJECT_CRASH will inject a crash of the MySQL Server if code
+ is set when macro is called. ERROR_INJECT_CRASH can be used in
+ if-statements, it will always return FALSE unless of course it
+ crashes in which case it doesn't return at all.
+
+ ERROR_INJECT_ACTION will inject the action specified in the action
+ parameter of the macro, before performing the action the code will
+ be removed such that no more events occur. ERROR_INJECT_ACTION
+ can also be used in if-statements and always returns FALSE.
+ ERROR_INJECT can be used in a normal if-statement, where the action
+ part is performed in the if-block. The macro returns TRUE if the
+ error was activated and otherwise returns FALSE. If activated the
+ code is removed.
+
+ Sometimes it is necessary to perform error inject actions as a serie
+ of events. In this case one can use one variable on the THD object.
+ Thus one sets this value by using e.g. SET_ERROR_INJECT_VALUE(100).
+ Then one can later test for it by using ERROR_INJECT_CRASH_VALUE,
+ ERROR_INJECT_ACTION_VALUE and ERROR_INJECT_VALUE. This have the same
+ behaviour as the above described macros except that they use the
+ error inject value instead of a code used by DBUG macros.
+*/
+#define SET_ERROR_INJECT_VALUE(x) \
+ current_thd->error_inject_value= (x)
+#define ERROR_INJECT_CRASH(code) \
+ DBUG_EVALUATE_IF(code, (abort(), 0), 0)
+#define ERROR_INJECT_ACTION(code, action) \
+ (check_and_unset_keyword(code) ? ((action), 0) : 0)
+#define ERROR_INJECT(code) \
+ check_and_unset_keyword(code)
+#define ERROR_INJECT_VALUE(value) \
+ check_and_unset_inject_value(value)
+#define ERROR_INJECT_VALUE_ACTION(value,action) \
+ (check_and_unset_inject_value(value) ? (action) : 0)
+#define ERROR_INJECT_VALUE_CRASH(value) \
+ ERROR_INJECT_VALUE_ACTION(value, (abort(), 0))
+
+#endif
+
uint build_table_path(char *buff, size_t bufflen, const char *db,
const char *table, const char *ext);
void write_bin_log(THD *thd, bool clear_error,
@@ -764,13 +863,6 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
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,
- TABLE_LIST *create_table,
- List<create_field> *extra_fields,
- List<Key> *keys,
- List<Item> *items,
- MYSQL_LOCK **lock,
- TABLEOP_HOOKS *hooks);
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
@@ -908,6 +1000,7 @@ int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
bool mysqld_show_storage_engines(THD *thd);
bool mysqld_show_authors(THD *thd);
+bool mysqld_show_contributors(THD *thd);
bool mysqld_show_privileges(THD *thd);
bool mysqld_show_column_types(THD *thd);
bool mysqld_help (THD *thd, const char *text);
@@ -1090,6 +1183,16 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
bool remove_table_from_cache(THD *thd, const char *db, const char *table,
uint flags);
+#define NORMAL_PART_NAME 0
+#define TEMP_PART_NAME 1
+#define RENAMED_PART_NAME 2
+void create_partition_name(char *out, const char *in1,
+ const char *in2, uint name_variant,
+ bool translate);
+void create_subpartition_name(char *out, const char *in1,
+ const char *in2, const char *in3,
+ uint name_variant);
+
typedef struct st_lock_param_type
{
ulonglong copied;
@@ -1109,14 +1212,94 @@ typedef struct st_lock_param_type
uint key_count;
uint db_options;
uint pack_frm_len;
+ partition_info *part_info;
} ALTER_PARTITION_PARAM_TYPE;
void mem_alloc_error(size_t size);
-#define WFRM_INITIAL_WRITE 1
-#define WFRM_CREATE_HANDLER_FILES 2
+
+enum ddl_log_entry_code
+{
+ /*
+ DDL_LOG_EXECUTE_CODE:
+ This is a code that indicates that this is a log entry to
+ be executed, from this entry a linked list of log entries
+ can be found and executed.
+ DDL_LOG_ENTRY_CODE:
+ An entry to be executed in a linked list from an execute log
+ entry.
+ DDL_IGNORE_LOG_ENTRY_CODE:
+ An entry that is to be ignored
+ */
+ DDL_LOG_EXECUTE_CODE = 'e',
+ DDL_LOG_ENTRY_CODE = 'l',
+ DDL_IGNORE_LOG_ENTRY_CODE = 'i'
+};
+
+enum ddl_log_action_code
+{
+ /*
+ The type of action that a DDL_LOG_ENTRY_CODE entry is to
+ perform.
+ DDL_LOG_DELETE_ACTION:
+ Delete an entity
+ DDL_LOG_RENAME_ACTION:
+ Rename an entity
+ DDL_LOG_REPLACE_ACTION:
+ Rename an entity after removing the previous entry with the
+ new name, that is replace this entry.
+ */
+ DDL_LOG_DELETE_ACTION = 'd',
+ DDL_LOG_RENAME_ACTION = 'r',
+ DDL_LOG_REPLACE_ACTION = 's'
+};
+
+
+typedef struct st_ddl_log_entry
+{
+ const char *name;
+ const char *from_name;
+ const char *handler_name;
+ uint next_entry;
+ uint entry_pos;
+ enum ddl_log_entry_code entry_type;
+ enum ddl_log_action_code action_type;
+ /*
+ Most actions have only one phase. REPLACE does however have two
+ phases. The first phase removes the file with the new name if
+ there was one there before and the second phase renames the
+ old name to the new name.
+ */
+ char phase;
+} DDL_LOG_ENTRY;
+
+typedef struct st_ddl_log_memory_entry
+{
+ uint entry_pos;
+ struct st_ddl_log_memory_entry *next_log_entry;
+ struct st_ddl_log_memory_entry *prev_log_entry;
+ struct st_ddl_log_memory_entry *next_active_log_entry;
+} DDL_LOG_MEMORY_ENTRY;
+
+
+bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
+ DDL_LOG_MEMORY_ENTRY **active_entry);
+bool write_execute_ddl_log_entry(uint first_entry,
+ bool complete,
+ DDL_LOG_MEMORY_ENTRY **active_entry);
+bool deactivate_ddl_log_entry(uint entry_no);
+void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry);
+bool sync_ddl_log();
+void release_ddl_log();
+void execute_ddl_log_recovery();
+bool execute_ddl_log_entry(THD *thd, uint first_entry);
+
+extern pthread_mutex_t LOCK_gdl;
+
+#define WFRM_WRITE_SHADOW 1
+#define WFRM_INSTALL_SHADOW 2
#define WFRM_PACK_FRM 4
bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
-bool abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt);
+int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt);
void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt);
void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table);
@@ -1179,8 +1362,8 @@ bool mysql_manager_submit(void (*action)());
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);
+void print_plan(JOIN* join,uint idx, double record_count, double read_time,
+ double current_read_time, const char *info);
#endif
void mysql_print_status();
/* key.cc */
@@ -1198,10 +1381,13 @@ bool init_errmessage(void);
#endif /* MYSQL_SERVER */
void sql_perror(const char *message);
+
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
void sql_print_error(const char *format, ...);
void sql_print_warning(const char *format, ...);
void sql_print_information(const char *format, ...);
+typedef void (*sql_print_message_func)(const char *format, ...);
+extern sql_print_message_func sql_print_message_handlers[];
/* type of the log table */
#define QUERY_LOG_SLOW 1
@@ -1224,6 +1410,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
/* mysqld.cc */
extern void MYSQLerror(const char*);
+void refresh_status(THD *thd);
/* item_func.cc */
extern bool check_reserved_words(LEX_STRING *name);
@@ -1317,6 +1504,7 @@ extern my_bool locked_in_memory;
extern bool opt_using_transactions, mysqld_embedded;
extern bool using_update_log, opt_large_files, server_id_supplied;
extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log, opt_error_log;
+extern my_bool opt_log_queries_not_using_indexes;
extern bool opt_disable_networking, opt_skip_show_db;
extern my_bool opt_character_set_client_handshake;
extern bool volatile abort_loop, shutdown_in_progress, grant_option;
@@ -1456,15 +1644,16 @@ extern pthread_t signal_thread;
#endif
#ifdef HAVE_OPENSSL
-extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
+extern struct st_VioSSLFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
uint flags, bool *need_reopen);
-/* mysql_lock_tables() flags bits */
+/* mysql_lock_tables() and open_table() flags bits */
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK 0x0001
#define MYSQL_LOCK_IGNORE_FLUSH 0x0002
#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
+#define MYSQL_OPEN_IGNORE_LOCKED_TABLES 0x0008
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
@@ -1754,7 +1943,6 @@ inline int hexchar_to_int(char c)
return -1;
}
-
/*
Some functions that are different in the embedded library and the normal
server
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 73bd0d57eb3..0320b027bc2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -318,7 +318,6 @@ 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;
@@ -344,6 +343,7 @@ static my_bool opt_sync_bdb_logs;
/* Global variables */
bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
+my_bool opt_log_queries_not_using_indexes= 0;
bool opt_error_log= IF_WIN(1,0);
bool opt_disable_networking=0, opt_skip_show_db=0;
my_bool opt_character_set_client_handshake= 1;
@@ -693,6 +693,7 @@ my_bool opt_enable_shared_memory;
HANDLE smem_event_connect_request= 0;
#endif
+#define SSL_VARS_NOT_STATIC
#include "sslopt-vars.h"
#ifdef HAVE_OPENSSL
#include <openssl/crypto.h>
@@ -710,7 +711,7 @@ static void openssl_lock(int, openssl_lock_t *, const char *, int);
static unsigned long openssl_id_function();
#endif
char *des_key_file;
-struct st_VioSSLAcceptorFd *ssl_acceptor_fd;
+struct st_VioSSLFd *ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
@@ -742,6 +743,7 @@ static void clean_up_mutexes(void);
static void wait_for_signal_thread_to_end(void);
static int test_if_case_insensitive(const char *dir_name);
static void create_pid_file();
+static void end_ssl();
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
@@ -862,8 +864,8 @@ 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)
+ /* We skip slave threads & scheduler on this first loop through. */
+ if (tmp->slave_thread || tmp->system_thread == SYSTEM_THREAD_EVENT_SCHEDULER)
continue;
tmp->killed= THD::KILL_CONNECTION;
@@ -882,6 +884,7 @@ static void close_connections(void)
}
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
+ Events::shutdown();
end_slave();
if (thread_count)
@@ -1021,7 +1024,20 @@ void kill_mysql(void)
DBUG_VOID_RETURN;
}
- /* Force server down. kill all connections and threads and exit */
+/*
+ Force server down. Kill all connections and threads and exit
+
+ SYNOPSIS
+ kill_server
+
+ sig_ptr Signal number that caused kill_server to be called.
+
+ NOTE!
+ A signal number of 0 mean that the function was not called
+ from a signal handler and there is thus no signal to block
+ or stop, we just want to kill the server.
+
+*/
#if defined(__NETWARE__)
extern "C" void kill_server(int sig_ptr)
@@ -1042,7 +1058,8 @@ static void __cdecl kill_server(int sig_ptr)
RETURN_FROM_KILL_SERVER;
kill_in_progress=TRUE;
abort_loop=1; // This should be set
- my_sigset(sig,SIG_IGN);
+ if (sig != 0) // 0 is not a valid signal number
+ my_sigset(sig,SIG_IGN);
if (sig == MYSQL_KILL_SIGNAL || sig == 0)
sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
else
@@ -1074,6 +1091,10 @@ static void __cdecl kill_server(int sig_ptr)
pthread_join(select_thread, NULL); // wait for main thread
#endif /* __NETWARE__ */
+#if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
+ my_thread_end();
+#endif
+
pthread_exit(0); /* purecov: deadcode */
#endif /* EMBEDDED_LIBRARY */
@@ -1184,8 +1205,8 @@ void clean_up(bool print_message)
#ifdef HAVE_DLOPEN
udf_free();
#endif
- plugin_free();
}
+ plugin_free();
if (tc_log)
tc_log->close();
xid_cache_free();
@@ -1217,10 +1238,8 @@ void clean_up(bool print_message)
#endif
delete binlog_filter;
delete rpl_filter;
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
-#endif /* HAVE_OPENSSL */
+ end_ssl();
+ vio_end();
#ifdef USE_REGEX
my_regex_end();
#endif
@@ -1294,6 +1313,7 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_user_conn);
+ Events::destroy_mutexes();
#ifdef HAVE_OPENSSL
(void) pthread_mutex_destroy(&LOCK_des_key_file);
#ifndef HAVE_YASSL
@@ -1755,17 +1775,6 @@ void end_thread(THD *thd, bool put_in_cache)
}
-/* Start a cached thread. LOCK_thread_count is locked on entry */
-
-static void start_cached_thread(THD *thd)
-{
- thread_cache.append(thd);
- wake_thread++;
- thread_count++;
- pthread_cond_signal(&COND_thread_cache);
-}
-
-
void flush_thread_cache()
{
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -2648,12 +2657,6 @@ static int init_common_variables(const char *conf_file_name, int argc,
return 1;
}
- if (ha_register_builtin_plugins())
- {
- sql_print_error("Failed to register built-in storage engines.");
- return 1;
- }
-
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
get_options(argc,argv);
@@ -2866,6 +2869,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_server_started,NULL);
sp_cache_init();
+ Events::init_mutexes();
/* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib,
@@ -2979,6 +2983,18 @@ static void init_ssl()
}
+static void end_ssl()
+{
+#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ {
+ free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
+ ssl_acceptor_fd= 0;
+ }
+#endif /* HAVE_OPENSSL */
+}
+
+
static int init_server_components()
{
DBUG_ENTER("init_server_components");
@@ -2999,7 +3015,6 @@ static int init_server_components()
#ifdef HAVE_REPLICATION
init_slave_list();
#endif
- init_events();
/* Setup logs */
@@ -3023,42 +3038,13 @@ static int init_server_components()
}
}
-#ifdef WITH_CSV_STORAGE_ENGINE
- if (opt_bootstrap)
- log_output_options= LOG_FILE;
- else
- logger.init_log_tables();
-
- if (log_output_options & LOG_NONE)
- {
- /*
- Issue a warining if there were specified additional options to the
- log-output along with NONE. Probably this wasn't what user wanted.
- */
- if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
- sql_print_warning("There were other values specified to "
- "log-output besides NONE. Disabling slow "
- "and general logs anyway.");
- logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
- }
- else
+ if (xid_cache_init())
{
- /* fall back to the log files if tables are not present */
- if (have_csv_db == SHOW_OPTION_NO)
- {
- sql_print_error("CSV engine is not present, falling back to the "
- "log files");
- log_output_options= log_output_options & ~LOG_TABLE | LOG_FILE;
- }
-
- logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
- opt_log ? log_output_options:LOG_NONE);
+ sql_print_error("Out of memory");
+ unireg_abort(1);
}
-#else
- logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
- opt_log ? LOG_FILE:LOG_NONE);
-#endif
+ /* need to configure logging before initializing storage engines */
if (opt_update_log)
{
/*
@@ -3126,7 +3112,7 @@ with --log-bin instead.");
}
if (global_system_variables.binlog_format == BINLOG_FORMAT_UNSPEC)
{
-#ifdef HAVE_NDB_BINLOG
+#if defined(HAVE_NDB_BINLOG) && defined(HAVE_ROW_BASED_REPLICATION)
if (opt_bin_log && have_ndbcluster == SHOW_OPTION_YES)
global_system_variables.binlog_format= BINLOG_FORMAT_ROW;
else
@@ -3186,17 +3172,49 @@ server.");
using_update_log=1;
}
- if (xid_cache_init())
- {
- sql_print_error("Out of memory");
- unireg_abort(1);
- }
+ /* We have to initialize the storage engines before CSV logging */
if (ha_init())
{
sql_print_error("Can't init databases");
unireg_abort(1);
}
+#ifdef WITH_CSV_STORAGE_ENGINE
+ if (opt_bootstrap)
+ log_output_options= LOG_FILE;
+ else
+ logger.init_log_tables();
+
+ if (log_output_options & LOG_NONE)
+ {
+ /*
+ Issue a warining if there were specified additional options to the
+ log-output along with NONE. Probably this wasn't what user wanted.
+ */
+ if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
+ sql_print_warning("There were other values specified to "
+ "log-output besides NONE. Disabling slow "
+ "and general logs anyway.");
+ logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
+ }
+ else
+ {
+ /* fall back to the log files if tables are not present */
+ if (have_csv_db == SHOW_OPTION_NO)
+ {
+ sql_print_error("CSV engine is not present, falling back to the "
+ "log files");
+ log_output_options= log_output_options & ~LOG_TABLE | LOG_FILE;
+ }
+
+ logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
+ opt_log ? log_output_options:LOG_NONE);
+ }
+#else
+ logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
+ opt_log ? LOG_FILE:LOG_NONE);
+#endif
+
/*
Check that the default storage engine is actually available.
*/
@@ -3605,6 +3623,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
unireg_abort(1);
}
}
+ execute_ddl_log_recovery();
create_shutdown_thread();
create_maintenance_thread();
@@ -3619,6 +3638,10 @@ we force server id to 2, but this MySQL server will not act as a slave.");
mysqld_server_started= 1;
pthread_cond_signal(&COND_server_started);
+ if (!opt_noacl)
+ {
+ Events::init();
+ }
#if defined(__NT__) || defined(HAVE_SMEM)
handle_connections_methods();
#else
@@ -3656,6 +3679,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ release_ddl_log();
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (Service.IsNT() && start_mode)
Service.Stop();
@@ -3669,7 +3693,6 @@ we force server id to 2, but this MySQL server will not act as a slave.");
clean_up(1);
wait_for_signal_thread_to_end();
clean_up_mutexes();
- shutdown_events();
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(0);
@@ -3927,6 +3950,25 @@ static bool read_init_file(char *file_name)
#ifndef EMBEDDED_LIBRARY
+/*
+ Create new thread to handle incoming connection.
+
+ SYNOPSIS
+ create_new_thread()
+ thd in/out Thread handle of future thread.
+
+ DESCRIPTION
+ This function will create new thread to handle the incoming
+ connection. If there are idle cached threads one will be used.
+ 'thd' will be pushed into 'threads'.
+
+ In single-threaded mode (#define ONE_THREAD) connection will be
+ handled inside this function.
+
+ RETURN VALUE
+ none
+*/
+
static void create_new_thread(THD *thd)
{
DBUG_ENTER("create_new_thread");
@@ -3950,11 +3992,12 @@ static void create_new_thread(THD *thd)
thd->real_id=pthread_self(); // Keep purify happy
/* Start a new thread to handle connection */
+ thread_count++;
+
#ifdef ONE_THREAD
if (test_flags & TEST_NO_THREADS) // For debugging under Linux
{
thread_cache_size=0; // Safety
- thread_count++;
threads.append(thd);
thd->real_id=pthread_self();
(void) pthread_mutex_unlock(&LOCK_thread_count);
@@ -3963,18 +4006,20 @@ static void create_new_thread(THD *thd)
else
#endif
{
+ if (thread_count-delayed_insert_threads > max_used_connections)
+ max_used_connections=thread_count-delayed_insert_threads;
+
if (cached_thread_count > wake_thread)
{
- start_cached_thread(thd);
+ thread_cache.append(thd);
+ wake_thread++;
+ pthread_cond_signal(&COND_thread_cache);
}
else
{
int error;
- thread_count++;
thread_created++;
threads.append(thd);
- if (thread_count-delayed_insert_threads > max_used_connections)
- max_used_connections=thread_count-delayed_insert_threads;
DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
thd->connect_time = time(NULL);
if ((error=pthread_create(&thd->real_id,&connection_attrib,
@@ -4638,7 +4683,7 @@ enum options_mysqld
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
OPT_HAVE_NAMED_PIPE,
- OPT_DO_PSTACK, OPT_EVENT_EXECUTOR, OPT_REPORT_HOST,
+ OPT_DO_PSTACK, OPT_EVENT_SCHEDULER, OPT_REPORT_HOST,
OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
OPT_SHOW_SLAVE_AUTH_INFO,
OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
@@ -4856,14 +4901,6 @@ Disable with --skip-bdb (will save memory).",
{"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
"Tells the master that updates to the given database should not be logged tothe binary log.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
- {"binlog-show-xid", OPT_BINLOG_SHOW_XID,
- "Option used by mysql-test for debugging and testing: "
- "do not display the XID in SHOW BINLOG EVENTS; "
- "may be removed in future versions",
- (gptr*) &Xid_log_event::show_xid, (gptr*) &Xid_log_event::show_xid,
- 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
-#endif
#ifdef HAVE_ROW_BASED_REPLICATION
{"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
"The maximum size of a row-based binary log event in bytes. Rows will be "
@@ -4971,9 +5008,9 @@ Disable with --skip-bdb (will save memory).",
(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},
- {"event-scheduler", OPT_EVENT_EXECUTOR, "Enable/disable the event scheduler.",
- (gptr*) &opt_event_executor, (gptr*) &opt_event_executor, 0, GET_BOOL, NO_ARG,
- 0/*default*/, 0/*min-value*/, 1/*max-value*/, 0, 0, 0},
+ {"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.",
+ (gptr*) &Events::opt_event_scheduler, (gptr*) &Events::opt_event_scheduler, 0, GET_ULONG,
+ REQUIRED_ARG, 2/*default*/, 0/*min-value*/, 2/*max-value*/, 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.",
@@ -5918,7 +5955,7 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
{"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT,
- "Maximum numbrer of prepared statements in the server.",
+ "Maximum number of prepared statements in the server.",
(gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count,
0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0},
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
@@ -6160,23 +6197,6 @@ The minimum value for this variable is 4096.",
{"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.",
- (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.",
- (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.",
- (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 /* HAVE_REPLICATION */
{"table_cache", OPT_TABLE_OPEN_CACHE,
"Deprecated; use --table_open_cache instead.",
(gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG,
@@ -7317,6 +7337,24 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
}
#endif
+ case OPT_EVENT_SCHEDULER:
+ if (!argument)
+ Events::opt_event_scheduler= 2;
+ else
+ {
+ int type;
+ if ((type=find_type(argument, &Events::opt_typelib, 1)) <= 0)
+ {
+ fprintf(stderr,"Unknown option to event-scheduler: %s\n",argument);
+ exit(1);
+ }
+ /*
+ type= 1 2 3 4 5 6
+ (OFF | 0) - (ON | 1) - (2 | SUSPEND)
+ */
+ Events::opt_event_scheduler= (type-1) / 2;
+ }
+ break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
@@ -8062,7 +8100,38 @@ static void create_pid_file()
(void) my_close(file, MYF(0));
}
sql_perror("Can't start server: can't create PID file");
- exit(1);
+ exit(1);
+}
+
+
+/* Clear most status variables */
+void refresh_status(THD *thd)
+{
+ pthread_mutex_lock(&LOCK_status);
+
+ /* 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));
+
+ for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++)
+ {
+ /* Note that SHOW_LONG_NOFLUSH variables are not reset */
+ if (ptr->type == SHOW_LONG)
+ *(ulong*) ptr->value= 0;
+ }
+ /* Reset the counters of all key caches (default and named). */
+ process_key_caches(reset_key_cache_counters);
+ pthread_mutex_unlock(&LOCK_status);
+
+ /*
+ Set max_used_connections to the number of currently open
+ connections. Lock LOCK_thread_count out of LOCK_status to avoid
+ deadlocks. Status reset becomes not atomic, but status data is
+ not exact anyway.
+ */
+ pthread_mutex_lock(&LOCK_thread_count);
+ max_used_connections= thread_count-delayed_insert_threads;
+ pthread_mutex_unlock(&LOCK_thread_count);
}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 9713e4bed44..03164827e8f 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -37,9 +37,6 @@
HFTODO this must be hidden if we don't want client capabilities in
embedded library
*/
-#ifdef __WIN__
-#include <winsock.h>
-#endif
#include <my_global.h>
#include <mysql.h>
#include <mysql_embed.h>
@@ -51,6 +48,12 @@
#include <violite.h>
#include <signal.h>
#include <errno.h>
+#ifdef __WIN__
+#include <winsock.h>
+#endif
+#ifdef __NETWARE__
+#include <sys/select.h>
+#endif
#ifdef EMBEDDED_LIBRARY
#undef MYSQL_SERVER
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 3fddd780171..ffaf3fad6c8 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -450,6 +450,8 @@ public:
/* TRUE if last checked tree->key can be used for ROR-scan */
bool is_ror_scan;
+ /* Number of ranges in the last checked tree->key */
+ uint n_ranges;
};
class TABLE_READ_PLAN;
@@ -4306,7 +4308,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
"building covering ROR-I",
ror_scan_mark, ror_scans_end););
- do {
+ do
+ {
/*
Update changed sorting info:
#covered fields,
@@ -4695,17 +4698,143 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
if (inv)
{
- tree= get_ne_mm_tree(param, cond_func, field,
- func->arguments()[1], func->arguments()[1],
- cmp_type);
- if (tree)
+ if (func->array && func->cmp_type != ROW_RESULT)
{
- Item **arg, **end;
- for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
- arg < end ; arg++)
+ /*
+ We get here for conditions in form "t.key NOT IN (c1, c2, ...)"
+ (where c{i} are constants).
+ Our goal is to produce a SEL_ARG graph that represents intervals:
+
+ ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*)
+
+ where $MIN is either "-inf" or NULL.
+
+ The most straightforward way to handle NOT IN would be to convert
+ it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range
+ optimizer to build SEL_ARG graph from that. However that will cause
+ the range optimizer to use O(N^2) memory (it's a bug, not filed),
+ and people do use big NOT IN lists (see BUG#15872). Also, for big
+ NOT IN lists constructing/using graph (*) does not make the query
+ faster.
+
+ So, we will handle NOT IN manually in the following way:
+ * if the number of entries in the NOT IN list is less then
+ NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*)
+ manually.
+ * Otherwise, we will construct a smaller graph: for
+ "t.key NOT IN (c1,...cN)" we construct a graph representing
+ ($MIN < t.key) OR (cN < t.key) // here sequence of c_i is
+ // ordered.
+
+ A note about partially-covering indexes: for those (e.g. for
+ "a CHAR(10), KEY(a(5))") the handling is correct (albeit not very
+ efficient):
+ Instead of "t.key < c1" we get "t.key <= prefix-val(c1)".
+ Combining the intervals in (*) together, we get:
+ (-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR ...
+ i.e. actually we get intervals combined into one interval:
+ (-inf<=t.key<=+inf). This doesn't make much sense but it doesn't
+ cause any problems.
+ */
+ MEM_ROOT *tmp_root= param->mem_root;
+ param->thd->mem_root= param->old_root;
+ /*
+ Create one Item_type constant object. We'll need it as
+ get_mm_parts only accepts constant values wrapped in Item_Type
+ objects.
+ We create the Item on param->mem_root which points to
+ per-statement mem_root (while thd->mem_root is currently pointing
+ to mem_root local to range optimizer).
+ */
+ Item *value_item= func->array->create_item();
+ param->thd->mem_root= tmp_root;
+
+ if (!value_item)
+ break;
+
+ /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
+ uint i=0;
+ do
+ {
+ func->array->value_to_item(i, value_item);
+ tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+ value_item, cmp_type);
+ if (!tree)
+ break;
+ i++;
+ } while (i < func->array->count && tree->type == SEL_TREE::IMPOSSIBLE);
+
+ if (!tree || tree->type == SEL_TREE::IMPOSSIBLE)
{
- tree= tree_and(param, tree, get_ne_mm_tree(param, cond_func, field,
- *arg, *arg, cmp_type));
+ /* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */
+ tree= NULL;
+ break;
+ }
+#define NOT_IN_IGNORE_THRESHOLD 1000
+ SEL_TREE *tree2;
+ if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
+ {
+ for (; i < func->array->count; i++)
+ {
+ if (func->array->compare_elems(i, i-1))
+ {
+ /* Get a SEL_TREE for "-inf < X < c_i" interval */
+ func->array->value_to_item(i, value_item);
+ tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+ value_item, cmp_type);
+ if (!tree2)
+ {
+ tree= NULL;
+ break;
+ }
+
+ /* Change all intervals to be "c_{i-1} < X < c_i" */
+ for (uint idx= 0; idx < param->keys; idx++)
+ {
+ SEL_ARG *new_interval, *last_val;
+ if (((new_interval= tree2->keys[idx])) &&
+ ((last_val= tree->keys[idx]->last())))
+ {
+ new_interval->min_value= last_val->max_value;
+ new_interval->min_flag= NEAR_MIN;
+ }
+ }
+ /*
+ The following doesn't try to allocate memory so no need to
+ check for NULL.
+ */
+ tree= tree_or(param, tree, tree2);
+ }
+ }
+ }
+ else
+ func->array->value_to_item(func->array->count - 1, value_item);
+
+ if (tree && tree->type != SEL_TREE::IMPOSSIBLE)
+ {
+ /*
+ Get the SEL_TREE for the last "c_last < X < +inf" interval
+ (value_item cotains c_last already)
+ */
+ tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC,
+ value_item, cmp_type);
+ tree= tree_or(param, tree, tree2);
+ }
+ }
+ else
+ {
+ 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));
+ }
}
}
}
@@ -6506,6 +6635,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
param->table->file->primary_key_is_clustered());
param->is_ror_scan= !cpk_scan;
}
+ param->n_ranges= 0;
records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
if (records != HA_POS_ERROR)
@@ -6513,7 +6643,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
param->table->quick_keys.set_bit(key);
param->table->quick_rows[key]=records;
param->table->quick_key_parts[key]=param->max_key_part+1;
-
+ param->table->quick_n_ranges[key]= param->n_ranges;
if (cpk_scan)
param->is_ror_scan= TRUE;
}
@@ -6649,7 +6779,10 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
HA_NOSAME &&
min_key_length == max_key_length &&
!memcmp(param->min_key,param->max_key,min_key_length))
+ {
tmp=1; // Max one record
+ param->n_ranges++;
+ }
else
{
if (param->is_ror_scan)
@@ -6669,6 +6802,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
is_key_scan_ror(param, keynr, key_tree->part + 1)))
param->is_ror_scan= FALSE;
}
+ param->n_ranges++;
if (tmp_min_flag & GEOM_FLAG)
{
@@ -7312,64 +7446,69 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
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
{
- do {
+ /* 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();
- }while (!error && !cpk_quick->row_in_ranges());
- }
- else
- error= quick->get_next();
- if (error)
- DBUG_RETURN(error);
+ if (error)
+ DBUG_RETURN(error);
- quick->file->position(quick->record);
- memcpy(last_rowid, quick->file->ref, head->file->ref_length);
- last_rowid_count= 1;
+ 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++))
+ while (last_rowid_count < quick_selects.elements)
{
- 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);
+ if (!(quick= quick_it++))
+ {
+ quick_it.rewind();
+ quick= quick_it++;
+ }
- /* 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)
+ do
{
- while (!cpk_quick->row_in_ranges())
+ 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)
{
- if ((error= quick->get_next()))
- DBUG_RETURN(error);
+ 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++;
}
- 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);
+ /* 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);
+ } while (error == HA_ERR_RECORD_DELETED);
DBUG_RETURN(error);
}
@@ -7398,41 +7537,44 @@ int 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 */
+ 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);
+ 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);
- }
+ /* 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);
+ 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;
+ tmp= cur_rowid;
+ cur_rowid= prev_rowid;
+ prev_rowid= tmp;
- error= head->file->rnd_pos(quick->record, prev_rowid);
+ error= head->file->rnd_pos(quick->record, prev_rowid);
+ } while (error == HA_ERR_RECORD_DELETED);
DBUG_RETURN(error);
}
diff --git a/sql/partition_element.h b/sql/partition_element.h
index d20715d2408..13693934c0f 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -36,6 +36,8 @@ enum partition_state {
PART_IS_ADDED= 8
};
+struct st_ddl_log_memory_entry;
+
class partition_element :public Sql_alloc {
public:
List<partition_element> subpartitions;
@@ -44,6 +46,7 @@ public:
ulonglong part_min_rows;
char *partition_name;
char *tablespace_name;
+ struct st_ddl_log_memory_entry *log_entry;
longlong range_value;
char* part_comment;
char* data_file_name;
@@ -55,7 +58,8 @@ public:
partition_element()
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
- tablespace_name(NULL), range_value(0), part_comment(NULL),
+ tablespace_name(NULL), log_entry(NULL),
+ range_value(0), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL),
engine_type(NULL),part_state(PART_NORMAL),
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE)
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index a62b58a04ac..289296fcac3 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -21,9 +21,10 @@
#endif
#include "mysql_priv.h"
-#include "ha_partition.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
+#include "ha_partition.h"
+
partition_info *partition_info::get_clone()
{
@@ -88,10 +89,10 @@ partition_info *partition_info::get_clone()
The external routine needing this code is check_partition_info
*/
-#define MAX_PART_NAME_SIZE 16
+#define MAX_PART_NAME_SIZE 8
char *partition_info::create_default_partition_names(uint part_no, uint no_parts,
- uint start_no, bool is_subpart)
+ uint start_no)
{
char *ptr= sql_calloc(no_parts*MAX_PART_NAME_SIZE);
char *move_ptr= ptr;
@@ -102,10 +103,7 @@ char *partition_info::create_default_partition_names(uint part_no, uint no_parts
{
do
{
- if (is_subpart)
- my_sprintf(move_ptr, (move_ptr,"p%usp%u", part_no, (start_no + i)));
- else
- my_sprintf(move_ptr, (move_ptr,"p%u", (start_no + i)));
+ my_sprintf(move_ptr, (move_ptr,"p%u", (start_no + i)));
move_ptr+=MAX_PART_NAME_SIZE;
} while (++i < no_parts);
}
@@ -118,6 +116,36 @@ char *partition_info::create_default_partition_names(uint part_no, uint no_parts
/*
+ Create a unique name for the subpartition as part_name'sp''subpart_no'
+ SYNOPSIS
+ create_subpartition_name()
+ subpart_no Number of subpartition
+ part_name Name of partition
+ RETURN VALUES
+ >0 A reference to the created name string
+ 0 Memory allocation error
+*/
+
+char *partition_info::create_subpartition_name(uint subpart_no,
+ const char *part_name)
+{
+ uint size_alloc= strlen(part_name) + MAX_PART_NAME_SIZE;
+ char *ptr= sql_calloc(size_alloc);
+ DBUG_ENTER("create_subpartition_name");
+
+ if (likely(ptr != NULL))
+ {
+ my_sprintf(ptr, (ptr, "%ssp%u", part_name, subpart_no));
+ }
+ else
+ {
+ mem_alloc_error(size_alloc);
+ }
+ DBUG_RETURN(ptr);
+}
+
+
+/*
Set up all the default partitions not set-up by the user in the SQL
statement. Also perform a number of checks that the user hasn't tried
to use default values where no defaults exists.
@@ -167,8 +195,7 @@ bool partition_info::set_up_default_partitions(handler *file, ulonglong max_rows
goto end;
}
if (unlikely((!(default_name= create_default_partition_names(0, no_parts,
- start_no,
- FALSE)))))
+ start_no)))))
goto end;
i= 0;
do
@@ -238,18 +265,17 @@ bool partition_info::set_up_default_subpartitions(handler *file,
{
part_elem= part_it++;
j= 0;
- name_ptr= create_default_partition_names(i, no_subparts, (uint)0, TRUE);
- if (unlikely(!name_ptr))
- goto end;
do
{
partition_element *subpart_elem= new partition_element();
if (likely(subpart_elem != 0 &&
(!part_elem->subpartitions.push_back(subpart_elem))))
{
+ char *ptr= create_subpartition_name(j, part_elem->partition_name);
+ if (!ptr)
+ goto end;
subpart_elem->engine_type= default_engine_type;
- subpart_elem->partition_name= name_ptr;
- name_ptr+= MAX_PART_NAME_SIZE;
+ subpart_elem->partition_name= ptr;
}
else
{
@@ -406,18 +432,22 @@ char *partition_info::has_unique_names()
bool partition_info::check_engine_mix(handlerton **engine_array, uint no_parts)
{
uint i= 0;
- bool result= FALSE;
DBUG_ENTER("partition_info::check_engine_mix");
do
{
if (engine_array[i] != engine_array[0])
{
- result= TRUE;
- break;
+ my_error(ER_MIX_HANDLER_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
}
} while (++i < no_parts);
- DBUG_RETURN(result);
+ if (engine_array[0] == &myisammrg_hton)
+ {
+ my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
}
@@ -743,10 +773,7 @@ bool partition_info::check_partition_info(handlerton **eng_type,
} while (++i < no_parts);
}
if (unlikely(partition_info::check_engine_mix(engine_array, part_count)))
- {
- my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
- }
if (eng_type)
*eng_type= (handlerton*)engine_array[0];
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 664c8834b0b..af43f7b7933 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -28,7 +28,7 @@ typedef int (*get_part_id_func)(partition_info *part_info,
longlong *func_value);
typedef uint32 (*get_subpart_id_func)(partition_info *part_info);
-
+struct st_ddl_log_memory_entry;
class partition_info : public Sql_alloc
{
@@ -76,7 +76,11 @@ public:
Item *subpart_expr;
Item *item_free_list;
-
+
+ struct st_ddl_log_memory_entry *first_log_entry;
+ struct st_ddl_log_memory_entry *exec_log_entry;
+ struct st_ddl_log_memory_entry *frm_log_entry;
+
/*
A bitmap of partitions used by the current query.
Usage pattern:
@@ -180,6 +184,7 @@ public:
bool list_of_subpart_fields;
bool linear_hash_ind;
bool fixed;
+ bool is_auto_partitioned;
bool from_openfrm;
bool has_null_value;
uint has_null_part_id;
@@ -191,6 +196,7 @@ public:
part_field_array(NULL), subpart_field_array(NULL),
full_part_field_array(NULL),
part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
+ first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
list_array(NULL),
part_info_string(NULL),
part_func_string(NULL), subpart_func_string(NULL),
@@ -214,6 +220,7 @@ public:
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
linear_hash_ind(FALSE),
fixed(FALSE),
+ is_auto_partitioned(FALSE),
from_openfrm(FALSE),
has_null_value(FALSE),
has_null_part_id(0)
@@ -256,7 +263,8 @@ private:
uint start_no);
bool set_up_default_subpartitions(handler *file, ulonglong max_rows);
char *create_default_partition_names(uint part_no, uint no_parts,
- uint start_no, bool is_subpart);
+ uint start_no);
+ char *create_subpartition_name(uint subpart_no, const char *part_name);
bool has_unique_name(partition_element *element);
};
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index e207a0bf633..66e2aa1c31c 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -61,12 +61,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
static int init_failsafe_rpl_thread(THD* thd)
{
DBUG_ENTER("init_failsafe_rpl_thread");
+ thd->system_thread = SYSTEM_THREAD_DELAYED_INSERT;
/*
thd->bootstrap is to report errors barely to stderr; if this code is
enable again one day, one should check if bootstrap is still needed (maybe
this thread has no other error reporting method).
*/
- thd->system_thread = thd->bootstrap = 1;
+ thd->bootstrap = 1;
thd->security_ctx->skip_grants();
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
@@ -861,7 +862,8 @@ bool load_master_data(THD* thd)
if (!rpl_filter->db_ok(db) ||
!rpl_filter->db_ok_with_wild_table(db) ||
- !strcmp(db,"mysql"))
+ !strcmp(db,"mysql") ||
+ is_schema_db(db))
{
*cur_table_res = 0;
continue;
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index cacae1aa4c2..99606353080 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -309,15 +309,14 @@ typedef struct st_relay_log_info
void cleanup_context(THD *, bool);
void clear_tables_to_lock() {
- TABLE_LIST *ptr= tables_to_lock;
- while (ptr)
+ while (tables_to_lock)
{
- char *to_free= reinterpret_cast<char*>(ptr);
- ptr= ptr->next_global;
+ char *to_free= reinterpret_cast<gptr>(tables_to_lock);
+ tables_to_lock= tables_to_lock->next_global;
+ tables_to_lock_count--;
my_free(to_free, MYF(MY_WME));
}
- tables_to_lock= 0;
- tables_to_lock_count= 0;
+ DBUG_ASSERT(tables_to_lock == NULL && tables_to_lock_count == 0);
}
time_t unsafe_to_stop_at;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 59e0c7b6ff7..242fe0f6068 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -56,6 +56,8 @@
#include <thr_alarm.h>
#include <myisam.h>
+#include "event_scheduler.h"
+
/* WITH_BERKELEY_STORAGE_ENGINE */
extern bool berkeley_shared_data;
extern ulong berkeley_max_lock, berkeley_log_buffer_size;
@@ -106,7 +108,6 @@ extern ulong ndb_report_thresh_binlog_mem_usage;
-extern my_bool event_executor_running_global_var;
static HASH system_variable_hash;
const char *bool_type_names[]= { "OFF", "ON", NullS };
@@ -162,6 +163,7 @@ void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
static byte *get_prepared_stmt_count(THD *thd);
+static byte *get_tmpdir(THD *thd);
/*
Variable definition list
@@ -184,6 +186,7 @@ sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset",
sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges",
&sp_automatic_privileges);
+sys_var_const_str sys_basedir("basedir", mysql_home);
sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
&binlog_cache_size);
sys_var_thd_binlog_format sys_binlog_format("binlog_format",
@@ -209,6 +212,7 @@ 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_const_str sys_datadir("datadir", mysql_real_data_home);
#ifndef DBUG_OFF
sys_var_thd_dbug sys_dbug("debug");
#endif
@@ -222,9 +226,8 @@ sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout",
&delayed_insert_timeout);
sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size",
&delayed_queue_size);
-sys_var_event_executor sys_event_executor("event_scheduler",
- (my_bool *)
- &event_executor_running_global_var);
+
+sys_var_event_scheduler sys_event_scheduler("event_scheduler");
sys_var_long_ptr sys_expire_logs_days("expire_logs_days",
&expire_logs_days);
sys_var_bool_ptr sys_flush("flush", &myisam_flush);
@@ -262,6 +265,9 @@ sys_trust_routine_creators("log_bin_trust_routine_creators",
sys_var_bool_ptr
sys_trust_function_creators("log_bin_trust_function_creators",
&trust_function_creators);
+sys_var_bool_ptr
+ sys_log_queries_not_using_indexes("log_queries_not_using_indexes",
+ &opt_log_queries_not_using_indexes);
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);
@@ -389,6 +395,7 @@ sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size",
sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size",
&SV::query_prealloc_size,
0, fix_thd_mem_root);
+sys_var_readonly sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size",
&SV::trans_alloc_block_size,
0, fix_trans_mem_root);
@@ -425,6 +432,21 @@ 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);
+#ifdef HAVE_OPENSSL
+extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
+ *opt_ssl_key;
+sys_var_const_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca);
+sys_var_const_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath);
+sys_var_const_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert);
+sys_var_const_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
+sys_var_const_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key);
+#else
+sys_var_const_str sys_ssl_ca("ssl_ca", NULL);
+sys_var_const_str sys_ssl_capath("ssl_capath", NULL);
+sys_var_const_str sys_ssl_cert("ssl_cert", NULL);
+sys_var_const_str sys_ssl_cipher("ssl_cipher", NULL);
+sys_var_const_str sys_ssl_key("ssl_key", NULL);
+#endif
sys_var_thd_enum
sys_updatable_views_with_limit("updatable_views_with_limit",
&SV::updatable_views_with_limit,
@@ -436,16 +458,10 @@ sys_var_thd_storage_engine sys_storage_engine("storage_engine",
&SV::table_type);
#ifdef HAVE_REPLICATION
sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period);
-sys_var_thd_ulong sys_sync_replication("sync_replication",
- &SV::sync_replication);
-sys_var_thd_ulong sys_sync_replication_slave_id(
- "sync_replication_slave_id",
- &SV::sync_replication_slave_id);
-sys_var_thd_ulong sys_sync_replication_timeout(
- "sync_replication_timeout",
- &SV::sync_replication_timeout);
#endif
sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm);
+sys_var_const_str sys_system_time_zone("system_time_zone",
+ system_time_zone);
sys_var_long_ptr sys_table_def_size("table_definition_cache",
&table_def_size);
sys_var_long_ptr sys_table_cache_size("table_open_cache",
@@ -463,6 +479,13 @@ 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_const_str sys_version("version", server_version);
+sys_var_const_str sys_version_comment("version_comment",
+ MYSQL_COMPILATION_COMMENT);
+sys_var_const_str sys_version_compile_machine("version_compile_machine",
+ MACHINE_TYPE);
+sys_var_const_str sys_version_compile_os("version_compile_os",
+ SYSTEM_TYPE);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
@@ -630,7 +653,6 @@ sys_var_thd_time_zone sys_time_zone("time_zone");
/* Read only variables */
-sys_var_const_str sys_os("version_compile_os", SYSTEM_TYPE);
sys_var_have_variable sys_have_archive_db("have_archive", &have_archive_db);
sys_var_have_variable sys_have_berkeley_db("have_bdb", &have_berkeley_db);
sys_var_have_variable sys_have_blackhole_db("have_blackhole_engine",
@@ -638,7 +660,7 @@ sys_var_have_variable sys_have_blackhole_db("have_blackhole_engine",
sys_var_have_variable sys_have_compress("have_compress", &have_compress);
sys_var_have_variable sys_have_crypt("have_crypt", &have_crypt);
sys_var_have_variable sys_have_csv_db("have_csv", &have_csv_db);
-sys_var_have_variable sys_have_dlopen("have_dlopen", &have_dlopen);
+sys_var_have_variable sys_have_dlopen("have_dynamic_loading", &have_dlopen);
sys_var_have_variable sys_have_example_db("have_example_engine",
&have_example_db);
sys_var_have_variable sys_have_federated_db("have_federated_engine",
@@ -696,7 +718,6 @@ static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff)
}
#endif /* HAVE_REPLICATION */
-
/*
Variables shown by SHOW variables in alphabetical order
*/
@@ -706,7 +727,7 @@ SHOW_VAR init_vars[]= {
{"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},
+ {sys_basedir.name, (char*) &sys_basedir, SHOW_SYS},
{"bdb_cache_parts", (char*) &berkeley_cache_parts, SHOW_LONG},
{"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONGLONG},
{"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR},
@@ -733,7 +754,7 @@ SHOW_VAR init_vars[]= {
{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},
+ {sys_datadir.name, (char*) &sys_datadir, SHOW_SYS},
{sys_date_format.name, (char*) &sys_date_format, SHOW_SYS},
{sys_datetime_format.name, (char*) &sys_datetime_format, SHOW_SYS},
#ifndef DBUG_OFF
@@ -747,7 +768,7 @@ SHOW_VAR init_vars[]= {
{sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
{sys_engine_condition_pushdown.name,
(char*) &sys_engine_condition_pushdown, SHOW_SYS},
- {sys_event_executor.name, (char*) &sys_event_executor, SHOW_SYS},
+ {sys_event_scheduler.name, (char*) &sys_event_scheduler, 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},
@@ -833,6 +854,8 @@ SHOW_VAR init_vars[]= {
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
{sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS},
{"log_error", (char*) log_error_file, SHOW_CHAR},
+ {sys_log_queries_not_using_indexes.name,
+ (char*) &sys_log_queries_not_using_indexes, SHOW_SYS},
#ifdef HAVE_REPLICATION
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
#endif
@@ -910,9 +933,9 @@ SHOW_VAR init_vars[]= {
SHOW_SYS},
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR},
- {sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
+ {sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},
@@ -957,20 +980,21 @@ SHOW_VAR init_vars[]= {
#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR},
#endif
- {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
+ {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
+ {sys_big_selects.name, (char*) &sys_big_selects, SHOW_SYS},
{sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS},
- {"sql_notes", (char*) &sys_sql_notes, SHOW_BOOL},
- {"sql_warnings", (char*) &sys_sql_warnings, SHOW_BOOL},
+ {"sql_notes", (char*) &sys_sql_notes, SHOW_SYS},
+ {"sql_warnings", (char*) &sys_sql_warnings, SHOW_SYS},
+ {sys_ssl_ca.name, (char*) &sys_ssl_ca, SHOW_SYS},
+ {sys_ssl_capath.name, (char*) &sys_ssl_capath, SHOW_SYS},
+ {sys_ssl_cert.name, (char*) &sys_ssl_cert, SHOW_SYS},
+ {sys_ssl_cipher.name, (char*) &sys_ssl_cipher, SHOW_SYS},
+ {sys_ssl_key.name, (char*) &sys_ssl_key, SHOW_SYS},
{sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS},
#ifdef HAVE_REPLICATION
{sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS},
#endif
{sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS},
-#ifdef HAVE_REPLICATION
- {sys_sync_replication.name, (char*) &sys_sync_replication, SHOW_SYS},
- {sys_sync_replication_slave_id.name, (char*) &sys_sync_replication_slave_id,SHOW_SYS},
- {sys_sync_replication_timeout.name, (char*) &sys_sync_replication_timeout,SHOW_SYS},
-#endif
#ifdef HAVE_TZNAME
{"system_time_zone", system_time_zone, SHOW_CHAR},
#endif
@@ -987,17 +1011,18 @@ SHOW_VAR init_vars[]= {
{"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_tmpdir.name, (char*) &sys_tmpdir, SHOW_SYS},
{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},
- {"version_comment", (char*) MYSQL_COMPILATION_COMMENT, SHOW_CHAR},
- {"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR},
- {sys_os.name, (char*) &sys_os, SHOW_SYS},
+ {sys_version.name, (char*) &sys_version, SHOW_SYS},
+ {sys_version_comment.name, (char*) &sys_version_comment, SHOW_SYS},
+ {sys_version_compile_machine.name, (char*) &sys_version_compile_machine,
+ SHOW_SYS},
+ {sys_version_compile_os.name, (char*) &sys_version_compile_os, SHOW_SYS},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG}
};
@@ -1273,12 +1298,14 @@ bool sys_var_thd_binlog_format::is_readonly() const
And this test will also prevent switching from RBR to RBR (a no-op which
should not happen too often).
*/
+#ifdef HAVE_ROW_BASED_REPLICATION
if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) &&
thd->temporary_tables)
{
my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
return 1;
}
+#endif /*HAVE_ROW_BASED_REPLICATION*/
/*
if in a stored function, it's too late to change mode
*/
@@ -1302,7 +1329,9 @@ bool sys_var_thd_binlog_format::is_readonly() const
void fix_binlog_format_after_update(THD *thd, enum_var_type type)
{
+#ifdef HAVE_ROW_BASED_REPLICATION
thd->reset_current_stmt_binlog_row_based();
+#endif /*HAVE_ROW_BASED_REPLICATION*/
}
static void fix_max_binlog_size(THD *thd, enum_var_type type)
@@ -2854,6 +2883,31 @@ static byte *get_prepared_stmt_count(THD *thd)
return (byte*) &thd->sys_var_tmp.ulong_value;
}
+
+/*
+ Get the tmpdir that was specified or chosen by default
+
+ SYNOPSIS
+ get_tmpdir()
+ thd thread handle
+
+ DESCRIPTION
+ This is necessary because if the user does not specify a temporary
+ directory via the command line, one is chosen based on the environment
+ or system defaults. But we can't just always use mysql_tmpdir, because
+ that is actually a call to my_tmpdir() which cycles among possible
+ temporary directories.
+
+ RETURN VALUES
+ ptr pointer to NUL-terminated string
+ */
+static byte *get_tmpdir(THD *thd)
+{
+ if (opt_mysql_tmpdir)
+ return (byte *)opt_mysql_tmpdir;
+ return (byte*)mysql_tmpdir;
+}
+
/****************************************************************************
Main handling of variables:
- Initialisation
@@ -3416,9 +3470,9 @@ ulong fix_sql_mode(ulong sql_mode)
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MYSQL40)
- sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
+ sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
if (sql_mode & MODE_MYSQL323)
- sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
+ sql_mode|= 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 |
@@ -3578,6 +3632,69 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
return (byte*) thd->strdup(buf);
}
+
+/*
+ The update method of the global variable event_scheduler.
+ If event_scheduler is switched from 0 to 1 then the scheduler main
+ thread is resumed and if from 1 to 0 the scheduler thread is suspended
+
+ SYNOPSIS
+ sys_var_event_scheduler::update()
+ thd Thread context (unused)
+ var The new value
+
+ Returns
+ FALSE OK
+ TRUE Error
+*/
+
+bool
+sys_var_event_scheduler::update(THD *thd, set_var *var)
+{
+ enum Event_scheduler::enum_error_code res;
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+ /* here start the thread if not running. */
+ DBUG_ENTER("sys_var_event_scheduler::update");
+
+ DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
+ if (!scheduler->initialized())
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=0");
+ DBUG_RETURN(true);
+ }
+
+ if (var->save_result.ulonglong_value < 1 ||
+ var->save_result.ulonglong_value > 2)
+ {
+ char buf[64];
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "event_scheduler",
+ llstr(var->save_result.ulonglong_value, buf));
+ DBUG_RETURN(true);
+ }
+ if ((res= scheduler->suspend_or_resume(var->save_result.ulonglong_value == 1?
+ Event_scheduler::RESUME :
+ Event_scheduler::SUSPEND)))
+ my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), (uint) res);
+ DBUG_RETURN((bool) res);
+}
+
+
+byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ Event_scheduler *scheduler= Event_scheduler::get_instance();
+
+ if (!scheduler->initialized())
+ thd->sys_var_tmp.long_value= 0;
+ else if (scheduler->get_state() == Event_scheduler::RUNNING)
+ thd->sys_var_tmp.long_value= 1;
+ else
+ thd->sys_var_tmp.long_value= 2;
+
+ return (byte*) &thd->sys_var_tmp;
+}
+
+
/****************************************************************************
Used templates
****************************************************************************/
diff --git a/sql/set_var.h b/sql/set_var.h
index 8076f10bb0a..1049b154d47 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -231,6 +231,35 @@ public:
};
+class sys_var_const_str_ptr :public sys_var
+{
+public:
+ char **value; // Pointer to const value
+ sys_var_const_str_ptr(const char *name_arg, char **value_arg)
+ :sys_var(name_arg),value(value_arg)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return 1;
+ }
+ bool update(THD *thd, set_var *var)
+ {
+ return 1;
+ }
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ {
+ return (byte*) *value;
+ }
+ bool check_update_type(Item_result type)
+ {
+ return 1;
+ }
+ bool check_default(enum_var_type type) { return 1; }
+ bool is_readonly() const { return 1; }
+};
+
+
class sys_var_enum :public sys_var
{
uint *value;
@@ -842,13 +871,14 @@ public:
};
-class sys_var_event_executor :public sys_var_bool_ptr
+class sys_var_event_scheduler :public sys_var_long_ptr
{
/* We need a derived class only to have a warn_deprecated() */
public:
- sys_var_event_executor(const char *name_arg, my_bool *value_arg) :
- sys_var_bool_ptr(name_arg, value_arg) {};
+ sys_var_event_scheduler(const char *name_arg) :
+ sys_var_long_ptr(name_arg, NULL, NULL) {};
bool update(THD *thd, set_var *var);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
extern void fix_binlog_format_after_update(THD *thd, enum_var_type type);
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 8fe93cb99f3..58dc107900a 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -2978,52 +2978,52 @@ ER_UDF_EXISTS
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 %s)"
- jps "shared library '%-.64s' ‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %s)",
- est "Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %s)"
- fre "Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %s)"
- ger "Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %s)"
- 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 %s)"
- rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %s)"
- serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %s)"
- 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 %s)"
-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 symbol '%-.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' Õ Â¦Â̦ÏÔÅæ"
+ cze "Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %-.128s)"
+ dan "Kan ikke åbne delt bibliotek '%-.64s' (errno: %d %-.128s)"
+ nla "Kan shared library '%-.64s' niet openen (Errcode: %d %-.128s)"
+ eng "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ jps "shared library '%-.64s' ‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %-.128s)",
+ est "Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %-.128s)"
+ fre "Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %-.128s)"
+ ger "Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %-.128s)"
+ greek "Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.64s' (êùäéêüò ëÜèïõò: %d %-.128s)"
+ hun "A(z) '%-.64s' megosztott konyvtar nem hasznalhato (hibakod: %d %-.128s)"
+ ita "Impossibile aprire la libreria condivisa '%-.64s' (errno: %d %-.128s)"
+ jpn "shared library '%-.64s' ¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d %-.128s)"
+ kor "'%-.64s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿­¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %-.128s)"
+ nor "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ norwegian-ny "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ pol "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ por "Não pode abrir biblioteca compartilhada '%-.64s' (erro no. %d '%-.128s')"
+ rum "Nu pot deschide libraria shared '%-.64s' (Eroare: %d %-.128s)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %-.128s)"
+ serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %-.128s)"
+ slo "Nemô¾em otvori» zdieµanú kni¾nicu '%-.64s' (chybový kód: %d %-.128s)"
+ spa "No puedo abrir libraria conjugada '%-.64s' (errno: %d %-.128s)"
+ swe "Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %-.128s)"
+ ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %-.128s)"
+ER_CANT_FIND_DL_ENTRY
+ cze "Nemohu naj-Bít funkci '%-.128s' v knihovnì"
+ dan "Kan ikke finde funktionen '%-.128s' i bibliotek"
+ nla "Kan functie '%-.128s' niet in library vinden"
+ eng "Can't find symbol '%-.128s' in library"
+ jps "function '%-.128s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ",
+ est "Ei leia funktsiooni '%-.128s' antud teegis"
+ fre "Impossible de trouver la fonction '%-.128s' dans la bibliothèque"
+ ger "Kann Funktion '%-.128s' in der Library nicht finden"
+ greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.128s' óôçí âéâëéïèÞêç"
+ hun "A(z) '%-.128s' fuggveny nem talalhato a konyvtarban"
+ ita "Impossibile trovare la funzione '%-.128s' nella libreria"
+ jpn "function '%-.128s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó"
+ kor "¶óÀ̹ö·¯¸®¿¡¼­ '%-.128s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù."
+ por "Não pode encontrar a função '%-.128s' na biblioteca"
+ rum "Nu pot gasi functia '%-.128s' in libraria"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÓÉÍ×ÏÌ '%-.128s' × ÂÉÂÌÉÏÔÅËÅ"
+ serbian "Ne mogu da pronadjem funkciju '%-.128s' u biblioteci"
+ slo "Nemô¾em nájs» funkciu '%-.128s' v kni¾nici"
+ spa "No puedo encontrar función '%-.128s' en libraria"
+ swe "Hittar inte funktionen '%-.128s' in det dynamiska biblioteket"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.128s' Õ Â¦Â̦ÏÔÅæ"
ER_FUNCTION_NOT_DEFINED
cze "Funkce '%-.64s' nen-Bí definována"
dan "Funktionen '%-.64s' er ikke defineret"
@@ -5042,7 +5042,7 @@ ER_OPTION_PREVENTS_STATEMENT
ger "Der MySQL-Server läuft mit der Option %s und kann diese Anweisung deswegen nicht ausführen"
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"
+ swe "MySQL är startad med %s. Pga av detta kan du inte använda detta kommando"
ER_DUPLICATED_VALUE_IN_TYPE
eng "Column '%-.100s' has duplicated value '%-.64s' in %s"
ger "Feld '%-.100s' hat doppelten Wert '%-.64s' in %s"
@@ -5472,7 +5472,7 @@ ER_SP_DUP_HANDLER 42000
eng "Duplicate handler declared in the same block"
ger "Doppelter Handler im selben Block deklariert"
ER_SP_NOT_VAR_ARG 42000
- eng "OUT or INOUT argument %d for routine %s is not a variable"
+ eng "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger"
ger "OUT- oder INOUT-Argument %d für Routine %s ist keine Variable"
ER_SP_NO_RETSET 0A000
eng "Not allowed to return a result set from a %s"
@@ -5602,6 +5602,22 @@ ER_SP_RECURSION_LIMIT
ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten"
ER_SP_PROC_TABLE_CORRUPT
eng "Failed to load routine %-.64s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
+ER_SP_WRONG_NAME 42000
+ eng "Incorrect routine name '%-.64s'"
+ER_TABLE_NEEDS_UPGRADE
+ eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
+ER_SP_NO_AGGREGATE 42000
+ eng "AGGREGATE is not supported for stored functions"
+ER_MAX_PREPARED_STMT_COUNT_REACHED 42000
+ eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)"
+ER_VIEW_RECURSIVE
+ eng "`%-.64s`.`%-.64s` contains view recursion"
+ER_NON_GROUPING_FIELD_USED 42000
+ eng "non-grouping field '%-.64s' is used in %-.64s clause"
+ER_TABLE_CANT_HANDLE_SPKEYS
+ eng "The used table type doesn't support SPATIAL indexes"
+ER_ILLEGAL_HA_CREATE_OPTION
+ eng "Table storage engine '%-.64s' does not support the create option '%.64s'"
ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%-.64s PARTITIONING requires definition of VALUES %-.64s for each partition"
swe "%-.64s PARTITIONering kräver definition av VALUES %-.64s för varje partition"
@@ -5798,26 +5814,16 @@ ER_EVENT_DATA_TOO_LONG
ER_DROP_INDEX_FK
eng "Cannot drop index '%-.64s': needed in a foreign key constraint"
ger "Kann Index '%-.64s' nicht löschen: wird für einen Fremdschlüssel benötigt"
+ER_WARN_DEPRECATED_SYNTAX
+ eng "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead."
ER_CANT_WRITE_LOCK_LOG_TABLE
eng "You can't write-lock a log table. Only read access is possible."
ER_CANT_READ_LOCK_LOG_TABLE
eng "You can't use usual read lock with log tables. Try READ LOCAL instead."
-ER_SP_WRONG_NAME 42000
- eng "Incorrect routine name '%-.64s'"
ER_FOREIGN_DUPLICATE_KEY 23000 S1009
eng "Upholding foreign key constraints for table '%.64s', entry '%-.64s', key %d would lead to a duplicate entry"
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
eng "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use scripts/mysql_fix_privilege_tables"
-ER_TABLE_NEEDS_UPGRADE
- eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
-ER_ILLEGAL_HA_CREATE_OPTION
- eng "Table storage engine '%-.64s' does not support the create option '%.64s'"
-ER_CANT_CHANGE_TX_ISOLATION 25001
- eng "Transaction isolation level can't be changed while a transaction is in progress"
-ER_WARN_DEPRECATED
- eng "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead."
-ER_SP_NO_AGGREGATE 42000
- eng "AGGREGATE is not supported for stored functions"
ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
eng "Cannot switch out of the row-based binary log format when the session has open temporary tables"
ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
@@ -5829,11 +5835,22 @@ ER_PARTITION_NO_TEMPORARY
ER_PARTITION_FUNCTION_IS_NOT_ALLOWED
eng "This partition function is not allowed"
swe "Denna partitioneringsfunktion är inte tillåten"
+ER_DDL_LOG_ERROR
+ eng "Error in DDL log"
ER_NULL_IN_VALUES_LESS_THAN
eng "Not allowed to use NULL value in VALUES LESS THAN"
swe "Det är inte tillåtet att använda NULL-värden i VALUES LESS THAN"
ER_WRONG_PARTITION_NAME
eng "Incorrect partition name"
swe "Felaktigt partitionsnamn"
-ER_MAX_PREPARED_STMT_COUNT_REACHED 42000
- eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)"
+ER_CANT_CHANGE_TX_ISOLATION 25001
+ eng "Transaction isolation level can't be changed while a transaction is in progress"
+ER_DUP_ENTRY_AUTOINCREMENT_CASE
+ eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.64s' for key '%-.64s'"
+ER_EVENT_MODIFY_QUEUE_ERROR
+ eng "Internal scheduler error %d"
+ER_EVENT_SET_VAR_ERROR
+ eng "Error during starting/stopping of the scheduler. Error code %u"
+ER_PARTITION_MERGE_ERROR
+ eng "MyISAM Merge handler cannot be used in partitioned tables"
+ swe "MyISAM Merge kan inte anändas i en partitionerad tabell"
diff --git a/sql/sp.cc b/sql/sp.cc
index 7fc388860d1..0e81e627f71 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -268,7 +268,6 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
static int
db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
{
- extern int MYSQLparse(void *thd);
TABLE *table;
const char *params, *returns, *body;
int ret;
@@ -409,15 +408,13 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
ulong old_sql_mode= thd->variables.sql_mode;
ha_rows old_select_limit= thd->variables.select_limit;
sp_rcontext *old_spcont= thd->spcont;
-
+
char definer_user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder,
- USERNAME_LENGTH);
+ LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH };
char definer_host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder,
- HOSTNAME_LENGTH);
-
+ LEX_STRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH };
+
int ret;
thd->variables.sql_mode= sql_mode;
@@ -477,6 +474,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
(*sphp)->optimize();
}
end:
+ lex_end(thd->lex);
thd->spcont= old_spcont;
thd->variables.sql_mode= old_sql_mode;
thd->variables.select_limit= old_select_limit;
@@ -885,28 +883,23 @@ int
sp_drop_db_routines(THD *thd, char *db)
{
TABLE *table;
- byte key[64]; // db
- uint keylen;
int ret;
+ uint key_len;
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;
+ table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
+ key_len= table->key_info->key_part[0].store_length;
+
ret= SP_OK;
table->file->ha_index_init(0, 1);
if (! table->file->index_read(table->record[0],
- key, keylen, HA_READ_KEY_EXACT))
+ (byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
+ key_len, HA_READ_KEY_EXACT))
{
int nxtres;
bool deleted= FALSE;
@@ -922,7 +915,8 @@ sp_drop_db_routines(THD *thd, char *db)
break;
}
} while (! (nxtres= table->file->index_next_same(table->record[0],
- key, keylen)));
+ (byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
+ key_len)));
if (nxtres != HA_ERR_END_OF_FILE)
ret= SP_KEY_NOT_FOUND;
if (deleted)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 47d4326d780..c98394e3a05 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -202,6 +202,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
case SQLCOM_SHOW_AUTHORS:
+ case SQLCOM_SHOW_CONTRIBUTORS:
case SQLCOM_REPAIR:
case SQLCOM_BACKUP_TABLE:
case SQLCOM_RESTORE_TABLE:
@@ -249,6 +250,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_TRUNCATE:
case SQLCOM_COMMIT:
case SQLCOM_ROLLBACK:
+ case SQLCOM_LOAD:
case SQLCOM_LOAD_MASTER_DATA:
case SQLCOM_LOCK_TABLES:
case SQLCOM_CREATE_PROCEDURE:
@@ -315,14 +317,16 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
*/
bool
-sp_eval_expr(THD *thd, Field *result_field, Item *expr_item)
+sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
{
+ Item *expr_item;
+
DBUG_ENTER("sp_eval_expr");
- if (!expr_item)
+ if (!*expr_item_ptr)
DBUG_RETURN(TRUE);
- if (!(expr_item= sp_prepare_func_item(thd, &expr_item)))
+ if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
DBUG_RETURN(TRUE);
bool err_status= FALSE;
@@ -680,6 +684,7 @@ sp_head::destroy()
DBUG_ASSERT(m_lex.is_empty() || m_thd);
while ((lex= (LEX *)m_lex.pop()))
{
+ lex_end(m_thd->lex);
delete m_thd->lex;
m_thd->lex= lex;
}
@@ -950,6 +955,7 @@ sp_head::execute(THD *thd)
bool err_status= FALSE;
uint ip= 0;
ulong save_sql_mode;
+ bool save_abort_on_warning;
Query_arena *old_arena;
/* per-instruction arena */
MEM_ROOT execute_mem_root;
@@ -1010,6 +1016,10 @@ sp_head::execute(THD *thd)
thd->derived_tables= 0;
save_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
+ save_abort_on_warning= thd->abort_on_warning;
+ thd->abort_on_warning=
+ (m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES));
+
/*
It is also more efficient to save/restore current thd->lex once when
do it in each instruction
@@ -1142,6 +1152,7 @@ sp_head::execute(THD *thd)
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
thd->variables.sql_mode= save_sql_mode;
+ thd->abort_on_warning= save_abort_on_warning;
thd->stmt_arena= old_arena;
state= EXECUTED;
@@ -1218,18 +1229,22 @@ bool
sp_head::execute_function(THD *thd, Item **argp, uint argcount,
Field *return_value_fld)
{
- Item_cache **param_values;
ulonglong binlog_save_options;
bool need_binlog_call;
- uint params;
+ uint arg_no;
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ String binlog_buf(buf, sizeof(buf), &my_charset_bin);
bool err_status= FALSE;
+ MEM_ROOT call_mem_root;
+ Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+ Query_arena backup_arena;
+
DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str));
LINT_INIT(binlog_save_options);
- params = m_pcont->context_pvars();
/*
Check that the function is called with all specified arguments.
@@ -1237,74 +1252,97 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
If it is not, use my_error() to report an error, or it will not terminate
the invoking query properly.
*/
-
- if (argcount != params)
+ if (argcount != m_pcont->context_var_count())
{
/*
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);
+ "FUNCTION", m_qname.str, m_pcont->context_var_count(), argcount);
DBUG_RETURN(TRUE);
}
-
- /* Allocate param_values to be used for dumping the call into binlog. */
-
- if (!(param_values= (Item_cache**)thd->alloc(sizeof(Item_cache*)*argcount)))
- DBUG_RETURN(TRUE);
-
- // QQ Should have some error checking here? (types, etc...)
+ /*
+ Prepare arena and memroot for objects which lifetime is whole
+ duration of function call (sp_rcontext, it's tables and items,
+ sp_cursor and Item_cache holders for case expressions).
+ We can't use caller's arena/memroot for those objects because
+ in this case some fixed amount of memory will be consumed for
+ each function/trigger invocation and so statements which involve
+ lot of them will hog memory.
+ TODO: we should create sp_rcontext once per command and reuse
+ it on subsequent executions of a function/trigger.
+ */
+ init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+ thd->set_n_backup_active_arena(&call_arena, &backup_arena);
if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
nctx->init(thd))
{
- delete nctx; /* Delete nctx if it was init() that failed. */
- DBUG_RETURN(TRUE);
+ thd->restore_active_arena(&call_arena, &backup_arena);
+ err_status= TRUE;
+ goto err_with_cleanup;
}
+ /*
+ We have to switch temporarily back to callers arena/memroot.
+ Function arguments belong to the caller and so the may reference
+ memory which they will allocate during calculation long after
+ this function call will be finished (e.g. in Item::cleanup()).
+ */
+ thd->restore_active_arena(&call_arena, &backup_arena);
+
#ifndef DBUG_OFF
nctx->sp= this;
#endif
/* Pass arguments. */
-
+ for (arg_no= 0; arg_no < argcount; arg_no++)
{
- uint i;
-
- for (i= 0 ; i < argcount ; i++)
- {
- if (!argp[i]->fixed && argp[i]->fix_fields(thd, &argp[i]))
- {
- err_status= TRUE;
- break;
- }
+ /* Arguments must be fixed in Item_func_sp::fix_fields */
+ DBUG_ASSERT(argp[arg_no]->fixed);
- param_values[i]= Item_cache::get_cache(argp[i]->result_type());
- param_values[i]->store(argp[i]);
-
- if (nctx->set_variable(thd, i, param_values[i]))
- {
- err_status= TRUE;
- break;
- }
- }
- }
-
- if (err_status)
- {
- delete nctx;
- DBUG_RETURN(TRUE);
+ if ((err_status= nctx->set_variable(thd, arg_no, &(argp[arg_no]))))
+ goto err_with_cleanup;
}
- thd->spcont= nctx;
-
/*
If row-based binlogging, we don't need to binlog the function's call, let
each substatement be binlogged its way.
*/
need_binlog_call= mysql_bin_log.is_open() &&
(thd->options & OPTION_BIN_LOG) && !thd->current_stmt_binlog_row_based;
+
+ /*
+ Remember the original arguments for unrolled replication of functions
+ before they are changed by execution.
+ */
+ if (need_binlog_call)
+ {
+ binlog_buf.length(0);
+ binlog_buf.append(STRING_WITH_LEN("SELECT "));
+ append_identifier(thd, &binlog_buf, m_name.str, m_name.length);
+ binlog_buf.append('(');
+ for (arg_no= 0; arg_no < argcount; arg_no++)
+ {
+ String str_value_holder;
+ String *str_value;
+
+ if (arg_no)
+ binlog_buf.append(',');
+
+ str_value= sp_get_item_value(nctx->get_item(arg_no),
+ &str_value_holder);
+
+ if (str_value)
+ binlog_buf.append(*str_value);
+ else
+ binlog_buf.append(STRING_WITH_LEN("NULL"));
+ }
+ binlog_buf.append(')');
+ }
+ thd->spcont= nctx;
+
if (need_binlog_call)
{
reset_dynamic(&thd->user_var_events);
@@ -1313,38 +1351,27 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
thd->options&= ~OPTION_BIN_LOG;
}
+ /*
+ Switch to call arena/mem_root so objects like sp_cursor or
+ Item_cache holders for case expressions can be allocated on it.
+
+ TODO: In future we should associate call arena/mem_root with
+ sp_rcontext and allocate all these objects (and sp_rcontext
+ itself) on it directly rather than juggle with arenas.
+ */
+ thd->set_n_backup_active_arena(&call_arena, &backup_arena);
+
err_status= execute(thd);
+ thd->restore_active_arena(&call_arena, &backup_arena);
+
if (need_binlog_call)
{
mysql_bin_log.stop_union_events(thd);
thd->options= binlog_save_options;
if (thd->binlog_evt_union.unioned_events)
{
- char buf[256];
- String bufstr(buf, sizeof(buf), &my_charset_bin);
- bufstr.length(0);
- bufstr.append(STRING_WITH_LEN("SELECT "));
- append_identifier(thd, &bufstr, m_name.str, m_name.length);
- bufstr.append('(');
- for (uint i=0; i < argcount; i++)
- {
- String str_value_holder;
- String *str_value;
-
- if (i)
- bufstr.append(',');
-
- str_value= sp_get_item_value(param_values[i], &str_value_holder);
-
- if (str_value)
- bufstr.append(*str_value);
- else
- bufstr.append(STRING_WITH_LEN("NULL"));
- }
- bufstr.append(')');
-
- Query_log_event qinfo(thd, bufstr.ptr(), bufstr.length(),
+ Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(),
thd->binlog_evt_union.unioned_events_trans, FALSE);
if (mysql_bin_log.write(&qinfo) &&
thd->binlog_evt_union.unioned_events_trans)
@@ -1368,27 +1395,19 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
}
}
+
nctx->pop_all_cursors(); // To avoid memory leaks after an error
+
+err_with_cleanup:
delete nctx;
+ call_arena.free_items();
+ free_root(&call_mem_root, MYF(0));
thd->spcont= octx;
DBUG_RETURN(err_status);
}
-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
@@ -1412,7 +1431,7 @@ bool
sp_head::execute_procedure(THD *thd, List<Item> *args)
{
bool err_status= FALSE;
- uint params = m_pcont->context_pvars();
+ uint params = m_pcont->context_var_count();
sp_rcontext *save_spcont, *octx;
sp_rcontext *nctx = NULL;
bool save_enable_slow_log= false;
@@ -1466,30 +1485,36 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
for (uint i= 0 ; i < params ; i++)
{
Item *arg_item= it_args++;
- sp_pvar_t *pvar= m_pcont->find_pvar(i);
if (!arg_item)
break;
- if (!pvar)
+ sp_variable_t *spvar= m_pcont->find_variable(i);
+
+ if (!spvar)
continue;
- if (pvar->mode != sp_param_in)
+ if (spvar->mode != sp_param_in)
{
- if (!arg_item->is_splocal() && !item_is_user_var(arg_item))
+ Settable_routine_parameter *srp=
+ arg_item->get_settable_routine_parameter();
+
+ if (!srp)
{
my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str);
err_status= TRUE;
break;
}
+
+ srp->set_required_privilege(spvar->mode == sp_param_inout);
}
- if (pvar->mode == sp_param_out)
+ if (spvar->mode == sp_param_out)
{
Item_null *null_item= new Item_null();
if (!null_item ||
- nctx->set_variable(thd, i, null_item))
+ nctx->set_variable(thd, i, (struct Item **)&null_item))
{
err_status= TRUE;
break;
@@ -1497,7 +1522,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
else
{
- if (nctx->set_variable(thd, i, *it_args.ref()))
+ if (nctx->set_variable(thd, i, it_args.ref()))
{
err_status= TRUE;
break;
@@ -1560,41 +1585,21 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!arg_item)
break;
- sp_pvar_t *pvar= m_pcont->find_pvar(i);
+ sp_variable_t *spvar= m_pcont->find_variable(i);
- if (pvar->mode == sp_param_in)
+ if (spvar->mode == sp_param_in)
continue;
- if (arg_item->is_splocal())
- {
- if (octx->set_variable(thd,
- ((Item_splocal*) arg_item)->get_var_idx(),
- nctx->get_item(i)))
- {
- err_status= TRUE;
- break;
- }
- }
- else
+ Settable_routine_parameter *srp=
+ arg_item->get_settable_routine_parameter();
+
+ DBUG_ASSERT(srp);
+
+ if (srp->set_value(thd, octx, nctx->get_item_addr(i)))
{
- Item_func_get_user_var *guv= item_is_user_var(arg_item);
-
- 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);
- /*
- Item_func_set_user_var is not fixed after construction,
- call fix_fields().
- */
- if ((err_status= test(!suv || suv->fix_fields(thd, &item) ||
- suv->check() || suv->update())))
- break;
- }
+ err_status= TRUE;
+ break;
}
-
}
}
@@ -1682,7 +1687,10 @@ sp_head::restore_lex(THD *thd)
*/
merge_table_list(thd, sublex->query_tables, sublex);
if (! sublex->sp_lex_in_use)
+ {
+ lex_end(sublex);
delete sublex;
+ }
thd->lex= oldlex;
DBUG_VOID_RETURN;
}
@@ -1709,44 +1717,11 @@ sp_head::backpatch(sp_label_t *lab)
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;
- }
+ if (bp->lab == lab)
+ bp->instr->backpatch(dest, lab->ctx);
}
- return 0;
}
-
/*
Prepare an instance of create_field for field creation (fill all necessary
attributes).
@@ -1850,10 +1825,10 @@ void
sp_head::set_definer(const char *definer, uint definerlen)
{
char user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH);
+ LEX_STRING user_name= { user_name_holder, USERNAME_LENGTH };
char host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH);
+ LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
parse_user(definer, definerlen, user_name.str, &user_name.length,
host_name.str, &host_name.length);
@@ -2401,7 +2376,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
int
sp_instr_set::exec_core(THD *thd, uint *nextp)
{
- int res= thd->spcont->set_variable(thd, m_offset, m_value);
+ int res= thd->spcont->set_variable(thd, m_offset, &m_value);
if (res && thd->spcont->found_handler_here())
{
@@ -2432,7 +2407,7 @@ sp_instr_set::print(String *str)
{
/* set name@offset ... */
int rsrv = SP_INSTR_UINT_MAXLEN+6;
- sp_pvar_t *var = m_ctx->find_pvar(m_offset);
+ sp_variable_t *var = m_ctx->find_variable(m_offset);
/* 'var' should always be non-null, but just in case... */
if (var)
@@ -2466,12 +2441,7 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
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;
+ const int res= (trigger_field->set_value(thd, &value) ? -1 : 0);
*nextp = m_ip+1;
return res;
}
@@ -2676,7 +2646,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
do it in scope of execution the current context/block.
*/
- return thd->spcont->set_return_value(thd, m_value);
+ return thd->spcont->set_return_value(thd, &m_value);
}
void
@@ -3048,8 +3018,8 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
void
sp_instr_cfetch::print(String *str)
{
- List_iterator_fast<struct sp_pvar> li(m_varlist);
- sp_pvar_t *pv;
+ List_iterator_fast<struct sp_variable> li(m_varlist);
+ sp_variable_t *pv;
LEX_STRING n;
my_bool found= m_ctx->find_cursor(m_cursor, &n);
/* cfetch name@offset vars... */
@@ -3120,7 +3090,7 @@ sp_instr_set_case_expr::execute(THD *thd, uint *nextp)
int
sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
{
- int res= thd->spcont->set_case_expr(thd, m_case_expr_id, m_case_expr);
+ int res= thd->spcont->set_case_expr(thd, m_case_expr_id, &m_case_expr);
if (res &&
!thd->spcont->get_case_expr(m_case_expr_id) &&
@@ -3134,7 +3104,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
Item *null_item= new Item_null();
if (!null_item ||
- thd->spcont->set_case_expr(thd, m_case_expr_id, null_item))
+ thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item))
{
/* If this also failed, we have to abort. */
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 66e0a5856f4..791343f0061 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -44,7 +44,7 @@ class sp_instr;
class sp_instr_opt_meta;
class sp_instr_jump_if_not;
struct sp_cond_type;
-struct sp_pvar;
+struct sp_variable;
class sp_name : public Sql_alloc
{
@@ -264,13 +264,6 @@ public:
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);
-
// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
void
new_cont_backpatch(sp_instr_opt_meta *i);
@@ -528,7 +521,10 @@ public:
virtual ~sp_lex_keeper()
{
if (m_lex_resp)
+ {
+ lex_end(m_lex);
delete m_lex;
+ }
}
/*
@@ -1075,7 +1071,7 @@ public:
virtual void print(String *str);
- void add_to_varlist(struct sp_pvar *var)
+ void add_to_varlist(struct sp_variable *var)
{
m_varlist.push_back(var);
}
@@ -1083,7 +1079,7 @@ public:
private:
uint m_cursor;
- List<struct sp_pvar> m_varlist;
+ List<struct sp_variable> m_varlist;
}; // class sp_instr_cfetch : public sp_instr
@@ -1174,6 +1170,6 @@ Item *
sp_prepare_func_item(THD* thd, Item **it_addr);
bool
-sp_eval_expr(THD *thd, Field *result_field, Item *expr_item);
+sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr);
#endif /* _SP_HEAD_H_ */
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index f69053a7c88..b0b65d5313b 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -27,10 +27,10 @@
#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.
- */
+ 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)
{
@@ -51,25 +51,25 @@ sp_cond_check(LEX_STRING *sqlstate)
}
sp_pcontext::sp_pcontext(sp_pcontext *prev)
- :Sql_alloc(), m_total_pvars(0), m_csubsize(0), m_hsubsize(0),
- m_handlers(0), m_parent(prev), m_pboundary(0)
+ :Sql_alloc(), m_max_var_index(0), m_max_cursor_index(0), m_max_handler_index(0),
+ m_context_handlers(0), m_parent(prev), m_pboundary(0)
{
- VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
+ VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), 16, 8));
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 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));
+ VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), 16, 8));
+ VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), 16, 8));
+ VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), 16, 8));
m_label.empty();
m_children.empty();
if (!prev)
{
- m_poffset= m_coffset= 0;
+ m_var_offset= m_cursor_offset= 0;
m_num_case_exprs= 0;
}
else
{
- m_poffset= prev->m_poffset + prev->m_total_pvars;
- m_coffset= prev->current_cursors();
+ m_var_offset= prev->m_var_offset + prev->m_max_var_index;
+ m_cursor_offset= prev->current_cursor_count();
m_num_case_exprs= prev->get_num_case_exprs();
}
}
@@ -85,11 +85,11 @@ sp_pcontext::destroy()
m_children.empty();
m_label.empty();
- delete_dynamic(&m_pvar);
+ delete_dynamic(&m_vars);
delete_dynamic(&m_case_expr_id_lst);
- delete_dynamic(&m_cond);
- delete_dynamic(&m_cursor);
- delete_dynamic(&m_handler);
+ delete_dynamic(&m_conds);
+ delete_dynamic(&m_cursors);
+ delete_dynamic(&m_handlers);
}
sp_pcontext *
@@ -105,15 +105,15 @@ sp_pcontext::push_context()
sp_pcontext *
sp_pcontext::pop_context()
{
- m_parent->m_total_pvars= m_parent->m_total_pvars + m_total_pvars;
+ m_parent->m_max_var_index+= m_max_var_index;
- uint submax= max_handlers();
- if (submax > m_parent->m_hsubsize)
- m_parent->m_hsubsize= submax;
+ uint submax= max_handler_index();
+ if (submax > m_parent->m_max_handler_index)
+ m_parent->m_max_handler_index= submax;
- submax= max_cursors();
- if (submax > m_parent->m_csubsize)
- m_parent->m_csubsize= submax;
+ submax= max_cursor_index();
+ if (submax > m_parent->m_max_cursor_index)
+ m_parent->m_max_cursor_index= submax;
if (m_num_case_exprs > m_parent->m_num_case_exprs)
m_parent->m_num_case_exprs= m_num_case_exprs;
@@ -130,12 +130,12 @@ sp_pcontext::diff_handlers(sp_pcontext *ctx, bool exclusive)
while (pctx && pctx != ctx)
{
- n+= pctx->m_handlers;
+ n+= pctx->m_context_handlers;
last_ctx= pctx;
pctx= pctx->parent_context();
}
if (pctx)
- return (exclusive && last_ctx ? n - last_ctx->m_handlers : n);
+ return (exclusive && last_ctx ? n - last_ctx->m_context_handlers : n);
return 0; // Didn't find ctx
}
@@ -148,32 +148,33 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx, bool exclusive)
while (pctx && pctx != ctx)
{
- n+= pctx->m_cursor.elements;
+ n+= pctx->m_cursors.elements;
last_ctx= pctx;
pctx= pctx->parent_context();
}
if (pctx)
- return (exclusive && last_ctx ? n - last_ctx->m_cursor.elements : n);
+ return (exclusive && last_ctx ? n - last_ctx->m_cursors.elements : n);
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.
+/*
+ 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)
+sp_variable_t *
+sp_pcontext::find_variable(LEX_STRING *name, my_bool scoped)
{
- uint i= m_pvar.elements - m_pboundary;
+ uint i= m_vars.elements - m_pboundary;
while (i--)
{
- sp_pvar_t *p;
+ sp_variable_t *p;
- get_dynamic(&m_pvar, (gptr)&p, i);
+ get_dynamic(&m_vars, (gptr)&p, i);
if (my_strnncoll(system_charset_info,
(const uchar *)name->str, name->length,
(const uchar *)p->name.str, p->name.length) == 0)
@@ -182,7 +183,7 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
}
}
if (!scoped && m_parent)
- return m_parent->find_pvar(name, scoped);
+ return m_parent->find_variable(name, scoped);
return NULL;
}
@@ -192,40 +193,40 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
- When evaluating parameters at the beginning, and setting out parameters
at the end, of invokation. (Top frame only, so no recursion then.)
- For printing of sp_instr_set. (Debug mode only.)
- */
-sp_pvar_t *
-sp_pcontext::find_pvar(uint offset)
+*/
+sp_variable_t *
+sp_pcontext::find_variable(uint offset)
{
- if (m_poffset <= offset && offset < m_poffset + m_pvar.elements)
+ if (m_var_offset <= offset && offset < m_var_offset + m_vars.elements)
{ // This frame
- sp_pvar_t *p;
+ sp_variable_t *p;
- get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset);
+ get_dynamic(&m_vars, (gptr)&p, offset - m_var_offset);
return p;
}
if (m_parent)
- return m_parent->find_pvar(offset); // Some previous frame
+ return m_parent->find_variable(offset); // Some previous frame
return NULL; // index out of bounds
}
-sp_pvar_t *
-sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
- sp_param_mode_t mode)
+sp_variable_t *
+sp_pcontext::push_variable(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));
+ sp_variable_t *p= (sp_variable_t *)sql_alloc(sizeof(sp_variable_t));
if (!p)
return NULL;
- ++m_total_pvars;
+ ++m_max_var_index;
p->name.str= name->str;
p->name.length= name->length;
p->type= type;
p->mode= mode;
- p->offset= current_pvars();
+ p->offset= current_var_count();
p->dflt= NULL;
- insert_dynamic(&m_pvar, (gptr)&p);
+ insert_dynamic(&m_vars, (gptr)&p);
return p;
}
@@ -240,7 +241,7 @@ sp_pcontext::push_label(char *name, uint ip)
{
lab->name= name;
lab->ip= ip;
- lab->type= SP_LAB_GOTO;
+ lab->type= SP_LAB_IMPL;
lab->ctx= this;
m_label.push_front(lab);
}
@@ -272,23 +273,23 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
p->name.str= name->str;
p->name.length= name->length;
p->val= val;
- insert_dynamic(&m_cond, (gptr)&p);
+ insert_dynamic(&m_conds, (gptr)&p);
}
}
/*
- * See comment for find_pvar() above
- */
+ See comment for find_variable() above
+*/
sp_cond_type_t *
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
{
- uint i= m_cond.elements;
+ uint i= m_conds.elements;
while (i--)
{
sp_cond_t *p;
- get_dynamic(&m_cond, (gptr)&p, i);
+ get_dynamic(&m_conds, (gptr)&p, i);
if (my_strnncoll(system_charset_info,
(const uchar *)name->str, name->length,
(const uchar *)p->name.str, p->name.length) == 0)
@@ -302,20 +303,20 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
}
/*
- * This only searches the current context, for error checking of
- * duplicates.
- * Returns TRUE if found.
- */
+ 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;
+ uint i= m_handlers.elements;
while (i--)
{
sp_cond_type_t *p;
- get_dynamic(&m_handler, (gptr)&p, i);
+ get_dynamic(&m_handlers, (gptr)&p, i);
if (cond->type == p->type)
{
switch (p->type)
@@ -341,31 +342,31 @@ sp_pcontext::push_cursor(LEX_STRING *name)
{
LEX_STRING n;
- if (m_cursor.elements == m_csubsize)
- m_csubsize+= 1;
+ if (m_cursors.elements == m_max_cursor_index)
+ m_max_cursor_index+= 1;
n.str= name->str;
n.length= name->length;
- insert_dynamic(&m_cursor, (gptr)&n);
+ insert_dynamic(&m_cursors, (gptr)&n);
}
/*
- * See comment for find_pvar() above
- */
+ See comment for find_variable() above
+*/
my_bool
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
{
- uint i= m_cursor.elements;
+ uint i= m_cursors.elements;
while (i--)
{
LEX_STRING n;
- get_dynamic(&m_cursor, (gptr)&n, i);
+ get_dynamic(&m_cursors, (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;
+ *poff= m_cursor_offset + i;
return TRUE;
}
}
@@ -380,10 +381,10 @@ sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
{
/* Put local/context fields in the result list. */
- for (uint i = 0; i < m_pvar.elements; ++i)
+ for (uint i = 0; i < m_vars.elements; ++i)
{
- sp_pvar_t *var_def;
- get_dynamic(&m_pvar, (gptr) &var_def, i);
+ sp_variable_t *var_def;
+ get_dynamic(&m_vars, (gptr) &var_def, i);
field_def_lst->push_back(&var_def->field_def);
}
@@ -400,17 +401,17 @@ sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
/*
Find a cursor by offset from the top.
This is only used for debugging.
- */
+*/
my_bool
sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
{
- if (m_coffset <= offset && offset < m_coffset + m_cursor.elements)
+ if (m_cursor_offset <= offset &&
+ offset < m_cursor_offset + m_cursors.elements)
{ // This frame
- get_dynamic(&m_cursor, (gptr)n, offset - m_coffset);
+ get_dynamic(&m_cursors, (gptr)n, offset - m_cursor_offset);
return TRUE;
}
if (m_parent)
return m_parent->find_cursor(offset, n); // Some previous frame
return FALSE; // index out of bounds
}
-
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 872c7c1d505..2ee77696efb 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -29,28 +29,28 @@ typedef enum
sp_param_inout
} sp_param_mode_t;
-typedef struct sp_pvar
+typedef struct sp_variable
{
LEX_STRING name;
enum enum_field_types type;
sp_param_mode_t mode;
/*
- offset -- basically, this is an index of variable in the scope of root
- parsing context. This means, that all variables in a stored routine
- have distinct indexes/offsets.
+ offset -- this the index to the variable's value in the runtime frame.
+ This is calculated during parsing and used when creating sp_instr_set
+ instructions and Item_splocal items.
+ I.e. values are set/referred by array indexing in runtime.
*/
uint offset;
Item *dflt;
create_field field_def;
-} sp_pvar_t;
+} sp_variable_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
+#define SP_LAB_IMPL 0 // Implicit label generated by parser
+#define SP_LAB_BEGIN 1 // Label at BEGIN
+#define SP_LAB_ITER 2 // Label at iteration control
/*
An SQL/PSM label. Can refer to the identifier used with the
@@ -76,9 +76,10 @@ typedef struct sp_cond_type
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.
- */
+/*
+ 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);
@@ -90,7 +91,17 @@ typedef struct sp_cond
/*
- This seems to be an "SP parsing context" or something.
+ The parse-time context, used to keep track on declared variables/parameters,
+ conditions, handlers, cursors and labels, during parsing.
+ sp_contexts are organized as a tree, with one object for each begin-end
+ block, plus a root-context for the parameters.
+ This is used during parsing for looking up defined names (e.g. declared
+ variables and visible labels), for error checking, and to calculate offsets
+ to be used at runtime. (During execution variable values, active handlers
+ and cursors, etc, are referred to by an index in a stack.)
+ The pcontext tree is also kept during execution and is used for error
+ checking (e.g. correct number of parameters), and in the future, used by
+ the debugger.
*/
class sp_pcontext : public Sql_alloc
@@ -134,50 +145,64 @@ class sp_pcontext : public Sql_alloc
// Parameters and variables
//
+ /*
+ The maximum number of variables used in this and all child contexts
+ In the root, this gives us the number of slots needed for variables
+ during execution.
+ */
inline uint
- total_pvars()
+ max_var_index()
{
- return m_total_pvars;
+ return m_max_var_index;
}
+ /*
+ The current number of variables used in the parents (from the root),
+ including this context.
+ */
inline uint
- current_pvars()
+ current_var_count()
{
- return m_poffset + m_pvar.elements;
+ return m_var_offset + m_vars.elements;
}
+ /* The number of variables in this context alone */
inline uint
- context_pvars()
+ context_var_count()
{
- return m_pvar.elements;
+ return m_vars.elements;
}
+ /* Map index in this pcontext to runtime offset */
inline uint
- pvar_context2index(uint i)
+ var_context2runtime(uint i)
{
- return m_poffset + i;
+ return m_var_offset + i;
}
+ /* Set type of variable. 'i' is the offset from the top */
inline void
set_type(uint i, enum enum_field_types type)
{
- sp_pvar_t *p= find_pvar(i);
+ sp_variable_t *p= find_variable(i);
if (p)
p->type= type;
}
+ /* Set default value of variable. 'i' is the offset from the top */
inline void
set_default(uint i, Item *it)
{
- sp_pvar_t *p= find_pvar(i);
+ sp_variable_t *p= find_variable(i);
if (p)
p->dflt= it;
}
- sp_pvar_t *
- push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode);
+ sp_variable_t *
+ push_variable(LEX_STRING *name, enum enum_field_types type,
+ sp_param_mode_t mode);
/*
Retrieve definitions of fields from the current context and its
@@ -187,12 +212,12 @@ class sp_pcontext : public Sql_alloc
retrieve_field_definitions(List<create_field> *field_def_lst);
// Find by name
- sp_pvar_t *
- find_pvar(LEX_STRING *name, my_bool scoped=0);
+ sp_variable_t *
+ find_variable(LEX_STRING *name, my_bool scoped=0);
- // Find by offset
- sp_pvar_t *
- find_pvar(uint offset);
+ // Find by offset (from the top)
+ sp_variable_t *
+ find_variable(uint offset);
/*
Set the current scope boundary (for default values).
@@ -280,7 +305,7 @@ class sp_pcontext : public Sql_alloc
pop_cond(uint num)
{
while (num--)
- pop_dynamic(&m_cond);
+ pop_dynamic(&m_conds);
}
sp_cond_type_t *
@@ -293,22 +318,22 @@ class sp_pcontext : public Sql_alloc
inline void
push_handler(sp_cond_type_t *cond)
{
- insert_dynamic(&m_handler, (gptr)&cond);
+ insert_dynamic(&m_handlers, (gptr)&cond);
}
bool
find_handler(sp_cond_type *cond);
inline uint
- max_handlers()
+ max_handler_index()
{
- return m_hsubsize + m_handlers;
+ return m_max_handler_index + m_context_handlers;
}
inline void
add_handlers(uint n)
{
- m_handlers+= n;
+ m_context_handlers+= n;
}
//
@@ -326,51 +351,51 @@ class sp_pcontext : public Sql_alloc
find_cursor(uint offset, LEX_STRING *n);
inline uint
- max_cursors()
+ max_cursor_index()
{
- return m_csubsize + m_cursor.elements;
+ return m_max_cursor_index + m_cursors.elements;
}
inline uint
- current_cursors()
+ current_cursor_count()
{
- return m_coffset + m_cursor.elements;
+ return m_cursor_offset + m_cursors.elements;
}
protected:
/*
- m_total_pvars -- number of variables (including all types of arguments)
+ m_max_var_index -- number of variables (including all types of arguments)
in this context including all children contexts.
- m_total_pvars >= m_pvar.elements.
+ m_max_var_index >= m_vars.elements.
- m_total_pvars of the root parsing context contains number of all
+ m_max_var_index of the root parsing context contains number of all
variables (including arguments) in all enclosed contexts.
*/
- uint m_total_pvars;
+ uint m_max_var_index;
// The maximum sub context's framesizes
- uint m_csubsize;
- uint m_hsubsize;
- uint m_handlers; // No. of handlers in this context
+ uint m_max_cursor_index;
+ uint m_max_handler_index;
+ uint m_context_handlers; // No. of handlers in this context
private:
sp_pcontext *m_parent; // Parent context
/*
- m_poffset -- basically, this is an index of the first variable in this
- parsing context.
+ m_var_offset -- this is an index of the first variable in this
+ parsing context.
- m_poffset is 0 for root context.
+ m_var_offset is 0 for root context.
Since now each variable is stored in separate place, no reuse is done,
- so m_poffset is different for all enclosed contexts.
+ so m_var_offset is different for all enclosed contexts.
*/
- uint m_poffset;
+ uint m_var_offset;
- uint m_coffset; // Cursor offset for this context
+ uint m_cursor_offset; // Cursor offset for this context
/*
Boundary for finding variables in this context. This is the number
@@ -382,11 +407,11 @@ private:
int m_num_case_exprs;
- DYNAMIC_ARRAY m_pvar; // Parameters/variables
+ DYNAMIC_ARRAY m_vars; // Parameters/variables
DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
- DYNAMIC_ARRAY m_cond; // Conditions
- DYNAMIC_ARRAY m_cursor; // Cursors
- DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates
+ DYNAMIC_ARRAY m_conds; // Conditions
+ DYNAMIC_ARRAY m_cursors; // Cursors
+ DYNAMIC_ARRAY m_handlers; // Handlers, for checking for duplicates
List<sp_label_t> m_label; // The label list
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index af4e41c29be..3bc27a029d0 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -73,16 +73,16 @@ bool sp_rcontext::init(THD *thd)
return
!(m_handler=
- (sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handlers() *
+ (sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
sizeof(sp_handler_t))) ||
!(m_hstack=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
+ (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
sizeof(uint))) ||
!(m_in_handler=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
+ (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
sizeof(uint))) ||
!(m_cstack=
- (sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursors() *
+ (sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursor_index() *
sizeof(sp_cursor*))) ||
!(m_case_expr_holders=
(Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() *
@@ -105,12 +105,12 @@ sp_rcontext::init_var_table(THD *thd)
{
List<create_field> field_def_lst;
- if (!m_root_parsing_ctx->total_pvars())
+ if (!m_root_parsing_ctx->max_var_index())
return FALSE;
m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
- DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->total_pvars());
+ DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
return TRUE;
@@ -134,7 +134,7 @@ bool
sp_rcontext::init_var_items()
{
uint idx;
- uint num_vars= m_root_parsing_ctx->total_pvars();
+ uint num_vars= m_root_parsing_ctx->max_var_index();
if (!(m_var_items= (Item**) sql_alloc(num_vars * sizeof (Item *))))
return TRUE;
@@ -150,7 +150,7 @@ sp_rcontext::init_var_items()
bool
-sp_rcontext::set_return_value(THD *thd, Item *return_value_item)
+sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
@@ -279,14 +279,14 @@ sp_rcontext::pop_cursors(uint count)
int
-sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value)
+sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value)
{
return set_variable(thd, m_var_table->field[var_idx], value);
}
int
-sp_rcontext::set_variable(THD *thd, Field *field, Item *value)
+sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
{
if (!value)
{
@@ -381,7 +381,7 @@ sp_cursor::destroy()
int
-sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
+sp_cursor::fetch(THD *thd, List<struct sp_variable> *vars)
{
if (! server_side_cursor)
{
@@ -478,9 +478,10 @@ sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type)
*/
int
-sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item)
+sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr)
{
- if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item)))
+ Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
+ if (!case_expr_item)
return TRUE;
if (!m_case_expr_holders[case_expr_id] ||
@@ -528,9 +529,9 @@ int Select_fetch_into_spvars::prepare(List<Item> &fields, SELECT_LEX_UNIT *u)
bool Select_fetch_into_spvars::send_data(List<Item> &items)
{
- List_iterator_fast<struct sp_pvar> pv_iter(*spvar_list);
+ List_iterator_fast<struct sp_variable> spvar_iter(*spvar_list);
List_iterator_fast<Item> item_iter(items);
- sp_pvar_t *pv;
+ sp_variable_t *spvar;
Item *item;
/* Must be ensured by the caller */
@@ -540,9 +541,9 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items)
Assign the row fetched from a server side cursor to stored
procedure variables.
*/
- for (; pv= pv_iter++, item= item_iter++; )
+ for (; spvar= spvar_iter++, item= item_iter++; )
{
- if (thd->spcont->set_variable(thd, pv->offset, item))
+ if (thd->spcont->set_variable(thd, spvar->offset, &item))
return TRUE;
}
return FALSE;
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index e7393902e72..30521f6da84 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -24,7 +24,7 @@
struct sp_cond_type;
class sp_cursor;
-struct sp_pvar;
+struct sp_variable;
class sp_lex_keeper;
class sp_instr_cpush;
@@ -91,7 +91,7 @@ class sp_rcontext : public Sql_alloc
~sp_rcontext();
int
- set_variable(THD *thd, uint var_idx, Item *value);
+ set_variable(THD *thd, uint var_idx, Item **value);
Item *
get_item(uint var_idx);
@@ -100,7 +100,7 @@ class sp_rcontext : public Sql_alloc
get_item_addr(uint var_idx);
bool
- set_return_value(THD *thd, Item *return_value_item);
+ set_return_value(THD *thd, Item **return_value_item);
inline bool
is_return_value_set() const
@@ -200,7 +200,7 @@ class sp_rcontext : public Sql_alloc
*/
int
- set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item);
+ set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
Item *
get_case_expr(int case_expr_id);
@@ -254,7 +254,7 @@ private:
Item_cache *create_case_expr_holder(THD *thd, Item_result result_type);
- int set_variable(THD *thd, Field *field, Item *value);
+ int set_variable(THD *thd, Field *field, Item **value);
}; // class sp_rcontext : public Sql_alloc
@@ -265,12 +265,12 @@ private:
class Select_fetch_into_spvars: public select_result_interceptor
{
- List<struct sp_pvar> *spvar_list;
+ List<struct sp_variable> *spvar_list;
uint field_count;
public:
Select_fetch_into_spvars() {} /* Remove gcc warning */
uint get_field_count() { return field_count; }
- void set_spvar_list(List<struct sp_pvar> *vars) { spvar_list= vars; }
+ void set_spvar_list(List<struct sp_variable> *vars) { spvar_list= vars; }
virtual bool send_eof() { return FALSE; }
virtual bool send_data(List<Item> &items);
@@ -307,7 +307,7 @@ public:
}
int
- fetch(THD *, List<struct sp_pvar> *vars);
+ fetch(THD *, List<struct sp_variable> *vars);
inline sp_instr_cpush *
get_instr()
diff --git a/sql/spatial.cc b/sql/spatial.cc
index e91653f79d5..9f1f05aa18f 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -34,8 +34,11 @@ static Geometry::Class_info **ci_collection_end=
Geometry::Class_info::Class_info(const char *name, int type_id,
void(*create_func)(void *)):
- m_name(name, strlen(name)), m_type_id(type_id), m_create_func(create_func)
+ m_type_id(type_id), m_create_func(create_func)
{
+ m_name.str= (char *) name;
+ m_name.length= strlen(name);
+
ci_collection[type_id]= this;
}
diff --git a/sql/spatial.h b/sql/spatial.h
index a6f74a1ada0..36949ff5014 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -200,7 +200,7 @@ public:
class Class_info
{
public:
- LEX_STRING_WITH_INIT m_name;
+ LEX_STRING m_name;
int m_type_id;
void (*m_create_func)(void *);
Class_info(const char *name, int type_id, void(*create_func)(void *));
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 09b684c8706..d2501d08c4d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -987,8 +987,8 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
if (acl_user->x509_issuer)
{
DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
acl_user->x509_issuer, ptr));
if (strcmp(acl_user->x509_issuer, ptr))
{
@@ -1156,6 +1156,8 @@ static void acl_update_user(const char *user, const char *host,
USER_RESOURCES *mqh,
ulong privileges)
{
+ safe_mutex_assert_owner(&acl_cache->lock);
+
for (uint i=0 ; i < acl_users.elements ; i++)
{
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
@@ -1206,6 +1208,9 @@ static void acl_insert_user(const char *user, const char *host,
ulong privileges)
{
ACL_USER acl_user;
+
+ safe_mutex_assert_owner(&acl_cache->lock);
+
acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
acl_user.access=privileges;
@@ -1235,6 +1240,8 @@ static void acl_insert_user(const char *user, const char *host,
static void acl_update_db(const char *user, const char *host, const char *db,
ulong privileges)
{
+ safe_mutex_assert_owner(&acl_cache->lock);
+
for (uint i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*);
@@ -1660,6 +1667,9 @@ find_acl_user(const char *host, const char *user, my_bool exact)
{
DBUG_ENTER("find_acl_user");
DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user));
+
+ safe_mutex_assert_owner(&acl_cache->lock);
+
for (uint i=0 ; i < acl_users.elements ; i++)
{
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
@@ -1672,7 +1682,7 @@ find_acl_user(const char *host, const char *user, my_bool exact)
if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user))
{
- if (exact ? !my_strcasecmp(&my_charset_latin1, host,
+ if (exact ? !my_strcasecmp(system_charset_info, host,
acl_user->host.hostname ?
acl_user->host.hostname : "") :
compare_hostname(&acl_user->host,host,host))
@@ -2977,7 +2987,6 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
some kind of updates to the mysql.% tables.
*/
if (thd->slave_thread && rpl_filter->is_on())
- if (thd->slave_thread && rpl_filter->is_on())
{
/*
The tables must be marked "updating" so that tables_ok() takes them into
@@ -2999,6 +3008,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
create_new_users= test_if_create_new_users(thd);
bool result= FALSE;
rw_wrlock(&LOCK_grant);
+ pthread_mutex_lock(&acl_cache->lock);
MEM_ROOT *old_root= thd->mem_root;
thd->mem_root= &memex;
grant_version++;
@@ -3016,12 +3026,10 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
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
@@ -3113,6 +3121,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
}
grant_option=TRUE;
thd->mem_root= old_root;
+ pthread_mutex_unlock(&acl_cache->lock);
rw_unlock(&LOCK_grant);
if (!result)
send_ok(thd);
@@ -3205,6 +3214,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
rw_wrlock(&LOCK_grant);
+ pthread_mutex_lock(&acl_cache->lock);
MEM_ROOT *old_root= thd->mem_root;
thd->mem_root= &memex;
@@ -3224,12 +3234,10 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
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
@@ -3271,6 +3279,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
}
grant_option=TRUE;
thd->mem_root= old_root;
+ pthread_mutex_unlock(&acl_cache->lock);
rw_unlock(&LOCK_grant);
if (!result && !no_error)
send_ok(thd);
@@ -4247,20 +4256,15 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
DBUG_RETURN(TRUE);
}
- for (counter=0 ; counter < acl_users.elements ; counter++)
- {
- const char *user,*host;
- acl_user=dynamic_element(&acl_users,counter,ACL_USER*);
- if (!(user=acl_user->user))
- user= "";
- if (!(host=acl_user->host.hostname))
- host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
- break;
- }
- if (counter == acl_users.elements)
+ rw_rdlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ acl_user= find_acl_user(lex_user->host.str, lex_user->user.str, TRUE);
+ if (!acl_user)
{
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+
my_error(ER_NONEXISTING_GRANT, MYF(0),
lex_user->user.str, lex_user->host.str);
DBUG_RETURN(TRUE);
@@ -4275,10 +4279,12 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
field_list.push_back(field);
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(TRUE);
+ {
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
- rw_wrlock(&LOCK_grant);
- VOID(pthread_mutex_lock(&acl_cache->lock));
+ DBUG_RETURN(TRUE);
+ }
/* Add first global access grants */
{
@@ -4686,10 +4692,15 @@ void get_privilege_desc(char *to, uint max_length, ulong access)
void get_mqh(const char *user, const char *host, USER_CONN *uc)
{
ACL_USER *acl_user;
+
+ pthread_mutex_lock(&acl_cache->lock);
+
if (initialized && (acl_user= find_acl_user(host,user, FALSE)))
uc->user_resources= acl_user->user_resource;
else
bzero((char*) &uc->user_resources, sizeof(uc->user_resources));
+
+ pthread_mutex_unlock(&acl_cache->lock);
}
/*
@@ -4769,31 +4780,6 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
DBUG_RETURN(0);
}
-ACL_USER *check_acl_user(LEX_USER *user_name,
- uint *acl_acl_userdx)
-{
- ACL_USER *acl_user= 0;
- uint counter;
-
- for (counter= 0 ; counter < acl_users.elements ; counter++)
- {
- const char *user,*host;
- acl_user= dynamic_element(&acl_users, counter, ACL_USER*);
- if (!(user=acl_user->user))
- user= "";
- if (!(host=acl_user->host.hostname))
- host= "";
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
- break;
- }
- if (counter == acl_users.elements)
- return 0;
-
- *acl_acl_userdx= counter;
- return acl_user;
-}
-
/*
Modify a privilege table.
@@ -5040,6 +5026,8 @@ static int handle_grant_struct(uint struct_no, bool drop,
LINT_INIT(user);
LINT_INIT(host);
+ safe_mutex_assert_owner(&acl_cache->lock);
+
/* Get the number of elements in the in-memory structure. */
switch (struct_no) {
case 0:
@@ -5502,7 +5490,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
List_iterator <LEX_USER> user_list(list);
while ((lex_user=user_list++))
{
- if (!check_acl_user(lex_user, &counter))
+ if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE))
{
sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
"exists", lex_user->user.str, lex_user->host.str);
@@ -5738,6 +5726,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
combo->user.str= sctx->user;
+ VOID(pthread_mutex_lock(&acl_cache->lock));
if (!find_acl_user(combo->host.str=(char*)sctx->host_or_ip, combo->user.str,
FALSE) &&
!find_acl_user(combo->host.str=(char*)sctx->host, combo->user.str,
@@ -5745,7 +5734,11 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
!find_acl_user(combo->host.str=(char*)sctx->ip, combo->user.str,
FALSE) &&
!find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE))
+ {
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(TRUE);
+ }
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
bzero((char*)tables, sizeof(TABLE_LIST));
user_list.empty();
@@ -5863,6 +5856,8 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
char *curr_host= thd->security_ctx->priv_host_name();
DBUG_ENTER("fill_schema_user_privileges");
+ pthread_mutex_lock(&acl_cache->lock);
+
for (counter=0 ; counter < acl_users.elements ; counter++)
{
const char *user,*host, *is_grantable="YES";
@@ -5898,6 +5893,9 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
}
}
}
+
+ pthread_mutex_unlock(&acl_cache->lock);
+
DBUG_RETURN(0);
#else
return(0);
@@ -5917,6 +5915,8 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
char *curr_host= thd->security_ctx->priv_host_name();
DBUG_ENTER("fill_schema_schema_privileges");
+ pthread_mutex_lock(&acl_cache->lock);
+
for (counter=0 ; counter < acl_dbs.elements ; counter++)
{
const char *user, *host, *is_grantable="YES";
@@ -5955,6 +5955,9 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
}
}
}
+
+ pthread_mutex_unlock(&acl_cache->lock);
+
DBUG_RETURN(0);
#else
return (0);
@@ -5972,6 +5975,8 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
char *curr_host= thd->security_ctx->priv_host_name();
DBUG_ENTER("fill_schema_table_privileges");
+ rw_rdlock(&LOCK_grant);
+
for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user, *is_grantable= "YES";
@@ -6017,6 +6022,9 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
}
}
}
+
+ rw_unlock(&LOCK_grant);
+
DBUG_RETURN(0);
#else
return (0);
@@ -6034,6 +6042,8 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
char *curr_host= thd->security_ctx->priv_host_name();
DBUG_ENTER("fill_schema_table_privileges");
+ rw_rdlock(&LOCK_grant);
+
for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user, *is_grantable= "YES";
@@ -6085,6 +6095,9 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
}
}
}
+
+ rw_unlock(&LOCK_grant);
+
DBUG_RETURN(0);
#else
return (0);
@@ -6141,20 +6154,21 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
}
/* table privileges */
+ rw_rdlock(&LOCK_grant);
if (grant->version != grant_version)
{
- rw_rdlock(&LOCK_grant);
grant->grant_table=
table_hash_search(sctx->host, sctx->ip, db,
sctx->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;
}
+ rw_unlock(&LOCK_grant);
+
DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 8c64adbbece..e1153522ed5 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -236,7 +236,6 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
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);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e09fed180ba..58c04224ac9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -288,13 +288,13 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (!(share= alloc_table_share(table_list, key, key_length)))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
DBUG_RETURN(0);
}
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
// We need a write lock to be able to add a new entry
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&LOCK_open);
@@ -331,19 +331,19 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (my_hash_insert(&table_def_cache, (byte*) share))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
(void) pthread_mutex_unlock(&share->mutex);
#endif
free_table_share(share);
DBUG_RETURN(0); // return error
}
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (open_table_def(thd, share, db_flags))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
/*
No such table or wrong table definition file
Lock first the table cache and then the mutex.
@@ -372,7 +372,7 @@ found:
/* We must do a lock to ensure that the structure is initialized */
(void) pthread_mutex_lock(&share->mutex);
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (share->error)
@@ -540,7 +540,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
DBUG_VOID_RETURN;
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
if (to_be_deleted)
{
/*
@@ -1069,7 +1069,9 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
handled either before writing a query log event (inside
binlog_query()) or when preparing a pending event.
*/
- thd->binlog_flush_pending_rows_event(true);
+#ifdef HAVE_ROW_BASED_REPLICATION
+ thd->binlog_flush_pending_rows_event(TRUE);
+#endif /*HAVE_ROW_BASED_REPLICATION*/
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
@@ -1167,16 +1169,26 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
+/* close_temporary_tables' internal, 4 is due to uint4korr definition */
+static inline uint tmpkeyval(THD *thd, TABLE *table)
+{
+ return uint4korr(table->s->table_cache_key.str + table->s->table_cache_key.length - 4);
+}
+
+
/*
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
+ creates one DROP TEMPORARY TABLE binlog event for each pseudo-thread
*/
void close_temporary_tables(THD *thd)
{
- TABLE *table,*next;
- char *query, *end;
- uint query_buf_size;
- bool found_user_tables = 0;
+ TABLE *next,
+ *prev_table /* prev link is not maintained in TABLE's double-linked list */,
+ *table;
+ char *query= (gptr) 0, *end;
+ uint query_buf_size, max_names_len;
+ bool found_user_tables;
if (!thd->temporary_tables)
return;
@@ -1184,55 +1196,127 @@ void close_temporary_tables(THD *thd)
LINT_INIT(end);
query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
- for (table=thd->temporary_tables ; table ; table=table->next)
+ /*
+ insertion sort of temp tables by pseudo_thread_id to build ordered list
+ of sublists of equal pseudo_thread_id
+ */
+ for (prev_table= thd->temporary_tables,
+ table= prev_table->next,
+ found_user_tables= (prev_table->s->table_name.str[0] != '#');
+ table;
+ prev_table= table, table= table->next)
{
+ TABLE *prev_sorted /* same as for prev_table */,
+ *sorted;
/*
- We are going to add 4 ` around the db/table names, so 1 does not look
- enough; indeed it is enough, because table->table_cache_key.length is
- greater (by 8, because of server_id and thread_id) than db||table.
+ table not created directly by the user is moved to the tail.
+ Fixme/todo: nothing (I checked the manual) prevents user to create temp
+ with `#'
*/
- query_buf_size+= table->s->table_cache_key.length+1;
+ if (table->s->table_name.str[0] == '#')
+ continue;
+ else
+ {
+ found_user_tables = 1;
+ }
+ for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
+ prev_sorted= sorted, sorted= sorted->next)
+ {
+ if (sorted->s->table_name.str[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
+ {
+ /* move into the sorted part of the list from the unsorted */
+ prev_table->next= table->next;
+ table->next= sorted;
+ if (prev_sorted)
+ {
+ prev_sorted->next= table;
+ }
+ else
+ {
+ thd->temporary_tables= table;
+ }
+ table= prev_table;
+ break;
+ }
+ }
+ }
+ /*
+ calc query_buf_size as max per sublists, one sublist per pseudo thread id.
+ Also stop at first occurence of `#'-named table that starts
+ all implicitly created temp tables
+ */
+ for (max_names_len= 0, table=thd->temporary_tables;
+ table && table->s->table_name.str[0] != '#';
+ table=table->next)
+ {
+ uint tmp_names_len;
+ for (tmp_names_len= table->s->table_cache_key.length + 1;
+ table->next && table->s->table_name.str[0] != '#' &&
+ tmpkeyval(thd, table) == tmpkeyval(thd, table->next);
+ table=table->next)
+ {
+ /*
+ We are going to add 4 ` around the db/table names, so 1 might not look
+ enough; indeed it is enough, because table->s->table_cache_key.length is
+ greater (by 8, because of server_id and thread_id) than db||table.
+ */
+ tmp_names_len += table->next->s->table_cache_key.length + 1;
+ }
+ if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
}
-
- if ((query = alloc_root(thd->mem_root, query_buf_size)))
+
+ /* allocate */
+ if (found_user_tables && mysql_bin_log.is_open() &&
+ !thd->current_stmt_binlog_row_based &&
+ (query = alloc_root(thd->mem_root, query_buf_size+= max_names_len)))
// Better add "if exists", in case a RESET MASTER has been done
- end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
+ end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
- for (table=thd->temporary_tables ; table ; table=next)
+ /* scan sorted tmps to generate sequence of DROP */
+ for (table=thd->temporary_tables; table; table= next)
{
- if (query) // we might be out of memory, but this is not fatal
+ if (query // we might be out of memory, but this is not fatal
+ && table->s->table_name.str[0] != '#')
{
- // skip temporary tables not created directly by the user
- if (table->s->table_name.str[0] != '#')
- found_user_tables = 1;
- end= strxmov(end, "`",table->s->db.str, "`.`",
- table->s->table_name.str, "`,", NullS);
+ char *end_cur;
+ /* Set pseudo_thread_id to be that of the processed table */
+ thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
+ /* Loop forward through all tables within the sublist of
+ common pseudo_thread_id to create single DROP query */
+ for (end_cur= end;
+ table && table->s->table_name.str[0] != '#' &&
+ tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
+ table= next)
+ {
+ end_cur= strxmov(end_cur, "`", table->s->db.str, "`.`",
+ table->s->table_name.str, "`,", NullS);
+ next= table->next;
+ close_temporary(table, 1, 1);
+ }
+ thd->clear_error();
+ /* The -1 is to remove last ',' */
+ Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE);
+ /*
+ Imagine the thread had created a temp table, then was doing a SELECT,
+ and the SELECT was killed. Then it's not clever to mark the statement
+ above as "killed", because it's not really a statement updating data,
+ and there are 99.99% chances it will succeed on slave. If a real update
+ (one updating a persistent table) was killed on the master, then this
+ real update will be logged with error_code=killed, rightfully causing
+ the slave to stop.
+ */
+ qinfo.error_code= 0;
+ mysql_bin_log.write(&qinfo);
+ }
+ else
+ {
+ next= table->next;
+ close_temporary(table, 1, 1);
}
- next=table->next;
- close_temporary(table, 1, 1);
- }
- if (query && found_user_tables && mysql_bin_log.is_open() &&
- !thd->current_stmt_binlog_row_based) // CREATE TEMP TABLE not binlogged if row-based
- {
- /* The -1 is to remove last ',' */
- thd->clear_error();
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE);
- /*
- Imagine the thread had created a temp table, then was doing a SELECT, and
- the SELECT was killed. Then it's not clever to mark the statement above
- as "killed", because it's not really a statement updating data, and there
- are 99.99% chances it will succeed on slave.
- If a real update (one updating a persistent table) was killed on the
- master, then this real update will be logged with error_code=killed,
- rightfully causing the slave to stop.
- */
- qinfo.error_code= 0;
- mysql_bin_log.write(&qinfo);
}
thd->temporary_tables=0;
}
-
/*
Find table in list.
@@ -1708,6 +1792,8 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
MYSQL_LOCK_IGNORE_FLUSH - Open table even if
someone has done a flush or namelock on it.
No version number checking is done.
+ MYSQL_OPEN_IGNORE_LOCKED_TABLES - Open table
+ ignoring set of locked tables and prelocked mode.
IMPLEMENTATION
Uses a cache of open tables to find a table not in use.
@@ -1767,7 +1853,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
}
- if (thd->locked_tables || thd->prelocked_mode)
+ if (!(flags & MYSQL_OPEN_IGNORE_LOCKED_TABLES) &&
+ (thd->locked_tables || thd->prelocked_mode))
{ // Using table locks
TABLE *best_table= 0;
int best_distance= INT_MIN;
@@ -6140,9 +6227,8 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
abort_and_upgrade_lock()
lpt Parameter passing struct
All parameters passed through the ALTER_PARTITION_PARAM_TYPE object
- RETURN VALUES
- TRUE Failure
- FALSE Success
+ RETURN VALUE
+ 0
DESCRIPTION
Remember old lock level (for possible downgrade later on), abort all
waiting threads and ensure that all keeping locks currently are
@@ -6156,23 +6242,17 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
old_lock_level Old lock level
*/
-bool abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
+int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
{
uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
- int error= FALSE;
DBUG_ENTER("abort_and_upgrade_locks");
lpt->old_lock_type= lpt->table->reginfo.lock_type;
VOID(pthread_mutex_lock(&LOCK_open));
mysql_lock_abort(lpt->thd, lpt->table, TRUE);
VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags));
- if (lpt->thd->killed)
- {
- lpt->thd->no_warnings_for_error= 0;
- error= TRUE;
- }
VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in
new file mode 100644
index 00000000000..18705aa3dfb
--- /dev/null
+++ b/sql/sql_builtin.cc.in
@@ -0,0 +1,13 @@
+
+#include <mysql/plugin.h>
+
+typedef struct st_mysql_plugin builtin_plugin[];
+
+extern builtin_plugin
+ builtin_binlog_plugin@mysql_plugin_defs@;
+
+struct st_mysql_plugin *mysqld_builtins[]=
+{
+ builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+};
+
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 63d3b053529..b4a7f9abc1c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -186,6 +186,11 @@ const char *thd_proc_info(THD *thd, const char *info)
return old_info;
}
+void **thd_ha_data(const THD *thd, const struct handlerton *hton)
+{
+ return (void **) thd->ha_data + hton->slot;
+}
+
/*
Pass nominal parameters to Statement constructor only to ensure that
@@ -197,7 +202,10 @@ THD::THD()
:Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
Open_tables_state(refresh_version), rli_fake(0),
lock_id(&main_lock_id),
- user_time(0), in_sub_stmt(0), binlog_table_maps(0),
+ user_time(0), in_sub_stmt(0),
+#ifdef HAVE_ROW_BASED_REPLICATION
+ binlog_table_maps(0),
+#endif /*HAVE_ROW_BASED_REPLICATION*/
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),
@@ -223,6 +231,9 @@ THD::THD()
cuted_fields= sent_row_count= 0L;
limit_found_rows= 0;
statement_id_counter= 0UL;
+#ifdef ERROR_INJECT_SUPPORT
+ error_inject_value= 0UL;
+#endif
// Must be reset to handle error with THD's created for init of mysqld
lex->current_select= 0;
start_time=(time_t) 0;
@@ -247,7 +258,8 @@ THD::THD()
net.last_error[0]=0; // If error on boot
net.query_cache_query=0; // If error on boot
ull=0;
- system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
+ system_thread= NON_SYSTEM_THREAD;
+ cleanup_done= abort_on_warning= no_warnings_for_error= 0;
peer_port= 0; // For SHOW PROCESSLIST
#ifdef HAVE_ROW_BASED_REPLICATION
transaction.m_pending_rows_event= 0;
@@ -330,7 +342,9 @@ void THD::init(void)
bzero((char*) warn_count, sizeof(warn_count));
total_warn_count= 0;
update_charset();
+#ifdef HAVE_ROW_BASED_REPLICATION
reset_current_stmt_binlog_row_based();
+#endif /*HAVE_ROW_BASED_REPLICATION*/
bzero((char *) &status_var, sizeof(status_var));
}
@@ -504,6 +518,8 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
void THD::awake(THD::killed_state state_to_set)
{
+ DBUG_ENTER("THD::awake");
+ DBUG_PRINT("enter", ("this=0x%lx", this));
THD_CHECK_SENTRY(this);
safe_mutex_assert_owner(&LOCK_delete);
@@ -547,6 +563,7 @@ void THD::awake(THD::killed_state state_to_set)
}
pthread_mutex_unlock(&mysys_var->mutex);
}
+ DBUG_VOID_RETURN;
}
/*
@@ -1922,7 +1939,7 @@ bool select_dumpvar::send_data(List<Item> &items)
if ((yy=var_li++))
{
if (thd->spcont->set_variable(current_thd, yy->get_var_idx(),
- *it.ref()))
+ it.ref()))
DBUG_RETURN(1);
}
}
@@ -2023,6 +2040,13 @@ void Security_context::skip_grants()
}
+bool Security_context::set_user(char *user_arg)
+{
+ safeFree(user);
+ user= my_strdup(user_arg, MYF(0));
+ return user == 0;
+}
+
/****************************************************************************
Handling of open and locked tables states.
@@ -2071,7 +2095,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
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 of last_insert_id() is saved 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
@@ -2083,6 +2107,8 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
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.
+
+ We do not reset value of last_insert_id().
****************************************************************************/
void THD::reset_sub_statement_state(Sub_statement_state *backup,
@@ -2109,7 +2135,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
/* 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;
@@ -2684,8 +2709,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
DBUG_ENTER("THD::binlog_query");
DBUG_ASSERT(query && mysql_bin_log.is_open());
- switch (qtype)
- {
+ switch (qtype) {
case THD::MYSQL_QUERY_TYPE:
/*
Using this query type is a conveniece hack, since we have been
@@ -2710,8 +2734,10 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
the flushing will be done inside the top-most
close_thread_tables().
*/
+#ifdef HAVE_ROW_BASED_REPLICATION
if (this->lock)
DBUG_RETURN(binlog_flush_pending_rows_event(TRUE));
+#endif /*HAVE_ROW_BASED_REPLICATION*/
DBUG_RETURN(0);
}
/* Otherwise, we fall through */
@@ -2730,7 +2756,9 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
table maps were written.
*/
int error= mysql_bin_log.write(&qinfo);
+#ifdef HAVE_ROW_BASED_REPLICATION
binlog_table_maps= 0;
+#endif /*HAVE_ROW_BASED_REPLICATION*/
DBUG_RETURN(error);
}
break;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 53712aaf69e..a0971b22d3d 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -112,17 +112,16 @@ class Key :public Sql_alloc {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
enum Keytype type;
- enum ha_key_alg algorithm;
+ KEY_CREATE_INFO key_create_info;
List<key_part_spec> columns;
const char *name;
bool generated;
- LEX_STRING *parser_name;
- Key(enum Keytype type_par, const char *name_arg, enum ha_key_alg alg_par,
- bool generated_arg, List<key_part_spec> &cols,
- LEX_STRING *parser_arg= 0)
- :type(type_par), algorithm(alg_par), columns(cols), name(name_arg),
- generated(generated_arg), parser_name(parser_arg)
+ Key(enum Keytype type_par, const char *name_arg,
+ KEY_CREATE_INFO *key_info_arg,
+ bool generated_arg, List<key_part_spec> &cols)
+ :type(type_par), key_create_info(*key_info_arg), columns(cols),
+ name(name_arg), generated(generated_arg)
{}
~Key() {}
/* Equality comparison of keys (ignoring name) */
@@ -144,7 +143,7 @@ public:
foreign_key(const char *name_arg, List<key_part_spec> &cols,
Table_ident *table, List<key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
ref_table(table), ref_columns(cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
@@ -241,11 +240,6 @@ struct system_variables
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;
- ulong sync_replication_timeout;
-#endif /* HAVE_REPLICATION */
my_bool innodb_table_locks;
my_bool innodb_support_xa;
my_bool ndb_force_send;
@@ -635,6 +629,8 @@ public:
{
return (*priv_host ? priv_host : (char *)"%");
}
+
+ bool set_user(char *user_arg);
};
@@ -776,6 +772,19 @@ public:
};
+/* Flags for the THD::system_thread variable */
+enum enum_thread_type
+{
+ NON_SYSTEM_THREAD= 0,
+ SYSTEM_THREAD_DELAYED_INSERT= 1,
+ SYSTEM_THREAD_SLAVE_IO= 2,
+ SYSTEM_THREAD_SLAVE_SQL= 4,
+ SYSTEM_THREAD_NDBCLUSTER_BINLOG= 8,
+ SYSTEM_THREAD_EVENT_SCHEDULER= 16,
+ SYSTEM_THREAD_EVENT_WORKER= 32
+};
+
+
/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor
@@ -1099,6 +1108,9 @@ public:
query_id_t query_id, warn_id;
ulong thread_id, col_access;
+#ifdef ERROR_INJECT_SUPPORT
+ ulong error_inject_value;
+#endif
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
ulong rand_saved_seed1, rand_saved_seed2;
@@ -1106,7 +1118,8 @@ public:
long dbug_thread_id;
pthread_t real_id;
uint tmp_table, global_read_lock;
- uint server_status,open_options,system_thread;
+ uint server_status,open_options;
+ enum enum_thread_type system_thread;
uint32 db_length;
uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
@@ -1383,6 +1396,7 @@ public:
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);
+#ifdef HAVE_ROW_BASED_REPLICATION
inline void set_current_stmt_binlog_row_based_if_mixed()
{
if (variables.binlog_format == BINLOG_FORMAT_MIXED)
@@ -1396,6 +1410,7 @@ public:
{
current_stmt_binlog_row_based= test(variables.binlog_format == BINLOG_FORMAT_ROW);
}
+#endif /*HAVE_ROW_BASED_REPLICATION*/
};
@@ -1405,11 +1420,6 @@ public:
#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
-#define SYSTEM_THREAD_SLAVE_IO 2
-#define SYSTEM_THREAD_SLAVE_SQL 4
-#define SYSTEM_THREAD_NDBCLUSTER_BINLOG 8
/*
Used to hold information about file and file structure in exchainge
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 3d035359b6f..6d5362c2554 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -871,7 +871,7 @@ bool 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 */
- (void)evex_drop_db_events(thd, db); /* QQ Ignore errors for now */
+ error= Events::drop_schema_events(thd, db);
start_waiting_global_read_lock(thd);
/*
If this database was the client's selected database, we silently change the
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 4365d5b04ce..44b0fe1a2f1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -21,7 +21,9 @@
*/
#include "mysql_priv.h"
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
#include "ha_innodb.h"
+#endif
#include "sql_select.h"
#include "sp_head.h"
#include "sql_trigger.h"
diff --git a/sql/sql_error.h b/sql/sql_error.h
index 223b50be744..b5cac24d894 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -40,3 +40,5 @@ 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);
+
+extern LEX_STRING warning_level_names[];
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 946c0536897..84760e93d8e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2518,23 +2518,179 @@ bool select_insert::send_eof()
CREATE TABLE (SELECT) ...
***************************************************************************/
-int
-select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
-{
- DBUG_ENTER("select_create::prepare");
+/*
+ Create table from lists of fields and items (or open existing table
+ with same name).
+
+ SYNOPSIS
+ create_table_from_items()
+ thd in Thread object
+ create_info in Create information (like MAX_ROWS, ENGINE or
+ temporary table flag)
+ create_table in Pointer to TABLE_LIST object providing database
+ and name for table to be created or to be open
+ extra_fields in/out Initial list of fields for table to be created
+ keys in List of keys for table to be created
+ items in List of items which should be used to produce rest
+ of fields for the table (corresponding fields will
+ be added to the end of 'extra_fields' list)
+ lock out Pointer to the MYSQL_LOCK object for table created
+ (open) will be returned in this parameter. Since
+ this table is not included in THD::lock caller is
+ responsible for explicitly unlocking this table.
+ hooks
+
+ NOTES
+ If 'create_info->options' bitmask has HA_LEX_CREATE_IF_NOT_EXISTS
+ flag and table with name provided already exists then this function will
+ simply open existing table.
+ Also note that create, open and lock sequence in this function is not
+ atomic and thus contains gap for deadlock and can cause other troubles.
+ Since this function contains some logic specific to CREATE TABLE ... SELECT
+ it should be changed before it can be used in other contexts.
+
+ RETURN VALUES
+ non-zero Pointer to TABLE object for table created or opened
+ 0 Error
+*/
- class MY_HOOKS : public TABLEOP_HOOKS {
- public:
- MY_HOOKS(select_create *x) : ptr(x) { }
- virtual void do_prelock(TABLE **tables, uint count)
+static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
+ TABLE_LIST *create_table,
+ List<create_field> *extra_fields,
+ List<Key> *keys,
+ List<Item> *items,
+ MYSQL_LOCK **lock,
+ TABLEOP_HOOKS *hooks)
+{
+ TABLE tmp_table; // Used during 'create_field()'
+ TABLE_SHARE share;
+ TABLE *table= 0;
+ uint select_field_count= items->elements;
+ /* Add selected items to field list */
+ List_iterator_fast<Item> it(*items);
+ Item *item;
+ Field *tmp_field;
+ bool not_used;
+ DBUG_ENTER("create_table_from_items");
+
+ tmp_table.alias= 0;
+ tmp_table.timestamp_field= 0;
+ tmp_table.s= &share;
+ init_tmp_table_share(&share, "", 0, "", "");
+
+ 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 == &myisam_hton ||
+ create_info->db_type == &heap_hton);
+ tmp_table.null_row=tmp_table.maybe_null=0;
+
+ while ((item=it++))
+ {
+ create_field *cr_field;
+ Field *field;
+ if (item->type() == Item::FUNC_ITEM)
+ 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, 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
+
+ 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().
+ NOTE: By locking table which we just have created (or for which we just have
+ have found that it already exists) separately from other tables used by the
+ statement we create potential window for deadlock.
+ TODO: create and open should be done atomic !
+ */
+ {
+ 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 (ptr->get_thd()->current_stmt_binlog_row_based)
- ptr->binlog_show_create_table(tables, count);
+ /*
+ If we are here in prelocked mode we either create temporary table
+ or prelocked mode is caused by the SELECT part of this statement.
+ */
+ DBUG_ASSERT(!thd->prelocked_mode ||
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ||
+ thd->lex->requires_prelocking());
+
+ /*
+ NOTE: We don't want to ignore set of locked tables here if we are
+ under explicit LOCK TABLES since it will open gap for deadlock
+ too wide (and also is not backward compatible).
+ */
+
+ if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
+ (MYSQL_LOCK_IGNORE_FLUSH |
+ ((thd->prelocked_mode == PRELOCKED) ?
+ MYSQL_OPEN_IGNORE_LOCKED_TABLES:0)))))
+ 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);
+ }
+
+ /*
+ 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;
+ hooks->prelock(&table, 1); // Call prelock hooks
+ 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, create_table->db,
+ table_case_name(create_info, create_table->table_name));
+ DBUG_RETURN(0);
+ }
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ DBUG_RETURN(table);
+}
- private:
- select_create *ptr;
- };
+
+class MY_HOOKS : public TABLEOP_HOOKS {
+public:
+ MY_HOOKS(select_create *x) : ptr(x) { }
+ virtual void do_prelock(TABLE **tables, uint count)
+ {
+ if (ptr->get_thd()->current_stmt_binlog_row_based)
+ ptr->binlog_show_create_table(tables, count);
+ }
+
+private:
+ select_create *ptr;
+};
+
+int
+select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
+{
+ DBUG_ENTER("select_create::prepare");
MY_HOOKS hooks(this);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5a76066af8c..02711ed8f48 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -168,8 +168,6 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
- 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= lex->orig_sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
@@ -197,8 +195,16 @@ void lex_start(THD *thd, const uchar *buf, uint length)
void lex_end(LEX *lex)
{
- x_free(lex->yacc_yyss);
- x_free(lex->yacc_yyvs);
+ DBUG_ENTER("lex_end");
+ DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
+ if (lex->yacc_yyss)
+ {
+ my_free(lex->yacc_yyss, MYF(0));
+ my_free(lex->yacc_yyvs, MYF(0));
+ lex->yacc_yyss= 0;
+ lex->yacc_yyvs= 0;
+ }
+ DBUG_VOID_RETURN;
}
@@ -313,18 +319,7 @@ static char *get_text(LEX *lex)
found_escape=1;
if (lex->ptr == lex->end_of_query)
return 0;
-#ifdef USE_MB
- int l;
- if (use_mb(cs) &&
- (l = my_ismbchar(cs,
- (const char *)lex->ptr,
- (const char *)lex->end_of_query))) {
- lex->ptr += l;
- continue;
- }
- else
-#endif
- yySkip();
+ yySkip();
}
else if (c == sep)
{
@@ -354,9 +349,6 @@ static char *get_text(LEX *lex)
{
uchar *to;
- /* Re-use found_escape for tracking state of escapes */
- found_escape= 0;
-
for (to=start ; str != end ; str++)
{
#ifdef USE_MB
@@ -370,8 +362,7 @@ static char *get_text(LEX *lex)
continue;
}
#endif
- if (!found_escape &&
- !(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
+ if (!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
*str == '\\' && str+1 != end)
{
switch(*++str) {
@@ -398,20 +389,14 @@ static char *get_text(LEX *lex)
*to++= '\\'; // remember prefix for wildcard
/* Fall through */
default:
- found_escape= 1;
- str--;
+ *to++= *str;
break;
}
}
- else if (!found_escape && *str == sep)
- {
- found_escape= 1;
- }
+ else if (*str == sep)
+ *to++= *str++; // Two ' or "
else
- {
*to++ = *str;
- found_escape= 0;
- }
}
*to=0;
lex->yytoklen=(uint) (to-start);
@@ -1633,7 +1618,8 @@ void st_select_lex::print_limit(THD *thd, String *str)
*/
st_lex::st_lex()
- :result(0), sql_command(SQLCOM_END), query_tables_own_last(0)
+ :result(0), yacc_yyss(0), yacc_yyvs(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();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index f5141806b38..12c7b106c26 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -110,8 +110,10 @@ enum enum_sql_command {
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS,
+ SQLCOM_SHOW_CONTRIBUTORS,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
- SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
+ SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
+ SQLCOM_SHOW_SCHEDULER_STATUS,
/* This should be the last !!! */
@@ -479,6 +481,7 @@ public:
void print(String *str);
+ bool add_fake_select_lex(THD *thd);
void init_prepare_fake_select_lex(THD *thd);
inline bool is_prepared() { return prepared; }
bool change_result(select_subselect *result, select_subselect *old_result);
@@ -839,6 +842,7 @@ typedef struct st_lex
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
+ KEY_CREATE_INFO key_create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
USER_RESOURCES mqh;
ulong type;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index c63a5c23d60..3206cfa2d52 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -68,7 +68,6 @@ 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);
static void remove_escape(char *name);
-static void refresh_status(THD *thd);
const char *any_db="*any*"; // Special symbol for check_access
@@ -138,7 +137,7 @@ static void unlock_locked_tables(THD *thd)
}
-static bool end_active_trans(THD *thd)
+bool end_active_trans(THD *thd)
{
int error=0;
DBUG_ENTER("end_active_trans");
@@ -1009,6 +1008,7 @@ static int check_connection(THD *thd)
char *user= end;
char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1;
char *db= passwd;
char db_buff[NAME_LEN+1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8
@@ -1023,22 +1023,37 @@ static int check_connection(THD *thd)
*passwd++ : strlen(passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
db + passwd_len + 1 : 0;
+ uint db_len= db ? strlen(db) : 0;
+
+ if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return ER_HANDSHAKE_ERROR;
+ }
/* Since 4.1 all database names are stored in utf8 */
if (db)
{
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
system_charset_info,
- db, strlen(db),
+ db, db_len,
thd->charset(), &dummy_errors)]= 0;
db= db_buff;
}
- user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1,
- system_charset_info, user, strlen(user),
- thd->charset(), &dummy_errors)]= '\0';
+ user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors)]= '\0';
user= user_buff;
+ /* If username starts and ends in "'", chop them off */
+ if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
+ {
+ user[user_len-1]= 0;
+ user++;
+ user_len-= 2;
+ }
+
if (thd->main_security_ctx.user)
x_free(thd->main_security_ctx.user);
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
@@ -1607,7 +1622,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
char *db, *tbl_name;
uint db_len= *(uchar*) packet;
+ if (db_len >= packet_length || db_len > NAME_LEN)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ break;
+ }
uint tbl_len= *(uchar*) (packet + db_len + 1);
+ if (db_len+tbl_len+2 > packet_length || tbl_len > NAME_LEN)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ break;
+ }
statistic_increment(thd->status_var.com_other, &LOCK_status);
thd->enable_slow_log= opt_log_slow_admin_statements;
@@ -1728,7 +1753,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query + thd->query_length;
- general_log_print(thd, command, "%s", thd->query);
+ general_log_print(thd, command, "%.*b", thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2024,7 +2049,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status);
ulong id=(ulong) uint4korr(packet);
- kill_one_thread(thd,id,false);
+ sql_kill(thd,id,false);
break;
}
case COM_SET_OPTION:
@@ -2443,8 +2468,10 @@ mysql_execute_command(THD *thd)
statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status);
+#ifdef HAVE_ROW_BASED_REPLICATION
if (lex->binlog_row_based_if_mixed)
thd->set_current_stmt_binlog_row_based_if_mixed();
+#endif /*HAVE_ROW_BASED_REPLICATION*/
switch (lex->sql_command) {
case SQLCOM_SELECT:
@@ -2830,6 +2857,17 @@ mysql_execute_command(THD *thd)
res= 1;
goto end_with_restore_list;
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ {
+ partition_info *part_info= thd->lex->part_info;
+ if (part_info && !(part_info= thd->lex->part_info->get_clone()))
+ {
+ res= -1;
+ goto end_with_restore_list;
+ }
+ thd->work_part_info= part_info;
+ }
+#endif
if (select_lex->item_list.elements) // With select
{
select_result *result;
@@ -2899,15 +2937,6 @@ mysql_execute_command(THD *thd)
lex->like_name);
else
{
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- partition_info *part_info= thd->lex->part_info;
- if (part_info && !(part_info= thd->lex->part_info->get_clone()))
- {
- res= -1;
- goto end_with_restore_list;
- }
- thd->work_part_info= part_info;
-#endif
res= mysql_create_table(thd, create_table->db,
create_table->table_name, &lex->create_info,
lex->create_list,
@@ -2936,8 +2965,7 @@ end_with_restore_list:
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
goto error;
- else
- res = mysql_create_index(thd, first_table, lex->key_list);
+ res= mysql_create_index(thd, first_table, lex->key_list);
break;
#ifdef HAVE_REPLICATION
@@ -3044,18 +3072,16 @@ end_with_restore_list:
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
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,
- 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,
- 1);
- }
+
+ thd->enable_slow_log= opt_log_slow_admin_statements;
+ res= mysql_alter_table(thd, select_lex->db, lex->name,
+ &lex->create_info,
+ first_table, lex->create_list,
+ lex->key_list,
+ select_lex->order_list.elements,
+ (ORDER *) select_lex->order_list.first,
+ lex->duplicates, lex->ignore, &lex->alter_info,
+ 1);
break;
}
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
@@ -3182,7 +3208,7 @@ end_with_restore_list:
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, first_table, &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)
{
@@ -3487,8 +3513,7 @@ end_with_restore_list:
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
- else
- res = mysql_drop_index(thd, first_table, &lex->alter_info);
+ res= mysql_drop_index(thd, first_table, &lex->alter_info);
break;
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
@@ -3506,6 +3531,9 @@ end_with_restore_list:
case SQLCOM_SHOW_AUTHORS:
res= mysqld_show_authors(thd);
break;
+ case SQLCOM_SHOW_CONTRIBUTORS:
+ res= mysqld_show_contributors(thd);
+ break;
case SQLCOM_SHOW_PRIVILEGES:
res= mysqld_show_privileges(thd);
break;
@@ -3811,14 +3839,17 @@ end_with_restore_list:
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
- res= evex_create_event(thd, lex->et, (uint) lex->create_info.options,
- &rows_affected);
+ res= Events::create_event(thd, lex->et,
+ (uint) lex->create_info.options,
+ &rows_affected);
break;
case SQLCOM_ALTER_EVENT:
- res= evex_update_event(thd, lex->et, lex->spname, &rows_affected);
+ res= Events::update_event(thd, lex->et, lex->spname,
+ &rows_affected);
break;
case SQLCOM_DROP_EVENT:
- res= evex_drop_event(thd, lex->et, lex->drop_if_exists, &rows_affected);
+ res= Events::drop_event(thd, lex->et, lex->drop_if_exists,
+ &rows_affected);
default:;
}
DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
@@ -3856,9 +3887,16 @@ end_with_restore_list:
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
goto error;
}
- res= evex_show_create_event(thd, lex->spname, lex->et->definer);
+ res= Events::show_create_event(thd, lex->spname);
+ break;
+ }
+#ifndef DBUG_OFF
+ case SQLCOM_SHOW_SCHEDULER_STATUS:
+ {
+ res= Events::dump_internal_status(thd);
break;
}
+#endif
case SQLCOM_CREATE_FUNCTION: // UDF function
{
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
@@ -3961,7 +3999,6 @@ end_with_restore_list:
if (thd->security_ctx->user) // If not replication
{
LEX_USER *user;
- uint counter;
List_iterator <LEX_USER> user_list(lex->users_list);
while ((user= user_list++))
@@ -3979,7 +4016,8 @@ end_with_restore_list:
user->host.str, thd->security_ctx->host_or_ip))
{
// TODO: use check_change_password()
- if (check_acl_user(user, &counter) && user->password.str &&
+ if (is_acl_user(user->host.str, user->user.str) &&
+ user->password.str &&
check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
{
my_message(ER_PASSWORD_NOT_ALLOWED,
@@ -4098,7 +4136,7 @@ end_with_restore_list:
MYF(0));
goto error;
}
- kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
+ sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
break;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -5110,7 +5148,9 @@ end:
*/
if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
reset_one_shot_variables(thd);
+#ifdef HAVE_ROW_BASED_REPLICATION
thd->reset_current_stmt_binlog_row_based();
+#endif /*HAVE_ROW_BASED_REPLICATION*/
/*
The return value for ROW_COUNT() is "implementation dependent" if the
@@ -5724,48 +5764,17 @@ mysql_new_select(LEX *lex, bool move_down)
}
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)
- {
- /*
- 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 (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= 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_UNIT *unit= select_lex->master_unit();
+ if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
+ DBUG_RETURN(1);
+ select_lex->context.outer_context=
+ unit->first_select()->context.outer_context;
}
select_lex->master_unit()->global_parameters= select_lex;
@@ -5898,6 +5907,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
}
else
{
+ DBUG_ASSERT(thd->net.report_error);
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
query_cache_abort(&thd->net);
@@ -5979,14 +5989,16 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (type_modifier & PRI_KEY_FLAG)
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
+ lex->key_list.push_back(new Key(Key::PRIMARY, NullS,
+ &default_key_create_info,
0, lex->col_list));
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
+ lex->key_list.push_back(new Key(Key::UNIQUE, NullS,
+ &default_key_create_info, 0,
lex->col_list));
lex->col_list.empty();
}
@@ -6550,6 +6562,68 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
/*
+ Create a fake SELECT_LEX for a unit
+
+ SYNOPSIS:
+ add_fake_select_lex()
+ thd thread handle
+
+ DESCRIPTION
+ The method create a fake SELECT_LEX object for a unit.
+ This object is created for any union construct containing a union
+ operation and also for any single select union construct of the form
+ (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
+ or of the form
+ (SELECT ... ORDER BY LIMIT n) ORDER BY ...
+
+ NOTES
+ The object is used to retrieve rows from the temporary table
+ where the result on the union is obtained.
+
+ RETURN VALUES
+ 1 on failure to create the object
+ 0 on success
+*/
+
+bool st_select_lex_unit::add_fake_select_lex(THD *thd)
+{
+ SELECT_LEX *first_sl= first_select();
+ DBUG_ENTER("add_fake_select_lex");
+ DBUG_ASSERT(!fake_select_lex);
+
+ if (!(fake_select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ fake_select_lex->include_standalone(this,
+ (SELECT_LEX_NODE**)&fake_select_lex);
+ fake_select_lex->select_number= INT_MAX;
+ fake_select_lex->parent_lex= thd->lex; /* Used in init_query. */
+ fake_select_lex->make_empty_select();
+ fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
+ fake_select_lex->select_limit= 0;
+
+ fake_select_lex->context.outer_context=first_sl->context.outer_context;
+ /* allow item list resolving in fake select for ORDER BY */
+ fake_select_lex->context.resolve_in_select_list= TRUE;
+ fake_select_lex->context.select_lex= fake_select_lex;
+
+ if (!first_sl->next_select())
+ {
+ /*
+ This works only for
+ (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
+ (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
+ just before the parser starts processing order_list
+ */
+ global_parameters= fake_select_lex;
+ fake_select_lex->no_table_names_allowed= 1;
+ thd->lex->current_select= fake_select_lex;
+ }
+ thd->lex->pop_context();
+ DBUG_RETURN(0);
+}
+
+
+/*
Push a new name resolution context for a JOIN ... ON clause to the
context stack of a query block.
@@ -6856,22 +6930,26 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
return result;
}
+
/*
- kill on thread
+ kills a thread
SYNOPSIS
kill_one_thread()
thd Thread class
id Thread id
+ only_kill_query Should it kill the query or the connection
NOTES
This is written such that we have a short lock on LOCK_thread_count
*/
-void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
+uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
{
THD *tmp;
uint error=ER_NO_SUCH_THREAD;
+ DBUG_ENTER("kill_one_thread");
+ DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query));
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
@@ -6897,31 +6975,28 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
error=ER_KILL_DENIED_ERROR;
pthread_mutex_unlock(&tmp->LOCK_delete);
}
-
- if (!error)
- send_ok(thd);
- else
- my_error(error, MYF(0), id);
+ DBUG_PRINT("exit", ("%d", error));
+ DBUG_RETURN(error);
}
-/* Clear most status variables */
-
-static void refresh_status(THD *thd)
-{
- pthread_mutex_lock(&LOCK_status);
-
- /* 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));
+/*
+ kills a thread and sends response
- for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++)
- if (ptr->type == SHOW_LONG) // note that SHOW_LONG_NOFLUSH variables are not reset
- *(ulong*) ptr->value= 0;
+ SYNOPSIS
+ sql_kill()
+ thd Thread class
+ id Thread id
+ only_kill_query Should it kill the query or the connection
+*/
- /* Reset the counters of all key caches (default and named). */
- process_key_caches(reset_key_cache_counters);
- pthread_mutex_unlock(&LOCK_status);
+void sql_kill(THD *thd, ulong id, bool only_kill_query)
+{
+ uint error;
+ if (!(error= kill_one_thread(thd, id, only_kill_query)))
+ send_ok(thd);
+ else
+ my_error(error, MYF(0), id);
}
@@ -7386,7 +7461,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
lex->create_info.merge_list.first))
goto err;
if (grant_option && want_priv != CREATE_TMP_ACL &&
- check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0))
+ check_grant(thd, want_priv, create_table, 0, 1, 0))
goto err;
if (select_lex->item_list.elements)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index aae80f07b71..e946e972968 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1792,15 +1792,10 @@ char *generate_partition_syntax(partition_info *part_info,
char path[FN_REFLEN];
int err= 0;
List_iterator<partition_element> part_it(part_info->partitions);
- List_iterator<partition_element> temp_it(part_info->temp_partitions);
File fptr;
char *buf= NULL; //Return buffer
- uint use_temp= 0;
- uint no_temp_parts= part_info->temp_partitions.elements;
- bool write_part_state;
DBUG_ENTER("generate_partition_syntax");
- write_part_state= (part_info->part_state && !part_info->part_state_len);
if (unlikely(((fptr= create_temp_file(path,mysql_tmpdir,"psy",
O_RDWR | O_BINARY | O_TRUNC |
O_TEMPORARY, MYF(MY_WME)))) < 0))
@@ -1865,67 +1860,26 @@ char *generate_partition_syntax(partition_info *part_info,
err+= add_space(fptr);
}
}
- no_parts= part_info->no_parts;
- tot_no_parts= no_parts + no_temp_parts;
+ tot_no_parts= part_info->partitions.elements;
no_subparts= part_info->no_subparts;
if (write_all || (!part_info->use_default_partitions))
{
+ bool first= TRUE;
err+= add_begin_parenthesis(fptr);
i= 0;
do
{
- /*
- We need to do some clever list manipulation here since we have two
- different needs for our list processing and here we take some of the
- cost of using a simpler list processing for the other parts of the
- code.
-
- ALTER TABLE REORGANIZE PARTITIONS has the list of partitions to be
- the final list as the main list and the reorganised partitions is in
- the temporary partition list. Thus when finding the first part added
- we insert the temporary list if there is such a list. If there is no
- temporary list we are performing an ADD PARTITION.
- */
- if (use_temp && use_temp <= no_temp_parts)
- {
- part_elem= temp_it++;
- DBUG_ASSERT(no_temp_parts);
- no_temp_parts--;
- }
- else if (use_temp)
- {
- DBUG_ASSERT(no_parts);
- part_elem= save_part_elem;
- use_temp= 0;
- no_parts--;
- }
- else
- {
- part_elem= part_it++;
- if ((part_elem->part_state == PART_TO_BE_ADDED ||
- part_elem->part_state == PART_IS_ADDED) && no_temp_parts)
- {
- save_part_elem= part_elem;
- part_elem= temp_it++;
- no_temp_parts--;
- use_temp= 1;
- }
- else
- {
- DBUG_ASSERT(no_parts);
- no_parts--;
- }
- }
-
- if (part_elem->part_state != PART_IS_DROPPED)
+ part_elem= part_it++;
+ if (part_elem->part_state != PART_TO_BE_DROPPED &&
+ part_elem->part_state != PART_REORGED_DROPPED)
{
- if (write_part_state)
+ if (!first)
{
- uint32 part_state_id= part_info->part_state_len;
- part_info->part_state[part_state_id]= (uchar)part_elem->part_state;
- part_info->part_state_len= part_state_id+1;
+ err+= add_comma(fptr);
+ err+= add_space(fptr);
}
+ first= FALSE;
err+= add_partition(fptr);
err+= add_name_string(fptr, part_elem->partition_name);
err+= add_space(fptr);
@@ -1955,16 +1909,10 @@ char *generate_partition_syntax(partition_info *part_info,
err+= add_end_parenthesis(fptr);
} while (++j < no_subparts);
}
- if (i != (tot_no_parts-1))
- {
- err+= add_comma(fptr);
- err+= add_space(fptr);
- }
}
if (i == (tot_no_parts-1))
err+= add_end_parenthesis(fptr);
} while (++i < tot_no_parts);
- DBUG_ASSERT(!no_parts && !no_temp_parts);
}
if (err)
goto close_file;
@@ -3482,6 +3430,7 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
result= FALSE;
end:
+ lex_end(thd->lex);
thd->free_list= thd_free_list;
thd->lex= old_lex;
thd->variables.character_set_client= old_character_set_client;
@@ -3527,27 +3476,6 @@ set_engine_all_partitions(partition_info *part_info,
}
/*
SYNOPSIS
- fast_alter_partition_error_handler()
- lpt Container for parameters
-
- RETURN VALUES
- None
-
- DESCRIPTION
- Support routine to clean up after failures of on-line ALTER TABLE
- for partition management.
-*/
-
-static void fast_alter_partition_error_handler(ALTER_PARTITION_PARAM_TYPE *lpt)
-{
- DBUG_ENTER("fast_alter_partition_error_handler");
- /* TODO: WL 2826 Error handling */
- DBUG_VOID_RETURN;
-}
-
-
-/*
- SYNOPSIS
fast_end_partition()
thd Thread object
out:copied Number of records copied
@@ -3567,6 +3495,7 @@ static void fast_alter_partition_error_handler(ALTER_PARTITION_PARAM_TYPE *lpt)
static int fast_end_partition(THD *thd, ulonglong copied,
ulonglong deleted,
+ TABLE *table,
TABLE_LIST *table_list, bool is_empty,
ALTER_PARTITION_PARAM_TYPE *lpt,
bool written_bin_log)
@@ -3594,7 +3523,7 @@ static int fast_end_partition(THD *thd, ulonglong copied,
send_ok(thd,copied+deleted,0L,tmp_name);
DBUG_RETURN(FALSE);
}
- fast_alter_partition_error_handler(lpt);
+ table->file->print_error(error, MYF(0));
DBUG_RETURN(TRUE);
}
@@ -3843,7 +3772,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
after the change as before. Thus we can reply ok immediately
without any changes at all.
*/
- DBUG_RETURN(fast_end_partition(thd, ULL(0), ULL(0), NULL,
+ DBUG_RETURN(fast_end_partition(thd, ULL(0), ULL(0),
+ table, NULL,
TRUE, NULL, FALSE));
}
else if (new_part_no > curr_part_no)
@@ -4146,6 +4076,7 @@ that are reorganised.
tab_part_info->use_default_partitions= FALSE;
}
tab_part_info->use_default_no_partitions= FALSE;
+ tab_part_info->is_auto_partitioned= FALSE;
}
}
else if (alter_info->flags == ALTER_DROP_PARTITION)
@@ -4161,6 +4092,8 @@ that are reorganised.
uint no_parts_dropped= alter_info->partition_names.elements;
uint no_parts_found= 0;
List_iterator<partition_element> part_it(tab_part_info->partitions);
+
+ tab_part_info->is_auto_partitioned= FALSE;
if (!(tab_part_info->part_type == RANGE_PARTITION ||
tab_part_info->part_type == LIST_PARTITION))
{
@@ -4195,6 +4128,7 @@ that are reorganised.
my_error(ER_ROW_IS_REFERENCED, MYF(0));
DBUG_RETURN(TRUE);
}
+ tab_part_info->no_parts-= no_parts_dropped;
}
else if ((alter_info->flags & ALTER_OPTIMIZE_PARTITION) ||
(alter_info->flags & ALTER_ANALYZE_PARTITION) ||
@@ -4239,6 +4173,11 @@ that are reorganised.
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), ptr);
DBUG_RETURN(TRUE);
}
+ if (!(*fast_alter_partition))
+ {
+ table->file->print_error(HA_ERR_WRONG_COMMAND, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
}
else if (alter_info->flags & ALTER_COALESCE_PARTITION)
{
@@ -4339,7 +4278,10 @@ state of p1.
tab_part_info->no_parts= no_parts_remain;
}
if (!(alter_info->flags & ALTER_TABLE_REORG))
+ {
tab_part_info->use_default_no_partitions= FALSE;
+ tab_part_info->is_auto_partitioned= FALSE;
+ }
}
else if (alter_info->flags == ALTER_REORGANIZE_PARTITION)
{
@@ -4358,6 +4300,8 @@ state of p1.
uint no_parts_new= thd->work_part_info->partitions.elements;
partition_info *alt_part_info= thd->work_part_info;
uint check_total_partitions;
+
+ tab_part_info->is_auto_partitioned= FALSE;
if (no_parts_reorged > tab_part_info->no_parts)
{
my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
@@ -4574,7 +4518,7 @@ the generated partition syntax in a correct manner.
if (alter_info->flags & ALTER_REMOVE_PARTITIONING)
{
DBUG_PRINT("info", ("Remove partitioning"));
- if (!(thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE))
+ if (!(create_info->used_fields & HA_CREATE_USED_ENGINE))
{
DBUG_PRINT("info", ("No explicit engine used"));
create_info->db_type= table->part_info->default_engine_type;
@@ -4591,13 +4535,29 @@ the generated partition syntax in a correct manner.
beneath.
*/
thd->work_part_info= table->part_info;
- if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE &&
+ if (create_info->used_fields & HA_CREATE_USED_ENGINE &&
create_info->db_type != table->part_info->default_engine_type)
{
/*
Make sure change of engine happens to all partitions.
*/
- set_engine_all_partitions(thd->work_part_info, create_info->db_type);
+ DBUG_PRINT("info", ("partition changed"));
+ if (table->part_info->is_auto_partitioned)
+ {
+ /*
+ If the user originally didn't specify partitioning to be
+ used we can remove it now.
+ */
+ thd->work_part_info= NULL;
+ }
+ else
+ {
+ /*
+ Ensure that all partitions have the proper engine set-up
+ */
+ set_engine_all_partitions(thd->work_part_info,
+ create_info->db_type);
+ }
*partition_changed= TRUE;
}
}
@@ -4611,7 +4571,10 @@ the generated partition syntax in a correct manner.
using the partition handler.
*/
if (thd->work_part_info != table->part_info)
+ {
+ DBUG_PRINT("info", ("partition changed"));
*partition_changed= TRUE;
+ }
if (create_info->db_type == &partition_hton)
part_info->default_engine_type= table->part_info->default_engine_type;
else
@@ -4663,14 +4626,22 @@ the generated partition syntax in a correct manner.
static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
{
char path[FN_REFLEN+1];
+ int error;
+ handler *file= lpt->table->file;
DBUG_ENTER("mysql_change_partitions");
build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "");
- DBUG_RETURN(lpt->table->file->change_partitions(lpt->create_info, path,
- &lpt->copied,
- &lpt->deleted,
- lpt->pack_frm_data,
- lpt->pack_frm_len));
+ if ((error= file->change_partitions(lpt->create_info, path, &lpt->copied,
+ &lpt->deleted, lpt->pack_frm_data,
+ lpt->pack_frm_len)))
+ {
+ if (error != ER_OUTOFMEMORY)
+ file->print_error(error, MYF(0));
+ else
+ lpt->thd->fatal_error();
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
}
@@ -4696,10 +4667,17 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
static bool mysql_rename_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
{
char path[FN_REFLEN+1];
+ int error;
DBUG_ENTER("mysql_rename_partitions");
build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "");
- DBUG_RETURN(lpt->table->file->rename_partitions(path));
+ if ((error= lpt->table->file->rename_partitions(path)))
+ {
+ if (error != 1)
+ lpt->table->file->print_error(error, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
}
@@ -4730,11 +4708,13 @@ static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
List_iterator<partition_element> part_it(part_info->partitions);
uint i= 0;
uint remove_count= 0;
+ int error;
DBUG_ENTER("mysql_drop_partitions");
build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "");
- if (lpt->table->file->drop_partitions(path))
+ if ((error= lpt->table->file->drop_partitions(path)))
{
+ lpt->table->file->print_error(error, MYF(0));
DBUG_RETURN(TRUE);
}
do
@@ -4752,6 +4732,767 @@ static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
/*
+ Insert log entry into list
+ SYNOPSIS
+ insert_part_info_log_entry_list()
+ log_entry
+ RETURN VALUES
+ NONE
+*/
+
+static void insert_part_info_log_entry_list(partition_info *part_info,
+ DDL_LOG_MEMORY_ENTRY *log_entry)
+{
+ log_entry->next_active_log_entry= part_info->first_log_entry;
+ part_info->first_log_entry= log_entry;
+}
+
+
+/*
+ Release all log entries for this partition info struct
+ SYNOPSIS
+ release_part_info_log_entries()
+ first_log_entry First log entry in list to release
+ RETURN VALUES
+ NONE
+*/
+
+static void release_part_info_log_entries(DDL_LOG_MEMORY_ENTRY *log_entry)
+{
+ DBUG_ENTER("release_part_info_log_entries");
+
+ while (log_entry)
+ {
+ release_ddl_log_memory_entry(log_entry);
+ log_entry= log_entry->next_active_log_entry;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Log an delete/rename frm file
+ SYNOPSIS
+ write_log_replace_delete_frm()
+ lpt Struct for parameters
+ next_entry Next reference to use in log record
+ from_path Name to rename from
+ to_path Name to rename to
+ replace_flag TRUE if replace, else delete
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Support routine that writes a replace or delete of an frm file into the
+ ddl log. It also inserts an entry that keeps track of used space into
+ the partition info object
+*/
+
+static bool write_log_replace_delete_frm(ALTER_PARTITION_PARAM_TYPE *lpt,
+ uint next_entry,
+ const char *from_path,
+ const char *to_path,
+ bool replace_flag)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DBUG_ENTER("write_log_replace_delete_frm");
+
+ if (replace_flag)
+ ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
+ else
+ ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
+ ddl_log_entry.next_entry= next_entry;
+ ddl_log_entry.handler_name= reg_ext;
+ ddl_log_entry.name= to_path;
+ if (replace_flag)
+ ddl_log_entry.from_name= from_path;
+ if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ insert_part_info_log_entry_list(lpt->part_info, log_entry);
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Log final partition changes in change partition
+ SYNOPSIS
+ write_log_changed_partitions()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ This code is used to perform safe ADD PARTITION for HASH partitions
+ and COALESCE for HASH partitions and REORGANIZE for any type of
+ partitions.
+ We prepare entries for all partitions except the reorganised partitions
+ in REORGANIZE partition, those are handled by
+ write_log_dropped_partitions. For those partitions that are replaced
+ special care is needed to ensure that this is performed correctly and
+ this requires a two-phased approach with this log as a helper for this.
+
+ This code is closely intertwined with the code in rename_partitions in
+ the partition handler.
+*/
+
+static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
+ uint *next_entry, const char *path)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ char tmp_path[FN_LEN];
+ char normal_path[FN_LEN];
+ List_iterator<partition_element> part_it(part_info->partitions);
+ uint temp_partitions= part_info->temp_partitions.elements;
+ uint no_elements= part_info->partitions.elements;
+ uint i= 0;
+ DBUG_ENTER("write_log_changed_partitions");
+
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_IS_CHANGED ||
+ (part_elem->part_state == PART_IS_ADDED && temp_partitions))
+ {
+ if (part_info->is_sub_partitioned())
+ {
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ uint no_subparts= part_info->no_subparts;
+ uint j= 0;
+ do
+ {
+ partition_element *sub_elem= sub_it++;
+ ddl_log_entry.next_entry= *next_entry;
+ ddl_log_entry.handler_name=
+ ha_resolve_storage_engine_name(sub_elem->engine_type);
+ create_subpartition_name(tmp_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ TEMP_PART_NAME);
+ create_subpartition_name(normal_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ NORMAL_PART_NAME);
+ ddl_log_entry.name= normal_path;
+ ddl_log_entry.from_name= tmp_path;
+ if (part_elem->part_state == PART_IS_CHANGED)
+ ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
+ else
+ ddl_log_entry.action_type= DDL_LOG_RENAME_ACTION;
+ if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ sub_elem->log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ } while (++j < no_subparts);
+ }
+ else
+ {
+ ddl_log_entry.next_entry= *next_entry;
+ ddl_log_entry.handler_name=
+ ha_resolve_storage_engine_name(part_elem->engine_type);
+ create_partition_name(tmp_path, path,
+ part_elem->partition_name,
+ TEMP_PART_NAME, TRUE);
+ create_partition_name(normal_path, path,
+ part_elem->partition_name,
+ NORMAL_PART_NAME, TRUE);
+ ddl_log_entry.name= normal_path;
+ ddl_log_entry.from_name= tmp_path;
+ if (part_elem->part_state == PART_IS_CHANGED)
+ ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
+ else
+ ddl_log_entry.action_type= DDL_LOG_RENAME_ACTION;
+ if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ part_elem->log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ }
+ }
+ } while (++i < no_elements);
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Log dropped partitions
+ SYNOPSIS
+ write_log_dropped_partitions()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
+ uint *next_entry,
+ const char *path,
+ bool temp_list)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ char tmp_path[FN_LEN];
+ List_iterator<partition_element> part_it(part_info->partitions);
+ List_iterator<partition_element> temp_it(part_info->temp_partitions);
+ uint no_temp_partitions= part_info->temp_partitions.elements;
+ uint no_elements= part_info->partitions.elements;
+ uint i= 0;
+ DBUG_ENTER("write_log_dropped_partitions");
+
+ ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
+ if (temp_list)
+ no_elements= no_temp_partitions;
+ while (no_elements--)
+ {
+ partition_element *part_elem;
+ if (temp_list)
+ part_elem= temp_it++;
+ else
+ part_elem= part_it++;
+ if (part_elem->part_state == PART_TO_BE_DROPPED ||
+ part_elem->part_state == PART_TO_BE_ADDED ||
+ part_elem->part_state == PART_CHANGED)
+ {
+ uint name_variant;
+ if (part_elem->part_state == PART_CHANGED ||
+ (part_elem->part_state == PART_TO_BE_ADDED &&
+ no_temp_partitions))
+ name_variant= TEMP_PART_NAME;
+ else
+ name_variant= NORMAL_PART_NAME;
+ if (part_info->is_sub_partitioned())
+ {
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ uint no_subparts= part_info->no_subparts;
+ uint j= 0;
+ do
+ {
+ partition_element *sub_elem= sub_it++;
+ ddl_log_entry.next_entry= *next_entry;
+ ddl_log_entry.handler_name=
+ ha_resolve_storage_engine_name(sub_elem->engine_type);
+ create_subpartition_name(tmp_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ name_variant);
+ ddl_log_entry.name= tmp_path;
+ if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ if (temp_list)
+ sub_elem->log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ } while (++j < no_subparts);
+ }
+ else
+ {
+ ddl_log_entry.next_entry= *next_entry;
+ ddl_log_entry.handler_name=
+ ha_resolve_storage_engine_name(part_elem->engine_type);
+ create_partition_name(tmp_path, path,
+ part_elem->partition_name,
+ name_variant, TRUE);
+ ddl_log_entry.name= tmp_path;
+ if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ if (temp_list)
+ part_elem->log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Set execute log entry in ddl log for this partitioned table
+ SYNOPSIS
+ set_part_info_exec_log_entry()
+ part_info Partition info object
+ exec_log_entry Log entry
+ RETURN VALUES
+ NONE
+*/
+
+static void set_part_info_exec_log_entry(partition_info *part_info,
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry)
+{
+ part_info->exec_log_entry= exec_log_entry;
+ exec_log_entry->next_active_log_entry= NULL;
+}
+
+
+/*
+ Write the log entry to ensure that the shadow frm file is removed at
+ crash.
+ SYNOPSIS
+ write_log_drop_shadow_frm()
+ lpt Struct containing parameters
+ install_frm Should we log action to install shadow frm or should
+ the action be to remove the shadow frm file.
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Prepare an entry to the ddl log indicating a drop/install of the shadow frm
+ file and its corresponding handler file.
+*/
+
+static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL;
+ char shadow_path[FN_LEN];
+ DBUG_ENTER("write_log_drop_shadow_frm");
+
+ build_table_filename(shadow_path, sizeof(shadow_path), lpt->db,
+ lpt->table_name, "#");
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_log_replace_delete_frm(lpt, 0UL, NULL,
+ (const char*)shadow_path, FALSE))
+ goto error;
+ log_entry= part_info->first_log_entry;
+ if (write_execute_ddl_log_entry(log_entry->entry_pos,
+ FALSE, &exec_log_entry))
+ goto error;
+ pthread_mutex_unlock(&LOCK_gdl);
+ set_part_info_exec_log_entry(part_info, exec_log_entry);
+ DBUG_RETURN(FALSE);
+
+error:
+ release_part_info_log_entries(part_info->first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= NULL;
+ my_error(ER_DDL_LOG_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Log renaming of shadow frm to real frm name and dropping of old frm
+ SYNOPSIS
+ write_log_rename_frm()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Prepare an entry to ensure that we complete the renaming of the frm
+ file if failure occurs in the middle of the rename process.
+*/
+
+static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
+ char path[FN_LEN];
+ char shadow_path[FN_LEN];
+ DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
+ DBUG_ENTER("write_log_rename_frm");
+
+ part_info->first_log_entry= NULL;
+ build_table_filename(path, sizeof(path), lpt->db,
+ lpt->table_name, "");
+ build_table_filename(shadow_path, sizeof(shadow_path), lpt->db,
+ lpt->table_name, "#");
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE))
+ goto error;
+ log_entry= part_info->first_log_entry;
+ part_info->frm_log_entry= log_entry;
+ if (write_execute_ddl_log_entry(log_entry->entry_pos,
+ FALSE, &exec_log_entry))
+ goto error;
+ release_part_info_log_entries(old_first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ DBUG_RETURN(FALSE);
+
+error:
+ release_part_info_log_entries(part_info->first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= old_first_log_entry;
+ part_info->frm_log_entry= NULL;
+ my_error(ER_DDL_LOG_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Write the log entries to ensure that the drop partition command is completed
+ even in the presence of a crash.
+
+ SYNOPSIS
+ write_log_drop_partition()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Prepare entries to the ddl log indicating all partitions to drop and to
+ install the shadow frm file and remove the old frm file.
+*/
+
+static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
+ char tmp_path[FN_LEN];
+ char path[FN_LEN];
+ uint next_entry= 0;
+ DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
+ DBUG_ENTER("write_log_drop_partition");
+
+ part_info->first_log_entry= NULL;
+ build_table_filename(path, sizeof(path), lpt->db,
+ lpt->table_name, "");
+ build_table_filename(tmp_path, sizeof(tmp_path), lpt->db,
+ lpt->table_name, "#");
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
+ FALSE))
+ goto error;
+ if (write_log_replace_delete_frm(lpt, next_entry, (const char*)tmp_path,
+ (const char*)path, TRUE))
+ goto error;
+ log_entry= part_info->first_log_entry;
+ part_info->frm_log_entry= log_entry;
+ if (write_execute_ddl_log_entry(log_entry->entry_pos,
+ FALSE, &exec_log_entry))
+ goto error;
+ release_part_info_log_entries(old_first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ DBUG_RETURN(FALSE);
+
+error:
+ release_part_info_log_entries(part_info->first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= old_first_log_entry;
+ part_info->frm_log_entry= NULL;
+ my_error(ER_DDL_LOG_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Write the log entries to ensure that the add partition command is not
+ executed at all if a crash before it has completed
+
+ SYNOPSIS
+ write_log_add_change_partition()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Prepare entries to the ddl log indicating all partitions to drop and to
+ remove the shadow frm file.
+ We always inject entries backwards in the list in the ddl log since we
+ don't know the entry position until we have written it.
+*/
+
+static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL;
+ char tmp_path[FN_LEN];
+ char path[FN_LEN];
+ uint next_entry= 0;
+ DBUG_ENTER("write_log_add_change_partition");
+
+ build_table_filename(path, sizeof(path), lpt->db,
+ lpt->table_name, "");
+ build_table_filename(tmp_path, sizeof(tmp_path), lpt->db,
+ lpt->table_name, "#");
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
+ FALSE))
+ goto error;
+ if (write_log_replace_delete_frm(lpt, next_entry, NULL, tmp_path,
+ FALSE))
+ goto error;
+ log_entry= part_info->first_log_entry;
+ if (write_execute_ddl_log_entry(log_entry->entry_pos,
+ FALSE, &exec_log_entry))
+ goto error;
+ pthread_mutex_unlock(&LOCK_gdl);
+ set_part_info_exec_log_entry(part_info, exec_log_entry);
+ DBUG_RETURN(FALSE);
+
+error:
+ release_part_info_log_entries(part_info->first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= NULL;
+ my_error(ER_DDL_LOG_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Write description of how to complete the operation after first phase of
+ change partitions.
+
+ SYNOPSIS
+ write_log_final_change_partition()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ We will write log entries that specify to remove all partitions reorganised,
+ to rename others to reflect the new naming scheme and to install the shadow
+ frm file.
+*/
+
+static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ partition_info *part_info= lpt->part_info;
+ DDL_LOG_MEMORY_ENTRY *log_entry;
+ DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
+ char path[FN_LEN];
+ char shadow_path[FN_LEN];
+ DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
+ uint next_entry= 0;
+ DBUG_ENTER("write_log_final_change_partition");
+
+ part_info->first_log_entry= NULL;
+ build_table_filename(path, sizeof(path), lpt->db,
+ lpt->table_name, "");
+ build_table_filename(shadow_path, sizeof(shadow_path), lpt->db,
+ lpt->table_name, "#");
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
+ TRUE))
+ goto error;
+ if (write_log_changed_partitions(lpt, &next_entry, (const char*)path))
+ goto error;
+ if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE))
+ goto error;
+ log_entry= part_info->first_log_entry;
+ part_info->frm_log_entry= log_entry;
+ if (write_execute_ddl_log_entry(log_entry->entry_pos,
+ FALSE, &exec_log_entry))
+ goto error;
+ release_part_info_log_entries(old_first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ DBUG_RETURN(FALSE);
+
+error:
+ release_part_info_log_entries(part_info->first_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= old_first_log_entry;
+ part_info->frm_log_entry= NULL;
+ my_error(ER_DDL_LOG_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Remove entry from ddl log and release resources for others to use
+
+ SYNOPSIS
+ write_log_completed()
+ lpt Struct containing parameters
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt,
+ bool dont_crash)
+{
+ partition_info *part_info= lpt->part_info;
+ uint count_loop= 0;
+ bool not_success;
+ DDL_LOG_MEMORY_ENTRY *log_entry= part_info->exec_log_entry;
+ DBUG_ENTER("write_log_completed");
+
+ DBUG_ASSERT(log_entry);
+ pthread_mutex_lock(&LOCK_gdl);
+ if (write_execute_ddl_log_entry(0UL, TRUE, &log_entry))
+ {
+ /*
+ Failed to write, Bad...
+ We have completed the operation but have log records to REMOVE
+ stuff that shouldn't be removed. What clever things could one do
+ here? An error output was written to the error output by the
+ above method so we don't do anything here.
+ */
+ ;
+ }
+ release_part_info_log_entries(part_info->first_log_entry);
+ release_part_info_log_entries(part_info->exec_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->exec_log_entry= NULL;
+ part_info->first_log_entry= NULL;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Release all log entries
+ SYNOPSIS
+ release_log_entries()
+ part_info Partition info struct
+ RETURN VALUES
+ NONE
+*/
+
+static void release_log_entries(partition_info *part_info)
+{
+ pthread_mutex_lock(&LOCK_gdl);
+ release_part_info_log_entries(part_info->first_log_entry);
+ release_part_info_log_entries(part_info->exec_log_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ part_info->first_log_entry= NULL;
+ part_info->exec_log_entry= NULL;
+}
+
+
+/*
+ Handle errors for ALTER TABLE for partitioning
+ SYNOPSIS
+ handle_alter_part_error()
+ lpt Struct carrying parameters
+ not_completed Was request in complete phase when error occurred
+ RETURN VALUES
+ NONE
+*/
+
+void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt,
+ bool not_completed,
+ bool drop_partition,
+ bool frm_install)
+{
+ partition_info *part_info= lpt->part_info;
+ DBUG_ENTER("handle_alter_part_error");
+
+ if (!part_info->first_log_entry &&
+ execute_ddl_log_entry(current_thd,
+ part_info->first_log_entry->entry_pos))
+ {
+ /*
+ We couldn't recover from error, most likely manual interaction
+ is required.
+ */
+ write_log_completed(lpt, FALSE);
+ release_log_entries(part_info);
+ if (not_completed)
+ {
+ if (drop_partition)
+ {
+ /* Table is still ok, but we left a shadow frm file behind. */
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,
+ "%s %s",
+ "Operation was unsuccessful, table is still intact,",
+ "but it is possible that a shadow frm file was left behind");
+ }
+ else
+ {
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,
+ "%s %s %s %s",
+ "Operation was unsuccessful, table is still intact,",
+ "but it is possible that a shadow frm file was left behind.",
+ "It is also possible that temporary partitions are left behind,",
+ "these could be empty or more or less filled with records");
+ }
+ }
+ else
+ {
+ if (frm_install)
+ {
+ /*
+ Failed during install of shadow frm file, table isn't intact
+ and dropped partitions are still there
+ */
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,
+ "%s %s %s",
+ "Failed during alter of partitions, table is no longer intact.",
+ "The frm file is in an unknown state, and a backup",
+ "is required.");
+ }
+ else if (drop_partition)
+ {
+ /*
+ Table is ok, we have switched to new table but left dropped
+ partitions still in their places. We remove the log records and
+ ask the user to perform the action manually. We remove the log
+ records and ask the user to perform the action manually.
+ */
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,
+ "%s %s",
+ "Failed during drop of partitions, table is intact.",
+ "Manual drop of remaining partitions is required");
+ }
+ else
+ {
+ /*
+ We failed during renaming of partitions. The table is most
+ certainly in a very bad state so we give user warning and disable
+ the table by writing an ancient frm version into it.
+ */
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,
+ "%s %s %s",
+ "Failed during renaming of partitions. We are now in a position",
+ "where table is not reusable",
+ "Table is disabled by writing ancient frm file version into it");
+ }
+ }
+ }
+ else
+ {
+ release_log_entries(part_info);
+ if (not_completed)
+ {
+ /*
+ We hit an error before things were completed but managed
+ to recover from the error. An error occurred and we have
+ restored things to original so no need for further action.
+ */
+ ;
+ }
+ else
+ {
+ /*
+ We hit an error after we had completed most of the operation
+ and were successful in a second attempt so the operation
+ actually is successful now. We need to issue a warning that
+ even though we reported an error the operation was successfully
+ completed.
+ */
+ push_warning_printf(lpt->thd, MYSQL_ERROR::WARN_LEVEL_WARN, 1,"%s %s",
+ "Operation was successfully completed by failure handling,",
+ "after failure of normal operation");
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Actually perform the change requested by ALTER TABLE of partitions
previously prepared.
@@ -4792,9 +5533,12 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ALTER_PARTITION_PARAM_TYPE lpt_obj;
ALTER_PARTITION_PARAM_TYPE *lpt= &lpt_obj;
bool written_bin_log= TRUE;
+ bool not_completed= TRUE;
+ bool frm_install= FALSE;
DBUG_ENTER("fast_alter_partition_table");
lpt->thd= thd;
+ lpt->part_info= part_info;
lpt->create_info= create_info;
lpt->create_list= create_list;
lpt->key_list= key_list;
@@ -4826,17 +5570,18 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
In this case it is enough to call optimise_partitions, there is no
need to change frm files or anything else.
*/
+ int error;
written_bin_log= FALSE;
if (((alter_info->flags & ALTER_OPTIMIZE_PARTITION) &&
- (table->file->optimize_partitions(thd))) ||
+ (error= table->file->optimize_partitions(thd))) ||
((alter_info->flags & ALTER_ANALYZE_PARTITION) &&
- (table->file->analyze_partitions(thd))) ||
+ (error= table->file->analyze_partitions(thd))) ||
((alter_info->flags & ALTER_CHECK_PARTITION) &&
- (table->file->check_partitions(thd))) ||
+ (error= table->file->check_partitions(thd))) ||
((alter_info->flags & ALTER_REPAIR_PARTITION) &&
- (table->file->repair_partitions(thd))))
+ (error= table->file->repair_partitions(thd))))
{
- fast_alter_partition_error_handler(lpt);
+ table->file->print_error(error, MYF(0));
DBUG_RETURN(TRUE);
}
}
@@ -4881,10 +5626,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
1) Write the new frm, pack it and then delete it
2) Perform the change within the handler
*/
- if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE | WFRM_PACK_FRM)) ||
- (mysql_change_partitions(lpt)))
+ if (mysql_write_frm(lpt, WFRM_WRITE_SHADOW | WFRM_PACK_FRM) ||
+ mysql_change_partitions(lpt))
{
- fast_alter_partition_error_handler(lpt);
DBUG_RETURN(TRUE);
}
}
@@ -4912,32 +5656,62 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
after a DROP PARTITION) if one ensured that failed accesses to the
dropped partitions was aborted for sure (thus only possible for
transactional engines).
-
- 1) Lock the table in TL_WRITE_ONLY to ensure all other accesses to
+
+ 0) Write an entry that removes the shadow frm file if crash occurs
+ 1) Write the new frm file as a shadow frm
+ 2) Write the ddl log to ensure that the operation is completed
+ even in the presence of a MySQL Server crash
+ 3) Lock the table in TL_WRITE_ONLY to ensure all other accesses to
the table have completed
- 2) Write the new frm file where the partitions have changed but are
- still remaining with the state PART_TO_BE_DROPPED
- 3) Write the bin log
- 4) Prepare MyISAM handlers for drop of partitions
- 5) Ensure that any users that has opened the table but not yet
+ 4) Write the bin log
+ Unfortunately the writing of the binlog is not synchronised with
+ other logging activities. So no matter in which order the binlog
+ is written compared to other activities there will always be cases
+ where crashes make strange things occur. In this placement it can
+ happen that the ALTER TABLE DROP PARTITION gets performed in the
+ master but not in the slaves if we have a crash, after writing the
+ ddl log but before writing the binlog. A solution to this would
+ require writing the statement first in the ddl log and then
+ when recovering from the crash read the binlog and insert it into
+ the binlog if not written already.
+ 5) Install the previously written shadow frm file
+ 6) Ensure that any users that has opened the table but not yet
reached the abort lock do that before downgrading the lock.
- 6) Drop the partitions
- 7) Write the frm file that the partition has been dropped
- 8) Wait until all accesses using the old frm file has completed
- 9) Complete query
+ 7) Prepare MyISAM handlers for drop of partitions
+ 8) Drop the partitions
+ 9) Remove entries from ddl log
+ 10) Wait until all accesses using the old frm file has completed
+ 11) Complete query
+
+ We insert Error injections at all places where it could be interesting
+ to test if recovery is properly done.
*/
- if ((abort_and_upgrade_lock(lpt)) ||
- (mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
+ if (write_log_drop_shadow_frm(lpt) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_1") ||
+ mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_2") ||
+ write_log_drop_partition(lpt) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_3") ||
+ (not_completed= FALSE) ||
+ abort_and_upgrade_lock(lpt) || /* Always returns 0 */
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
- thd->query, thd->query_length), FALSE)) ||
- (table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE)) ||
+ thd->query, thd->query_length), FALSE)) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_4") ||
+ (table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_5") ||
+ ((frm_install= TRUE), FALSE) ||
+ mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ ((frm_install= FALSE), FALSE) ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
- (mysql_drop_partitions(lpt)) ||
- (mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_6") ||
+ mysql_drop_partitions(lpt) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_7") ||
+ (write_log_completed(lpt, FALSE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_drop_partition_8") ||
(mysql_wait_completed_table(lpt, table), FALSE))
{
- fast_alter_partition_error_handler(lpt);
+ handle_alter_part_error(lpt, not_completed, TRUE, frm_install);
DBUG_RETURN(TRUE);
}
}
@@ -4954,28 +5728,45 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
miss updates made by a transaction serialised before it that are
inserted into the new partition.
- 1) Write the new frm file where state of added partitions is
- changed to PART_TO_BE_ADDED
+ 0) Write an entry that removes the shadow frm file if crash occurs
+ 1) Write the new frm file as a shadow frm file
+ 2) Log the changes to happen in ddl log
2) Add the new partitions
3) Lock all partitions in TL_WRITE_ONLY to ensure that no users
are still using the old partitioning scheme. Wait until all
ongoing users have completed before progressing.
- 4) Write a new frm file of the table where the partitions are added
- to the table.
- 5) Write binlog
- 6) Wait until all accesses using the old frm file has completed
- 7) Complete query
+ 4) Write binlog
+ 5) Now the change is completed except for the installation of the
+ new frm file. We thus write an action in the log to change to
+ the shadow frm file
+ 6) Install the new frm file of the table where the partitions are
+ added to the table.
+ 7) Wait until all accesses using the old frm file has completed
+ 8) Remove entries from ddl log
+ 9) Complete query
*/
- if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
- (mysql_change_partitions(lpt)) ||
- (abort_and_upgrade_lock(lpt)) ||
- (mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
+ if (write_log_add_change_partition(lpt) ||
+ ERROR_INJECT_CRASH("crash_add_partition_1") ||
+ mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
+ ERROR_INJECT_CRASH("crash_add_partition_2") ||
+ mysql_change_partitions(lpt) ||
+ ERROR_INJECT_CRASH("crash_add_partition_3") ||
+ abort_and_upgrade_lock(lpt) || /* Always returns 0 */
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE)) ||
- (close_open_tables_and_downgrade(lpt), FALSE))
+ ERROR_INJECT_CRASH("crash_add_partition_4") ||
+ write_log_rename_frm(lpt) ||
+ (not_completed= FALSE) ||
+ ERROR_INJECT_CRASH("crash_add_partition_5") ||
+ ((frm_install= TRUE), FALSE) ||
+ mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ ERROR_INJECT_CRASH("crash_add_partition_6") ||
+ (close_open_tables_and_downgrade(lpt), FALSE) ||
+ (write_log_completed(lpt, FALSE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_add_partition_7"))
{
- fast_alter_partition_error_handler(lpt);
+ handle_alter_part_error(lpt, not_completed, FALSE, frm_install);
DBUG_RETURN(TRUE);
}
}
@@ -5012,44 +5803,57 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
use a lower lock level. This can be handled inside store_lock in the
respective handler.
- 1) Write the new frm file where state of added partitions is
- changed to PART_TO_BE_ADDED and the reorganised partitions
- are set in state PART_TO_BE_REORGED.
- 2) Add the new partitions
+ 0) Write an entry that removes the shadow frm file if crash occurs
+ 1) Write the shadow frm file of new partitioning
+ 2) Log such that temporary partitions added in change phase are
+ removed in a crash situation
+ 3) Add the new partitions
Copy from the reorganised partitions to the new partitions
- 3) Lock all partitions in TL_WRITE_ONLY to ensure that no users
+ 4) Log that operation is completed and log all complete actions
+ needed to complete operation from here
+ 5) Lock all partitions in TL_WRITE_ONLY to ensure that no users
are still using the old partitioning scheme. Wait until all
ongoing users have completed before progressing.
- 4) Prepare MyISAM handlers for rename and delete of partitions
- 5) Write a new frm file of the table where the partitions are
- reorganised.
- 6) Rename the reorged partitions such that they are no longer
+ 6) Prepare MyISAM handlers for rename and delete of partitions
+ 7) Rename the reorged partitions such that they are no longer
used and rename those added to their real new names.
- 7) Write bin log
- 8) Wait until all accesses using the old frm file has completed
- 9) Drop the reorganised partitions
- 10)Write a new frm file of the table where the partitions are
- reorganised.
- 11)Wait until all accesses using the old frm file has completed
- 12)Complete query
+ 8) Write bin log
+ 9) Install the shadow frm file
+ 10) Wait until all accesses using the old frm file has completed
+ 11) Drop the reorganised partitions
+ 12) Remove log entry
+ 13)Wait until all accesses using the old frm file has completed
+ 14)Complete query
*/
-
- if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
- (mysql_change_partitions(lpt)) ||
- (abort_and_upgrade_lock(lpt)) ||
- (mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
- (table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE)) ||
- (mysql_rename_partitions(lpt)) ||
+ if (write_log_add_change_partition(lpt) ||
+ ERROR_INJECT_CRASH("crash_change_partition_1") ||
+ mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
+ ERROR_INJECT_CRASH("crash_change_partition_2") ||
+ mysql_change_partitions(lpt) ||
+ ERROR_INJECT_CRASH("crash_change_partition_3") ||
+ write_log_final_change_partition(lpt) ||
+ ERROR_INJECT_CRASH("crash_change_partition_4") ||
+ (not_completed= FALSE) ||
+ abort_and_upgrade_lock(lpt) || /* Always returns 0 */
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE)) ||
+ ERROR_INJECT_CRASH("crash_change_partition_5") ||
+ (table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_change_partition_6") ||
+ mysql_rename_partitions(lpt) ||
+ ((frm_install= TRUE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_change_partition_7") ||
+ mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ ERROR_INJECT_CRASH("crash_change_partition_8") ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
- (mysql_drop_partitions(lpt)) ||
- (mysql_write_frm(lpt, 0UL)) ||
+ ERROR_INJECT_CRASH("crash_change_partition_9") ||
+ (write_log_completed(lpt, FALSE), FALSE) ||
+ ERROR_INJECT_CRASH("crash_change_partition_10") ||
(mysql_wait_completed_table(lpt, table), FALSE))
{
- fast_alter_partition_error_handler(lpt);
- DBUG_RETURN(TRUE);
+ handle_alter_part_error(lpt, not_completed, FALSE, frm_install);
+ DBUG_RETURN(TRUE);
}
}
/*
@@ -5057,7 +5861,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
user
*/
DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted,
- table_list, FALSE, lpt,
+ table, table_list, FALSE, lpt,
written_bin_log));
}
#endif
@@ -5709,5 +6513,85 @@ static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter)
field->store(part_iter->field_vals.cur++, FALSE);
return part_iter->part_info->get_subpartition_id(part_iter->part_info);
}
+
+
+/*
+ Create partition names
+
+ SYNOPSIS
+ create_partition_name()
+ out:out Created partition name string
+ in1 First part
+ in2 Second part
+ name_variant Normal, temporary or renamed partition name
+
+ RETURN VALUE
+ NONE
+
+ DESCRIPTION
+ This method is used to calculate the partition name, service routine to
+ the del_ren_cre_table method.
+*/
+
+void create_partition_name(char *out, const char *in1,
+ const char *in2, uint name_variant,
+ bool translate)
+{
+ char transl_part_name[FN_REFLEN];
+ const char *transl_part;
+
+ if (translate)
+ {
+ tablename_to_filename(in2, transl_part_name, FN_REFLEN);
+ transl_part= transl_part_name;
+ }
+ else
+ transl_part= in2;
+ if (name_variant == NORMAL_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part, NullS);
+ else if (name_variant == TEMP_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS);
+ else if (name_variant == RENAMED_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part, "#REN#", NullS);
+}
+
+
+/*
+ Create subpartition name
+
+ SYNOPSIS
+ create_subpartition_name()
+ out:out Created partition name string
+ in1 First part
+ in2 Second part
+ in3 Third part
+ name_variant Normal, temporary or renamed partition name
+
+ RETURN VALUE
+ NONE
+
+ DESCRIPTION
+ This method is used to calculate the subpartition name, service routine to
+ the del_ren_cre_table method.
+*/
+
+void create_subpartition_name(char *out, const char *in1,
+ const char *in2, const char *in3,
+ uint name_variant)
+{
+ char transl_part_name[FN_REFLEN], transl_subpart_name[FN_REFLEN];
+
+ tablename_to_filename(in2, transl_part_name, FN_REFLEN);
+ tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
+ if (name_variant == NORMAL_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part_name,
+ "#SP#", transl_subpart_name, NullS);
+ else if (name_variant == TEMP_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part_name,
+ "#SP#", transl_subpart_name, "#TMP#", NullS);
+ else if (name_variant == RENAMED_PART_NAME)
+ strxmov(out, in1, "#P#", transl_part_name,
+ "#SP#", transl_subpart_name, "#REN#", NullS);
+}
#endif
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index b4e42dc4700..01faae22c57 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -19,6 +19,8 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
+extern struct st_mysql_plugin *mysqld_builtins[];
+
char *opt_plugin_dir_ptr;
char opt_plugin_dir[FN_REFLEN];
LEX_STRING plugin_type_names[]=
@@ -529,7 +531,7 @@ static int plugin_initialize(struct st_plugin_int *plugin)
switch (plugin->plugin->type)
{
case MYSQL_STORAGE_ENGINE_PLUGIN:
- if (ha_initialize_handlerton((handlerton*) plugin->plugin->info))
+ if (ha_initialize_handlerton(plugin))
{
sql_print_error("Plugin '%s' handlerton init returned error.",
plugin->name.str);
@@ -548,6 +550,53 @@ err:
DBUG_RETURN(1);
}
+static int plugin_finalize(THD *thd, struct st_plugin_int *plugin)
+{
+ int rc;
+ DBUG_ENTER("plugin_finalize");
+
+ if (plugin->ref_count)
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Plugin is busy and will be uninstalled on shutdown");
+ goto err;
+ }
+
+ switch (plugin->plugin->type)
+ {
+ case MYSQL_STORAGE_ENGINE_PLUGIN:
+ if (ha_finalize_handlerton(plugin))
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Storage engine shutdown failed. "
+ "It will be uninstalled on shutdown");
+ sql_print_warning("Storage engine '%s' shutdown failed. "
+ "It will be uninstalled on shutdown", plugin->name.str);
+ goto err;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (plugin->plugin->deinit)
+ {
+ if ((rc= plugin->plugin->deinit()))
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Plugin deinit failed. "
+ "It will be uninstalled on shutdown");
+ sql_print_warning("Plugin '%s' deinit failed. "
+ "It will be uninstalled on shutdown", plugin->name.str);
+ goto err;
+ }
+ }
+
+ DBUG_RETURN(0);
+err:
+ DBUG_RETURN(1);
+}
+
static void plugin_call_initializer(void)
{
uint i;
@@ -606,6 +655,8 @@ static byte *get_hash_key(const byte *buff, uint *length,
int plugin_init(void)
{
int i;
+ struct st_mysql_plugin **builtins;
+ struct st_mysql_plugin *plugin;
DBUG_ENTER("plugin_init");
if (initialized)
@@ -625,6 +676,16 @@ int plugin_init(void)
get_hash_key, NULL, 0))
goto err;
}
+
+ /* Register all the built-in plugins */
+ for (builtins= mysqld_builtins; *builtins; builtins++)
+ {
+ for (plugin= *builtins; plugin->info; plugin++)
+ {
+ if (plugin_register_builtin(plugin))
+ goto err;
+ }
+ }
initialized= 1;
@@ -831,18 +892,10 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
goto err;
}
- if (plugin->ref_count)
- {
- plugin->state= PLUGIN_IS_DELETED;
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
- "Plugin is not deleted, waiting on tables.");
- }
- else
- {
- if (plugin->plugin->deinit)
- plugin->plugin->deinit();
+ if (!plugin_finalize(thd, plugin))
plugin_del(name);
- }
+ else
+ plugin->state= PLUGIN_IS_DELETED;
table->field[0]->store(name->str, name->length, system_charset_info);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index e0cf9095a22..14bcb437337 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1755,6 +1755,9 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_CALL:
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
+ case SQLCOM_REPAIR:
+ case SQLCOM_ANALYZE:
+ case SQLCOM_OPTIMIZE:
break;
default:
@@ -2084,19 +2087,20 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
sl->exclude_from_table_unique_test= FALSE;
/*
- Copy WHERE, HAVING clause pointers to avoid damaging them by optimisation
+ Copy WHERE, HAVING clause pointers to avoid damaging them
+ by optimisation
*/
- if (sl->prep_where)
- {
- sl->where= sl->prep_where->copy_andor_structure(thd);
- sl->where->cleanup();
- }
- if (sl->prep_having)
- {
- sl->having= sl->prep_having->copy_andor_structure(thd);
- sl->having->cleanup();
- }
- DBUG_ASSERT(sl->join == 0);
+ if (sl->prep_where)
+ {
+ sl->where= sl->prep_where->copy_andor_structure(thd);
+ sl->where->cleanup();
+ }
+ if (sl->prep_having)
+ {
+ sl->having= sl->prep_having->copy_andor_structure(thd);
+ sl->having->cleanup();
+ }
+ DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
for (order= (ORDER *)sl->group_list.first; order; order= order->next)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 6ec010b8a44..918c9f507e2 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -694,7 +694,7 @@ impossible position";
if (loop_breaker)
break;
-
+
end_io_cache(&log);
(void) my_close(file, MYF(MY_WME));
@@ -834,7 +834,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
/* 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,
+ ER_MISSING_SKIP_SLAVE,
ER(ER_MISSING_SKIP_SLAVE));
}
@@ -860,7 +860,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SLAVE_WAS_RUNNING,
ER(ER_SLAVE_WAS_RUNNING));
}
-
+
unlock_slave_threads(mi);
if (slave_errno)
@@ -1023,7 +1023,7 @@ err:
slave_server_id the slave's server id
*/
-
+
void kill_zombie_dump_threads(uint32 slave_server_id)
{
@@ -1088,9 +1088,9 @@ bool change_master(THD* thd, MASTER_INFO* mi)
*/
/*
- If the user specified host or port without binlog or position,
+ If the user specified host or port without binlog or position,
reset binlog's name to FIRST and position to 4.
- */
+ */
if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
{
@@ -1117,7 +1117,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
mi->port = lex_mi->port;
if (lex_mi->connect_retry)
mi->connect_retry = lex_mi->connect_retry;
-
+
if (lex_mi->ssl != LEX_MASTER_INFO::SSL_UNCHANGED)
mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::SSL_ENABLE);
if (lex_mi->ssl_ca)
@@ -1133,7 +1133,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
#ifndef HAVE_OPENSSL
if (lex_mi->ssl || lex_mi->ssl_ca || lex_mi->ssl_capath ||
lex_mi->ssl_cert || lex_mi->ssl_cipher || lex_mi->ssl_key )
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SLAVE_IGNORED_SSL_PARAMS, ER(ER_SLAVE_IGNORED_SSL_PARAMS));
#endif
@@ -1500,7 +1500,7 @@ bool show_binlogs(THD* thd)
}
field_list.push_back(new Item_empty_string("Log_name", 255));
- field_list.push_back(new Item_return_int("File_size", 20,
+ field_list.push_back(new Item_return_int("File_size", 20,
MYSQL_TYPE_LONGLONG));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4e67ce0d67f..2212371db92 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -224,7 +224,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
- if (select_lex->next_select())
+ if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex)
res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
else
{
@@ -2419,7 +2419,19 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
{
if (old->field == new_fields->field)
{
- if (new_fields->val->used_tables())
+ /*
+ NOTE: below const_item() call really works as "!used_tables()", i.e.
+ it can return FALSE where it is feasible to make it return TRUE.
+
+ The cause is as follows: Some of the tables are already known to be
+ const tables (the detection code is in make_join_statistics(),
+ above the update_ref_and_keys() call), but we didn't propagate
+ information about this: TABLE::const_table is not set to TRUE, and
+ Item::update_used_tables() hasn't been called for each item.
+ The result of this is that we're missing some 'ref' accesses.
+ TODO: OptimizerTeam: Fix this
+ */
+ if (!new_fields->val->const_item())
{
/*
If the value matches, we can use the key reference.
@@ -2449,7 +2461,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
new_fields->null_rejecting);
}
else if (old->eq_func && new_fields->eq_func &&
- (old->val->is_null() || new_fields->val->is_null()))
+ ((old->val->const_item() && old->val->is_null()) ||
+ new_fields->val->is_null()))
{
/* field = expression OR field IS NULL */
old->level= and_level;
@@ -3360,33 +3373,51 @@ best_access_path(JOIN *join,
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;
+ table_map found_ref= 0;
+ uint key= keyuse->key;
KEY *keyinfo= table->key_info+key;
bool ft_key= (keyuse->keypart == FT_KEYPART);
+ /* Bitmap of keyparts where the ref access is over 'keypart=const': */
+ key_part_map const_part= 0;
+ /* The or-null keypart in ref-or-null access: */
+ key_part_map ref_or_null_part= 0;
/* 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;
+ table_map best_part_found_ref= 0;
+ double best_prev_record_reads= DBL_MAX;
do
{
if (!(remaining_tables & keyuse->used_tables) &&
- !(found_ref_or_null & keyuse->optimize))
+ !(ref_or_null_part && (keyuse->optimize &
+ KEY_OPTIMIZE_REF_OR_NULL)))
{
found_part|= keyuse->keypart_map;
- found_ref|= keyuse->used_tables;
+ if (!(keyuse->used_tables & ~join->const_table_map))
+ const_part|= keyuse->keypart_map;
+ double tmp= prev_record_reads(join, (found_ref |
+ keyuse->used_tables));
+ if (tmp < best_prev_record_reads)
+ {
+ best_part_found_ref= keyuse->used_tables;
+ best_prev_record_reads= tmp;
+ }
if (rec > keyuse->ref_table_rows)
rec= keyuse->ref_table_rows;
- found_part_ref_or_null&= keyuse->optimize;
+ /*
+ If there is one 'key_column IS NULL' expression, we can
+ use this ref_or_null optimisation of this field
+ */
+ if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
+ ref_or_null_part |= keyuse->keypart_map;
}
keyuse++;
- found_ref_or_null|= found_part_ref_or_null;
} while (keyuse->table == table && keyuse->key == key &&
keyuse->keypart == keypart);
+ found_ref|= best_part_found_ref;
} while (keyuse->table == table && keyuse->key == key);
/*
@@ -3417,7 +3448,7 @@ best_access_path(JOIN *join,
Check if we found full key
*/
if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
- !found_ref_or_null)
+ !ref_or_null_part)
{ /* use eq key */
max_key_part= (uint) ~0;
if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
@@ -3429,6 +3460,23 @@ best_access_path(JOIN *join,
{
if (!found_ref)
{ /* We found a const key */
+ /*
+ ReuseRangeEstimateForRef-1:
+ We get here if we've found a ref(const) (c_i are constants):
+ "(keypart1=c1) AND ... AND (keypartN=cN)" [ref_const_cond]
+
+ If range optimizer was able to construct a "range"
+ access on this index, then its condition "quick_cond" was
+ eqivalent to ref_const_cond (*), and we can re-use E(#rows)
+ from the range optimizer.
+
+ Proof of (*): By properties of range and ref optimizers
+ quick_cond will be equal or tighther than ref_const_cond.
+ ref_const_cond already covers "smallest" possible interval -
+ a singlepoint interval over all keyparts. Therefore,
+ quick_cond is equivalent to ref_const_cond (if it was an
+ empty interval we wouldn't have got here).
+ */
if (table->quick_keys.is_set(key))
records= (double) table->quick_rows[key];
else
@@ -3449,19 +3497,36 @@ best_access_path(JOIN *join,
if (records < 2.0)
records=2.0; /* Can't be as good as a unique */
}
+ /*
+ ReuseRangeEstimateForRef-2: We get here if we could not reuse
+ E(#rows) from range optimizer. Make another try:
+
+ If range optimizer produced E(#rows) for a prefix of the ref
+ access we're considering, and that E(#rows) is lower then our
+ current estimate, make an adjustment. The criteria of when we
+ can make an adjustment is a special case of the criteria used
+ in ReuseRangeEstimateForRef-3.
+ */
+ if (table->quick_keys.is_set(key) &&
+ const_part & (1 << table->quick_key_parts[key]) &&
+ table->quick_n_ranges[key] == 1 &&
+ records > (double) table->quick_rows[key])
+ {
+ records= (double) table->quick_rows[key];
+ }
}
/* Limit the number of matched rows */
- tmp = records;
+ 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;
+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
}
else
- tmp = record_count*min(tmp,s->worst_seeks);
+ tmp= record_count*min(tmp,s->worst_seeks);
}
}
else
@@ -3475,19 +3540,57 @@ best_access_path(JOIN *join,
(!(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);
+ max_key_part= max_part_bit(found_part);
/*
- Check if quick_range could determinate how many rows we
- will match
+ ReuseRangeEstimateForRef-3:
+ We're now considering a ref[or_null] access via
+ (t.keypart1=e1 AND ... AND t.keypartK=eK) [ OR
+ (same-as-above but with one cond replaced
+ with "t.keypart_i IS NULL")] (**)
+
+ Try re-using E(#rows) from "range" optimizer:
+ We can do so if "range" optimizer used the same intervals as
+ in (**). The intervals used by range optimizer may be not
+ available at this point (as "range" access might have choosen to
+ create quick select over another index), so we can't compare
+ them to (**). We'll make indirect judgements instead.
+ The sufficient conditions for re-use are:
+ (C1) All e_i in (**) are constants, i.e. found_ref==FALSE. (if
+ this is not satisfied we have no way to know which ranges
+ will be actually scanned by 'ref' until we execute the
+ join)
+ (C2) max #key parts in 'range' access == K == max_key_part (this
+ is apparently a necessary requirement)
+
+ We also have a property that "range optimizer produces equal or
+ tighter set of scan intervals than ref(const) optimizer". Each
+ of the intervals in (**) are "tightest possible" intervals when
+ one limits itself to using keyparts 1..K (which we do in #2).
+ From here it follows that range access used either one, or
+ both of the (I1) and (I2) intervals:
+
+ (t.keypart1=c1 AND ... AND t.keypartK=eK) (I1)
+ (same-as-above but with one cond replaced
+ with "t.keypart_i IS NULL") (I2)
+
+ The remaining part is to exclude the situation where range
+ optimizer used one interval while we're considering
+ ref-or-null and looking for estimate for two intervals. This
+ is done by last limitation:
+
+ (C3) "range optimizer used (have ref_or_null?2:1) intervals"
*/
- if (table->quick_keys.is_set(key) &&
- table->quick_key_parts[key] == max_key_part)
+ if (table->quick_keys.is_set(key) && !found_ref && //(C1)
+ table->quick_key_parts[key] == max_key_part && //(C2)
+ table->quick_n_ranges[key] == 1+test(ref_or_null_part)) //(C3)
+ {
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;
+ if ((records= keyinfo->rec_per_key[max_key_part-1]))
+ tmp= records;
else
{
/*
@@ -3526,21 +3629,37 @@ best_access_path(JOIN *join,
}
records = (ulong) tmp;
}
+
+ if (ref_or_null_part)
+ {
+ /* We need to do two key searches to find key */
+ tmp *= 2.0;
+ records *= 2.0;
+ }
+
/*
- If quick_select was used on a part of this key, we know
- the maximum number of rows that the key can match.
+ ReuseRangeEstimateForRef-4: We get here if we could not reuse
+ E(#rows) from range optimizer. Make another try:
+
+ If range optimizer produced E(#rows) for a prefix of the ref
+ access we're considering, and that E(#rows) is lower then our
+ current estimate, make the adjustment.
+
+ The decision whether we can re-use the estimate from the range
+ optimizer is the same as in ReuseRangeEstimateForRef-3,
+ applied to first table->quick_key_parts[key] key parts.
*/
if (table->quick_keys.is_set(key) &&
table->quick_key_parts[key] <= max_key_part &&
+ const_part & (1 << table->quick_key_parts[key]) &&
+ table->quick_n_ranges[key] == 1 + test(ref_or_null_part &
+ const_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;
+ tmp= records= (double) table->quick_rows[key];
}
}
+
/* Limit the number of matched rows */
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
if (table->used_keys.is_set(key))
@@ -3548,13 +3667,13 @@ best_access_path(JOIN *join,
/* 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;
+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
}
else
- tmp = record_count*min(tmp,s->worst_seeks);
+ tmp= record_count*min(tmp,s->worst_seeks);
}
else
- tmp = best_time; // Do nothing
+ tmp= best_time; // Do nothing
}
} /* not ft_key */
if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
@@ -3906,7 +4025,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
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);
+ 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;
@@ -4029,8 +4149,9 @@ greedy_search(JOIN *join,
'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_EXECUTE("opt", print_plan(join, join->tables,
+ record_count, read_time, read_time,
+ "optimal"););
DBUG_VOID_RETURN;
}
@@ -4061,8 +4182,9 @@ greedy_search(JOIN *join,
--rem_size;
++idx;
- DBUG_EXECUTE("opt",
- print_plan(join, read_time, record_count, idx, "extended"););
+ DBUG_EXECUTE("opt", print_plan(join, join->tables,
+ record_count, read_time, read_time,
+ "extended"););
} while (TRUE);
}
@@ -4085,13 +4207,14 @@ greedy_search(JOIN *join,
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
+ 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
+ '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.
@@ -4201,8 +4324,8 @@ best_extension_by_limited_search(JOIN *join,
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"););
+ DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time,
+ "part_plan"););
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
@@ -4214,7 +4337,8 @@ best_extension_by_limited_search(JOIN *join,
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);
+ 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;
@@ -4223,7 +4347,12 @@ best_extension_by_limited_search(JOIN *join,
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,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ (current_read_time +
+ current_record_count /
+ (double) TIME_FOR_COMPARE),
"prune_by_cost"););
restore_prev_nj_state(s);
continue;
@@ -4252,7 +4381,10 @@ best_extension_by_limited_search(JOIN *join,
}
else
{
- DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ current_read_time,
"pruned_by_heuristic"););
restore_prev_nj_state(s);
continue;
@@ -4280,7 +4412,8 @@ best_extension_by_limited_search(JOIN *join,
*/
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)
+ 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))
@@ -4289,8 +4422,10 @@ best_extension_by_limited_search(JOIN *join,
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,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ current_read_time,
"full_plan"););
}
restore_prev_nj_state(s);
@@ -4311,7 +4446,6 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
ha_rows rec;
double tmp;
THD *thd= join->thd;
-
if (!rest_tables)
{
DBUG_PRINT("best",("read_time: %g record_count: %g",read_time,
@@ -4341,344 +4475,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
(!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s)))
{
- double best,best_time,records;
- best=best_time=records=DBL_MAX;
- KEYUSE *best_key=0;
- uint best_max_key_part=0;
- my_bool found_constraint= 0;
-
- 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 key=keyuse->key;
- KEY *keyinfo=table->key_info+key;
- bool ft_key=(keyuse->keypart == FT_KEYPART);
- uint found_ref_or_null= 0;
-
- /* Calculate how many key segments of the current key we can use */
- start_key=keyuse;
- do
- {
- uint keypart=keyuse->keypart;
- table_map best_part_found_ref= 0;
- double best_prev_record_reads= DBL_MAX;
- do
- {
- if (!(rest_tables & keyuse->used_tables) &&
- !(found_ref_or_null & keyuse->optimize))
- {
- found_part|=keyuse->keypart_map;
- double tmp= prev_record_reads(join,
- (found_ref |
- keyuse->used_tables));
- if (tmp < best_prev_record_reads)
- {
- best_part_found_ref= keyuse->used_tables;
- best_prev_record_reads= tmp;
- }
- if (rec > keyuse->ref_table_rows)
- rec= keyuse->ref_table_rows;
- /*
- If there is one 'key_column IS NULL' expression, we can
- use this ref_or_null optimisation of this field
- */
- found_ref_or_null|= (keyuse->optimize &
- KEY_OPTIMIZE_REF_OR_NULL);
- }
- keyuse++;
- } while (keyuse->table == table && keyuse->key == key &&
- keyuse->keypart == keypart);
- found_ref|= best_part_found_ref;
- } 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_END_SPACE_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]))
- { // Prefere 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 (10% of all records?)
- c = number of key parts in key
- x = used key parts (1 <= x <= c)
- */
- double rec_per_key;
- rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ?
- (double) keyinfo->rec_per_key[keyinfo->key_parts-1] :
- (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;
- tmp=(max_key_part * (rec_per_key - a) +
- a*keyinfo->key_parts - rec_per_key)/
- (keyinfo->key_parts-1);
- 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.
- (see comment in best_access_path() for more details on the below
- condition)
- */
- 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 && !s->quick))
- { // 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;
- }
- }
- join->positions[idx].records_read= records;
- 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
-
+ double records, best;
+ best_access_path(join, s, thd, rest_tables, idx, record_count,
+ read_time);
+ records= join->positions[idx].records_read;
+ best= join->positions[idx].read_time;
/*
Go to the next level only if there hasn't been a better key on
this level! This will cut down the search for a lot simple cases!
@@ -8233,6 +8034,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
item->result_field= new_field;
else
new_field->field_name= name;
+ new_field->flags|= (org_field->flags & NO_DEFAULT_VALUE_FLAG);
if (org_field->maybe_null() || (item && item->maybe_null))
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
@@ -8396,6 +8198,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
bool make_copy_field,
uint convert_blob_length)
{
+ Field *result;
Item::Type orig_type= type;
Item *orig_item= 0;
@@ -8413,8 +8216,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::SUM_FUNC_ITEM:
{
Item_sum *item_sum=(Item_sum*) item;
- Field *result= item_sum->create_tmp_field(group, table,
- convert_blob_length);
+ result= item_sum->create_tmp_field(group, table, convert_blob_length);
if (!result)
thd->fatal_error();
return result;
@@ -8424,7 +8226,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
{
Item_field *field= (Item_field*) item;
bool orig_modify= modify_item;
- Field *result;
if (orig_type == Item::REF_ITEM)
modify_item= 0;
/*
@@ -8458,6 +8259,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
convert_blob_length);
if (orig_type == Item::REF_ITEM && orig_modify)
((Item_ref*)orig_item)->set_result_field(result);
+ if (field->field->eq_def(result))
+ result->dflt_field= field->field;
return result;
}
/* Fall through */
@@ -8480,10 +8283,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
DBUG_ASSERT(((Item_result_field*)item)->result_field);
*from_field= ((Item_result_field*)item)->result_field;
}
- return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 :
- copy_func), modify_item,
- convert_blob_length);
- case Item::TYPE_HOLDER:
+ return create_tmp_field_from_item(thd, item, table,
+ (make_copy_field ? 0 : copy_func),
+ modify_item, convert_blob_length);
+ case Item::TYPE_HOLDER:
return ((Item_type_holder *)item)->make_field_by_type(table);
default: // Dosen't have to be stored
return 0;
@@ -8938,6 +8741,33 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count+= (field->field_length & 7);
}
field->reset();
+
+ if (field->dflt_field && field->dflt_field->ptr)
+ {
+ /*
+ field->dflt_field is set only in the cases when 'field' can
+ inherit the default value that is defined for the field referred
+ by the Item_field object from which 'field' has been created.
+ For a field created not from a Item_field item dflt_field == 0.
+ */
+ my_ptrdiff_t diff;
+ Field *orig_field= field->dflt_field;
+ /* Get the value from default_values */
+ diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
+ orig_field->table->record[0]);
+ orig_field->move_field_offset(diff); // Points now at default_values
+ bool is_null= orig_field->is_real_null();
+ char *from= orig_field->ptr;
+ orig_field->move_field_offset(-diff); // Back to record[0]
+ if (is_null)
+ field->set_null();
+ else
+ {
+ field->set_notnull();
+ memcpy(field->ptr, from, field->pack_length());
+ }
+ }
+
if (from_field[i])
{ /* Not a table Item */
copy->set(field,from_field[i],save_sum_fields);
@@ -12690,6 +12520,10 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
!item->const_item())
{
+ /*
+ TODO: change ER_WRONG_FIELD_WITH_GROUP to more detailed
+ ER_NON_GROUPING_FIELD_USED
+ */
my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), item->full_name());
return 1;
}
@@ -12771,6 +12605,17 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
{
if (!item->const_item() && !item->with_sum_func && !item->marker)
{
+ /*
+ Don't put duplicate columns from the SELECT list into the
+ GROUP BY list.
+ */
+ ORDER *ord_iter;
+ for (ord_iter= group; ord_iter; ord_iter= ord_iter->next)
+ if ((*ord_iter->item)->eq(item, 1))
+ break;
+ if (ord_iter)
+ continue;
+
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
if (!ord)
return 0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 95433828a1e..bdf0724ee96 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -25,6 +25,7 @@
#include "sp_head.h"
#include "sql_trigger.h"
#include "authors.h"
+#include "contributors.h"
#include "event.h"
#include <my_dir.h>
@@ -42,6 +43,9 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
grant_names, NULL};
#endif
+static void store_key_options(THD *thd, String *packet, TABLE *table,
+ KEY *key_info);
+
/***************************************************************************
** List all table types supported
***************************************************************************/
@@ -119,7 +123,7 @@ static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
make_version_string(version_buf, sizeof(version_buf), plug->version),
cs);
-
+
switch (plugin->state)
{
/* case PLUGIN_IS_FREED: does not happen */
@@ -226,6 +230,41 @@ bool mysqld_show_authors(THD *thd)
DBUG_RETURN(FALSE);
}
+
+/***************************************************************************
+** List all Contributors.
+** Please get permission before updating
+***************************************************************************/
+
+bool mysqld_show_contributors(THD *thd)
+{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysqld_show_contributors");
+
+ field_list.push_back(new Item_empty_string("Name",40));
+ field_list.push_back(new Item_empty_string("Location",40));
+ field_list.push_back(new Item_empty_string("Comment",80));
+
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
+
+ show_table_contributors_st *contributors;
+ for (contributors= show_table_contributors; contributors->name; contributors++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(contributors->name, system_charset_info);
+ protocol->store(contributors->location, system_charset_info);
+ protocol->store(contributors->comment, system_charset_info);
+ if (protocol->write())
+ DBUG_RETURN(TRUE);
+ }
+ send_eof(thd);
+ DBUG_RETURN(FALSE);
+}
+
+
/***************************************************************************
List all privileges supported
***************************************************************************/
@@ -929,15 +968,15 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
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 |
- MODE_MSSQL |
- MODE_DB2 |
- MODE_MAXDB |
- MODE_ANSI)) != 0;
- my_bool limited_mysql_mode= (thd->variables.sql_mode &
- (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
- MODE_MYSQL40)) != 0;
+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_MAXDB |
+ MODE_ANSI)) != 0;
+ 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->s->table_name.str));
@@ -1022,8 +1061,8 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
has_default= (field->type() != FIELD_TYPE_BLOB &&
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
field->unireg_check != Field::NEXT_NUMBER &&
- !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
- has_now_default));
+ !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
+ && has_now_default));
if (has_default)
{
@@ -1052,8 +1091,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(tmp);
}
- if (!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) &&
- table->timestamp_field == field &&
+ if (!limited_mysql_mode && table->timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
@@ -1100,22 +1138,6 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
if (!found_primary)
append_identifier(thd, packet, key_info->name, strlen(key_info->name));
- if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
- !limited_mysql_mode && !foreign_db_mode)
- {
- if (key_info->algorithm == HA_KEY_ALG_BTREE)
- packet->append(STRING_WITH_LEN(" USING BTREE"));
-
- if (key_info->algorithm == HA_KEY_ALG_HASH)
- packet->append(STRING_WITH_LEN(" USING HASH"));
-
- // +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(STRING_WITH_LEN(" USING RTREE"));
-
- // No need to send USING FULLTEXT, it is sent as FULLTEXT KEY
- }
packet->append(STRING_WITH_LEN(" ("));
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
@@ -1140,6 +1162,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
}
packet->append(')');
+ store_key_options(thd, packet, table, key_info);
if (key_info->parser)
{
packet->append(" WITH PARSER ", 13);
@@ -1196,6 +1219,25 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(file->table_type());
#endif
}
+
+ /*
+ Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
+ and NEXT_ID > 1 (the default). We must not print the clause
+ for engines that do not support this as it would break the
+ import of dumps, but as of this writing, the test for whether
+ AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
+ is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
+ Because of that, we do not explicitly test for the feature,
+ but may extrapolate its existence from that of an AUTO_INCREMENT column.
+ */
+
+ if(create_info.auto_increment_value > 1)
+ {
+ packet->append(" AUTO_INCREMENT=", 16);
+ end= longlong10_to_str(create_info.auto_increment_value, buff,10);
+ packet->append(buff, (uint) (end - buff));
+ }
+
if (share->table_charset &&
!(thd->variables.sql_mode & MODE_MYSQL323) &&
@@ -1252,6 +1294,12 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
packet->append(ha_row_type[(uint) share->row_type]);
}
+ if (table->s->key_block_size)
+ {
+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
+ end= longlong10_to_str(table->s->key_block_size, buff, 10);
+ packet->append(buff, (uint) (end - buff));
+ }
table->file->append_create_info(packet);
if (share->comment && share->comment[0])
{
@@ -1274,6 +1322,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
uint part_syntax_len;
char *part_syntax;
if (table->part_info &&
+ (!table->part_info->is_auto_partitioned) &&
((part_syntax= generate_partition_syntax(table->part_info,
&part_syntax_len,
FALSE,FALSE))))
@@ -1286,6 +1335,47 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
DBUG_RETURN(0);
}
+
+static void store_key_options(THD *thd, String *packet, TABLE *table,
+ KEY *key_info)
+{
+ bool limited_mysql_mode= (thd->variables.sql_mode &
+ (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
+ MODE_MYSQL40)) != 0;
+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_MAXDB |
+ MODE_ANSI)) != 0;
+ char *end, buff[32];
+
+ if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
+ !limited_mysql_mode && !foreign_db_mode)
+ {
+
+ if (key_info->algorithm == HA_KEY_ALG_BTREE)
+ packet->append(STRING_WITH_LEN(" USING BTREE"));
+
+ if (key_info->algorithm == HA_KEY_ALG_HASH)
+ packet->append(STRING_WITH_LEN(" USING HASH"));
+
+ /* 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(STRING_WITH_LEN(" USING RTREE"));
+
+ if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
+ table->s->key_block_size != key_info->block_size)
+ {
+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
+ end= longlong10_to_str(key_info->block_size, buff, 10);
+ packet->append(buff, (uint) (end - buff));
+ }
+ }
+}
+
+
void
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
{
@@ -1553,15 +1643,11 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;
char *user;
- bool verbose;
- ulong max_query_length;
time_t now= time(0);
DBUG_ENTER("fill_process_list");
user= thd->security_ctx->master_access & PROCESS_ACL ?
NullS : thd->security_ctx->priv_user;
- verbose= thd->lex->verbose;
- max_query_length= PROCESS_LIST_WIDTH;
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -1645,7 +1731,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
if (tmp->query)
{
table->field[7]->store(tmp->query,
- min(max_query_length, tmp->query_length), cs);
+ min(PROCESS_LIST_INFO_WIDTH,
+ tmp->query_length), cs);
table->field[7]->set_notnull();
}
@@ -2881,7 +2968,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
field->real_type() == MYSQL_TYPE_STRING) // For binary type
{
uint32 octet_max_length= field->max_length();
- if (octet_max_length != (uint32) 4294967295U)
+ if (is_blob && octet_max_length != (uint32) 4294967295U)
octet_max_length /= field->charset()->mbmaxlen;
longlong char_max_len= is_blob ?
(longlong) octet_max_length / field->charset()->mbminlen :
@@ -3000,46 +3087,49 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
}
-int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
+static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin,
+ void *ptable)
{
+ TABLE *table= (TABLE *) ptable;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
- TABLE *table= tables->table;
CHARSET_INFO *scs= system_charset_info;
- handlerton **types;
+ DBUG_ENTER("iter_schema_engines");
- DBUG_ENTER("fill_schema_engines");
-
- for (types= sys_table_types; *types; types++)
+ if (!(hton->flags & HTON_HIDDEN))
{
- if ((*types)->flags & HTON_HIDDEN)
- continue;
-
if (!(wild && wild[0] &&
- wild_case_compare(scs, (*types)->name,wild)))
+ wild_case_compare(scs, hton->name,wild)))
{
const char *tmp;
restore_record(table, s->default_values);
- table->field[0]->store((*types)->name, strlen((*types)->name), scs);
- tmp= (*types)->state ? "DISABLED" : "ENABLED";
+ table->field[0]->store(hton->name, strlen(hton->name), scs);
+ tmp= hton->state ? "DISABLED" : "ENABLED";
table->field[1]->store( tmp, strlen(tmp), scs);
- table->field[2]->store((*types)->comment, strlen((*types)->comment), scs);
- tmp= (*types)->commit ? "YES" : "NO";
+ table->field[2]->store(hton->comment, strlen(hton->comment), scs);
+ tmp= hton->commit ? "YES" : "NO";
table->field[3]->store( tmp, strlen(tmp), scs);
- tmp= (*types)->prepare ? "YES" : "NO";
+ tmp= hton->prepare ? "YES" : "NO";
table->field[4]->store( tmp, strlen(tmp), scs);
- tmp= (*types)->savepoint_set ? "YES" : "NO";
+ tmp= hton->savepoint_set ? "YES" : "NO";
table->field[5]->store( tmp, strlen(tmp), scs);
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
}
}
-
DBUG_RETURN(0);
}
+int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ return plugin_foreach(thd, iter_schema_engines,
+ MYSQL_STORAGE_ENGINE_PLUGIN, tables->table);
+}
+
+
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
{
CHARSET_INFO **cs;
@@ -3115,17 +3205,18 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
const char *wild, bool full_access, const char *sp_user)
{
String tmp_string;
+ String sp_db, sp_name, definer;
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]);
+ get_field(thd->mem_root, proc_table->field[0], &sp_db);
+ get_field(thd->mem_root, proc_table->field[1], &sp_name);
+ get_field(thd->mem_root, proc_table->field[11], &definer);
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))
+ full_access= !strcmp(sp_user, definer.ptr());
+ if (!full_access && check_some_routine_access(thd, sp_db.ptr(), sp_name.ptr(),
+ proc_table->field[2]->val_int() ==
+ TYPE_ENUM_PROCEDURE))
return 0;
if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
@@ -3135,13 +3226,13 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
lex->orig_sql_command == SQLCOM_END)
{
restore_record(table, s->default_values);
- if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0))
+ if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0))
{
int enum_idx= proc_table->field[5]->val_int();
- table->field[3]->store(sp_name, strlen(sp_name), cs);
+ table->field[3]->store(sp_name.ptr(), sp_name.length(), 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);
+ table->field[2]->store(sp_db.ptr(), sp_db.length(), 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)
@@ -3173,7 +3264,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
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);
+ table->field[19]->store(definer.ptr(), definer.length(), cs);
return schema_table_store_record(thd, table);
}
}
@@ -3336,11 +3427,33 @@ static int get_schema_views_record(THD *thd, struct st_table_list *tables,
if (tables->view)
{
+ Security_context *sctx= thd->security_ctx;
+ ulong grant= SHOW_VIEW_ACL;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ char *save_table_name= tables->table_name;
+ if (!my_strcasecmp(system_charset_info, tables->definer.user.str,
+ sctx->priv_user) &&
+ !my_strcasecmp(system_charset_info, tables->definer.host.str,
+ sctx->priv_host))
+ grant= SHOW_VIEW_ACL;
+ else
+ {
+ tables->table_name= tables->view_name.str;
+ if (check_access(thd, SHOW_VIEW_ACL , base_name,
+ &tables->grant.privilege, 0, 1,
+ test(tables->schema_table)))
+ grant= get_table_grant(thd, tables);
+ else
+ grant= tables->grant.privilege;
+ }
+ tables->table_name= save_table_name;
+#endif
+
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);
+ table->field[2]->store(tables->view_name.str, tables->view_name.length, cs);
+ if (grant & SHOW_VIEW_ACL)
+ table->field[3]->store(tables->query.str, tables->query.length, cs);
if (tables->with_check != VIEW_CHECK_NONE)
{
@@ -3965,8 +4078,24 @@ static interval_type get_real_interval_type(interval_type i_type)
extern LEX_STRING interval_type_to_name[];
+
+/*
+ Loads an event from mysql.event and copies it's data to a row of
+ I_S.EVENTS
+
+ Synopsis
+ copy_event_to_schema_table()
+ thd Thread
+ sch_table The schema table (information_schema.event)
+ event_table The event table to use for loading (mysql.event).
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
static int
-fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
+copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
CHARSET_INFO *scs= system_charset_info;
@@ -3984,9 +4113,19 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
DBUG_RETURN(0);
-
+
+ /*
+ Skip events in schemas one does not have access to. The check is
+ optimized. It's guaranteed in case of SHOW EVENTS that the user
+ has access.
+ */
+ if (thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS &&
+ check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
+ is_schema_db(et.dbname.str)))
+ DBUG_RETURN(0);
+
/* ->field[0] is EVENT_CATALOG and is by default NULL */
-
+
sch_table->field[1]->store(et.dbname.str, et.dbname.length, scs);
sch_table->field[2]->store(et.name.str, et.name.length, scs);
sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
@@ -3998,18 +4137,18 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
ulong sql_mode_len=0;
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
- &sql_mode_len);
+ &sql_mode_len);
sch_table->field[9]->store((const char*)sql_mode_str, sql_mode_len, scs);
}
-
+
if (et.expression)
{
String show_str;
/* type */
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
- if (event_reconstruct_interval_expression(&show_str, et.interval,
- et.expression))
+ if (Events::reconstruct_interval_expression(&show_str, et.interval,
+ et.expression))
DBUG_RETURN(1);
sch_table->field[7]->set_notnull();
@@ -4019,7 +4158,7 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[8]->set_notnull();
sch_table->field[8]->store(ival->str, ival->length, scs);
- //starts & ends
+ /* starts & ends */
sch_table->field[10]->set_notnull();
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
@@ -4038,14 +4177,14 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
}
- //status
- if (et.status == MYSQL_EVENT_ENABLED)
+ /* status */
+ if (et.status == Event_timed::ENABLED)
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
else
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
- //on_completion
- if (et.on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
+ /* on_completion */
+ if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
else
sch_table->field[13]->store(STRING_WITH_LEN("PRESERVE"), scs);
@@ -4074,100 +4213,179 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
-int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
+/*
+ Performs an index scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ events_table_index_read_for_db()
+ thd Thread
+ schema_table The I_S.EVENTS table
+ event_table The event table to use for loading (mysql.event)
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+static
+int events_table_index_read_for_db(THD *thd, TABLE *schema_table,
+ TABLE *event_table)
{
- TABLE *table= tables->table;
- CHARSET_INFO *scs= system_charset_info;
- TABLE *event_table= NULL;
- Open_tables_state backup;
int ret=0;
- bool verbose= false;
- char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
- bool use_prefix_scanning= true;
- uint key_len= 0;
+ CHARSET_INFO *scs= system_charset_info;
+ KEY *key_info;
+ uint key_len;
byte *key_buf= NULL;
LINT_INIT(key_buf);
- DBUG_ENTER("fill_schema_events");
-
- strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host,
- NullS);
-
- DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer));
+ DBUG_ENTER("schema_events_do_index_scan");
- thd->reset_n_backup_open_tables_state(&backup);
+ DBUG_PRINT("info", ("Using prefix scanning on PK"));
+ event_table->file->ha_index_init(0, 1);
+ event_table->field[Events::FIELD_DB]->
+ store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
+ key_info= event_table->key_info;
+ key_len= key_info->key_part[0].store_length;
- if ((ret= evex_open_event_table(thd, TL_READ, &event_table)))
+ if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
{
- sql_print_error("Table mysql.event is damaged.");
ret= 1;
- goto err;
- }
-
- event_table->file->ha_index_init(0, 1);
-
- /*
- see others' events only if you have PROCESS_ACL !!
- thd->lex->verbose is set either if SHOW FULL EVENTS or
- in case of SELECT FROM I_S.EVENTS
- */
- verbose= (thd->lex->verbose
- && (thd->security_ctx->master_access & PROCESS_ACL));
-
- if (verbose && thd->security_ctx->user)
- {
- ret= event_table->file->index_first(event_table->record[0]);
- use_prefix_scanning= false;
+ /* don't send error, it would be done by sql_alloc_error_handler() */
}
else
{
- event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs);
- key_len= event_table->key_info->key_part[0].store_length;
-
- if (thd->lex->select_lex.db)
+ key_copy(key_buf, event_table->record[0], key_info, key_len);
+ if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
+ key_len, HA_READ_PREFIX)))
{
- event_table->field[EVEX_FIELD_DB]->
- store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
- key_len+= event_table->key_info->key_part[1].store_length;
- }
- if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
- {
- ret= 1;
- goto err;
+ DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
+ do
+ {
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
+ if (ret == 0)
+ ret= event_table->file->index_next_same(event_table->record[0],
+ key_buf, key_len);
+ } while (ret == 0);
}
-
- key_copy(key_buf, event_table->record[0], event_table->key_info, key_len);
- ret= event_table->file->index_read(event_table->record[0], key_buf, key_len,
- HA_READ_PREFIX);
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
}
+ event_table->file->ha_index_end();
+ /* ret is guaranteed to be != 0 */
+ if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(0);
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Performs a table scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ events_table_scan_all()
+ thd Thread
+ schema_table The I_S.EVENTS in memory table
+ event_table The event table to use for loading.
- if (ret)
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+static
+int events_table_scan_all(THD *thd, TABLE *schema_table,
+ TABLE *event_table)
+{
+ int ret;
+ READ_RECORD read_record_info;
+
+ DBUG_ENTER("schema_events_do_table_scan");
+ init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
+
+ /*
+ rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
+ but rr_handle_error returns -1 for that reason. Thus, read_record()
+ returns -1 eventually.
+ */
+ do
{
- ret= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1;
- goto err;
+ ret= read_record_info.read_record(&read_record_info);
+ if (ret == 0)
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
}
+ while (ret == 0);
- while (!ret)
- {
- if ((ret= fill_events_copy_to_schema_table(thd, table, event_table)))
- goto err;
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
+ end_read_record(&read_record_info);
- if (use_prefix_scanning)
- ret= event_table->file->
- index_next_same(event_table->record[0], key_buf, key_len);
- else
- ret= event_table->file->index_next(event_table->record[0]);
+ /* ret is guaranteed to be != 0 */
+ DBUG_RETURN(ret == -1? 0:1);
+}
+
+
+/*
+ Fills I_S.EVENTS with data loaded from mysql.event. Also used by
+ SHOW EVENTS
+
+ Synopsis
+ fill_schema_events()
+ thd Thread
+ tables The schema table
+ cond Unused
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
+{
+ TABLE *schema_table= tables->table;
+ TABLE *event_table= NULL;
+ Open_tables_state backup;
+ int ret= 0;
+
+ DBUG_ENTER("fill_schema_events");
+ /*
+ If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
+ be NULL. Let's do an assert anyway.
+ */
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+ {
+ DBUG_ASSERT(thd->lex->select_lex.db);
+ if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
+ is_schema_db(thd->lex->select_lex.db)))
+ DBUG_RETURN(1);
}
- // ret is guaranteed to be != 0
- ret= (ret != HA_ERR_END_OF_FILE);
-err:
- if (event_table)
+
+ DBUG_PRINT("info",("db=%s", thd->lex->select_lex.db?
+ thd->lex->select_lex.db:"(null)"));
+
+ thd->reset_n_backup_open_tables_state(&backup);
+ if (Events::open_event_table(thd, TL_READ, &event_table))
{
- event_table->file->ha_index_end();
- close_thread_tables(thd);
+ sql_print_error("Table mysql.event is damaged.");
+ thd->restore_backup_open_tables_state(&backup);
+ DBUG_RETURN(1);
}
+ /*
+ 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
+ thus we won't order it. OTOH, SHOW EVENTS will be
+ ordered.
+ 2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
+ Reasoning: Events are per schema, therefore a scan over an index
+ will save use from doing a table scan and comparing
+ every single row's `db` with the schema which we show.
+ */
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+ ret= events_table_index_read_for_db(thd, schema_table, event_table);
+ else
+ ret= events_table_scan_all(thd, schema_table, event_table);
+
+ close_thread_tables(thd);
thd->restore_backup_open_tables_state(&backup);
+
+ DBUG_PRINT("info", ("Return code=%d", ret));
DBUG_RETURN(ret);
}
@@ -4232,6 +4450,75 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
/*
+ Fill and store records into I_S.referential_constraints table
+
+ SYNOPSIS
+ get_referential_constraints_record()
+ thd thread handle
+ tables table list struct(processed table)
+ table I_S table
+ res 1 means the error during opening of the processed table
+ 0 means processed table is opened without error
+ base_name db name
+ file_name table name
+
+ RETURN
+ 0 ok
+ # error
+*/
+
+static int
+get_referential_constraints_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_referential_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);
+ }
+ if (!tables->view)
+ {
+ List<FOREIGN_KEY_INFO> f_key_list;
+ TABLE *show_table= tables->table;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+
+ 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++))
+ {
+ restore_record(table, s->default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[9]->store(file_name, strlen(file_name), cs);
+ table->field[2]->store(f_key_info->forein_id->str,
+ f_key_info->forein_id->length, cs);
+ table->field[4]->store(f_key_info->referenced_db->str,
+ f_key_info->referenced_db->length, cs);
+ table->field[5]->store(f_key_info->referenced_table->str,
+ f_key_info->referenced_table->length, cs);
+ table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
+ table->field[7]->store(f_key_info->update_method->str,
+ f_key_info->update_method->length, cs);
+ table->field[8]->store(f_key_info->delete_method->str,
+ f_key_info->delete_method->length, cs);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
Find schema_tables elment by name
SYNOPSIS
@@ -5096,9 +5383,9 @@ ST_FIELD_INFO processlist_fields_info[]=
{"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host"},
{"DB", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Db"},
{"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command"},
- {"TIME", 4, MYSQL_TYPE_LONG, 0, 0, "Time"},
+ {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time"},
{"STATE", 30, MYSQL_TYPE_STRING, 0, 1, "State"},
- {"INFO", PROCESS_LIST_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"},
+ {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
@@ -5160,6 +5447,22 @@ ST_FIELD_INFO files_fields_info[]=
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
+ST_FIELD_INFO referential_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},
+ {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"UNIQUE_CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"UNIQUE_CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"MATCH_OPTION", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"UPDATE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"DELETE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
/*
Description of ST_FIELD_INFO in table.h
@@ -5195,6 +5498,9 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_plugins, make_old_format, 0, -1, -1, 0},
{"PROCESSLIST", processlist_fields_info, create_schema_table,
fill_schema_processlist, make_old_format, 0, -1, -1, 0},
+ {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
+ create_schema_table, get_all_tables, 0, get_referential_constraints_record,
+ 1, 9, 0},
{"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,
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 79228be8a76..19ee9f259dc 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -331,7 +331,7 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
return copy_aligned(str, arg_length, offset, cs);
}
- /* Copy with charset convertion */
+ /* Copy with charset conversion */
bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 0659f684afe..ddae6368228 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -24,8 +24,6 @@
#define NOT_FIXED_DEC 31
#endif
-#define STRING_WITH_LEN(X) ((const char*) X), ((uint) (sizeof(X) - 1))
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 6cc2ad266e5..289051c2dd1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -231,10 +231,9 @@ static int mysql_copy_key_list(List<Key> *orig_key,
}
}
if (!(temp_key= new Key(prep_key->type, prep_key->name,
- prep_key->algorithm,
+ &prep_key->key_create_info,
prep_key->generated,
- prep_columns,
- prep_key->parser_name)))
+ prep_columns)))
{
mem_alloc_error(sizeof(Key));
DBUG_RETURN(TRUE);
@@ -248,6 +247,918 @@ static int mysql_copy_key_list(List<Key> *orig_key,
DBUG_RETURN(FALSE);
}
+/*
+--------------------------------------------------------------------------
+
+ MODULE: DDL log
+ -----------------
+
+ This module is used to ensure that we can recover from crashes that occur
+ in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
+ We need to ensure that both t1 and t2 are dropped and not only t1 and
+ also that each table drop is entirely done and not "half-baked".
+
+ To support this we create log entries for each meta-data statement in the
+ ddl log while we are executing. These entries are dropped when the
+ operation is completed.
+
+ At recovery those entries that were not completed will be executed.
+
+ There is only one ddl log in the system and it is protected by a mutex
+ and there is a global struct that contains information about its current
+ state.
+
+ History:
+ First version written in 2006 by Mikael Ronstrom
+--------------------------------------------------------------------------
+*/
+
+
+typedef struct st_global_ddl_log
+{
+ /*
+ We need to adjust buffer size to be able to handle downgrades/upgrades
+ where IO_SIZE has changed. We'll set the buffer size such that we can
+ handle that the buffer size was upto 4 times bigger in the version
+ that wrote the DDL log.
+ */
+ char file_entry_buf[4*IO_SIZE];
+ char file_name_str[FN_REFLEN];
+ char *file_name;
+ DDL_LOG_MEMORY_ENTRY *first_free;
+ DDL_LOG_MEMORY_ENTRY *first_used;
+ uint num_entries;
+ File file_id;
+ uint name_len;
+ uint io_size;
+ bool inited;
+ bool recovery_phase;
+} GLOBAL_DDL_LOG;
+
+GLOBAL_DDL_LOG global_ddl_log;
+
+pthread_mutex_t LOCK_gdl;
+
+#define DDL_LOG_ENTRY_TYPE_POS 0
+#define DDL_LOG_ACTION_TYPE_POS 1
+#define DDL_LOG_PHASE_POS 2
+#define DDL_LOG_NEXT_ENTRY_POS 4
+#define DDL_LOG_NAME_POS 8
+
+#define DDL_LOG_NUM_ENTRY_POS 0
+#define DDL_LOG_NAME_LEN_POS 4
+#define DDL_LOG_IO_SIZE_POS 8
+
+/*
+ Read one entry from ddl log file
+ SYNOPSIS
+ read_ddl_log_file_entry()
+ entry_no Entry number to read
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool read_ddl_log_file_entry(uint entry_no)
+{
+ bool error= FALSE;
+ File file_id= global_ddl_log.file_id;
+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ uint io_size= global_ddl_log.io_size;
+ DBUG_ENTER("read_ddl_log_file_entry");
+
+ if (my_pread(file_id, (byte*)file_entry_buf, io_size, io_size * entry_no,
+ MYF(MY_WME)) != io_size)
+ error= TRUE;
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Write one entry from ddl log file
+ SYNOPSIS
+ write_ddl_log_file_entry()
+ entry_no Entry number to read
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool write_ddl_log_file_entry(uint entry_no)
+{
+ bool error= FALSE;
+ File file_id= global_ddl_log.file_id;
+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ DBUG_ENTER("write_ddl_log_file_entry");
+
+ if (my_pwrite(file_id, (byte*)file_entry_buf,
+ IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE)
+ error= TRUE;
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Write ddl log header
+ SYNOPSIS
+ write_ddl_log_header()
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool write_ddl_log_header()
+{
+ uint16 const_var;
+ bool error= FALSE;
+ DBUG_ENTER("write_ddl_log_header");
+
+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
+ global_ddl_log.num_entries);
+ const_var= FN_LEN;
+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
+ const_var);
+ const_var= IO_SIZE;
+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
+ const_var);
+ if (write_ddl_log_file_entry(0UL))
+ {
+ sql_print_error("Error writing ddl log header");
+ DBUG_RETURN(TRUE);
+ }
+ VOID(sync_ddl_log());
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Create ddl log file name
+ SYNOPSIS
+ create_ddl_log_file_name()
+ file_name Filename setup
+ RETURN VALUES
+ NONE
+*/
+
+static inline void create_ddl_log_file_name(char *file_name)
+{
+ strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
+}
+
+
+/*
+ Read header of ddl log file
+ SYNOPSIS
+ read_ddl_log_header()
+ RETURN VALUES
+ > 0 Last entry in ddl log
+ 0 No entries in ddl log
+ DESCRIPTION
+ When we read the ddl log header we get information about maximum sizes
+ of names in the ddl log and we also get information about the number
+ of entries in the ddl log.
+*/
+
+static uint read_ddl_log_header()
+{
+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ char file_name[FN_REFLEN];
+ uint entry_no;
+ bool successful_open= FALSE;
+ DBUG_ENTER("read_ddl_log_header");
+
+ create_ddl_log_file_name(file_name);
+ if ((global_ddl_log.file_id= my_open(file_name,
+ O_RDWR | O_BINARY, MYF(MY_WME))) >= 0)
+ {
+ if (read_ddl_log_file_entry(0UL))
+ {
+ /* Write message into error log */
+ sql_print_error("Failed to read ddl log file in recovery");
+ }
+ else
+ successful_open= TRUE;
+ }
+ entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
+ global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
+ if (successful_open)
+ {
+ global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
+ DBUG_ASSERT(global_ddl_log.io_size <=
+ sizeof(global_ddl_log.file_entry_buf));
+ }
+ else
+ {
+ entry_no= 0;
+ }
+ global_ddl_log.first_free= NULL;
+ global_ddl_log.first_used= NULL;
+ global_ddl_log.num_entries= 0;
+ VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
+ DBUG_RETURN(entry_no);
+}
+
+
+/*
+ Read a ddl log entry
+ SYNOPSIS
+ read_ddl_log_entry()
+ read_entry Number of entry to read
+ out:entry_info Information from entry
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Read a specified entry in the ddl log
+*/
+
+bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
+{
+ char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
+ uint inx;
+ uchar single_char;
+ DBUG_ENTER("read_ddl_log_entry");
+
+ if (read_ddl_log_file_entry(read_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ ddl_log_entry->entry_pos= read_entry;
+ single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
+ ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
+ single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
+ ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
+ ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
+ ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
+ ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
+ inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
+ ddl_log_entry->from_name= &file_entry_buf[inx];
+ inx+= global_ddl_log.name_len;
+ ddl_log_entry->handler_name= &file_entry_buf[inx];
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Initialise ddl log
+ SYNOPSIS
+ init_ddl_log()
+
+ DESCRIPTION
+ Write the header of the ddl log file and length of names. Also set
+ number of entries to zero.
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool init_ddl_log()
+{
+ bool error= FALSE;
+ char file_name[FN_REFLEN];
+ DBUG_ENTER("init_ddl_log");
+
+ if (global_ddl_log.inited)
+ goto end;
+
+ global_ddl_log.io_size= IO_SIZE;
+ create_ddl_log_file_name(file_name);
+ if ((global_ddl_log.file_id= my_create(file_name,
+ CREATE_MODE,
+ O_RDWR | O_TRUNC | O_BINARY,
+ MYF(MY_WME))) < 0)
+ {
+ /* Couldn't create ddl log file, this is serious error */
+ sql_print_error("Failed to open ddl log file");
+ DBUG_RETURN(TRUE);
+ }
+ global_ddl_log.inited= TRUE;
+ if (write_ddl_log_header())
+ {
+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
+ global_ddl_log.inited= FALSE;
+ DBUG_RETURN(TRUE);
+ }
+
+end:
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Execute one action in a ddl log entry
+ SYNOPSIS
+ execute_ddl_log_action()
+ ddl_log_entry Information in action entry to execute
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
+{
+ bool frm_action= FALSE;
+ LEX_STRING handler_name;
+ handler *file= NULL;
+ MEM_ROOT mem_root;
+ int error= TRUE;
+ char to_path[FN_REFLEN];
+ char from_path[FN_REFLEN];
+ char *par_ext= (char*)".par";
+ handlerton *hton;
+ DBUG_ENTER("execute_ddl_log_action");
+
+ if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
+ {
+ DBUG_RETURN(FALSE);
+ }
+ handler_name.str= (char*)ddl_log_entry->handler_name;
+ handler_name.length= strlen(ddl_log_entry->handler_name);
+ init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
+ if (!strcmp(ddl_log_entry->handler_name, reg_ext))
+ frm_action= TRUE;
+ else
+ {
+ TABLE_SHARE dummy;
+
+ hton= ha_resolve_by_name(thd, &handler_name);
+ if (!hton)
+ {
+ my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
+ goto error;
+ }
+ bzero(&dummy, sizeof(TABLE_SHARE));
+ file= get_new_handler(&dummy, &mem_root, hton);
+ if (!file)
+ {
+ mem_alloc_error(sizeof(handler));
+ goto error;
+ }
+ }
+ switch (ddl_log_entry->action_type)
+ {
+ case DDL_LOG_REPLACE_ACTION:
+ case DDL_LOG_DELETE_ACTION:
+ {
+ if (ddl_log_entry->phase == 0)
+ {
+ if (frm_action)
+ {
+ strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
+ if ((error= my_delete(to_path, MYF(MY_WME))))
+ {
+ if (my_errno != ENOENT)
+ break;
+ }
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
+ VOID(my_delete(to_path, MYF(MY_WME)));
+#endif
+ }
+ else
+ {
+ if ((error= file->delete_table(ddl_log_entry->name)))
+ {
+ if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
+ break;
+ }
+ }
+ if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
+ break;
+ VOID(sync_ddl_log());
+ error= FALSE;
+ if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
+ break;
+ }
+ DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
+ /*
+ Fall through and perform the rename action of the replace
+ action. We have already indicated the success of the delete
+ action in the log entry by stepping up the phase.
+ */
+ }
+ case DDL_LOG_RENAME_ACTION:
+ {
+ error= TRUE;
+ if (frm_action)
+ {
+ strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
+ strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
+ if (my_rename(from_path, to_path, MYF(MY_WME)))
+ break;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
+ strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS);
+ VOID(my_rename(from_path, to_path, MYF(MY_WME)));
+#endif
+ }
+ else
+ {
+ if (file->rename_table(ddl_log_entry->from_name,
+ ddl_log_entry->name))
+ break;
+ }
+ if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
+ break;
+ VOID(sync_ddl_log());
+ error= FALSE;
+ break;
+ }
+ default:
+ DBUG_ASSERT(0);
+ break;
+ }
+ delete file;
+error:
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Get a free entry in the ddl log
+ SYNOPSIS
+ get_free_ddl_log_entry()
+ out:active_entry A ddl log memory entry returned
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
+ bool *write_header)
+{
+ DDL_LOG_MEMORY_ENTRY *used_entry;
+ DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
+ DBUG_ENTER("get_free_ddl_log_entry");
+
+ if (global_ddl_log.first_free == NULL)
+ {
+ if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
+ sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
+ {
+ sql_print_error("Failed to allocate memory for ddl log free list");
+ DBUG_RETURN(TRUE);
+ }
+ global_ddl_log.num_entries++;
+ used_entry->entry_pos= global_ddl_log.num_entries;
+ *write_header= TRUE;
+ }
+ else
+ {
+ used_entry= global_ddl_log.first_free;
+ global_ddl_log.first_free= used_entry->next_log_entry;
+ *write_header= FALSE;
+ }
+ /*
+ Move from free list to used list
+ */
+ used_entry->next_log_entry= first_used;
+ used_entry->prev_log_entry= NULL;
+ global_ddl_log.first_used= used_entry;
+ if (first_used)
+ first_used->prev_log_entry= used_entry;
+
+ *active_entry= used_entry;
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ External interface methods for the DDL log Module
+ ---------------------------------------------------
+*/
+
+/*
+ SYNOPSIS
+ write_ddl_log_entry()
+ ddl_log_entry Information about log entry
+ out:entry_written Entry information written into
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+
+ DESCRIPTION
+ A careful write of the ddl log is performed to ensure that we can
+ handle crashes occurring during CREATE and ALTER TABLE processing.
+*/
+
+bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
+ DDL_LOG_MEMORY_ENTRY **active_entry)
+{
+ bool error, write_header;
+ DBUG_ENTER("write_ddl_log_entry");
+
+ if (init_ddl_log())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
+ (char)DDL_LOG_ENTRY_CODE;
+ global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
+ (char)ddl_log_entry->action_type;
+ global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
+ ddl_log_entry->next_entry);
+ DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_LEN);
+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
+ ddl_log_entry->name, FN_LEN - 1);
+ if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
+ ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
+ {
+ DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_LEN);
+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
+ ddl_log_entry->from_name, FN_LEN - 1);
+ }
+ else
+ global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
+ DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_LEN);
+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
+ ddl_log_entry->handler_name, FN_LEN - 1);
+ if (get_free_ddl_log_entry(active_entry, &write_header))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ error= FALSE;
+ if (write_ddl_log_file_entry((*active_entry)->entry_pos))
+ {
+ error= TRUE;
+ sql_print_error("Failed to write entry_no = %u",
+ (*active_entry)->entry_pos);
+ }
+ if (write_header && !error)
+ {
+ VOID(sync_ddl_log());
+ if (write_ddl_log_header())
+ error= TRUE;
+ }
+ if (error)
+ release_ddl_log_memory_entry(*active_entry);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Write final entry in the ddl log
+ SYNOPSIS
+ write_execute_ddl_log_entry()
+ first_entry First entry in linked list of entries
+ to execute, if 0 = NULL it means that
+ the entry is removed and the entries
+ are put into the free list.
+ complete Flag indicating we are simply writing
+ info about that entry has been completed
+ in:out:active_entry Entry to execute, 0 = NULL if the entry
+ is written first time and needs to be
+ returned. In this case the entry written
+ is returned in this parameter
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+
+ DESCRIPTION
+ This is the last write in the ddl log. The previous log entries have
+ already been written but not yet synched to disk.
+ We write a couple of log entries that describes action to perform.
+ This entries are set-up in a linked list, however only when a first
+ execute entry is put as the first entry these will be executed.
+ This routine writes this first
+*/
+
+bool write_execute_ddl_log_entry(uint first_entry,
+ bool complete,
+ DDL_LOG_MEMORY_ENTRY **active_entry)
+{
+ bool write_header= FALSE;
+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ DBUG_ENTER("write_execute_ddl_log_entry");
+
+ if (init_ddl_log())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (!complete)
+ {
+ /*
+ We haven't synched the log entries yet, we synch them now before
+ writing the execute entry. If complete is true we haven't written
+ any log entries before, we are only here to write the execute
+ entry to indicate it is done.
+ */
+ VOID(sync_ddl_log());
+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
+ }
+ else
+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
+ file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
+ file_entry_buf[DDL_LOG_PHASE_POS]= 0;
+ int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
+ file_entry_buf[DDL_LOG_NAME_POS]= 0;
+ file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
+ file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
+ if (!(*active_entry))
+ {
+ if (get_free_ddl_log_entry(active_entry, &write_header))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ if (write_ddl_log_file_entry((*active_entry)->entry_pos))
+ {
+ sql_print_error("Error writing execute entry in ddl log");
+ release_ddl_log_memory_entry(*active_entry);
+ DBUG_RETURN(TRUE);
+ }
+ VOID(sync_ddl_log());
+ if (write_header)
+ {
+ if (write_ddl_log_header())
+ {
+ release_ddl_log_memory_entry(*active_entry);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ For complex rename operations we need to deactivate individual entries.
+ SYNOPSIS
+ deactivate_ddl_log_entry()
+ entry_no Entry position of record to change
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ During replace operations where we start with an existing table called
+ t1 and a replacement table called t1#temp or something else and where
+ we want to delete t1 and rename t1#temp to t1 this is not possible to
+ do in a safe manner unless the ddl log is informed of the phases in
+ the change.
+
+ Delete actions are 1-phase actions that can be ignored immediately after
+ being executed.
+ Rename actions from x to y is also a 1-phase action since there is no
+ interaction with any other handlers named x and y.
+ Replace action where drop y and x -> y happens needs to be a two-phase
+ action. Thus the first phase will drop y and the second phase will
+ rename x -> y.
+*/
+
+bool deactivate_ddl_log_entry(uint entry_no)
+{
+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ DBUG_ENTER("deactivate_ddl_log_entry");
+
+ if (!read_ddl_log_file_entry(entry_no))
+ {
+ if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
+ {
+ if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
+ file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
+ (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
+ file_entry_buf[DDL_LOG_PHASE_POS] == 1))
+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
+ else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
+ {
+ DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
+ file_entry_buf[DDL_LOG_PHASE_POS]= 1;
+ }
+ else
+ {
+ DBUG_ASSERT(0);
+ }
+ if (write_ddl_log_file_entry(entry_no))
+ {
+ sql_print_error("Error in deactivating log entry. Position = %u",
+ entry_no);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ else
+ {
+ sql_print_error("Failed in reading entry before deactivating it");
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Sync ddl log file
+ SYNOPSIS
+ sync_ddl_log()
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+bool sync_ddl_log()
+{
+ bool error= FALSE;
+ DBUG_ENTER("sync_ddl_log");
+
+ if ((!global_ddl_log.recovery_phase) &&
+ init_ddl_log())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (my_sync(global_ddl_log.file_id, MYF(0)))
+ {
+ /* Write to error log */
+ sql_print_error("Failed to sync ddl log");
+ error= TRUE;
+ }
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Release a log memory entry
+ SYNOPSIS
+ release_ddl_log_memory_entry()
+ log_memory_entry Log memory entry to release
+ RETURN VALUES
+ NONE
+*/
+
+void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
+{
+ DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
+ DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
+ DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
+ DBUG_ENTER("release_ddl_log_memory_entry");
+
+ global_ddl_log.first_free= log_entry;
+ log_entry->next_log_entry= first_free;
+
+ if (prev_log_entry)
+ prev_log_entry->next_log_entry= next_log_entry;
+ else
+ global_ddl_log.first_used= next_log_entry;
+ if (next_log_entry)
+ next_log_entry->prev_log_entry= prev_log_entry;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Execute one entry in the ddl log. Executing an entry means executing
+ a linked list of actions.
+ SYNOPSIS
+ execute_ddl_log_entry()
+ first_entry Reference to first action in entry
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+bool execute_ddl_log_entry(THD *thd, uint first_entry)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ uint read_entry= first_entry;
+ DBUG_ENTER("execute_ddl_log_entry");
+
+ pthread_mutex_lock(&LOCK_gdl);
+ do
+ {
+ if (read_ddl_log_entry(read_entry, &ddl_log_entry))
+ {
+ /* Write to error log and continue with next log entry */
+ sql_print_error("Failed to read entry = %u from ddl log",
+ read_entry);
+ break;
+ }
+ DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
+ ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
+
+ if (execute_ddl_log_action(thd, &ddl_log_entry))
+ {
+ /* Write to error log and continue with next log entry */
+ sql_print_error("Failed to execute action for entry = %u from ddl log",
+ read_entry);
+ break;
+ }
+ read_entry= ddl_log_entry.next_entry;
+ } while (read_entry);
+ pthread_mutex_unlock(&LOCK_gdl);
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Execute the ddl log at recovery of MySQL Server
+ SYNOPSIS
+ execute_ddl_log_recovery()
+ RETURN VALUES
+ NONE
+*/
+
+void execute_ddl_log_recovery()
+{
+ uint num_entries, i;
+ THD *thd;
+ DDL_LOG_ENTRY ddl_log_entry;
+ char file_name[FN_REFLEN];
+ DBUG_ENTER("execute_ddl_log_recovery");
+
+ /*
+ Initialise global_ddl_log struct
+ */
+ bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
+ global_ddl_log.inited= FALSE;
+ global_ddl_log.recovery_phase= TRUE;
+ global_ddl_log.io_size= IO_SIZE;
+ global_ddl_log.file_id= (File) -1;
+
+ /*
+ To be able to run this from boot, we allocate a temporary THD
+ */
+ if (!(thd=new THD))
+ DBUG_VOID_RETURN;
+ thd->thread_stack= (char*) &thd;
+ thd->store_globals();
+
+ num_entries= read_ddl_log_header();
+ for (i= 1; i < num_entries + 1; i++)
+ {
+ if (read_ddl_log_entry(i, &ddl_log_entry))
+ {
+ sql_print_error("Failed to read entry no = %u from ddl log",
+ i);
+ continue;
+ }
+ if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
+ {
+ if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
+ {
+ /* Real unpleasant scenario but we continue anyways. */
+ continue;
+ }
+ }
+ }
+ create_ddl_log_file_name(file_name);
+ VOID(my_delete(file_name, MYF(0)));
+ global_ddl_log.recovery_phase= FALSE;
+ delete thd;
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Release all memory allocated to the ddl log
+ SYNOPSIS
+ release_ddl_log()
+ RETURN VALUES
+ NONE
+*/
+
+void release_ddl_log()
+{
+ DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
+ DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
+ DBUG_ENTER("release_ddl_log");
+
+ pthread_mutex_lock(&LOCK_gdl);
+ while (used_list)
+ {
+ DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
+ my_free((char*)used_list, MYF(0));
+ used_list= tmp;
+ }
+ while (free_list)
+ {
+ DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
+ my_free((char*)free_list, MYF(0));
+ free_list= tmp;
+ }
+ if (global_ddl_log.file_id >= 0)
+ {
+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
+ global_ddl_log.file_id= (File) -1;
+ }
+ global_ddl_log.inited= 0;
+ pthread_mutex_unlock(&LOCK_gdl);
+ VOID(pthread_mutex_destroy(&LOCK_gdl));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+---------------------------------------------------------------------------
+
+ END MODULE DDL log
+ --------------------
+
+---------------------------------------------------------------------------
+*/
+
/*
SYNOPSIS
@@ -281,83 +1192,68 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
*/
int error= 0;
char path[FN_REFLEN+1];
+ char shadow_path[FN_REFLEN+1];
+ char shadow_frm_name[FN_REFLEN+1];
char frm_name[FN_REFLEN+1];
DBUG_ENTER("mysql_write_frm");
- if (flags & WFRM_INITIAL_WRITE)
+ /*
+ Build shadow frm file name
+ */
+ build_table_filename(shadow_path, sizeof(shadow_path), lpt->db,
+ lpt->table_name, "#");
+ strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
+ if (flags & WFRM_WRITE_SHADOW)
{
- error= mysql_copy_create_list(lpt->create_list,
- &lpt->new_create_list);
- error+= mysql_copy_key_list(lpt->key_list,
- &lpt->new_key_list);
- if (error)
+ if (mysql_copy_create_list(lpt->create_list,
+ &lpt->new_create_list) ||
+ mysql_copy_key_list(lpt->key_list,
+ &lpt->new_key_list) ||
+ mysql_prepare_table(lpt->thd, lpt->create_info,
+ &lpt->new_create_list,
+ &lpt->new_key_list,
+ /*tmp_table*/ 1,
+ &lpt->db_options,
+ lpt->table->file,
+ &lpt->key_info_buffer,
+ &lpt->key_count,
+ /*select_field_count*/ 0))
{
DBUG_RETURN(TRUE);
}
- }
- build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "");
- strxmov(frm_name, path, reg_ext, NullS);
- if ((flags & WFRM_INITIAL_WRITE) &&
- (mysql_prepare_table(lpt->thd, lpt->create_info, &lpt->new_create_list,
- &lpt->new_key_list,/*tmp_table*/ 1, &lpt->db_options,
- lpt->table->file, &lpt->key_info_buffer,
- &lpt->key_count, /*select_field_count*/ 0)))
- {
- DBUG_RETURN(TRUE);
- }
#ifdef WITH_PARTITION_STORAGE_ENGINE
- {
- partition_info *part_info= lpt->table->part_info;
- char *part_syntax_buf;
- uint syntax_len, i;
- bool any_unnormal_state= FALSE;
-
- if (part_info)
{
- uint max_part_state_len= part_info->partitions.elements +
- part_info->temp_partitions.elements;
- if (!(part_info->part_state= (uchar*)sql_alloc(max_part_state_len)))
- {
- DBUG_RETURN(TRUE);
- }
- part_info->part_state_len= 0;
- if (!(part_syntax_buf= generate_partition_syntax(part_info,
- &syntax_len,
- TRUE, FALSE)))
- {
- DBUG_RETURN(TRUE);
- }
- for (i= 0; i < part_info->part_state_len; i++)
- {
- enum partition_state part_state=
- (enum partition_state)part_info->part_state[i];
- if (part_state != PART_NORMAL && part_state != PART_IS_ADDED)
- any_unnormal_state= TRUE;
- }
- if (!any_unnormal_state)
+ partition_info *part_info= lpt->table->part_info;
+ char *part_syntax_buf;
+ uint syntax_len;
+
+ if (part_info)
{
- part_info->part_state= NULL;
- part_info->part_state_len= 0;
+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
+ &syntax_len,
+ TRUE, FALSE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ part_info->part_info_string= part_syntax_buf;
+ part_info->part_info_len= syntax_len;
}
- part_info->part_info_string= part_syntax_buf;
- part_info->part_info_len= syntax_len;
}
- }
#endif
- /*
- We write the frm file with the LOCK_open mutex since otherwise we could
- overwrite the frm file as another is reading it in open_table.
- */
- lpt->create_info->table_options= lpt->db_options;
- VOID(pthread_mutex_lock(&LOCK_open));
- if ((mysql_create_frm(lpt->thd, frm_name, lpt->db, lpt->table_name,
- lpt->create_info, lpt->new_create_list, lpt->key_count,
- lpt->key_info_buffer, lpt->table->file)) ||
- ((flags & WFRM_CREATE_HANDLER_FILES) &&
- lpt->table->file->create_handler_files(path, lpt->create_info)))
- {
- error= 1;
- goto end;
+ /* Write shadow frm file */
+ lpt->create_info->table_options= lpt->db_options;
+ if ((mysql_create_frm(lpt->thd, shadow_frm_name, lpt->db,
+ lpt->table_name, lpt->create_info,
+ lpt->new_create_list, lpt->key_count,
+ lpt->key_info_buffer, lpt->table->file)) ||
+ lpt->table->file->create_handler_files(shadow_path, NULL,
+ CHF_CREATE_FLAG,
+ lpt->create_info))
+ {
+ my_delete(shadow_frm_name, MYF(0));
+ error= 1;
+ goto end;
+ }
}
if (flags & WFRM_PACK_FRM)
{
@@ -369,7 +1265,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
*/
const void *data= 0;
uint length= 0;
- if (readfrm(path, &data, &length) ||
+ if (readfrm(shadow_path, &data, &length) ||
packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len))
{
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
@@ -378,11 +1274,56 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
error= 1;
goto end;
}
- error= my_delete(frm_name, MYF(MY_WME));
+ error= my_delete(shadow_frm_name, MYF(MY_WME));
+ }
+ if (flags & WFRM_INSTALL_SHADOW)
+ {
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ partition_info *part_info= lpt->part_info;
+#endif
+ /*
+ Build frm file name
+ */
+ build_table_filename(path, sizeof(path), lpt->db,
+ lpt->table_name, "");
+ strxmov(frm_name, path, reg_ext, NullS);
+ /*
+ When we are changing to use new frm file we need to ensure that we
+ don't collide with another thread in process to open the frm file.
+ We start by deleting the .frm file and possible .par file. Then we
+ write to the DDL log that we have completed the delete phase by
+ increasing the phase of the log entry. Next step is to rename the
+ new .frm file and the new .par file to the real name. After
+ completing this we write a new phase to the log entry that will
+ deactivate it.
+ */
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (my_delete(frm_name, MYF(MY_WME)) ||
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ lpt->table->file->create_handler_files(path, shadow_path,
+ CHF_DELETE_FLAG, NULL) ||
+ deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos) ||
+ (sync_ddl_log(), FALSE) ||
+#endif
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ my_rename(shadow_frm_name, frm_name, MYF(MY_WME)) ||
+ lpt->table->file->create_handler_files(path, shadow_path,
+ CHF_RENAME_FLAG, NULL))
+#else
+ my_rename(shadow_frm_name, frm_name, MYF(MY_WME)))
+#endif
+ {
+ error= 1;
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
+ part_info->frm_log_entry= NULL;
+ VOID(sync_ddl_log());
+#endif
}
- /* Frm file have been updated to reflect the change about to happen. */
+
end:
- VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(error);
}
@@ -1256,7 +2197,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (need_to_change_arena)
thd->restore_active_arena(thd->stmt_arena, &backup_arena);
- if (! sql_field->def)
+ if (sql_field->def == NULL)
{
/* Could not convert */
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
@@ -1267,15 +2208,30 @@ static 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)
+ if (sql_field->def != NULL)
{
char *not_used;
uint not_used2;
bool not_found= 0;
String str, *def= sql_field->def->val_str(&str);
- def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
- (void) find_set(interval, def->ptr(), def->length(),
- cs, &not_used, &not_used2, &not_found);
+ if (def == NULL) /* SQL "NULL" maps to NULL */
+ {
+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+
+ /* else, NULL is an allowed value */
+ (void) find_set(interval, NULL, 0,
+ cs, &not_used, &not_used2, &not_found);
+ }
+ else /* not NULL */
+ {
+ (void) find_set(interval, def->ptr(), def->length(),
+ cs, &not_used, &not_used2, &not_found);
+ }
+
if (not_found)
{
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
@@ -1288,14 +2244,28 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
else /* FIELD_TYPE_ENUM */
{
uint32 field_length;
- if (sql_field->def)
+ DBUG_ASSERT(sql_field->sql_type == FIELD_TYPE_ENUM);
+ if (sql_field->def != NULL)
{
String str, *def= sql_field->def->val_str(&str);
- def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
- if (!find_type2(interval, def->ptr(), def->length(), cs))
+ if (def == NULL) /* SQL "NULL" maps to NULL */
{
- my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
- DBUG_RETURN(-1);
+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+
+ /* else, the defaults yield the correct length for NULLs. */
+ }
+ else /* not NULL */
+ {
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
}
}
calculate_interval_lengths(cs, interval, &field_length, &dummy);
@@ -1538,14 +2508,16 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
break;
}
- switch(key->type){
+ switch (key->type) {
case Key::MULTIPLE:
key_info->flags= 0;
break;
case Key::FULLTEXT:
key_info->flags= HA_FULLTEXT;
- if ((key_info->parser_name= key->parser_name))
+ if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
key_info->flags|= HA_USES_PARSER;
+ else
+ key_info->parser_name= 0;
break;
case Key::SPATIAL:
#ifdef HAVE_SPATIAL
@@ -1569,7 +2541,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->key_parts=(uint8) key->columns.elements;
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
- key_info->algorithm=key->algorithm;
+ key_info->algorithm= key->key_create_info.algorithm;
if (key->type == Key::FULLTEXT)
{
@@ -1591,6 +2563,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/* TODO: Add proper checks if handler supports key_type and algorithm */
if (key_info->flags & HA_SPATIAL)
{
+ if (!(file->table_flags() & HA_CAN_RTREEKEYS))
+ {
+ my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
+ MYF(0));
+ DBUG_RETURN(-1);
+ }
if (key_info->key_parts != 1)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
@@ -1615,6 +2593,18 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
#endif
}
+ /* Take block size from key part or table part */
+ /*
+ TODO: Add warning if block size changes. We can't do it here, as
+ this may depend on the size of the key
+ */
+ key_info->block_size= (key->key_create_info.block_size ?
+ key->key_create_info.block_size :
+ create_info->key_block_size);
+
+ if (key_info->block_size)
+ key_info->flags|= HA_USES_BLOCK_SIZE;
+
List_iterator<key_part_spec> cols(key->columns), cols2(key->columns);
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
@@ -2088,6 +3078,7 @@ bool mysql_create_table_internal(THD *thd,
}
file->set_auto_partitions(part_info);
part_info->default_engine_type= create_info->db_type;
+ part_info->is_auto_partitioned= TRUE;
}
if (part_info)
{
@@ -2148,8 +3139,8 @@ bool mysql_create_table_internal(THD *thd,
}
DBUG_PRINT("info", ("db_type = %d",
ha_legacy_type(part_info->default_engine_type)));
- if (part_info->check_partition_info( &engine_type, file,
- create_info->max_rows))
+ if (part_info->check_partition_info(&engine_type, file,
+ create_info->max_rows))
goto err;
part_info->default_engine_type= engine_type;
@@ -2208,6 +3199,12 @@ bool mysql_create_table_internal(THD *thd,
}
else if (create_info->db_type != engine_type)
{
+ /*
+ We come here when we don't use a partitioned handler.
+ Since we use a partitioned table it must be "native partitioned".
+ We have switched engine from defaults, most likely only specified
+ engines in partition clauses.
+ */
delete file;
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, engine_type)))
{
@@ -2429,111 +3426,6 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
/****************************************************************************
-** Create table from a list of fields and items
-****************************************************************************/
-
-TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
- TABLE_LIST *create_table,
- List<create_field> *extra_fields,
- List<Key> *keys,
- List<Item> *items,
- MYSQL_LOCK **lock,
- TABLEOP_HOOKS *hooks)
-{
- TABLE tmp_table; // Used during 'create_field()'
- TABLE_SHARE share;
- TABLE *table= 0;
- uint select_field_count= items->elements;
- /* Add selected items to field list */
- List_iterator_fast<Item> it(*items);
- Item *item;
- Field *tmp_field;
- bool not_used;
- DBUG_ENTER("create_table_from_items");
-
- tmp_table.alias= 0;
- tmp_table.timestamp_field= 0;
- tmp_table.s= &share;
- init_tmp_table_share(&share, "", 0, "", "");
-
- 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 == &myisam_hton ||
- create_info->db_type == &heap_hton);
- tmp_table.null_row=tmp_table.maybe_null=0;
-
- while ((item=it++))
- {
- create_field *cr_field;
- Field *field;
- if (item->type() == Item::FUNC_ITEM)
- 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, 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
-
- 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, 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);
- }
-
- /*
- 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;
- hooks->prelock(&table, 1); // Call prelock hooks
- 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, create_table->db,
- table_case_name(create_info, create_table->table_name));
- DBUG_RETURN(0);
- }
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- DBUG_RETURN(table);
-}
-
-
-/****************************************************************************
** Alter a table definition
****************************************************************************/
@@ -2588,7 +3480,9 @@ mysql_rename_table(handlerton *base,
}
}
delete file;
- if (error)
+ if (error == HA_ERR_WRONG_COMMAND)
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
+ else if (error)
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
DBUG_RETURN(error != 0);
}
@@ -2906,6 +3800,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
int result_code;
DBUG_ENTER("mysql_admin_table");
+ if (end_active_trans(thd))
+ DBUG_RETURN(1);
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Op", 10));
@@ -2956,6 +3852,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
switch ((*prepare_func)(thd, table, check_opt)) {
case 1: // error, message written to net
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
continue;
case -1: // error, message could be written to net
@@ -2997,6 +3894,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
View opening can be interrupted in the middle of process so some
tables can be left opening
*/
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
if (protocol->write())
goto err;
@@ -3021,6 +3919,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name);
protocol->store(buff, length, system_charset_info);
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -3066,6 +3965,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
(table->table->file->ha_check_for_upgrade(check_opt) ==
HA_ADMIN_NEEDS_ALTER))
{
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
@@ -3152,6 +4052,7 @@ send_result_message:
"try with alter", so here we close the table, do an ALTER TABLE,
reopen the table and do ha_innobase::analyze() on it.
*/
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
@@ -3159,6 +4060,7 @@ send_result_message:
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
reenable_binlog(thd);
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
{
@@ -3233,14 +4135,20 @@ send_result_message:
table->table->s->version=0; // Force close of table
else if (open_for_modify && !table->table->s->log_table)
{
- pthread_mutex_lock(&LOCK_open);
- remove_table_from_cache(thd, table->table->s->db.str,
- table->table->s->table_name.str, RTFC_NO_FLAG);
- pthread_mutex_unlock(&LOCK_open);
- /* Something may be modified, that's why we have to invalidate cache */
+ if (table->table->s->tmp_table)
+ table->table->file->info(HA_STATUS_CONST);
+ else
+ {
+ pthread_mutex_lock(&LOCK_open);
+ remove_table_from_cache(thd, table->table->s->db.str,
+ table->table->s->table_name.str, 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);
}
}
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -3249,7 +4157,9 @@ send_result_message:
send_eof(thd);
DBUG_RETURN(FALSE);
+
err:
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
@@ -3704,7 +4614,9 @@ mysql_discard_or_import_tablespace(THD *thd,
if (error)
goto err;
write_bin_log(thd, FALSE, thd->query, thd->query_length);
+
err:
+ ha_autocommit_or_rollback(thd, error);
close_thread_tables(thd);
thd->tablespace_op=FALSE;
@@ -4088,7 +5000,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
ha_resolve_storage_engine_name(old_db_type),
ha_resolve_storage_engine_name(new_db_type)));
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
- ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
+ ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED) ||
+ (old_db_type != new_db_type &&
+ ha_check_storage_engine_flag(new_db_type, HTON_ALTER_CANNOT_CREATE)))
{
DBUG_PRINT("info", ("doesn't support alter"));
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
@@ -4185,6 +5099,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->avg_row_length= table->s->avg_row_length;
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->s->table_charset;
+ if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
+ create_info->key_block_size= table->s->key_block_size;
restore_record(table, s->default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
@@ -4387,6 +5303,16 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
key_part_length));
}
if (key_parts.elements)
+ {
+ KEY_CREATE_INFO key_create_info;
+ bzero((char*) &key_create_info, sizeof(key_create_info));
+
+ key_create_info.algorithm= key_info->algorithm;
+ if (key_info->flags & HA_USES_BLOCK_SIZE)
+ key_create_info.block_size= key_info->block_size;
+ if (key_info->flags & HA_USES_PARSER)
+ key_create_info.parser_name= *key_info->parser_name;
+
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
(key_info->flags & HA_NOSAME ?
(!my_strcasecmp(system_charset_info,
@@ -4395,11 +5321,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
(key_info->flags & HA_FULLTEXT ?
Key::FULLTEXT : Key::MULTIPLE)),
key_name,
- key_info->algorithm,
+ &key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts,
- key_info->flags & HA_USES_PARSER ?
- &key_info->parser->name : 0));
+ key_parts));
+ }
}
{
Key *key;
@@ -4495,9 +5420,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((prep_col= prep_col_it++))
prep_columns.push_back(new key_part_spec(*prep_col));
prepared_key_list.push_back(new Key(prep_key->type, prep_key->name,
- prep_key->algorithm,
- prep_key->generated, prep_columns,
- prep_key->parser_name));
+ &prep_key->key_create_info,
+ prep_key->generated, prep_columns));
}
/* Create the prepared information. */
@@ -4737,10 +5661,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
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;
- }
+ goto err1;
}
/* Copy the data if necessary. */
@@ -4790,10 +5711,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
error= (mysql_create_frm(thd, reg_path, db, table_name,
create_info, prepared_create_list, key_count,
key_info_buffer, table->file) ||
- table->file->create_handler_files(path, create_info));
+ table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG,
+ create_info));
VOID(pthread_mutex_unlock(&LOCK_open));
if (error)
- goto err;
+ goto err1;
#endif
/* The add_index() method takes an array of KEY structs. */
@@ -4821,7 +5743,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->key_info= key_info;
table->file->print_error(error, MYF(0));
table->key_info= save_key_info;
- goto err;
+ goto err1;
}
}
/*end of if (index_add_count)*/
@@ -4836,10 +5758,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
error= (mysql_create_frm(thd, reg_path, db, table_name,
create_info, prepared_create_list, key_count,
key_info_buffer, table->file) ||
- table->file->create_handler_files(path, create_info));
+ table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG,
+ create_info));
VOID(pthread_mutex_unlock(&LOCK_open));
if (error)
- goto err;
+ goto err1;
if (! need_lock_for_indexes)
{
@@ -4873,7 +5796,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
index_drop_count)))
{
table->file->print_error(error, MYF(0));
- goto err;
+ goto err1;
}
#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020
@@ -4901,7 +5824,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if ((error= table->file->final_drop_index(table)))
{
table->file->print_error(error, MYF(0));
- goto err;
+ goto err1;
}
}
/*end of if (index_drop_count)*/
@@ -4914,7 +5837,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* Need to commit before a table is unlocked (NDB requirement). */
DBUG_PRINT("info", ("Committing before unlocking table"));
if (ha_commit_stmt(thd) || ha_commit(thd))
- goto err;
+ goto err1;
committed= 1;
}
/*end of if (! new_table) for add/drop index*/
@@ -4923,17 +5846,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
/* We changed a temporary table */
if (error)
- {
- /*
- The following function call will free the new_table pointer,
- in close_temporary_table(), so we can safely directly jump to err
- */
- if (new_table)
- close_temporary_table(thd, new_table, 1, 1);
- else
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- goto err;
- }
+ goto err1;
/* Close lock if this is a transactional table */
if (thd->lock)
{
@@ -4944,16 +5857,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
close_temporary_table(thd, table, 1, 1);
/* 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
- if (new_table)
- {
- close_temporary_table(thd, new_table, 1, 1);
- my_free((gptr) new_table,MYF(0));
- }
- else
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- goto err;
- }
+ goto err1;
/* We don't replicate alter table statement on temporary tables */
if (!thd->current_stmt_binlog_row_based)
write_bin_log(thd, TRUE, thd->query, thd->query_length);
@@ -5060,7 +5964,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_lock(&LOCK_open));
}
/* Tell the handler that a new frm file is in place. */
- if (table->file->create_handler_files(path, create_info))
+ if (table->file->create_handler_files(path, NULL, CHF_INDEX_FLAG,
+ create_info))
{
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
@@ -5168,6 +6073,15 @@ end_temporary:
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
+ err1:
+ if (new_table)
+ {
+ /* close_temporary_table() frees the new_table pointer. */
+ close_temporary_table(thd, new_table, 1, 1);
+ }
+ else
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+
err:
DBUG_RETURN(TRUE);
}
@@ -5313,6 +6227,20 @@ copy_data_between_tables(TABLE *from,TABLE *to,
(error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE))
{
+ if (error == HA_ERR_FOUND_DUPP_KEY)
+ {
+ uint key_nr= to->file->get_dup_key(error);
+ if ((int) key_nr >= 0)
+ {
+ const char *err_msg= ER(ER_DUP_ENTRY);
+ if (key_nr == 0 &&
+ (to->key_info[0].key_part[0].field->flags & AUTO_INCREMENT_FLAG))
+ err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
+ to->file->print_keydupp_error(key_nr, err_msg);
+ break;
+ }
+ }
+
to->file->print_error(error,MYF(0));
break;
}
@@ -5391,7 +6319,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
}
-bool 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;
diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc
index 954d65ea44e..8bc39ec82c6 100644
--- a/sql/sql_tablespace.cc
+++ b/sql/sql_tablespace.cc
@@ -21,31 +21,51 @@
int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info)
{
int error= HA_ADMIN_NOT_IMPLEMENTED;
- handlerton *hton;
+ const handlerton *hton= ts_info->storage_engine;
DBUG_ENTER("mysql_alter_tablespace");
/*
If the user haven't defined an engine, this will fallback to using the
default storage engine.
*/
- hton= ha_resolve_by_legacy_type(thd, ts_info->storage_engine);
+ if (hton == NULL || hton == &default_hton || hton->state != SHOW_OPTION_YES)
+ {
+ hton= ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT);
+ if (ts_info->storage_engine != 0)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER(ER_WARN_USING_OTHER_HANDLER),
+ hton->name,
+ ts_info->tablespace_name
+ ? ts_info->tablespace_name : ts_info->logfile_group_name);
+ }
- if (hton->state == SHOW_OPTION_YES &&
- hton->alter_tablespace && (error= hton->alter_tablespace(thd, ts_info)))
+ if (hton->alter_tablespace)
{
- if (error == HA_ADMIN_NOT_IMPLEMENTED)
- {
- my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "");
- }
- else if (error == 1)
+ if ((error= hton->alter_tablespace(thd, ts_info)))
{
- DBUG_RETURN(1);
+ if (error == HA_ADMIN_NOT_IMPLEMENTED)
+ {
+ my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "");
+ }
+ else if (error == 1)
+ {
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ my_error(error, MYF(0));
+ }
+ DBUG_RETURN(error);
}
- else
- {
- my_error(error, MYF(0));
- }
- DBUG_RETURN(error);
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ ER(ER_ILLEGAL_HA_CREATE_OPTION),
+ hton->name,
+ "TABLESPACE or LOGFILE GROUP");
}
if (mysql_bin_log.is_open())
{
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index bf86630d28c..b28aa4a1ce5 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -230,8 +230,8 @@ TEST_join(JOIN *join)
*/
void
-print_plan(JOIN* join, double read_time, double record_count,
- uint idx, const char *info)
+print_plan(JOIN* join, uint idx, double record_count, double read_time,
+ double current_read_time, const char *info)
{
uint i;
POSITION pos;
@@ -245,13 +245,15 @@ print_plan(JOIN* join, double read_time, double record_count,
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);
+ fprintf(DBUG_FILE,
+ "%s; idx:%u, best: DBL_MAX, atime: %g, itime: %g, count: %g\n",
+ info, idx, current_read_time, read_time, record_count);
}
else
{
- fprintf(DBUG_FILE,"%s; idx: %u, best: %g, current: %g\n",
- info, idx, join->best_read, read_time);
+ fprintf(DBUG_FILE,
+ "%s; idx:%u, best: %g, accumulated: %g, increment: %g, count: %g\n",
+ info, idx, join->best_read, current_read_time, read_time, record_count);
}
/* Print the tables in JOIN->positions */
@@ -270,9 +272,9 @@ print_plan(JOIN* join, double read_time, double record_count,
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)
{
+ fputs("BEST_POSITIONS: ", DBUG_FILE);
for (i= 0; i < idx ; i++)
{
pos= join->best_positions[i];
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index b2b6b115f7d..0ea87f3dfe4 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1412,8 +1412,8 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
}
if (table.triggers)
{
- LEX_STRING_WITH_INIT old_table_name(old_table, strlen(old_table));
- LEX_STRING_WITH_INIT new_table_name(new_table, strlen(new_table));
+ LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) };
+ LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
/*
Since triggers should be in the same schema as their subject tables
moving table with them between two schemas raises too many questions.
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index e80aaecfd64..3c156acfc14 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -202,7 +202,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= sl= first_sl;
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
- is_union= test(first_sl->next_select());
+ is_union= first_sl->next_select() || fake_select_lex;
/* Global option */
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 18217094ff7..8e5a776950d 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -773,6 +773,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
SELECT_LEX *end, *view_select;
LEX *old_lex, *lex;
Query_arena *arena, backup;
+ TABLE_LIST *top_view= table->top_table();
int res;
bool result;
DBUG_ENTER("mysql_make_view");
@@ -800,6 +801,24 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
DBUG_RETURN(0);
}
+ /* check loop via view definition */
+ for (TABLE_LIST *precedent= table->referencing_view;
+ precedent;
+ precedent= precedent->referencing_view)
+ {
+ if (precedent->view_name.length == table->table_name_length &&
+ precedent->view_db.length == table->db_length &&
+ my_strcasecmp(system_charset_info,
+ precedent->view_name.str, table->table_name) == 0 &&
+ my_strcasecmp(system_charset_info,
+ precedent->view_db.str, table->db) == 0)
+ {
+ my_error(ER_VIEW_RECURSIVE, MYF(0),
+ top_view->view_db.str, top_view->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+ }
+
/*
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).
@@ -898,7 +917,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
}
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;
@@ -925,7 +943,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
goto err;
}
-
if (!(table->view_tables=
(List<TABLE_LIST>*) new(thd->mem_root) List<TABLE_LIST>))
goto err;
@@ -1041,15 +1058,23 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
!old_lex->can_not_use_merged())
{
List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
+ /*
+ Currently 'view_main_select_tables' differs from 'view_tables'
+ only then view has CONVERT_TZ() function in its select list.
+ This may change in future, for example if we enable merging
+ of views with subqueries in select list.
+ */
+ TABLE_LIST *view_main_select_tables=
+ (TABLE_LIST*)lex->select_lex.table_list.first;
/* lex should contain at least one table */
- DBUG_ASSERT(view_tables != 0);
+ DBUG_ASSERT(view_main_select_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);
- table->merge_underlying_list= view_tables;
+ table->merge_underlying_list= view_main_select_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
@@ -1065,7 +1090,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
}
/* prepare view context */
- lex->select_lex.context.resolve_in_table_list_only(view_tables);
+ lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);
lex->select_lex.context.outer_context= 0;
lex->select_lex.context.select_lex= table->select_lex;
lex->select_lex.select_n_having_items+=
@@ -1081,7 +1106,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
tbl->select_lex= table->select_lex;
{
- if (view_tables->next_local)
+ if (view_main_select_tables->next_local)
{
table->multitable_view= TRUE;
if (table->belong_to_view)
@@ -1168,6 +1193,7 @@ ok2:
old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used;
result= !table->prelocking_placeholder && table->prepare_security(thd);
+ lex_end(thd->lex);
end:
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -1175,6 +1201,8 @@ end:
DBUG_RETURN(result);
err:
+ DBUG_ASSERT(thd->lex == table->view);
+ lex_end(thd->lex);
delete table->view;
table->view= 0; // now it is not VIEW placeholder
result= 1;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2f91472ad2d..82dcc758ff0 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -204,6 +204,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CONSTRAINT
%token CONTAINS_SYM
%token CONTINUE_SYM
+%token CONTRIBUTORS_SYM
%token CONVERT_SYM
%token CONVERT_TZ_SYM
%token COUNT_SYM
@@ -317,7 +318,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GEOMFROMWKB
%token GET_FORMAT
%token GLOBAL_SYM
-%token GOTO_SYM
%token GRANT
%token GRANTS
%token GREATEST_SYM
@@ -365,8 +365,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token JOIN_SYM
%token KEYS
%token KEY_SYM
+%token KEY_BLOCK_SIZE
%token KILL_SYM
-%token LABEL_SYM
%token LANGUAGE_SYM
%token LAST_INSERT_ID
%token LAST_SYM
@@ -476,6 +476,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NUMERIC_SYM
%token NVARCHAR_SYM
%token OFFSET_SYM
+%token OJ_SYM
%token OLD_PASSWORD
%token ON
%token ONE_SHOT_SYM
@@ -568,6 +569,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RTREE_SYM
%token SAVEPOINT_SYM
%token SCHEDULE_SYM
+%token SCHEDULER_SYM
%token SECOND_MICROSECOND_SYM
%token SECOND_SYM
%token SECURITY_SYM
@@ -732,7 +734,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem
%type <lex_str_ptr>
- opt_table_alias opt_fulltext_parser
+ opt_table_alias
%type <table>
table_ident table_ident_nodb references xid
@@ -797,7 +799,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
key_type opt_unique_or_fulltext constraint_key_type
%type <key_alg>
- key_alg opt_btree_or_rtree
+ btree_or_rtree
%type <string_list>
key_usage_list using_list
@@ -888,13 +890,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
view_suid view_tail view_list_opt view_list view_select
view_check_option trigger_tail sp_tail
install uninstall partition_entry binlog_base64_event
+ init_key_options key_options key_opts key_opt key_using_alg
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
%type <NONE> sp_proc_stmt_if sp_proc_stmt_case_simple sp_proc_stmt_case
%type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave
-%type <NONE> sp_proc_stmt_iterate sp_proc_stmt_label sp_proc_stmt_goto
+%type <NONE> sp_proc_stmt_iterate
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
@@ -1222,11 +1225,13 @@ create:
}
create2
{ Lex->current_select= &Lex->select_lex; }
- | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
+ | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON
+ table_ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
- if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
+ if (!lex->current_select->add_table_to_list(lex->thd, $7,
+ NULL,
TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
@@ -1234,15 +1239,16 @@ create:
lex->col_list.empty();
lex->change=NullS;
}
- '(' key_list ')' opt_fulltext_parser
+ '(' key_list ')' key_options
{
LEX *lex=Lex;
- if ($2 != Key::FULLTEXT && $12)
+ if ($2 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- lex->key_list.push_back(new Key($2,$4.str,$5,0,lex->col_list,$12));
+ lex->key_list.push_back(new Key($2, $4.str, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident
@@ -1397,7 +1403,7 @@ opt_ev_status: /* empty */ { $$= 0; }
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
- lex->et->status= MYSQL_EVENT_ENABLED;
+ lex->et->status= Event_timed::ENABLED;
$$= 1;
}
| DISABLE_SYM
@@ -1405,7 +1411,7 @@ opt_ev_status: /* empty */ { $$= 0; }
LEX *lex=Lex;
if (!lex->et_compile_phase)
- lex->et->status= MYSQL_EVENT_DISABLED;
+ lex->et->status= Event_timed::DISABLED;
$$= 1;
}
;
@@ -1469,14 +1475,14 @@ ev_on_completion:
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
- lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_PRESERVE;
+ lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE;
$$= 1;
}
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
- lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_DROP;
+ lex->et->on_completion= Event_timed::ON_COMPLETION_DROP;
$$= 1;
}
;
@@ -1555,8 +1561,6 @@ ev_sql_stmt_inner:
| sp_proc_stmt_unlabeled
| sp_proc_stmt_leave
| sp_proc_stmt_iterate
- | sp_proc_stmt_label
- | sp_proc_stmt_goto
| sp_proc_stmt_open
| sp_proc_stmt_fetch
| sp_proc_stmt_close
@@ -1691,8 +1695,6 @@ create_function_tail:
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);
if (!(sp->m_flags & sp_head::HAS_RETURN))
@@ -1819,22 +1821,23 @@ sp_fdparam:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_pvar(&$1, TRUE))
+ if (spc->find_variable(&$1, TRUE))
{
my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
YYABORT;
}
- sp_pvar_t *pvar= spc->push_pvar(&$1, (enum enum_field_types)$3,
- sp_param_in);
+ sp_variable_t *spvar= spc->push_variable(&$1,
+ (enum enum_field_types)$3,
+ sp_param_in);
if (lex->sphead->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $3,
- &pvar->field_def))
+ &spvar->field_def))
{
YYABORT;
}
- pvar->field_def.field_name= pvar->name.str;
- pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
+ spvar->field_def.field_name= spvar->name.str;
+ spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
}
;
@@ -1855,22 +1858,23 @@ sp_pdparam:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_pvar(&$3, TRUE))
+ if (spc->find_variable(&$3, TRUE))
{
my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
YYABORT;
}
- sp_pvar_t *pvar= spc->push_pvar(&$3, (enum enum_field_types)$4,
- (sp_param_mode_t)$1);
+ sp_variable_t *spvar= spc->push_variable(&$3,
+ (enum enum_field_types)$4,
+ (sp_param_mode_t)$1);
if (lex->sphead->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $4,
- &pvar->field_def))
+ &spvar->field_def))
{
YYABORT;
}
- pvar->field_def.field_name= pvar->name.str;
- pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
+ spvar->field_def.field_name= spvar->name.str;
+ spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
}
;
@@ -1934,7 +1938,7 @@ sp_decl:
{
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
- uint num_vars= pctx->context_pvars();
+ uint num_vars= pctx->context_var_count();
enum enum_field_types var_type= (enum enum_field_types) $4;
Item *dflt_value_item= $5;
create_field *create_field_op;
@@ -1947,23 +1951,23 @@ sp_decl:
for (uint i = num_vars-$2 ; i < num_vars ; i++)
{
- uint var_idx= pctx->pvar_context2index(i);
- sp_pvar_t *pvar= pctx->find_pvar(var_idx);
+ uint var_idx= pctx->var_context2runtime(i);
+ sp_variable_t *spvar= pctx->find_variable(var_idx);
- if (!pvar)
+ if (!spvar)
YYABORT;
- pvar->type= var_type;
- pvar->dflt= dflt_value_item;
+ spvar->type= var_type;
+ spvar->dflt= dflt_value_item;
if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
- &pvar->field_def))
+ &spvar->field_def))
{
YYABORT;
}
- pvar->field_def.field_name= pvar->name.str;
- pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
+ spvar->field_def.field_name= spvar->name.str;
+ spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
@@ -2000,7 +2004,7 @@ sp_decl:
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
- ctx->current_pvars());
+ ctx->current_var_count());
sp->add_instr(i);
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
@@ -2017,7 +2021,7 @@ sp_decl:
if ($2 == SP_HANDLER_CONTINUE)
{
i= new sp_instr_hreturn(sp->instructions(), ctx,
- ctx->current_pvars());
+ ctx->current_var_count());
sp->add_instr(i);
}
else
@@ -2048,7 +2052,7 @@ sp_decl:
YYABORT;
}
i= new sp_instr_cpush(sp->instructions(), ctx, $5,
- ctx->current_cursors());
+ ctx->current_cursor_count());
sp->add_instr(i);
ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0;
@@ -2203,12 +2207,12 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_pvar(&$1, TRUE))
+ if (spc->find_variable(&$1, TRUE))
{
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
YYABORT;
}
- spc->push_pvar(&$1, (enum_field_types)0, sp_param_in);
+ spc->push_variable(&$1, (enum_field_types)0, sp_param_in);
$$= 1;
}
| sp_decl_idents ',' ident
@@ -2218,12 +2222,12 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_pvar(&$3, TRUE))
+ if (spc->find_variable(&$3, TRUE))
{
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
YYABORT;
}
- spc->push_pvar(&$3, (enum_field_types)0, sp_param_in);
+ spc->push_variable(&$3, (enum_field_types)0, sp_param_in);
$$= $1 + 1;
}
;
@@ -2243,8 +2247,6 @@ sp_proc_stmt:
| sp_proc_stmt_unlabeled
| sp_proc_stmt_leave
| sp_proc_stmt_iterate
- | sp_proc_stmt_label
- | sp_proc_stmt_goto
| sp_proc_stmt_open
| sp_proc_stmt_fetch
| sp_proc_stmt_close
@@ -2447,97 +2449,6 @@ sp_proc_stmt_iterate:
}
;
-sp_proc_stmt_label:
- 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
- }
- ;
-
-sp_proc_stmt_goto:
- 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
- }
- ;
-
sp_proc_stmt_open:
OPEN_SYM ident
{
@@ -2606,9 +2517,9 @@ sp_fetch_list:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *spc= lex->spcont;
- sp_pvar_t *spv;
+ sp_variable_t *spv;
- if (!spc || !(spv = spc->find_pvar(&$1)))
+ if (!spc || !(spv = spc->find_variable(&$1)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
YYABORT;
@@ -2627,9 +2538,9 @@ sp_fetch_list:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *spc= lex->spcont;
- sp_pvar_t *spv;
+ sp_variable_t *spv;
- if (!spc || !(spv = spc->find_pvar(&$3)))
+ if (!spc || !(spv = spc->find_variable(&$3)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
YYABORT;
@@ -3185,13 +3096,13 @@ opt_ts_engine:
opt_storage ENGINE_SYM opt_equal storage_engines
{
LEX *lex= Lex;
- if (lex->alter_tablespace_info->storage_engine != DB_TYPE_UNKNOWN)
+ if (lex->alter_tablespace_info->storage_engine != NULL)
{
my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),
"STORAGE ENGINE");
YYABORT;
}
- lex->alter_tablespace_info->storage_engine= $4->db_type;
+ lex->alter_tablespace_info->storage_engine= $4 ? $4 : &default_hton;
};
opt_ts_wait:
@@ -3558,75 +3469,14 @@ part_definition:
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
partition_element *p_elem= new partition_element();
- uint part_id= part_info->partitions.elements +
- part_info->temp_partitions.elements;
- enum partition_state part_state;
+ uint part_id= part_info->partitions.elements;
- if (part_info->part_state)
- part_state= (enum partition_state)part_info->part_state[part_id];
- else
- part_state= PART_NORMAL;
- switch (part_state)
+ if (!p_elem || part_info->partitions.push_back(p_elem))
{
- case PART_TO_BE_DROPPED:
- /*
- This part is currently removed so we keep it in a
- temporary list for REPAIR TABLE to be able to handle
- failures during drop partition process.
- */
- case PART_TO_BE_ADDED:
- /*
- This part is currently being added so we keep it in a
- temporary list for REPAIR TABLE to be able to handle
- failures during add partition process.
- */
- if (!p_elem || part_info->temp_partitions.push_back(p_elem))
- {
- mem_alloc_error(sizeof(partition_element));
- YYABORT;
- }
- break;
- case PART_IS_ADDED:
- /*
- Part has been added and is now a normal partition
- */
- case PART_TO_BE_REORGED:
- /*
- This part is currently reorganised, it is still however
- used so we keep it in the list of partitions. We do
- however need the state to be able to handle REPAIR TABLE
- after failures in the reorganisation process.
- */
- case PART_REORGED_DROPPED:
- /*
- This part is currently reorganised as part of a
- COALESCE PARTITION and it will be dropped without a new
- replacement partition after completing the reorganisation.
- */
- case PART_CHANGED:
- /*
- This part is currently split or merged as part of ADD
- PARTITION for a hash partition or as part of COALESCE
- PARTITION for a hash partitioned table.
- */
- case PART_IS_CHANGED:
- /*
- This part has been split or merged as part of ADD
- PARTITION for a hash partition or as part of COALESCE
- PARTITION for a hash partitioned table.
- */
- case PART_NORMAL:
- if (!p_elem || part_info->partitions.push_back(p_elem))
- {
- mem_alloc_error(sizeof(partition_element));
- YYABORT;
- }
- break;
- default:
- mem_alloc_error((part_id * 1000) + part_state);
- YYABORT;
+ mem_alloc_error(sizeof(partition_element));
+ YYABORT;
}
- p_elem->part_state= part_state;
+ p_elem->part_state= PART_NORMAL;
part_info->curr_part_elem= p_elem;
part_info->current_partition= p_elem;
part_info->use_default_partitions= FALSE;
@@ -4048,6 +3898,11 @@ create_table_option:
| STORAGE_SYM DISK_SYM {Lex->create_info.store_on_disk= TRUE;}
| STORAGE_SYM MEMORY_SYM {Lex->create_info.store_on_disk= FALSE;}
| 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; }
+ | KEY_BLOCK_SIZE opt_equal ulong_num
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE;
+ Lex->create_info.key_block_size= $3;
+ }
;
default_charset:
@@ -4141,23 +3996,25 @@ column_def:
;
key_def:
- key_type opt_ident key_alg '(' key_list ')' opt_fulltext_parser
+ key_type opt_ident key_alg '(' key_list ')' key_options
{
LEX *lex=Lex;
- if ($1 != Key::FULLTEXT && $7)
+ if ($1 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list, $7));
+ lex->key_list.push_back(new Key($1,$2, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
- | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
+ | opt_constraint constraint_key_type opt_ident key_alg
+ '(' key_list ')' key_options
{
LEX *lex=Lex;
- const char *key_name= $3 ? $3:$1;
- lex->key_list.push_back(new Key($2, key_name, $4, 0,
- lex->col_list));
+ const char *key_name= $3 ? $3 : $1;
+ lex->key_list.push_back(new Key($2, key_name, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
@@ -4170,7 +4027,7 @@ key_def:
lex->fk_update_opt,
lex->fk_match_option));
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
- HA_KEY_ALG_UNDEF, 1,
+ &default_key_create_info, 1,
lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
@@ -4187,20 +4044,6 @@ key_def:
}
;
-opt_fulltext_parser:
- /* empty */ { $$= (LEX_STRING *)0; }
- | WITH PARSER_SYM IDENT_sys
- {
- if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
- $$= (LEX_STRING *)sql_memdup(&$3, sizeof(LEX_STRING));
- else
- {
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
- YYABORT;
- }
- }
- ;
-
opt_check_constraint:
/* empty */
| check_constraint
@@ -4674,12 +4517,56 @@ opt_unique_or_fulltext:
}
;
+init_key_options:
+ {
+ Lex->key_create_info= default_key_create_info;
+ }
+ ;
+
+/*
+ For now, key_alg initializies lex->key_create_info.
+ In the future, when all key options are after key definition,
+ we can remove key_alg and move init_key_options to key_options
+*/
+
key_alg:
- /* empty */ { $$= HA_KEY_ALG_UNDEF; }
- | USING opt_btree_or_rtree { $$= $2; }
- | TYPE_SYM opt_btree_or_rtree { $$= $2; };
+ /* empty */ init_key_options
+ | init_key_options key_using_alg
+ ;
+
+key_options:
+ /* empty */ {}
+ | key_opts
+ ;
+
+key_opts:
+ key_opt
+ | key_opts key_opt
+ ;
+
+key_using_alg:
+ USING btree_or_rtree { Lex->key_create_info.algorithm= $2; }
+ | TYPE_SYM btree_or_rtree { Lex->key_create_info.algorithm= $2; }
+ ;
+
+key_opt:
+ key_using_alg
+ | KEY_BLOCK_SIZE opt_equal ulong_num
+ { Lex->key_create_info.block_size= $3; }
+ | WITH PARSER_SYM IDENT_sys
+ {
+ if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
+ Lex->key_create_info.parser_name= $3;
+ else
+ {
+ my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
+ YYABORT;
+ }
+ }
+ ;
+
-opt_btree_or_rtree:
+btree_or_rtree:
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
| RTREE_SYM
{
@@ -4693,7 +4580,7 @@ key_list:
key_part:
ident { $$=new key_part_spec($1.str); }
- | ident '(' NUM ')'
+ | ident '(' NUM ')'
{
int key_part_len= atoi($3.str);
if (!key_part_len)
@@ -4801,7 +4688,7 @@ alter:
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);
+ lex->select_lex.add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING);
}
view_list_opt AS view_select view_check_option
{}
@@ -7059,11 +6946,14 @@ table_factor:
}
expr '}'
{
+ LEX *lex= Lex;
YYERROR_UNLESS($3 && $7);
add_join_on($7,$10);
Lex->pop_context();
$7->outer_join|=JOIN_TYPE_LEFT;
$$=$7;
+ if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ YYABORT;
}
| select_derived_init get_select_lex select_derived2
{
@@ -7422,14 +7312,32 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->olap !=
- UNSPECIFIED_OLAP_TYPE)
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel-> master_unit();
+ if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE)
{
my_error(ER_WRONG_USAGE, MYF(0),
"CUBE/ROLLUP", "ORDER BY");
YYABORT;
}
+ if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
+ {
+ /*
+ A query of the of the form (SELECT ...) ORDER BY order_list is
+ executed in the same way as the query
+ SELECT ... ORDER BY order_list
+ unless the SELECT construct contains ORDER BY or LIMIT clauses.
+ Otherwise we create a fake SELECT_LEX if it has not been created
+ yet.
+ */
+ SELECT_LEX *first_sl= unit->first_select();
+ if (!first_sl->next_select() &&
+ (first_sl->order_list.elements ||
+ first_sl->select_limit) &&
+ unit->add_fake_select_lex(lex->thd))
+ YYABORT;
+ }
} order_list;
order_list:
@@ -7590,22 +7498,24 @@ select_var_ident:
if (lex->result)
((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0));
else
- YYABORT;
+ /*
+ The parser won't create select_result instance only
+ if it's an EXPLAIN.
+ */
+ DBUG_ASSERT(lex->describe);
}
| ident_or_text
{
LEX *lex=Lex;
- sp_pvar_t *t;
+ sp_variable_t *t;
- if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
+ if (!lex->spcont || !(t=lex->spcont->find_variable(&$1)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
YYABORT;
}
- if (! lex->result)
- YYABORT;
- else
- {
+ if (lex->result)
+ {
my_var *var;
((select_dumpvar *)lex->result)->
var_list.push_back(var= new my_var($1,1,t->offset,t->type));
@@ -7613,6 +7523,14 @@ select_var_ident:
if (var)
var->sp= lex->sphead;
#endif
+ }
+ else
+ {
+ /*
+ The parser won't create select_result instance only
+ if it's an EXPLAIN.
+ */
+ DBUG_ASSERT(lex->describe);
}
}
;
@@ -8151,15 +8069,24 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
YYABORT;
}
- | opt_full EVENTS_SYM opt_db wild_and_where
+ | EVENTS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
- lex->select_lex.db= $3;
+ lex->select_lex.db= $2;
if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
YYABORT;
}
+ | SCHEDULER_SYM STATUS_SYM
+ {
+#ifndef DBUG_OFF
+ Lex->sql_command= SQLCOM_SHOW_SCHEDULER_STATUS;
+#else
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+#endif
+ }
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
@@ -8178,7 +8105,7 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
YYABORT;
}
- | PLUGIN_SYM
+ | opt_full PLUGIN_SYM
{
LEX *lex= Lex;
WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'");
@@ -8268,6 +8195,11 @@ show_param:
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_AUTHORS;
}
+ | CONTRIBUTORS_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS;
+ }
| PRIVILEGES
{
LEX *lex=Lex;
@@ -9034,10 +8966,10 @@ order_ident:
simple_ident:
ident
{
- sp_pvar_t *spv;
+ sp_variable_t *spv;
LEX *lex = Lex;
sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_pvar(&$1)))
+ if (spc && (spv = spc->find_variable(&$1)))
{
/* We're compiling a stored procedure and found a variable */
Item_splocal *splocal;
@@ -9108,12 +9040,18 @@ simple_ident_q:
YYABORT;
}
+ DBUG_ASSERT(!new_row ||
+ (lex->trg_chistics.event == TRG_EVENT_INSERT ||
+ lex->trg_chistics.event == TRG_EVENT_UPDATE));
+ const bool read_only=
+ !(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE);
if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
new_row ?
Item_trigger_field::NEW_ROW:
Item_trigger_field::OLD_ROW,
$3.str,
- Item_trigger_field::AT_READ)))
+ SELECT_ACL,
+ read_only)))
YYABORT;
/*
@@ -9488,7 +9426,7 @@ keyword_sp:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
- | RELAY_THREAD {}
+ | KEY_BLOCK_SIZE {}
| LAST_SYM {}
| LEAVES {}
| LESS_SYM {}
@@ -9575,6 +9513,7 @@ keyword_sp:
| REDUNDANT_SYM {}
| RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {}
+ | RELAY_THREAD {}
| RELOAD {}
| REORGANIZE_SYM {}
| REPEATABLE_SYM {}
@@ -9589,6 +9528,7 @@ keyword_sp:
| ROW_SYM {}
| RTREE_SYM {}
| SCHEDULE_SYM {}
+ | SCHEDULER_SYM {}
| SECOND_SYM {}
| SERIAL_SYM {}
| SERIALIZABLE_SYM {}
@@ -9793,11 +9733,13 @@ sys_option_value:
it= new Item_null();
}
+ DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
+ (lex->trg_chistics.event == TRG_EVENT_INSERT ||
+ lex->trg_chistics.event == TRG_EVENT_UPDATE));
if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
Item_trigger_field::NEW_ROW,
$2.base_name.str,
- Item_trigger_field::AT_UPDATE)
- ) ||
+ UPDATE_ACL, FALSE)) ||
!(sp_fld= new sp_instr_set_trigger_field(lex->sphead->
instructions(),
lex->spcont,
@@ -9825,7 +9767,7 @@ sys_option_value:
{
/* An SP local variable */
sp_pcontext *ctx= lex->spcont;
- sp_pvar_t *spv;
+ sp_variable_t *spv;
sp_instr_set *sp_set;
Item *it;
if ($1)
@@ -9834,7 +9776,7 @@ sys_option_value:
YYABORT;
}
- spv= ctx->find_pvar(&$2.base_name);
+ spv= ctx->find_variable(&$2.base_name);
if ($4)
it= $4;
@@ -9883,7 +9825,7 @@ option_value:
names.str= (char *)"names";
names.length= 5;
- if (spc && spc->find_pvar(&names))
+ if (spc && spc->find_variable(&names))
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
else
yyerror(ER(ER_SYNTAX_ERROR));
@@ -9913,7 +9855,7 @@ option_value:
pw.str= (char *)"password";
pw.length= 8;
- if (spc && spc->find_pvar(&pw))
+ if (spc && spc->find_variable(&pw))
{
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
YYABORT;
@@ -9935,10 +9877,10 @@ internal_variable_name:
{
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- sp_pvar_t *spv;
+ sp_variable_t *spv;
/* We have to lookup here since local vars can shadow sysvars */
- if (!spc || !(spv = spc->find_pvar(&$1)))
+ if (!spc || !(spv = spc->find_variable(&$1)))
{
/* Not an SP local variable */
sys_var *tmp=find_sys_var($1.str, $1.length);
@@ -10904,7 +10846,7 @@ view_tail:
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, $3, NULL, 0))
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING))
YYABORT;
}
view_list_opt AS view_select view_check_option
@@ -11105,8 +11047,6 @@ sp_tail:
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;
/*
diff --git a/sql/structs.h b/sql/structs.h
index e369d8ed7e8..78f00f72df1 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,22 +20,6 @@
struct st_table;
class Field;
-typedef struct st_lex_string
-{
- char *str;
- uint length;
-} LEX_STRING;
-
-typedef struct st_lex_string_with_init :public st_lex_string
-{
- st_lex_string_with_init(const char *str_arg, uint length_arg)
- {
- str= (char*) str_arg;
- length= length_arg;
- }
-} LEX_STRING_WITH_INIT;
-
-
typedef struct st_date_time_format {
uchar positions[8];
char time_separator; /* Separator between hour and minute */
@@ -86,6 +70,7 @@ typedef struct st_key {
uint key_parts; /* How many key_parts */
uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */
+ uint block_size;
enum ha_key_alg algorithm;
/*
Note that parser is used when the table is opened for use, and
diff --git a/sql/table.cc b/sql/table.cc
index 41621a19900..d0caba7fe9e 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -535,6 +535,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->key_length= (uint) uint2korr(strpos+2);
keyinfo->key_parts= (uint) strpos[4];
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
+ keyinfo->block_size= uint2korr(strpos+6);
strpos+=8;
}
else
@@ -655,7 +656,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
my_free(buff, MYF(0));
goto err;
}
- next_chunk++;
}
#else
if (partition_info_len)
@@ -667,38 +667,27 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
#endif
next_chunk+= 5 + partition_info_len;
}
- if (share->mysql_version > 50105 && next_chunk + 5 < buff_end)
+#if MYSQL_VERSION_ID < 50200
+ if (share->mysql_version >= 50106 && share->mysql_version <= 50109)
{
/*
- Partition state was introduced to support partition management in version 5.1.5
+ Partition state array was here in version 5.1.6 to 5.1.9, this code
+ makes it possible to load a 5.1.6 table in later versions. Can most
+ likely be removed at some point in time. Will only be used for
+ upgrades within 5.1 series of versions. Upgrade to 5.2 can only be
+ done from newer 5.1 versions.
*/
- uint32 part_state_len= uint4korr(next_chunk);
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- if ((share->part_state_len= part_state_len))
- if (!(share->part_state=
- (uchar*) memdup_root(&share->mem_root, next_chunk + 4,
- part_state_len)))
- {
- my_free(buff, MYF(0));
- goto err;
- }
-#else
- if (part_state_len)
- {
- DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
- }
-#endif
- next_chunk+= 4 + part_state_len;
+ next_chunk+= 4;
}
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- else
+ else if (share->mysql_version >= 50110)
+#endif
{
- share->part_state_len= 0;
- share->part_state= NULL;
- }
+ /* New auto_partitioned indicator introduced in 5.1.11 */
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ share->auto_partitioned= *next_chunk;
#endif
+ next_chunk++;
+ }
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
{
@@ -725,6 +714,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
}
my_free(buff, MYF(0));
}
+ share->key_block_size= uint2korr(head+62);
error=4;
extra_rec_buf_length= uint2korr(head+59);
@@ -1488,6 +1478,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
Fix the partition functions and ensure they are not constant
functions
*/
+ outparam->part_info->is_auto_partitioned= share->auto_partitioned;
+ DBUG_PRINT("info", ("autopartitioned = %u", share->auto_partitioned));
if (fix_partition_func(thd, share->normalized_path.str, outparam,
is_create_table))
goto err;
@@ -2084,6 +2076,11 @@ File create_frm(THD *thd, const char *name, const char *db,
tmp= MYSQL_VERSION_ID; // Store to avoid warning from int4store
int4store(fileinfo+51, tmp);
int4store(fileinfo+55, create_info->extra_size);
+ /*
+ 59-60 is reserved for extra_rec_buf_length,
+ 61 for default_part_db_type
+ */
+ int2store(fileinfo+62, create_info->key_block_size);
bzero(fill,IO_SIZE);
for (; length > IO_SIZE ; length-= IO_SIZE)
{
@@ -2404,9 +2401,7 @@ table_check_intact(TABLE *table, uint table_f_count,
table running on a old server will be valid.
*/
field->sql_type(sql_type);
- if (sql_type.length() < table_def->type.length - 1 ||
- strncmp(sql_type.ptr(),
- table_def->type.str,
+ if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
table_def->type.length - 1))
{
sql_print_error("(%s) Expected field %s at position %d to have type "
diff --git a/sql/table.h b/sql/table.h
index aec9a7115e6..ffecc60b19c 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -160,6 +160,7 @@ typedef struct st_table_share
uint ref_count; /* How many TABLE objects uses this */
uint open_count; /* Number of tables in open list */
uint blob_ptr_size; /* 4 or 8 */
+ uint key_block_size; /* create key_block_size, if used */
uint null_bytes, last_null_bit_pos;
uint fields; /* Number of fields */
uint rec_buff_length; /* Size of table->record[] buffer */
@@ -213,6 +214,7 @@ typedef struct st_table_share
*/
bool log_table;
#ifdef WITH_PARTITION_STORAGE_ENGINE
+ bool auto_partitioned;
const uchar *partition_info;
uint partition_info_len;
const uchar *part_state;
@@ -262,6 +264,7 @@ struct st_table {
ha_rows quick_rows[MAX_KEY];
key_part_map const_key_parts[MAX_KEY];
uint quick_key_parts[MAX_KEY];
+ uint quick_n_ranges[MAX_KEY];
/*
If this table has TIMESTAMP field with auto-set property (pointed by
@@ -335,7 +338,8 @@ typedef struct st_foreign_key_info
LEX_STRING *forein_id;
LEX_STRING *referenced_db;
LEX_STRING *referenced_table;
- LEX_STRING *constraint_method;
+ LEX_STRING *update_method;
+ LEX_STRING *delete_method;
List<LEX_STRING> foreign_fields;
List<LEX_STRING> referenced_fields;
} FOREIGN_KEY_INFO;
@@ -359,6 +363,7 @@ enum enum_schema_tables
SCH_PARTITIONS,
SCH_PLUGINS,
SCH_PROCESSLIST,
+ SCH_REFERENTIAL_CONSTRAINTS,
SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 1be2321200b..228a8cd9b92 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1382,11 +1382,30 @@ static LS_INFO *tz_lsis= 0;
static bool time_zone_tables_exist= 1;
-typedef struct st_tz_names_entry: public Sql_alloc
+/*
+ Names of tables (with their lengths) that are needed
+ for dynamical loading of time zone descriptions.
+*/
+
+static const LEX_STRING tz_tables_names[MY_TZ_TABLES_COUNT]=
{
+ {(char *) STRING_WITH_LEN("time_zone_name")},
+ {(char *) STRING_WITH_LEN("time_zone")},
+ {(char *) STRING_WITH_LEN("time_zone_transition_type")},
+ {(char *) STRING_WITH_LEN("time_zone_transition")}
+};
+
+/* Name of database to which those tables belong. */
+
+static const LEX_STRING tz_tables_db_name= {(char *) STRING_WITH_LEN("mysql")};
+
+
+class Tz_names_entry: public Sql_alloc
+{
+public:
String name;
Time_zone *tz;
-} TZ_NAMES_ENTRY;
+};
/*
@@ -1394,7 +1413,7 @@ typedef struct st_tz_names_entry: public Sql_alloc
they should obey C calling conventions.
*/
-extern "C" byte* my_tz_names_get_key(TZ_NAMES_ENTRY *entry, uint *length,
+extern "C" byte* my_tz_names_get_key(Tz_names_entry *entry, uint *length,
my_bool not_used __attribute__((unused)))
{
*length= entry->name.length();
@@ -1415,7 +1434,8 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
SYNOPSIS
tz_init_table_list()
- tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects
+ tz_tabs - pointer to preallocated array of MY_TZ_TABLES_COUNT
+ 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).
@@ -1430,27 +1450,27 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
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].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";
+ bzero(tz_tabs, sizeof(TABLE_LIST) * MY_TZ_TABLES_COUNT);
+
+ for (int i= 0; i < MY_TZ_TABLES_COUNT; i++)
+ {
+ tz_tabs[i].alias= tz_tabs[i].table_name= tz_tables_names[i].str;
+ tz_tabs[i].table_name_length= tz_tables_names[i].length;
+ tz_tabs[i].db= tz_tables_db_name.str;
+ tz_tabs[i].db_length= tz_tables_db_name.length;
+ tz_tabs[i].lock_type= TL_READ;
+
+ if (i != MY_TZ_TABLES_COUNT - 1)
+ tz_tabs[i].next_global= tz_tabs[i].next_local= &tz_tabs[i+1];
+ if (i != 0)
+ tz_tabs[i].prev_global= &tz_tabs[i-1].next_global;
+ }
/* 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;
+ *global_next_ptr= &tz_tabs[MY_TZ_TABLES_COUNT-1].next_global;
}
@@ -1479,7 +1499,8 @@ TABLE_LIST fake_time_zone_tables_list;
NOTE
my_tz_check_n_skip_implicit_tables() function depends on fact that
- elements of list created are allocated as TABLE_LIST[4] array.
+ elements of list created are allocated as TABLE_LIST[MY_TZ_TABLES_COUNT]
+ array.
RETURN VALUES
Returns pointer to first TABLE_LIST object, (could be 0 if time zone
@@ -1495,7 +1516,8 @@ my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr)
if (!time_zone_tables_exist)
DBUG_RETURN(0);
- if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * 4)))
+ if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) *
+ MY_TZ_TABLES_COUNT)))
DBUG_RETURN(&fake_time_zone_tables_list);
tz_init_table_list(tz_tabs, global_next_ptr);
@@ -1534,9 +1556,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
THD *thd;
TABLE_LIST *tables= 0;
- TABLE_LIST tables_buff[5], **last_global_next_ptr;
+ TABLE_LIST tables_buff[1+MY_TZ_TABLES_COUNT], **last_global_next_ptr;
TABLE *table;
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
my_bool return_val= 1;
int res;
DBUG_ENTER("my_tz_init");
@@ -1568,7 +1590,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_inited= 1;
/* Add 'SYSTEM' time zone to tz_names hash */
- if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()))
+ if (!(tmp_tzname= new (&tz_storage) Tz_names_entry()))
{
sql_print_error("Fatal error: OOM while initializing time zones");
goto end_with_cleanup;
@@ -1764,7 +1786,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
{
TABLE *table= 0;
TIME_ZONE_INFO *tz_info;
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
Time_zone *return_val= 0;
int res;
uint tzid, ttid;
@@ -2039,7 +2061,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
}
- if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()) ||
+ if (!(tmp_tzname= new (&tz_storage) Tz_names_entry()) ||
!(tmp_tzname->tz= new (&tz_storage) Time_zone_db(tz_info,
&(tmp_tzname->name))) ||
(tmp_tzname->name.set(tz_name_buff, tz_name->length(),
@@ -2186,7 +2208,7 @@ str_to_offset(const char *str, uint length, long *offset)
Time_zone *
my_tz_find(const String * name, TABLE_LIST *tz_tables)
{
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
Time_zone *result_tz= 0;
long offset;
DBUG_ENTER("my_tz_find");
@@ -2221,7 +2243,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
else
{
result_tz= 0;
- if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names,
+ if ((tmp_tzname= (Tz_names_entry *)hash_search(&tz_names,
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
@@ -2273,7 +2295,7 @@ Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
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 tables[MY_TZ_TABLES_COUNT];
TABLE_LIST *dummy;
TABLE_LIST **dummyp= &dummy;
tz_init_table_list(tables, &dummyp);
diff --git a/sql/tztime.h b/sql/tztime.h
index 42e50988e52..95184c9b3d1 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -70,6 +70,15 @@ extern my_time_t sec_since_epoch_TIME(TIME *t);
extern TABLE_LIST fake_time_zone_tables_list;
/*
+ Number of elements in table list produced by my_tz_get_table_list()
+ (this table list contains tables which are needed for dynamical loading
+ of time zone descriptions). Actually it is imlementation detail that
+ should not be used anywhere outside of tztime.h and tztime.cc.
+*/
+
+static const int MY_TZ_TABLES_COUNT= 4;
+
+/*
Check if we have pointer to the begining of list of implicitly used time
zone tables, set SELECT_ACL for them and fast-forward to its end.
@@ -91,9 +100,9 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table,
{
if (*table == tz_tables)
{
- for (int i= 0; i < 4; i++)
+ for (int i= 0; i < MY_TZ_TABLES_COUNT; i++)
(*table)[i].grant.privilege= SELECT_ACL;
- (*table)+= 3;
+ (*table)+= MY_TZ_TABLES_COUNT - 1;
return TRUE;
}
return FALSE;
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index f4f936f34ef..6ad066eacc2 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -344,7 +344,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
KSflag = 0; /* state flag for KS translation */
for (metaph_end = result + MAXMETAPH, n_start = n;
- n <= n_end && result < metaph_end; n++ )
+ n < n_end && result < metaph_end; n++ )
{
if ( KSflag )
diff --git a/sql/unireg.cc b/sql/unireg.cc
index bb197181e2a..11aa73bb502 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -130,13 +130,18 @@ bool mysql_create_frm(THD *thd, const char *file_name,
/* str_db_type */
create_info->extra_size= (2 + str_db_type.length +
2 + create_info->connect_string.length);
- /* Partition */
- create_info->extra_size+= 9;
+ /*
+ Partition:
+ Length of partition info = 4 byte
+ Potential NULL byte at end of partition info string = 1 byte
+ Indicator if auto-partitioned table = 1 byte
+ => Total 6 byte
+ */
+ create_info->extra_size+= 6;
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (part_info)
{
create_info->extra_size+= part_info->part_info_len;
- create_info->extra_size+= part_info->part_state_len;
}
#endif
@@ -204,23 +209,19 @@ bool mysql_create_frm(THD *thd, const char *file_name,
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (part_info)
{
+ char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0;
int4store(buff, part_info->part_info_len);
if (my_write(file, (const byte*)buff, 4, MYF_RW) ||
my_write(file, (const byte*)part_info->part_info_string,
- part_info->part_info_len + 1, MYF_RW))
- goto err;
- DBUG_PRINT("info", ("Part state len = %d", part_info->part_state_len));
- int4store(buff, part_info->part_state_len);
- if (my_write(file, (const byte*)buff, 4, MYF_RW) ||
- my_write(file, (const byte*)part_info->part_state,
- part_info->part_state_len, MYF_RW))
+ part_info->part_info_len + 1, MYF_RW) ||
+ my_write(file, (const byte*)&auto_partitioned, 1, MYF_RW))
goto err;
}
else
#endif
{
- bzero(buff, 9);
- if (my_write(file, (byte*) buff, 9, MYF_RW))
+ bzero(buff, 6);
+ if (my_write(file, (byte*) buff, 6, MYF_RW))
goto err;
}
for (i= 0; i < keys; i++)
@@ -330,7 +331,7 @@ int rea_create_table(THD *thd, const char *path,
// Make sure mysql_create_frm din't remove extension
DBUG_ASSERT(*fn_rext(frm_name));
- if (file->create_handler_files(path, create_info))
+ if (file->create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
goto err_handler;
if (!create_info->frm_only && ha_create_table(thd, path, db, table_name,
create_info,0))
@@ -345,9 +346,9 @@ err_handler:
/* Pack screens to a screen for save in a form-file */
-static uchar * pack_screens(List<create_field> &create_fields,
- uint *info_length, uint *screens,
- bool small_file)
+static uchar *pack_screens(List<create_field> &create_fields,
+ uint *info_length, uint *screens,
+ bool small_file)
{
reg1 uint i;
uint row,start_row,end_row,fields_on_screen;
@@ -438,7 +439,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
int2store(pos+2,key->key_length);
pos[4]= (uchar) key->key_parts;
pos[5]= (uchar) key->algorithm;
- pos[6]=pos[7]=0; // For the future
+ int2store(pos+6, key->block_size);
pos+=8;
key_parts+=key->key_parts;
DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx",
diff --git a/storage/archive/CMakeLists.txt b/storage/archive/CMakeLists.txt
new file mode 100644
index 00000000000..a631f194b1a
--- /dev/null
+++ b/storage/archive/CMakeLists.txt
@@ -0,0 +1,8 @@
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
+ ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(archive azio.c ha_archive.cc ha_archive.h)
+TARGET_LINK_LIBRARIES(archive zlib mysys dbug strings)
diff --git a/storage/archive/Makefile.am b/storage/archive/Makefile.am
index 415e0dc8f8f..3d933408b0b 100644
--- a/storage/archive/Makefile.am
+++ b/storage/archive/Makefile.am
@@ -14,20 +14,49 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
- @ZLIB_INCLUDES@
+#called from the top level Makefile
-LDADD = libarchive.a \
- $(top_builddir)/mysys/libmysys.a \
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir) @ZLIB_INCLUDES@
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_archive.h azlib.h
+noinst_PROGRAMS = archive_test
+
+EXTRA_LTLIBRARIES = ha_archive.la
+pkglib_LTLIBRARIES = @plugin_archive_shared_target@
+ha_archive_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_archive_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_archive_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_archive_la_SOURCES = ha_archive.cc azio.c
+
+
+EXTRA_LIBRARIES = libarchive.a
+noinst_LIBRARIES = @plugin_archive_static_target@
+libarchive_a_CXXFLAGS = $(AM_CFLAGS)
+libarchive_a_CFLAGS = $(AM_CFLAGS)
+libarchive_a_SOURCES = ha_archive.cc azio.c
+
+
+archive_test_SOURCES = archive_test.c azio.c
+archive_test_CFLAGS = $(AM_CFLAGS)
+archive_test_LDADD = $(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a \
@ZLIB_LIBS@
-pkglib_LIBRARIES = libarchive.a
-noinst_PROGRAMS = archive_test
archive_test_LDFLAGS = @NOINST_LDFLAGS@
-noinst_HEADERS = azlib.h
-libarchive_a_SOURCES = azio.c
-EXTRA_DIST = cmakelists.txt
+
+EXTRA_DIST = CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql/ha_archive.cc b/storage/archive/ha_archive.cc
index 942faaae517..f3f20f6b103 100644
--- a/sql/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -19,10 +19,13 @@
#endif
#include "mysql_priv.h"
+#include <myisam.h>
#include "ha_archive.h"
#include <my_dir.h>
+#include <mysql/plugin.h>
+
/*
First, if you want to understand storage engines you should look at
ha_example.cc and ha_example.h.
@@ -143,12 +146,15 @@ static handler *archive_create_handler(TABLE_SHARE *table);
#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
+static const char archive_hton_name[]= "ARCHIVE";
+static const char archive_hton_comment[]= "Archive storage engine";
+
/* dummy handlerton - only to have something to return from archive_db_init */
handlerton archive_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "ARCHIVE",
+ archive_hton_name,
SHOW_OPTION_YES,
- "Archive storage engine",
+ archive_hton_comment,
DB_TYPE_ARCHIVE_DB,
archive_db_init,
0, /* slot */
@@ -214,6 +220,8 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length,
bool archive_db_init()
{
DBUG_ENTER("archive_db_init");
+ if (archive_inited)
+ DBUG_RETURN(FALSE);
if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
goto error;
if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
@@ -227,7 +235,6 @@ bool archive_db_init()
DBUG_RETURN(FALSE);
}
error:
- have_archive_db= SHOW_OPTION_DISABLED; // If we couldn't use handler
DBUG_RETURN(TRUE);
}
@@ -235,14 +242,14 @@ error:
Release the archive handler.
SYNOPSIS
- archive_db_end()
+ archive_db_done()
void
RETURN
FALSE OK
*/
-int archive_db_end(ha_panic_function type)
+int archive_db_done()
{
if (archive_inited)
{
@@ -253,6 +260,12 @@ int archive_db_end(ha_panic_function type)
return 0;
}
+
+int archive_db_end(ha_panic_function type)
+{
+ return archive_db_done();
+}
+
ha_archive::ha_archive(TABLE_SHARE *table_arg)
:handler(&archive_hton, table_arg), delayed_insert(0), bulk_insert(0)
{
@@ -459,12 +472,11 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name,
share->table_name_length= length;
share->table_name= tmp_name;
share->crashed= FALSE;
+ share->archive_write_open= 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);
- DBUG_PRINT("info", ("archive opening (1) up write at %s",
- share->data_file_name));
strmov(share->table_name,table_name);
/*
We will use this lock for rows.
@@ -476,38 +488,20 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name,
share->data_file_name));
/*
- After we read, we set the file to dirty. When we close, we will do the
- opposite. If the meta file will not open we assume it is crashed and
- leave it up to the user to fix.
+ We read the meta file, but do not mark it dirty unless we actually do
+ a write.
*/
if (read_meta_file(share->meta_file, &share->rows_recorded,
&share->auto_increment_value,
&share->forced_flushes,
share->real_path))
share->crashed= TRUE;
- else
- (void)write_meta_file(share->meta_file, share->rows_recorded,
- share->auto_increment_value,
- share->forced_flushes,
- share->real_path,
- TRUE);
/*
Since we now possibly no real_path, we will use it instead if it exists.
*/
if (*share->real_path)
fn_format(share->data_file_name, share->real_path, "", ARZ,
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
- /*
- It is expensive to open and close the data files and since you can't have
- a gzip file that can be both read and written we keep a writer open
- that is shared amoung all open tables.
- */
- if (!(azopen(&(share->archive_write), share->data_file_name,
- O_WRONLY|O_APPEND|O_BINARY)))
- {
- DBUG_PRINT("info", ("Could not open archive write file"));
- share->crashed= TRUE;
- }
VOID(my_hash_insert(&archive_open_tables, (byte*) share));
thr_lock_init(&share->lock);
}
@@ -554,8 +548,9 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
share->forced_flushes,
share->real_path,
share->crashed ? TRUE :FALSE);
- if (azclose(&(share->archive_write)))
- rc= 1;
+ if (share->archive_write_open)
+ if (azclose(&(share->archive_write)))
+ rc= 1;
if (my_close(share->meta_file, MYF(0)))
rc= 1;
my_free((gptr) share, MYF(0));
@@ -565,6 +560,32 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
DBUG_RETURN(rc);
}
+int ha_archive::init_archive_writer()
+{
+ DBUG_ENTER("ha_archive::init_archive_writer");
+ (void)write_meta_file(share->meta_file, share->rows_recorded,
+ share->auto_increment_value,
+ share->forced_flushes,
+ share->real_path,
+ TRUE);
+
+ /*
+ It is expensive to open and close the data files and since you can't have
+ a gzip file that can be both read and written we keep a writer open
+ that is shared amoung all open tables.
+ */
+ if (!(azopen(&(share->archive_write), share->data_file_name,
+ O_WRONLY|O_APPEND|O_BINARY)))
+ {
+ DBUG_PRINT("info", ("Could not open archive write file"));
+ share->crashed= TRUE;
+ DBUG_RETURN(1);
+ }
+ share->archive_write_open= TRUE;
+
+ DBUG_RETURN(0);
+}
+
/*
We just implement one additional file extension.
@@ -830,7 +851,7 @@ int ha_archive::write_row(byte *buf)
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
+ ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
@@ -910,6 +931,9 @@ int ha_archive::write_row(byte *buf)
Notice that the global auto_increment has been increased.
In case of a failed row write, we will never try to reuse the value.
*/
+ if (!share->archive_write_open)
+ if (init_archive_writer())
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
share->rows_recorded++;
rc= real_write_row(buf, &(share->archive_write));
@@ -1147,8 +1171,7 @@ int ha_archive::rnd_next(byte *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
scan_rows--;
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_next_count);
current_position= aztell(&archive);
rc= get_row(&archive, buf);
@@ -1184,8 +1207,7 @@ void ha_archive::position(const byte *record)
int ha_archive::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_archive::rnd_pos");
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_next_count);
current_position= (my_off_t)my_get_ptr(pos, ref_length);
(void)azseek(&archive, current_position, SEEK_SET);
@@ -1217,10 +1239,14 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("ha_archive::optimize");
- int rc;
+ int rc= 0;
azio_stream writer;
char writer_filename[FN_REFLEN];
+ /* Open up the writer if we haven't yet */
+ if (!share->archive_write_open)
+ init_archive_writer();
+
/* Flush any waiting data */
azflush(&(share->archive_write), Z_SYNC_FLUSH);
share->forced_flushes++;
@@ -1316,7 +1342,20 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
azclose(&writer);
share->dirty= FALSE;
share->forced_flushes= 0;
+
+ // now we close both our writer and our reader for the rename
azclose(&(share->archive_write));
+ azclose(&archive);
+
+ // make the file we just wrote be our data file
+ rc = my_rename(writer_filename,share->data_file_name,MYF(0));
+
+ /*
+ now open the shared writer back up
+ we don't check rc here because we want to open the file back up even
+ if the optimize failed but we will return rc below so that we will
+ know it failed.
+ */
DBUG_PRINT("info", ("Reopening archive data file"));
if (!(azopen(&(share->archive_write), share->data_file_name,
O_WRONLY|O_APPEND|O_BINARY)))
@@ -1326,21 +1365,15 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
goto error;
}
- my_rename(writer_filename,share->data_file_name,MYF(0));
-
/*
Now we need to reopen our read descriptor since it has changed.
*/
- azclose(&archive);
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
{
rc= HA_ERR_CRASHED_ON_USAGE;
goto error;
}
-
- DBUG_RETURN(0);
-
error:
azclose(&writer);
@@ -1369,8 +1402,8 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !thd->in_lock_tables
- && !thd->tablespace_op)
+ lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
+ && !thd_tablespace_op(thd))
lock_type = TL_WRITE_ALLOW_WRITE;
/*
@@ -1381,7 +1414,7 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
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))
lock_type = TL_READ;
lock.type=lock_type;
@@ -1494,11 +1527,11 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
{
int rc= 0;
byte *buf;
- const char *old_proc_info=thd->proc_info;
+ const char *old_proc_info;
ha_rows count= share->rows_recorded;
DBUG_ENTER("ha_archive::check");
- thd->proc_info= "Checking table";
+ old_proc_info= thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
azflush(&(share->archive_write), Z_SYNC_FLUSH);
share->forced_flushes++;
@@ -1523,7 +1556,7 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
my_free((char*)buf, MYF(0));
- thd->proc_info= old_proc_info;
+ thd_proc_info(thd, old_proc_info);
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
{
@@ -1548,3 +1581,17 @@ bool ha_archive::check_and_repair(THD *thd)
DBUG_RETURN(repair(thd, &check_opt));
}
+
+
+mysql_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_hton,
+ archive_hton_name,
+ "Brian Aker, MySQL AB",
+ archive_hton_comment,
+ NULL, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_archive.h b/storage/archive/ha_archive.h
index c3f4e82d997..4663531b674 100644
--- a/sql/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -19,7 +19,7 @@
#endif
#include <zlib.h>
-#include "../storage/archive/azlib.h"
+#include "azlib.h"
/*
Please read ha_archive.cc first. If you are looking for more general
@@ -35,6 +35,7 @@ typedef struct st_archive_share {
THR_LOCK lock;
File meta_file; /* Meta file we use */
azio_stream archive_write; /* Archive file we are working with */
+ bool archive_write_open;
bool dirty; /* Flag for if a flush should occur */
bool crashed; /* Meta file is crashed */
ha_rows rows_recorded; /* Number of rows in tables */
@@ -112,6 +113,7 @@ public:
bool dirty);
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table, int *rc);
int free_share(ARCHIVE_SHARE *share);
+ int init_archive_writer();
bool auto_repair() const { return 1; } // For the moment we just do this
int read_data_header(azio_stream *file_to_read);
int write_data_header(azio_stream *file_to_write);
diff --git a/storage/archive/plug.in b/storage/archive/plug.in
new file mode 100644
index 00000000000..52131b12e6b
--- /dev/null
+++ b/storage/archive/plug.in
@@ -0,0 +1,4 @@
+MYSQL_STORAGE_ENGINE(archive,, [Archive Storage Engine],
+ [Archive Storage Engine], [max,max-no-ndb])
+MYSQL_PLUGIN_STATIC(archive, [libarchive.a])
+MYSQL_PLUGIN_DYNAMIC(archive, [ha_archive.la])
diff --git a/storage/bdb/cmakelists.txt b/storage/bdb/CMakeLists.txt
index c27665d902c..c27665d902c 100644
--- a/storage/bdb/cmakelists.txt
+++ b/storage/bdb/CMakeLists.txt
diff --git a/storage/bdb/Makefile.in b/storage/bdb/Makefile.in
index 4e2439025f3..6d7da66edf4 100644
--- a/storage/bdb/Makefile.in
+++ b/storage/bdb/Makefile.in
@@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@
# distdir and top_distdir are set by the calling Makefile
bdb_build = build_unix
-files = LICENSE Makefile Makefile.in README cmakelists.txt
+files = LICENSE Makefile Makefile.in README CMakeLists.txt
subdirs = btree build_win32 clib common cxx db dbinc \
dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \
db_dump185 db_hotbackup db_load db_printlog db_recover db_stat db_upgrade \
diff --git a/storage/blackhole/CMakeLists.txt b/storage/blackhole/CMakeLists.txt
new file mode 100644
index 00000000000..ea3a7eae38e
--- /dev/null
+++ b/storage/blackhole/CMakeLists.txt
@@ -0,0 +1,6 @@
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(blackhole ha_blackhole.cc ha_blackhole.h)
diff --git a/storage/blackhole/Makefile.am b/storage/blackhole/Makefile.am
new file mode 100644
index 00000000000..e3e28cd75b5
--- /dev/null
+++ b/storage/blackhole/Makefile.am
@@ -0,0 +1,52 @@
+# 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
+
+#called from the top level Makefile
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_blackhole.h
+
+EXTRA_LTLIBRARIES = ha_blackhole.la
+pkglib_LTLIBRARIES = @plugin_blackhole_shared_target@
+ha_blackhole_la_LDFLAGS=-module -rpath $(MYSQLLIBdir)
+ha_blackhole_la_CXXFLAGS=$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_blackhole_la_CFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_blackhole_la_SOURCES=ha_blackhole.cc
+
+
+EXTRA_LIBRARIES = libblackhole.a
+noinst_LIBRARIES = @plugin_blackhole_static_target@
+libblackhole_a_CXXFLAGS=$(AM_CFLAGS)
+libblackhole_a_CFLAGS = $(AM_CFLAGS)
+libblackhole_a_SOURCES= ha_blackhole.cc
+
+
+EXTRA_DIST = CMakeLists.txt
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/sql/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 2f5e8ee0abc..098e44f39ee 100644
--- a/sql/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -22,18 +22,24 @@
#include "mysql_priv.h"
#include "ha_blackhole.h"
+#include <mysql/plugin.h>
+
/* Static declarations for handlerton */
static handler *blackhole_create_handler(TABLE_SHARE *table);
+static const char blackhole_hton_name[]= "BLACKHOLE";
+static const char blackhole_hton_comment[]=
+ "/dev/null storage engine (anything you write to it disappears)";
+
/* Blackhole storage engine handlerton */
handlerton blackhole_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "BLACKHOLE",
+ blackhole_hton_name,
SHOW_OPTION_YES,
- "/dev/null storage engine (anything you write to it disappears)",
+ blackhole_hton_comment,
DB_TYPE_BLACKHOLE_DB,
NULL,
0, /* slot */
@@ -61,7 +67,7 @@ handlerton blackhole_hton= {
NULL, /* Alter table flags */
NULL, /* Alter Tablespace */
NULL, /* Fill FILES table */
- HTON_CAN_RECREATE,
+ HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE,
NULL, /* binlog_func */
NULL, /* binlog_log_query */
NULL /* release_temporary_latches */
@@ -250,3 +256,15 @@ int ha_blackhole::index_last(byte * buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
+mysql_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_hton,
+ blackhole_hton_name,
+ "MySQL AB",
+ blackhole_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index 15e12659aa0..15e12659aa0 100644
--- a/sql/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
diff --git a/storage/archive/cmakelists.txt b/storage/csv/CMakeLists.txt
index 4189781e73a..28748527cc3 100644
--- a/storage/archive/cmakelists.txt
+++ b/storage/csv/CMakeLists.txt
@@ -1,6 +1,6 @@
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib)
-ADD_LIBRARY(archive azio.c)
-TARGET_LINK_LIBRARIES(archive zlib mysys dbug strings)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(csv ha_tina.cc ha_tina.h)
diff --git a/storage/csv/Makefile.am b/storage/csv/Makefile.am
index 5573df720a3..adebebd7cd8 100644
--- a/storage/csv/Makefile.am
+++ b/storage/csv/Makefile.am
@@ -25,16 +25,22 @@ INCLUDES = -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir)
-
-pkglib_LIBRARIES = libcsv.a
-
LDADD =
DEFS = @DEFS@
+noinst_HEADERS = ha_tina.h
+
+EXTRA_LTLIBRARIES = ha_csv.la
+pkglib_LTLIBRARIES = @plugin_csv_shared_target@
+ha_csv_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_csv_la_CXXFLAGS = $(AM_CFLAGS) -DMYSQL_PLUGIN
+ha_csv_la_SOURCES = ha_tina.cc
+EXTRA_LIBRARIES = libcsv.a
+noinst_LIBRARIES = @plugin_csv_static_target@
libcsv_a_CXXFLAGS = $(AM_CFLAGS)
-noinst_HEADERS = ha_tina.h
libcsv_a_SOURCES = ha_tina.cc
+EXTRA_DIST = CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/csv/cmakelists.txt b/storage/csv/cmakelists.txt
deleted file mode 100644
index 4e142646b2d..00000000000
--- a/storage/csv/cmakelists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
-ADD_LIBRARY(csv ha_tina.cc ha_tina.h)
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index aed861279d9..f15ce7cccb5 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -77,11 +77,14 @@ static int tina_init= 0;
static handler *tina_create_handler(TABLE_SHARE *table);
static int tina_init_func();
+static const char tina_hton_name[]= "CSV";
+static const char tina_hton_comment[]= "CSV storage engine";
+
handlerton tina_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "CSV",
+ tina_hton_name,
SHOW_OPTION_YES,
- "CSV storage engine",
+ tina_hton_comment,
DB_TYPE_CSV_DB,
(bool (*)()) tina_init_func,
0, /* slot */
@@ -143,6 +146,11 @@ static byte* tina_get_key(TINA_SHARE *share,uint *length,
int get_mmap(TINA_SHARE *share, int write)
{
DBUG_ENTER("ha_tina::get_mmap");
+#ifdef __NETWARE__
+ my_message(errno, "Sorry, no mmap() on Netware", 0);
+ DBUG_ASSERT(0);
+ DBUG_RETURN(1);
+#else
if (share->mapped_file && my_munmap(share->mapped_file,
share->file_stat.st_size))
DBUG_RETURN(1);
@@ -177,6 +185,7 @@ int get_mmap(TINA_SHARE *share, int write)
share->mapped_file= NULL;
DBUG_RETURN(0);
+#endif /* __NETWARE__ */
}
@@ -463,14 +472,28 @@ int tina_end(ha_panic_function type)
/*
Finds the end of a line.
- Currently only supports files written on a UNIX OS.
+ Supports DOS, Unix, or Mac OS line endings.
*/
-byte * find_eoln(byte *data, off_t begin, off_t end)
+byte * find_eoln(byte *data, off_t begin, off_t end, int *eoln_len)
{
+ off_t dataend= begin;
+ *eoln_len= 0;
+
for (off_t x= begin; x < end; x++)
- if (data[x] == '\n')
- return data + x;
+ if (data[x] == '\r' || data[x] == '\n')
+ (*eoln_len)++;
+ else if (!(*eoln_len))
+ dataend++;
+ else
+ return data+dataend;
+ /*
+ if we only have one record in the file then our for loop will break
+ before we return. we should still have seen end of line markers and
+ so we just return the line here
+ */
+ if (*eoln_len > 0)
+ return data+dataend;
return 0;
}
@@ -618,6 +641,7 @@ int ha_tina::find_current_row(byte *buf)
{
byte *mapped_ptr;
byte *end_ptr;
+ int eoln_len;
DBUG_ENTER("ha_tina::find_current_row");
mapped_ptr= (byte *)share->mapped_file + current_position;
@@ -627,7 +651,7 @@ int ha_tina::find_current_row(byte *buf)
not to conflict with undergoing concurrent insert.
*/
if ((end_ptr= find_eoln(share->mapped_file, current_position,
- local_saved_data_file_length)) == 0)
+ local_saved_data_file_length, &eoln_len)) == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE);
for (Field **field=table->field ; *field ; field++)
@@ -675,7 +699,7 @@ int ha_tina::find_current_row(byte *buf)
}
(*field)->store(buffer.ptr(), buffer.length(), system_charset_info);
}
- next_position= (end_ptr - share->mapped_file)+1;
+ next_position= (end_ptr - share->mapped_file)+eoln_len;
/* Maybe use \N for null? */
memset(buf, 0, table->s->null_bytes); /* We do not implement nulls! */
@@ -1398,17 +1422,17 @@ bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_YES;
}
-#ifdef MYSQL_PLUGIN
-mysql_declare_plugin
+
+mysql_declare_plugin(csv)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&tina_hton,
- tina_hton.name,
+ tina_hton_name,
"Brian Aker, MySQL AB",
- "CSV Storage Engine",
+ tina_hton_comment,
tina_init_func, /* Plugin Init */
tina_done_func, /* Plugin Deinit */
0x0100 /* 1.0 */,
}
mysql_declare_plugin_end;
-#endif
+
diff --git a/storage/example/cmakelists.txt b/storage/example/CMakeLists.txt
index f4579aa0c66..f4579aa0c66 100644
--- a/storage/example/cmakelists.txt
+++ b/storage/example/CMakeLists.txt
diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am
index 518d82abe2d..db3e35e4315 100644
--- a/storage/example/Makefile.am
+++ b/storage/example/Makefile.am
@@ -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
@@ -20,20 +20,33 @@ MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_srcdir)/include \
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir)
WRAPLIBS=
-pkglib_LIBRARIES = libexample.a
-
-noinst_HEADERS = ha_example.h
-libexample_a_SOURCES = ha_example.cc
-EXTRA_DIST = cmakelists.txt
LDADD =
-DEFS = -DMYSQL_SERVER @DEFS@
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_example.h
+
+EXTRA_LTLIBRARIES = ha_example.la
+pkglib_LTLIBRARIES = @plugin_example_shared_target@
+ha_example_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_example_la_SOURCES = ha_example.cc
+
+
+EXTRA_LIBRARIES = libexample.a
+noinst_LIBRARIES = @plugin_example_static_target@
+libexample_a_CXXFLAGS = $(AM_CFLAGS)
+libexample_a_CFLAGS = $(AM_CFLAGS)
+libexample_a_SOURCES= ha_example.cc
+
+EXTRA_DIST = CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index caa64c10bbd..2ce543dfbb0 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -77,11 +77,14 @@ static int example_init_func();
static bool example_init_func_for_handlerton();
static int example_panic(enum ha_panic_function flag);
+static const char example_hton_name[]= "EXAMPLE";
+static const char example_hton_comment[]= "Example storage engine";
+
handlerton example_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "EXAMPLE",
+ example_hton_name,
SHOW_OPTION_YES,
- "Example storage engine",
+ example_hton_comment,
DB_TYPE_EXAMPLE_DB,
example_init_func_for_handlerton,
0, /* slot */
@@ -742,17 +745,17 @@ int ha_example::create(const char *name, TABLE *table_arg,
DBUG_RETURN(0);
}
-#ifdef MYSQL_PLUGIN
-mysql_declare_plugin
+
+mysql_declare_plugin(example)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&example_hton,
- example_hton.name,
+ example_hton_name,
"Brian Aker, MySQL AB",
- "Example Storage Engine",
+ example_hton_comment,
example_init_func, /* Plugin Init */
example_done_func, /* Plugin Deinit */
0x0001 /* 0.1 */,
}
mysql_declare_plugin_end;
-#endif
+
diff --git a/storage/example/plug.in b/storage/example/plug.in
new file mode 100644
index 00000000000..bf5bb49b429
--- /dev/null
+++ b/storage/example/plug.in
@@ -0,0 +1,4 @@
+MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine],
+ [Skeleton for Storage Engines for developers], [max,max-no-ndb])
+MYSQL_PLUGIN_STATIC(example, [libexample.a])
+MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la])
diff --git a/storage/heap/cmakelists.txt b/storage/heap/CMakeLists.txt
index db5fb8b2981..db5fb8b2981 100644
--- a/storage/heap/cmakelists.txt
+++ b/storage/heap/CMakeLists.txt
diff --git a/storage/heap/Makefile.am b/storage/heap/Makefile.am
index fceaeec664a..68dce9bca5f 100644
--- a/storage/heap/Makefile.am
+++ b/storage/heap/Makefile.am
@@ -30,7 +30,7 @@ libheap_a_SOURCES = hp_open.c hp_extra.c hp_close.c hp_panic.c hp_info.c \
hp_rnext.c hp_rlast.c hp_rprev.c hp_clear.c \
hp_rkey.c hp_block.c \
hp_hash.c _check.c _rectest.c hp_static.c
-EXTRA_DIST = cmakelists.txt
+EXTRA_DIST = CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index 329f4b7fa2d..8e185a60262 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -85,6 +85,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (!my_binary_compare(keyinfo->seg[j].charset))
keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ length+= 2;
/* Save number of bytes used to store length */
keyinfo->seg[j].bit_start= 1;
break;
@@ -95,6 +96,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (!my_binary_compare(keyinfo->seg[j].charset))
keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ length+= 2;
/* Save number of bytes used to store length */
keyinfo->seg[j].bit_start= 2;
/*
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c
index 2d94418a1bf..f37db2588f3 100644
--- a/storage/heap/hp_delete.c
+++ b/storage/heap/hp_delete.c
@@ -79,7 +79,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
custom_arg.search_flag= SEARCH_SAME;
old_allocated= keyinfo->rb_tree.allocated;
- res= tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
+ res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length,
+ &custom_arg);
info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated);
return res;
}
diff --git a/storage/innobase/cmakelists.txt b/storage/innobase/CMakeLists.txt
index de46430e2ab..def51873725 100644
--- a/storage/innobase/cmakelists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -32,4 +32,4 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
thr/thr0loc.c
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c
- ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c)
+ ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c)
diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am
index 22796b45882..bf41d3dca88 100644
--- a/storage/innobase/Makefile.am
+++ b/storage/innobase/Makefile.am
@@ -76,8 +76,36 @@ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr
include/univ.i include/usr0sess.h include/usr0sess.ic include/usr0types.h \
include/ut0byte.h include/ut0byte.ic include/ut0dbg.h include/ut0lst.h \
include/ut0mem.h include/ut0mem.ic include/ut0rnd.h include/ut0rnd.ic \
- include/ut0sort.h include/ut0ut.h include/ut0ut.ic \
- cmakelists.txt
+ include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic \
+ CMakeLists.txt
+
+noinst_LIBRARIES = libinnobase.a
+libinnobase_a_LIBADD = usr/libusr.a srv/libsrv.a dict/libdict.a \
+ que/libque.a srv/libsrv.a ibuf/libibuf.a \
+ row/librow.a pars/libpars.a btr/libbtr.a \
+ trx/libtrx.a read/libread.a usr/libusr.a \
+ buf/libbuf.a ibuf/libibuf.a eval/libeval.a \
+ log/liblog.a fsp/libfsp.a fut/libfut.a \
+ fil/libfil.a lock/liblock.a mtr/libmtr.a \
+ page/libpage.a rem/librem.a thr/libthr.a \
+ sync/libsync.a data/libdata.a mach/libmach.a \
+ ha/libha.a dyn/libdyn.a mem/libmem.a \
+ ut/libut.a os/libos.a ut/libut.a
+libinnobase_a_SOURCES =
+
+
+libinnobase.a: $(libinnobase_a_LIBADD)
+ -rm -f $@
+ if test "$(host_os)" = "netware" ; \
+ then \
+ $(libinnobase_a_AR) $@ $(libinnobase_a_LIBADD) ; \
+ else \
+ for arc in $(libinnobase_a_LIBADD); do \
+ arpath=`echo $$arc|sed 's|[^/]*$$||'`; \
+ $(AR) t $$arc|sed "s|^|$$arpath|"; \
+ done | sort -u | xargs $(AR) cq $@ ; \
+ $(RANLIB) $@ ; \
+ fi
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index 4ece0e36b19..5e338f97982 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -144,7 +144,7 @@ btr_root_get(
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
ut_a((ibool)!!page_is_comp(root) ==
- dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table));
+ dict_table_is_comp(tree->tree_index->table));
return(root);
}
@@ -259,7 +259,7 @@ btr_page_create(
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
page_create(page, mtr,
- dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table));
+ dict_table_is_comp(tree->tree_index->table));
buf_block_align(page)->check_index_page_at_flush = TRUE;
btr_page_set_index_id(page, tree->id, mtr);
@@ -574,7 +574,7 @@ 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);
+ index = tree->tree_index;
/* In the following, we choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */
@@ -1073,8 +1073,7 @@ btr_root_raise_and_insert(
/* fprintf(stderr, "Root raise new page no %lu\n",
buf_frame_get_page_no(new_page)); */
- ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
- new_page);
+ ibuf_reset_free_bits(tree->tree_index, new_page);
/* Reposition the cursor to the child node */
page_cur_search(new_page, cursor->index, tuple,
PAGE_CUR_LE, page_cursor);
@@ -1415,7 +1414,7 @@ btr_insert_on_non_leaf_level(
/* In the following, 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(tree->tree_index,
level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE,
&cursor, 0, mtr);
@@ -1479,7 +1478,7 @@ btr_attach_half_pages(
btr_node_ptr_set_child_page_no(node_ptr,
rec_get_offsets(node_ptr,
- UT_LIST_GET_FIRST(tree->tree_indexes),
+ tree->tree_index,
NULL, ULINT_UNDEFINED, &heap),
lower_page_no, mtr);
mem_heap_empty(heap);
@@ -1768,8 +1767,8 @@ func_start:
buf_frame_get_page_no(left_page),
buf_frame_get_page_no(right_page)); */
- 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)));
+ ut_ad(page_validate(left_page, tree->tree_index));
+ ut_ad(page_validate(right_page, tree->tree_index));
mem_heap_free(heap);
return(rec);
@@ -1910,8 +1909,7 @@ btr_node_ptr_delete(
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
- &cursor);
+ btr_cur_position(tree->tree_index, node_ptr, &cursor);
compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
mtr);
ut_a(err == DB_SUCCESS);
@@ -1947,7 +1945,7 @@ btr_lift_page_up(
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);
+ index = tree->tree_index;
btr_search_drop_page_hash_index(page);
@@ -2180,8 +2178,7 @@ btr_discard_only_page_on_level(
btr_page_empty(father_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);
+ ibuf_reset_free_bits(tree->tree_index, father_page);
} else {
ut_ad(page_get_n_recs(father_page) == 1);
@@ -2449,7 +2446,7 @@ btr_check_node_ptr(
ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
rec_get_offsets(node_ptr,
- dict_tree_find_index(tree, node_ptr),
+ tree->tree_index,
NULL, ULINT_UNDEFINED, &heap)) == 0);
mem_heap_free(heap);
@@ -2692,7 +2689,7 @@ btr_validate_level(
space = buf_frame_get_space_id(page);
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ index = tree->tree_index;
while (level != btr_page_get_level(page, &mtr)) {
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 14e991bb3c6..deba3e23487 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -1606,7 +1606,7 @@ btr_cur_optimistic_update(
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);
+ FALSE, NULL);
old_rec_size = rec_offs_size(offsets);
new_rec_size = rec_get_converted_size(index, new_entry);
@@ -1846,7 +1846,7 @@ btr_cur_pessimistic_update(
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,
- heap);
+ FALSE, heap);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
@@ -1915,13 +1915,13 @@ 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, index,
ext_vect, n_ext_vect, mtr);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally
stored fields */
@@ -2371,8 +2371,7 @@ btr_cur_compress(
ut_ad(mtr_memo_contains(mtr,
dict_tree_get_lock(btr_cur_get_tree(cursor)),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, buf_block_align(
- btr_cur_get_page(cursor)),
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)),
MTR_MEMO_PAGE_X_FIX));
ut_ad(btr_page_get_level(btr_cur_get_page(cursor), mtr) == 0);
@@ -2398,8 +2397,7 @@ btr_cur_compress_if_useful(
ut_ad(mtr_memo_contains(mtr,
dict_tree_get_lock(btr_cur_get_tree(cursor)),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, buf_block_align(
- btr_cur_get_page(cursor)),
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)),
MTR_MEMO_PAGE_X_FIX));
if (btr_cur_compress_recommendation(cursor, mtr)) {
@@ -2437,7 +2435,7 @@ btr_cur_optimistic_delete(
ibool no_compress_needed;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
- ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_page(cursor)),
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)),
MTR_MEMO_PAGE_X_FIX));
/* This is intended only for leaf page deletions */
@@ -3330,7 +3328,10 @@ 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) */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index);
+ the "external storage" flags in offsets
+ will not correspond to rec when
+ this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index e3ba50a2d5b..85a6577bafb 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -259,10 +259,7 @@ btr_pcur_restore_position(
cursor->latch_mode = latch_mode;
#ifdef UNIV_DEBUG
rec = btr_pcur_get_rec(cursor);
- index = dict_tree_find_index(
- btr_cur_get_tree(
- btr_pcur_get_btr_cur(cursor)),
- rec);
+ index = btr_pcur_get_btr_cur(cursor)->index;
heap = mem_heap_create(256);
offsets1 = rec_get_offsets(cursor->old_rec,
diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
index 428b4d9a6b7..be7bb7c421f 100644
--- a/storage/innobase/btr/btr0sea.c
+++ b/storage/innobase/btr/btr0sea.c
@@ -24,8 +24,8 @@ ulint btr_search_this_is_zero = 0; /* A dummy variable to fool the
#ifdef UNIV_SEARCH_PERF_STAT
ulint btr_search_n_succ = 0;
-#endif /* UNIV_SEARCH_PERF_STAT */
ulint btr_search_n_hash_fail = 0;
+#endif /* UNIV_SEARCH_PERF_STAT */
byte btr_sea_pad1[64]; /* padding to prevent other memory update
hotspots from residing on the same memory
@@ -59,9 +59,6 @@ before hash index building is started */
#define BTR_SEARCH_BUILD_LIMIT 100
-/* How many cells to check before temporarily releasing btr_search_latch */
-#define BTR_CHUNK_SIZE 10000
-
/************************************************************************
Builds a hash index on a page with the given parameters. If the page already
has a hash index with different parameters, the old hash index is removed.
@@ -172,10 +169,12 @@ btr_search_info_create(
info->last_hash_succ = FALSE;
+#ifdef UNIV_SEARCH_PERF_STAT
info->n_hash_succ = 0;
info->n_hash_fail = 0;
info->n_patt_succ = 0;
info->n_searches = 0;
+#endif /* UNIV_SEARCH_PERF_STAT */
/* Set some sensible values */
info->n_fields = 1;
@@ -487,7 +486,9 @@ btr_search_info_update_slow(
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
+#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_hash_fail++;
+#endif /* UNIV_SEARCH_PERF_STAT */
rw_lock_x_lock(&btr_search_latch);
@@ -872,11 +873,11 @@ failure_unlock:
rw_lock_s_unlock(&btr_search_latch);
}
failure:
- info->n_hash_fail++;
-
cursor->flag = BTR_CUR_HASH_FAIL;
#ifdef UNIV_SEARCH_PERF_STAT
+ info->n_hash_fail++;
+
if (info->n_hash_succ > 0) {
info->n_hash_succ--;
}
@@ -1607,21 +1608,26 @@ btr_search_validate(void)
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+
+ /* How many cells to check before temporarily releasing
+ btr_search_latch. */
+ ulint chunk_size = 10000;
+
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
rw_lock_x_lock(&btr_search_latch);
cell_count = hash_get_n_cells(btr_search_sys->hash_index);
-
+
for (i = 0; i < cell_count; i++) {
/* We release btr_search_latch every once in a while to
give other queries a chance to run. */
- if ((i != 0) && ((i % BTR_CHUNK_SIZE) == 0)) {
+ if ((i != 0) && ((i % chunk_size) == 0)) {
rw_lock_x_unlock(&btr_search_latch);
os_thread_yield();
rw_lock_x_lock(&btr_search_latch);
}
-
+
node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
while (node != NULL) {
@@ -1675,9 +1681,9 @@ btr_search_validate(void)
}
}
- for (i = 0; i < cell_count; i += BTR_CHUNK_SIZE) {
- ulint end_index = ut_min(i + BTR_CHUNK_SIZE - 1, cell_count - 1);
-
+ for (i = 0; i < cell_count; i += chunk_size) {
+ ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1);
+
/* We release btr_search_latch every once in a while to
give other queries a chance to run. */
if (i != 0) {
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
index 3b6c47a21e9..08be5811a4b 100644
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
@@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void)
}
/**********************************************************************
-Returns TRUE if less than 15 % of the buffer pool is available. This can be
+Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */
ibool
buf_LRU_buf_pool_running_out(void)
/*==============================*/
- /* out: TRUE if less than 15 % of buffer pool
+ /* out: TRUE if less than 25 % of buffer pool
left */
{
ibool ret = FALSE;
@@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void)
mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) {
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
ret = TRUE;
}
@@ -340,11 +340,11 @@ loop:
mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) {
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
+" InnoDB: ERROR: over 95 percent of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\n"
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
@@ -356,17 +356,17 @@ loop:
ut_error;
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
if (!buf_lru_switched_on_innodb_mon) {
- /* Over 80 % of the buffer pool is occupied by lock
+ /* Over 67 % of the buffer pool is occupied by lock
heaps or the adaptive hash index. This may be a memory
leak! */
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
+" InnoDB: WARNING: over 67 percent of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\n"
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
@@ -881,10 +881,10 @@ buf_LRU_block_remove_hashed_page(
if (buf_page_hash_get(block->space, block->offset)) {
fprintf(stderr,
"InnoDB: From hash table we find block %p of %lu %lu which is not %p\n",
- buf_page_hash_get(block->space, block->offset),
+ (void*) buf_page_hash_get(block->space, block->offset),
(ulong) buf_page_hash_get(block->space, block->offset)->space,
(ulong) buf_page_hash_get(block->space, block->offset)->offset,
- block);
+ (void*) block);
}
#ifdef UNIV_DEBUG
diff --git a/storage/innobase/configure.in b/storage/innobase/configure.in
index e0521471c2f..91afcc1c9b3 100644
--- a/storage/innobase/configure.in
+++ b/storage/innobase/configure.in
@@ -89,6 +89,25 @@ else
CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS -DDEBUG_OFF"
fi
+# NOTE: The flags below are disabled by default since we can't easily get
+# rid of the "string over 509 characters in length" warnings, and thus can't
+# add -Werror. But it's a good idea to enable these for a test compile
+# before shipping a new snapshot to MySQL to catch errors that could make
+# the compile fail on non-C99 compilers.
+
+# If using gcc, disallow usage of C99 features to avoid accidentally
+# introducing problems on compilers that only implement C89.
+#if test "$ac_cv_prog_gcc" = "yes"
+#then
+# CFLAGS="$CFLAGS -std=c89 -ansi -pedantic -Wno-long-long"
+#fi
+
+# If using gcc, add some extra warning flags.
+if test "$ac_cv_prog_gcc" = "yes"
+then
+ CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+fi
+
case "$target_os" in
lin*)
CFLAGS="$CFLAGS -DUNIV_LINUX";;
diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c
index 3ac1139d952..2f36e7250fc 100644
--- a/storage/innobase/data/data0type.c
+++ b/storage/innobase/data/data0type.c
@@ -216,20 +216,43 @@ dtype_print(
mtype = type->mtype;
prtype = type->prtype;
- if (mtype == DATA_VARCHAR) {
+
+ switch (mtype) {
+ case DATA_VARCHAR:
fputs("DATA_VARCHAR", stderr);
- } else if (mtype == DATA_CHAR) {
+ break;
+
+ case DATA_CHAR:
fputs("DATA_CHAR", stderr);
- } else if (mtype == DATA_BINARY) {
+ break;
+
+ case DATA_BINARY:
fputs("DATA_BINARY", stderr);
- } else if (mtype == DATA_INT) {
+ break;
+
+ case DATA_FIXBINARY:
+ fputs("DATA_FIXBINARY", stderr);
+ break;
+
+ case DATA_BLOB:
+ fputs("DATA_BLOB", stderr);
+ break;
+
+ case DATA_INT:
fputs("DATA_INT", stderr);
- } else if (mtype == DATA_MYSQL) {
+ break;
+
+ case DATA_MYSQL:
fputs("DATA_MYSQL", stderr);
- } else if (mtype == DATA_SYS) {
+ break;
+
+ case DATA_SYS:
fputs("DATA_SYS", stderr);
- } else {
+ break;
+
+ default:
fprintf(stderr, "type %lu", (ulong) mtype);
+ break;
}
len = type->len;
@@ -254,6 +277,18 @@ dtype_print(
} else {
fprintf(stderr, "prtype %lu", (ulong) prtype);
}
+ } else {
+ if (prtype & DATA_UNSIGNED) {
+ fputs(" DATA_UNSIGNED", stderr);
+ }
+
+ if (prtype & DATA_BINARY_TYPE) {
+ fputs(" DATA_BINARY_TYPE", stderr);
+ }
+
+ if (prtype & DATA_NOT_NULL) {
+ fputs(" DATA_NOT_NULL", stderr);
+ }
}
fprintf(stderr, " len %lu prec %lu", (ulong) len, (ulong) type->prec);
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index 6f0a81296ac..4233cb05773 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -24,6 +24,7 @@ Created 1/8/1996 Heikki Tuuri
#include "pars0pars.h"
#include "trx0roll.h"
#include "usr0sess.h"
+#include "ut0vec.h"
/*********************************************************************
Based on a table object, this function builds the entry to be inserted
@@ -74,14 +75,14 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 3);
ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->type);
+ mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
dfield_set_data(dfield, ptr, 4);
/* 6: MIX_ID ---------------------------*/
dfield = dtuple_get_nth_field(entry, 4);
ptr = mem_heap_alloc(heap, 8);
- mach_write_to_8(ptr, table->mix_id);
+ memset(ptr, 0, 8);
dfield_set_data(dfield, ptr, 8);
/* 7: MIX_LEN --------------------------*/
@@ -89,19 +90,13 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 5);
ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->mix_len);
+ memset(ptr, 0, 4);
dfield_set_data(dfield, ptr, 4);
/* 8: CLUSTER_NAME ---------------------*/
dfield = dtuple_get_nth_field(entry, 6);
+ dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- dfield_set_data(dfield, table->cluster_name,
- ut_strlen(table->cluster_name));
- ut_error; /* Oracle-style clusters are not supported yet */
- } else {
- dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
- }
/* 9: SPACE ----------------------------*/
dfield = dtuple_get_nth_field(entry, 7);
@@ -207,7 +202,6 @@ dict_build_table_def_step(
tab_node_t* node) /* in: table create node */
{
dict_table_t* table;
- dict_table_t* cluster_table;
dtuple_t* row;
ulint error;
const char* path_or_name;
@@ -235,23 +229,6 @@ dict_build_table_def_step(
return(DB_TOO_BIG_RECORD);
}
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- cluster_table = dict_table_get_low(table->cluster_name);
-
- if (cluster_table == NULL) {
-
- return(DB_CLUSTER_NOT_FOUND);
- }
-
- /* Inherit space and mix len from the cluster */
-
- table->space = cluster_table->space;
- table->mix_len = cluster_table->mix_len;
-
- table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID);
- }
-
if (srv_file_per_table) {
/* We create a new single-table tablespace for the table.
We initially let it be 4 pages:
@@ -614,15 +591,6 @@ dict_create_index_tree_step(
sys_indexes = dict_sys->sys_indexes;
- if (index->type & DICT_CLUSTERED
- && table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- /* Do not create a new index tree: entries are put to the
- cluster tree */
-
- return(DB_SUCCESS);
- }
-
/* Run a mini-transaction in which the index tree is allocated for
the index and its root address is written to the index entry in
sys_indexes */
@@ -1159,11 +1127,8 @@ dict_create_or_check_foreign_constraint_tables(void)
{
dict_table_t* table1;
dict_table_t* table2;
- que_thr_t* thr;
- que_t* graph;
ulint error;
trx_t* trx;
- const char* str;
mutex_enter(&(dict_sys->mutex));
@@ -1215,7 +1180,7 @@ dict_create_or_check_foreign_constraint_tables(void)
VARBINARY, like in other InnoDB system tables, to get a clean
design. */
- str =
+ error = que_eval_sql(NULL,
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n"
"CREATE TABLE\n"
@@ -1227,22 +1192,8 @@ dict_create_or_check_foreign_constraint_tables(void)
"SYS_FOREIGN_COLS(ID CHAR, POS INT, FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
"CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);\n"
"COMMIT WORK;\n"
- "END;\n";
-
- graph = pars_sql(str);
-
- ut_a(graph);
-
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
-
- ut_a(thr = que_fork_start_command(graph));
-
- que_run_threads(thr);
-
- error = trx->error_state;
+ "END;\n"
+ , trx);
if (error != DB_SUCCESS) {
fprintf(stderr, "InnoDB: error %lu in creation\n",
@@ -1261,8 +1212,6 @@ dict_create_or_check_foreign_constraint_tables(void)
error = DB_MUST_GET_MORE_FILE_SPACE;
}
- que_graph_free(graph);
-
trx->op_info = "";
row_mysql_unlock_data_dictionary(trx);
@@ -1277,150 +1226,23 @@ dict_create_or_check_foreign_constraint_tables(void)
return(error);
}
-/************************************************************************
-Adds foreign key definitions to data dictionary tables in the database. We
-look at table->foreign_list, and also generate names to constraints that were
-not named by the user. A generated constraint has a name of the format
-databasename/tablename_ibfk_<number>, where the numbers start from 1, and are
-given locally for this table, that is, the number is not global, as in the
-old format constraints < 4.0.18 it used to be. */
+/********************************************************************
+Evaluate the given foreign key SQL statement. */
ulint
-dict_create_add_foreigns_to_dictionary(
-/*===================================*/
+dict_foreign_eval_sql(
+/*==================*/
/* out: error code or DB_SUCCESS */
- ulint start_id,/* in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
+ pars_info_t* info, /* in: info struct, or NULL */
+ const char* sql, /* in: SQL string to evaluate */
dict_table_t* table, /* in: table */
+ dict_foreign_t* foreign,/* in: foreign */
trx_t* trx) /* in: transaction */
{
- dict_foreign_t* foreign;
- que_thr_t* thr;
- que_t* graph;
- ulint number = start_id + 1;
- ulint len;
ulint error;
FILE* ef = dict_foreign_err_file;
- ulint i;
- char* sql;
- char* sqlend;
- /* This procedure builds an InnoDB stored procedure which will insert
- the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */
- static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_FOREIGN VALUES(";
- static const char str2[] = ");\n";
- static const char str3[] =
- "INSERT INTO SYS_FOREIGN_COLS VALUES(";
- static const char str4[] =
- "COMMIT WORK;\n"
- "END;\n";
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (NULL == dict_table_get_low("SYS_FOREIGN")) {
- fprintf(stderr,
-"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
-
- return(DB_ERROR);
- }
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-loop:
- if (foreign == NULL) {
-
- return(DB_SUCCESS);
- }
-
- if (foreign->id == NULL) {
- /* Generate a new constraint id */
- ulint namelen = strlen(table->name);
- char* id = mem_heap_alloc(foreign->heap, namelen + 20);
- /* no overflow if number < 1e13 */
- sprintf(id, "%s_ibfk_%lu", table->name, (ulong) number++);
- foreign->id = id;
- }
-
- len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3
- + 9/* ' and , chars */ + 10/* 32-bit integer */
- + ut_strlenq(foreign->id, '\'') * (foreign->n_fields + 1)
- + ut_strlenq(table->name, '\'')
- + ut_strlenq(foreign->referenced_table_name, '\'');
-
- for (i = 0; i < foreign->n_fields; i++) {
- len += 9/* ' and , chars */ + 10/* 32-bit integer */
- + (sizeof str3) + (sizeof str2) - 2
- + ut_strlenq(foreign->foreign_col_names[i], '\'')
- + ut_strlenq(foreign->referenced_col_names[i], '\'');
- }
-
- sql = sqlend = mem_alloc(len + 1);
-
- /* INSERT INTO SYS_FOREIGN VALUES(...); */
- memcpy(sqlend, str1, (sizeof str1) - 1);
- sqlend += (sizeof str1) - 1;
- *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
- *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', table->name);
- *sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_table_name);
- *sqlend++ = '\'', *sqlend++ = ',';
- sqlend += sprintf(sqlend, "%010lu",
- foreign->n_fields + (foreign->type << 24));
- memcpy(sqlend, str2, (sizeof str2) - 1);
- sqlend += (sizeof str2) - 1;
-
- for (i = 0; i < foreign->n_fields; i++) {
- /* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */
- memcpy(sqlend, str3, (sizeof str3) - 1);
- sqlend += (sizeof str3) - 1;
- *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
- *sqlend++ = '\''; *sqlend++ = ',';
- sqlend += sprintf(sqlend, "%010lu", (ulong) i);
- *sqlend++ = ','; *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'',
- foreign->foreign_col_names[i]);
- *sqlend++ = '\''; *sqlend++ = ','; *sqlend++ = '\'';
- sqlend = ut_strcpyq(sqlend, '\'',
- foreign->referenced_col_names[i]);
- *sqlend++ = '\'';
- memcpy(sqlend, str2, (sizeof str2) - 1);
- sqlend += (sizeof str2) - 1;
- }
-
- memcpy(sqlend, str4, sizeof str4);
- sqlend += sizeof str4;
-
- ut_a(sqlend == sql + len + 1);
-
- graph = pars_sql(sql);
-
- ut_a(graph);
-
- mem_free(sql);
-
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
-
- ut_a(thr = que_fork_start_command(graph));
-
- que_run_threads(thr);
-
- error = trx->error_state;
-
- que_graph_free(graph);
+ error = que_eval_sql(info, sql, trx);
if (error == DB_DUPLICATE_KEY) {
mutex_enter(&dict_foreign_err_mutex);
@@ -1466,7 +1288,163 @@ loop:
return(error);
}
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ return(DB_SUCCESS);
+}
+
+/************************************************************************
+Add a single foreign key field definition to the data dictionary tables in
+the database. */
+static
+ulint
+dict_create_add_foreign_field_to_dictionary(
+/*========================================*/
+ /* out: error code or DB_SUCCESS */
+ ulint field_nr, /* in: foreign field number */
+ dict_table_t* table, /* in: table */
+ dict_foreign_t* foreign, /* in: foreign */
+ trx_t* trx) /* in: transaction */
+{
+ pars_info_t* info = pars_info_create();
+
+ pars_info_add_str_literal(info, "id", foreign->id);
+
+ pars_info_add_int4_literal(info, "pos", field_nr);
+
+ pars_info_add_str_literal(info, "for_col_name",
+ foreign->foreign_col_names[field_nr]);
+
+ pars_info_add_str_literal(info, "ref_col_name",
+ foreign->referenced_col_names[field_nr]);
+
+ return dict_foreign_eval_sql(info,
+ "PROCEDURE P () IS\n"
+ "BEGIN\n"
+ "INSERT INTO SYS_FOREIGN_COLS VALUES"
+ "(:id, :pos, :for_col_name, :ref_col_name);\n"
+ "END;\n"
+ , table, foreign, trx);
+}
+
+/************************************************************************
+Add a single foreign key definition to the data dictionary tables in the
+database. We also generate names to constraints that were not named by the
+user. A generated constraint has a name of the format
+databasename/tablename_ibfk_<number>, where the numbers start from 1, and
+are given locally for this table, that is, the number is not global, as in
+the old format constraints < 4.0.18 it used to be. */
+static
+ulint
+dict_create_add_foreign_to_dictionary(
+/*==================================*/
+ /* out: error code or DB_SUCCESS */
+ ulint* id_nr, /* in/out: number to use in id generation;
+ incremented if used */
+ dict_table_t* table, /* in: table */
+ dict_foreign_t* foreign,/* in: foreign */
+ trx_t* trx) /* in: transaction */
+{
+ ulint error;
+ ulint i;
+
+ pars_info_t* info = pars_info_create();
+
+ if (foreign->id == NULL) {
+ /* Generate a new constraint id */
+ ulint namelen = strlen(table->name);
+ char* id = mem_heap_alloc(foreign->heap, namelen + 20);
+ /* no overflow if number < 1e13 */
+ sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
+ foreign->id = id;
+ }
+
+ pars_info_add_str_literal(info, "id", foreign->id);
+
+ pars_info_add_str_literal(info, "for_name", table->name);
+
+ pars_info_add_str_literal(info, "ref_name",
+ foreign->referenced_table_name);
+
+ pars_info_add_int4_literal(info, "n_cols",
+ foreign->n_fields + (foreign->type << 24));
+
+ error = dict_foreign_eval_sql(info,
+ "PROCEDURE P () IS\n"
+ "BEGIN\n"
+ "INSERT INTO SYS_FOREIGN VALUES"
+ "(:id, :for_name, :ref_name, :n_cols);\n"
+ "END;\n"
+ , table, foreign, trx);
+
+ if (error != DB_SUCCESS) {
+
+ return(error);
+ }
+
+ for (i = 0; i < foreign->n_fields; i++) {
+ error = dict_create_add_foreign_field_to_dictionary(i,
+ table, foreign, trx);
+
+ if (error != DB_SUCCESS) {
+
+ return(error);
+ }
+ }
+
+ error = dict_foreign_eval_sql(NULL,
+ "PROCEDURE P () IS\n"
+ "BEGIN\n"
+ "COMMIT WORK;\n"
+ "END;\n"
+ , table, foreign, trx);
- goto loop;
+ return(error);
+}
+
+/************************************************************************
+Adds foreign key definitions to data dictionary tables in the database. */
+
+ulint
+dict_create_add_foreigns_to_dictionary(
+/*===================================*/
+ /* out: error code or DB_SUCCESS */
+ ulint start_id,/* in: if we are actually doing ALTER TABLE
+ ADD CONSTRAINT, we want to generate constraint
+ numbers which are bigger than in the table so
+ far; we number the constraints from
+ start_id + 1 up; start_id should be set to 0 if
+ we are creating a new table, or if the table
+ so far has no constraints for which the name
+ was generated here */
+ dict_table_t* table, /* in: table */
+ trx_t* trx) /* in: transaction */
+{
+ dict_foreign_t* foreign;
+ ulint number = start_id + 1;
+ ulint error;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (NULL == dict_table_get_low("SYS_FOREIGN")) {
+ fprintf(stderr,
+"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
+
+ return(DB_ERROR);
+ }
+
+ for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ foreign;
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+
+ error = dict_create_add_foreign_to_dictionary(&number,
+ table, foreign, trx);
+
+ if (error != DB_SUCCESS) {
+
+ return(error);
+ }
+ }
+
+ return(DB_SUCCESS);
}
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 1fac5e26fa9..74dffd4c906 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -243,11 +243,10 @@ dict_remove_db_name(
const char* name) /* in: table name in the form
dbname '/' tablename */
{
- const char* s;
- s = strchr(name, '/');
+ const char* s = strchr(name, '/');
ut_a(s);
- if (s) s++;
- return(s);
+
+ return(s + 1);
}
/************************************************************************
@@ -658,6 +657,19 @@ dict_table_get_nth_col_pos(
}
/************************************************************************
+Check whether the table uses the compact page format. */
+
+ibool
+dict_table_is_comp_noninline(
+/*=========================*/
+ /* out: TRUE if table uses the
+ compact page format */
+ const dict_table_t* table) /* in: table */
+{
+ return(dict_table_is_comp(table));
+}
+
+/************************************************************************
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns. */
@@ -870,13 +882,6 @@ dict_table_add_to_cache(
ut_a(table2 == NULL);
}
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- table->mix_id_len = mach_dulint_get_compressed_size(
- table->mix_id);
- mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
- }
-
/* Add the columns to the column hash table */
for (i = 0; i < table->n_cols; i++) {
dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
@@ -1251,15 +1256,13 @@ dict_table_remove_from_cache(
/* Remove table from LRU list of tables */
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
- mutex_free(&(table->autoinc_mutex));
-
size = mem_heap_get_size(table->heap);
ut_ad(dict_sys->size >= size);
dict_sys->size -= size;
- mem_heap_free(table->heap);
+ dict_mem_table_free(table);
}
/**************************************************************************
@@ -1380,6 +1383,38 @@ dict_col_reposition_in_cache(
HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
}
+/********************************************************************
+If the given column name is reserved for InnoDB system columns, return
+TRUE. */
+
+ibool
+dict_col_name_is_reserved(
+/*======================*/
+ /* out: TRUE if name is reserved */
+ const char* name) /* in: column name */
+{
+ /* This check reminds that if a new system column is added to
+ the program, it should be dealt with here. */
+#if DATA_N_SYS_COLS != 4
+#error "DATA_N_SYS_COLS != 4"
+#endif
+
+ static const char* reserved_names[] = {
+ "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID"
+ };
+
+ ulint i;
+
+ for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
+ if (strcmp(name, reserved_names[i]) == 0) {
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
/**************************************************************************
Adds an index to the dictionary cache. */
@@ -1394,7 +1429,6 @@ dict_index_add_to_cache(
{
dict_index_t* new_index;
dict_tree_t* tree;
- dict_table_t* cluster;
dict_field_t* field;
ulint n_ord;
ibool success;
@@ -1468,21 +1502,11 @@ dict_index_add_to_cache(
dict_field_get_col(field)->ord_part++;
}
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- /* The index tree is found from the cluster object */
+ /* Create an index tree memory object for the index */
+ tree = dict_tree_create(new_index, page_no);
+ ut_ad(tree);
- cluster = dict_table_get_low(table->cluster_name);
-
- tree = dict_index_get_tree(
- UT_LIST_GET_FIRST(cluster->indexes));
- new_index->tree = tree;
- } else {
- /* Create an index tree memory object for the index */
- tree = dict_tree_create(new_index, page_no);
- ut_ad(tree);
-
- new_index->tree = tree;
- }
+ new_index->tree = tree;
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@@ -1500,7 +1524,7 @@ dict_index_add_to_cache(
}
/* Add the index to the list of indexes stored in the tree */
- UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index);
+ tree->tree_index = new_index;
/* If the dictionary cache grows too big, trim the table LRU list */
@@ -1532,7 +1556,7 @@ dict_index_remove_from_cache(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
+ ut_ad(index->tree->tree_index);
dict_tree_free(index->tree);
/* Decrement the ord_part counts in columns which are ordering */
@@ -1553,7 +1577,7 @@ dict_index_remove_from_cache(
dict_sys->size -= size;
- mem_heap_free(index->heap);
+ dict_mem_index_free(index);
}
/***********************************************************************
@@ -1699,8 +1723,6 @@ dict_table_copy_types(
dtype_t* type;
ulint i;
- ut_ad(!(table->type & DICT_UNIVERSAL));
-
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
@@ -1749,22 +1771,8 @@ dict_index_build_internal_clust(
new_index->id = index->id;
- if (table->type != DICT_TABLE_ORDINARY) {
- /* The index is mixed: copy common key prefix fields */
-
- dict_index_copy(new_index, index, 0, table->mix_len);
-
- /* Add the mix id column */
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_MIX_ID), 0);
-
- /* Copy the rest of fields */
- dict_index_copy(new_index, index, table->mix_len,
- index->n_fields);
- } else {
- /* Copy the fields of index */
- dict_index_copy(new_index, index, 0, index->n_fields);
- }
+ /* Copy the fields of index */
+ dict_index_copy(new_index, index, 0, index->n_fields);
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* No fixed number of fields determines an entry uniquely */
@@ -3641,7 +3649,7 @@ dict_tree_create(
tree->id = index->id;
- UT_LIST_INIT(tree->tree_indexes);
+ tree->tree_index = NULL;
tree->magic_n = DICT_TREE_MAGIC_N;
@@ -3667,135 +3675,7 @@ dict_tree_free(
mem_free(tree);
}
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-UNIV_INLINE
-dict_index_t*
-dict_tree_find_index_low(
-/*=====================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec) /* in: record for which to find correct
- index */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
- ulint len;
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if ((index->type & DICT_CLUSTERED)
- && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
-
- /* Get the mix id of the record */
- ut_a(!dict_table_is_comp(table));
-
- mix_id = mach_dulint_read_compressed(
- rec_get_nth_field_old(rec, table->mix_len, &len));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
- }
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-
-dict_index_t*
-dict_tree_find_index(
-/*=================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec) /* in: record for which to find correct
- index */
-{
- dict_index_t* index;
-
- index = dict_tree_find_index_low(tree, rec);
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a dtuple which is used
-in a search to a tree. */
-
-dict_index_t*
-dict_tree_find_index_for_tuple(
-/*===========================*/
- /* out: index; NULL if the tuple does not
- contain the mix id field in a mixed tree */
- dict_tree_t* tree, /* in: index tree */
- dtuple_t* tuple) /* in: tuple for which to find index */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
-
- ut_ad(dtuple_check_typed(tuple));
-
- if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
-
- return(UT_LIST_GET_FIRST(tree->tree_indexes));
- }
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if (dtuple_get_n_fields(tuple) <= table->mix_len) {
-
- return(NULL);
- }
-
- /* Get the mix id of the record */
-
- mix_id = mach_dulint_read_compressed(
- dfield_get_data(
- dtuple_get_nth_field(tuple, table->mix_len)));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
-
- 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(!dict_table_is_comp(table));
-
- 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));
-}
-
+#ifdef UNIV_DEBUG
/**************************************************************************
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. */
@@ -3807,19 +3687,14 @@ dict_tree_check_search_tuple(
dict_tree_t* tree, /* in: index tree */
dtuple_t* tuple) /* in: tuple used in a search */
{
- dict_index_t* index;
-
- index = dict_tree_find_index_for_tuple(tree, tuple);
-
- if (index == NULL) {
-
- return(TRUE);
- }
+ dict_index_t* index = tree->tree_index;
+ ut_a(index);
ut_a(dtuple_get_n_fields_cmp(tuple)
<= dict_index_get_n_unique_in_tree(index));
return(TRUE);
}
+#endif /* UNIV_DEBUG */
/**************************************************************************
Builds a node pointer out of a physical record and a page number. */
@@ -3842,7 +3717,7 @@ dict_tree_build_node_ptr(
byte* buf;
ulint n_unique;
- ind = dict_tree_find_index_low(tree, rec);
+ ind = tree->tree_index;
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
/* In a universal index tree, we take the whole record as
@@ -3910,7 +3785,7 @@ dict_tree_copy_rec_order_prefix(
ulint n;
UNIV_PREFETCH_R(rec);
- index = dict_tree_find_index_low(tree, rec);
+ index = tree->tree_index;
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
ut_a(!dict_table_is_comp(index->table));
@@ -3938,7 +3813,7 @@ dict_tree_build_data_tuple(
dtuple_t* tuple;
dict_index_t* ind;
- ind = dict_tree_find_index_low(tree, rec);
+ ind = tree->tree_index;
ut_ad(dict_table_is_comp(ind->table)
|| n_fields <= rec_get_n_fields_old(rec));
@@ -4097,6 +3972,18 @@ dict_update_statistics(
}
/**************************************************************************
+A noninlined version of dict_table_get_low. */
+
+dict_table_t*
+dict_table_get_low_noninlined(
+/*==========================*/
+ /* out: table, NULL if not found */
+ const char* table_name) /* in: table name */
+{
+ return(dict_table_get_low(table_name));
+}
+
+/**************************************************************************
Prints info of a foreign key constraint. */
static
void
@@ -4520,15 +4407,3 @@ dict_index_name_print(
fputs(" of table ", file);
ut_print_name(file, trx, index->table_name);
}
-
-/************************************************************************
-Export an inlined function for use in ha_innodb.c. */
-ibool
-innodb_dict_table_is_comp(
-/*===============*/
- /* out: TRUE if table uses the
- compact page format */
- const dict_table_t* table) /* in: table */
-{
- return dict_table_is_comp(table);
-}
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 09935c03288..ccf4b47c284 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -617,7 +617,7 @@ dict_load_indexes(
break;
}
- if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) {
+ if (rec_get_deleted_flag(rec, 0)) {
dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED);
@@ -768,7 +768,7 @@ dict_load_table(
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
|| rec_get_deleted_flag(rec, 0)) {
/* Not found */
-
+ err_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
mem_heap_free(heap);
@@ -780,11 +780,8 @@ dict_load_table(
/* Check if the table name in record is the searched one */
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- mem_heap_free(heap);
- return(NULL);
+ goto err_exit;
}
ut_a(0 == ut_strcmp("SPACE",
@@ -848,36 +845,17 @@ dict_load_table(
table->id = mach_read_from_8(field);
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_old(rec, 6, &len);
- table->mix_id = mach_read_from_8(field);
-
- 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_old(rec, 7, &len);
- ut_a(len == 4);
- table->mix_len = mach_read_from_4(field);
+ if (UNIV_UNLIKELY(mach_read_from_4(field) != DICT_TABLE_ORDINARY)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: table %s: unknown table type %lu\n",
+ name, (ulong) mach_read_from_4(field));
+ goto err_exit;
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- /* Load the cluster table definition if not yet in
- memory cache */
- dict_table_get_low(table->cluster_name);
- }
-
dict_load_columns(table, heap);
dict_table_add_to_cache(table);
diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c
index d9f0ad3d84e..fe21890adc8 100644
--- a/storage/innobase/dict/dict0mem.c
+++ b/storage/innobase/dict/dict0mem.c
@@ -50,7 +50,6 @@ dict_mem_table_create(
table->heap = heap;
- table->type = DICT_TABLE_ORDINARY;
table->flags = flags;
table->name = mem_heap_strdup(heap, name);
table->dir_path_of_temp_table = NULL;
@@ -66,9 +65,6 @@ dict_mem_table_create(
table->cached = FALSE;
- table->mix_id = ut_dulint_zero;
- table->mix_len = 0;
-
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
* sizeof(dict_col_t));
UT_LIST_INIT(table->indexes);
@@ -97,42 +93,19 @@ dict_mem_table_create(
return(table);
}
-/**************************************************************************
-Creates a cluster memory object. */
-
-dict_table_t*
-dict_mem_cluster_create(
-/*====================*/
- /* out, own: cluster object */
- const char* name, /* in: cluster name */
- ulint space, /* in: space where the clustered indexes
- of the member tables are placed */
- ulint n_cols, /* in: number of columns */
- ulint mix_len)/* in: length of the common key prefix in the
- cluster */
-{
- dict_table_t* cluster;
-
- /* Clustered tables cannot work with the compact record format. */
- cluster = dict_mem_table_create(name, space, n_cols, 0);
-
- cluster->type = DICT_TABLE_CLUSTER;
- cluster->mix_len = mix_len;
-
- return(cluster);
-}
-
-/**************************************************************************
-Declares a non-published table as a member in a cluster. */
+/********************************************************************
+Free a table memory object. */
void
-dict_mem_table_make_cluster_member(
-/*===============================*/
- dict_table_t* table, /* in: non-published table */
- const char* cluster_name) /* in: cluster name */
+dict_mem_table_free(
+/*================*/
+ dict_table_t* table) /* in: table */
{
- table->type = DICT_TABLE_CLUSTER_MEMBER;
- table->cluster_name = cluster_name;
+ ut_ad(table);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
}
/**************************************************************************
@@ -286,5 +259,8 @@ dict_mem_index_free(
/*================*/
dict_index_t* index) /* in: index */
{
+ ut_ad(index);
+ ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+
mem_heap_free(index->heap);
}
diff --git a/storage/innobase/eval/eval0proc.c b/storage/innobase/eval/eval0proc.c
index dcbdc0da5fc..96b8ef75955 100644
--- a/storage/innobase/eval/eval0proc.c
+++ b/storage/innobase/eval/eval0proc.c
@@ -213,6 +213,38 @@ for_step(
}
/**************************************************************************
+Performs an execution step of an exit statement node. */
+
+que_thr_t*
+exit_step(
+/*======*/
+ /* out: query thread to run next or NULL */
+ que_thr_t* thr) /* in: query thread */
+{
+ exit_node_t* node;
+ que_node_t* loop_node;
+
+ ut_ad(thr);
+
+ node = thr->run_node;
+
+ ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
+
+ /* Loops exit by setting thr->run_node as the loop node's parent, so
+ find our containing loop node and get its parent. */
+
+ loop_node = que_node_get_containing_loop_node(node);
+
+ /* If someone uses an EXIT statement outside of a loop, this will
+ trigger. */
+ ut_a(loop_node);
+
+ thr->run_node = que_node_get_parent(loop_node);
+
+ return(thr);
+}
+
+/**************************************************************************
Performs an execution step of a return-statement node. */
que_thr_t*
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 36cc97e5e0e..3263a0efd5b 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -1170,9 +1170,9 @@ 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);
+
+ dict_mem_index_free(index);
+ dict_mem_table_free(table);
}
/*************************************************************************
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index cb6cb1b1a4d..d5dd4f3010a 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -459,7 +459,10 @@ 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) */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index);
+ the "external storage" flags in offsets
+ will not correspond to rec when
+ this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to
diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic
index 5d2ae768416..a199c3d4d32 100644
--- a/storage/innobase/include/btr0cur.ic
+++ b/storage/innobase/include/btr0cur.ic
@@ -98,8 +98,7 @@ btr_cur_compress_recommendation(
{
page_t* page;
- ut_ad(mtr_memo_contains(mtr, buf_block_align(
- btr_cur_get_page(cursor)),
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)),
MTR_MEMO_PAGE_X_FIX));
page = btr_cur_get_page(cursor);
@@ -142,8 +141,7 @@ btr_cur_can_delete_without_compress(
{
page_t* page;
- ut_ad(mtr_memo_contains(mtr, buf_block_align(
- btr_cur_get_page(cursor)),
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)),
MTR_MEMO_PAGE_X_FIX));
page = btr_cur_get_page(cursor);
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index b64d5e62e03..62b1d2db559 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -180,12 +180,14 @@ struct btr_search_struct{
the same prefix should be indexed in the
hash index */
/*----------------------*/
+#ifdef UNIV_SEARCH_PERF_STAT
ulint n_hash_succ; /* number of successful hash searches thus
far */
ulint n_hash_fail; /* number of failed hash searches */
ulint n_patt_succ; /* number of successful pattern searches thus
far */
ulint n_searches; /* number of searches */
+#endif /* UNIV_SEARCH_PERF_STAT */
};
#define BTR_SEARCH_MAGIC_N 1112765
@@ -218,8 +220,8 @@ extern rw_lock_t* btr_search_latch_temp;
#ifdef UNIV_SEARCH_PERF_STAT
extern ulint btr_search_n_succ;
-#endif /* UNIV_SEARCH_PERF_STAT */
extern ulint btr_search_n_hash_fail;
+#endif /* UNIV_SEARCH_PERF_STAT */
/* After change in n_fields or n_bytes in info, this many rounds are waited
before starting the hash analysis again: this is to save CPU time when there
diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h
index f8150db0437..6d26fd4d3b2 100644
--- a/storage/innobase/include/buf0lru.h
+++ b/storage/innobase/include/buf0lru.h
@@ -26,14 +26,14 @@ void
buf_LRU_try_free_flushed_blocks(void);
/*==================================*/
/**********************************************************************
-Returns TRUE if less than 15 % of the buffer pool is available. This can be
+Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */
ibool
buf_LRU_buf_pool_running_out(void);
/*==============================*/
- /* out: TRUE if less than 15 % of buffer pool
+ /* out: TRUE if less than 25 % of buffer pool
left */
/*#######################################################################
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 9de5c5b52d5..39cde5bfb55 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -100,6 +100,15 @@ ulint
dict_col_get_clust_pos(
/*===================*/
dict_col_t* col);
+/********************************************************************
+If the given column name is reserved for InnoDB system columns, return
+TRUE. */
+
+ibool
+dict_col_name_is_reserved(
+/*======================*/
+ /* out: TRUE if name is reserved */
+ const char* name); /* in: column name */
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
@@ -321,6 +330,14 @@ dict_table_get_low(
/* out: table, NULL if not found */
const char* table_name); /* in: table name */
/**************************************************************************
+A noninlined version of dict_table_get_low. */
+
+dict_table_t*
+dict_table_get_low_noninlined(
+/*==========================*/
+ /* out: table, NULL if not found */
+ const char* table_name); /* in: table name */
+/**************************************************************************
Returns an index object. */
UNIV_INLINE
dict_index_t*
@@ -496,10 +513,11 @@ dict_table_is_comp(
compact page format */
const dict_table_t* table); /* in: table */
/************************************************************************
-Non inlined version of 'dict_table_is_comp' above. */
+Check whether the table uses the compact page format. */
+
ibool
-innodb_dict_table_is_comp(
-/*===============*/
+dict_table_is_comp_noninline(
+/*=========================*/
/* out: TRUE if table uses the
compact page format */
const dict_table_t* table); /* in: table */
@@ -725,33 +743,6 @@ dict_tree_free(
/**************************************************************************
In an index tree, finds the index corresponding to a record in the tree. */
-dict_index_t*
-dict_tree_find_index(
-/*=================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec); /* in: record for which to find correct index */
-/**************************************************************************
-In an index tree, finds the index corresponding to a dtuple which is used
-in a search to a tree. */
-
-dict_index_t*
-dict_tree_find_index_for_tuple(
-/*===========================*/
- /* out: index; NULL if the tuple does not
- contain the mix id field in a mixed tree */
- dict_tree_t* tree, /* in: index tree */
- dtuple_t* tuple); /* in: tuple for which to find 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 */
/**************************************************************************
Returns an index object if it is found in the dictionary cache. */
@@ -760,6 +751,7 @@ dict_index_get_if_in_cache(
/*=======================*/
/* out: index, NULL if not found */
dulint index_id); /* in: index id */
+#ifdef UNIV_DEBUG
/**************************************************************************
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. */
@@ -770,6 +762,7 @@ dict_tree_check_search_tuple(
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
dtuple_t* tuple); /* in: tuple used in a search */
+#endif /* UNIV_DEBUG */
/**************************************************************************
Builds a node pointer out of a physical record and a page number. */
@@ -916,7 +909,6 @@ dict_tables_have_same_db(
dbname '/' tablename */
const char* name2); /* in: table name in the form
dbname '/' tablename */
-
/*************************************************************************
Scans from pointer onwards. Stops if is at the start of a copy of
'string' where characters are compared without case sensitivity. Stops
@@ -928,7 +920,6 @@ dict_scan_to(
/* out: scanned up to this */
const char* ptr, /* in: scan from */
const char* string);/* in: look for this */
-
/* Buffers for storing detailed information about the latest foreign key
and unique key errors */
extern FILE* dict_foreign_err_file;
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index b99ca7815a8..0b5a23e9380 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -92,7 +92,6 @@ dict_table_get_n_user_cols(
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(table->cached);
return(table->n_cols - DATA_N_SYS_COLS);
}
@@ -126,7 +125,6 @@ dict_table_get_n_cols(
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(table->cached);
return(table->n_cols);
}
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index ab07213de3b..0135ba3874d 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -35,9 +35,11 @@ combination of types */
/* Types for a table object */
#define DICT_TABLE_ORDINARY 1
+#if 0 /* not implemented */
#define DICT_TABLE_CLUSTER_MEMBER 2
#define DICT_TABLE_CLUSTER 3 /* this means that the table is
really a cluster definition */
+#endif
/* Table flags */
#define DICT_TF_COMPACT 1 /* compact page format */
@@ -56,29 +58,13 @@ dict_mem_table_create(
a member of a cluster */
ulint n_cols, /* in: number of columns */
ulint flags); /* in: table flags */
-/**************************************************************************
-Creates a cluster memory object. */
-
-dict_cluster_t*
-dict_mem_cluster_create(
-/*====================*/
- /* out, own: cluster object (where the
- type dict_cluster_t == dict_table_t) */
- const char* name, /* in: cluster name */
- ulint space, /* in: space where the clustered
- indexes of the member tables are
- placed */
- ulint n_cols, /* in: number of columns */
- ulint mix_len); /* in: length of the common key prefix
- in the cluster */
-/**************************************************************************
-Declares a non-published table as a member in a cluster. */
+/********************************************************************
+Free a table memory object. */
void
-dict_mem_table_make_cluster_member(
-/*===============================*/
- dict_table_t* table, /* in: non-published table */
- const char* cluster_name); /* in: cluster name */
+dict_mem_table_free(
+/*================*/
+ dict_table_t* table); /* in: table */
/**************************************************************************
Adds a column definition to a table. */
@@ -176,9 +162,7 @@ struct dict_field_struct{
/* Data structure for an index tree */
struct dict_tree_struct{
ulint type; /* tree type */
- dulint id; /* id of the index stored in the tree, in the
- case of a mixed index, the id of the clustered
- index of the cluster table */
+ dulint id; /* id of the index stored in the tree */
ulint space; /* space of index tree */
ulint page; /* index tree root page number */
byte pad[64];/* Padding to prevent other memory hotspots on
@@ -189,13 +173,8 @@ struct dict_tree_struct{
struct has been memoryfixed (by mini-
transactions wanting to access the index
tree) */
- UT_LIST_BASE_NODE_T(dict_index_t)
- tree_indexes; /* list of indexes stored in the
- index tree: if the tree is not of the
- mixed type there is only one index in
- the list; if the tree is of the mixed
- type, the first index in the list is the
- index of the cluster which owns the tree */
+ dict_index_t* tree_index; /* the index stored in the
+ index tree */
ulint magic_n;/* magic number */
};
@@ -301,8 +280,7 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
/* Data structure for a database table */
struct dict_table_struct{
- dulint id; /* id of the table or cluster */
- ulint type; /* DICT_TABLE_ORDINARY, ... */
+ dulint id; /* id of the table */
ulint flags; /* DICT_TF_COMPACT, ... */
mem_heap_t* heap; /* memory heap */
const char* name; /* table name */
@@ -371,17 +349,6 @@ struct dict_table_struct{
UT_LIST_BASE_NODE_T(lock_t)
locks; /* list of locks on the table */
/*----------------------*/
- dulint mix_id; /* if the table is a member in a cluster,
- this is its mix id */
- ulint mix_len;/* if the table is a cluster or a member
- this is the common key prefix lenght */
- ulint mix_id_len;/* mix id length in a compressed form */
- byte mix_id_buf[12];
- /* mix id of a mixed table written in
- a compressed form */
- const char* cluster_name; /* if the table is a member in a
- cluster, this is the name of the cluster */
- /*----------------------*/
ibool does_not_fit_in_memory;
/* this field is used to specify in simulations
tables which are so big that disk should be
diff --git a/storage/innobase/include/eval0proc.h b/storage/innobase/include/eval0proc.h
index 2cf98f26265..8416551d0ba 100644
--- a/storage/innobase/include/eval0proc.h
+++ b/storage/innobase/include/eval0proc.h
@@ -63,6 +63,14 @@ proc_eval_step(
/* out: query thread to run next or NULL */
que_thr_t* thr); /* in: query thread */
/**************************************************************************
+Performs an execution step of an exit statement node. */
+
+que_thr_t*
+exit_step(
+/*======*/
+ /* out: query thread to run next or NULL */
+ que_thr_t* thr); /* in: query thread */
+/**************************************************************************
Performs an execution step of a return-statement node. */
que_thr_t*
diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h
index a5cd32d956f..31c5c57ae35 100644
--- a/storage/innobase/include/hash0hash.h
+++ b/storage/innobase/include/hash0hash.h
@@ -222,6 +222,32 @@ do {\
mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
} while (0)
+/********************************************************************
+Move all hash table entries from OLD_TABLE to NEW_TABLE.*/
+
+#define HASH_MIGRATE(OLD_TABLE, NEW_TABLE, NODE_TYPE, PTR_NAME, FOLD_FUNC) \
+do {\
+ ulint i2222;\
+ ulint cell_count2222;\
+\
+ cell_count2222 = hash_get_n_cells(OLD_TABLE);\
+\
+ for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
+ NODE_TYPE* node2222 = HASH_GET_FIRST((OLD_TABLE), i2222);\
+\
+ while (node2222) {\
+ NODE_TYPE* next2222 = node2222->PTR_NAME;\
+ ulint fold2222 = FOLD_FUNC(node2222);\
+\
+ HASH_INSERT(NODE_TYPE, PTR_NAME, (NEW_TABLE),\
+ fold2222, node2222);\
+\
+ node2222 = next2222;\
+ }\
+ }\
+} while (0)
+
+
/****************************************************************
Gets the mutex index for a fold value in a hash table. */
UNIV_INLINE
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index 3dda3a7cca8..6b863e32183 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -595,6 +595,15 @@ ibool
lock_validate(void);
/*===============*/
/* out: TRUE if ok */
+/*************************************************************************
+Return approximate number or record locks (bits set in the bitmap) for
+this transaction. Since delete-marked records ma ybe removed, the
+record count will not be precise. */
+
+ulint
+lock_number_of_rows_locked(
+/*=======================*/
+ trx_t* trx); /* in: transaction */
/* The lock system */
extern lock_sys_t* lock_sys;
diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h
index e2f8be98b01..f9342e962f2 100644
--- a/storage/innobase/include/mem0mem.h
+++ b/storage/innobase/include/mem0mem.h
@@ -311,6 +311,17 @@ mem_heap_strdupl(
const char* str, /* in: string to be copied */
ulint len); /* in: length of str, in bytes */
+/**************************************************************************
+Concatenate two strings and return the result, using a memory heap. */
+
+char*
+mem_heap_strcat(
+/*============*/
+ /* out, own: the result */
+ mem_heap_t* heap, /* in: memory heap where string is allocated */
+ const char* s1, /* in: string 1 */
+ const char* s2); /* in: string 2 */
+
#ifdef MEM_PERIODIC_CHECK
/**********************************************************************
Goes through the list of all allocated mem blocks, checks their magic
diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h
index 4685ffad351..3cf05feb3a9 100644
--- a/storage/innobase/include/os0thread.h
+++ b/storage/innobase/include/os0thread.h
@@ -77,7 +77,7 @@ os_thread_create(
void* arg, /* in: argument to start
function */
os_thread_id_t* thread_id); /* out: id of the created
- thread */
+ thread, or NULL */
int
os_thread_join(
/*===========*/
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index 2f651b40319..b33eeaceb1c 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -175,19 +175,6 @@ 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)));
}
diff --git a/storage/innobase/include/pars0grm.h b/storage/innobase/include/pars0grm.h
index e35fcf47692..996fc37f13b 100644
--- a/storage/innobase/include/pars0grm.h
+++ b/storage/innobase/include/pars0grm.h
@@ -32,177 +32,187 @@
PARS_INT_LIT = 258,
PARS_FLOAT_LIT = 259,
PARS_STR_LIT = 260,
- PARS_NULL_LIT = 261,
- PARS_ID_TOKEN = 262,
- PARS_AND_TOKEN = 263,
- PARS_OR_TOKEN = 264,
- PARS_NOT_TOKEN = 265,
- PARS_GE_TOKEN = 266,
- PARS_LE_TOKEN = 267,
- PARS_NE_TOKEN = 268,
- PARS_PROCEDURE_TOKEN = 269,
- PARS_IN_TOKEN = 270,
- PARS_OUT_TOKEN = 271,
- PARS_BINARY_TOKEN = 272,
- PARS_BLOB_TOKEN = 273,
- PARS_INT_TOKEN = 274,
- PARS_INTEGER_TOKEN = 275,
- PARS_FLOAT_TOKEN = 276,
- PARS_CHAR_TOKEN = 277,
- PARS_IS_TOKEN = 278,
- PARS_BEGIN_TOKEN = 279,
- PARS_END_TOKEN = 280,
- PARS_IF_TOKEN = 281,
- PARS_THEN_TOKEN = 282,
- PARS_ELSE_TOKEN = 283,
- PARS_ELSIF_TOKEN = 284,
- PARS_LOOP_TOKEN = 285,
- PARS_WHILE_TOKEN = 286,
- PARS_RETURN_TOKEN = 287,
- PARS_SELECT_TOKEN = 288,
- PARS_SUM_TOKEN = 289,
- PARS_COUNT_TOKEN = 290,
- PARS_DISTINCT_TOKEN = 291,
- PARS_FROM_TOKEN = 292,
- PARS_WHERE_TOKEN = 293,
- PARS_FOR_TOKEN = 294,
- PARS_DDOT_TOKEN = 295,
- PARS_CONSISTENT_TOKEN = 296,
- PARS_READ_TOKEN = 297,
- PARS_ORDER_TOKEN = 298,
- PARS_BY_TOKEN = 299,
- PARS_ASC_TOKEN = 300,
- PARS_DESC_TOKEN = 301,
- PARS_INSERT_TOKEN = 302,
- PARS_INTO_TOKEN = 303,
- PARS_VALUES_TOKEN = 304,
- PARS_UPDATE_TOKEN = 305,
- PARS_SET_TOKEN = 306,
- PARS_DELETE_TOKEN = 307,
- PARS_CURRENT_TOKEN = 308,
- PARS_OF_TOKEN = 309,
- PARS_CREATE_TOKEN = 310,
- PARS_TABLE_TOKEN = 311,
- PARS_INDEX_TOKEN = 312,
- PARS_UNIQUE_TOKEN = 313,
- PARS_CLUSTERED_TOKEN = 314,
- PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315,
- PARS_ON_TOKEN = 316,
- PARS_ASSIGN_TOKEN = 317,
- PARS_DECLARE_TOKEN = 318,
- PARS_CURSOR_TOKEN = 319,
- PARS_SQL_TOKEN = 320,
- PARS_OPEN_TOKEN = 321,
- PARS_FETCH_TOKEN = 322,
- PARS_CLOSE_TOKEN = 323,
- PARS_NOTFOUND_TOKEN = 324,
- PARS_TO_CHAR_TOKEN = 325,
- PARS_TO_NUMBER_TOKEN = 326,
- PARS_TO_BINARY_TOKEN = 327,
- PARS_BINARY_TO_NUMBER_TOKEN = 328,
- PARS_SUBSTR_TOKEN = 329,
- PARS_REPLSTR_TOKEN = 330,
- PARS_CONCAT_TOKEN = 331,
- PARS_INSTR_TOKEN = 332,
- PARS_LENGTH_TOKEN = 333,
- PARS_SYSDATE_TOKEN = 334,
- PARS_PRINTF_TOKEN = 335,
- PARS_ASSERT_TOKEN = 336,
- PARS_RND_TOKEN = 337,
- PARS_RND_STR_TOKEN = 338,
- PARS_ROW_PRINTF_TOKEN = 339,
- PARS_COMMIT_TOKEN = 340,
- PARS_ROLLBACK_TOKEN = 341,
- PARS_WORK_TOKEN = 342,
- NEG = 343
+ PARS_FIXBINARY_LIT = 261,
+ PARS_BLOB_LIT = 262,
+ PARS_NULL_LIT = 263,
+ PARS_ID_TOKEN = 264,
+ PARS_AND_TOKEN = 265,
+ PARS_OR_TOKEN = 266,
+ PARS_NOT_TOKEN = 267,
+ PARS_GE_TOKEN = 268,
+ PARS_LE_TOKEN = 269,
+ PARS_NE_TOKEN = 270,
+ PARS_PROCEDURE_TOKEN = 271,
+ PARS_IN_TOKEN = 272,
+ PARS_OUT_TOKEN = 273,
+ PARS_BINARY_TOKEN = 274,
+ PARS_BLOB_TOKEN = 275,
+ PARS_INT_TOKEN = 276,
+ PARS_INTEGER_TOKEN = 277,
+ PARS_FLOAT_TOKEN = 278,
+ PARS_CHAR_TOKEN = 279,
+ PARS_IS_TOKEN = 280,
+ PARS_BEGIN_TOKEN = 281,
+ PARS_END_TOKEN = 282,
+ PARS_IF_TOKEN = 283,
+ PARS_THEN_TOKEN = 284,
+ PARS_ELSE_TOKEN = 285,
+ PARS_ELSIF_TOKEN = 286,
+ PARS_LOOP_TOKEN = 287,
+ PARS_WHILE_TOKEN = 288,
+ PARS_RETURN_TOKEN = 289,
+ PARS_SELECT_TOKEN = 290,
+ PARS_SUM_TOKEN = 291,
+ PARS_COUNT_TOKEN = 292,
+ PARS_DISTINCT_TOKEN = 293,
+ PARS_FROM_TOKEN = 294,
+ PARS_WHERE_TOKEN = 295,
+ PARS_FOR_TOKEN = 296,
+ PARS_DDOT_TOKEN = 297,
+ PARS_CONSISTENT_TOKEN = 298,
+ PARS_READ_TOKEN = 299,
+ PARS_ORDER_TOKEN = 300,
+ PARS_BY_TOKEN = 301,
+ PARS_ASC_TOKEN = 302,
+ PARS_DESC_TOKEN = 303,
+ PARS_INSERT_TOKEN = 304,
+ PARS_INTO_TOKEN = 305,
+ PARS_VALUES_TOKEN = 306,
+ PARS_UPDATE_TOKEN = 307,
+ PARS_SET_TOKEN = 308,
+ PARS_DELETE_TOKEN = 309,
+ PARS_CURRENT_TOKEN = 310,
+ PARS_OF_TOKEN = 311,
+ PARS_CREATE_TOKEN = 312,
+ PARS_TABLE_TOKEN = 313,
+ PARS_INDEX_TOKEN = 314,
+ PARS_UNIQUE_TOKEN = 315,
+ PARS_CLUSTERED_TOKEN = 316,
+ PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 317,
+ PARS_ON_TOKEN = 318,
+ PARS_ASSIGN_TOKEN = 319,
+ PARS_DECLARE_TOKEN = 320,
+ PARS_CURSOR_TOKEN = 321,
+ PARS_SQL_TOKEN = 322,
+ PARS_OPEN_TOKEN = 323,
+ PARS_FETCH_TOKEN = 324,
+ PARS_CLOSE_TOKEN = 325,
+ PARS_NOTFOUND_TOKEN = 326,
+ PARS_TO_CHAR_TOKEN = 327,
+ PARS_TO_NUMBER_TOKEN = 328,
+ PARS_TO_BINARY_TOKEN = 329,
+ PARS_BINARY_TO_NUMBER_TOKEN = 330,
+ PARS_SUBSTR_TOKEN = 331,
+ PARS_REPLSTR_TOKEN = 332,
+ PARS_CONCAT_TOKEN = 333,
+ PARS_INSTR_TOKEN = 334,
+ PARS_LENGTH_TOKEN = 335,
+ PARS_SYSDATE_TOKEN = 336,
+ PARS_PRINTF_TOKEN = 337,
+ PARS_ASSERT_TOKEN = 338,
+ PARS_RND_TOKEN = 339,
+ PARS_RND_STR_TOKEN = 340,
+ PARS_ROW_PRINTF_TOKEN = 341,
+ PARS_COMMIT_TOKEN = 342,
+ PARS_ROLLBACK_TOKEN = 343,
+ PARS_WORK_TOKEN = 344,
+ PARS_UNSIGNED_TOKEN = 345,
+ PARS_EXIT_TOKEN = 346,
+ PARS_FUNCTION_TOKEN = 347,
+ NEG = 348
};
#endif
#define PARS_INT_LIT 258
#define PARS_FLOAT_LIT 259
#define PARS_STR_LIT 260
-#define PARS_NULL_LIT 261
-#define PARS_ID_TOKEN 262
-#define PARS_AND_TOKEN 263
-#define PARS_OR_TOKEN 264
-#define PARS_NOT_TOKEN 265
-#define PARS_GE_TOKEN 266
-#define PARS_LE_TOKEN 267
-#define PARS_NE_TOKEN 268
-#define PARS_PROCEDURE_TOKEN 269
-#define PARS_IN_TOKEN 270
-#define PARS_OUT_TOKEN 271
-#define PARS_BINARY_TOKEN 272
-#define PARS_BLOB_TOKEN 273
-#define PARS_INT_TOKEN 274
-#define PARS_INTEGER_TOKEN 275
-#define PARS_FLOAT_TOKEN 276
-#define PARS_CHAR_TOKEN 277
-#define PARS_IS_TOKEN 278
-#define PARS_BEGIN_TOKEN 279
-#define PARS_END_TOKEN 280
-#define PARS_IF_TOKEN 281
-#define PARS_THEN_TOKEN 282
-#define PARS_ELSE_TOKEN 283
-#define PARS_ELSIF_TOKEN 284
-#define PARS_LOOP_TOKEN 285
-#define PARS_WHILE_TOKEN 286
-#define PARS_RETURN_TOKEN 287
-#define PARS_SELECT_TOKEN 288
-#define PARS_SUM_TOKEN 289
-#define PARS_COUNT_TOKEN 290
-#define PARS_DISTINCT_TOKEN 291
-#define PARS_FROM_TOKEN 292
-#define PARS_WHERE_TOKEN 293
-#define PARS_FOR_TOKEN 294
-#define PARS_DDOT_TOKEN 295
-#define PARS_CONSISTENT_TOKEN 296
-#define PARS_READ_TOKEN 297
-#define PARS_ORDER_TOKEN 298
-#define PARS_BY_TOKEN 299
-#define PARS_ASC_TOKEN 300
-#define PARS_DESC_TOKEN 301
-#define PARS_INSERT_TOKEN 302
-#define PARS_INTO_TOKEN 303
-#define PARS_VALUES_TOKEN 304
-#define PARS_UPDATE_TOKEN 305
-#define PARS_SET_TOKEN 306
-#define PARS_DELETE_TOKEN 307
-#define PARS_CURRENT_TOKEN 308
-#define PARS_OF_TOKEN 309
-#define PARS_CREATE_TOKEN 310
-#define PARS_TABLE_TOKEN 311
-#define PARS_INDEX_TOKEN 312
-#define PARS_UNIQUE_TOKEN 313
-#define PARS_CLUSTERED_TOKEN 314
-#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315
-#define PARS_ON_TOKEN 316
-#define PARS_ASSIGN_TOKEN 317
-#define PARS_DECLARE_TOKEN 318
-#define PARS_CURSOR_TOKEN 319
-#define PARS_SQL_TOKEN 320
-#define PARS_OPEN_TOKEN 321
-#define PARS_FETCH_TOKEN 322
-#define PARS_CLOSE_TOKEN 323
-#define PARS_NOTFOUND_TOKEN 324
-#define PARS_TO_CHAR_TOKEN 325
-#define PARS_TO_NUMBER_TOKEN 326
-#define PARS_TO_BINARY_TOKEN 327
-#define PARS_BINARY_TO_NUMBER_TOKEN 328
-#define PARS_SUBSTR_TOKEN 329
-#define PARS_REPLSTR_TOKEN 330
-#define PARS_CONCAT_TOKEN 331
-#define PARS_INSTR_TOKEN 332
-#define PARS_LENGTH_TOKEN 333
-#define PARS_SYSDATE_TOKEN 334
-#define PARS_PRINTF_TOKEN 335
-#define PARS_ASSERT_TOKEN 336
-#define PARS_RND_TOKEN 337
-#define PARS_RND_STR_TOKEN 338
-#define PARS_ROW_PRINTF_TOKEN 339
-#define PARS_COMMIT_TOKEN 340
-#define PARS_ROLLBACK_TOKEN 341
-#define PARS_WORK_TOKEN 342
-#define NEG 343
+#define PARS_FIXBINARY_LIT 261
+#define PARS_BLOB_LIT 262
+#define PARS_NULL_LIT 263
+#define PARS_ID_TOKEN 264
+#define PARS_AND_TOKEN 265
+#define PARS_OR_TOKEN 266
+#define PARS_NOT_TOKEN 267
+#define PARS_GE_TOKEN 268
+#define PARS_LE_TOKEN 269
+#define PARS_NE_TOKEN 270
+#define PARS_PROCEDURE_TOKEN 271
+#define PARS_IN_TOKEN 272
+#define PARS_OUT_TOKEN 273
+#define PARS_BINARY_TOKEN 274
+#define PARS_BLOB_TOKEN 275
+#define PARS_INT_TOKEN 276
+#define PARS_INTEGER_TOKEN 277
+#define PARS_FLOAT_TOKEN 278
+#define PARS_CHAR_TOKEN 279
+#define PARS_IS_TOKEN 280
+#define PARS_BEGIN_TOKEN 281
+#define PARS_END_TOKEN 282
+#define PARS_IF_TOKEN 283
+#define PARS_THEN_TOKEN 284
+#define PARS_ELSE_TOKEN 285
+#define PARS_ELSIF_TOKEN 286
+#define PARS_LOOP_TOKEN 287
+#define PARS_WHILE_TOKEN 288
+#define PARS_RETURN_TOKEN 289
+#define PARS_SELECT_TOKEN 290
+#define PARS_SUM_TOKEN 291
+#define PARS_COUNT_TOKEN 292
+#define PARS_DISTINCT_TOKEN 293
+#define PARS_FROM_TOKEN 294
+#define PARS_WHERE_TOKEN 295
+#define PARS_FOR_TOKEN 296
+#define PARS_DDOT_TOKEN 297
+#define PARS_CONSISTENT_TOKEN 298
+#define PARS_READ_TOKEN 299
+#define PARS_ORDER_TOKEN 300
+#define PARS_BY_TOKEN 301
+#define PARS_ASC_TOKEN 302
+#define PARS_DESC_TOKEN 303
+#define PARS_INSERT_TOKEN 304
+#define PARS_INTO_TOKEN 305
+#define PARS_VALUES_TOKEN 306
+#define PARS_UPDATE_TOKEN 307
+#define PARS_SET_TOKEN 308
+#define PARS_DELETE_TOKEN 309
+#define PARS_CURRENT_TOKEN 310
+#define PARS_OF_TOKEN 311
+#define PARS_CREATE_TOKEN 312
+#define PARS_TABLE_TOKEN 313
+#define PARS_INDEX_TOKEN 314
+#define PARS_UNIQUE_TOKEN 315
+#define PARS_CLUSTERED_TOKEN 316
+#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 317
+#define PARS_ON_TOKEN 318
+#define PARS_ASSIGN_TOKEN 319
+#define PARS_DECLARE_TOKEN 320
+#define PARS_CURSOR_TOKEN 321
+#define PARS_SQL_TOKEN 322
+#define PARS_OPEN_TOKEN 323
+#define PARS_FETCH_TOKEN 324
+#define PARS_CLOSE_TOKEN 325
+#define PARS_NOTFOUND_TOKEN 326
+#define PARS_TO_CHAR_TOKEN 327
+#define PARS_TO_NUMBER_TOKEN 328
+#define PARS_TO_BINARY_TOKEN 329
+#define PARS_BINARY_TO_NUMBER_TOKEN 330
+#define PARS_SUBSTR_TOKEN 331
+#define PARS_REPLSTR_TOKEN 332
+#define PARS_CONCAT_TOKEN 333
+#define PARS_INSTR_TOKEN 334
+#define PARS_LENGTH_TOKEN 335
+#define PARS_SYSDATE_TOKEN 336
+#define PARS_PRINTF_TOKEN 337
+#define PARS_ASSERT_TOKEN 338
+#define PARS_RND_TOKEN 339
+#define PARS_RND_STR_TOKEN 340
+#define PARS_ROW_PRINTF_TOKEN 341
+#define PARS_COMMIT_TOKEN 342
+#define PARS_ROLLBACK_TOKEN 343
+#define PARS_WORK_TOKEN 344
+#define PARS_UNSIGNED_TOKEN 345
+#define PARS_EXIT_TOKEN 346
+#define PARS_FUNCTION_TOKEN 347
+#define NEG 348
diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h
index 2ae2d6cff74..68b8ae41cc0 100644
--- a/storage/innobase/include/pars0pars.h
+++ b/storage/innobase/include/pars0pars.h
@@ -15,6 +15,13 @@ Created 11/19/1996 Heikki Tuuri
#include "pars0types.h"
#include "row0types.h"
#include "trx0types.h"
+#include "ut0vec.h"
+
+/* Type of the user functions. The first argument is always InnoDB-supplied
+and varies in type, while 'user_arg' is a user-supplied argument. The
+meaning of the return type also varies. See the individual use cases, e.g.
+the FETCH statement, for details on them. */
+typedef void* (*pars_user_func_cb_t)(void* arg, void* user_arg);
extern int yydebug;
@@ -77,6 +84,7 @@ que_t*
pars_sql(
/*=====*/
/* out, own: the query graph */
+ pars_info_t* info, /* in: extra information, or NULL */
const char* str); /* in: SQL string */
/*****************************************************************
Retrieves characters to the lexical analyzer. */
@@ -157,6 +165,15 @@ pars_cursor_declaration(
table */
sel_node_t* select_node); /* in: select node */
/*************************************************************************
+Parses a function declaration. */
+
+que_node_t*
+pars_function_declaration(
+/*======================*/
+ /* out: sym_node */
+ sym_node_t* sym_node); /* in: function id node in the symbol
+ table */
+/*************************************************************************
Parses a select statement. */
sel_node_t*
@@ -269,6 +286,13 @@ pars_while_statement(
que_node_t* cond, /* in: while-condition */
que_node_t* stat_list); /* in: statement list */
/*************************************************************************
+Parses an exit statement. */
+
+exit_node_t*
+pars_exit_statement(void);
+/*=====================*/
+ /* out: exit statement node */
+/*************************************************************************
Parses a return-statement. */
return_node_t*
@@ -294,14 +318,16 @@ pars_assignment_statement(
sym_node_t* var, /* in: variable to assign */
que_node_t* val); /* in: value to assign */
/*************************************************************************
-Parses a fetch statement. */
+Parses a fetch statement. into_list or user_func (but not both) must be
+non-NULL. */
fetch_node_t*
pars_fetch_statement(
/*=================*/
/* out: fetch statement node */
sym_node_t* cursor, /* in: cursor node */
- sym_node_t* into_list); /* in: variables to set */
+ sym_node_t* into_list, /* in: variables to set, or NULL */
+ sym_node_t* user_func); /* in: user function name, or NULL */
/*************************************************************************
Parses an open or close cursor statement. */
@@ -345,6 +371,8 @@ pars_column_def(
pars_res_word_t* type, /* in: data type */
sym_node_t* len, /* in: length of column, or
NULL */
+ void* is_unsigned, /* in: if not NULL, column
+ is of type UNSIGNED. */
void* is_not_null); /* in: if not NULL, column
is of type NOT NULL. */
/*************************************************************************
@@ -418,6 +446,142 @@ pars_complete_graph_for_exec(
trx_t* trx, /* in: transaction handle */
mem_heap_t* heap); /* in: memory heap from which allocated */
+/********************************************************************
+Create parser info struct.*/
+
+pars_info_t*
+pars_info_create(void);
+/*==================*/
+ /* out, own: info struct */
+
+/********************************************************************
+Free info struct and everything it contains.*/
+
+void
+pars_info_free(
+/*===========*/
+ pars_info_t* info); /* in: info struct */
+
+/********************************************************************
+Add bound literal. */
+
+void
+pars_info_add_literal(
+/*==================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ const void* address, /* in: address */
+ ulint length, /* in: length of data */
+ ulint type, /* in: type, e.g. DATA_FIXBINARY */
+ ulint prtype); /* in: precise type, e.g.
+ DATA_UNSIGNED */
+
+/********************************************************************
+Equivalent to pars_info_add_literal(info, name, str, strlen(str),
+DATA_VARCHAR, DATA_ENGLISH). */
+
+void
+pars_info_add_str_literal(
+/*======================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ const char* str); /* in: string */
+
+/********************************************************************
+Equivalent to:
+
+char buf[4];
+mach_write_to_4(buf, val);
+pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
+
+except that the buffer is dynamically allocated from the info struct's
+heap. */
+
+void
+pars_info_add_int4_literal(
+/*=======================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ lint val); /* in: value */
+
+/********************************************************************
+Equivalent to:
+
+char buf[8];
+mach_write_to_8(buf, val);
+pars_info_add_literal(info, name, buf, 8, DATA_BINARY, 0);
+
+except that the buffer is dynamically allocated from the info struct's
+heap. */
+
+void
+pars_info_add_dulint_literal(
+/*=========================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ dulint val); /* in: value */
+/********************************************************************
+Add user function. */
+
+void
+pars_info_add_function(
+/*===================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: function name */
+ pars_user_func_cb_t func, /* in: function address */
+ void* arg); /* in: user-supplied argument */
+
+/********************************************************************
+Get user function with the given name.*/
+
+pars_user_func_t*
+pars_info_get_user_func(
+/*====================*/
+ /* out: user func, or NULL if not
+ found */
+ pars_info_t* info, /* in: info struct */
+ const char* name); /* in: function name to find*/
+
+/********************************************************************
+Get bound literal with the given name.*/
+
+pars_bound_lit_t*
+pars_info_get_bound_lit(
+/*====================*/
+ /* out: bound literal, or NULL if
+ not found */
+ pars_info_t* info, /* in: info struct */
+ const char* name); /* in: bound literal name to find */
+
+
+/* Extra information supplied for pars_sql(). */
+struct pars_info_struct {
+ mem_heap_t* heap; /* our own memory heap */
+
+ ib_vector_t* funcs; /* user functions, or NUll
+ (pars_user_func_t*) */
+ ib_vector_t* bound_lits; /* bound literals, or NULL
+ (pars_bound_lit_t*) */
+
+ ibool graph_owns_us; /* if TRUE (which is the default),
+ que_graph_free() will free us */
+};
+
+/* User-supplied function and argument. */
+struct pars_user_func_struct {
+ const char* name; /* function name */
+ pars_user_func_cb_t func; /* function address */
+ void* arg; /* user-supplied argument */
+};
+
+/* Bound literal. */
+struct pars_bound_lit_struct {
+ const char* name; /* name */
+ const void* address; /* address */
+ ulint length; /* length of data */
+ ulint type; /* type, e.g. DATA_FIXBINARY */
+ ulint prtype; /* precise type, e.g. DATA_UNSIGNED */
+};
/* Struct used to denote a reserved word in a parsing tree */
struct pars_res_word_struct{
@@ -498,6 +662,11 @@ struct for_node_struct{
que_node_t* stat_list; /* statement list */
};
+/* exit statement node */
+struct exit_node_struct{
+ que_common_t common; /* type: QUE_NODE_EXIT */
+};
+
/* return-statement node */
struct return_node_struct{
que_common_t common; /* type: QUE_NODE_RETURN */
diff --git a/storage/innobase/include/pars0sym.h b/storage/innobase/include/pars0sym.h
index a10d70d48b6..14f762d5b7a 100644
--- a/storage/innobase/include/pars0sym.h
+++ b/storage/innobase/include/pars0sym.h
@@ -54,6 +54,16 @@ sym_tab_add_str_lit(
it */
ulint len); /* in: string length */
/**********************************************************************
+Add a bound literal to a symbol table. */
+
+sym_node_t*
+sym_tab_add_bound_lit(
+/*==================*/
+ /* out: symbol table node */
+ sym_tab_t* sym_tab, /* in: symbol table */
+ const char* name, /* in: name of bound literal */
+ ulint* lit_type); /* out: type of literal (PARS_*_LIT) */
+/**********************************************************************
Adds an SQL null literal to a symbol table. */
sym_node_t*
@@ -83,6 +93,19 @@ struct sym_node_struct{
been allocated from dynamic memory and it should be freed when the
symbol table is discarded */
+ /* 'alias' and 'indirection' are almost the same, but not quite.
+ 'alias' always points to the primary instance of the variable, while
+ 'indirection' does the same only if we should use the primary
+ instance's values for the node's data. This is usually the case, but
+ when initializing a cursor (e.g., "DECLARE CURSOR c IS SELECT * FROM
+ t WHERE id = x;"), we copy the values from the primary instance to
+ the cursor's instance so that they are fixed for the duration of the
+ cursor, and set 'indirection' to NULL. If we did not, the value of
+ 'x' could change between fetches and things would break horribly.
+
+ TODO: It would be cleaner to make 'indirection' a boolean field and
+ always use 'alias' to refer to the primary node. */
+
sym_node_t* indirection; /* pointer to
another symbol table
node which contains
@@ -158,6 +181,7 @@ struct sym_tab_struct{
/* position of the next character in
sql_string to give to the lexical
analyzer */
+ pars_info_t* info; /* extra information, or NULL */
sym_node_list_t sym_list;
/* list of symbol nodes in the symbol
table */
@@ -180,6 +204,7 @@ struct sym_tab_struct{
#define SYM_CURSOR 96 /* named cursor */
#define SYM_PROCEDURE_NAME 97 /* stored procedure name */
#define SYM_INDEX 98 /* database index name */
+#define SYM_FUNCTION 99 /* user function name */
#ifndef UNIV_NONINL
#include "pars0sym.ic"
diff --git a/storage/innobase/include/pars0types.h b/storage/innobase/include/pars0types.h
index cf62617e066..6fcfaf23024 100644
--- a/storage/innobase/include/pars0types.h
+++ b/storage/innobase/include/pars0types.h
@@ -9,6 +9,9 @@ Created 1/11/1998 Heikki Tuuri
#ifndef pars0types_h
#define pars0types_h
+typedef struct pars_info_struct pars_info_t;
+typedef struct pars_user_func_struct pars_user_func_t;
+typedef struct pars_bound_lit_struct pars_bound_lit_t;
typedef struct sym_node_struct sym_node_t;
typedef struct sym_tab_struct sym_tab_t;
typedef struct pars_res_word_struct pars_res_word_t;
@@ -19,6 +22,7 @@ typedef struct elsif_node_struct elsif_node_t;
typedef struct if_node_struct if_node_t;
typedef struct while_node_struct while_node_t;
typedef struct for_node_struct for_node_t;
+typedef struct exit_node_struct exit_node_t;
typedef struct return_node_struct return_node_t;
typedef struct assign_node_struct assign_node_t;
typedef struct col_assign_node_struct col_assign_node_t;
diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h
index 4e31e2db4b7..c3314a1167b 100644
--- a/storage/innobase/include/que0que.h
+++ b/storage/innobase/include/que0que.h
@@ -277,6 +277,15 @@ que_node_get_parent(
/*================*/
/* out: parent node or NULL */
que_node_t* node); /* in: node */
+/********************************************************************
+Get the first containing loop node (e.g. while_node_t or for_node_t) for the
+given node, or NULL if the node is not within a loop. */
+
+que_node_t*
+que_node_get_containing_loop_node(
+/*==============================*/
+ /* out: containing loop node, or NULL. */
+ que_node_t* node); /* in: node */
/*************************************************************************
Catenates a query graph node to a list of them, possible empty list. */
UNIV_INLINE
@@ -322,8 +331,15 @@ void
que_node_print_info(
/*================*/
que_node_t* node); /* in: query graph node */
+/*************************************************************************
+Evaluate the given SQL */
-
+ulint
+que_eval_sql(
+/*=========*/
+ pars_info_t* info, /* out: error code or DB_SUCCESS */
+ const char* sql, /* in: info struct, or NULL */
+ trx_t* trx); /* in: trx */
/* Query graph query thread node: the fields are protected by the kernel
mutex with the exceptions named below */
@@ -388,6 +404,7 @@ struct que_fork_struct{
sym_tab_t* sym_tab; /* symbol table of the query,
generated by the parser, or NULL
if the graph was created 'by hand' */
+ pars_info_t* info; /* in: info struct, or NULL */
/* The following cur_... fields are relevant only in a select graph */
ulint cur_end; /* QUE_CUR_NOT_DEFINED, QUE_CUR_START,
@@ -469,6 +486,7 @@ struct que_fork_struct{
#define QUE_NODE_ROW_PRINTF 29
#define QUE_NODE_ELSIF 30
#define QUE_NODE_CALL 31
+#define QUE_NODE_EXIT 32
/* Query thread states */
#define QUE_THR_RUNNING 1
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 8ff8a0476a1..48fb7432b54 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -244,7 +244,8 @@ 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
+This can only be used when srv_locks_unsafe_for_binlog is TRUE or
+session is using a READ COMMITTED isolation level. 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,
diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h
index c9f2389d3dd..70b08d82994 100644
--- a/storage/innobase/include/row0sel.h
+++ b/storage/innobase/include/row0sel.h
@@ -78,6 +78,26 @@ fetch_step(
/*=======*/
/* out: query thread to run next or NULL */
que_thr_t* thr); /* in: query thread */
+/********************************************************************
+Sample callback function for fetch that prints each row.*/
+
+void*
+row_fetch_print(
+/*============*/
+ /* out: always returns non-NULL */
+ void* row, /* in: sel_node_t* */
+ void* user_arg); /* in: not used */
+/********************************************************************
+Callback function for fetch that stores an unsigned 4 byte integer to the
+location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
+= 4. */
+
+void*
+row_fetch_store_uint4(
+/*==================*/
+ /* out: always returns NULL */
+ void* row, /* in: sel_node_t* */
+ void* user_arg); /* in: data pointer */
/***************************************************************
Prints a row in a select result. */
@@ -204,8 +224,6 @@ struct plan_struct{
ulint first_prefetched;/* index of the first cached row in
select buffer arrays for each column */
ibool no_prefetch; /* no prefetch for this table */
- ibool mixed_index; /* TRUE if index is a clustered index
- in a mixed cluster */
sym_node_list_t columns; /* symbol table nodes for the columns
to retrieve from the table */
UT_LIST_BASE_NODE_T(func_node_t)
@@ -311,6 +329,20 @@ struct fetch_node_struct{
que_common_t common; /* type: QUE_NODE_FETCH */
sel_node_t* cursor_def; /* cursor definition */
sym_node_t* into_list; /* variables to set */
+
+ pars_user_func_t*
+ func; /* User callback function or NULL.
+ The first argument to the function
+ is a sel_node_t*, containing the
+ results of the SELECT operation for
+ one row. If the function returns
+ NULL, it is not interested in
+ further rows and the cursor is
+ modified so (cursor % NOTFOUND) is
+ true. If it returns not-NULL,
+ continue normally. See
+ row_fetch_print() for an example
+ (and a useful debugging tool). */
};
/* Open or close cursor statement node */
diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h
index 41cce851d87..efbc6d6facf 100644
--- a/storage/innobase/include/row0upd.h
+++ b/storage/innobase/include/row0upd.h
@@ -185,6 +185,10 @@ row_upd_index_replace_new_col_vals_index_pos(
upd_t* update, /* in: an update vector built for the index so
that the field number in an upd_field is the
index position */
+ ibool order_only,
+ /* in: if TRUE, limit the replacement to
+ ordering fields of index; note that this
+ does not work for non-clustered indexes. */
mem_heap_t* heap); /* in: memory heap to which we allocate and
copy the new values, set this as NULL if you
do not want allocation */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 906f0e3875c..ff82cb2999a 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -157,33 +157,12 @@ extern ulint srv_pool_size;
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
-extern ulint srv_sim_disk_wait_pct;
-extern ulint srv_sim_disk_wait_len;
-extern ibool srv_sim_disk_wait_by_yield;
-extern ibool srv_sim_disk_wait_by_wait;
-
-extern ibool srv_measure_contention;
-extern ibool srv_measure_by_spin;
-
extern ibool srv_print_thread_releases;
extern ibool srv_print_lock_waits;
extern ibool srv_print_buf_io;
extern ibool srv_print_log_io;
-extern ibool srv_print_parsed_sql;
extern ibool srv_print_latch_waits;
-extern ibool srv_test_nocache;
-extern ibool srv_test_cache_evict;
-
-extern ibool srv_test_extra_mutexes;
-extern ibool srv_test_sync;
-extern ulint srv_test_n_threads;
-extern ulint srv_test_n_loops;
-extern ulint srv_test_n_free_rnds;
-extern ulint srv_test_n_reserved_rnds;
-extern ulint srv_test_n_mutexes;
-extern ulint srv_test_array_size;
-
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
extern ulint srv_dml_needed_delay;
@@ -365,11 +344,7 @@ srv_release_threads(
/*************************************************************************
The master thread controlling the server. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_master_thread(
/*==============*/
/* out: a dummy parameter */
@@ -451,11 +426,7 @@ srv_release_mysql_thread_if_suspended(
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
@@ -465,11 +436,7 @@ srv_lock_timeout_and_monitor_thread(
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_error_monitor_thread(
/*=====================*/
/* out: a dummy parameter */
@@ -567,9 +534,6 @@ struct export_var_struct{
/* The server system struct */
struct srv_sys_struct{
- os_event_t operational; /* created threads must wait for the
- server to become operational by
- waiting for this event */
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index 7b450f9da39..25546430ba0 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -107,11 +107,7 @@ 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.
Note: this is done in a background thread. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 4278d602675..838b5b546c7 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -544,7 +544,9 @@ struct trx_struct{
the transaction; note that it is also
in the lock list trx_locks */
dict_index_t* new_rec_locks[2];/* these are normally NULL; if
- srv_locks_unsafe_for_binlog is TRUE,
+ srv_locks_unsafe_for_binlog is TRUE
+ or session is using READ COMMITTED
+ isolation level,
in a cursor search, if we set a new
record lock on an index, this is set
to point to the index; this is
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index de57f6f07b8..c5e87e468c6 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -82,10 +82,6 @@ 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
@@ -128,7 +124,7 @@ by one. */
#ifdef __WIN__
#define UNIV_INLINE __inline
#else
-#define UNIV_INLINE static inline
+#define UNIV_INLINE static __inline__
#endif
#else
@@ -178,6 +174,16 @@ management to ensure correct alignment for doubles etc. */
/* Note that inside MySQL 'byte' is defined as char on Linux! */
#define byte unsigned char
+/* Define an unsigned integer type that is exactly 32 bits. */
+
+#if SIZEOF_INT == 4
+typedef unsigned int ib_uint32_t;
+#elif SIZEOF_LONG == 4
+typedef unsigned long ib_uint32_t;
+#else
+#error "Neither int or long is 4 bytes"
+#endif
+
/* 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
@@ -205,9 +211,6 @@ typedef longlong ib_longlong;
#endif
#endif
-/* The following type should be at least a 64-bit floating point number */
-typedef double utfloat;
-
/* The 'undefined' value for a ulint */
#define ULINT_UNDEFINED ((ulint)(-1))
@@ -270,6 +273,18 @@ it is read or written. */
/* Compile-time constant of the given array's size. */
#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+/* The return type from a thread's start function differs between Unix and
+Windows, so define a typedef for it and a macro to use at the end of such
+functions. */
+
+#ifdef __WIN__
+typedef ulint os_thread_ret_t;
+#define OS_THREAD_DUMMY_RETURN return(0)
+#else
+typedef void* os_thread_ret_t;
+#define OS_THREAD_DUMMY_RETURN return(NULL)
+#endif
+
#include <stdio.h>
#include "ut0dbg.h"
#include "ut0ut.h"
diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h
index 6e4a265349f..90c16f4fad5 100644
--- a/storage/innobase/include/ut0mem.h
+++ b/storage/innobase/include/ut0mem.h
@@ -181,6 +181,30 @@ ut_memcpyq(
const char* src, /* in: string to be quoted */
ulint len); /* in: length of src */
+/**************************************************************************
+Return the number of times s2 occurs in s1. Overlapping instances of s2
+are only counted once. */
+
+ulint
+ut_strcount(
+/*========*/
+ /* out: the number of times s2 occurs in s1 */
+ const char* s1, /* in: string to search in */
+ const char* s2); /* in: string to search for */
+
+/**************************************************************************
+Replace every occurrence of s1 in str with s2. Overlapping instances of s1
+are only replaced once. */
+
+char *
+ut_strreplace(
+/*==========*/
+ /* out, own: modified string, must be
+ freed with mem_free() */
+ const char* str, /* in: string to operate on */
+ const char* s1, /* in: string to replace */
+ const char* s2); /* in: string to replace s1 with */
+
#ifndef UNIV_NONINL
#include "ut0mem.ic"
#endif
diff --git a/storage/innobase/include/ut0vec.h b/storage/innobase/include/ut0vec.h
new file mode 100644
index 00000000000..e0cc4dfb009
--- /dev/null
+++ b/storage/innobase/include/ut0vec.h
@@ -0,0 +1,73 @@
+#ifndef IB_VECTOR_H
+#define IB_VECTOR_H
+
+#include "univ.i"
+#include "mem0mem.h"
+
+typedef struct ib_vector_struct ib_vector_t;
+
+/* An automatically resizing vector datatype with the following properties:
+
+ -Contains void* items.
+
+ -The items are owned by the caller.
+
+ -All memory allocation is done through a heap owned by the caller, who is
+ responsible for freeing it when done with the vector.
+
+ -When the vector is resized, the old memory area is left allocated since it
+ uses the same heap as the new memory area, so this is best used for
+ relatively small or short-lived uses.
+*/
+
+/********************************************************************
+Create a new vector with the given initial size. */
+
+ib_vector_t*
+ib_vector_create(
+/*=============*/
+ /* out: vector */
+ mem_heap_t* heap, /* in: heap */
+ ulint size); /* in: initial size */
+
+/********************************************************************
+Push a new element to the vector, increasing its size if necessary. */
+
+void
+ib_vector_push(
+/*===========*/
+ ib_vector_t* vec, /* in: vector */
+ void* elem); /* in: data element */
+
+/********************************************************************
+Get the number of elements in the vector. */
+UNIV_INLINE
+ulint
+ib_vector_size(
+/*===========*/
+ /* out: number of elements in vector */
+ ib_vector_t* vec); /* in: vector */
+
+/********************************************************************
+Get the n'th element. */
+UNIV_INLINE
+void*
+ib_vector_get(
+/*==========*/
+ /* out: n'th element */
+ ib_vector_t* vec, /* in: vector */
+ ulint n); /* in: element index to get */
+
+/* See comment at beginning of file. */
+struct ib_vector_struct {
+ mem_heap_t* heap; /* heap */
+ void** data; /* data elements */
+ ulint used; /* number of elements currently used */
+ ulint total; /* number of elements allocated */
+};
+
+#ifndef UNIV_NONINL
+#include "ut0vec.ic"
+#endif
+
+#endif
diff --git a/storage/innobase/include/ut0vec.ic b/storage/innobase/include/ut0vec.ic
new file mode 100644
index 00000000000..417a17d951f
--- /dev/null
+++ b/storage/innobase/include/ut0vec.ic
@@ -0,0 +1,26 @@
+/********************************************************************
+Get number of elements in vector. */
+UNIV_INLINE
+ulint
+ib_vector_size(
+/*===========*/
+ /* out: number of elements in vector */
+ ib_vector_t* vec) /* in: vector */
+{
+ return(vec->used);
+}
+
+/********************************************************************
+Get n'th element. */
+UNIV_INLINE
+void*
+ib_vector_get(
+/*==========*/
+ /* out: n'th element */
+ ib_vector_t* vec, /* in: vector */
+ ulint n) /* in: element index to get */
+{
+ ut_a(n < vec->used);
+
+ return(vec->data[n]);
+}
diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
index 1152e0c89ea..34e3296c9bc 100644
--- a/storage/innobase/lock/lock0lock.c
+++ b/storage/innobase/lock/lock0lock.c
@@ -1698,6 +1698,40 @@ lock_sec_rec_some_has_impl_off_kernel(
return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
}
+/*************************************************************************
+Return approximate number or record locks (bits set in the bitmap) for
+this transaction. Since delete-marked records may be removed, the
+record count will not be precise. */
+
+ulint
+lock_number_of_rows_locked(
+/*=======================*/
+ trx_t* trx) /* in: transaction */
+{
+ lock_t* lock;
+ ulint n_records = 0;
+ ulint n_bits;
+ ulint n_bit;
+
+ lock = UT_LIST_GET_FIRST(trx->trx_locks);
+
+ while (lock) {
+ if (lock_get_type(lock) == LOCK_REC) {
+ n_bits = lock_rec_get_n_bits(lock);
+
+ for (n_bit = 0; n_bit < n_bits; n_bit++) {
+ if (lock_rec_get_nth_bit(lock, n_bit)) {
+ n_records++;
+ }
+ }
+ }
+
+ lock = UT_LIST_GET_NEXT(trx_locks, lock);
+ }
+
+ return (n_records);
+}
+
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
/*************************************************************************
@@ -2001,7 +2035,8 @@ lock_rec_lock_fast(
if (!impl) {
lock_rec_create(mode, rec, index, trx);
- if (srv_locks_unsafe_for_binlog) {
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
trx_register_new_rec_lock(trx, index);
}
}
@@ -2027,7 +2062,8 @@ lock_rec_lock_fast(
if (!lock_rec_get_nth_bit(lock, heap_no)) {
lock_rec_set_nth_bit(lock, heap_no);
- if (srv_locks_unsafe_for_binlog) {
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
trx_register_new_rec_lock(trx, index);
}
}
@@ -2087,7 +2123,8 @@ lock_rec_lock_slow(
err = lock_rec_enqueue_waiting(mode, rec, index, thr);
- if (srv_locks_unsafe_for_binlog) {
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
trx_register_new_rec_lock(trx, index);
}
} else {
@@ -2096,7 +2133,8 @@ lock_rec_lock_slow(
lock_rec_add_to_queue(LOCK_REC | mode, rec, index,
trx);
- if (srv_locks_unsafe_for_binlog) {
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
trx_register_new_rec_lock(trx, index);
}
}
@@ -2436,15 +2474,18 @@ lock_rec_inherit_to_gap(
lock = lock_rec_get_first(rec);
- /* If srv_locks_unsafe_for_binlog is TRUE, we do not want locks set
+ /* If srv_locks_unsafe_for_binlog is TRUE or session is using
+ READ COMMITTED isolation level, 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)
- && !(srv_locks_unsafe_for_binlog
- && lock_get_mode(lock) == LOCK_X)) {
+ && !((srv_locks_unsafe_for_binlog
+ || lock->trx->isolation_level ==
+ TRX_ISO_READ_COMMITTED)
+ && lock_get_mode(lock) == LOCK_X)) {
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
| LOCK_GAP,
@@ -4320,6 +4361,10 @@ loop:
(ulong) ut_dulint_get_low(trx->read_view->up_limit_id));
}
+ fprintf(file,
+ "Trx has approximately %lu row locks\n",
+ (ulong) lock_number_of_rows_locked(trx));
+
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
fprintf(file,
"------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n",
@@ -5167,3 +5212,4 @@ lock_clust_rec_read_check_and_lock_alt(
}
return(ret);
}
+
diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index f210afe6b5d..4a91192782e 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -897,9 +897,9 @@ recv_parse_or_apply_log_rec_body(
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);
+
+ dict_mem_index_free(index);
+ dict_mem_table_free(table);
}
return(ptr);
@@ -2940,7 +2940,6 @@ recv_recovery_from_checkpoint_finish(void)
/*======================================*/
{
int i;
- os_thread_id_t recovery_thread_id;
/* Apply the hashed log records to the respective file pages */
@@ -2984,7 +2983,7 @@ recv_recovery_from_checkpoint_finish(void)
session */
os_thread_create(trx_rollback_or_clean_all_without_sess,
- (void *)&i, &recovery_thread_id);
+ (void *)&i, NULL);
}
}
diff --git a/storage/innobase/mem/mem0dbg.c b/storage/innobase/mem/mem0dbg.c
index 86d5beb9c80..86c33a22531 100644
--- a/storage/innobase/mem/mem0dbg.c
+++ b/storage/innobase/mem/mem0dbg.c
@@ -445,7 +445,7 @@ mem_heap_validate_or_print(
&& (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
fprintf(stderr,
-"InnoDB: Error: mem block %p length %lu > UNIV_PAGE_SIZE\n", block,
+"InnoDB: Error: mem block %p length %lu > UNIV_PAGE_SIZE\n", (void*) block,
(ulong) mem_block_get_len(block));
/* error */
diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c
index 90d3f4fa6b1..5e7c48d3d3d 100644
--- a/storage/innobase/mem/mem0mem.c
+++ b/storage/innobase/mem/mem0mem.c
@@ -114,6 +114,31 @@ mem_heap_strdup(
return(memcpy(mem_heap_alloc(heap, len), str, len));
}
+/**************************************************************************
+Concatenate two strings and return the result, using a memory heap. */
+
+char*
+mem_heap_strcat(
+/*============*/
+ /* out, own: the result */
+ mem_heap_t* heap, /* in: memory heap where string is allocated */
+ const char* s1, /* in: string 1 */
+ const char* s2) /* in: string 2 */
+{
+ char* s;
+ ulint s1_len = strlen(s1);
+ ulint s2_len = strlen(s2);
+
+ s = mem_heap_alloc(heap, s1_len + s2_len + 1);
+
+ memcpy(s, s1, s1_len);
+ memcpy(s + s1_len, s2, s2_len);
+
+ s[s1_len + s2_len] = '\0';
+
+ return(s);
+}
+
/*******************************************************************
Creates a memory heap block where data can be allocated. */
diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c
index 706c10ac613..eceedcb66b2 100644
--- a/storage/innobase/os/os0sync.c
+++ b/storage/innobase/os/os0sync.c
@@ -641,7 +641,7 @@ os_fast_mutex_free(
" InnoDB: error: return value %lu when calling\n"
"InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
fprintf(stderr,
-"InnoDB: Byte contents of the pthread mutex at %p:\n", fast_mutex);
+"InnoDB: Byte contents of the pthread mutex at %p:\n", (void*) fast_mutex);
ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
fprintf(stderr, "\n");
}
diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c
index ff0362840c7..0b739c07557 100644
--- a/storage/innobase/os/os0thread.c
+++ b/storage/innobase/os/os0thread.c
@@ -96,7 +96,7 @@ os_thread_create(
void* arg, /* in: argument to start
function */
os_thread_id_t* thread_id) /* out: id of the created
- thread */
+ thread, or NULL */
{
#ifdef __WIN__
os_thread_t thread;
@@ -122,7 +122,9 @@ os_thread_create(
ut_a(SetThreadPriority(thread, srv_query_thread_priority));
}
- *thread_id = win_thread_id;
+ if (thread_id) {
+ *thread_id = win_thread_id;
+ }
return(thread);
#else
@@ -180,7 +182,9 @@ os_thread_create(
my_pthread_setprio(pthread, srv_query_thread_priority);
}
- *thread_id = pthread;
+ if (thread_id) {
+ *thread_id = pthread;
+ }
return(pthread);
#endif
diff --git a/storage/innobase/pars/lexyy.c b/storage/innobase/pars/lexyy.c
index d64ecbbfcbc..bbe78db1613 100644
--- a/storage/innobase/pars/lexyy.c
+++ b/storage/innobase/pars/lexyy.c
@@ -1,7 +1,7 @@
-
-#line 3 "lex.yy.c"
-
#include "univ.i"
+#line 2 "_flex_tmp.c"
+
+#line 4 "_flex_tmp.c"
#define YY_INT_ALIGNED short int
@@ -356,8 +356,8 @@ static void yy_fatal_error (yyconst char msg[] );
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 109
-#define YY_END_OF_BUFFER 110
+#define YY_NUM_RULES 116
+#define YY_END_OF_BUFFER 117
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -365,48 +365,52 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[370] =
+static yyconst flex_int16_t yy_accept[394] =
{ 0,
- 0, 0, 104, 104, 0, 0, 110, 108, 107, 107,
- 99, 3, 88, 94, 97, 95, 92, 96, 108, 98,
- 1, 108, 93, 91, 89, 90, 102, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 100, 101, 104, 105, 4,
- 5, 107, 83, 103, 2, 1, 84, 85, 87, 86,
- 82, 82, 82, 82, 82, 82, 40, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 23, 12, 20, 82, 82, 82, 82, 50, 57,
- 82, 9, 82, 82, 82, 82, 82, 82, 82, 82,
-
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 104,
- 105, 105, 106, 4, 5, 2, 8, 41, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 22, 82, 82, 36,
- 82, 82, 82, 16, 82, 82, 10, 82, 82, 82,
- 13, 82, 82, 82, 82, 82, 76, 82, 82, 82,
- 47, 7, 82, 31, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 15, 19, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 42, 82, 82, 25, 82, 82, 82, 34, 82, 82,
-
- 82, 82, 44, 82, 27, 82, 6, 60, 82, 82,
- 82, 38, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 24, 82, 82, 82, 82, 82, 82, 82, 82,
- 81, 82, 21, 82, 62, 82, 82, 82, 82, 32,
- 82, 82, 82, 82, 82, 82, 82, 26, 61, 18,
- 53, 82, 71, 82, 82, 82, 39, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 52, 82, 82,
- 82, 82, 82, 82, 35, 28, 75, 14, 82, 79,
- 70, 82, 51, 82, 59, 82, 48, 82, 82, 43,
- 82, 72, 82, 74, 82, 82, 29, 82, 82, 82,
-
- 30, 68, 82, 82, 82, 82, 54, 46, 45, 82,
- 82, 82, 49, 58, 82, 82, 17, 82, 82, 69,
- 77, 82, 82, 73, 82, 64, 82, 82, 82, 82,
- 33, 82, 63, 82, 80, 82, 82, 82, 82, 55,
- 82, 82, 11, 82, 66, 65, 82, 37, 82, 78,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 67, 82, 82, 82, 82, 82, 82, 56, 0
+ 0, 0, 111, 111, 0, 0, 0, 0, 117, 115,
+ 114, 114, 7, 106, 4, 95, 101, 104, 102, 99,
+ 103, 115, 105, 1, 115, 100, 98, 96, 97, 109,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 107, 108,
+ 111, 112, 5, 6, 8, 9, 114, 90, 110, 2,
+ 1, 3, 91, 92, 94, 93, 89, 89, 89, 89,
+ 89, 89, 44, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 27,
+ 16, 24, 89, 89, 89, 89, 54, 61, 89, 13,
+
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 111, 112, 112,
+ 113, 5, 6, 8, 9, 2, 12, 45, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 26, 89, 89, 89,
+ 40, 89, 89, 89, 89, 20, 89, 89, 14, 89,
+ 89, 89, 17, 89, 89, 89, 89, 89, 80, 89,
+ 89, 89, 51, 11, 89, 35, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 19, 23, 89, 89, 89, 89, 89, 89, 89, 89,
+
+ 89, 89, 89, 46, 89, 89, 29, 89, 87, 89,
+ 89, 38, 89, 89, 89, 89, 89, 48, 89, 31,
+ 89, 10, 64, 89, 89, 89, 42, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 28, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 85, 89, 25, 89,
+ 66, 89, 89, 89, 89, 36, 89, 89, 89, 89,
+ 89, 89, 89, 30, 65, 22, 89, 57, 89, 75,
+ 89, 89, 89, 43, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 56, 89, 89, 89, 89, 89,
+ 89, 89, 39, 32, 79, 18, 89, 83, 74, 89,
+
+ 55, 89, 63, 89, 52, 89, 89, 89, 47, 89,
+ 76, 89, 78, 89, 89, 33, 89, 89, 89, 34,
+ 72, 89, 89, 89, 89, 58, 89, 50, 49, 89,
+ 89, 89, 53, 62, 89, 89, 89, 21, 89, 89,
+ 73, 81, 89, 89, 77, 89, 68, 89, 89, 89,
+ 89, 89, 37, 89, 88, 67, 89, 84, 89, 89,
+ 89, 86, 89, 59, 89, 89, 15, 89, 70, 69,
+ 89, 41, 89, 82, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 71, 89, 89, 89, 89, 89,
+ 89, 60, 0
+
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -414,17 +418,17 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 1, 1, 1, 4, 1, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 15, 16, 17,
- 18, 19, 20, 1, 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, 30,
- 1, 1, 1, 1, 46, 1, 30, 30, 30, 30,
-
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 47, 1, 48, 1, 1, 1, 1, 1,
+ 1, 2, 1, 4, 1, 1, 5, 1, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 16, 17, 18,
+ 19, 20, 21, 1, 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, 31,
+ 1, 1, 1, 1, 47, 1, 31, 31, 31, 31,
+
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 48, 1, 49, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -441,209 +445,229 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[49] =
+static yyconst flex_int32_t yy_meta[50] =
{ 0,
- 1, 1, 1, 1, 2, 1, 1, 3, 1, 1,
- 1, 1, 1, 4, 1, 1, 1, 1, 1, 1,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 1, 1
+ 1, 1, 1, 2, 1, 3, 1, 1, 4, 1,
+ 1, 1, 1, 1, 5, 1, 1, 1, 6, 1,
+ 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 1, 1
} ;
-static yyconst flex_int16_t yy_base[376] =
+static yyconst flex_int16_t yy_base[403] =
{ 0,
- 0, 0, 390, 389, 391, 390, 394, 399, 47, 49,
- 399, 399, 399, 399, 399, 399, 399, 399, 381, 384,
- 41, 373, 399, 38, 399, 372, 399, 20, 33, 32,
- 46, 29, 44, 0, 46, 49, 42, 60, 351, 65,
- 66, 67, 32, 367, 69, 399, 399, 0, 79, 0,
- 382, 103, 399, 399, 372, 96, 399, 399, 399, 399,
- 0, 361, 70, 357, 349, 347, 0, 360, 77, 80,
- 355, 341, 92, 339, 352, 337, 351, 334, 338, 334,
- 336, 0, 93, 0, 336, 334, 328, 335, 0, 0,
- 341, 341, 324, 87, 98, 339, 93, 88, 330, 104,
-
- 322, 338, 334, 312, 328, 332, 323, 98, 316, 0,
- 122, 131, 399, 0, 348, 338, 0, 0, 326, 321,
- 328, 326, 309, 307, 306, 311, 106, 309, 321, 102,
- 309, 315, 316, 298, 298, 117, 0, 313, 314, 0,
- 301, 308, 118, 122, 305, 295, 304, 297, 294, 302,
- 0, 292, 302, 300, 291, 281, 275, 288, 273, 293,
- 0, 0, 278, 0, 292, 283, 280, 126, 276, 291,
- 270, 272, 277, 277, 269, 272, 267, 0, 0, 279,
- 263, 273, 280, 271, 259, 258, 272, 261, 274, 254,
- 0, 264, 246, 0, 265, 262, 249, 0, 244, 249,
-
- 248, 258, 0, 244, 0, 248, 0, 0, 244, 241,
- 255, 0, 240, 240, 238, 254, 239, 251, 233, 251,
- 246, 0, 241, 241, 227, 226, 226, 240, 239, 238,
- 0, 222, 0, 216, 0, 235, 219, 218, 218, 0,
- 231, 221, 216, 215, 227, 217, 216, 0, 0, 0,
- 0, 209, 0, 223, 219, 205, 0, 219, 220, 203,
- 208, 201, 219, 201, 198, 199, 196, 0, 201, 213,
- 200, 207, 206, 191, 0, 0, 0, 183, 190, 0,
- 0, 187, 0, 186, 0, 200, 0, 201, 188, 0,
- 184, 0, 187, 0, 179, 181, 0, 180, 194, 187,
-
- 0, 0, 190, 193, 175, 190, 0, 0, 0, 171,
- 185, 184, 0, 0, 168, 167, 0, 182, 167, 0,
- 0, 173, 169, 0, 164, 0, 176, 165, 175, 164,
- 0, 151, 0, 171, 0, 155, 149, 155, 146, 0,
- 151, 164, 0, 163, 0, 0, 154, 0, 158, 0,
- 145, 145, 151, 137, 160, 152, 153, 137, 121, 110,
- 0, 122, 129, 120, 117, 113, 105, 0, 399, 160,
- 164, 85, 168, 172, 176
+ 0, 0, 434, 433, 435, 434, 435, 434, 437, 444,
+ 48, 50, 444, 444, 444, 444, 444, 444, 444, 444,
+ 444, 423, 426, 41, 415, 444, 38, 444, 414, 444,
+ 20, 33, 32, 46, 40, 44, 0, 54, 52, 48,
+ 60, 393, 65, 66, 74, 27, 409, 69, 444, 444,
+ 0, 97, 0, 424, 0, 425, 111, 444, 444, 413,
+ 54, 408, 444, 444, 444, 444, 0, 401, 69, 397,
+ 389, 387, 0, 400, 79, 82, 395, 381, 94, 379,
+ 392, 377, 391, 385, 373, 377, 373, 375, 375, 0,
+ 82, 0, 374, 372, 366, 373, 0, 0, 379, 379,
+
+ 362, 89, 98, 377, 93, 95, 368, 106, 360, 376,
+ 372, 350, 101, 371, 362, 112, 355, 0, 134, 135,
+ 444, 0, 387, 0, 388, 376, 0, 0, 364, 359,
+ 366, 364, 347, 345, 344, 349, 106, 347, 359, 93,
+ 347, 353, 354, 336, 336, 121, 0, 334, 350, 351,
+ 0, 338, 347, 344, 119, 126, 341, 331, 340, 333,
+ 330, 338, 0, 328, 338, 336, 327, 317, 311, 324,
+ 309, 329, 0, 0, 314, 0, 328, 319, 316, 130,
+ 312, 319, 326, 305, 307, 312, 312, 304, 307, 302,
+ 0, 0, 314, 298, 308, 315, 306, 294, 293, 307,
+
+ 296, 309, 289, 0, 299, 281, 0, 300, 0, 297,
+ 284, 0, 283, 278, 283, 282, 292, 0, 278, 0,
+ 282, 0, 0, 278, 275, 289, 0, 274, 274, 272,
+ 288, 273, 285, 267, 285, 280, 0, 275, 275, 261,
+ 260, 273, 259, 273, 272, 271, 0, 255, 0, 249,
+ 0, 268, 252, 251, 251, 0, 264, 254, 249, 248,
+ 260, 250, 249, 0, 0, 0, 253, 0, 241, 0,
+ 255, 251, 237, 0, 251, 252, 235, 240, 233, 251,
+ 233, 230, 231, 228, 0, 233, 245, 232, 239, 229,
+ 237, 222, 0, 0, 0, 214, 221, 0, 0, 218,
+
+ 0, 217, 0, 231, 0, 232, 219, 218, 0, 214,
+ 0, 217, 0, 209, 211, 0, 210, 224, 217, 0,
+ 0, 220, 223, 205, 220, 0, 216, 0, 0, 200,
+ 214, 213, 0, 0, 197, 196, 201, 0, 210, 195,
+ 0, 0, 201, 197, 0, 192, 0, 204, 204, 192,
+ 202, 191, 0, 178, 0, 0, 198, 0, 182, 176,
+ 182, 0, 173, 0, 178, 191, 0, 190, 0, 0,
+ 181, 0, 185, 0, 172, 172, 178, 164, 187, 175,
+ 174, 154, 125, 116, 0, 127, 133, 124, 121, 117,
+ 109, 0, 444, 165, 171, 177, 179, 145, 185, 191,
+
+ 197, 203
} ;
-static yyconst flex_int16_t yy_def[376] =
+static yyconst flex_int16_t yy_def[403] =
{ 0,
- 369, 1, 370, 370, 371, 371, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 369, 369, 373, 374, 375,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
-
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 373,
- 374, 374, 369, 375, 369, 369, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
-
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
-
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 0, 369,
- 369, 369, 369, 369, 369
+ 393, 1, 394, 394, 395, 395, 396, 396, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 397, 393, 393, 393, 393, 393,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 393, 393,
+ 399, 400, 401, 393, 402, 393, 393, 393, 393, 393,
+ 393, 397, 393, 393, 393, 393, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 399, 400, 400,
+ 393, 401, 393, 402, 393, 393, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 0, 393, 393, 393, 393, 393, 393, 393,
+
+ 393, 393
} ;
-static yyconst flex_int16_t yy_nxt[448] =
+static yyconst flex_int16_t yy_nxt[494] =
{ 0,
- 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, 34, 35, 34,
- 34, 36, 34, 37, 38, 39, 34, 40, 41, 42,
- 43, 44, 45, 34, 34, 34, 46, 47, 52, 52,
- 52, 52, 55, 62, 56, 58, 59, 64, 63, 68,
- 76, 65, 77, 69, 66, 105, 70, 106, 78, 71,
- 73, 82, 72, 85, 74, 79, 87, 67, 80, 83,
- 75, 81, 88, 86, 84, 89, 112, 102, 61, 95,
- 98, 113, 118, 90, 103, 91, 108, 92, 96, 97,
-
- 93, 104, 99, 109, 52, 52, 100, 55, 119, 56,
- 101, 124, 126, 127, 131, 152, 142, 125, 154, 160,
- 128, 153, 172, 132, 158, 163, 173, 161, 183, 369,
- 133, 143, 144, 155, 369, 159, 164, 156, 112, 187,
- 188, 194, 200, 113, 184, 195, 202, 223, 224, 368,
- 367, 366, 365, 364, 363, 362, 203, 201, 361, 225,
- 48, 48, 48, 48, 50, 50, 50, 50, 110, 110,
- 360, 110, 111, 111, 111, 111, 114, 359, 114, 114,
- 358, 357, 356, 355, 354, 353, 352, 351, 350, 349,
- 348, 347, 346, 345, 344, 343, 342, 341, 340, 339,
-
- 338, 337, 336, 335, 334, 333, 332, 331, 330, 329,
- 328, 327, 326, 325, 324, 323, 322, 321, 320, 319,
- 318, 317, 316, 315, 314, 313, 312, 311, 310, 309,
- 308, 307, 306, 305, 304, 303, 302, 301, 300, 299,
- 298, 297, 296, 295, 294, 293, 292, 291, 290, 289,
- 288, 287, 286, 285, 284, 283, 282, 281, 280, 279,
- 278, 277, 276, 275, 274, 273, 272, 271, 270, 269,
- 268, 267, 266, 265, 264, 263, 262, 261, 260, 259,
- 258, 257, 256, 255, 254, 253, 252, 251, 250, 249,
- 248, 247, 246, 245, 244, 243, 242, 241, 240, 239,
-
- 238, 237, 236, 235, 234, 233, 232, 231, 230, 229,
- 228, 227, 226, 222, 221, 220, 219, 218, 217, 216,
- 215, 214, 213, 212, 211, 210, 209, 208, 207, 206,
- 205, 204, 199, 198, 197, 196, 193, 192, 191, 190,
- 189, 186, 185, 182, 181, 180, 179, 178, 177, 176,
- 175, 116, 115, 174, 171, 170, 169, 168, 167, 166,
- 165, 162, 157, 151, 150, 149, 148, 147, 146, 145,
- 141, 140, 139, 138, 137, 136, 135, 134, 130, 129,
- 123, 122, 121, 120, 117, 116, 115, 107, 94, 60,
- 57, 54, 53, 369, 51, 51, 49, 49, 7, 369,
-
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369
+ 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, 37, 38,
+ 37, 37, 39, 37, 40, 41, 42, 37, 43, 44,
+ 45, 46, 47, 48, 37, 37, 37, 49, 50, 57,
+ 57, 57, 57, 60, 68, 61, 64, 65, 70, 69,
+ 74, 113, 71, 114, 75, 72, 60, 76, 61, 85,
+ 77, 79, 82, 78, 83, 80, 86, 93, 73, 87,
+ 90, 81, 88, 95, 84, 89, 97, 94, 91, 96,
+ 103, 106, 128, 92, 98, 110, 99, 116, 100, 104,
+
+ 105, 101, 111, 107, 117, 120, 154, 108, 129, 112,
+ 121, 109, 57, 57, 134, 136, 137, 141, 164, 166,
+ 135, 155, 156, 138, 165, 170, 142, 172, 175, 196,
+ 181, 200, 201, 143, 167, 173, 171, 185, 168, 176,
+ 182, 186, 393, 120, 215, 197, 207, 393, 121, 67,
+ 208, 217, 238, 239, 392, 391, 390, 389, 388, 216,
+ 387, 218, 386, 385, 240, 51, 51, 51, 51, 51,
+ 51, 53, 53, 53, 53, 53, 53, 55, 55, 55,
+ 55, 55, 55, 62, 62, 118, 118, 118, 384, 118,
+ 118, 119, 119, 119, 119, 119, 119, 122, 122, 383,
+
+ 122, 122, 122, 124, 382, 124, 124, 124, 124, 381,
+ 380, 379, 378, 377, 376, 375, 374, 373, 372, 371,
+ 370, 369, 368, 367, 366, 365, 364, 363, 362, 361,
+ 360, 359, 358, 357, 356, 355, 354, 353, 352, 351,
+ 350, 349, 348, 347, 346, 345, 344, 343, 342, 341,
+ 340, 339, 338, 337, 336, 335, 334, 333, 332, 331,
+ 330, 329, 328, 327, 326, 325, 324, 323, 322, 321,
+ 320, 319, 318, 317, 316, 315, 314, 313, 312, 311,
+ 310, 309, 308, 307, 306, 305, 304, 303, 302, 301,
+ 300, 299, 298, 297, 296, 295, 294, 293, 292, 291,
+
+ 290, 289, 288, 287, 286, 285, 284, 283, 282, 281,
+ 280, 279, 278, 277, 276, 275, 274, 273, 272, 271,
+ 270, 269, 268, 267, 266, 265, 264, 263, 262, 261,
+ 260, 259, 258, 257, 256, 255, 254, 253, 252, 251,
+ 250, 249, 248, 247, 246, 245, 244, 243, 242, 241,
+ 237, 236, 235, 234, 233, 232, 231, 230, 229, 228,
+ 227, 226, 225, 224, 223, 222, 221, 220, 219, 214,
+ 213, 212, 211, 210, 209, 206, 205, 204, 203, 202,
+ 199, 198, 195, 194, 193, 192, 191, 190, 189, 188,
+ 126, 125, 123, 187, 184, 183, 180, 179, 178, 177,
+
+ 174, 169, 163, 162, 161, 160, 159, 158, 157, 153,
+ 152, 151, 150, 149, 148, 147, 146, 145, 144, 140,
+ 139, 133, 132, 131, 130, 127, 393, 126, 125, 123,
+ 115, 102, 66, 63, 59, 58, 393, 56, 56, 54,
+ 54, 52, 52, 9, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393
+
} ;
-static yyconst flex_int16_t yy_chk[448] =
+static yyconst flex_int16_t yy_chk[494] =
{ 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, 9, 9,
- 10, 10, 21, 28, 21, 24, 24, 29, 28, 30,
- 32, 29, 32, 30, 29, 43, 30, 43, 33, 30,
- 31, 35, 30, 36, 31, 33, 37, 29, 33, 35,
- 31, 33, 37, 36, 35, 38, 49, 42, 372, 40,
- 41, 49, 63, 38, 42, 38, 45, 38, 40, 40,
-
- 38, 42, 41, 45, 52, 52, 41, 56, 63, 56,
- 41, 69, 70, 70, 73, 94, 83, 69, 95, 98,
- 70, 94, 108, 73, 97, 100, 108, 98, 127, 111,
- 73, 83, 83, 95, 111, 97, 100, 95, 112, 130,
- 130, 136, 143, 112, 127, 136, 144, 168, 168, 367,
- 366, 365, 364, 363, 362, 360, 144, 143, 359, 168,
- 370, 370, 370, 370, 371, 371, 371, 371, 373, 373,
- 358, 373, 374, 374, 374, 374, 375, 357, 375, 375,
- 356, 355, 354, 353, 352, 351, 349, 347, 344, 342,
- 341, 339, 338, 337, 336, 334, 332, 330, 329, 328,
-
- 327, 325, 323, 322, 319, 318, 316, 315, 312, 311,
- 310, 306, 305, 304, 303, 300, 299, 298, 296, 295,
- 293, 291, 289, 288, 286, 284, 282, 279, 278, 274,
- 273, 272, 271, 270, 269, 267, 266, 265, 264, 263,
- 262, 261, 260, 259, 258, 256, 255, 254, 252, 247,
- 246, 245, 244, 243, 242, 241, 239, 238, 237, 236,
- 234, 232, 230, 229, 228, 227, 226, 225, 224, 223,
- 221, 220, 219, 218, 217, 216, 215, 214, 213, 211,
- 210, 209, 206, 204, 202, 201, 200, 199, 197, 196,
- 195, 193, 192, 190, 189, 188, 187, 186, 185, 184,
-
- 183, 182, 181, 180, 177, 176, 175, 174, 173, 172,
- 171, 170, 169, 167, 166, 165, 163, 160, 159, 158,
- 157, 156, 155, 154, 153, 152, 150, 149, 148, 147,
- 146, 145, 142, 141, 139, 138, 135, 134, 133, 132,
- 131, 129, 128, 126, 125, 124, 123, 122, 121, 120,
- 119, 116, 115, 109, 107, 106, 105, 104, 103, 102,
- 101, 99, 96, 93, 92, 91, 88, 87, 86, 85,
- 81, 80, 79, 78, 77, 76, 75, 74, 72, 71,
- 68, 66, 65, 64, 62, 55, 51, 44, 39, 26,
- 22, 20, 19, 7, 6, 5, 4, 3, 369, 369,
-
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
- 369, 369, 369, 369, 369, 369, 369
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 11,
+ 11, 12, 12, 24, 31, 24, 27, 27, 32, 31,
+ 33, 46, 32, 46, 33, 32, 61, 33, 61, 36,
+ 33, 34, 35, 33, 35, 34, 36, 39, 32, 36,
+ 38, 34, 36, 40, 35, 36, 41, 39, 38, 40,
+ 43, 44, 69, 38, 41, 45, 41, 48, 41, 43,
+
+ 43, 41, 45, 44, 48, 52, 91, 44, 69, 45,
+ 52, 44, 57, 57, 75, 76, 76, 79, 102, 103,
+ 75, 91, 91, 76, 102, 105, 79, 106, 108, 137,
+ 113, 140, 140, 79, 103, 106, 105, 116, 103, 108,
+ 113, 116, 119, 120, 155, 137, 146, 119, 120, 398,
+ 146, 156, 180, 180, 391, 390, 389, 388, 387, 155,
+ 386, 156, 384, 383, 180, 394, 394, 394, 394, 394,
+ 394, 395, 395, 395, 395, 395, 395, 396, 396, 396,
+ 396, 396, 396, 397, 397, 399, 399, 399, 382, 399,
+ 399, 400, 400, 400, 400, 400, 400, 401, 401, 381,
+
+ 401, 401, 401, 402, 380, 402, 402, 402, 402, 379,
+ 378, 377, 376, 375, 373, 371, 368, 366, 365, 363,
+ 361, 360, 359, 357, 354, 352, 351, 350, 349, 348,
+ 346, 344, 343, 340, 339, 337, 336, 335, 332, 331,
+ 330, 327, 325, 324, 323, 322, 319, 318, 317, 315,
+ 314, 312, 310, 308, 307, 306, 304, 302, 300, 297,
+ 296, 292, 291, 290, 289, 288, 287, 286, 284, 283,
+ 282, 281, 280, 279, 278, 277, 276, 275, 273, 272,
+ 271, 269, 267, 263, 262, 261, 260, 259, 258, 257,
+ 255, 254, 253, 252, 250, 248, 246, 245, 244, 243,
+
+ 242, 241, 240, 239, 238, 236, 235, 234, 233, 232,
+ 231, 230, 229, 228, 226, 225, 224, 221, 219, 217,
+ 216, 215, 214, 213, 211, 210, 208, 206, 205, 203,
+ 202, 201, 200, 199, 198, 197, 196, 195, 194, 193,
+ 190, 189, 188, 187, 186, 185, 184, 183, 182, 181,
+ 179, 178, 177, 175, 172, 171, 170, 169, 168, 167,
+ 166, 165, 164, 162, 161, 160, 159, 158, 157, 154,
+ 153, 152, 150, 149, 148, 145, 144, 143, 142, 141,
+ 139, 138, 136, 135, 134, 133, 132, 131, 130, 129,
+ 126, 125, 123, 117, 115, 114, 112, 111, 110, 109,
+
+ 107, 104, 101, 100, 99, 96, 95, 94, 93, 89,
+ 88, 87, 86, 85, 84, 83, 82, 81, 80, 78,
+ 77, 74, 72, 71, 70, 68, 62, 60, 56, 54,
+ 47, 42, 29, 25, 23, 22, 9, 8, 7, 6,
+ 5, 4, 3, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393, 393, 393, 393, 393, 393, 393, 393,
+ 393, 393, 393
+
} ;
static yy_state_type yy_last_accepting_state;
@@ -675,34 +699,16 @@ not automatically generate them from pars0grm.y and pars0lex.l.
How to make the InnoDB parser and lexer C files:
-1. First do
- bison -d pars0grm.y
- That generates pars0grm.tab.c and pars0grm.tab.h.
-
-2. Rename pars0grm.tab.c to pars0grm.c and pars0grm.tab.h to pars0grm.h.
-
-3. Copy pars0grm.h also to /innobase/include
-
-4. Do
- flex pars0lex.l
- That generates lex.yy.c.
-
-5. Rename lex.yy.c to lexyy.c.
+1. Run ./make_flex.sh to generate lexer files.
-6. Remove the #include of unistd.h from about line 2500 of lexyy.c
+2. Run ./make_bison.sh to generate parser 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
+These instructions seem to work at least with bison-1.875d and flex-2.5.31 on
Linux.
*******************************************************/
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 1
-#line 56 "pars0lex.l"
+#line 38 "pars0lex.l"
#define YYSTYPE que_node_t*
#include "univ.i"
@@ -749,11 +755,13 @@ string_append(
-#line 751 "lex.yy.c"
+
+#line 759 "_flex_tmp.c"
#define INITIAL 0
#define comment 1
#define quoted 2
+#define id 3
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -900,10 +908,10 @@ YY_DECL
register char *yy_cp, *yy_bp;
register int yy_act;
-#line 106 "pars0lex.l"
+#line 91 "pars0lex.l"
-#line 905 "lex.yy.c"
+#line 914 "_flex_tmp.c"
if ( (yy_init) )
{
@@ -956,13 +964,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 370 )
+ if ( yy_current_state >= 394 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 369 );
+ while ( yy_current_state != 393 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -984,7 +992,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 108 "pars0lex.l"
+#line 93 "pars0lex.l"
{
yylval = sym_tab_add_int_lit(pars_sym_tab_global,
atoi(yytext));
@@ -993,7 +1001,7 @@ YY_RULE_SETUP
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 114 "pars0lex.l"
+#line 99 "pars0lex.l"
{
ut_error; /* not implemented */
@@ -1002,7 +1010,19 @@ YY_RULE_SETUP
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 120 "pars0lex.l"
+#line 105 "pars0lex.l"
+{
+ ulint type;
+
+ yylval = sym_tab_add_bound_lit(pars_sym_tab_global,
+ yytext + 1, &type);
+
+ return(type);
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 114 "pars0lex.l"
{
/* Quoted character string literals are handled in an explicit
start state 'quoted'. This state is entered and the buffer for
@@ -1013,19 +1033,19 @@ In the state 'quoted', only two actions are possible (defined below). */
stringbuf_len = 0;
}
YY_BREAK
-case 4:
-/* rule 4 can match eol */
+case 5:
+/* rule 5 can match eol */
YY_RULE_SETUP
-#line 129 "pars0lex.l"
+#line 123 "pars0lex.l"
{
/* Got a sequence of characters other than "'":
append to string buffer */
string_append(yytext, yyleng);
}
YY_BREAK
-case 5:
+case 6:
YY_RULE_SETUP
-#line 134 "pars0lex.l"
+#line 128 "pars0lex.l"
{
/* Got a sequence of "'" characters:
append half of them to string buffer,
@@ -1050,18 +1070,69 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 6:
+case 7:
YY_RULE_SETUP
-#line 158 "pars0lex.l"
+#line 152 "pars0lex.l"
+{
+/* Quoted identifiers are handled in an explicit start state 'id'.
+This state is entered and the buffer for the scanned string is emptied
+upon encountering a starting quote.
+
+In the state 'id', only two actions are possible (defined below). */
+ BEGIN(id);
+ stringbuf_len = 0;
+}
+ YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+#line 161 "pars0lex.l"
+{
+ /* Got a sequence of characters other than '"':
+ append to string buffer */
+ string_append(yytext, yyleng);
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 166 "pars0lex.l"
+{
+ /* Got a sequence of '"' characters:
+ append half of them to string buffer,
+ as '""' represents a single '"'.
+ We apply truncating division,
+ so that '"""' will result in '"'. */
+
+ string_append(yytext, yyleng / 2);
+
+ /* If we got an odd number of quotes, then the
+ last quote we got is the terminating quote.
+ At the end of the string, we return to the
+ initial start state and report the scanned
+ identifier. */
+
+ if (yyleng % 2) {
+ BEGIN(INITIAL);
+ yylval = sym_tab_add_id(
+ pars_sym_tab_global,
+ (byte*) stringbuf, stringbuf_len);
+
+ return(PARS_ID_TOKEN);
+ }
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 191 "pars0lex.l"
{
yylval = sym_tab_add_null_lit(pars_sym_tab_global);
return(PARS_NULL_LIT);
}
YY_BREAK
-case 7:
+case 11:
YY_RULE_SETUP
-#line 164 "pars0lex.l"
+#line 197 "pars0lex.l"
{
/* Implicit cursor name */
yylval = sym_tab_add_str_lit(pars_sym_tab_global,
@@ -1069,527 +1140,548 @@ YY_RULE_SETUP
return(PARS_SQL_TOKEN);
}
YY_BREAK
-case 8:
+case 12:
YY_RULE_SETUP
-#line 171 "pars0lex.l"
+#line 204 "pars0lex.l"
{
return(PARS_AND_TOKEN);
}
YY_BREAK
-case 9:
+case 13:
YY_RULE_SETUP
-#line 175 "pars0lex.l"
+#line 208 "pars0lex.l"
{
return(PARS_OR_TOKEN);
}
YY_BREAK
-case 10:
+case 14:
YY_RULE_SETUP
-#line 179 "pars0lex.l"
+#line 212 "pars0lex.l"
{
return(PARS_NOT_TOKEN);
}
YY_BREAK
-case 11:
+case 15:
YY_RULE_SETUP
-#line 183 "pars0lex.l"
+#line 216 "pars0lex.l"
{
return(PARS_PROCEDURE_TOKEN);
}
YY_BREAK
-case 12:
+case 16:
YY_RULE_SETUP
-#line 187 "pars0lex.l"
+#line 220 "pars0lex.l"
{
return(PARS_IN_TOKEN);
}
YY_BREAK
-case 13:
+case 17:
YY_RULE_SETUP
-#line 191 "pars0lex.l"
+#line 224 "pars0lex.l"
{
return(PARS_OUT_TOKEN);
}
YY_BREAK
-case 14:
+case 18:
YY_RULE_SETUP
-#line 195 "pars0lex.l"
+#line 228 "pars0lex.l"
{
return(PARS_BINARY_TOKEN);
}
YY_BREAK
-case 15:
+case 19:
YY_RULE_SETUP
-#line 199 "pars0lex.l"
+#line 232 "pars0lex.l"
{
return(PARS_BLOB_TOKEN);
}
YY_BREAK
-case 16:
+case 20:
YY_RULE_SETUP
-#line 203 "pars0lex.l"
+#line 236 "pars0lex.l"
{
return(PARS_INT_TOKEN);
}
YY_BREAK
-case 17:
+case 21:
YY_RULE_SETUP
-#line 207 "pars0lex.l"
+#line 240 "pars0lex.l"
{
return(PARS_INT_TOKEN);
}
YY_BREAK
-case 18:
+case 22:
YY_RULE_SETUP
-#line 211 "pars0lex.l"
+#line 244 "pars0lex.l"
{
return(PARS_FLOAT_TOKEN);
}
YY_BREAK
-case 19:
+case 23:
YY_RULE_SETUP
-#line 215 "pars0lex.l"
+#line 248 "pars0lex.l"
{
return(PARS_CHAR_TOKEN);
}
YY_BREAK
-case 20:
+case 24:
YY_RULE_SETUP
-#line 219 "pars0lex.l"
+#line 252 "pars0lex.l"
{
return(PARS_IS_TOKEN);
}
YY_BREAK
-case 21:
+case 25:
YY_RULE_SETUP
-#line 223 "pars0lex.l"
+#line 256 "pars0lex.l"
{
return(PARS_BEGIN_TOKEN);
}
YY_BREAK
-case 22:
+case 26:
YY_RULE_SETUP
-#line 227 "pars0lex.l"
+#line 260 "pars0lex.l"
{
return(PARS_END_TOKEN);
}
YY_BREAK
-case 23:
+case 27:
YY_RULE_SETUP
-#line 231 "pars0lex.l"
+#line 264 "pars0lex.l"
{
return(PARS_IF_TOKEN);
}
YY_BREAK
-case 24:
+case 28:
YY_RULE_SETUP
-#line 235 "pars0lex.l"
+#line 268 "pars0lex.l"
{
return(PARS_THEN_TOKEN);
}
YY_BREAK
-case 25:
+case 29:
YY_RULE_SETUP
-#line 239 "pars0lex.l"
+#line 272 "pars0lex.l"
{
return(PARS_ELSE_TOKEN);
}
YY_BREAK
-case 26:
+case 30:
YY_RULE_SETUP
-#line 243 "pars0lex.l"
+#line 276 "pars0lex.l"
{
return(PARS_ELSIF_TOKEN);
}
YY_BREAK
-case 27:
+case 31:
YY_RULE_SETUP
-#line 247 "pars0lex.l"
+#line 280 "pars0lex.l"
{
return(PARS_LOOP_TOKEN);
}
YY_BREAK
-case 28:
+case 32:
YY_RULE_SETUP
-#line 251 "pars0lex.l"
+#line 284 "pars0lex.l"
{
return(PARS_WHILE_TOKEN);
}
YY_BREAK
-case 29:
+case 33:
YY_RULE_SETUP
-#line 255 "pars0lex.l"
+#line 288 "pars0lex.l"
{
return(PARS_RETURN_TOKEN);
}
YY_BREAK
-case 30:
+case 34:
YY_RULE_SETUP
-#line 259 "pars0lex.l"
+#line 292 "pars0lex.l"
{
return(PARS_SELECT_TOKEN);
}
YY_BREAK
-case 31:
+case 35:
YY_RULE_SETUP
-#line 263 "pars0lex.l"
+#line 296 "pars0lex.l"
{
return(PARS_SUM_TOKEN);
}
YY_BREAK
-case 32:
+case 36:
YY_RULE_SETUP
-#line 267 "pars0lex.l"
+#line 300 "pars0lex.l"
{
return(PARS_COUNT_TOKEN);
}
YY_BREAK
-case 33:
+case 37:
YY_RULE_SETUP
-#line 271 "pars0lex.l"
+#line 304 "pars0lex.l"
{
return(PARS_DISTINCT_TOKEN);
}
YY_BREAK
-case 34:
+case 38:
YY_RULE_SETUP
-#line 275 "pars0lex.l"
+#line 308 "pars0lex.l"
{
return(PARS_FROM_TOKEN);
}
YY_BREAK
-case 35:
+case 39:
YY_RULE_SETUP
-#line 279 "pars0lex.l"
+#line 312 "pars0lex.l"
{
return(PARS_WHERE_TOKEN);
}
YY_BREAK
-case 36:
+case 40:
YY_RULE_SETUP
-#line 283 "pars0lex.l"
+#line 316 "pars0lex.l"
{
return(PARS_FOR_TOKEN);
}
YY_BREAK
-case 37:
+case 41:
YY_RULE_SETUP
-#line 287 "pars0lex.l"
+#line 320 "pars0lex.l"
{
return(PARS_CONSISTENT_TOKEN);
}
YY_BREAK
-case 38:
+case 42:
YY_RULE_SETUP
-#line 291 "pars0lex.l"
+#line 324 "pars0lex.l"
{
return(PARS_READ_TOKEN);
}
YY_BREAK
-case 39:
+case 43:
YY_RULE_SETUP
-#line 295 "pars0lex.l"
+#line 328 "pars0lex.l"
{
return(PARS_ORDER_TOKEN);
}
YY_BREAK
-case 40:
+case 44:
YY_RULE_SETUP
-#line 299 "pars0lex.l"
+#line 332 "pars0lex.l"
{
return(PARS_BY_TOKEN);
}
YY_BREAK
-case 41:
+case 45:
YY_RULE_SETUP
-#line 303 "pars0lex.l"
+#line 336 "pars0lex.l"
{
return(PARS_ASC_TOKEN);
}
YY_BREAK
-case 42:
+case 46:
YY_RULE_SETUP
-#line 307 "pars0lex.l"
+#line 340 "pars0lex.l"
{
return(PARS_DESC_TOKEN);
}
YY_BREAK
-case 43:
+case 47:
YY_RULE_SETUP
-#line 311 "pars0lex.l"
+#line 344 "pars0lex.l"
{
return(PARS_INSERT_TOKEN);
}
YY_BREAK
-case 44:
+case 48:
YY_RULE_SETUP
-#line 315 "pars0lex.l"
+#line 348 "pars0lex.l"
{
return(PARS_INTO_TOKEN);
}
YY_BREAK
-case 45:
+case 49:
YY_RULE_SETUP
-#line 319 "pars0lex.l"
+#line 352 "pars0lex.l"
{
return(PARS_VALUES_TOKEN);
}
YY_BREAK
-case 46:
+case 50:
YY_RULE_SETUP
-#line 323 "pars0lex.l"
+#line 356 "pars0lex.l"
{
return(PARS_UPDATE_TOKEN);
}
YY_BREAK
-case 47:
+case 51:
YY_RULE_SETUP
-#line 327 "pars0lex.l"
+#line 360 "pars0lex.l"
{
return(PARS_SET_TOKEN);
}
YY_BREAK
-case 48:
+case 52:
YY_RULE_SETUP
-#line 331 "pars0lex.l"
+#line 364 "pars0lex.l"
{
return(PARS_DELETE_TOKEN);
}
YY_BREAK
-case 49:
+case 53:
YY_RULE_SETUP
-#line 335 "pars0lex.l"
+#line 368 "pars0lex.l"
{
return(PARS_CURRENT_TOKEN);
}
YY_BREAK
-case 50:
+case 54:
YY_RULE_SETUP
-#line 339 "pars0lex.l"
+#line 372 "pars0lex.l"
{
return(PARS_OF_TOKEN);
}
YY_BREAK
-case 51:
+case 55:
YY_RULE_SETUP
-#line 343 "pars0lex.l"
+#line 376 "pars0lex.l"
{
return(PARS_CREATE_TOKEN);
}
YY_BREAK
-case 52:
+case 56:
YY_RULE_SETUP
-#line 347 "pars0lex.l"
+#line 380 "pars0lex.l"
{
return(PARS_TABLE_TOKEN);
}
YY_BREAK
-case 53:
+case 57:
YY_RULE_SETUP
-#line 351 "pars0lex.l"
+#line 384 "pars0lex.l"
{
return(PARS_INDEX_TOKEN);
}
YY_BREAK
-case 54:
+case 58:
YY_RULE_SETUP
-#line 355 "pars0lex.l"
+#line 388 "pars0lex.l"
{
return(PARS_UNIQUE_TOKEN);
}
YY_BREAK
-case 55:
+case 59:
YY_RULE_SETUP
-#line 359 "pars0lex.l"
+#line 392 "pars0lex.l"
{
return(PARS_CLUSTERED_TOKEN);
}
YY_BREAK
-case 56:
+case 60:
YY_RULE_SETUP
-#line 363 "pars0lex.l"
+#line 396 "pars0lex.l"
{
return(PARS_DOES_NOT_FIT_IN_MEM_TOKEN);
}
YY_BREAK
-case 57:
+case 61:
YY_RULE_SETUP
-#line 367 "pars0lex.l"
+#line 400 "pars0lex.l"
{
return(PARS_ON_TOKEN);
}
YY_BREAK
-case 58:
+case 62:
YY_RULE_SETUP
-#line 371 "pars0lex.l"
+#line 404 "pars0lex.l"
{
return(PARS_DECLARE_TOKEN);
}
YY_BREAK
-case 59:
+case 63:
YY_RULE_SETUP
-#line 375 "pars0lex.l"
+#line 408 "pars0lex.l"
{
return(PARS_CURSOR_TOKEN);
}
YY_BREAK
-case 60:
+case 64:
YY_RULE_SETUP
-#line 379 "pars0lex.l"
+#line 412 "pars0lex.l"
{
return(PARS_OPEN_TOKEN);
}
YY_BREAK
-case 61:
+case 65:
YY_RULE_SETUP
-#line 383 "pars0lex.l"
+#line 416 "pars0lex.l"
{
return(PARS_FETCH_TOKEN);
}
YY_BREAK
-case 62:
+case 66:
YY_RULE_SETUP
-#line 387 "pars0lex.l"
+#line 420 "pars0lex.l"
{
return(PARS_CLOSE_TOKEN);
}
YY_BREAK
-case 63:
+case 67:
YY_RULE_SETUP
-#line 391 "pars0lex.l"
+#line 424 "pars0lex.l"
{
return(PARS_NOTFOUND_TOKEN);
}
YY_BREAK
-case 64:
+case 68:
YY_RULE_SETUP
-#line 395 "pars0lex.l"
+#line 428 "pars0lex.l"
{
return(PARS_TO_CHAR_TOKEN);
}
YY_BREAK
-case 65:
+case 69:
YY_RULE_SETUP
-#line 399 "pars0lex.l"
+#line 432 "pars0lex.l"
{
return(PARS_TO_NUMBER_TOKEN);
}
YY_BREAK
-case 66:
+case 70:
YY_RULE_SETUP
-#line 403 "pars0lex.l"
+#line 436 "pars0lex.l"
{
return(PARS_TO_BINARY_TOKEN);
}
YY_BREAK
-case 67:
+case 71:
YY_RULE_SETUP
-#line 407 "pars0lex.l"
+#line 440 "pars0lex.l"
{
return(PARS_BINARY_TO_NUMBER_TOKEN);
}
YY_BREAK
-case 68:
+case 72:
YY_RULE_SETUP
-#line 411 "pars0lex.l"
+#line 444 "pars0lex.l"
{
return(PARS_SUBSTR_TOKEN);
}
YY_BREAK
-case 69:
+case 73:
YY_RULE_SETUP
-#line 415 "pars0lex.l"
+#line 448 "pars0lex.l"
{
return(PARS_REPLSTR_TOKEN);
}
YY_BREAK
-case 70:
+case 74:
YY_RULE_SETUP
-#line 419 "pars0lex.l"
+#line 452 "pars0lex.l"
{
return(PARS_CONCAT_TOKEN);
}
YY_BREAK
-case 71:
+case 75:
YY_RULE_SETUP
-#line 423 "pars0lex.l"
+#line 456 "pars0lex.l"
{
return(PARS_INSTR_TOKEN);
}
YY_BREAK
-case 72:
+case 76:
YY_RULE_SETUP
-#line 427 "pars0lex.l"
+#line 460 "pars0lex.l"
{
return(PARS_LENGTH_TOKEN);
}
YY_BREAK
-case 73:
+case 77:
YY_RULE_SETUP
-#line 431 "pars0lex.l"
+#line 464 "pars0lex.l"
{
return(PARS_SYSDATE_TOKEN);
}
YY_BREAK
-case 74:
+case 78:
YY_RULE_SETUP
-#line 435 "pars0lex.l"
+#line 468 "pars0lex.l"
{
return(PARS_PRINTF_TOKEN);
}
YY_BREAK
-case 75:
+case 79:
YY_RULE_SETUP
-#line 439 "pars0lex.l"
+#line 472 "pars0lex.l"
{
return(PARS_ASSERT_TOKEN);
}
YY_BREAK
-case 76:
+case 80:
YY_RULE_SETUP
-#line 443 "pars0lex.l"
+#line 476 "pars0lex.l"
{
return(PARS_RND_TOKEN);
}
YY_BREAK
-case 77:
+case 81:
YY_RULE_SETUP
-#line 447 "pars0lex.l"
+#line 480 "pars0lex.l"
{
return(PARS_RND_STR_TOKEN);
}
YY_BREAK
-case 78:
+case 82:
YY_RULE_SETUP
-#line 451 "pars0lex.l"
+#line 484 "pars0lex.l"
{
return(PARS_ROW_PRINTF_TOKEN);
}
YY_BREAK
-case 79:
+case 83:
YY_RULE_SETUP
-#line 455 "pars0lex.l"
+#line 488 "pars0lex.l"
{
return(PARS_COMMIT_TOKEN);
}
YY_BREAK
-case 80:
+case 84:
YY_RULE_SETUP
-#line 459 "pars0lex.l"
+#line 492 "pars0lex.l"
{
return(PARS_ROLLBACK_TOKEN);
}
YY_BREAK
-case 81:
+case 85:
YY_RULE_SETUP
-#line 463 "pars0lex.l"
+#line 496 "pars0lex.l"
{
return(PARS_WORK_TOKEN);
}
YY_BREAK
-case 82:
+case 86:
+YY_RULE_SETUP
+#line 500 "pars0lex.l"
+{
+ return(PARS_UNSIGNED_TOKEN);
+}
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 504 "pars0lex.l"
+{
+ return(PARS_EXIT_TOKEN);
+}
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 508 "pars0lex.l"
+{
+ return(PARS_FUNCTION_TOKEN);
+}
+ YY_BREAK
+case 89:
YY_RULE_SETUP
-#line 467 "pars0lex.l"
+#line 512 "pars0lex.l"
{
yylval = sym_tab_add_id(pars_sym_tab_global,
(byte*)yytext,
@@ -1597,192 +1689,192 @@ YY_RULE_SETUP
return(PARS_ID_TOKEN);
}
YY_BREAK
-case 83:
+case 90:
YY_RULE_SETUP
-#line 474 "pars0lex.l"
+#line 519 "pars0lex.l"
{
return(PARS_DDOT_TOKEN);
}
YY_BREAK
-case 84:
+case 91:
YY_RULE_SETUP
-#line 478 "pars0lex.l"
+#line 523 "pars0lex.l"
{
return(PARS_ASSIGN_TOKEN);
}
YY_BREAK
-case 85:
+case 92:
YY_RULE_SETUP
-#line 482 "pars0lex.l"
+#line 527 "pars0lex.l"
{
return(PARS_LE_TOKEN);
}
YY_BREAK
-case 86:
+case 93:
YY_RULE_SETUP
-#line 486 "pars0lex.l"
+#line 531 "pars0lex.l"
{
return(PARS_GE_TOKEN);
}
YY_BREAK
-case 87:
+case 94:
YY_RULE_SETUP
-#line 490 "pars0lex.l"
+#line 535 "pars0lex.l"
{
return(PARS_NE_TOKEN);
}
YY_BREAK
-case 88:
+case 95:
YY_RULE_SETUP
-#line 494 "pars0lex.l"
+#line 539 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 89:
+case 96:
YY_RULE_SETUP
-#line 499 "pars0lex.l"
+#line 544 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 90:
+case 97:
YY_RULE_SETUP
-#line 504 "pars0lex.l"
+#line 549 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 91:
+case 98:
YY_RULE_SETUP
-#line 509 "pars0lex.l"
+#line 554 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 92:
+case 99:
YY_RULE_SETUP
-#line 514 "pars0lex.l"
+#line 559 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 93:
+case 100:
YY_RULE_SETUP
-#line 519 "pars0lex.l"
+#line 564 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 94:
+case 101:
YY_RULE_SETUP
-#line 524 "pars0lex.l"
+#line 569 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 95:
+case 102:
YY_RULE_SETUP
-#line 529 "pars0lex.l"
+#line 574 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 96:
+case 103:
YY_RULE_SETUP
-#line 534 "pars0lex.l"
+#line 579 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 97:
+case 104:
YY_RULE_SETUP
-#line 539 "pars0lex.l"
+#line 584 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 98:
+case 105:
YY_RULE_SETUP
-#line 544 "pars0lex.l"
+#line 589 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 99:
+case 106:
YY_RULE_SETUP
-#line 549 "pars0lex.l"
+#line 594 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 100:
+case 107:
YY_RULE_SETUP
-#line 554 "pars0lex.l"
+#line 599 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 101:
+case 108:
YY_RULE_SETUP
-#line 559 "pars0lex.l"
+#line 604 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 102:
+case 109:
YY_RULE_SETUP
-#line 564 "pars0lex.l"
+#line 609 "pars0lex.l"
{
return((int)(*yytext));
}
YY_BREAK
-case 103:
+case 110:
YY_RULE_SETUP
-#line 569 "pars0lex.l"
+#line 614 "pars0lex.l"
BEGIN(comment); /* eat up comment */
YY_BREAK
-case 104:
-/* rule 104 can match eol */
+case 111:
+/* rule 111 can match eol */
YY_RULE_SETUP
-#line 571 "pars0lex.l"
+#line 616 "pars0lex.l"
YY_BREAK
-case 105:
-/* rule 105 can match eol */
+case 112:
+/* rule 112 can match eol */
YY_RULE_SETUP
-#line 572 "pars0lex.l"
+#line 617 "pars0lex.l"
YY_BREAK
-case 106:
+case 113:
YY_RULE_SETUP
-#line 573 "pars0lex.l"
+#line 618 "pars0lex.l"
BEGIN(INITIAL);
YY_BREAK
-case 107:
-/* rule 107 can match eol */
+case 114:
+/* rule 114 can match eol */
YY_RULE_SETUP
-#line 575 "pars0lex.l"
+#line 620 "pars0lex.l"
/* eat up whitespace */
YY_BREAK
-case 108:
+case 115:
YY_RULE_SETUP
-#line 578 "pars0lex.l"
+#line 623 "pars0lex.l"
{
fprintf(stderr,"Unrecognized character: %02x\n",
*yytext);
@@ -1792,15 +1884,16 @@ YY_RULE_SETUP
return(0);
}
YY_BREAK
-case 109:
+case 116:
YY_RULE_SETUP
-#line 587 "pars0lex.l"
+#line 632 "pars0lex.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1799 "lex.yy.c"
+#line 1892 "_flex_tmp.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(comment):
case YY_STATE_EOF(quoted):
+case YY_STATE_EOF(id):
yyterminate();
case YY_END_OF_BUFFER:
@@ -2084,7 +2177,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 370 )
+ if ( yy_current_state >= 394 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -2112,11 +2205,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 370 )
+ if ( yy_current_state >= 394 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 369);
+ yy_is_jam = (yy_current_state == 393);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -2145,7 +2238,7 @@ static int yy_get_next_buffer (void)
else
{ /* need more input */
- int offset = (int)(yy_c_buf_p - yytext_ptr);
+ int offset = (int)((yy_c_buf_p) - (yytext_ptr));
++(yy_c_buf_p);
switch ( yy_get_next_buffer( ) )
@@ -2639,7 +2732,7 @@ void yyfree (void * ptr )
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
-#line 587 "pars0lex.l"
+#line 632 "pars0lex.l"
diff --git a/storage/innobase/pars/make_bison.sh b/storage/innobase/pars/make_bison.sh
index 43b0322494c..c11456230c4 100755
--- a/storage/innobase/pars/make_bison.sh
+++ b/storage/innobase/pars/make_bison.sh
@@ -1,7 +1,6 @@
#!/bin/bash
#
-# regenerate parser from bison input files as documented at the top of
-# pars0lex.l.
+# generate parser files from bison input files.
set -eu
diff --git a/storage/innobase/pars/make_flex.sh b/storage/innobase/pars/make_flex.sh
new file mode 100755
index 00000000000..c015327bf8c
--- /dev/null
+++ b/storage/innobase/pars/make_flex.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# generate lexer files from flex input files.
+
+set -eu
+
+TMPFILE=_flex_tmp.c
+OUTFILE=lexyy.c
+
+flex -o $TMPFILE pars0lex.l
+
+# AIX needs its includes done in a certain order, so include "univ.i" first
+# to be sure we get it right.
+echo '#include "univ.i"' > $OUTFILE
+
+# flex assigns a pointer to an int in one place without a cast, resulting in
+# a warning on Win64. this adds the cast.
+sed -e 's/int offset = (yy_c_buf_p) - (yytext_ptr);/int offset = (int)((yy_c_buf_p) - (yytext_ptr));/;' < $TMPFILE >> $OUTFILE
+
+rm $TMPFILE
diff --git a/storage/innobase/pars/pars0grm.c b/storage/innobase/pars/pars0grm.c
index 3800cdda88e..2cce7cb1c8b 100644
--- a/storage/innobase/pars/pars0grm.c
+++ b/storage/innobase/pars/pars0grm.c
@@ -56,177 +56,187 @@
PARS_INT_LIT = 258,
PARS_FLOAT_LIT = 259,
PARS_STR_LIT = 260,
- PARS_NULL_LIT = 261,
- PARS_ID_TOKEN = 262,
- PARS_AND_TOKEN = 263,
- PARS_OR_TOKEN = 264,
- PARS_NOT_TOKEN = 265,
- PARS_GE_TOKEN = 266,
- PARS_LE_TOKEN = 267,
- PARS_NE_TOKEN = 268,
- PARS_PROCEDURE_TOKEN = 269,
- PARS_IN_TOKEN = 270,
- PARS_OUT_TOKEN = 271,
- PARS_BINARY_TOKEN = 272,
- PARS_BLOB_TOKEN = 273,
- PARS_INT_TOKEN = 274,
- PARS_INTEGER_TOKEN = 275,
- PARS_FLOAT_TOKEN = 276,
- PARS_CHAR_TOKEN = 277,
- PARS_IS_TOKEN = 278,
- PARS_BEGIN_TOKEN = 279,
- PARS_END_TOKEN = 280,
- PARS_IF_TOKEN = 281,
- PARS_THEN_TOKEN = 282,
- PARS_ELSE_TOKEN = 283,
- PARS_ELSIF_TOKEN = 284,
- PARS_LOOP_TOKEN = 285,
- PARS_WHILE_TOKEN = 286,
- PARS_RETURN_TOKEN = 287,
- PARS_SELECT_TOKEN = 288,
- PARS_SUM_TOKEN = 289,
- PARS_COUNT_TOKEN = 290,
- PARS_DISTINCT_TOKEN = 291,
- PARS_FROM_TOKEN = 292,
- PARS_WHERE_TOKEN = 293,
- PARS_FOR_TOKEN = 294,
- PARS_DDOT_TOKEN = 295,
- PARS_CONSISTENT_TOKEN = 296,
- PARS_READ_TOKEN = 297,
- PARS_ORDER_TOKEN = 298,
- PARS_BY_TOKEN = 299,
- PARS_ASC_TOKEN = 300,
- PARS_DESC_TOKEN = 301,
- PARS_INSERT_TOKEN = 302,
- PARS_INTO_TOKEN = 303,
- PARS_VALUES_TOKEN = 304,
- PARS_UPDATE_TOKEN = 305,
- PARS_SET_TOKEN = 306,
- PARS_DELETE_TOKEN = 307,
- PARS_CURRENT_TOKEN = 308,
- PARS_OF_TOKEN = 309,
- PARS_CREATE_TOKEN = 310,
- PARS_TABLE_TOKEN = 311,
- PARS_INDEX_TOKEN = 312,
- PARS_UNIQUE_TOKEN = 313,
- PARS_CLUSTERED_TOKEN = 314,
- PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315,
- PARS_ON_TOKEN = 316,
- PARS_ASSIGN_TOKEN = 317,
- PARS_DECLARE_TOKEN = 318,
- PARS_CURSOR_TOKEN = 319,
- PARS_SQL_TOKEN = 320,
- PARS_OPEN_TOKEN = 321,
- PARS_FETCH_TOKEN = 322,
- PARS_CLOSE_TOKEN = 323,
- PARS_NOTFOUND_TOKEN = 324,
- PARS_TO_CHAR_TOKEN = 325,
- PARS_TO_NUMBER_TOKEN = 326,
- PARS_TO_BINARY_TOKEN = 327,
- PARS_BINARY_TO_NUMBER_TOKEN = 328,
- PARS_SUBSTR_TOKEN = 329,
- PARS_REPLSTR_TOKEN = 330,
- PARS_CONCAT_TOKEN = 331,
- PARS_INSTR_TOKEN = 332,
- PARS_LENGTH_TOKEN = 333,
- PARS_SYSDATE_TOKEN = 334,
- PARS_PRINTF_TOKEN = 335,
- PARS_ASSERT_TOKEN = 336,
- PARS_RND_TOKEN = 337,
- PARS_RND_STR_TOKEN = 338,
- PARS_ROW_PRINTF_TOKEN = 339,
- PARS_COMMIT_TOKEN = 340,
- PARS_ROLLBACK_TOKEN = 341,
- PARS_WORK_TOKEN = 342,
- NEG = 343
+ PARS_FIXBINARY_LIT = 261,
+ PARS_BLOB_LIT = 262,
+ PARS_NULL_LIT = 263,
+ PARS_ID_TOKEN = 264,
+ PARS_AND_TOKEN = 265,
+ PARS_OR_TOKEN = 266,
+ PARS_NOT_TOKEN = 267,
+ PARS_GE_TOKEN = 268,
+ PARS_LE_TOKEN = 269,
+ PARS_NE_TOKEN = 270,
+ PARS_PROCEDURE_TOKEN = 271,
+ PARS_IN_TOKEN = 272,
+ PARS_OUT_TOKEN = 273,
+ PARS_BINARY_TOKEN = 274,
+ PARS_BLOB_TOKEN = 275,
+ PARS_INT_TOKEN = 276,
+ PARS_INTEGER_TOKEN = 277,
+ PARS_FLOAT_TOKEN = 278,
+ PARS_CHAR_TOKEN = 279,
+ PARS_IS_TOKEN = 280,
+ PARS_BEGIN_TOKEN = 281,
+ PARS_END_TOKEN = 282,
+ PARS_IF_TOKEN = 283,
+ PARS_THEN_TOKEN = 284,
+ PARS_ELSE_TOKEN = 285,
+ PARS_ELSIF_TOKEN = 286,
+ PARS_LOOP_TOKEN = 287,
+ PARS_WHILE_TOKEN = 288,
+ PARS_RETURN_TOKEN = 289,
+ PARS_SELECT_TOKEN = 290,
+ PARS_SUM_TOKEN = 291,
+ PARS_COUNT_TOKEN = 292,
+ PARS_DISTINCT_TOKEN = 293,
+ PARS_FROM_TOKEN = 294,
+ PARS_WHERE_TOKEN = 295,
+ PARS_FOR_TOKEN = 296,
+ PARS_DDOT_TOKEN = 297,
+ PARS_CONSISTENT_TOKEN = 298,
+ PARS_READ_TOKEN = 299,
+ PARS_ORDER_TOKEN = 300,
+ PARS_BY_TOKEN = 301,
+ PARS_ASC_TOKEN = 302,
+ PARS_DESC_TOKEN = 303,
+ PARS_INSERT_TOKEN = 304,
+ PARS_INTO_TOKEN = 305,
+ PARS_VALUES_TOKEN = 306,
+ PARS_UPDATE_TOKEN = 307,
+ PARS_SET_TOKEN = 308,
+ PARS_DELETE_TOKEN = 309,
+ PARS_CURRENT_TOKEN = 310,
+ PARS_OF_TOKEN = 311,
+ PARS_CREATE_TOKEN = 312,
+ PARS_TABLE_TOKEN = 313,
+ PARS_INDEX_TOKEN = 314,
+ PARS_UNIQUE_TOKEN = 315,
+ PARS_CLUSTERED_TOKEN = 316,
+ PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 317,
+ PARS_ON_TOKEN = 318,
+ PARS_ASSIGN_TOKEN = 319,
+ PARS_DECLARE_TOKEN = 320,
+ PARS_CURSOR_TOKEN = 321,
+ PARS_SQL_TOKEN = 322,
+ PARS_OPEN_TOKEN = 323,
+ PARS_FETCH_TOKEN = 324,
+ PARS_CLOSE_TOKEN = 325,
+ PARS_NOTFOUND_TOKEN = 326,
+ PARS_TO_CHAR_TOKEN = 327,
+ PARS_TO_NUMBER_TOKEN = 328,
+ PARS_TO_BINARY_TOKEN = 329,
+ PARS_BINARY_TO_NUMBER_TOKEN = 330,
+ PARS_SUBSTR_TOKEN = 331,
+ PARS_REPLSTR_TOKEN = 332,
+ PARS_CONCAT_TOKEN = 333,
+ PARS_INSTR_TOKEN = 334,
+ PARS_LENGTH_TOKEN = 335,
+ PARS_SYSDATE_TOKEN = 336,
+ PARS_PRINTF_TOKEN = 337,
+ PARS_ASSERT_TOKEN = 338,
+ PARS_RND_TOKEN = 339,
+ PARS_RND_STR_TOKEN = 340,
+ PARS_ROW_PRINTF_TOKEN = 341,
+ PARS_COMMIT_TOKEN = 342,
+ PARS_ROLLBACK_TOKEN = 343,
+ PARS_WORK_TOKEN = 344,
+ PARS_UNSIGNED_TOKEN = 345,
+ PARS_EXIT_TOKEN = 346,
+ PARS_FUNCTION_TOKEN = 347,
+ NEG = 348
};
#endif
#define PARS_INT_LIT 258
#define PARS_FLOAT_LIT 259
#define PARS_STR_LIT 260
-#define PARS_NULL_LIT 261
-#define PARS_ID_TOKEN 262
-#define PARS_AND_TOKEN 263
-#define PARS_OR_TOKEN 264
-#define PARS_NOT_TOKEN 265
-#define PARS_GE_TOKEN 266
-#define PARS_LE_TOKEN 267
-#define PARS_NE_TOKEN 268
-#define PARS_PROCEDURE_TOKEN 269
-#define PARS_IN_TOKEN 270
-#define PARS_OUT_TOKEN 271
-#define PARS_BINARY_TOKEN 272
-#define PARS_BLOB_TOKEN 273
-#define PARS_INT_TOKEN 274
-#define PARS_INTEGER_TOKEN 275
-#define PARS_FLOAT_TOKEN 276
-#define PARS_CHAR_TOKEN 277
-#define PARS_IS_TOKEN 278
-#define PARS_BEGIN_TOKEN 279
-#define PARS_END_TOKEN 280
-#define PARS_IF_TOKEN 281
-#define PARS_THEN_TOKEN 282
-#define PARS_ELSE_TOKEN 283
-#define PARS_ELSIF_TOKEN 284
-#define PARS_LOOP_TOKEN 285
-#define PARS_WHILE_TOKEN 286
-#define PARS_RETURN_TOKEN 287
-#define PARS_SELECT_TOKEN 288
-#define PARS_SUM_TOKEN 289
-#define PARS_COUNT_TOKEN 290
-#define PARS_DISTINCT_TOKEN 291
-#define PARS_FROM_TOKEN 292
-#define PARS_WHERE_TOKEN 293
-#define PARS_FOR_TOKEN 294
-#define PARS_DDOT_TOKEN 295
-#define PARS_CONSISTENT_TOKEN 296
-#define PARS_READ_TOKEN 297
-#define PARS_ORDER_TOKEN 298
-#define PARS_BY_TOKEN 299
-#define PARS_ASC_TOKEN 300
-#define PARS_DESC_TOKEN 301
-#define PARS_INSERT_TOKEN 302
-#define PARS_INTO_TOKEN 303
-#define PARS_VALUES_TOKEN 304
-#define PARS_UPDATE_TOKEN 305
-#define PARS_SET_TOKEN 306
-#define PARS_DELETE_TOKEN 307
-#define PARS_CURRENT_TOKEN 308
-#define PARS_OF_TOKEN 309
-#define PARS_CREATE_TOKEN 310
-#define PARS_TABLE_TOKEN 311
-#define PARS_INDEX_TOKEN 312
-#define PARS_UNIQUE_TOKEN 313
-#define PARS_CLUSTERED_TOKEN 314
-#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315
-#define PARS_ON_TOKEN 316
-#define PARS_ASSIGN_TOKEN 317
-#define PARS_DECLARE_TOKEN 318
-#define PARS_CURSOR_TOKEN 319
-#define PARS_SQL_TOKEN 320
-#define PARS_OPEN_TOKEN 321
-#define PARS_FETCH_TOKEN 322
-#define PARS_CLOSE_TOKEN 323
-#define PARS_NOTFOUND_TOKEN 324
-#define PARS_TO_CHAR_TOKEN 325
-#define PARS_TO_NUMBER_TOKEN 326
-#define PARS_TO_BINARY_TOKEN 327
-#define PARS_BINARY_TO_NUMBER_TOKEN 328
-#define PARS_SUBSTR_TOKEN 329
-#define PARS_REPLSTR_TOKEN 330
-#define PARS_CONCAT_TOKEN 331
-#define PARS_INSTR_TOKEN 332
-#define PARS_LENGTH_TOKEN 333
-#define PARS_SYSDATE_TOKEN 334
-#define PARS_PRINTF_TOKEN 335
-#define PARS_ASSERT_TOKEN 336
-#define PARS_RND_TOKEN 337
-#define PARS_RND_STR_TOKEN 338
-#define PARS_ROW_PRINTF_TOKEN 339
-#define PARS_COMMIT_TOKEN 340
-#define PARS_ROLLBACK_TOKEN 341
-#define PARS_WORK_TOKEN 342
-#define NEG 343
+#define PARS_FIXBINARY_LIT 261
+#define PARS_BLOB_LIT 262
+#define PARS_NULL_LIT 263
+#define PARS_ID_TOKEN 264
+#define PARS_AND_TOKEN 265
+#define PARS_OR_TOKEN 266
+#define PARS_NOT_TOKEN 267
+#define PARS_GE_TOKEN 268
+#define PARS_LE_TOKEN 269
+#define PARS_NE_TOKEN 270
+#define PARS_PROCEDURE_TOKEN 271
+#define PARS_IN_TOKEN 272
+#define PARS_OUT_TOKEN 273
+#define PARS_BINARY_TOKEN 274
+#define PARS_BLOB_TOKEN 275
+#define PARS_INT_TOKEN 276
+#define PARS_INTEGER_TOKEN 277
+#define PARS_FLOAT_TOKEN 278
+#define PARS_CHAR_TOKEN 279
+#define PARS_IS_TOKEN 280
+#define PARS_BEGIN_TOKEN 281
+#define PARS_END_TOKEN 282
+#define PARS_IF_TOKEN 283
+#define PARS_THEN_TOKEN 284
+#define PARS_ELSE_TOKEN 285
+#define PARS_ELSIF_TOKEN 286
+#define PARS_LOOP_TOKEN 287
+#define PARS_WHILE_TOKEN 288
+#define PARS_RETURN_TOKEN 289
+#define PARS_SELECT_TOKEN 290
+#define PARS_SUM_TOKEN 291
+#define PARS_COUNT_TOKEN 292
+#define PARS_DISTINCT_TOKEN 293
+#define PARS_FROM_TOKEN 294
+#define PARS_WHERE_TOKEN 295
+#define PARS_FOR_TOKEN 296
+#define PARS_DDOT_TOKEN 297
+#define PARS_CONSISTENT_TOKEN 298
+#define PARS_READ_TOKEN 299
+#define PARS_ORDER_TOKEN 300
+#define PARS_BY_TOKEN 301
+#define PARS_ASC_TOKEN 302
+#define PARS_DESC_TOKEN 303
+#define PARS_INSERT_TOKEN 304
+#define PARS_INTO_TOKEN 305
+#define PARS_VALUES_TOKEN 306
+#define PARS_UPDATE_TOKEN 307
+#define PARS_SET_TOKEN 308
+#define PARS_DELETE_TOKEN 309
+#define PARS_CURRENT_TOKEN 310
+#define PARS_OF_TOKEN 311
+#define PARS_CREATE_TOKEN 312
+#define PARS_TABLE_TOKEN 313
+#define PARS_INDEX_TOKEN 314
+#define PARS_UNIQUE_TOKEN 315
+#define PARS_CLUSTERED_TOKEN 316
+#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 317
+#define PARS_ON_TOKEN 318
+#define PARS_ASSIGN_TOKEN 319
+#define PARS_DECLARE_TOKEN 320
+#define PARS_CURSOR_TOKEN 321
+#define PARS_SQL_TOKEN 322
+#define PARS_OPEN_TOKEN 323
+#define PARS_FETCH_TOKEN 324
+#define PARS_CLOSE_TOKEN 325
+#define PARS_NOTFOUND_TOKEN 326
+#define PARS_TO_CHAR_TOKEN 327
+#define PARS_TO_NUMBER_TOKEN 328
+#define PARS_TO_BINARY_TOKEN 329
+#define PARS_BINARY_TO_NUMBER_TOKEN 330
+#define PARS_SUBSTR_TOKEN 331
+#define PARS_REPLSTR_TOKEN 332
+#define PARS_CONCAT_TOKEN 333
+#define PARS_INSTR_TOKEN 334
+#define PARS_LENGTH_TOKEN 335
+#define PARS_SYSDATE_TOKEN 336
+#define PARS_PRINTF_TOKEN 337
+#define PARS_ASSERT_TOKEN 338
+#define PARS_RND_TOKEN 339
+#define PARS_RND_STR_TOKEN 340
+#define PARS_ROW_PRINTF_TOKEN 341
+#define PARS_COMMIT_TOKEN 342
+#define PARS_ROLLBACK_TOKEN 343
+#define PARS_WORK_TOKEN 344
+#define PARS_UNSIGNED_TOKEN 345
+#define PARS_EXIT_TOKEN 346
+#define PARS_FUNCTION_TOKEN 347
+#define NEG 348
@@ -279,7 +289,7 @@ typedef int YYSTYPE;
/* Line 214 of yacc.c. */
-#line 283 "pars0grm.tab.c"
+#line 293 "pars0grm.tab.c"
#if ! defined (yyoverflow) || YYERROR_VERBOSE
@@ -383,22 +393,22 @@ union yyalloc
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 95
+#define YYFINAL 99
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 734
+#define YYLAST 756
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 104
+#define YYNTOKENS 109
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 64
+#define YYNNTS 69
/* YYNRULES -- Number of rules. */
-#define YYNRULES 164
+#define YYNRULES 175
/* YYNRULES -- Number of states. */
-#define YYNSTATES 321
+#define YYNSTATES 337
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 343
+#define YYMAXUTOK 348
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -409,16 +419,16 @@ static const unsigned char yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 96, 2, 2,
- 98, 99, 93, 92, 101, 91, 2, 94, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 97,
- 89, 88, 90, 100, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 101, 2, 2,
+ 103, 104, 98, 97, 106, 96, 2, 99, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 102,
+ 94, 93, 95, 105, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 102, 2, 103, 2, 2, 2, 2,
+ 2, 2, 2, 107, 2, 108, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -440,7 +450,7 @@ static const unsigned char yytranslate[] =
55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 95
+ 85, 86, 87, 88, 89, 90, 91, 92, 100
};
#if YYDEBUG
@@ -450,100 +460,105 @@ static const unsigned short int yyprhs[] =
{
0, 0, 3, 6, 8, 11, 14, 17, 20, 23,
26, 29, 32, 35, 38, 41, 44, 47, 50, 53,
- 56, 59, 62, 65, 68, 70, 73, 75, 80, 82,
- 84, 86, 88, 90, 94, 98, 102, 106, 109, 113,
- 117, 121, 125, 129, 133, 137, 141, 145, 148, 152,
- 156, 158, 160, 162, 164, 166, 168, 170, 172, 174,
- 176, 178, 179, 181, 185, 192, 197, 199, 201, 203,
- 205, 209, 210, 212, 216, 217, 219, 223, 225, 230,
- 236, 241, 242, 244, 248, 250, 254, 256, 257, 260,
- 261, 264, 265, 268, 269, 271, 273, 274, 279, 288,
- 292, 298, 301, 305, 307, 311, 316, 321, 324, 327,
- 331, 334, 337, 340, 344, 349, 351, 354, 355, 358,
- 360, 368, 375, 386, 388, 391, 394, 399, 404, 406,
- 410, 411, 415, 416, 419, 420, 422, 430, 432, 436,
- 437, 439, 440, 442, 453, 456, 459, 461, 463, 465,
- 467, 469, 473, 477, 478, 480, 484, 488, 489, 491,
- 494, 501, 502, 504, 507
+ 56, 59, 62, 65, 68, 71, 73, 76, 78, 83,
+ 85, 87, 89, 91, 93, 95, 97, 101, 105, 109,
+ 113, 116, 120, 124, 128, 132, 136, 140, 144, 148,
+ 152, 155, 159, 163, 165, 167, 169, 171, 173, 175,
+ 177, 179, 181, 183, 185, 186, 188, 192, 199, 204,
+ 206, 208, 210, 214, 216, 220, 221, 223, 227, 228,
+ 230, 234, 236, 241, 247, 252, 253, 255, 259, 261,
+ 265, 267, 268, 271, 272, 275, 276, 279, 280, 282,
+ 284, 285, 290, 299, 303, 309, 312, 316, 318, 322,
+ 327, 332, 335, 338, 342, 345, 348, 351, 355, 360,
+ 362, 365, 366, 369, 371, 379, 386, 397, 399, 401,
+ 404, 407, 412, 417, 423, 425, 429, 430, 434, 435,
+ 437, 438, 441, 442, 444, 452, 454, 458, 459, 461,
+ 462, 464, 475, 478, 481, 483, 485, 487, 489, 491,
+ 495, 499, 500, 502, 506, 510, 511, 513, 516, 523,
+ 528, 530, 532, 533, 535, 538
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const short int yyrhs[] =
{
- 105, 0, -1, 167, 97, -1, 110, -1, 111, 97,
- -1, 142, 97, -1, 143, 97, -1, 141, 97, -1,
- 144, 97, -1, 137, 97, -1, 124, 97, -1, 126,
- 97, -1, 136, 97, -1, 134, 97, -1, 135, 97,
- -1, 131, 97, -1, 132, 97, -1, 145, 97, -1,
- 147, 97, -1, 146, 97, -1, 158, 97, -1, 159,
- 97, -1, 153, 97, -1, 157, 97, -1, 105, -1,
- 106, 105, -1, 7, -1, 108, 98, 115, 99, -1,
- 3, -1, 4, -1, 5, -1, 6, -1, 65, -1,
- 107, 92, 107, -1, 107, 91, 107, -1, 107, 93,
- 107, -1, 107, 94, 107, -1, 91, 107, -1, 98,
- 107, 99, -1, 107, 88, 107, -1, 107, 89, 107,
- -1, 107, 90, 107, -1, 107, 11, 107, -1, 107,
- 12, 107, -1, 107, 13, 107, -1, 107, 8, 107,
- -1, 107, 9, 107, -1, 10, 107, -1, 7, 96,
- 69, -1, 65, 96, 69, -1, 70, -1, 71, -1,
- 72, -1, 73, -1, 74, -1, 76, -1, 77, -1,
- 78, -1, 79, -1, 82, -1, 83, -1, -1, 100,
- -1, 109, 101, 100, -1, 102, 7, 98, 109, 99,
- 103, -1, 112, 98, 115, 99, -1, 75, -1, 80,
- -1, 81, -1, 7, -1, 113, 101, 7, -1, -1,
- 7, -1, 114, 101, 7, -1, -1, 107, -1, 115,
- 101, 107, -1, 107, -1, 35, 98, 93, 99, -1,
- 35, 98, 36, 7, 99, -1, 34, 98, 107, 99,
- -1, -1, 116, -1, 117, 101, 116, -1, 93, -1,
- 117, 48, 114, -1, 117, -1, -1, 38, 107, -1,
- -1, 39, 50, -1, -1, 41, 42, -1, -1, 45,
- -1, 46, -1, -1, 43, 44, 7, 122, -1, 33,
- 118, 37, 113, 119, 120, 121, 123, -1, 47, 48,
- 7, -1, 125, 49, 98, 115, 99, -1, 125, 124,
- -1, 7, 88, 107, -1, 127, -1, 128, 101, 127,
- -1, 38, 53, 54, 7, -1, 50, 7, 51, 128,
- -1, 130, 119, -1, 130, 129, -1, 52, 37, 7,
- -1, 133, 119, -1, 133, 129, -1, 84, 124, -1,
- 7, 62, 107, -1, 29, 107, 27, 106, -1, 138,
- -1, 139, 138, -1, -1, 28, 106, -1, 139, -1,
- 26, 107, 27, 106, 140, 25, 26, -1, 31, 107,
- 30, 106, 25, 30, -1, 39, 7, 15, 107, 40,
- 107, 30, 106, 25, 30, -1, 32, -1, 66, 7,
- -1, 68, 7, -1, 67, 7, 48, 114, -1, 7,
- 160, 150, 151, -1, 148, -1, 149, 101, 148, -1,
- -1, 98, 3, 99, -1, -1, 10, 6, -1, -1,
- 60, -1, 55, 56, 7, 98, 149, 99, 152, -1,
- 7, -1, 154, 101, 7, -1, -1, 58, -1, -1,
- 59, -1, 55, 155, 156, 57, 7, 61, 7, 98,
- 154, 99, -1, 85, 87, -1, 86, 87, -1, 19,
- -1, 20, -1, 22, -1, 17, -1, 18, -1, 7,
- 15, 160, -1, 7, 16, 160, -1, -1, 161, -1,
- 162, 101, 161, -1, 7, 160, 97, -1, -1, 163,
- -1, 164, 163, -1, 63, 64, 7, 23, 124, 97,
- -1, -1, 165, -1, 166, 165, -1, 14, 7, 98,
- 162, 99, 23, 164, 166, 24, 106, 25, -1
+ 110, 0, -1, 177, 102, -1, 115, -1, 116, 102,
+ -1, 148, 102, -1, 149, 102, -1, 150, 102, -1,
+ 147, 102, -1, 151, 102, -1, 143, 102, -1, 130,
+ 102, -1, 132, 102, -1, 142, 102, -1, 140, 102,
+ -1, 141, 102, -1, 137, 102, -1, 138, 102, -1,
+ 152, 102, -1, 154, 102, -1, 153, 102, -1, 166,
+ 102, -1, 167, 102, -1, 161, 102, -1, 165, 102,
+ -1, 110, -1, 111, 110, -1, 9, -1, 113, 103,
+ 121, 104, -1, 3, -1, 4, -1, 5, -1, 6,
+ -1, 7, -1, 8, -1, 67, -1, 112, 97, 112,
+ -1, 112, 96, 112, -1, 112, 98, 112, -1, 112,
+ 99, 112, -1, 96, 112, -1, 103, 112, 104, -1,
+ 112, 93, 112, -1, 112, 94, 112, -1, 112, 95,
+ 112, -1, 112, 13, 112, -1, 112, 14, 112, -1,
+ 112, 15, 112, -1, 112, 10, 112, -1, 112, 11,
+ 112, -1, 12, 112, -1, 9, 101, 71, -1, 67,
+ 101, 71, -1, 72, -1, 73, -1, 74, -1, 75,
+ -1, 76, -1, 78, -1, 79, -1, 80, -1, 81,
+ -1, 84, -1, 85, -1, -1, 105, -1, 114, 106,
+ 105, -1, 107, 9, 103, 114, 104, 108, -1, 117,
+ 103, 121, 104, -1, 77, -1, 82, -1, 83, -1,
+ 9, 103, 104, -1, 9, -1, 119, 106, 9, -1,
+ -1, 9, -1, 120, 106, 9, -1, -1, 112, -1,
+ 121, 106, 112, -1, 112, -1, 37, 103, 98, 104,
+ -1, 37, 103, 38, 9, 104, -1, 36, 103, 112,
+ 104, -1, -1, 122, -1, 123, 106, 122, -1, 98,
+ -1, 123, 50, 120, -1, 123, -1, -1, 40, 112,
+ -1, -1, 41, 52, -1, -1, 43, 44, -1, -1,
+ 47, -1, 48, -1, -1, 45, 46, 9, 128, -1,
+ 35, 124, 39, 119, 125, 126, 127, 129, -1, 49,
+ 50, 9, -1, 131, 51, 103, 121, 104, -1, 131,
+ 130, -1, 9, 93, 112, -1, 133, -1, 134, 106,
+ 133, -1, 40, 55, 56, 9, -1, 52, 9, 53,
+ 134, -1, 136, 125, -1, 136, 135, -1, 54, 39,
+ 9, -1, 139, 125, -1, 139, 135, -1, 86, 130,
+ -1, 9, 64, 112, -1, 31, 112, 29, 111, -1,
+ 144, -1, 145, 144, -1, -1, 30, 111, -1, 145,
+ -1, 28, 112, 29, 111, 146, 27, 28, -1, 33,
+ 112, 32, 111, 27, 32, -1, 41, 9, 17, 112,
+ 42, 112, 32, 111, 27, 32, -1, 91, -1, 34,
+ -1, 68, 9, -1, 70, 9, -1, 69, 9, 50,
+ 120, -1, 69, 9, 50, 118, -1, 9, 168, 157,
+ 158, 159, -1, 155, -1, 156, 106, 155, -1, -1,
+ 103, 3, 104, -1, -1, 90, -1, -1, 12, 8,
+ -1, -1, 62, -1, 57, 58, 9, 103, 156, 104,
+ 160, -1, 9, -1, 162, 106, 9, -1, -1, 60,
+ -1, -1, 61, -1, 57, 163, 164, 59, 9, 63,
+ 9, 103, 162, 104, -1, 87, 89, -1, 88, 89,
+ -1, 21, -1, 22, -1, 24, -1, 19, -1, 20,
+ -1, 9, 17, 168, -1, 9, 18, 168, -1, -1,
+ 169, -1, 170, 106, 169, -1, 9, 168, 102, -1,
+ -1, 171, -1, 172, 171, -1, 65, 66, 9, 25,
+ 130, 102, -1, 65, 92, 9, 102, -1, 173, -1,
+ 174, -1, -1, 175, -1, 176, 175, -1, 16, 9,
+ 103, 170, 104, 25, 172, 176, 26, 111, 27, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const unsigned short int yyrline[] =
{
- 0, 131, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
- 149, 150, 151, 152, 156, 157, 162, 163, 165, 166,
- 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
- 177, 178, 179, 180, 181, 182, 183, 184, 185, 187,
- 192, 193, 194, 195, 197, 198, 199, 200, 201, 202,
- 203, 206, 208, 209, 213, 218, 223, 224, 225, 229,
- 230, 235, 236, 237, 242, 243, 244, 248, 249, 254,
- 260, 267, 268, 269, 274, 276, 278, 282, 283, 287,
- 288, 293, 294, 299, 300, 301, 305, 306, 311, 321,
- 326, 328, 333, 337, 338, 343, 349, 356, 361, 366,
- 372, 377, 382, 387, 392, 398, 399, 404, 405, 407,
- 411, 418, 424, 432, 436, 442, 448, 453, 458, 459,
- 464, 465, 470, 471, 477, 478, 484, 490, 491, 496,
- 497, 501, 502, 506, 514, 519, 524, 525, 526, 527,
- 528, 532, 535, 541, 542, 543, 548, 552, 554, 555,
- 559, 564, 566, 567, 571
+ 0, 136, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 162, 163, 168, 169, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 195, 200, 201, 202, 203, 205, 206, 207,
+ 208, 209, 210, 211, 214, 216, 217, 221, 226, 231,
+ 232, 233, 237, 241, 242, 247, 248, 249, 254, 255,
+ 256, 260, 261, 266, 272, 279, 280, 281, 286, 288,
+ 290, 294, 295, 299, 300, 305, 306, 311, 312, 313,
+ 317, 318, 323, 333, 338, 340, 345, 349, 350, 355,
+ 361, 368, 373, 378, 384, 389, 394, 399, 404, 410,
+ 411, 416, 417, 419, 423, 430, 436, 444, 448, 452,
+ 458, 464, 466, 471, 476, 477, 482, 483, 488, 489,
+ 495, 496, 502, 503, 509, 515, 516, 521, 522, 526,
+ 527, 531, 539, 544, 549, 550, 551, 552, 553, 557,
+ 560, 566, 567, 568, 573, 577, 579, 580, 584, 590,
+ 595, 596, 599, 601, 602, 606
};
#endif
@@ -553,38 +568,40 @@ static const unsigned short int yyrline[] =
static const char *const yytname[] =
{
"$end", "error", "$undefined", "PARS_INT_LIT", "PARS_FLOAT_LIT",
- "PARS_STR_LIT", "PARS_NULL_LIT", "PARS_ID_TOKEN", "PARS_AND_TOKEN",
- "PARS_OR_TOKEN", "PARS_NOT_TOKEN", "PARS_GE_TOKEN", "PARS_LE_TOKEN",
- "PARS_NE_TOKEN", "PARS_PROCEDURE_TOKEN", "PARS_IN_TOKEN",
- "PARS_OUT_TOKEN", "PARS_BINARY_TOKEN", "PARS_BLOB_TOKEN",
- "PARS_INT_TOKEN", "PARS_INTEGER_TOKEN", "PARS_FLOAT_TOKEN",
- "PARS_CHAR_TOKEN", "PARS_IS_TOKEN", "PARS_BEGIN_TOKEN", "PARS_END_TOKEN",
- "PARS_IF_TOKEN", "PARS_THEN_TOKEN", "PARS_ELSE_TOKEN",
- "PARS_ELSIF_TOKEN", "PARS_LOOP_TOKEN", "PARS_WHILE_TOKEN",
- "PARS_RETURN_TOKEN", "PARS_SELECT_TOKEN", "PARS_SUM_TOKEN",
- "PARS_COUNT_TOKEN", "PARS_DISTINCT_TOKEN", "PARS_FROM_TOKEN",
- "PARS_WHERE_TOKEN", "PARS_FOR_TOKEN", "PARS_DDOT_TOKEN",
- "PARS_CONSISTENT_TOKEN", "PARS_READ_TOKEN", "PARS_ORDER_TOKEN",
- "PARS_BY_TOKEN", "PARS_ASC_TOKEN", "PARS_DESC_TOKEN",
- "PARS_INSERT_TOKEN", "PARS_INTO_TOKEN", "PARS_VALUES_TOKEN",
- "PARS_UPDATE_TOKEN", "PARS_SET_TOKEN", "PARS_DELETE_TOKEN",
- "PARS_CURRENT_TOKEN", "PARS_OF_TOKEN", "PARS_CREATE_TOKEN",
- "PARS_TABLE_TOKEN", "PARS_INDEX_TOKEN", "PARS_UNIQUE_TOKEN",
- "PARS_CLUSTERED_TOKEN", "PARS_DOES_NOT_FIT_IN_MEM_TOKEN",
- "PARS_ON_TOKEN", "PARS_ASSIGN_TOKEN", "PARS_DECLARE_TOKEN",
- "PARS_CURSOR_TOKEN", "PARS_SQL_TOKEN", "PARS_OPEN_TOKEN",
- "PARS_FETCH_TOKEN", "PARS_CLOSE_TOKEN", "PARS_NOTFOUND_TOKEN",
- "PARS_TO_CHAR_TOKEN", "PARS_TO_NUMBER_TOKEN", "PARS_TO_BINARY_TOKEN",
- "PARS_BINARY_TO_NUMBER_TOKEN", "PARS_SUBSTR_TOKEN", "PARS_REPLSTR_TOKEN",
- "PARS_CONCAT_TOKEN", "PARS_INSTR_TOKEN", "PARS_LENGTH_TOKEN",
- "PARS_SYSDATE_TOKEN", "PARS_PRINTF_TOKEN", "PARS_ASSERT_TOKEN",
- "PARS_RND_TOKEN", "PARS_RND_STR_TOKEN", "PARS_ROW_PRINTF_TOKEN",
- "PARS_COMMIT_TOKEN", "PARS_ROLLBACK_TOKEN", "PARS_WORK_TOKEN", "'='",
- "'<'", "'>'", "'-'", "'+'", "'*'", "'/'", "NEG", "'%'", "';'", "'('",
- "')'", "'?'", "','", "'{'", "'}'", "$accept", "statement",
- "statement_list", "exp", "function_name", "question_mark_list",
- "stored_procedure_call", "predefined_procedure_call",
- "predefined_procedure_name", "table_list", "variable_list", "exp_list",
+ "PARS_STR_LIT", "PARS_FIXBINARY_LIT", "PARS_BLOB_LIT", "PARS_NULL_LIT",
+ "PARS_ID_TOKEN", "PARS_AND_TOKEN", "PARS_OR_TOKEN", "PARS_NOT_TOKEN",
+ "PARS_GE_TOKEN", "PARS_LE_TOKEN", "PARS_NE_TOKEN",
+ "PARS_PROCEDURE_TOKEN", "PARS_IN_TOKEN", "PARS_OUT_TOKEN",
+ "PARS_BINARY_TOKEN", "PARS_BLOB_TOKEN", "PARS_INT_TOKEN",
+ "PARS_INTEGER_TOKEN", "PARS_FLOAT_TOKEN", "PARS_CHAR_TOKEN",
+ "PARS_IS_TOKEN", "PARS_BEGIN_TOKEN", "PARS_END_TOKEN", "PARS_IF_TOKEN",
+ "PARS_THEN_TOKEN", "PARS_ELSE_TOKEN", "PARS_ELSIF_TOKEN",
+ "PARS_LOOP_TOKEN", "PARS_WHILE_TOKEN", "PARS_RETURN_TOKEN",
+ "PARS_SELECT_TOKEN", "PARS_SUM_TOKEN", "PARS_COUNT_TOKEN",
+ "PARS_DISTINCT_TOKEN", "PARS_FROM_TOKEN", "PARS_WHERE_TOKEN",
+ "PARS_FOR_TOKEN", "PARS_DDOT_TOKEN", "PARS_CONSISTENT_TOKEN",
+ "PARS_READ_TOKEN", "PARS_ORDER_TOKEN", "PARS_BY_TOKEN", "PARS_ASC_TOKEN",
+ "PARS_DESC_TOKEN", "PARS_INSERT_TOKEN", "PARS_INTO_TOKEN",
+ "PARS_VALUES_TOKEN", "PARS_UPDATE_TOKEN", "PARS_SET_TOKEN",
+ "PARS_DELETE_TOKEN", "PARS_CURRENT_TOKEN", "PARS_OF_TOKEN",
+ "PARS_CREATE_TOKEN", "PARS_TABLE_TOKEN", "PARS_INDEX_TOKEN",
+ "PARS_UNIQUE_TOKEN", "PARS_CLUSTERED_TOKEN",
+ "PARS_DOES_NOT_FIT_IN_MEM_TOKEN", "PARS_ON_TOKEN", "PARS_ASSIGN_TOKEN",
+ "PARS_DECLARE_TOKEN", "PARS_CURSOR_TOKEN", "PARS_SQL_TOKEN",
+ "PARS_OPEN_TOKEN", "PARS_FETCH_TOKEN", "PARS_CLOSE_TOKEN",
+ "PARS_NOTFOUND_TOKEN", "PARS_TO_CHAR_TOKEN", "PARS_TO_NUMBER_TOKEN",
+ "PARS_TO_BINARY_TOKEN", "PARS_BINARY_TO_NUMBER_TOKEN",
+ "PARS_SUBSTR_TOKEN", "PARS_REPLSTR_TOKEN", "PARS_CONCAT_TOKEN",
+ "PARS_INSTR_TOKEN", "PARS_LENGTH_TOKEN", "PARS_SYSDATE_TOKEN",
+ "PARS_PRINTF_TOKEN", "PARS_ASSERT_TOKEN", "PARS_RND_TOKEN",
+ "PARS_RND_STR_TOKEN", "PARS_ROW_PRINTF_TOKEN", "PARS_COMMIT_TOKEN",
+ "PARS_ROLLBACK_TOKEN", "PARS_WORK_TOKEN", "PARS_UNSIGNED_TOKEN",
+ "PARS_EXIT_TOKEN", "PARS_FUNCTION_TOKEN", "'='", "'<'", "'>'", "'-'",
+ "'+'", "'*'", "'/'", "NEG", "'%'", "';'", "'('", "')'", "'?'", "','",
+ "'{'", "'}'", "$accept", "statement", "statement_list", "exp",
+ "function_name", "question_mark_list", "stored_procedure_call",
+ "predefined_procedure_call", "predefined_procedure_name",
+ "user_function_call", "table_list", "variable_list", "exp_list",
"select_item", "select_item_list", "select_list", "search_condition",
"for_update_clause", "consistent_read_clause", "order_direction",
"order_by_clause", "select_statement", "insert_statement_start",
@@ -594,15 +611,16 @@ static const char *const yytname[] =
"delete_statement_start", "delete_statement_searched",
"delete_statement_positioned", "row_printf_statement",
"assignment_statement", "elsif_element", "elsif_list", "else_part",
- "if_statement", "while_statement", "for_statement", "return_statement",
- "open_cursor_statement", "close_cursor_statement", "fetch_statement",
- "column_def", "column_def_list", "opt_column_len", "opt_not_null",
- "not_fit_in_memory", "create_table", "column_list", "unique_def",
- "clustered_def", "create_index", "commit_statement",
- "rollback_statement", "type_name", "parameter_declaration",
- "parameter_declaration_list", "variable_declaration",
- "variable_declaration_list", "cursor_declaration", "declaration_list",
- "procedure_definition", 0
+ "if_statement", "while_statement", "for_statement", "exit_statement",
+ "return_statement", "open_cursor_statement", "close_cursor_statement",
+ "fetch_statement", "column_def", "column_def_list", "opt_column_len",
+ "opt_unsigned", "opt_not_null", "not_fit_in_memory", "create_table",
+ "column_list", "unique_def", "clustered_def", "create_index",
+ "commit_statement", "rollback_statement", "type_name",
+ "parameter_declaration", "parameter_declaration_list",
+ "variable_declaration", "variable_declaration_list",
+ "cursor_declaration", "function_declaration", "declaration",
+ "declaration_list", "procedure_definition", 0
};
#endif
@@ -619,32 +637,33 @@ static const unsigned short int yytoknum[] =
305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
- 335, 336, 337, 338, 339, 340, 341, 342, 61, 60,
- 62, 45, 43, 42, 47, 343, 37, 59, 40, 41,
- 63, 44, 123, 125
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 61, 60, 62, 45, 43, 42, 47,
+ 348, 37, 59, 40, 41, 63, 44, 123, 125
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const unsigned char yyr1[] =
{
- 0, 104, 105, 105, 105, 105, 105, 105, 105, 105,
- 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
- 105, 105, 105, 105, 106, 106, 107, 107, 107, 107,
- 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
- 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
- 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
- 108, 109, 109, 109, 110, 111, 112, 112, 112, 113,
- 113, 114, 114, 114, 115, 115, 115, 116, 116, 116,
- 116, 117, 117, 117, 118, 118, 118, 119, 119, 120,
- 120, 121, 121, 122, 122, 122, 123, 123, 124, 125,
- 126, 126, 127, 128, 128, 129, 130, 131, 132, 133,
- 134, 135, 136, 137, 138, 139, 139, 140, 140, 140,
- 141, 142, 143, 144, 145, 146, 147, 148, 149, 149,
- 150, 150, 151, 151, 152, 152, 153, 154, 154, 155,
- 155, 156, 156, 157, 158, 159, 160, 160, 160, 160,
- 160, 161, 161, 162, 162, 162, 163, 164, 164, 164,
- 165, 166, 166, 166, 167
+ 0, 109, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 111, 111, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
+ 112, 112, 112, 113, 113, 113, 113, 113, 113, 113,
+ 113, 113, 113, 113, 114, 114, 114, 115, 116, 117,
+ 117, 117, 118, 119, 119, 120, 120, 120, 121, 121,
+ 121, 122, 122, 122, 122, 123, 123, 123, 124, 124,
+ 124, 125, 125, 126, 126, 127, 127, 128, 128, 128,
+ 129, 129, 130, 131, 132, 132, 133, 134, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 145, 146, 146, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 154, 155, 156, 156, 157, 157, 158, 158,
+ 159, 159, 160, 160, 161, 162, 162, 163, 163, 164,
+ 164, 165, 166, 167, 168, 168, 168, 168, 168, 169,
+ 169, 170, 170, 170, 171, 172, 172, 172, 173, 174,
+ 175, 175, 176, 176, 176, 177
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -652,21 +671,22 @@ static const unsigned char yyr2[] =
{
0, 2, 2, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 1, 2, 1, 4, 1, 1,
- 1, 1, 1, 3, 3, 3, 3, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 2, 3, 3,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 3, 6, 4, 1, 1, 1, 1,
- 3, 0, 1, 3, 0, 1, 3, 1, 4, 5,
- 4, 0, 1, 3, 1, 3, 1, 0, 2, 0,
- 2, 0, 2, 0, 1, 1, 0, 4, 8, 3,
- 5, 2, 3, 1, 3, 4, 4, 2, 2, 3,
- 2, 2, 2, 3, 4, 1, 2, 0, 2, 1,
- 7, 6, 10, 1, 2, 2, 4, 4, 1, 3,
- 0, 3, 0, 2, 0, 1, 7, 1, 3, 0,
- 1, 0, 1, 10, 2, 2, 1, 1, 1, 1,
- 1, 3, 3, 0, 1, 3, 3, 0, 1, 2,
- 6, 0, 1, 2, 11
+ 2, 2, 2, 2, 2, 1, 2, 1, 4, 1,
+ 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 3, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 3, 6, 4, 1,
+ 1, 1, 3, 1, 3, 0, 1, 3, 0, 1,
+ 3, 1, 4, 5, 4, 0, 1, 3, 1, 3,
+ 1, 0, 2, 0, 2, 0, 2, 0, 1, 1,
+ 0, 4, 8, 3, 5, 2, 3, 1, 3, 4,
+ 4, 2, 2, 3, 2, 2, 2, 3, 4, 1,
+ 2, 0, 2, 1, 7, 6, 10, 1, 1, 2,
+ 2, 4, 4, 5, 1, 3, 0, 3, 0, 1,
+ 0, 2, 0, 1, 7, 1, 3, 0, 1, 0,
+ 1, 10, 2, 2, 1, 1, 1, 1, 1, 3,
+ 3, 0, 1, 3, 3, 0, 1, 2, 6, 4,
+ 1, 1, 0, 1, 2, 11
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -674,103 +694,105 @@ static const unsigned char yyr2[] =
means the default is an error. */
static const unsigned char yydefact[] =
{
- 0, 0, 0, 0, 0, 123, 81, 0, 0, 0,
- 0, 139, 0, 0, 0, 66, 67, 68, 0, 0,
- 0, 0, 0, 3, 0, 0, 0, 0, 0, 87,
- 0, 0, 87, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 85, 0, 0, 0,
+ 0, 147, 0, 0, 0, 69, 70, 71, 0, 0,
+ 0, 127, 0, 0, 3, 0, 0, 0, 0, 0,
+ 91, 0, 0, 91, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 28, 29, 30, 31, 26, 0, 32, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 0,
- 0, 0, 0, 0, 0, 0, 84, 77, 82, 86,
- 0, 0, 0, 0, 0, 0, 140, 141, 124, 0,
- 125, 112, 144, 145, 0, 1, 4, 74, 10, 0,
- 101, 11, 0, 107, 108, 15, 16, 110, 111, 13,
- 14, 12, 9, 7, 5, 6, 8, 17, 19, 18,
- 22, 23, 20, 21, 2, 113, 153, 0, 47, 0,
- 37, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 74, 0, 0, 0, 71,
- 0, 0, 0, 99, 0, 109, 0, 142, 0, 71,
- 61, 75, 0, 74, 0, 88, 0, 154, 0, 48,
- 49, 38, 45, 46, 42, 43, 44, 24, 117, 39,
- 40, 41, 34, 33, 35, 36, 0, 0, 0, 0,
- 0, 72, 85, 83, 69, 87, 0, 0, 103, 106,
- 0, 0, 126, 62, 0, 65, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 25, 115, 119, 0, 27,
- 0, 80, 0, 78, 0, 0, 0, 89, 0, 0,
- 0, 0, 128, 0, 0, 0, 0, 76, 100, 105,
- 149, 150, 146, 147, 148, 151, 152, 157, 155, 118,
- 0, 116, 0, 121, 79, 73, 70, 0, 91, 0,
- 102, 104, 130, 134, 0, 0, 64, 63, 0, 158,
- 161, 0, 120, 90, 0, 96, 0, 0, 132, 135,
- 136, 129, 0, 0, 0, 159, 162, 0, 114, 92,
- 0, 98, 0, 0, 0, 127, 0, 156, 0, 0,
- 163, 0, 0, 131, 133, 137, 0, 0, 0, 93,
- 122, 143, 0, 0, 164, 94, 95, 97, 138, 0,
- 160
+ 0, 0, 0, 29, 30, 31, 32, 33, 34, 27,
+ 0, 35, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 0, 0, 0, 0, 0, 0, 0,
+ 88, 81, 86, 90, 0, 0, 0, 0, 0, 0,
+ 148, 149, 129, 0, 130, 116, 152, 153, 0, 1,
+ 4, 78, 11, 0, 105, 12, 0, 111, 112, 16,
+ 17, 114, 115, 14, 15, 13, 10, 8, 5, 6,
+ 7, 9, 18, 20, 19, 23, 24, 21, 22, 2,
+ 117, 161, 0, 50, 0, 40, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 78, 0, 0, 0, 75, 0, 0, 0, 103, 0,
+ 113, 0, 150, 0, 75, 64, 79, 0, 78, 0,
+ 92, 0, 162, 0, 51, 52, 41, 48, 49, 45,
+ 46, 47, 25, 121, 42, 43, 44, 37, 36, 38,
+ 39, 0, 0, 0, 0, 0, 76, 89, 87, 73,
+ 91, 0, 0, 107, 110, 0, 0, 76, 132, 131,
+ 65, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 26, 119, 123, 0, 28, 0, 84, 0,
+ 82, 0, 0, 0, 93, 0, 0, 0, 0, 134,
+ 0, 0, 0, 0, 0, 80, 104, 109, 157, 158,
+ 154, 155, 156, 159, 160, 165, 163, 122, 0, 120,
+ 0, 125, 83, 77, 74, 0, 95, 0, 106, 108,
+ 136, 142, 0, 0, 72, 67, 66, 0, 166, 172,
+ 0, 124, 94, 0, 100, 0, 0, 138, 143, 144,
+ 135, 0, 0, 0, 167, 170, 171, 173, 0, 118,
+ 96, 0, 102, 0, 0, 139, 140, 0, 164, 0,
+ 0, 0, 174, 0, 0, 137, 0, 133, 145, 0,
+ 0, 0, 0, 97, 126, 141, 151, 0, 0, 169,
+ 175, 98, 99, 101, 146, 0, 168
};
/* YYDEFGOTO[NTERM-NUM]. */
static const short int yydefgoto[] =
{
- -1, 177, 178, 161, 72, 204, 23, 24, 25, 195,
- 192, 162, 78, 79, 80, 103, 258, 275, 317, 291,
- 26, 27, 28, 198, 199, 104, 29, 30, 31, 32,
- 33, 34, 35, 36, 216, 217, 218, 37, 38, 39,
- 40, 41, 42, 43, 232, 233, 278, 295, 280, 44,
- 306, 87, 158, 45, 46, 47, 245, 167, 168, 269,
- 270, 286, 287, 48
+ -1, 182, 183, 166, 76, 211, 24, 25, 26, 208,
+ 200, 197, 167, 82, 83, 84, 107, 266, 284, 333,
+ 302, 27, 28, 29, 203, 204, 108, 30, 31, 32,
+ 33, 34, 35, 36, 37, 223, 224, 225, 38, 39,
+ 40, 41, 42, 43, 44, 45, 239, 240, 287, 306,
+ 317, 289, 46, 319, 91, 163, 47, 48, 49, 253,
+ 172, 173, 278, 279, 295, 296, 297, 298, 50
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -205
+#define YYPACT_NINF -209
static const short int yypact[] =
{
- 454, -48, 30, 521, 521, -205, 12, 42, -18, 46,
- -4, -33, 67, 69, 71, -205, -205, -205, 47, -8,
- -6, 85, 93, -205, 1, -2, 2, -20, 3, 59,
- 5, 7, 59, 24, 27, 28, 31, 32, 33, 39,
- 50, 51, 55, 56, 57, 58, 60, 62, 63, 521,
- 22, -205, -205, -205, -205, 48, 521, 65, -205, -205,
- -205, -205, -205, -205, -205, -205, -205, -205, -205, 521,
- 521, 252, 64, 576, 66, 68, -205, 640, -205, -40,
- 86, 111, 120, 105, 156, 161, -205, 110, -205, 122,
- -205, -205, -205, -205, 73, -205, -205, 521, -205, 74,
- -205, -205, 492, -205, -205, -205, -205, -205, -205, -205,
- -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
- -205, -205, -205, -205, -205, 640, 167, 106, 309, 107,
- 168, 23, 521, 521, 521, 521, 521, 454, 521, 521,
- 521, 521, 521, 521, 521, 521, 454, 521, -27, 178,
- 204, 179, 521, -205, 181, -205, 91, -205, 134, 178,
- 92, 640, -75, 521, 139, 640, 29, -205, -59, -205,
- -205, -205, 309, 309, 15, 15, 640, -205, 151, 15,
- 15, 15, 25, 25, 168, 168, -58, 284, 535, 187,
- 96, -205, 95, -205, -205, -31, 568, 109, -205, 98,
- 193, 195, 95, -205, -49, -205, 521, -45, 197, 40,
- 40, 189, 167, 454, 521, -205, -205, 186, 191, -205,
- 190, -205, 123, -205, 214, 521, 216, 194, 521, 521,
- 181, 40, -205, -36, 164, 126, 130, 640, -205, -205,
- -205, -205, -205, -205, -205, -205, -205, 227, -205, 454,
- 605, -205, 215, -205, -205, -205, -205, 192, 199, 633,
- 640, -205, 145, 184, 193, 238, -205, -205, 40, -205,
- 4, 454, -205, -205, 205, 203, 454, 245, 240, -205,
- -205, -205, 153, 155, 198, -205, -205, -12, 454, -205,
- 210, -205, 341, 157, 249, -205, 250, -205, 251, 454,
- -205, 259, 229, -205, -205, -205, -26, 244, 398, 26,
- -205, -205, 261, 47, -205, -205, -205, -205, -205, 173,
- -205
+ 578, -30, 40, 256, 256, -209, 19, 44, 7, 55,
+ 26, -16, 62, 69, 73, -209, -209, -209, 48, -5,
+ -4, -209, 78, 75, -209, -13, -15, -6, -18, 4,
+ 67, 6, 12, 67, 17, 18, 21, 29, 30, 32,
+ 33, 39, 47, 50, 51, 64, 65, 70, 82, 83,
+ 84, 256, 13, -209, -209, -209, -209, -209, -209, 8,
+ 256, 20, -209, -209, -209, -209, -209, -209, -209, -209,
+ -209, -209, -209, 256, 256, 295, 15, 421, 77, 86,
+ -209, 657, -209, -44, 129, 152, 178, 137, 182, 189,
+ -209, 142, -209, 154, -209, -209, -209, -209, 104, -209,
+ -209, 256, -209, 105, -209, -209, 170, -209, -209, -209,
+ -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+ -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+ 657, 200, 139, 582, 140, 198, 66, 256, 256, 256,
+ 256, 256, 578, 256, 256, 256, 256, 256, 256, 256,
+ 256, 578, 256, -31, 205, 121, 206, 256, -209, 207,
+ -209, 115, -209, 160, 212, 117, 657, -63, 256, 167,
+ 657, -2, -209, -59, -209, -209, -209, 582, 582, 14,
+ 14, 657, -209, 330, 14, 14, 14, 3, 3, 198,
+ 198, -58, 392, 279, 217, 123, -209, 122, -209, -209,
+ -32, 607, 136, -209, 124, 223, 224, 133, -209, 122,
+ -209, -52, -209, 256, -46, 229, 16, 16, 214, 200,
+ 578, 256, -209, -209, 209, 220, -209, 221, -209, 148,
+ -209, 232, 256, 247, 226, 256, 256, 207, 16, -209,
+ -43, 195, 165, 162, 166, 657, -209, -209, -209, -209,
+ -209, -209, -209, -209, -209, 263, -209, 578, 483, -209,
+ 246, -209, -209, -209, -209, 225, 233, 626, 657, -209,
+ 172, 216, 223, 270, -209, -209, -209, 16, -209, 1,
+ 578, -209, -209, 236, 237, 578, 278, 193, -209, -209,
+ -209, 181, 183, -53, -209, -209, -209, -209, -14, 578,
+ -209, 240, -209, 454, 184, -209, 275, 282, -209, 286,
+ 287, 578, -209, 288, 266, -209, 292, -209, -209, -36,
+ 276, 202, 516, -28, -209, -209, -209, 293, 48, -209,
+ -209, -209, -209, -209, -209, 210, -209
};
/* YYPGOTO[NTERM-NUM]. */
static const short int yypgoto[] =
{
- -205, 0, -126, -1, -205, -205, -205, -205, -205, -205,
- 112, -124, 135, -205, -205, -28, -205, -205, -205, -205,
- -17, -205, -205, 43, -205, 257, -205, -205, -205, -205,
- -205, -205, -205, -205, 76, -205, -205, -205, -205, -205,
- -205, -205, -205, -205, 8, -205, -205, -205, -205, -205,
- -205, -205, -205, -205, -205, -205, -204, 72, -205, 20,
- -205, 10, -205, -205
+ -209, 0, -130, -1, -209, -209, -209, -209, -209, -209,
+ -209, 143, -136, 158, -209, -209, -29, -209, -209, -209,
+ -209, -17, -209, -209, 79, -209, 281, -209, -209, -209,
+ -209, -209, -209, -209, -209, 91, -209, -209, -209, -209,
+ -209, -209, -209, -209, -209, -209, 45, -209, -209, -209,
+ -209, -209, -209, -209, -209, -209, -209, -209, -209, -208,
+ 99, -209, 41, -209, -209, -209, 23, -209, -209
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -780,197 +802,202 @@ static const short int yypgoto[] =
#define YYTABLE_NINF -1
static const unsigned short int yytable[] =
{
- 22, 91, 71, 73, 107, 77, 246, 225, 149, 189,
- 100, 268, 299, 6, 49, 51, 52, 53, 54, 55,
- 187, 186, 56, 85, 205, 86, 206, 262, 136, 99,
- 82, 132, 133, 84, 134, 135, 136, 50, 136, 207,
- 211, 219, 212, 206, 209, 210, 74, 75, 125, 81,
- 235, 284, 236, 83, 238, 128, 206, 240, 241, 242,
- 243, 150, 244, 263, 283, 264, 190, 284, 130, 131,
- 226, 315, 316, 311, 88, 312, 89, 57, 90, 92,
- 6, 93, 58, 59, 60, 61, 62, 249, 63, 64,
- 65, 66, 94, 95, 67, 68, 97, 102, 96, 98,
- 101, 165, 105, 69, 106, 76, 141, 142, 143, 144,
- 70, 138, 139, 140, 141, 142, 143, 144, 143, 144,
- 126, 109, 171, 151, 110, 111, 152, 153, 112, 113,
- 114, 172, 173, 174, 175, 176, 115, 179, 180, 181,
- 182, 183, 184, 185, 127, 288, 188, 116, 117, 77,
- 292, 196, 118, 119, 120, 121, 154, 122, 1, 123,
- 124, 129, 145, 155, 147, 2, 148, 227, 156, 157,
- 159, 160, 163, 308, 166, 169, 170, 3, 215, 213,
- 214, 136, 4, 5, 6, 191, 194, 215, 197, 200,
- 7, 201, 203, 208, 222, 223, 224, 229, 8, 230,
- 231, 9, 234, 10, 239, 237, 11, 51, 52, 53,
- 54, 55, 247, 250, 56, 214, 252, 12, 13, 14,
- 253, 255, 254, 256, 165, 265, 15, 259, 260, 266,
- 267, 16, 17, 257, 268, 18, 19, 20, 74, 75,
- 274, 272, 273, 277, 279, 282, 290, 289, 293, 215,
- 294, 296, 297, 21, 301, 304, 303, 305, 307, 310,
- 132, 133, 298, 134, 135, 136, 309, 313, 318, 57,
- 320, 202, 281, 261, 58, 59, 60, 61, 62, 137,
- 63, 64, 65, 66, 248, 193, 67, 68, 215, 108,
- 285, 1, 215, 251, 0, 69, 319, 300, 2, 0,
- 0, 0, 70, 0, 0, 0, 0, 0, 215, 220,
- 3, 0, 0, 0, 0, 4, 5, 6, 0, 0,
- 134, 135, 136, 7, 0, 0, 0, 0, 0, 0,
+ 23, 95, 75, 77, 111, 81, 154, 194, 232, 254,
+ 277, 104, 311, 309, 191, 216, 217, 6, 141, 331,
+ 332, 192, 53, 54, 55, 56, 57, 58, 59, 141,
+ 270, 60, 214, 103, 51, 248, 249, 250, 251, 310,
+ 252, 212, 89, 213, 90, 218, 226, 219, 213, 52,
+ 130, 293, 243, 85, 244, 78, 79, 86, 246, 133,
+ 213, 271, 155, 272, 87, 88, 293, 195, 326, 292,
+ 327, 92, 135, 136, 233, 99, 137, 138, 93, 139,
+ 140, 141, 94, 6, 96, 97, 61, 98, 101, 100,
+ 257, 62, 63, 64, 65, 66, 102, 67, 68, 69,
+ 70, 148, 149, 71, 72, 170, 105, 106, 109, 132,
+ 146, 147, 148, 149, 110, 73, 131, 80, 150, 113,
+ 114, 134, 74, 115, 53, 54, 55, 56, 57, 58,
+ 59, 116, 117, 60, 118, 119, 177, 178, 179, 180,
+ 181, 120, 184, 185, 186, 187, 188, 189, 190, 121,
+ 299, 193, 122, 123, 81, 303, 201, 78, 79, 143,
+ 144, 145, 146, 147, 148, 149, 124, 125, 156, 157,
+ 176, 234, 126, 53, 54, 55, 56, 57, 58, 59,
+ 152, 322, 60, 222, 127, 128, 129, 158, 61, 153,
+ 159, 160, 222, 62, 63, 64, 65, 66, 161, 67,
+ 68, 69, 70, 162, 164, 71, 72, 165, 168, 171,
+ 174, 175, 245, 141, 196, 199, 202, 73, 205, 206,
+ 258, 207, 210, 215, 74, 169, 229, 230, 231, 236,
+ 237, 170, 238, 241, 267, 268, 242, 61, 247, 255,
+ 221, 263, 62, 63, 64, 65, 66, 260, 67, 68,
+ 69, 70, 262, 261, 71, 72, 264, 222, 273, 53,
+ 54, 55, 56, 57, 58, 59, 73, 265, 60, 274,
+ 275, 276, 277, 74, 281, 286, 283, 282, 288, 291,
+ 300, 304, 301, 305, 307, 308, 313, 316, 315, 137,
+ 138, 318, 139, 140, 141, 320, 321, 323, 324, 222,
+ 325, 328, 334, 222, 329, 137, 138, 209, 139, 140,
+ 141, 335, 336, 198, 112, 259, 269, 290, 256, 0,
+ 294, 312, 222, 61, 142, 0, 0, 0, 62, 63,
+ 64, 65, 66, 0, 67, 68, 69, 70, 0, 1,
+ 71, 72, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 73, 0, 0, 0, 0, 0, 3, 74,
+ 220, 221, 0, 4, 5, 6, 0, 0, 0, 0,
+ 0, 7, 143, 144, 145, 146, 147, 148, 149, 8,
+ 0, 0, 9, 228, 10, 0, 0, 11, 143, 144,
+ 145, 146, 147, 148, 149, 0, 0, 0, 12, 13,
+ 14, 1, 0, 0, 0, 0, 0, 15, 2, 0,
+ 0, 0, 16, 17, 0, 0, 18, 19, 20, 227,
+ 3, 21, 0, 0, 0, 4, 5, 6, 0, 0,
+ 0, 137, 138, 7, 139, 140, 141, 22, 0, 0,
0, 8, 0, 0, 9, 0, 10, 0, 0, 11,
- 138, 139, 140, 141, 142, 143, 144, 0, 1, 0,
- 12, 13, 14, 0, 0, 2, 0, 0, 0, 15,
- 0, 0, 0, 0, 16, 17, 302, 3, 18, 19,
- 20, 0, 4, 5, 6, 0, 0, 0, 0, 0,
- 7, 0, 0, 0, 0, 0, 21, 0, 8, 0,
- 0, 9, 0, 10, 0, 0, 11, 138, 139, 140,
- 141, 142, 143, 144, 0, 1, 0, 12, 13, 14,
- 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
- 0, 16, 17, 314, 3, 18, 19, 20, 0, 4,
+ 0, 0, 0, 151, 0, 0, 0, 0, 0, 0,
+ 12, 13, 14, 1, 0, 0, 0, 0, 0, 15,
+ 2, 0, 0, 0, 16, 17, 0, 0, 18, 19,
+ 20, 314, 3, 21, 0, 0, 0, 4, 5, 6,
+ 0, 0, 0, 137, 138, 7, 139, 140, 141, 22,
+ 0, 0, 0, 8, 0, 0, 9, 0, 10, 0,
+ 0, 11, 280, 0, 143, 144, 145, 146, 147, 148,
+ 149, 0, 12, 13, 14, 1, 0, 0, 0, 0,
+ 0, 15, 2, 0, 0, 0, 16, 17, 0, 0,
+ 18, 19, 20, 330, 3, 21, 0, 0, 0, 4,
5, 6, 0, 0, 0, 0, 0, 7, 0, 0,
- 0, 0, 0, 21, 0, 8, 0, 0, 9, 0,
- 10, 0, 0, 11, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 12, 13, 14, 0, 2, 0,
- 0, 0, 0, 15, 0, 0, 0, 0, 16, 17,
- 3, 0, 18, 19, 20, 4, 5, 6, 0, 0,
- 0, 0, 0, 7, 0, 51, 52, 53, 54, 55,
- 21, 8, 56, 0, 9, 0, 10, 0, 0, 11,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 12, 13, 14, 0, 51, 52, 53, 54, 55, 15,
- 0, 56, 0, 0, 16, 17, 0, 0, 18, 19,
- 20, 0, 0, 132, 133, 164, 134, 135, 136, 0,
- 0, 0, 0, 0, 0, 0, 21, 57, 0, 0,
- 0, 0, 58, 59, 60, 61, 62, 0, 63, 64,
- 65, 66, 0, 0, 67, 68, 132, 133, 0, 134,
- 135, 136, 0, 69, 132, 133, 57, 134, 135, 136,
- 70, 58, 59, 60, 61, 62, 0, 63, 64, 65,
- 66, 0, 0, 67, 68, 0, 146, 0, 228, 0,
- 0, 0, 69, 132, 133, 0, 134, 135, 136, 70,
- 0, 0, 0, 138, 139, 140, 141, 142, 143, 144,
- 0, 0, 271, 0, 221, 0, 0, 0, 0, 0,
- 0, 132, 133, 0, 134, 135, 136, 0, 132, 133,
- 0, 134, 135, 136, 0, 0, 138, 139, 140, 141,
- 142, 143, 144, 276, 138, 139, 140, 141, 142, 143,
- 144, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 22, 0, 0, 0, 8, 0, 0, 9, 0,
+ 10, 0, 0, 11, 0, 0, 143, 144, 145, 146,
+ 147, 148, 149, 0, 12, 13, 14, 1, 0, 0,
+ 0, 0, 0, 15, 2, 139, 140, 141, 16, 17,
+ 0, 0, 18, 19, 20, 0, 3, 21, 0, 0,
+ 0, 4, 5, 6, 0, 0, 0, 137, 138, 7,
+ 139, 140, 141, 22, 0, 0, 0, 8, 0, 0,
+ 9, 0, 10, 0, 0, 11, 137, 138, 0, 139,
+ 140, 141, 0, 0, 0, 0, 12, 13, 14, 235,
+ 0, 0, 0, 0, 0, 15, 0, 0, 285, 0,
+ 16, 17, 0, 0, 18, 19, 20, 137, 138, 21,
+ 139, 140, 141, 0, 0, 143, 144, 145, 146, 147,
+ 148, 149, 0, 0, 0, 22, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 138, 139, 140, 141, 142, 143, 144,
+ 143, 144, 145, 146, 147, 148, 149, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 143,
+ 144, 145, 146, 147, 148, 149, 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, 138, 139, 140, 141, 142, 143, 144, 138, 139,
- 140, 141, 142, 143, 144
+ 143, 144, 145, 146, 147, 148, 149
};
static const short int yycheck[] =
{
- 0, 18, 3, 4, 32, 6, 210, 38, 48, 36,
- 27, 7, 24, 33, 62, 3, 4, 5, 6, 7,
- 146, 145, 10, 56, 99, 58, 101, 231, 13, 49,
- 48, 8, 9, 37, 11, 12, 13, 7, 13, 163,
- 99, 99, 101, 101, 15, 16, 34, 35, 49, 7,
- 99, 63, 101, 7, 99, 56, 101, 17, 18, 19,
- 20, 101, 22, 99, 268, 101, 93, 63, 69, 70,
- 101, 45, 46, 99, 7, 101, 7, 65, 7, 87,
- 33, 87, 70, 71, 72, 73, 74, 213, 76, 77,
- 78, 79, 7, 0, 82, 83, 98, 38, 97, 97,
- 97, 102, 97, 91, 97, 93, 91, 92, 93, 94,
- 98, 88, 89, 90, 91, 92, 93, 94, 93, 94,
- 98, 97, 99, 37, 97, 97, 15, 7, 97, 97,
- 97, 132, 133, 134, 135, 136, 97, 138, 139, 140,
- 141, 142, 143, 144, 96, 271, 147, 97, 97, 150,
- 276, 152, 97, 97, 97, 97, 51, 97, 7, 97,
- 97, 96, 98, 7, 98, 14, 98, 195, 7, 59,
- 48, 98, 98, 299, 7, 69, 69, 26, 178, 28,
- 29, 13, 31, 32, 33, 7, 7, 187, 7, 98,
- 39, 57, 100, 54, 7, 99, 101, 88, 47, 101,
- 7, 50, 7, 52, 7, 206, 55, 3, 4, 5,
- 6, 7, 23, 214, 10, 29, 25, 66, 67, 68,
- 30, 7, 99, 7, 225, 61, 75, 228, 229, 103,
- 100, 80, 81, 39, 7, 84, 85, 86, 34, 35,
- 41, 26, 50, 98, 60, 7, 43, 42, 3, 249,
- 10, 98, 97, 102, 44, 6, 99, 7, 7, 30,
- 8, 9, 64, 11, 12, 13, 7, 23, 7, 65,
- 97, 159, 264, 230, 70, 71, 72, 73, 74, 27,
- 76, 77, 78, 79, 212, 150, 82, 83, 288, 32,
- 270, 7, 292, 217, -1, 91, 313, 287, 14, -1,
- -1, -1, 98, -1, -1, -1, -1, -1, 308, 25,
- 26, -1, -1, -1, -1, 31, 32, 33, -1, -1,
- 11, 12, 13, 39, -1, -1, -1, -1, -1, -1,
- -1, 47, -1, -1, 50, -1, 52, -1, -1, 55,
- 88, 89, 90, 91, 92, 93, 94, -1, 7, -1,
- 66, 67, 68, -1, -1, 14, -1, -1, -1, 75,
- -1, -1, -1, -1, 80, 81, 25, 26, 84, 85,
- 86, -1, 31, 32, 33, -1, -1, -1, -1, -1,
- 39, -1, -1, -1, -1, -1, 102, -1, 47, -1,
- -1, 50, -1, 52, -1, -1, 55, 88, 89, 90,
- 91, 92, 93, 94, -1, 7, -1, 66, 67, 68,
- -1, -1, 14, -1, -1, -1, 75, -1, -1, -1,
- -1, 80, 81, 25, 26, 84, 85, 86, -1, 31,
- 32, 33, -1, -1, -1, -1, -1, 39, -1, -1,
- -1, -1, -1, 102, -1, 47, -1, -1, 50, -1,
- 52, -1, -1, 55, -1, -1, -1, -1, -1, -1,
- -1, 7, -1, -1, 66, 67, 68, -1, 14, -1,
- -1, -1, -1, 75, -1, -1, -1, -1, 80, 81,
- 26, -1, 84, 85, 86, 31, 32, 33, -1, -1,
- -1, -1, -1, 39, -1, 3, 4, 5, 6, 7,
- 102, 47, 10, -1, 50, -1, 52, -1, -1, 55,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 66, 67, 68, -1, 3, 4, 5, 6, 7, 75,
- -1, 10, -1, -1, 80, 81, -1, -1, 84, 85,
- 86, -1, -1, 8, 9, 53, 11, 12, 13, -1,
- -1, -1, -1, -1, -1, -1, 102, 65, -1, -1,
- -1, -1, 70, 71, 72, 73, 74, -1, 76, 77,
- 78, 79, -1, -1, 82, 83, 8, 9, -1, 11,
- 12, 13, -1, 91, 8, 9, 65, 11, 12, 13,
- 98, 70, 71, 72, 73, 74, -1, 76, 77, 78,
- 79, -1, -1, 82, 83, -1, 30, -1, 40, -1,
- -1, -1, 91, 8, 9, -1, 11, 12, 13, 98,
- -1, -1, -1, 88, 89, 90, 91, 92, 93, 94,
- -1, -1, 27, -1, 99, -1, -1, -1, -1, -1,
- -1, 8, 9, -1, 11, 12, 13, -1, 8, 9,
- -1, 11, 12, 13, -1, -1, 88, 89, 90, 91,
- 92, 93, 94, 30, 88, 89, 90, 91, 92, 93,
- 94, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 18, 3, 4, 33, 6, 50, 38, 40, 217,
+ 9, 28, 26, 66, 150, 17, 18, 35, 15, 47,
+ 48, 151, 3, 4, 5, 6, 7, 8, 9, 15,
+ 238, 12, 168, 51, 64, 19, 20, 21, 22, 92,
+ 24, 104, 58, 106, 60, 104, 104, 106, 106, 9,
+ 51, 65, 104, 9, 106, 36, 37, 50, 104, 60,
+ 106, 104, 106, 106, 9, 39, 65, 98, 104, 277,
+ 106, 9, 73, 74, 106, 0, 10, 11, 9, 13,
+ 14, 15, 9, 35, 89, 89, 67, 9, 103, 102,
+ 220, 72, 73, 74, 75, 76, 102, 78, 79, 80,
+ 81, 98, 99, 84, 85, 106, 102, 40, 102, 101,
+ 96, 97, 98, 99, 102, 96, 103, 98, 103, 102,
+ 102, 101, 103, 102, 3, 4, 5, 6, 7, 8,
+ 9, 102, 102, 12, 102, 102, 137, 138, 139, 140,
+ 141, 102, 143, 144, 145, 146, 147, 148, 149, 102,
+ 280, 152, 102, 102, 155, 285, 157, 36, 37, 93,
+ 94, 95, 96, 97, 98, 99, 102, 102, 39, 17,
+ 104, 200, 102, 3, 4, 5, 6, 7, 8, 9,
+ 103, 311, 12, 183, 102, 102, 102, 9, 67, 103,
+ 53, 9, 192, 72, 73, 74, 75, 76, 9, 78,
+ 79, 80, 81, 61, 50, 84, 85, 103, 103, 9,
+ 71, 71, 213, 15, 9, 9, 9, 96, 103, 59,
+ 221, 9, 105, 56, 103, 55, 9, 104, 106, 93,
+ 106, 232, 9, 9, 235, 236, 103, 67, 9, 25,
+ 31, 9, 72, 73, 74, 75, 76, 27, 78, 79,
+ 80, 81, 104, 32, 84, 85, 9, 257, 63, 3,
+ 4, 5, 6, 7, 8, 9, 96, 41, 12, 104,
+ 108, 105, 9, 103, 28, 103, 43, 52, 62, 9,
+ 44, 3, 45, 90, 103, 102, 46, 12, 104, 10,
+ 11, 9, 13, 14, 15, 9, 9, 9, 32, 299,
+ 8, 25, 9, 303, 102, 10, 11, 164, 13, 14,
+ 15, 328, 102, 155, 33, 224, 237, 272, 219, -1,
+ 279, 298, 322, 67, 29, -1, -1, -1, 72, 73,
+ 74, 75, 76, -1, 78, 79, 80, 81, -1, 9,
+ 84, 85, -1, -1, -1, -1, 16, -1, -1, -1,
+ -1, -1, 96, -1, -1, -1, -1, -1, 28, 103,
+ 30, 31, -1, 33, 34, 35, -1, -1, -1, -1,
+ -1, 41, 93, 94, 95, 96, 97, 98, 99, 49,
+ -1, -1, 52, 104, 54, -1, -1, 57, 93, 94,
+ 95, 96, 97, 98, 99, -1, -1, -1, 68, 69,
+ 70, 9, -1, -1, -1, -1, -1, 77, 16, -1,
+ -1, -1, 82, 83, -1, -1, 86, 87, 88, 27,
+ 28, 91, -1, -1, -1, 33, 34, 35, -1, -1,
+ -1, 10, 11, 41, 13, 14, 15, 107, -1, -1,
+ -1, 49, -1, -1, 52, -1, 54, -1, -1, 57,
+ -1, -1, -1, 32, -1, -1, -1, -1, -1, -1,
+ 68, 69, 70, 9, -1, -1, -1, -1, -1, 77,
+ 16, -1, -1, -1, 82, 83, -1, -1, 86, 87,
+ 88, 27, 28, 91, -1, -1, -1, 33, 34, 35,
+ -1, -1, -1, 10, 11, 41, 13, 14, 15, 107,
+ -1, -1, -1, 49, -1, -1, 52, -1, 54, -1,
+ -1, 57, 29, -1, 93, 94, 95, 96, 97, 98,
+ 99, -1, 68, 69, 70, 9, -1, -1, -1, -1,
+ -1, 77, 16, -1, -1, -1, 82, 83, -1, -1,
+ 86, 87, 88, 27, 28, 91, -1, -1, -1, 33,
+ 34, 35, -1, -1, -1, -1, -1, 41, -1, -1,
+ -1, 107, -1, -1, -1, 49, -1, -1, 52, -1,
+ 54, -1, -1, 57, -1, -1, 93, 94, 95, 96,
+ 97, 98, 99, -1, 68, 69, 70, 9, -1, -1,
+ -1, -1, -1, 77, 16, 13, 14, 15, 82, 83,
+ -1, -1, 86, 87, 88, -1, 28, 91, -1, -1,
+ -1, 33, 34, 35, -1, -1, -1, 10, 11, 41,
+ 13, 14, 15, 107, -1, -1, -1, 49, -1, -1,
+ 52, -1, 54, -1, -1, 57, 10, 11, -1, 13,
+ 14, 15, -1, -1, -1, -1, 68, 69, 70, 42,
+ -1, -1, -1, -1, -1, 77, -1, -1, 32, -1,
+ 82, 83, -1, -1, 86, 87, 88, 10, 11, 91,
+ 13, 14, 15, -1, -1, 93, 94, 95, 96, 97,
+ 98, 99, -1, -1, -1, 107, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 88, 89, 90, 91, 92, 93, 94,
+ 93, 94, 95, 96, 97, 98, 99, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 93,
+ 94, 95, 96, 97, 98, 99, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 88, 89, 90, 91, 92, 93, 94, 88, 89,
- 90, 91, 92, 93, 94
+ 93, 94, 95, 96, 97, 98, 99
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const unsigned char yystos[] =
{
- 0, 7, 14, 26, 31, 32, 33, 39, 47, 50,
- 52, 55, 66, 67, 68, 75, 80, 81, 84, 85,
- 86, 102, 105, 110, 111, 112, 124, 125, 126, 130,
- 131, 132, 133, 134, 135, 136, 137, 141, 142, 143,
- 144, 145, 146, 147, 153, 157, 158, 159, 167, 62,
- 7, 3, 4, 5, 6, 7, 10, 65, 70, 71,
- 72, 73, 74, 76, 77, 78, 79, 82, 83, 91,
- 98, 107, 108, 107, 34, 35, 93, 107, 116, 117,
- 118, 7, 48, 7, 37, 56, 58, 155, 7, 7,
- 7, 124, 87, 87, 7, 0, 97, 98, 97, 49,
- 124, 97, 38, 119, 129, 97, 97, 119, 129, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 107, 98, 96, 107, 96,
- 107, 107, 8, 9, 11, 12, 13, 27, 88, 89,
- 90, 91, 92, 93, 94, 98, 30, 98, 98, 48,
- 101, 37, 15, 7, 51, 7, 7, 59, 156, 48,
- 98, 107, 115, 98, 53, 107, 7, 161, 162, 69,
- 69, 99, 107, 107, 107, 107, 107, 105, 106, 107,
- 107, 107, 107, 107, 107, 107, 115, 106, 107, 36,
- 93, 7, 114, 116, 7, 113, 107, 7, 127, 128,
- 98, 57, 114, 100, 109, 99, 101, 115, 54, 15,
- 16, 99, 101, 28, 29, 105, 138, 139, 140, 99,
- 25, 99, 7, 99, 101, 38, 101, 119, 40, 88,
- 101, 7, 148, 149, 7, 99, 101, 107, 99, 7,
- 17, 18, 19, 20, 22, 160, 160, 23, 161, 106,
- 107, 138, 25, 30, 99, 7, 7, 39, 120, 107,
- 107, 127, 160, 99, 101, 61, 103, 100, 7, 163,
- 164, 27, 26, 50, 41, 121, 30, 98, 150, 60,
- 152, 148, 7, 160, 63, 163, 165, 166, 106, 42,
- 43, 123, 106, 3, 10, 151, 98, 97, 64, 24,
- 165, 44, 25, 99, 6, 7, 154, 7, 106, 7,
- 30, 99, 101, 23, 25, 45, 46, 122, 7, 124,
- 97
+ 0, 9, 16, 28, 33, 34, 35, 41, 49, 52,
+ 54, 57, 68, 69, 70, 77, 82, 83, 86, 87,
+ 88, 91, 107, 110, 115, 116, 117, 130, 131, 132,
+ 136, 137, 138, 139, 140, 141, 142, 143, 147, 148,
+ 149, 150, 151, 152, 153, 154, 161, 165, 166, 167,
+ 177, 64, 9, 3, 4, 5, 6, 7, 8, 9,
+ 12, 67, 72, 73, 74, 75, 76, 78, 79, 80,
+ 81, 84, 85, 96, 103, 112, 113, 112, 36, 37,
+ 98, 112, 122, 123, 124, 9, 50, 9, 39, 58,
+ 60, 163, 9, 9, 9, 130, 89, 89, 9, 0,
+ 102, 103, 102, 51, 130, 102, 40, 125, 135, 102,
+ 102, 125, 135, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 112, 103, 101, 112, 101, 112, 112, 10, 11, 13,
+ 14, 15, 29, 93, 94, 95, 96, 97, 98, 99,
+ 103, 32, 103, 103, 50, 106, 39, 17, 9, 53,
+ 9, 9, 61, 164, 50, 103, 112, 121, 103, 55,
+ 112, 9, 169, 170, 71, 71, 104, 112, 112, 112,
+ 112, 112, 110, 111, 112, 112, 112, 112, 112, 112,
+ 112, 121, 111, 112, 38, 98, 9, 120, 122, 9,
+ 119, 112, 9, 133, 134, 103, 59, 9, 118, 120,
+ 105, 114, 104, 106, 121, 56, 17, 18, 104, 106,
+ 30, 31, 110, 144, 145, 146, 104, 27, 104, 9,
+ 104, 106, 40, 106, 125, 42, 93, 106, 9, 155,
+ 156, 9, 103, 104, 106, 112, 104, 9, 19, 20,
+ 21, 22, 24, 168, 168, 25, 169, 111, 112, 144,
+ 27, 32, 104, 9, 9, 41, 126, 112, 112, 133,
+ 168, 104, 106, 63, 104, 108, 105, 9, 171, 172,
+ 29, 28, 52, 43, 127, 32, 103, 157, 62, 160,
+ 155, 9, 168, 65, 171, 173, 174, 175, 176, 111,
+ 44, 45, 129, 111, 3, 90, 158, 103, 102, 66,
+ 92, 26, 175, 46, 27, 104, 12, 159, 9, 162,
+ 9, 9, 111, 9, 32, 8, 104, 106, 25, 102,
+ 27, 47, 48, 128, 9, 130, 102
};
#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
@@ -1581,271 +1608,286 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 24:
-#line 156 "pars0grm.y"
+ case 25:
+#line 162 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 25:
-#line 158 "pars0grm.y"
- { yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ;}
- break;
-
case 26:
-#line 162 "pars0grm.y"
- { yyval = yyvsp[0];;}
+#line 164 "pars0grm.y"
+ { yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ;}
break;
case 27:
-#line 164 "pars0grm.y"
- { yyval = pars_func(yyvsp[-3], yyvsp[-1]); ;}
+#line 168 "pars0grm.y"
+ { yyval = yyvsp[0];;}
break;
case 28:
-#line 165 "pars0grm.y"
- { yyval = yyvsp[0];;}
+#line 170 "pars0grm.y"
+ { yyval = pars_func(yyvsp[-3], yyvsp[-1]); ;}
break;
case 29:
-#line 166 "pars0grm.y"
+#line 171 "pars0grm.y"
{ yyval = yyvsp[0];;}
break;
case 30:
-#line 167 "pars0grm.y"
+#line 172 "pars0grm.y"
{ yyval = yyvsp[0];;}
break;
case 31:
-#line 168 "pars0grm.y"
+#line 173 "pars0grm.y"
{ yyval = yyvsp[0];;}
break;
case 32:
-#line 169 "pars0grm.y"
+#line 174 "pars0grm.y"
{ yyval = yyvsp[0];;}
break;
case 33:
-#line 170 "pars0grm.y"
- { yyval = pars_op('+', yyvsp[-2], yyvsp[0]); ;}
+#line 175 "pars0grm.y"
+ { yyval = yyvsp[0];;}
break;
case 34:
-#line 171 "pars0grm.y"
- { yyval = pars_op('-', yyvsp[-2], yyvsp[0]); ;}
+#line 176 "pars0grm.y"
+ { yyval = yyvsp[0];;}
break;
case 35:
-#line 172 "pars0grm.y"
- { yyval = pars_op('*', yyvsp[-2], yyvsp[0]); ;}
+#line 177 "pars0grm.y"
+ { yyval = yyvsp[0];;}
break;
case 36:
-#line 173 "pars0grm.y"
- { yyval = pars_op('/', yyvsp[-2], yyvsp[0]); ;}
+#line 178 "pars0grm.y"
+ { yyval = pars_op('+', yyvsp[-2], yyvsp[0]); ;}
break;
case 37:
-#line 174 "pars0grm.y"
- { yyval = pars_op('-', yyvsp[0], NULL); ;}
+#line 179 "pars0grm.y"
+ { yyval = pars_op('-', yyvsp[-2], yyvsp[0]); ;}
break;
case 38:
-#line 175 "pars0grm.y"
- { yyval = yyvsp[-1]; ;}
+#line 180 "pars0grm.y"
+ { yyval = pars_op('*', yyvsp[-2], yyvsp[0]); ;}
break;
case 39:
-#line 176 "pars0grm.y"
- { yyval = pars_op('=', yyvsp[-2], yyvsp[0]); ;}
+#line 181 "pars0grm.y"
+ { yyval = pars_op('/', yyvsp[-2], yyvsp[0]); ;}
break;
case 40:
-#line 177 "pars0grm.y"
- { yyval = pars_op('<', yyvsp[-2], yyvsp[0]); ;}
+#line 182 "pars0grm.y"
+ { yyval = pars_op('-', yyvsp[0], NULL); ;}
break;
case 41:
-#line 178 "pars0grm.y"
- { yyval = pars_op('>', yyvsp[-2], yyvsp[0]); ;}
+#line 183 "pars0grm.y"
+ { yyval = yyvsp[-1]; ;}
break;
case 42:
-#line 179 "pars0grm.y"
- { yyval = pars_op(PARS_GE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
+#line 184 "pars0grm.y"
+ { yyval = pars_op('=', yyvsp[-2], yyvsp[0]); ;}
break;
case 43:
-#line 180 "pars0grm.y"
- { yyval = pars_op(PARS_LE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
+#line 185 "pars0grm.y"
+ { yyval = pars_op('<', yyvsp[-2], yyvsp[0]); ;}
break;
case 44:
-#line 181 "pars0grm.y"
- { yyval = pars_op(PARS_NE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
+#line 186 "pars0grm.y"
+ { yyval = pars_op('>', yyvsp[-2], yyvsp[0]); ;}
break;
case 45:
-#line 182 "pars0grm.y"
- { yyval = pars_op(PARS_AND_TOKEN, yyvsp[-2], yyvsp[0]); ;}
+#line 187 "pars0grm.y"
+ { yyval = pars_op(PARS_GE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
break;
case 46:
-#line 183 "pars0grm.y"
- { yyval = pars_op(PARS_OR_TOKEN, yyvsp[-2], yyvsp[0]); ;}
+#line 188 "pars0grm.y"
+ { yyval = pars_op(PARS_LE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
break;
case 47:
-#line 184 "pars0grm.y"
- { yyval = pars_op(PARS_NOT_TOKEN, yyvsp[0], NULL); ;}
+#line 189 "pars0grm.y"
+ { yyval = pars_op(PARS_NE_TOKEN, yyvsp[-2], yyvsp[0]); ;}
break;
case 48:
-#line 186 "pars0grm.y"
- { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;}
+#line 190 "pars0grm.y"
+ { yyval = pars_op(PARS_AND_TOKEN, yyvsp[-2], yyvsp[0]); ;}
break;
case 49:
-#line 188 "pars0grm.y"
- { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;}
+#line 191 "pars0grm.y"
+ { yyval = pars_op(PARS_OR_TOKEN, yyvsp[-2], yyvsp[0]); ;}
break;
case 50:
#line 192 "pars0grm.y"
- { yyval = &pars_to_char_token; ;}
+ { yyval = pars_op(PARS_NOT_TOKEN, yyvsp[0], NULL); ;}
break;
case 51:
-#line 193 "pars0grm.y"
- { yyval = &pars_to_number_token; ;}
+#line 194 "pars0grm.y"
+ { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;}
break;
case 52:
-#line 194 "pars0grm.y"
- { yyval = &pars_to_binary_token; ;}
+#line 196 "pars0grm.y"
+ { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;}
break;
case 53:
-#line 196 "pars0grm.y"
- { yyval = &pars_binary_to_number_token; ;}
+#line 200 "pars0grm.y"
+ { yyval = &pars_to_char_token; ;}
break;
case 54:
-#line 197 "pars0grm.y"
- { yyval = &pars_substr_token; ;}
+#line 201 "pars0grm.y"
+ { yyval = &pars_to_number_token; ;}
break;
case 55:
-#line 198 "pars0grm.y"
- { yyval = &pars_concat_token; ;}
+#line 202 "pars0grm.y"
+ { yyval = &pars_to_binary_token; ;}
break;
case 56:
-#line 199 "pars0grm.y"
- { yyval = &pars_instr_token; ;}
+#line 204 "pars0grm.y"
+ { yyval = &pars_binary_to_number_token; ;}
break;
case 57:
-#line 200 "pars0grm.y"
- { yyval = &pars_length_token; ;}
+#line 205 "pars0grm.y"
+ { yyval = &pars_substr_token; ;}
break;
case 58:
-#line 201 "pars0grm.y"
- { yyval = &pars_sysdate_token; ;}
+#line 206 "pars0grm.y"
+ { yyval = &pars_concat_token; ;}
break;
case 59:
-#line 202 "pars0grm.y"
- { yyval = &pars_rnd_token; ;}
+#line 207 "pars0grm.y"
+ { yyval = &pars_instr_token; ;}
break;
case 60:
-#line 203 "pars0grm.y"
+#line 208 "pars0grm.y"
+ { yyval = &pars_length_token; ;}
+ break;
+
+ case 61:
+#line 209 "pars0grm.y"
+ { yyval = &pars_sysdate_token; ;}
+ break;
+
+ case 62:
+#line 210 "pars0grm.y"
+ { yyval = &pars_rnd_token; ;}
+ break;
+
+ case 63:
+#line 211 "pars0grm.y"
{ yyval = &pars_rnd_str_token; ;}
break;
- case 64:
-#line 214 "pars0grm.y"
+ case 67:
+#line 222 "pars0grm.y"
{ yyval = pars_stored_procedure_call(yyvsp[-4]); ;}
break;
- case 65:
-#line 219 "pars0grm.y"
+ case 68:
+#line 227 "pars0grm.y"
{ yyval = pars_procedure_call(yyvsp[-3], yyvsp[-1]); ;}
break;
- case 66:
-#line 223 "pars0grm.y"
+ case 69:
+#line 231 "pars0grm.y"
{ yyval = &pars_replstr_token; ;}
break;
- case 67:
-#line 224 "pars0grm.y"
+ case 70:
+#line 232 "pars0grm.y"
{ yyval = &pars_printf_token; ;}
break;
- case 68:
-#line 225 "pars0grm.y"
+ case 71:
+#line 233 "pars0grm.y"
{ yyval = &pars_assert_token; ;}
break;
- case 69:
-#line 229 "pars0grm.y"
+ case 72:
+#line 237 "pars0grm.y"
+ { yyval = yyvsp[-2]; ;}
+ break;
+
+ case 73:
+#line 241 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 70:
-#line 231 "pars0grm.y"
+ case 74:
+#line 243 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 71:
-#line 235 "pars0grm.y"
+ case 75:
+#line 247 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 72:
-#line 236 "pars0grm.y"
+ case 76:
+#line 248 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 73:
-#line 238 "pars0grm.y"
+ case 77:
+#line 250 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 74:
-#line 242 "pars0grm.y"
+ case 78:
+#line 254 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 75:
-#line 243 "pars0grm.y"
+ case 79:
+#line 255 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]);;}
break;
- case 76:
-#line 244 "pars0grm.y"
+ case 80:
+#line 256 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 77:
-#line 248 "pars0grm.y"
+ case 81:
+#line 260 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 78:
-#line 250 "pars0grm.y"
+ case 82:
+#line 262 "pars0grm.y"
{ yyval = pars_func(&pars_count_token,
que_node_list_add_last(NULL,
sym_tab_add_int_lit(
pars_sym_tab_global, 1))); ;}
break;
- case 79:
-#line 255 "pars0grm.y"
+ case 83:
+#line 267 "pars0grm.y"
{ yyval = pars_func(&pars_count_token,
que_node_list_add_last(NULL,
pars_func(&pars_distinct_token,
@@ -1853,410 +1895,436 @@ yyreduce:
NULL, yyvsp[-1])))); ;}
break;
- case 80:
-#line 261 "pars0grm.y"
+ case 84:
+#line 273 "pars0grm.y"
{ yyval = pars_func(&pars_sum_token,
que_node_list_add_last(NULL,
yyvsp[-1])); ;}
break;
- case 81:
-#line 267 "pars0grm.y"
+ case 85:
+#line 279 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 82:
-#line 268 "pars0grm.y"
+ case 86:
+#line 280 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 83:
-#line 270 "pars0grm.y"
+ case 87:
+#line 282 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 84:
-#line 274 "pars0grm.y"
+ case 88:
+#line 286 "pars0grm.y"
{ yyval = pars_select_list(&pars_star_denoter,
NULL); ;}
break;
- case 85:
-#line 277 "pars0grm.y"
+ case 89:
+#line 289 "pars0grm.y"
{ yyval = pars_select_list(yyvsp[-2], yyvsp[0]); ;}
break;
- case 86:
-#line 278 "pars0grm.y"
+ case 90:
+#line 290 "pars0grm.y"
{ yyval = pars_select_list(yyvsp[0], NULL); ;}
break;
- case 87:
-#line 282 "pars0grm.y"
+ case 91:
+#line 294 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 88:
-#line 283 "pars0grm.y"
+ case 92:
+#line 295 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 89:
-#line 287 "pars0grm.y"
+ case 93:
+#line 299 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 90:
-#line 289 "pars0grm.y"
+ case 94:
+#line 301 "pars0grm.y"
{ yyval = &pars_update_token; ;}
break;
- case 91:
-#line 293 "pars0grm.y"
+ case 95:
+#line 305 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 92:
-#line 295 "pars0grm.y"
+ case 96:
+#line 307 "pars0grm.y"
{ yyval = &pars_consistent_token; ;}
break;
- case 93:
-#line 299 "pars0grm.y"
+ case 97:
+#line 311 "pars0grm.y"
{ yyval = &pars_asc_token; ;}
break;
- case 94:
-#line 300 "pars0grm.y"
+ case 98:
+#line 312 "pars0grm.y"
{ yyval = &pars_asc_token; ;}
break;
- case 95:
-#line 301 "pars0grm.y"
+ case 99:
+#line 313 "pars0grm.y"
{ yyval = &pars_desc_token; ;}
break;
- case 96:
-#line 305 "pars0grm.y"
+ case 100:
+#line 317 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 97:
-#line 307 "pars0grm.y"
+ case 101:
+#line 319 "pars0grm.y"
{ yyval = pars_order_by(yyvsp[-1], yyvsp[0]); ;}
break;
- case 98:
-#line 316 "pars0grm.y"
+ case 102:
+#line 328 "pars0grm.y"
{ yyval = pars_select_statement(yyvsp[-6], yyvsp[-4], yyvsp[-3],
yyvsp[-2], yyvsp[-1], yyvsp[0]); ;}
break;
- case 99:
-#line 322 "pars0grm.y"
+ case 103:
+#line 334 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 100:
-#line 327 "pars0grm.y"
+ case 104:
+#line 339 "pars0grm.y"
{ yyval = pars_insert_statement(yyvsp[-4], yyvsp[-1], NULL); ;}
break;
- case 101:
-#line 329 "pars0grm.y"
+ case 105:
+#line 341 "pars0grm.y"
{ yyval = pars_insert_statement(yyvsp[-1], NULL, yyvsp[0]); ;}
break;
- case 102:
-#line 333 "pars0grm.y"
+ case 106:
+#line 345 "pars0grm.y"
{ yyval = pars_column_assignment(yyvsp[-2], yyvsp[0]); ;}
break;
- case 103:
-#line 337 "pars0grm.y"
+ case 107:
+#line 349 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 104:
-#line 339 "pars0grm.y"
+ case 108:
+#line 351 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 105:
-#line 345 "pars0grm.y"
+ case 109:
+#line 357 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 106:
-#line 351 "pars0grm.y"
+ case 110:
+#line 363 "pars0grm.y"
{ yyval = pars_update_statement_start(FALSE,
yyvsp[-2], yyvsp[0]); ;}
break;
- case 107:
-#line 357 "pars0grm.y"
+ case 111:
+#line 369 "pars0grm.y"
{ yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ;}
break;
- case 108:
-#line 362 "pars0grm.y"
+ case 112:
+#line 374 "pars0grm.y"
{ yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ;}
break;
- case 109:
-#line 367 "pars0grm.y"
+ case 113:
+#line 379 "pars0grm.y"
{ yyval = pars_update_statement_start(TRUE,
yyvsp[0], NULL); ;}
break;
- case 110:
-#line 373 "pars0grm.y"
+ case 114:
+#line 385 "pars0grm.y"
{ yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ;}
break;
- case 111:
-#line 378 "pars0grm.y"
+ case 115:
+#line 390 "pars0grm.y"
{ yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ;}
break;
- case 112:
-#line 383 "pars0grm.y"
+ case 116:
+#line 395 "pars0grm.y"
{ yyval = pars_row_printf_statement(yyvsp[0]); ;}
break;
- case 113:
-#line 388 "pars0grm.y"
+ case 117:
+#line 400 "pars0grm.y"
{ yyval = pars_assignment_statement(yyvsp[-2], yyvsp[0]); ;}
break;
- case 114:
-#line 394 "pars0grm.y"
+ case 118:
+#line 406 "pars0grm.y"
{ yyval = pars_elsif_element(yyvsp[-2], yyvsp[0]); ;}
break;
- case 115:
-#line 398 "pars0grm.y"
+ case 119:
+#line 410 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 116:
-#line 400 "pars0grm.y"
+ case 120:
+#line 412 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ;}
break;
- case 117:
-#line 404 "pars0grm.y"
+ case 121:
+#line 416 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 118:
-#line 406 "pars0grm.y"
+ case 122:
+#line 418 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 119:
-#line 407 "pars0grm.y"
+ case 123:
+#line 419 "pars0grm.y"
{ yyval = yyvsp[0]; ;}
break;
- case 120:
-#line 414 "pars0grm.y"
+ case 124:
+#line 426 "pars0grm.y"
{ yyval = pars_if_statement(yyvsp[-5], yyvsp[-3], yyvsp[-2]); ;}
break;
- case 121:
-#line 420 "pars0grm.y"
+ case 125:
+#line 432 "pars0grm.y"
{ yyval = pars_while_statement(yyvsp[-4], yyvsp[-2]); ;}
break;
- case 122:
-#line 428 "pars0grm.y"
+ case 126:
+#line 440 "pars0grm.y"
{ yyval = pars_for_statement(yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-2]); ;}
break;
- case 123:
-#line 432 "pars0grm.y"
+ case 127:
+#line 444 "pars0grm.y"
+ { yyval = pars_exit_statement(); ;}
+ break;
+
+ case 128:
+#line 448 "pars0grm.y"
{ yyval = pars_return_statement(); ;}
break;
- case 124:
-#line 437 "pars0grm.y"
+ case 129:
+#line 453 "pars0grm.y"
{ yyval = pars_open_statement(
ROW_SEL_OPEN_CURSOR, yyvsp[0]); ;}
break;
- case 125:
-#line 443 "pars0grm.y"
+ case 130:
+#line 459 "pars0grm.y"
{ yyval = pars_open_statement(
ROW_SEL_CLOSE_CURSOR, yyvsp[0]); ;}
break;
- case 126:
-#line 449 "pars0grm.y"
- { yyval = pars_fetch_statement(yyvsp[-2], yyvsp[0]); ;}
+ case 131:
+#line 465 "pars0grm.y"
+ { yyval = pars_fetch_statement(yyvsp[-2], yyvsp[0], NULL); ;}
break;
- case 127:
-#line 454 "pars0grm.y"
- { yyval = pars_column_def(yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); ;}
+ case 132:
+#line 467 "pars0grm.y"
+ { yyval = pars_fetch_statement(yyvsp[-2], NULL, yyvsp[0]); ;}
break;
- case 128:
-#line 458 "pars0grm.y"
+ case 133:
+#line 472 "pars0grm.y"
+ { yyval = pars_column_def(yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); ;}
+ break;
+
+ case 134:
+#line 476 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 129:
-#line 460 "pars0grm.y"
+ case 135:
+#line 478 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 130:
-#line 464 "pars0grm.y"
+ case 136:
+#line 482 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 131:
-#line 466 "pars0grm.y"
+ case 137:
+#line 484 "pars0grm.y"
{ yyval = yyvsp[-1]; ;}
break;
- case 132:
-#line 470 "pars0grm.y"
+ case 138:
+#line 488 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 133:
-#line 472 "pars0grm.y"
+ case 139:
+#line 490 "pars0grm.y"
{ yyval = &pars_int_token;
/* pass any non-NULL pointer */ ;}
break;
- case 134:
-#line 477 "pars0grm.y"
+ case 140:
+#line 495 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 135:
-#line 479 "pars0grm.y"
+ case 141:
+#line 497 "pars0grm.y"
{ yyval = &pars_int_token;
/* pass any non-NULL pointer */ ;}
break;
- case 136:
-#line 486 "pars0grm.y"
+ case 142:
+#line 502 "pars0grm.y"
+ { yyval = NULL; ;}
+ break;
+
+ case 143:
+#line 504 "pars0grm.y"
+ { yyval = &pars_int_token;
+ /* pass any non-NULL pointer */ ;}
+ break;
+
+ case 144:
+#line 511 "pars0grm.y"
{ yyval = pars_create_table(yyvsp[-4], yyvsp[-2], yyvsp[0]); ;}
break;
- case 137:
-#line 490 "pars0grm.y"
+ case 145:
+#line 515 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 138:
-#line 492 "pars0grm.y"
+ case 146:
+#line 517 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 139:
-#line 496 "pars0grm.y"
+ case 147:
+#line 521 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 140:
-#line 497 "pars0grm.y"
+ case 148:
+#line 522 "pars0grm.y"
{ yyval = &pars_unique_token; ;}
break;
- case 141:
-#line 501 "pars0grm.y"
+ case 149:
+#line 526 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 142:
-#line 502 "pars0grm.y"
+ case 150:
+#line 527 "pars0grm.y"
{ yyval = &pars_clustered_token; ;}
break;
- case 143:
-#line 510 "pars0grm.y"
+ case 151:
+#line 535 "pars0grm.y"
{ yyval = pars_create_index(yyvsp[-8], yyvsp[-7], yyvsp[-5], yyvsp[-3], yyvsp[-1]); ;}
break;
- case 144:
-#line 515 "pars0grm.y"
+ case 152:
+#line 540 "pars0grm.y"
{ yyval = pars_commit_statement(); ;}
break;
- case 145:
-#line 520 "pars0grm.y"
+ case 153:
+#line 545 "pars0grm.y"
{ yyval = pars_rollback_statement(); ;}
break;
- case 146:
-#line 524 "pars0grm.y"
+ case 154:
+#line 549 "pars0grm.y"
{ yyval = &pars_int_token; ;}
break;
- case 147:
-#line 525 "pars0grm.y"
+ case 155:
+#line 550 "pars0grm.y"
{ yyval = &pars_int_token; ;}
break;
- case 148:
-#line 526 "pars0grm.y"
+ case 156:
+#line 551 "pars0grm.y"
{ yyval = &pars_char_token; ;}
break;
- case 149:
-#line 527 "pars0grm.y"
+ case 157:
+#line 552 "pars0grm.y"
{ yyval = &pars_binary_token; ;}
break;
- case 150:
-#line 528 "pars0grm.y"
+ case 158:
+#line 553 "pars0grm.y"
{ yyval = &pars_blob_token; ;}
break;
- case 151:
-#line 533 "pars0grm.y"
+ case 159:
+#line 558 "pars0grm.y"
{ yyval = pars_parameter_declaration(yyvsp[-2],
PARS_INPUT, yyvsp[0]); ;}
break;
- case 152:
-#line 536 "pars0grm.y"
+ case 160:
+#line 561 "pars0grm.y"
{ yyval = pars_parameter_declaration(yyvsp[-2],
PARS_OUTPUT, yyvsp[0]); ;}
break;
- case 153:
-#line 541 "pars0grm.y"
+ case 161:
+#line 566 "pars0grm.y"
{ yyval = NULL; ;}
break;
- case 154:
-#line 542 "pars0grm.y"
+ case 162:
+#line 567 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ;}
break;
- case 155:
-#line 544 "pars0grm.y"
+ case 163:
+#line 569 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;}
break;
- case 156:
-#line 549 "pars0grm.y"
+ case 164:
+#line 574 "pars0grm.y"
{ yyval = pars_variable_declaration(yyvsp[-2], yyvsp[-1]); ;}
break;
- case 160:
-#line 561 "pars0grm.y"
+ case 168:
+#line 586 "pars0grm.y"
{ yyval = pars_cursor_declaration(yyvsp[-3], yyvsp[-1]); ;}
break;
- case 164:
-#line 577 "pars0grm.y"
+ case 169:
+#line 591 "pars0grm.y"
+ { yyval = pars_function_declaration(yyvsp[-1]); ;}
+ break;
+
+ case 175:
+#line 612 "pars0grm.y"
{ yyval = pars_procedure_definition(yyvsp[-9], yyvsp[-7],
yyvsp[-1]); ;}
break;
@@ -2265,7 +2333,7 @@ yyreduce:
}
/* Line 1010 of yacc.c. */
-#line 2269 "pars0grm.tab.c"
+#line 2337 "pars0grm.tab.c"
yyvsp -= yylen;
yyssp -= yylen;
@@ -2490,6 +2558,6 @@ yyreturn:
}
-#line 581 "pars0grm.y"
+#line 616 "pars0grm.y"
diff --git a/storage/innobase/pars/pars0grm.h b/storage/innobase/pars/pars0grm.h
index e35fcf47692..996fc37f13b 100644
--- a/storage/innobase/pars/pars0grm.h
+++ b/storage/innobase/pars/pars0grm.h
@@ -32,177 +32,187 @@
PARS_INT_LIT = 258,
PARS_FLOAT_LIT = 259,
PARS_STR_LIT = 260,
- PARS_NULL_LIT = 261,
- PARS_ID_TOKEN = 262,
- PARS_AND_TOKEN = 263,
- PARS_OR_TOKEN = 264,
- PARS_NOT_TOKEN = 265,
- PARS_GE_TOKEN = 266,
- PARS_LE_TOKEN = 267,
- PARS_NE_TOKEN = 268,
- PARS_PROCEDURE_TOKEN = 269,
- PARS_IN_TOKEN = 270,
- PARS_OUT_TOKEN = 271,
- PARS_BINARY_TOKEN = 272,
- PARS_BLOB_TOKEN = 273,
- PARS_INT_TOKEN = 274,
- PARS_INTEGER_TOKEN = 275,
- PARS_FLOAT_TOKEN = 276,
- PARS_CHAR_TOKEN = 277,
- PARS_IS_TOKEN = 278,
- PARS_BEGIN_TOKEN = 279,
- PARS_END_TOKEN = 280,
- PARS_IF_TOKEN = 281,
- PARS_THEN_TOKEN = 282,
- PARS_ELSE_TOKEN = 283,
- PARS_ELSIF_TOKEN = 284,
- PARS_LOOP_TOKEN = 285,
- PARS_WHILE_TOKEN = 286,
- PARS_RETURN_TOKEN = 287,
- PARS_SELECT_TOKEN = 288,
- PARS_SUM_TOKEN = 289,
- PARS_COUNT_TOKEN = 290,
- PARS_DISTINCT_TOKEN = 291,
- PARS_FROM_TOKEN = 292,
- PARS_WHERE_TOKEN = 293,
- PARS_FOR_TOKEN = 294,
- PARS_DDOT_TOKEN = 295,
- PARS_CONSISTENT_TOKEN = 296,
- PARS_READ_TOKEN = 297,
- PARS_ORDER_TOKEN = 298,
- PARS_BY_TOKEN = 299,
- PARS_ASC_TOKEN = 300,
- PARS_DESC_TOKEN = 301,
- PARS_INSERT_TOKEN = 302,
- PARS_INTO_TOKEN = 303,
- PARS_VALUES_TOKEN = 304,
- PARS_UPDATE_TOKEN = 305,
- PARS_SET_TOKEN = 306,
- PARS_DELETE_TOKEN = 307,
- PARS_CURRENT_TOKEN = 308,
- PARS_OF_TOKEN = 309,
- PARS_CREATE_TOKEN = 310,
- PARS_TABLE_TOKEN = 311,
- PARS_INDEX_TOKEN = 312,
- PARS_UNIQUE_TOKEN = 313,
- PARS_CLUSTERED_TOKEN = 314,
- PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315,
- PARS_ON_TOKEN = 316,
- PARS_ASSIGN_TOKEN = 317,
- PARS_DECLARE_TOKEN = 318,
- PARS_CURSOR_TOKEN = 319,
- PARS_SQL_TOKEN = 320,
- PARS_OPEN_TOKEN = 321,
- PARS_FETCH_TOKEN = 322,
- PARS_CLOSE_TOKEN = 323,
- PARS_NOTFOUND_TOKEN = 324,
- PARS_TO_CHAR_TOKEN = 325,
- PARS_TO_NUMBER_TOKEN = 326,
- PARS_TO_BINARY_TOKEN = 327,
- PARS_BINARY_TO_NUMBER_TOKEN = 328,
- PARS_SUBSTR_TOKEN = 329,
- PARS_REPLSTR_TOKEN = 330,
- PARS_CONCAT_TOKEN = 331,
- PARS_INSTR_TOKEN = 332,
- PARS_LENGTH_TOKEN = 333,
- PARS_SYSDATE_TOKEN = 334,
- PARS_PRINTF_TOKEN = 335,
- PARS_ASSERT_TOKEN = 336,
- PARS_RND_TOKEN = 337,
- PARS_RND_STR_TOKEN = 338,
- PARS_ROW_PRINTF_TOKEN = 339,
- PARS_COMMIT_TOKEN = 340,
- PARS_ROLLBACK_TOKEN = 341,
- PARS_WORK_TOKEN = 342,
- NEG = 343
+ PARS_FIXBINARY_LIT = 261,
+ PARS_BLOB_LIT = 262,
+ PARS_NULL_LIT = 263,
+ PARS_ID_TOKEN = 264,
+ PARS_AND_TOKEN = 265,
+ PARS_OR_TOKEN = 266,
+ PARS_NOT_TOKEN = 267,
+ PARS_GE_TOKEN = 268,
+ PARS_LE_TOKEN = 269,
+ PARS_NE_TOKEN = 270,
+ PARS_PROCEDURE_TOKEN = 271,
+ PARS_IN_TOKEN = 272,
+ PARS_OUT_TOKEN = 273,
+ PARS_BINARY_TOKEN = 274,
+ PARS_BLOB_TOKEN = 275,
+ PARS_INT_TOKEN = 276,
+ PARS_INTEGER_TOKEN = 277,
+ PARS_FLOAT_TOKEN = 278,
+ PARS_CHAR_TOKEN = 279,
+ PARS_IS_TOKEN = 280,
+ PARS_BEGIN_TOKEN = 281,
+ PARS_END_TOKEN = 282,
+ PARS_IF_TOKEN = 283,
+ PARS_THEN_TOKEN = 284,
+ PARS_ELSE_TOKEN = 285,
+ PARS_ELSIF_TOKEN = 286,
+ PARS_LOOP_TOKEN = 287,
+ PARS_WHILE_TOKEN = 288,
+ PARS_RETURN_TOKEN = 289,
+ PARS_SELECT_TOKEN = 290,
+ PARS_SUM_TOKEN = 291,
+ PARS_COUNT_TOKEN = 292,
+ PARS_DISTINCT_TOKEN = 293,
+ PARS_FROM_TOKEN = 294,
+ PARS_WHERE_TOKEN = 295,
+ PARS_FOR_TOKEN = 296,
+ PARS_DDOT_TOKEN = 297,
+ PARS_CONSISTENT_TOKEN = 298,
+ PARS_READ_TOKEN = 299,
+ PARS_ORDER_TOKEN = 300,
+ PARS_BY_TOKEN = 301,
+ PARS_ASC_TOKEN = 302,
+ PARS_DESC_TOKEN = 303,
+ PARS_INSERT_TOKEN = 304,
+ PARS_INTO_TOKEN = 305,
+ PARS_VALUES_TOKEN = 306,
+ PARS_UPDATE_TOKEN = 307,
+ PARS_SET_TOKEN = 308,
+ PARS_DELETE_TOKEN = 309,
+ PARS_CURRENT_TOKEN = 310,
+ PARS_OF_TOKEN = 311,
+ PARS_CREATE_TOKEN = 312,
+ PARS_TABLE_TOKEN = 313,
+ PARS_INDEX_TOKEN = 314,
+ PARS_UNIQUE_TOKEN = 315,
+ PARS_CLUSTERED_TOKEN = 316,
+ PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 317,
+ PARS_ON_TOKEN = 318,
+ PARS_ASSIGN_TOKEN = 319,
+ PARS_DECLARE_TOKEN = 320,
+ PARS_CURSOR_TOKEN = 321,
+ PARS_SQL_TOKEN = 322,
+ PARS_OPEN_TOKEN = 323,
+ PARS_FETCH_TOKEN = 324,
+ PARS_CLOSE_TOKEN = 325,
+ PARS_NOTFOUND_TOKEN = 326,
+ PARS_TO_CHAR_TOKEN = 327,
+ PARS_TO_NUMBER_TOKEN = 328,
+ PARS_TO_BINARY_TOKEN = 329,
+ PARS_BINARY_TO_NUMBER_TOKEN = 330,
+ PARS_SUBSTR_TOKEN = 331,
+ PARS_REPLSTR_TOKEN = 332,
+ PARS_CONCAT_TOKEN = 333,
+ PARS_INSTR_TOKEN = 334,
+ PARS_LENGTH_TOKEN = 335,
+ PARS_SYSDATE_TOKEN = 336,
+ PARS_PRINTF_TOKEN = 337,
+ PARS_ASSERT_TOKEN = 338,
+ PARS_RND_TOKEN = 339,
+ PARS_RND_STR_TOKEN = 340,
+ PARS_ROW_PRINTF_TOKEN = 341,
+ PARS_COMMIT_TOKEN = 342,
+ PARS_ROLLBACK_TOKEN = 343,
+ PARS_WORK_TOKEN = 344,
+ PARS_UNSIGNED_TOKEN = 345,
+ PARS_EXIT_TOKEN = 346,
+ PARS_FUNCTION_TOKEN = 347,
+ NEG = 348
};
#endif
#define PARS_INT_LIT 258
#define PARS_FLOAT_LIT 259
#define PARS_STR_LIT 260
-#define PARS_NULL_LIT 261
-#define PARS_ID_TOKEN 262
-#define PARS_AND_TOKEN 263
-#define PARS_OR_TOKEN 264
-#define PARS_NOT_TOKEN 265
-#define PARS_GE_TOKEN 266
-#define PARS_LE_TOKEN 267
-#define PARS_NE_TOKEN 268
-#define PARS_PROCEDURE_TOKEN 269
-#define PARS_IN_TOKEN 270
-#define PARS_OUT_TOKEN 271
-#define PARS_BINARY_TOKEN 272
-#define PARS_BLOB_TOKEN 273
-#define PARS_INT_TOKEN 274
-#define PARS_INTEGER_TOKEN 275
-#define PARS_FLOAT_TOKEN 276
-#define PARS_CHAR_TOKEN 277
-#define PARS_IS_TOKEN 278
-#define PARS_BEGIN_TOKEN 279
-#define PARS_END_TOKEN 280
-#define PARS_IF_TOKEN 281
-#define PARS_THEN_TOKEN 282
-#define PARS_ELSE_TOKEN 283
-#define PARS_ELSIF_TOKEN 284
-#define PARS_LOOP_TOKEN 285
-#define PARS_WHILE_TOKEN 286
-#define PARS_RETURN_TOKEN 287
-#define PARS_SELECT_TOKEN 288
-#define PARS_SUM_TOKEN 289
-#define PARS_COUNT_TOKEN 290
-#define PARS_DISTINCT_TOKEN 291
-#define PARS_FROM_TOKEN 292
-#define PARS_WHERE_TOKEN 293
-#define PARS_FOR_TOKEN 294
-#define PARS_DDOT_TOKEN 295
-#define PARS_CONSISTENT_TOKEN 296
-#define PARS_READ_TOKEN 297
-#define PARS_ORDER_TOKEN 298
-#define PARS_BY_TOKEN 299
-#define PARS_ASC_TOKEN 300
-#define PARS_DESC_TOKEN 301
-#define PARS_INSERT_TOKEN 302
-#define PARS_INTO_TOKEN 303
-#define PARS_VALUES_TOKEN 304
-#define PARS_UPDATE_TOKEN 305
-#define PARS_SET_TOKEN 306
-#define PARS_DELETE_TOKEN 307
-#define PARS_CURRENT_TOKEN 308
-#define PARS_OF_TOKEN 309
-#define PARS_CREATE_TOKEN 310
-#define PARS_TABLE_TOKEN 311
-#define PARS_INDEX_TOKEN 312
-#define PARS_UNIQUE_TOKEN 313
-#define PARS_CLUSTERED_TOKEN 314
-#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315
-#define PARS_ON_TOKEN 316
-#define PARS_ASSIGN_TOKEN 317
-#define PARS_DECLARE_TOKEN 318
-#define PARS_CURSOR_TOKEN 319
-#define PARS_SQL_TOKEN 320
-#define PARS_OPEN_TOKEN 321
-#define PARS_FETCH_TOKEN 322
-#define PARS_CLOSE_TOKEN 323
-#define PARS_NOTFOUND_TOKEN 324
-#define PARS_TO_CHAR_TOKEN 325
-#define PARS_TO_NUMBER_TOKEN 326
-#define PARS_TO_BINARY_TOKEN 327
-#define PARS_BINARY_TO_NUMBER_TOKEN 328
-#define PARS_SUBSTR_TOKEN 329
-#define PARS_REPLSTR_TOKEN 330
-#define PARS_CONCAT_TOKEN 331
-#define PARS_INSTR_TOKEN 332
-#define PARS_LENGTH_TOKEN 333
-#define PARS_SYSDATE_TOKEN 334
-#define PARS_PRINTF_TOKEN 335
-#define PARS_ASSERT_TOKEN 336
-#define PARS_RND_TOKEN 337
-#define PARS_RND_STR_TOKEN 338
-#define PARS_ROW_PRINTF_TOKEN 339
-#define PARS_COMMIT_TOKEN 340
-#define PARS_ROLLBACK_TOKEN 341
-#define PARS_WORK_TOKEN 342
-#define NEG 343
+#define PARS_FIXBINARY_LIT 261
+#define PARS_BLOB_LIT 262
+#define PARS_NULL_LIT 263
+#define PARS_ID_TOKEN 264
+#define PARS_AND_TOKEN 265
+#define PARS_OR_TOKEN 266
+#define PARS_NOT_TOKEN 267
+#define PARS_GE_TOKEN 268
+#define PARS_LE_TOKEN 269
+#define PARS_NE_TOKEN 270
+#define PARS_PROCEDURE_TOKEN 271
+#define PARS_IN_TOKEN 272
+#define PARS_OUT_TOKEN 273
+#define PARS_BINARY_TOKEN 274
+#define PARS_BLOB_TOKEN 275
+#define PARS_INT_TOKEN 276
+#define PARS_INTEGER_TOKEN 277
+#define PARS_FLOAT_TOKEN 278
+#define PARS_CHAR_TOKEN 279
+#define PARS_IS_TOKEN 280
+#define PARS_BEGIN_TOKEN 281
+#define PARS_END_TOKEN 282
+#define PARS_IF_TOKEN 283
+#define PARS_THEN_TOKEN 284
+#define PARS_ELSE_TOKEN 285
+#define PARS_ELSIF_TOKEN 286
+#define PARS_LOOP_TOKEN 287
+#define PARS_WHILE_TOKEN 288
+#define PARS_RETURN_TOKEN 289
+#define PARS_SELECT_TOKEN 290
+#define PARS_SUM_TOKEN 291
+#define PARS_COUNT_TOKEN 292
+#define PARS_DISTINCT_TOKEN 293
+#define PARS_FROM_TOKEN 294
+#define PARS_WHERE_TOKEN 295
+#define PARS_FOR_TOKEN 296
+#define PARS_DDOT_TOKEN 297
+#define PARS_CONSISTENT_TOKEN 298
+#define PARS_READ_TOKEN 299
+#define PARS_ORDER_TOKEN 300
+#define PARS_BY_TOKEN 301
+#define PARS_ASC_TOKEN 302
+#define PARS_DESC_TOKEN 303
+#define PARS_INSERT_TOKEN 304
+#define PARS_INTO_TOKEN 305
+#define PARS_VALUES_TOKEN 306
+#define PARS_UPDATE_TOKEN 307
+#define PARS_SET_TOKEN 308
+#define PARS_DELETE_TOKEN 309
+#define PARS_CURRENT_TOKEN 310
+#define PARS_OF_TOKEN 311
+#define PARS_CREATE_TOKEN 312
+#define PARS_TABLE_TOKEN 313
+#define PARS_INDEX_TOKEN 314
+#define PARS_UNIQUE_TOKEN 315
+#define PARS_CLUSTERED_TOKEN 316
+#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 317
+#define PARS_ON_TOKEN 318
+#define PARS_ASSIGN_TOKEN 319
+#define PARS_DECLARE_TOKEN 320
+#define PARS_CURSOR_TOKEN 321
+#define PARS_SQL_TOKEN 322
+#define PARS_OPEN_TOKEN 323
+#define PARS_FETCH_TOKEN 324
+#define PARS_CLOSE_TOKEN 325
+#define PARS_NOTFOUND_TOKEN 326
+#define PARS_TO_CHAR_TOKEN 327
+#define PARS_TO_NUMBER_TOKEN 328
+#define PARS_TO_BINARY_TOKEN 329
+#define PARS_BINARY_TO_NUMBER_TOKEN 330
+#define PARS_SUBSTR_TOKEN 331
+#define PARS_REPLSTR_TOKEN 332
+#define PARS_CONCAT_TOKEN 333
+#define PARS_INSTR_TOKEN 334
+#define PARS_LENGTH_TOKEN 335
+#define PARS_SYSDATE_TOKEN 336
+#define PARS_PRINTF_TOKEN 337
+#define PARS_ASSERT_TOKEN 338
+#define PARS_RND_TOKEN 339
+#define PARS_RND_STR_TOKEN 340
+#define PARS_ROW_PRINTF_TOKEN 341
+#define PARS_COMMIT_TOKEN 342
+#define PARS_ROLLBACK_TOKEN 343
+#define PARS_WORK_TOKEN 344
+#define PARS_UNSIGNED_TOKEN 345
+#define PARS_EXIT_TOKEN 346
+#define PARS_FUNCTION_TOKEN 347
+#define NEG 348
diff --git a/storage/innobase/pars/pars0grm.y b/storage/innobase/pars/pars0grm.y
index 435025d7386..7f13312fc6e 100644
--- a/storage/innobase/pars/pars0grm.y
+++ b/storage/innobase/pars/pars0grm.y
@@ -29,10 +29,12 @@ que_node_t */
int
yylex(void);
%}
-
+
%token PARS_INT_LIT
%token PARS_FLOAT_LIT
%token PARS_STR_LIT
+%token PARS_FIXBINARY_LIT
+%token PARS_BLOB_LIT
%token PARS_NULL_LIT
%token PARS_ID_TOKEN
%token PARS_AND_TOKEN
@@ -115,6 +117,9 @@ yylex(void);
%token PARS_COMMIT_TOKEN
%token PARS_ROLLBACK_TOKEN
%token PARS_WORK_TOKEN
+%token PARS_UNSIGNED_TOKEN
+%token PARS_EXIT_TOKEN
+%token PARS_FUNCTION_TOKEN
%left PARS_AND_TOKEN PARS_OR_TOKEN
%left PARS_NOT_TOKEN
@@ -133,6 +138,7 @@ statement:
| predefined_procedure_call ';'
| while_statement ';'
| for_statement ';'
+ | exit_statement ';'
| if_statement ';'
| return_statement ';'
| assignment_statement ';'
@@ -165,6 +171,8 @@ exp:
| PARS_INT_LIT { $$ = $1;}
| PARS_FLOAT_LIT { $$ = $1;}
| PARS_STR_LIT { $$ = $1;}
+ | PARS_FIXBINARY_LIT { $$ = $1;}
+ | PARS_BLOB_LIT { $$ = $1;}
| PARS_NULL_LIT { $$ = $1;}
| PARS_SQL_TOKEN { $$ = $1;}
| exp '+' exp { $$ = pars_op('+', $1, $3); }
@@ -225,6 +233,10 @@ predefined_procedure_name:
| PARS_ASSERT_TOKEN { $$ = &pars_assert_token; }
;
+user_function_call:
+ PARS_ID_TOKEN '(' ')' { $$ = $1; }
+;
+
table_list:
PARS_ID_TOKEN { $$ = que_node_list_add_last(NULL, $1); }
| table_list ',' PARS_ID_TOKEN
@@ -262,14 +274,14 @@ select_item:
que_node_list_add_last(NULL,
$3)); }
;
-
+
select_item_list:
/* Nothing */ { $$ = NULL; }
| select_item { $$ = que_node_list_add_last(NULL, $1); }
| select_item_list ',' select_item
{ $$ = que_node_list_add_last($1, $3); }
;
-
+
select_list:
'*' { $$ = pars_select_list(&pars_star_denoter,
NULL); }
@@ -377,7 +389,7 @@ delete_statement_positioned:
delete_statement_start
cursor_positioned { $$ = pars_update_statement($1, $2, NULL); }
;
-
+
row_printf_statement:
PARS_ROW_PRINTF_TOKEN select_statement
{ $$ = pars_row_printf_statement($2); }
@@ -428,6 +440,10 @@ for_statement:
{ $$ = pars_for_statement($2, $4, $6, $8); }
;
+exit_statement:
+ PARS_EXIT_TOKEN { $$ = pars_exit_statement(); }
+;
+
return_statement:
PARS_RETURN_TOKEN { $$ = pars_return_statement(); }
;
@@ -446,12 +462,14 @@ close_cursor_statement:
fetch_statement:
PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN variable_list
- { $$ = pars_fetch_statement($2, $4); }
+ { $$ = pars_fetch_statement($2, $4, NULL); }
+ | PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN user_function_call
+ { $$ = pars_fetch_statement($2, NULL, $4); }
;
column_def:
- PARS_ID_TOKEN type_name opt_column_len opt_not_null
- { $$ = pars_column_def($1, $2, $3, $4); }
+ PARS_ID_TOKEN type_name opt_column_len opt_unsigned opt_not_null
+ { $$ = pars_column_def($1, $2, $3, $4, $5); }
;
column_def_list:
@@ -466,6 +484,13 @@ opt_column_len:
{ $$ = $2; }
;
+opt_unsigned:
+ /* Nothing */ { $$ = NULL; }
+ | PARS_UNSIGNED_TOKEN
+ { $$ = &pars_int_token;
+ /* pass any non-NULL pointer */ }
+;
+
opt_not_null:
/* Nothing */ { $$ = NULL; }
| PARS_NOT_TOKEN PARS_NULL_LIT
@@ -479,7 +504,7 @@ not_fit_in_memory:
{ $$ = &pars_int_token;
/* pass any non-NULL pointer */ }
;
-
+
create_table:
PARS_CREATE_TOKEN PARS_TABLE_TOKEN
PARS_ID_TOKEN '(' column_def_list ')'
@@ -550,8 +575,8 @@ variable_declaration:
;
variable_declaration_list:
- /* Nothing */
- | variable_declaration
+ /* Nothing */
+ | variable_declaration
| variable_declaration_list variable_declaration
;
@@ -561,10 +586,20 @@ cursor_declaration:
{ $$ = pars_cursor_declaration($3, $5); }
;
+function_declaration:
+ PARS_DECLARE_TOKEN PARS_FUNCTION_TOKEN PARS_ID_TOKEN ';'
+ { $$ = pars_function_declaration($3); }
+;
+
+declaration:
+ cursor_declaration
+ | function_declaration
+;
+
declaration_list:
/* Nothing */
- | cursor_declaration
- | declaration_list cursor_declaration
+ | declaration
+ | declaration_list declaration
;
procedure_definition:
@@ -577,5 +612,5 @@ procedure_definition:
PARS_END_TOKEN { $$ = pars_procedure_definition($2, $4,
$10); }
;
-
+
%%
diff --git a/storage/innobase/pars/pars0lex.l b/storage/innobase/pars/pars0lex.l
index 4224536d49e..ab1fe446924 100644
--- a/storage/innobase/pars/pars0lex.l
+++ b/storage/innobase/pars/pars0lex.l
@@ -12,27 +12,11 @@ not automatically generate them from pars0grm.y and pars0lex.l.
How to make the InnoDB parser and lexer C files:
-1. First do
- bison -d pars0grm.y
- That generates pars0grm.tab.c and pars0grm.tab.h.
+1. Run ./make_flex.sh to generate lexer files.
-2. Rename pars0grm.tab.c to pars0grm.c and pars0grm.tab.h to pars0grm.h.
+2. Run ./make_bison.sh to generate parser files.
-3. Copy pars0grm.h also to /innobase/include
-
-4. Do
- flex pars0lex.l
- That generates lex.yy.c.
-
-5. Rename lex.yy.c to lexyy.c.
-
-6. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
- (Needed for AIX)
-
-7. 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
+These instructions seem to work at least with bison-1.875d and flex-2.5.31 on
Linux.
*******************************************************/
@@ -96,11 +80,14 @@ string_append(
}
%}
-
+
DIGIT [0-9]
ID [a-z_A-Z][a-z_A-Z0-9]*
+BOUND_LIT \:[a-z_A-Z0-9]+
+
%x comment
%x quoted
+%x id
%%
{DIGIT}+ {
@@ -115,6 +102,15 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
return(PARS_FLOAT_LIT);
}
+{BOUND_LIT} {
+ ulint type;
+
+ yylval = sym_tab_add_bound_lit(pars_sym_tab_global,
+ yytext + 1, &type);
+
+ return(type);
+}
+
"'" {
/* Quoted character string literals are handled in an explicit
start state 'quoted'. This state is entered and the buffer for
@@ -153,6 +149,45 @@ In the state 'quoted', only two actions are possible (defined below). */
}
}
+\" {
+/* Quoted identifiers are handled in an explicit start state 'id'.
+This state is entered and the buffer for the scanned string is emptied
+upon encountering a starting quote.
+
+In the state 'id', only two actions are possible (defined below). */
+ BEGIN(id);
+ stringbuf_len = 0;
+}
+<id>[^\"]+ {
+ /* Got a sequence of characters other than '"':
+ append to string buffer */
+ string_append(yytext, yyleng);
+}
+<id>\"+ {
+ /* Got a sequence of '"' characters:
+ append half of them to string buffer,
+ as '""' represents a single '"'.
+ We apply truncating division,
+ so that '"""' will result in '"'. */
+
+ string_append(yytext, yyleng / 2);
+
+ /* If we got an odd number of quotes, then the
+ last quote we got is the terminating quote.
+ At the end of the string, we return to the
+ initial start state and report the scanned
+ identifier. */
+
+ if (yyleng % 2) {
+ BEGIN(INITIAL);
+ yylval = sym_tab_add_id(
+ pars_sym_tab_global,
+ (byte*) stringbuf, stringbuf_len);
+
+ return(PARS_ID_TOKEN);
+ }
+}
+
"NULL" {
yylval = sym_tab_add_null_lit(pars_sym_tab_global);
@@ -462,6 +497,18 @@ In the state 'quoted', only two actions are possible (defined below). */
return(PARS_WORK_TOKEN);
}
+"UNSIGNED" {
+ return(PARS_UNSIGNED_TOKEN);
+}
+
+"EXIT" {
+ return(PARS_EXIT_TOKEN);
+}
+
+"FUNCTION" {
+ return(PARS_FUNCTION_TOKEN);
+}
+
{ID} {
yylval = sym_tab_add_id(pars_sym_tab_global,
(byte*)yytext,
diff --git a/storage/innobase/pars/pars0opt.c b/storage/innobase/pars/pars0opt.c
index bb41b5da074..4037f50cb5c 100644
--- a/storage/innobase/pars/pars0opt.c
+++ b/storage/innobase/pars/pars0opt.c
@@ -313,7 +313,6 @@ opt_calc_index_goodness(
ulint goodness;
ulint n_fields;
ulint col_no;
- ulint mix_id_col_no;
ulint op;
ulint j;
@@ -326,8 +325,6 @@ opt_calc_index_goodness(
n_fields = dict_index_get_n_unique_in_tree(index);
- mix_id_col_no = dict_table_get_sys_col_no(index->table, DATA_MIX_ID);
-
for (j = 0; j < n_fields; j++) {
col_no = dict_index_get_nth_col_no(index, j);
@@ -335,13 +332,7 @@ opt_calc_index_goodness(
exp = opt_look_for_col_in_cond_before(OPT_EQUAL, col_no,
sel_node->search_cond,
sel_node, nth_table, &op);
- if (col_no == mix_id_col_no) {
- ut_ad(exp == NULL);
-
- index_plan[j] = NULL;
- *last_op = '=';
- goodness += 4;
- } else if (exp) {
+ if (exp) {
/* The value for this column is exactly known already
at this stage of the join */
@@ -531,7 +522,6 @@ opt_search_plan_for_table(
warning */
ulint best_goodness;
ulint best_last_op = 0; /* remove warning */
- ulint mix_id_pos;
que_node_t* index_plan[256];
que_node_t* best_index_plan[256];
@@ -601,26 +591,6 @@ opt_search_plan_for_table(
plan->unique_search = FALSE;
}
- if ((table->type != DICT_TABLE_ORDINARY)
- && (best_index->type & DICT_CLUSTERED)) {
-
- plan->mixed_index = TRUE;
-
- mix_id_pos = table->mix_len;
-
- if (mix_id_pos < n_fields) {
- /* We have to add the mix id as a (string) literal
- expression to the tuple_exps */
-
- plan->tuple_exps[mix_id_pos] =
- sym_tab_add_str_lit(pars_sym_tab_global,
- table->mix_id_buf,
- table->mix_id_len);
- }
- } else {
- plan->mixed_index = FALSE;
- }
-
plan->old_vers_heap = NULL;
btr_pcur_init(&(plan->pcur));
@@ -1055,7 +1025,6 @@ opt_clust_access(
dict_table_t* table;
dict_index_t* clust_index;
dict_index_t* index;
- dfield_t* dfield;
mem_heap_t* heap;
ulint n_fields;
ulint pos;
@@ -1109,22 +1078,7 @@ opt_clust_access(
*(plan->clust_map + i) = pos;
- ut_ad((pos != ULINT_UNDEFINED)
- || ((table->type == DICT_TABLE_CLUSTER_MEMBER)
- && (i == table->mix_len)));
- }
-
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- /* Preset the mix id field to the mix id constant */
-
- dfield = dtuple_get_nth_field(plan->clust_ref, table->mix_len);
-
- dfield_set_data(dfield, mem_heap_alloc(heap,
- table->mix_id_len),
- table->mix_id_len);
- ut_memcpy(dfield_get_data(dfield), table->mix_id_buf,
- table->mix_id_len);
+ ut_ad(pos != ULINT_UNDEFINED);
}
}
diff --git a/storage/innobase/pars/pars0pars.c b/storage/innobase/pars/pars0pars.c
index 1b7a3a653a9..7ef2f65c724 100644
--- a/storage/innobase/pars/pars0pars.c
+++ b/storage/innobase/pars/pars0pars.c
@@ -373,14 +373,15 @@ pars_resolve_exp_variables_and_types(
}
/* Not resolved yet: look in the symbol table for a variable
- or a cursor with the same name */
+ or a cursor or a function with the same name */
node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
while (node) {
if (node->resolved
&& ((node->token_type == SYM_VAR)
- || (node->token_type == SYM_CURSOR))
+ || (node->token_type == SYM_CURSOR)
+ || (node->token_type == SYM_FUNCTION))
&& node->name
&& (sym_node->name_len == node->name_len)
&& (ut_memcmp(sym_node->name, node->name,
@@ -486,7 +487,7 @@ pars_resolve_exp_columns(
while (t_node) {
table = t_node->table;
- n_cols = dict_table_get_n_user_cols(table);
+ n_cols = dict_table_get_n_cols(table);
for (i = 0; i < n_cols; i++) {
col = dict_table_get_nth_col(table, i);
@@ -787,6 +788,26 @@ pars_cursor_declaration(
}
/*************************************************************************
+Parses a function declaration. */
+
+que_node_t*
+pars_function_declaration(
+/*======================*/
+ /* out: sym_node */
+ sym_node_t* sym_node) /* in: function id node in the symbol
+ table */
+{
+ sym_node->resolved = TRUE;
+ sym_node->token_type = SYM_FUNCTION;
+
+ /* Check that the function exists. */
+ ut_a(pars_info_get_user_func(pars_sym_tab_global->info,
+ sym_node->name));
+
+ return(sym_node);
+}
+
+/*************************************************************************
Parses a delete or update statement start. */
upd_node_t*
@@ -1085,6 +1106,8 @@ pars_set_dfield_type(
pars_res_word_t* type, /* in: pointer to a type
token */
ulint len, /* in: length, or 0 */
+ ibool is_unsigned, /* in: if TRUE, column is
+ UNSIGNED. */
ibool is_not_null) /* in: if TRUE, column is
NOT NULL. */
{
@@ -1094,48 +1117,30 @@ pars_set_dfield_type(
flags |= DATA_NOT_NULL;
}
+ if (is_unsigned) {
+ flags |= DATA_UNSIGNED;
+ }
+
if (type == &pars_int_token) {
- if (len != 0) {
- ut_error;
- }
+ ut_a(len == 0);
dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4, 0);
} else if (type == &pars_char_token) {
- if (len != 0) {
- ut_error;
- }
+ ut_a(len == 0);
dtype_set(dfield_get_type(dfield), DATA_VARCHAR,
DATA_ENGLISH | flags, 0, 0);
} else if (type == &pars_binary_token) {
- if (len == 0) {
- ut_error;
- }
+ ut_a(len != 0);
dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
DATA_BINARY_TYPE | flags, len, 0);
} else if (type == &pars_blob_token) {
- if (len != 0) {
- ut_error;
- }
+ ut_a(len == 0);
dtype_set(dfield_get_type(dfield), DATA_BLOB,
DATA_BINARY_TYPE | flags, 0, 0);
- } else if (type == &pars_binary_token) {
- if (len == 0) {
- ut_error;
- }
-
- dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
- DATA_BINARY_TYPE, len, 0);
- } else if (type == &pars_blob_token) {
- if (len != 0) {
- ut_error;
- }
-
- dtype_set(dfield_get_type(dfield), DATA_BLOB,
- DATA_BINARY_TYPE, 0, 0);
} else {
ut_error;
}
@@ -1158,7 +1163,7 @@ pars_variable_declaration(
node->param_type = PARS_NOT_PARAM;
- pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE);
+ pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE, FALSE);
return(node);
}
@@ -1347,6 +1352,22 @@ pars_for_statement(
}
/*************************************************************************
+Parses an exit statement. */
+
+exit_node_t*
+pars_exit_statement(void)
+/*=====================*/
+ /* out: exit statement node */
+{
+ exit_node_t* node;
+
+ node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(exit_node_t));
+ node->common.type = QUE_NODE_EXIT;
+
+ return(node);
+}
+
+/*************************************************************************
Parses a return-statement. */
return_node_t*
@@ -1411,26 +1432,42 @@ pars_procedure_call(
}
/*************************************************************************
-Parses a fetch statement. */
+Parses a fetch statement. into_list or user_func (but not both) must be
+non-NULL. */
fetch_node_t*
pars_fetch_statement(
/*=================*/
/* out: fetch statement node */
sym_node_t* cursor, /* in: cursor node */
- sym_node_t* into_list) /* in: variables to set */
+ sym_node_t* into_list, /* in: variables to set, or NULL */
+ sym_node_t* user_func) /* in: user function name, or NULL */
{
sym_node_t* cursor_decl;
fetch_node_t* node;
+ /* Logical XOR. */
+ ut_a(!into_list != !user_func);
+
node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(fetch_node_t));
node->common.type = QUE_NODE_FETCH;
pars_resolve_exp_variables_and_types(NULL, cursor);
- pars_resolve_exp_list_variables_and_types(NULL, into_list);
- node->into_list = into_list;
+ if (into_list) {
+ pars_resolve_exp_list_variables_and_types(NULL, into_list);
+ node->into_list = into_list;
+ node->func = NULL;
+ } else {
+ pars_resolve_exp_variables_and_types(NULL, user_func);
+
+ node->func = pars_info_get_user_func(pars_sym_tab_global->info,
+ user_func->name);
+ ut_a(node->func);
+
+ node->into_list = NULL;
+ }
cursor_decl = cursor->alias;
@@ -1438,8 +1475,11 @@ pars_fetch_statement(
node->cursor_def = cursor_decl->cursor_def;
- ut_a(que_node_list_get_len(into_list)
- == que_node_list_get_len(node->cursor_def->select_list));
+ if (into_list) {
+ ut_a(que_node_list_get_len(into_list)
+ == que_node_list_get_len(
+ node->cursor_def->select_list));
+ }
return(node);
}
@@ -1529,6 +1569,8 @@ pars_column_def(
pars_res_word_t* type, /* in: data type */
sym_node_t* len, /* in: length of column, or
NULL */
+ void* is_unsigned, /* in: if not NULL, column
+ is of type UNSIGNED. */
void* is_not_null) /* in: if not NULL, column
is of type NOT NULL. */
{
@@ -1541,7 +1583,7 @@ pars_column_def(
}
pars_set_dfield_type(que_node_get_val(sym_node), type, len2,
- is_not_null != NULL);
+ is_unsigned != NULL, is_not_null != NULL);
return(sym_node);
}
@@ -1798,6 +1840,7 @@ que_t*
pars_sql(
/*=====*/
/* out, own: the query graph */
+ pars_info_t* info, /* in: extra information, or NULL */
const char* str) /* in: SQL string */
{
sym_node_t* sym_node;
@@ -1817,6 +1860,7 @@ pars_sql(
pars_sym_tab_global->sql_string = mem_heap_strdup(heap, str);
pars_sym_tab_global->string_len = strlen(str);
pars_sym_tab_global->next_char_pos = 0;
+ pars_sym_tab_global->info = info;
yyparse();
@@ -1831,6 +1875,7 @@ pars_sql(
graph = pars_sym_tab_global->query_graph;
graph->sym_tab = pars_sym_tab_global;
+ graph->info = info;
/* fprintf(stderr, "SQL graph size %lu\n", mem_heap_get_size(heap)); */
@@ -1867,3 +1912,222 @@ pars_complete_graph_for_exec(
return(thr);
}
+
+/********************************************************************
+Create parser info struct.*/
+
+pars_info_t*
+pars_info_create(void)
+/*==================*/
+ /* out, own: info struct */
+{
+ pars_info_t* info;
+ mem_heap_t* heap;
+
+ heap = mem_heap_create(512);
+
+ info = mem_heap_alloc(heap, sizeof(*info));
+
+ info->heap = heap;
+ info->funcs = NULL;
+ info->bound_lits = NULL;
+ info->graph_owns_us = TRUE;
+
+ return(info);
+}
+
+/********************************************************************
+Free info struct and everything it contains.*/
+
+void
+pars_info_free(
+/*===========*/
+ pars_info_t* info) /* in: info struct */
+{
+ mem_heap_free(info->heap);
+}
+
+/********************************************************************
+Add bound literal. */
+
+void
+pars_info_add_literal(
+/*==================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ const void* address, /* in: address */
+ ulint length, /* in: length of data */
+ ulint type, /* in: type, e.g. DATA_FIXBINARY */
+ ulint prtype) /* in: precise type, e.g.
+ DATA_UNSIGNED */
+{
+ pars_bound_lit_t* pbl;
+
+ ut_ad(!pars_info_get_bound_lit(info, name));
+
+ pbl = mem_heap_alloc(info->heap, sizeof(*pbl));
+
+ pbl->name = name;
+ pbl->address = address;
+ pbl->length = length;
+ pbl->type = type;
+ pbl->prtype = prtype;
+
+ if (!info->bound_lits) {
+ info->bound_lits = ib_vector_create(info->heap, 8);
+ }
+
+ ib_vector_push(info->bound_lits, pbl);
+}
+
+/********************************************************************
+Equivalent to pars_info_add_literal(info, name, str, strlen(str),
+DATA_VARCHAR, DATA_ENGLISH). */
+
+void
+pars_info_add_str_literal(
+/*======================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ const char* str) /* in: string */
+{
+ pars_info_add_literal(info, name, str, strlen(str),
+ DATA_VARCHAR, DATA_ENGLISH);
+}
+
+/********************************************************************
+Equivalent to:
+
+char buf[4];
+mach_write_to_4(buf, val);
+pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
+
+except that the buffer is dynamically allocated from the info struct's
+heap. */
+
+void
+pars_info_add_int4_literal(
+/*=======================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ lint val) /* in: value */
+{
+ byte* buf = mem_heap_alloc(info->heap, 4);
+
+ mach_write_to_4(buf, val);
+ pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
+}
+
+/********************************************************************
+Equivalent to:
+
+char buf[8];
+mach_write_to_8(buf, val);
+pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
+
+except that the buffer is dynamically allocated from the info struct's
+heap. */
+
+void
+pars_info_add_dulint_literal(
+/*=========================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: name */
+ dulint val) /* in: value */
+{
+ byte* buf = mem_heap_alloc(info->heap, 8);
+
+ mach_write_to_8(buf, val);
+
+ pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
+}
+
+/********************************************************************
+Add user function. */
+
+void
+pars_info_add_function(
+/*===================*/
+ pars_info_t* info, /* in: info struct */
+ const char* name, /* in: function name */
+ pars_user_func_cb_t func, /* in: function address */
+ void* arg) /* in: user-supplied argument */
+{
+ pars_user_func_t* puf;
+
+ ut_ad(!pars_info_get_user_func(info, name));
+
+ puf = mem_heap_alloc(info->heap, sizeof(*puf));
+
+ puf->name = name;
+ puf->func = func;
+ puf->arg = arg;
+
+ if (!info->funcs) {
+ info->funcs = ib_vector_create(info->heap, 8);
+ }
+
+ ib_vector_push(info->funcs, puf);
+}
+
+/********************************************************************
+Get user function with the given name.*/
+
+pars_user_func_t*
+pars_info_get_user_func(
+/*====================*/
+ /* out: user func, or NULL if not
+ found */
+ pars_info_t* info, /* in: info struct */
+ const char* name) /* in: function name to find*/
+{
+ ulint i;
+ ib_vector_t* vec;
+
+ if (!info || !info->funcs) {
+ return(NULL);
+ }
+
+ vec = info->funcs;
+
+ for (i = 0; i < ib_vector_size(vec); i++) {
+ pars_user_func_t* puf = ib_vector_get(vec, i);
+
+ if (strcmp(puf->name, name) == 0) {
+ return(puf);
+ }
+ }
+
+ return(NULL);
+}
+
+/********************************************************************
+Get bound literal with the given name.*/
+
+pars_bound_lit_t*
+pars_info_get_bound_lit(
+/*====================*/
+ /* out: bound literal, or NULL if
+ not found */
+ pars_info_t* info, /* in: info struct */
+ const char* name) /* in: bound literal name to find */
+{
+ ulint i;
+ ib_vector_t* vec;
+
+ if (!info || !info->bound_lits) {
+ return(NULL);
+ }
+
+ vec = info->bound_lits;
+
+ for (i = 0; i < ib_vector_size(vec); i++) {
+ pars_bound_lit_t* pbl = ib_vector_get(vec, i);
+
+ if (strcmp(pbl->name, name) == 0) {
+ return(pbl);
+ }
+ }
+
+ return(NULL);
+}
diff --git a/storage/innobase/pars/pars0sym.c b/storage/innobase/pars/pars0sym.c
index d8025998f9a..79a1e555b06 100644
--- a/storage/innobase/pars/pars0sym.c
+++ b/storage/innobase/pars/pars0sym.c
@@ -15,6 +15,7 @@ Created 12/15/1997 Heikki Tuuri
#include "mem0mem.h"
#include "data0type.h"
#include "data0data.h"
+#include "pars0grm.h"
#include "pars0pars.h"
#include "que0que.h"
#include "eval0eval.h"
@@ -166,6 +167,74 @@ sym_tab_add_str_lit(
}
/**********************************************************************
+Add a bound literal to a symbol table. */
+
+sym_node_t*
+sym_tab_add_bound_lit(
+/*==================*/
+ /* out: symbol table node */
+ sym_tab_t* sym_tab, /* in: symbol table */
+ const char* name, /* in: name of bound literal */
+ ulint* lit_type) /* out: type of literal (PARS_*_LIT) */
+{
+ sym_node_t* node;
+ pars_bound_lit_t* blit;
+ ulint len = 0;
+
+ blit = pars_info_get_bound_lit(sym_tab->info, name);
+ ut_a(blit);
+
+ node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));
+
+ node->common.type = QUE_NODE_SYMBOL;
+
+ node->resolved = TRUE;
+ node->token_type = SYM_LIT;
+
+ node->indirection = NULL;
+
+ switch (blit->type) {
+ case DATA_FIXBINARY:
+ len = blit->length;
+ *lit_type = PARS_FIXBINARY_LIT;
+ break;
+
+ case DATA_BLOB:
+ *lit_type = PARS_BLOB_LIT;
+ break;
+
+ case DATA_VARCHAR:
+ *lit_type = PARS_STR_LIT;
+ break;
+
+ case DATA_INT:
+ ut_a(blit->length > 0);
+ ut_a(blit->length <= 8);
+
+ len = blit->length;
+ *lit_type = PARS_INT_LIT;
+ break;
+
+ default:
+ ut_error;
+ }
+
+ dtype_set(&(node->common.val.type), blit->type, blit->prtype, len, 0);
+
+ dfield_set_data(&(node->common.val), blit->address, blit->length);
+
+ node->common.val_buf_size = 0;
+ node->prefetch_buf = NULL;
+ node->cursor_def = NULL;
+
+ UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
+
+ node->sym_table = sym_tab;
+
+ return(node);
+}
+
+/**********************************************************************
Adds an SQL null literal to a symbol table. */
sym_node_t*
@@ -220,7 +289,7 @@ sym_tab_add_id(
node->resolved = FALSE;
node->indirection = NULL;
- node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len + 1);
+ node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len);
node->name_len = len;
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
diff --git a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c
index e048b94cdc5..c6d287276c7 100644
--- a/storage/innobase/que/que0que.c
+++ b/storage/innobase/que/que0que.c
@@ -25,6 +25,7 @@ Created 5/27/1996 Heikki Tuuri
#include "log0log.h"
#include "eval0proc.h"
#include "eval0eval.h"
+#include "pars0types.h"
#define QUE_PARALLELIZE_LIMIT (64 * 256 * 256 * 256)
#define QUE_ROUND_ROBIN_LIMIT (64 * 256 * 256 * 256)
@@ -36,6 +37,50 @@ ibool que_trace_on = FALSE;
ibool que_always_false = FALSE;
+/* Short introduction to query graphs
+ ==================================
+
+A query graph consists of nodes linked to each other in various ways. The
+execution starts at que_run_threads() which takes a que_thr_t parameter.
+que_thr_t contains two fields that control query graph execution: run_node
+and prev_node. run_node is the next node to execute and prev_node is the
+last node executed.
+
+Each node has a pointer to a 'next' statement, i.e., its brother, and a
+pointer to its parent node. The next pointer is NULL in the last statement
+of a block.
+
+Loop nodes contain a link to the first statement of the enclosed statement
+list. While the loop runs, que_thr_step() checks if execution to the loop
+node came from its parent or from one of the statement nodes in the loop. If
+it came from the parent of the loop node it starts executing the first
+statement node in the loop. If it came from one of the statement nodes in
+the loop, then it checks if the statement node has another statement node
+following it, and runs it if so.
+
+To signify loop ending, the loop statements (see e.g. while_step()) set
+que_thr_t->run_node to the loop node's parent node. This is noticed on the
+next call of que_thr_step() and execution proceeds to the node pointed to by
+the loop node's 'next' pointer.
+
+For example, the code:
+
+X := 1;
+WHILE X < 5 LOOP
+ X := X + 1;
+ X := X + 1;
+X := 5
+
+will result in the following node hierarchy, with the X-axis indicating
+'next' links and the Y-axis indicating parent/child links:
+
+A - W - A
+ |
+ |
+ A - A
+
+A = assign_node_t, W = while_node_t. */
+
/* How a stored procedure containing COMMIT or ROLLBACK commands
is executed?
@@ -128,6 +173,7 @@ que_fork_create(
UT_LIST_INIT(fork->thrs);
fork->sym_tab = NULL;
+ fork->info = NULL;
fork->heap = heap;
@@ -583,6 +629,7 @@ que_graph_free_recursive(
break;
case QUE_NODE_ASSIGNMENT:
+ case QUE_NODE_EXIT:
case QUE_NODE_RETURN:
case QUE_NODE_COMMIT:
case QUE_NODE_ROLLBACK:
@@ -626,6 +673,10 @@ que_graph_free(
sym_tab_free_private(graph->sym_tab);
}
+ if (graph->info && graph->info->graph_owns_us) {
+ pars_info_free(graph->info);
+ }
+
que_graph_free_recursive(graph);
mem_heap_free(graph->heap);
@@ -1040,6 +1091,37 @@ que_thr_stop_for_mysql_no_error(
trx->n_active_thrs--;
}
+/********************************************************************
+Get the first containing loop node (e.g. while_node_t or for_node_t) for the
+given node, or NULL if the node is not within a loop. */
+
+que_node_t*
+que_node_get_containing_loop_node(
+/*==============================*/
+ /* out: containing loop node, or NULL. */
+ que_node_t* node) /* in: node */
+{
+ ut_ad(node);
+
+ for (;;) {
+ ulint type;
+
+ node = que_node_get_parent(node);
+
+ if (!node) {
+ break;
+ }
+
+ type = que_node_get_type(node);
+
+ if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
+ break;
+ }
+ }
+
+ return(node);
+}
+
/**************************************************************************
Prints info of an SQL query graph node. */
@@ -1093,6 +1175,8 @@ que_node_print_info(
str = "FOR LOOP";
} else if (type == QUE_NODE_RETURN) {
str = "RETURN";
+ } else if (type == QUE_NODE_EXIT) {
+ str = "EXIT";
} else {
str = "UNKNOWN NODE TYPE";
}
@@ -1120,8 +1204,8 @@ que_thr_step(
thr->resource++;
- type = que_node_get_type(thr->run_node);
node = thr->run_node;
+ type = que_node_get_type(node);
old_thr = thr;
@@ -1160,6 +1244,8 @@ que_thr_step(
proc_step(thr);
} else if (type == QUE_NODE_WHILE) {
while_step(thr);
+ } else {
+ ut_error;
}
} else if (type == QUE_NODE_ASSIGNMENT) {
assign_step(thr);
@@ -1192,6 +1278,8 @@ que_thr_step(
thr = row_purge_step(thr);
} else if (type == QUE_NODE_RETURN) {
thr = return_step(thr);
+ } else if (type == QUE_NODE_EXIT) {
+ thr = exit_step(thr);
} else if (type == QUE_NODE_ROLLBACK) {
thr = trx_rollback_step(thr);
} else if (type == QUE_NODE_CREATE_TABLE) {
@@ -1204,7 +1292,11 @@ que_thr_step(
ut_error;
}
- old_thr->prev_node = node;
+ if (type == QUE_NODE_EXIT) {
+ old_thr->prev_node = que_node_get_containing_loop_node(node);
+ } else {
+ old_thr->prev_node = node;
+ }
return(thr);
}
@@ -1248,14 +1340,6 @@ loop:
next_thr = que_thr_step(thr);
/*-------------------------*/
- /* Test the effect on performance of adding extra mutex
- reservations */
-
-/* if (srv_test_extra_mutexes) {
- mutex_enter(&kernel_mutex);
- mutex_exit(&kernel_mutex);
- }
-*/
loop_count++;
if (next_thr != thr) {
@@ -1274,3 +1358,33 @@ loop:
goto loop;
}
+
+/*************************************************************************
+Evaluate the given SQL */
+
+ulint
+que_eval_sql(
+/*=========*/
+ pars_info_t* info, /* out: error code or DB_SUCCESS */
+ const char* sql, /* in: info struct, or NULL */
+ trx_t* trx) /* in: trx */
+{
+ que_thr_t* thr;
+ que_t* graph;
+
+ graph = pars_sql(info, sql);
+ ut_a(graph);
+
+ graph->trx = trx;
+ trx->graph = NULL;
+
+ graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
+
+ ut_a(thr = que_fork_start_command(graph));
+
+ que_run_threads(thr);
+
+ que_graph_free(graph);
+
+ return(trx->error_state);
+}
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index c80a61cc729..e47d6a621a7 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri
#include "eval0eval.h"
#include "data0data.h"
#include "usr0sess.h"
+#include "buf0lru.h"
#define ROW_INS_PREV 1
#define ROW_INS_NEXT 2
@@ -139,7 +140,6 @@ row_ins_alloc_sys_fields(
mem_heap_t* heap;
dict_col_t* col;
dfield_t* dfield;
- ulint len;
byte* ptr;
row = node->row;
@@ -161,21 +161,6 @@ row_ins_alloc_sys_fields(
node->row_id_buf = ptr;
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- /* 2. Fill in the dfield for mix id */
-
- col = dict_table_get_sys_col(table, DATA_MIX_ID);
-
- dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
-
- len = mach_dulint_get_compressed_size(table->mix_id);
- ptr = mem_heap_alloc(heap, DATA_MIX_ID_LEN);
-
- mach_dulint_write_compressed(ptr, table->mix_id);
- dfield_set_data(dfield, ptr, len);
- }
-
/* 3. Allocate buffer for trx id */
col = dict_table_get_sys_col(table, DATA_TRX_ID);
@@ -279,10 +264,17 @@ row_ins_sec_index_entry_by_modify(
}
} else {
ut_a(mode == BTR_MODIFY_TREE);
+ if (buf_LRU_buf_pool_running_out()) {
+
+ err = DB_LOCK_TABLE_FULL;
+
+ goto func_exit;
+ }
+
err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
&dummy_big_rec, update, 0, thr, mtr);
}
-
+func_exit:
mem_heap_free(heap);
return(err);
@@ -344,10 +336,16 @@ row_ins_clust_index_entry_by_modify(
}
} else {
ut_a(mode == BTR_MODIFY_TREE);
+ if (buf_LRU_buf_pool_running_out()) {
+
+ err = DB_LOCK_TABLE_FULL;
+
+ goto func_exit;
+ }
err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
0, thr, mtr);
}
-
+func_exit:
mem_heap_free(heap);
return(err);
@@ -1882,7 +1880,6 @@ row_ins_duplicate_error_in_clust(
err = DB_DUPLICATE_KEY;
goto func_exit;
}
- mem_heap_free(heap);
}
ut_a(!(cursor->index->type & DICT_CLUSTERED));
@@ -1891,6 +1888,9 @@ row_ins_duplicate_error_in_clust(
err = DB_SUCCESS;
func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
#else /* UNIV_HOTBACKUP */
/* This function depends on MySQL code that is not included in
@@ -2091,6 +2091,12 @@ row_ins_index_entry_low(
&insert_rec, &big_rec, thr, &mtr);
} else {
ut_a(mode == BTR_MODIFY_TREE);
+ if (buf_LRU_buf_pool_running_out()) {
+
+ err = DB_LOCK_TABLE_FULL;
+
+ goto function_exit;
+ }
err = btr_cur_pessimistic_insert(0, &cursor, entry,
&insert_rec, &big_rec, thr, &mtr);
}
@@ -2429,7 +2435,15 @@ row_ins_step(
/* If this is the first time this node is executed (or when
execution resumes after wait for the table IX lock), set an
- IX lock on the table and reset the possible select node. */
+ IX lock on the table and reset the possible select node. MySQL's
+ partitioned table code may also call an insert within the same
+ SQL statement AFTER it has used this table handle to do a search.
+ This happens, for example, when a row update moves it to another
+ partition. In that case, we have already set the IX lock on the
+ table during the search operation, and there is no need to set
+ it again here. But we must write trx->id to node->trx_id_buf. */
+
+ trx_write_trx_id(node->trx_id_buf, trx->id);
if (node->state == INS_NODE_SET_IX_LOCK) {
@@ -2437,13 +2451,11 @@ row_ins_step(
its transaction, or it has been committed: */
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
- /* No need to do IX-locking or write trx id to buf */
+ /* No need to do IX-locking */
goto same_trx;
}
- trx_write_trx_id(node->trx_id_buf, trx->id);
-
err = lock_table(0, node->table, LOCK_IX, thr);
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 4dbe5128974..56574618f9a 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -85,9 +85,11 @@ row_mysql_is_system_table(
system table name */
const char* name)
{
- if (memcmp(name, "mysql/", 6)) {
+ if (strncmp(name, "mysql/", 6) != 0) {
+
return(FALSE);
}
+
return(0 == strcmp(name + 6, "host")
|| 0 == strcmp(name + 6, "user")
|| 0 == strcmp(name + 6, "db"));
@@ -1435,7 +1437,8 @@ run_again:
}
/*************************************************************************
-This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before
+This can only be used when srv_locks_unsafe_for_binlog is TRUE or
+this session is using a READ COMMITTED isolation level. 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,
@@ -1466,11 +1469,13 @@ row_unlock_for_mysql(
ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- if (!srv_locks_unsafe_for_binlog) {
+ if (!(srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
fprintf(stderr,
"InnoDB: Error: calling row_unlock_for_mysql though\n"
-"InnoDB: srv_locks_unsafe_for_binlog is FALSE.\n");
+"InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n"
+"InnoDB: this session is not using READ COMMITTED isolation level.\n");
return(DB_SUCCESS);
}
@@ -1670,7 +1675,9 @@ row_mysql_recover_tmp_table(
if (!ptr) {
/* table name does not begin with "/rsql" */
+ dict_mem_table_free(table);
trx_commit_for_mysql(trx);
+
return(DB_ERROR);
}
else {
@@ -1782,6 +1789,7 @@ row_create_table_for_mysql(
const char* table_name;
ulint table_name_len;
ulint err;
+ ulint i;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG
@@ -1799,6 +1807,7 @@ row_create_table_for_mysql(
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
+ dict_mem_table_free(table);
trx_commit_for_mysql(trx);
return(DB_ERROR);
@@ -1813,11 +1822,25 @@ row_create_table_for_mysql(
"InnoDB: MySQL system tables must be of the MyISAM type!\n",
table->name);
+ dict_mem_table_free(table);
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
+ /* Check that no reserved column names are used. */
+ for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
+ dict_col_t* col = dict_table_get_nth_col(table, i);
+
+ if (dict_col_name_is_reserved(col->name)) {
+
+ dict_mem_table_free(table);
+ trx_commit_for_mysql(trx);
+
+ return(DB_ERROR);
+ }
+ }
+
trx_start_if_not_started(trx);
if (row_mysql_is_recovered_tmp_table(table->name)) {
@@ -2361,11 +2384,9 @@ row_discard_tablespace_for_mysql(
dict_foreign_t* foreign;
dulint new_id;
dict_table_t* table;
- que_thr_t* thr;
- que_t* graph = NULL;
ibool success;
ulint err;
- char* buf;
+ pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages.
@@ -2387,36 +2408,6 @@ discard ongoing operations.
5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we
do not allow the discard. We also reserve the data dictionary latch. */
- static const char discard_tablespace_proc1[] =
- "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
- "old_id CHAR;\n"
- "new_id CHAR;\n"
- "new_id_low INT;\n"
- "new_id_high INT;\n"
- "table_name CHAR;\n"
- "BEGIN\n"
- "table_name := '";
- static const char discard_tablespace_proc2[] =
- "';\n"
- "new_id_high := %lu;\n"
- "new_id_low := %lu;\n"
- "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
- "SELECT ID INTO old_id\n"
- "FROM SYS_TABLES\n"
- "WHERE NAME = table_name;\n"
- "IF (SQL %% NOTFOUND) THEN\n"
- " COMMIT WORK;\n"
- " RETURN;\n"
- "END IF;\n"
- "UPDATE SYS_TABLES SET ID = new_id\n"
- "WHERE ID = old_id;\n"
- "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n"
- "WHERE TABLE_ID = old_id;\n"
- "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n"
- "WHERE TABLE_ID = old_id;\n"
- "COMMIT WORK;\n"
- "END;\n";
-
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "discarding tablespace";
@@ -2496,35 +2487,34 @@ do not allow the discard. We also reserve the data dictionary latch. */
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
- buf = mem_alloc((sizeof discard_tablespace_proc1) +
- (sizeof discard_tablespace_proc2) +
- 20 + ut_strlenq(name, '\''));
-
- memcpy(buf, discard_tablespace_proc1, sizeof discard_tablespace_proc1);
- sprintf(ut_strcpyq(buf + (sizeof discard_tablespace_proc1 - 1),
- '\'', name),
- discard_tablespace_proc2,
- (ulong) ut_dulint_get_high(new_id),
- (ulong) ut_dulint_get_low(new_id));
-
- graph = pars_sql(buf);
-
- ut_a(graph);
-
/* Remove any locks there are on the table or its records */
-
lock_reset_all_on_table(table);
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
+ info = pars_info_create();
- ut_a(thr = que_fork_start_command(graph));
+ pars_info_add_str_literal(info, "table_name", name);
+ pars_info_add_dulint_literal(info, "new_id", new_id);
- que_run_threads(thr);
-
- err = trx->error_state;
+ err = que_eval_sql(info,
+ "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
+ "old_id CHAR;\n"
+ "BEGIN\n"
+ "SELECT ID INTO old_id\n"
+ "FROM SYS_TABLES\n"
+ "WHERE NAME = :table_name;\n"
+ "IF (SQL % NOTFOUND) THEN\n"
+ " COMMIT WORK;\n"
+ " RETURN;\n"
+ "END IF;\n"
+ "UPDATE SYS_TABLES SET ID = :new_id\n"
+ " WHERE ID = old_id;\n"
+ "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
+ " WHERE TABLE_ID = old_id;\n"
+ "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
+ " WHERE TABLE_ID = old_id;\n"
+ "COMMIT WORK;\n"
+ "END;\n"
+ , trx);
if (err != DB_SUCCESS) {
trx->error_state = DB_SUCCESS;
@@ -2548,13 +2538,10 @@ do not allow the discard. We also reserve the data dictionary latch. */
table->ibd_file_missing = TRUE;
}
}
+
funct_exit:
row_mysql_unlock_data_dictionary(trx);
- if (graph) {
- que_graph_free(graph);
- }
-
trx_commit_for_mysql(trx);
trx->op_info = "";
@@ -2715,9 +2702,7 @@ row_truncate_table_for_mysql(
btr_pcur_t pcur;
mtr_t mtr;
dulint new_id;
- char* sql;
- que_thr_t* thr;
- que_t* graph = NULL;
+ pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages.
@@ -2745,30 +2730,6 @@ 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);
@@ -2929,35 +2890,27 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
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;
+ new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
- thr = que_fork_start_command(graph);
- ut_a(thr);
+ info = pars_info_create();
- que_run_threads(thr);
+ pars_info_add_dulint_literal(info, "old_id", table->id);
+ pars_info_add_dulint_literal(info, "new_id", new_id);
- que_graph_free(graph);
-
- err = trx->error_state;
+ err = que_eval_sql(info,
+ "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
+ "BEGIN\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"
+ , trx);
if (err != DB_SUCCESS) {
trx->error_state = DB_SUCCESS;
@@ -3007,83 +2960,13 @@ row_drop_table_for_mysql(
dict_foreign_t* foreign;
dict_table_t* table;
ulint space_id;
- que_thr_t* thr;
- que_t* graph;
ulint err;
const char* table_name;
ulint namelen;
char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE;
- char* quoted_name;
- char* sql;
-
- /* We use the private SQL parser of Innobase to generate the
- query graphs needed in deleting the dictionary data from system
- tables in Innobase. Deleting a row from SYS_INDEXES table also
- frees the file segments of the B-tree associated with the index. */
-
- static const char str1[] =
- "PROCEDURE DROP_TABLE_PROC () IS\n"
- "table_name CHAR;\n"
- "sys_foreign_id CHAR;\n"
- "table_id CHAR;\n"
- "index_id CHAR;\n"
- "foreign_id CHAR;\n"
- "found INT;\n"
- "BEGIN\n"
- "table_name := ";
- static const char str2[] =
- ";\n"
- "SELECT ID INTO table_id\n"
- "FROM SYS_TABLES\n"
- "WHERE NAME = table_name;\n"
- "IF (SQL % NOTFOUND) THEN\n"
- " COMMIT WORK;\n"
- " RETURN;\n"
- "END IF;\n"
- "found := 1;\n"
- "SELECT ID INTO sys_foreign_id\n"
- "FROM SYS_TABLES\n"
- "WHERE NAME = 'SYS_FOREIGN';\n"
- "IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- "END IF;\n"
- "IF (table_name = 'SYS_FOREIGN') THEN\n"
- " found := 0;\n"
- "END IF;\n"
- "IF (table_name = 'SYS_FOREIGN_COLS') THEN\n"
- " found := 0;\n"
- "END IF;\n"
- "WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = table_name\n"
- " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n"
- " IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- " ELSE"
- " DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n"
- " DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n"
- " END IF;\n"
- "END LOOP;\n"
- "found := 1;\n"
- "WHILE found = 1 LOOP\n"
- " SELECT ID INTO index_id\n"
- " FROM SYS_INDEXES\n"
- " WHERE TABLE_ID = table_id;\n"
- " IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- " ELSE"
- " DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n"
- " DELETE FROM SYS_INDEXES WHERE ID = index_id\n"
- " AND TABLE_ID = table_id;\n"
- " END IF;\n"
- "END LOOP;\n"
- "DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n"
- "DELETE FROM SYS_TABLES WHERE ID = table_id;\n"
- "COMMIT WORK;\n"
- "END;\n";
+ pars_info_t* info = NULL;
ut_a(name != NULL);
@@ -3138,14 +3021,6 @@ row_drop_table_for_mysql(
srv_print_innodb_table_monitor = FALSE;
}
- quoted_name = mem_strdupq(name, '\'');
- namelen = strlen(quoted_name);
- sql = mem_alloc((sizeof str1) + (sizeof str2) - 2 + 1 + namelen);
- memcpy(sql, str1, (sizeof str1) - 1);
- memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
- memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
- mem_free(quoted_name);
-
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
@@ -3163,16 +3038,6 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- graph = pars_sql(sql);
-
- ut_a(graph);
- mem_free(sql);
-
- graph->trx = trx;
- trx->graph = NULL;
-
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
-
table = dict_table_get_low(name);
if (!table) {
@@ -3296,18 +3161,80 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
trx->dict_operation = TRUE;
trx->table_id = table->id;
- ut_a(thr = que_fork_start_command(graph));
+ /* We use the private SQL parser of Innobase to generate the
+ query graphs needed in deleting the dictionary data from system
+ tables in Innobase. Deleting a row from SYS_INDEXES table also
+ frees the file segments of the B-tree associated with the index. */
- que_run_threads(thr);
+ info = pars_info_create();
- err = trx->error_state;
+ pars_info_add_str_literal(info, "table_name", name);
+
+ err = que_eval_sql(info,
+ "PROCEDURE DROP_TABLE_PROC () IS\n"
+ "sys_foreign_id CHAR;\n"
+ "table_id CHAR;\n"
+ "index_id CHAR;\n"
+ "foreign_id CHAR;\n"
+ "found INT;\n"
+ "BEGIN\n"
+ "SELECT ID INTO table_id\n"
+ "FROM SYS_TABLES\n"
+ "WHERE NAME = :table_name;\n"
+ "IF (SQL % NOTFOUND) THEN\n"
+ " COMMIT WORK;\n"
+ " RETURN;\n"
+ "END IF;\n"
+ "found := 1;\n"
+ "SELECT ID INTO sys_foreign_id\n"
+ "FROM SYS_TABLES\n"
+ "WHERE NAME = 'SYS_FOREIGN';\n"
+ "IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ "END IF;\n"
+ "IF (:table_name = 'SYS_FOREIGN') THEN\n"
+ " found := 0;\n"
+ "END IF;\n"
+ "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
+ " found := 0;\n"
+ "END IF;\n"
+ "WHILE found = 1 LOOP\n"
+ " SELECT ID INTO foreign_id\n"
+ " FROM SYS_FOREIGN\n"
+ " WHERE FOR_NAME = :table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(:table_name);\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSE"
+ " DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n"
+ " DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "found := 1;\n"
+ "WHILE found = 1 LOOP\n"
+ " SELECT ID INTO index_id\n"
+ " FROM SYS_INDEXES\n"
+ " WHERE TABLE_ID = table_id;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSE"
+ " DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n"
+ " DELETE FROM SYS_INDEXES WHERE ID = index_id\n"
+ " AND TABLE_ID = table_id;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n"
+ "DELETE FROM SYS_TABLES WHERE ID = table_id;\n"
+ "COMMIT WORK;\n"
+ "END;\n"
+ , trx);
if (err != DB_SUCCESS) {
ut_a(err == DB_OUT_OF_FILE_SPACE);
err = DB_MUST_GET_MORE_FILE_SPACE;
- row_mysql_handle_errors(&err, trx, thr, NULL);
+ row_mysql_handle_errors(&err, trx, NULL, NULL);
ut_error;
} else {
@@ -3385,8 +3312,6 @@ funct_exit:
mem_free(dir_path_of_temp_table);
}
- que_graph_free(graph);
-
trx_commit_for_mysql(trx);
trx->op_info = "";
@@ -3491,6 +3416,62 @@ row_is_mysql_tmp_table_name(
return(strstr(name, "/@0023sql") != NULL);
}
+/********************************************************************
+Delete a single constraint. */
+static
+int
+row_delete_constraint_low(
+/*======================*/
+ /* out: error code or DB_SUCCESS */
+ const char* id, /* in: constraint id */
+ trx_t* trx) /* in: transaction handle */
+{
+ pars_info_t* info = pars_info_create();
+
+ pars_info_add_str_literal(info, "id", id);
+
+ return(que_eval_sql(info,
+ "PROCEDURE DELETE_CONSTRAINT () IS\n"
+ "BEGIN\n"
+ "DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
+ "DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
+ "END;\n"
+ , trx));
+}
+
+/********************************************************************
+Delete a single constraint. */
+static
+int
+row_delete_constraint(
+/*==================*/
+ /* out: error code or DB_SUCCESS */
+ const char* id, /* in: constraint id */
+ const char* database_name, /* in: database name, with the
+ trailing '/' */
+ mem_heap_t* heap, /* in: memory heap */
+ trx_t* trx) /* in: transaction handle */
+{
+ ulint err;
+
+ /* New format constraints have ids <databasename>/<constraintname>. */
+ err = row_delete_constraint_low(
+ mem_heap_strcat(heap, database_name, id), trx);
+
+ if ((err == DB_SUCCESS) && !strchr(id, '/')) {
+ /* Old format < 4.0.18 constraints have constraint ids
+ <number>_<number>. We only try deleting them if the
+ constraint name does not contain a '/' character, otherwise
+ deleting a new format constraint named 'foo/bar' from
+ database 'baz' would remove constraint 'bar' from database
+ 'foo', if it existed. */
+
+ err = row_delete_constraint_low(id, trx);
+ }
+
+ return(err);
+}
+
/*************************************************************************
Renames a table for MySQL. */
@@ -3503,100 +3484,13 @@ row_rename_table_for_mysql(
trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
- que_thr_t* thr;
- que_t* graph = NULL;
ulint err;
- /* We use the private SQL parser of Innobase to generate the
- query graphs needed in deleting the dictionary data from system
- tables in Innobase. Deleting a row from SYS_INDEXES table also
- frees the file segments of the B-tree associated with the index. */
- static const char str1[] =
- "PROCEDURE RENAME_TABLE_PROC () IS\n"
- "new_table_name CHAR;\n"
- "old_table_name CHAR;\n"
- "gen_constr_prefix CHAR;\n"
- "new_db_name CHAR;\n"
- "foreign_id CHAR;\n"
- "new_foreign_id CHAR;\n"
- "old_db_name_len INT;\n"
- "old_t_name_len INT;\n"
- "new_db_name_len INT;\n"
- "id_len INT;\n"
- "found INT;\n"
- "BEGIN\n"
- "new_table_name := '";
- static const char str2[] =
- "';\nold_table_name := '";
- static const char str3[] =
- "';\n"
- "UPDATE SYS_TABLES SET NAME = new_table_name\n"
- "WHERE NAME = old_table_name;\n";
- static const char str4a1[] = /* drop some constraints of tmp tables */
- "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '";
- static const char str4a2[] = "';\n"
- "DELETE FROM SYS_FOREIGN WHERE ID = '";
- static const char str4a3[] = "';\n";
- static const char str4b[] = /* rename all constraints */
- "found := 1;\n"
- "old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
- "new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
- "new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
- "old_t_name_len := LENGTH(old_table_name);\n"
- "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
- "WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = old_table_name\n"
- " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n"
- " IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- " ELSE\n"
- " UPDATE SYS_FOREIGN\n"
- " SET FOR_NAME = new_table_name\n"
- " WHERE ID = foreign_id;\n"
- " id_len := LENGTH(foreign_id);\n"
- " IF (INSTR(foreign_id, '/') > 0) THEN\n"
- " IF (INSTR(foreign_id,\n"
- " gen_constr_prefix) > 0)\n"
- " THEN\n"
- " new_foreign_id :=\n"
- " CONCAT(new_table_name,\n"
- " SUBSTR(foreign_id, old_t_name_len,\n"
- " id_len - old_t_name_len));\n"
- " ELSE\n"
- " new_foreign_id :=\n"
- " CONCAT(new_db_name,\n"
- " SUBSTR(foreign_id,\n"
- " old_db_name_len,\n"
- " id_len - old_db_name_len));\n"
- " END IF;\n"
- " UPDATE SYS_FOREIGN\n"
- " SET ID = new_foreign_id\n"
- " WHERE ID = foreign_id;\n"
- " UPDATE SYS_FOREIGN_COLS\n"
- " SET ID = new_foreign_id\n"
- " WHERE ID = foreign_id;\n"
- " END IF;\n"
- " END IF;\n"
- "END LOOP;\n"
- "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
- "WHERE REF_NAME = old_table_name\n"
- " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n";
- static const char str5[] =
- "END;\n";
-
mem_heap_t* heap = NULL;
const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
ibool recovering_temp_table = FALSE;
ibool old_is_tmp, new_is_tmp;
- ulint len;
- ulint i;
- ibool success;
- /* length of database name; 0 if not renaming to a temporary table */
- ulint db_name_len;
- char* sql;
- char* sqlend;
+ pars_info_t* info = NULL;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
@@ -3674,13 +3568,7 @@ row_rename_table_for_mysql(
goto funct_exit;
}
- /* calculate the length of the SQL string */
- len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
- + ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
-
if (new_is_tmp) {
- db_name_len = dict_get_db_name_len(old_name) + 1;
-
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
the original foreign key constraint definitions despite the
@@ -3690,110 +3578,124 @@ row_rename_table_for_mysql(
heap = mem_heap_create(100);
err = dict_foreign_parse_drop_constraints(heap, trx,
- table,
- &n_constraints_to_drop,
- &constraints_to_drop);
+ table, &n_constraints_to_drop, &constraints_to_drop);
+
if (err != DB_SUCCESS) {
goto funct_exit;
}
+ }
- /* reserve space for all database names */
- len += 2 * n_constraints_to_drop
- * (ut_strlenq(old_name, '\'')
- - ut_strlenq(old_name + db_name_len, '\''));
+ /* We use the private SQL parser of Innobase to generate the query
+ graphs needed in deleting the dictionary data from system tables in
+ Innobase. Deleting a row from SYS_INDEXES table also frees the file
+ segments of the B-tree associated with the index. */
- for (i = 0; i < n_constraints_to_drop; i++) {
- ulint addlen
- = 2 * ut_strlenq(constraints_to_drop[i], '\'')
- + ((sizeof str4a1) + (sizeof str4a2)
- + (sizeof str4a3) - 3);
- if (!strchr(constraints_to_drop[i], '/')) {
- addlen *= 2;
- }
- len += addlen;
- }
- } else {
- db_name_len = 0;
- len += (sizeof str4b) - 1;
- }
+ info = pars_info_create();
- sql = sqlend = mem_alloc(len + 1);
- memcpy(sql, str1, (sizeof str1) - 1);
- sqlend += (sizeof str1) - 1;
- sqlend = ut_strcpyq(sqlend, '\'', new_name);
- memcpy(sqlend, str2, (sizeof str2) - 1);
- sqlend += (sizeof str2) - 1;
- sqlend = ut_strcpyq(sqlend, '\'', old_name);
- memcpy(sqlend, str3, (sizeof str3) - 1);
- sqlend += (sizeof str3) - 1;
-
- if (db_name_len) {
- /* Internally, old format < 4.0.18 constraints have as the
- constraint id <number>_<number>, while new format constraints
- have <databasename>/<constraintname>. */
+ pars_info_add_str_literal(info, "new_table_name", new_name);
+ pars_info_add_str_literal(info, "old_table_name", old_name);
- for (i = 0; i < n_constraints_to_drop; i++) {
- memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
- sqlend += (sizeof str4a1) - 1;
- sqlend = ut_memcpyq(sqlend, '\'',
- old_name, db_name_len);
- sqlend = ut_strcpyq(sqlend, '\'',
- constraints_to_drop[i]);
- memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
- sqlend += (sizeof str4a2) - 1;
- sqlend = ut_memcpyq(sqlend, '\'',
- old_name, db_name_len);
- sqlend = ut_strcpyq(sqlend, '\'',
- constraints_to_drop[i]);
- memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
- sqlend += (sizeof str4a3) - 1;
-
- if (!strchr(constraints_to_drop[i], '/')) {
- /* If this happens to be an old format
- constraint, let us delete it. Since all new
- format constraints contain '/', it does no
- harm to run these DELETEs anyway. */
-
- memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
- sqlend += (sizeof str4a1) - 1;
- sqlend = ut_strcpyq(sqlend, '\'',
- constraints_to_drop[i]);
- memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
- sqlend += (sizeof str4a2) - 1;
- sqlend = ut_strcpyq(sqlend, '\'',
- constraints_to_drop[i]);
- memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
- sqlend += (sizeof str4a3) - 1;
- }
- }
- }
- else {
- memcpy(sqlend, str4b, (sizeof str4b) - 1);
- sqlend += (sizeof str4b) - 1;
- }
+ err = que_eval_sql(info,
+ "PROCEDURE RENAME_TABLE () IS\n"
+ "BEGIN\n"
+ "UPDATE SYS_TABLES SET NAME = :new_table_name\n"
+ " WHERE NAME = :old_table_name;\n"
+ "END;\n"
+ , trx);
- memcpy(sqlend, str5, sizeof str5);
- sqlend += sizeof str5;
+ if (err != DB_SUCCESS) {
- ut_a(sqlend == sql + len + 1);
+ goto end;
+ }
- graph = pars_sql(sql);
+ if (!new_is_tmp) {
+ /* Rename all constraints. */
- ut_a(graph);
- mem_free(sql);
+ info = pars_info_create();
- graph->trx = trx;
- trx->graph = NULL;
+ pars_info_add_str_literal(info, "new_table_name", new_name);
+ pars_info_add_str_literal(info, "old_table_name", old_name);
- graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
+ err = que_eval_sql(info,
+ "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
+ "gen_constr_prefix CHAR;\n"
+ "new_db_name CHAR;\n"
+ "foreign_id CHAR;\n"
+ "new_foreign_id CHAR;\n"
+ "old_db_name_len INT;\n"
+ "old_t_name_len INT;\n"
+ "new_db_name_len INT;\n"
+ "id_len INT;\n"
+ "found INT;\n"
+ "BEGIN\n"
+ "found := 1;\n"
+ "old_db_name_len := INSTR(:old_table_name, '/') - 1;\n"
+ "new_db_name_len := INSTR(:new_table_name, '/') - 1;\n"
+ "new_db_name := SUBSTR(:new_table_name, 0, new_db_name_len);\n"
+ "old_t_name_len := LENGTH(:old_table_name);\n"
+ "gen_constr_prefix := CONCAT(:old_table_name, '_ibfk_');\n"
+ "WHILE found = 1 LOOP\n"
+ " SELECT ID INTO foreign_id\n"
+ " FROM SYS_FOREIGN\n"
+ " WHERE FOR_NAME = :old_table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(:old_table_name);\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSE\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET FOR_NAME = :new_table_name\n"
+ " WHERE ID = foreign_id;\n"
+ " id_len := LENGTH(foreign_id);\n"
+ " IF (INSTR(foreign_id, '/') > 0) THEN\n"
+ " IF (INSTR(foreign_id,\n"
+ " gen_constr_prefix) > 0)\n"
+ " THEN\n"
+ " new_foreign_id :=\n"
+ " CONCAT(:new_table_name,\n"
+ " SUBSTR(foreign_id, old_t_name_len,\n"
+ " id_len - old_t_name_len));\n"
+ " ELSE\n"
+ " new_foreign_id :=\n"
+ " CONCAT(new_db_name,\n"
+ " SUBSTR(foreign_id,\n"
+ " old_db_name_len,\n"
+ " id_len - old_db_name_len));\n"
+ " END IF;\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " UPDATE SYS_FOREIGN_COLS\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " END IF;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
+ "WHERE REF_NAME = :old_table_name\n"
+ " AND TO_BINARY(REF_NAME) = TO_BINARY(:old_table_name);\n"
+ "END;\n"
+ , trx);
- ut_a(thr = que_fork_start_command(graph));
+ } else if (n_constraints_to_drop > 0) {
+ /* Drop some constraints of tmp tables. */
- que_run_threads(thr);
+ ulint db_name_len = dict_get_db_name_len(old_name) + 1;
+ char* db_name = mem_heap_strdupl(heap, old_name,
+ db_name_len);
+ ulint i;
- err = trx->error_state;
+ for (i = 0; i < n_constraints_to_drop; i++) {
+ err = row_delete_constraint(constraints_to_drop[i],
+ db_name, heap, trx);
+ if (err != DB_SUCCESS) {
+ break;
+ }
+ }
+ }
+
+end:
if (err != DB_SUCCESS) {
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
@@ -3830,8 +3732,9 @@ row_rename_table_for_mysql(
/* The following call will also rename the .ibd data file if
the table is stored in a single-table tablespace */
- success = dict_table_rename_in_cache(table, new_name,
+ ibool success = dict_table_rename_in_cache(table, new_name,
!new_is_tmp);
+
if (!success) {
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -3879,20 +3782,16 @@ row_rename_table_for_mysql(
ut_a(dict_table_rename_in_cache(table,
old_name, FALSE));
trx->error_state = DB_SUCCESS;
- trx_general_rollback_for_mysql(trx, FALSE,
- NULL);
+ trx_general_rollback_for_mysql(trx, FALSE, NULL);
trx->error_state = DB_SUCCESS;
}
}
+
funct_exit:
if (!recovering_temp_table) {
row_mysql_unlock_data_dictionary(trx);
}
- if (graph) {
- que_graph_free(graph);
- }
-
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 0809d2872a5..c0f906f4ed7 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -710,12 +710,17 @@ row_sel_get_clust_rec(
if (!node->read_view) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED isolation level
we lock only the record, i.e., next-key locking is
not used. */
ulint lock_type;
+ trx_t* trx;
- if (srv_locks_unsafe_for_binlog) {
+ trx = thr_get_trx(thr);
+
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
@@ -1307,16 +1312,22 @@ 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. */
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED isolation
+ level, 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;
+ trx_t* trx;
+
+ trx = thr_get_trx(thr);
+
offsets = rec_get_offsets(next_rec, index, offsets,
ULINT_UNDEFINED, &heap);
- if (srv_locks_unsafe_for_binlog) {
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
@@ -1350,15 +1361,21 @@ rec_loop:
if (!consistent_read) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED isolation level,
we lock only the record, i.e., next-key locking is
not used. */
ulint lock_type;
+ trx_t* trx;
+
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
- if (srv_locks_unsafe_for_binlog) {
+ trx = thr_get_trx(thr);
+
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
@@ -1413,14 +1430,6 @@ rec_loop:
/* Ok, no need to test end_conds or mix id */
- } else if (plan->mixed_index) {
- /* We have to check if the record in a mixed cluster belongs
- to this table */
-
- if (!dict_is_mixed_table_rec(plan->table, rec)) {
-
- goto next_rec;
- }
}
/* We are ready to look at a possible new index entry in the result
@@ -1958,7 +1967,18 @@ fetch_step(
if (sel_node->state != SEL_NODE_NO_MORE_ROWS) {
- sel_assign_into_var_values(node->into_list, sel_node);
+ if (node->into_list) {
+ sel_assign_into_var_values(node->into_list,
+ sel_node);
+ } else {
+ void* ret = (*node->func->func)(sel_node,
+ node->func->arg);
+
+ if (!ret) {
+ sel_node->state =
+ SEL_NODE_NO_MORE_ROWS;
+ }
+ }
}
thr->run_node = que_node_get_parent(node);
@@ -1974,8 +1994,8 @@ fetch_step(
sel_node->common.parent = node;
if (sel_node->state == SEL_NODE_CLOSED) {
- /* SQL error detected */
- fprintf(stderr, "SQL error %lu\n", (ulong)DB_ERROR);
+ fprintf(stderr,
+ "InnoDB: Error: fetch called on a closed cursor\n");
que_thr_handle_error(thr, DB_ERROR, NULL, 0);
@@ -1987,6 +2007,76 @@ fetch_step(
return(thr);
}
+/********************************************************************
+Sample callback function for fetch that prints each row.*/
+
+void*
+row_fetch_print(
+/*============*/
+ /* out: always returns non-NULL */
+ void* row, /* in: sel_node_t* */
+ void* user_arg) /* in: not used */
+{
+ sel_node_t* node = row;
+ que_node_t* exp;
+ ulint i = 0;
+
+ UT_NOT_USED(user_arg);
+
+ fprintf(stderr, "row_fetch_print: row %p\n", row);
+
+ exp = node->select_list;
+
+ while (exp) {
+ dfield_t* dfield = que_node_get_val(exp);
+ dtype_t* type = dfield_get_type(dfield);
+
+ fprintf(stderr, " column %lu:\n", (ulong)i);
+
+ dtype_print(type);
+ fprintf(stderr, "\n");
+
+ ut_print_buf(stderr, dfield_get_data(dfield),
+ dfield_get_len(dfield));
+ fprintf(stderr, "\n");
+
+ exp = que_node_get_next(exp);
+ i++;
+ }
+
+ return((void*)42);
+}
+
+/********************************************************************
+Callback function for fetch that stores an unsigned 4 byte integer to the
+location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
+= 4. */
+
+void*
+row_fetch_store_uint4(
+/*==================*/
+ /* out: always returns NULL */
+ void* row, /* in: sel_node_t* */
+ void* user_arg) /* in: data pointer */
+{
+ sel_node_t* node = row;
+ ib_uint32_t* val = user_arg;
+ ulint tmp;
+
+ dfield_t* dfield = que_node_get_val(node->select_list);
+ dtype_t* type = dfield_get_type(dfield);
+ ulint len = dfield_get_len(dfield);
+
+ ut_a(dtype_get_mtype(type) == DATA_INT);
+ ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
+ ut_a(len == 4);
+
+ tmp = mach_read_from_4(dfield_get_data(dfield));
+ *val = tmp;
+
+ return(NULL);
+}
+
/***************************************************************
Prints a row in a select result. */
@@ -2397,18 +2487,16 @@ row_sel_field_store_in_mysql_format(
} else if (templ->type == DATA_MYSQL) {
memcpy(dest, data, len);
-#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG)
- ut_a(templ->mysql_col_len >= len);
- ut_a(templ->mbmaxlen >= templ->mbminlen);
+ ut_ad(templ->mysql_col_len >= len);
+ ut_ad(templ->mbmaxlen >= templ->mbminlen);
- ut_a(templ->mbmaxlen > templ->mbminlen
+ ut_ad(templ->mbmaxlen > templ->mbminlen
|| templ->mysql_col_len == len);
- ut_a(len * templ->mbmaxlen >= templ->mysql_col_len);
-#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */
/* 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_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
if (templ->mbminlen != templ->mbmaxlen) {
/* Pad with spaces. This undoes the stripping
@@ -2418,15 +2506,13 @@ row_sel_field_store_in_mysql_format(
memset(dest + len, 0x20, templ->mysql_col_len - len);
}
} else {
-#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG)
- ut_a(templ->type == DATA_CHAR
+ ut_ad(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);
-#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */
ut_ad(templ->mysql_col_len == len);
memcpy(dest, data, len);
@@ -3210,11 +3296,13 @@ stderr);
}
/* Reset the new record lock info if srv_locks_unsafe_for_binlog
- is set. Then we are able to remove the record locks set here on an
- individual row. */
+ is set or session is using a READ COMMITED isolation level. 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) {
+ if ((srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && prebuilt->select_lock_type != LOCK_NONE) {
trx_reset_new_rec_lock_info(trx);
}
@@ -3582,13 +3670,15 @@ rec_loop:
if (page_rec_is_supremum(rec)) {
if (set_also_gap_locks
- && !srv_locks_unsafe_for_binlog
- && prebuilt->select_lock_type != LOCK_NONE) {
+ && !(srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we do not lock gaps. Supremum record is really
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using a READ COMMITTED isolation
+ level we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
offsets = rec_get_offsets(rec, index, offsets,
@@ -3708,12 +3798,14 @@ wrong_offs:
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
if (set_also_gap_locks
- && !srv_locks_unsafe_for_binlog
- && prebuilt->select_lock_type != LOCK_NONE) {
+ && !(srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && 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 */
+ option is not set or this session is not
+ using a READ COMMITTED isolation level. */
err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
@@ -3739,12 +3831,14 @@ wrong_offs:
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
if (set_also_gap_locks
- && !srv_locks_unsafe_for_binlog
- && prebuilt->select_lock_type != LOCK_NONE) {
+ && !(srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && 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 */
+ option is not set or this session is not
+ using a READ COMMITTED isolation level. */
err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
@@ -3775,16 +3869,18 @@ wrong_offs:
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
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using a READ COMMITED isolation
+ level we lock only the record, i.e., next-key locking is
not used. */
ulint lock_type;
if (!set_also_gap_locks
- || srv_locks_unsafe_for_binlog
- || (unique_search && !UNIV_UNLIKELY(
- rec_get_deleted_flag(rec, comp)))) {
+ || srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED
+ || (unique_search
+ && !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
goto no_gap_lock;
} else {
@@ -3943,9 +4039,10 @@ no_gap_lock:
/* The record is delete-marked: we can skip it */
- if (srv_locks_unsafe_for_binlog
- && prebuilt->select_lock_type != LOCK_NONE
- && !did_semi_consistent_read) {
+ if ((srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && prebuilt->select_lock_type != LOCK_NONE
+ && !did_semi_consistent_read) {
/* No need to keep a lock on a delete-marked record
if we do not want to use next-key locking. */
@@ -3996,8 +4093,9 @@ requires_clust_rec:
/* The record is delete marked: we can skip it */
- if (srv_locks_unsafe_for_binlog
- && prebuilt->select_lock_type != LOCK_NONE) {
+ if ((srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && 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
@@ -4117,8 +4215,9 @@ next_rec:
}
did_semi_consistent_read = FALSE;
- if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog)
- && prebuilt->select_lock_type != LOCK_NONE) {
+ if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && prebuilt->select_lock_type != LOCK_NONE) {
trx_reset_new_rec_lock_info(trx);
}
@@ -4206,7 +4305,11 @@ lock_wait_or_error:
sel_restore_position_for_mysql(&same_user_rec,
BTR_SEARCH_LEAF, pcur,
moves_up, &mtr);
- if (srv_locks_unsafe_for_binlog && !same_user_rec) {
+
+ if ((srv_locks_unsafe_for_binlog
+ || trx->isolation_level == TRX_ISO_READ_COMMITTED)
+ && !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
diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index 23be601a17b..4023283a60c 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri
#include "log0log.h"
#include "pars0sym.h"
#include "eval0eval.h"
+#include "buf0lru.h"
/* What kind of latch and lock can we assume when the control comes to
@@ -869,6 +870,10 @@ row_upd_index_replace_new_col_vals_index_pos(
upd_t* update, /* in: an update vector built for the index so
that the field number in an upd_field is the
index position */
+ ibool order_only,
+ /* in: if TRUE, limit the replacement to
+ ordering fields of index; note that this
+ does not work for non-clustered indexes. */
mem_heap_t* heap) /* in: memory heap to which we allocate and
copy the new values, set this as NULL if you
do not want allocation */
@@ -879,13 +884,20 @@ row_upd_index_replace_new_col_vals_index_pos(
dfield_t* new_val;
ulint j;
ulint i;
+ ulint n_fields;
dtype_t* cur_type;
ut_ad(index);
dtuple_set_info_bits(entry, update->info_bits);
- for (j = 0; j < dict_index_get_n_fields(index); j++) {
+ if (order_only) {
+ n_fields = dict_index_get_n_unique(index);
+ } else {
+ n_fields = dict_index_get_n_fields(index);
+ }
+
+ for (j = 0; j < n_fields; j++) {
field = dict_index_get_nth_field(index, j);
@@ -1530,6 +1542,10 @@ row_upd_clust_rec(
return(err);
}
+ if (buf_LRU_buf_pool_running_out()) {
+
+ return(DB_LOCK_TABLE_FULL);
+ }
/* We may have to modify the tree structure: do a pessimistic descent
down the index tree */
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index 1256dd21c87..83cdcaa271b 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -362,30 +362,6 @@ ibool srv_print_innodb_lock_monitor = FALSE;
ibool srv_print_innodb_tablespace_monitor = FALSE;
ibool srv_print_innodb_table_monitor = FALSE;
-/* The parameters below are obsolete: */
-
-ibool srv_print_parsed_sql = FALSE;
-
-ulint srv_sim_disk_wait_pct = ULINT_MAX;
-ulint srv_sim_disk_wait_len = ULINT_MAX;
-ibool srv_sim_disk_wait_by_yield = FALSE;
-ibool srv_sim_disk_wait_by_wait = FALSE;
-
-ibool srv_measure_contention = FALSE;
-ibool srv_measure_by_spin = FALSE;
-
-ibool srv_test_extra_mutexes = FALSE;
-ibool srv_test_nocache = FALSE;
-ibool srv_test_cache_evict = FALSE;
-
-ibool srv_test_sync = FALSE;
-ulint srv_test_n_threads = ULINT_MAX;
-ulint srv_test_n_loops = ULINT_MAX;
-ulint srv_test_n_free_rnds = ULINT_MAX;
-ulint srv_test_n_reserved_rnds = ULINT_MAX;
-ulint srv_test_array_size = ULINT_MAX;
-ulint srv_test_n_mutexes = ULINT_MAX;
-
/* Array of English strings describing the current state of an
i/o handler thread */
@@ -911,10 +887,6 @@ srv_init(void)
srv_meter_foreground[i] = 250;
}
- srv_sys->operational = os_event_create(NULL);
-
- ut_a(srv_sys->operational);
-
UT_LIST_INIT(srv_sys->tasks);
/* create dummy table and index for old-style infimum and supremum */
@@ -1713,6 +1685,8 @@ srv_printf_innodb_monitor(
"; in additional pool allocated " ULINTPF "\n",
ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool));
+ fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
+ dict_sys->size);
if (srv_use_awe) {
fprintf(file,
@@ -1845,11 +1819,7 @@ srv_export_innodb_status(void)
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
@@ -2021,22 +1991,15 @@ exit_func:
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
-#ifndef __WIN__
- return(NULL);
-#else
- return(0);
-#endif
+
+ OS_THREAD_DUMMY_RETURN;
}
/*************************************************************************
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_error_monitor_thread(
/*=====================*/
/* out: a dummy parameter */
@@ -2118,11 +2081,7 @@ loop:
os_thread_exit(NULL);
-#ifndef __WIN__
- return(NULL);
-#else
- return(0);
-#endif
+ OS_THREAD_DUMMY_RETURN;
}
/***********************************************************************
@@ -2167,11 +2126,7 @@ srv_wake_master_thread(void)
/*************************************************************************
The master thread controlling the server. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
srv_master_thread(
/*==============*/
/* out: a dummy parameter */
@@ -2210,7 +2165,6 @@ srv_master_thread(
mutex_exit(&kernel_mutex);
- os_event_set(srv_sys->operational);
loop:
/*****************************************************************/
/* ---- When there is database activity by users, we cycle in this
@@ -2617,10 +2571,6 @@ suspend_thread:
os_thread_exit(NULL);
-#ifndef __WIN__
- return(NULL); /* Not reached */
-#else
- return(0);
-#endif
+ OS_THREAD_DUMMY_RETURN;
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index c792d600500..da2deac123d 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -426,11 +426,7 @@ srv_parse_log_group_home_dirs(
I/o-handler thread function. */
static
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
io_handler_thread(
/*==============*/
void* arg)
@@ -459,11 +455,7 @@ io_handler_thread(
os_thread_exit(NULL);
-#ifndef __WIN__
- return(NULL); /* Not reached */
-#else
- return(0);
-#endif
+ OS_THREAD_DUMMY_RETURN;
}
#endif /* !UNIV_HOTBACKUP */
@@ -1540,11 +1532,6 @@ NetWare. */
}
#endif /* UNIV_LOG_ARCHIVE */
- if (srv_measure_contention) {
- /* os_thread_create(&test_measure_cont, NULL, thread_ids +
- SRV_MAX_N_IO_THREADS); */
- }
-
/* fprintf(stderr, "Max allowed record size %lu\n",
page_get_free_space_of_empty() / 2); */
diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c
index 1f3d6df0403..fb7ec4cc78b 100644
--- a/storage/innobase/sync/sync0arr.c
+++ b/storage/innobase/sync/sync0arr.c
@@ -524,7 +524,7 @@ sync_array_cell_print(
"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n",
- mutex, mutex->cfile_name, (ulong) mutex->cline,
+ (void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line,
@@ -539,7 +539,7 @@ sync_array_cell_print(
fprintf(file,
" RW-latch at %p created in file %s line %lu\n",
- rwlock, rwlock->cfile_name,
+ (void*) rwlock, rwlock->cfile_name,
(ulong) rwlock->cline);
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
@@ -670,7 +670,6 @@ sync_array_detect_deadlock(
rw_lock_debug_t*debug;
ut_a(arr && start && cell);
- ut_ad(cell->state == SC_RESERVED);
ut_ad(cell->wait_object);
ut_ad(os_thread_get_curr_id() == start->thread);
ut_ad(depth < 100);
@@ -703,7 +702,7 @@ sync_array_detect_deadlock(
if (ret) {
fprintf(stderr,
"Mutex %p owned by thread %lu file %s line %lu\n",
- mutex,
+ (void*) mutex,
(ulong) os_thread_pf(mutex->thread_id),
mutex->file_name, (ulong) mutex->line);
sync_array_cell_print(stderr, cell);
@@ -740,7 +739,8 @@ sync_array_detect_deadlock(
thread, debug->pass, depth);
if (ret) {
print:
- fprintf(stderr, "rw-lock %p ", lock);
+ fprintf(stderr, "rw-lock %p ",
+ (void*) lock);
sync_array_cell_print(stderr, cell);
rw_lock_debug_print(debug);
return(TRUE);
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index b33c1553bae..673e1080d89 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -246,7 +246,7 @@ lock_loop:
if (srv_print_latch_waits) {
fprintf(stderr,
"Thread %lu spin wait rw-s-lock at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), lock,
+ (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) lock,
lock->cfile_name, (ulong) lock->cline, (ulong) i);
}
@@ -277,7 +277,8 @@ lock_loop:
fprintf(stderr,
"Thread %lu OS wait rw-s-lock at %p cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()),
- lock, lock->cfile_name, (ulong) lock->cline);
+ (void*) lock, lock->cfile_name,
+ (ulong) lock->cline);
}
rw_s_system_call_count++;
@@ -495,8 +496,8 @@ lock_loop:
if (srv_print_latch_waits) {
fprintf(stderr,
"Thread %lu spin wait rw-x-lock at %p cfile %s cline %lu rnds %lu\n",
- os_thread_pf(os_thread_get_curr_id()), lock,
- lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ os_thread_pf(os_thread_get_curr_id()), (void*) lock,
+ lock->cfile_name, (ulong) lock->cline, (ulong) i);
}
rw_x_spin_wait_count++;
@@ -528,8 +529,8 @@ lock_loop:
if (srv_print_latch_waits) {
fprintf(stderr,
"Thread %lu OS wait for rw-x-lock at %p cfile %s cline %lu\n",
- os_thread_pf(os_thread_get_curr_id()), lock,
- lock->cfile_name, (ulong) lock->cline);
+ os_thread_pf(os_thread_get_curr_id()), (void*) lock,
+ lock->cfile_name, (ulong) lock->cline);
}
rw_x_system_call_count++;
@@ -787,7 +788,7 @@ rw_lock_list_print_info(void)
|| (rw_lock_get_reader_count(lock) != 0)
|| (rw_lock_get_waiters(lock) != 0)) {
- fprintf(stderr, "RW-LOCK: %p ", lock);
+ fprintf(stderr, "RW-LOCK: %p ", (void*) lock);
if (rw_lock_get_waiters(lock)) {
fputs(" Waiters for the lock exist\n", stderr);
@@ -823,7 +824,7 @@ rw_lock_print(
fprintf(stderr,
"-------------\n"
"RW-LATCH INFO\n"
- "RW-LATCH: %p ", lock);
+ "RW-LATCH: %p ", (void*) lock);
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|| (rw_lock_get_reader_count(lock) != 0)
diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
index 86fa66d5112..6354830df70 100644
--- a/storage/innobase/sync/sync0sync.c
+++ b/storage/innobase/sync/sync0sync.c
@@ -423,7 +423,7 @@ spin_loop:
#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,
+ (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
@@ -485,7 +485,7 @@ spin_loop:
fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
" mutex at %p\n",
(ulong) os_thread_pf(os_thread_get_curr_id()),
- mutex);
+ (void*) mutex);
#endif
goto finish_timing;
@@ -503,7 +503,7 @@ spin_loop:
#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,
+ (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
@@ -666,7 +666,7 @@ mutex_list_print_info(void)
&thread_id);
fprintf(stderr,
"Locked mutex: addr %p thread %ld file %s line %ld\n",
- mutex, os_thread_pf(thread_id),
+ (void*) mutex, os_thread_pf(thread_id),
file_name, line);
}
@@ -852,10 +852,10 @@ sync_thread_levels_g(
fprintf(stderr,
"InnoDB: Locked mutex: addr %p thread %ld file %s line %ld\n",
- mutex, os_thread_pf(thread_id), file_name, (ulong) line);
+ (void*) mutex, os_thread_pf(thread_id), file_name, (ulong) line);
#else /* UNIV_SYNC_DEBUG */
fprintf(stderr,
- "InnoDB: Locked mutex: addr %p\n", mutex);
+ "InnoDB: Locked mutex: addr %p\n", (void*) mutex);
#endif /* UNIV_SYNC_DEBUG */
} else {
fputs("Not locked\n", stderr);
diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c
index fd733ef5fb8..af74cfe9032 100644
--- a/storage/innobase/trx/trx0roll.c
+++ b/storage/innobase/trx/trx0roll.c
@@ -391,11 +391,7 @@ 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.
Note: this is done in a background thread. */
-#ifndef __WIN__
-void*
-#else
-ulint
-#endif
+os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
@@ -576,13 +572,7 @@ leave_function:
os_thread_exit(NULL);
- /* The following is dummy code to keep the compiler happy: */
-
-#ifndef __WIN__
- return(NULL);
-#else
- return(0);
-#endif
+ OS_THREAD_DUMMY_RETURN;
}
/***********************************************************************
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index 90d6d92c09e..a3115e332cd 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -366,8 +366,6 @@ trx_free_for_mysql(
/*===============*/
trx_t* trx) /* in, own: trx object */
{
- thr_local_free(trx->mysql_thread_id);
-
mutex_enter(&kernel_mutex);
UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
@@ -1770,6 +1768,9 @@ trx_print(
fprintf(f, "%lu lock struct(s), heap size %lu",
(ulong) UT_LIST_GET_LEN(trx->trx_locks),
(ulong) mem_heap_get_size(trx->lock_heap));
+
+ fprintf(f, "%lu row lock(s)",
+ (ulong) lock_number_of_rows_locked(trx));
}
if (trx->has_search_latch) {
diff --git a/storage/innobase/ut/Makefile.am b/storage/innobase/ut/Makefile.am
index 2fdbb99e0f3..c833a6d5a4c 100644
--- a/storage/innobase/ut/Makefile.am
+++ b/storage/innobase/ut/Makefile.am
@@ -19,6 +19,6 @@ include ../include/Makefile.i
noinst_LIBRARIES = libut.a
-libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c
+libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c
EXTRA_PROGRAMS =
diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c
index 345c14e00f9..4358edba8c0 100644
--- a/storage/innobase/ut/ut0mem.c
+++ b/storage/innobase/ut/ut0mem.c
@@ -437,3 +437,96 @@ ut_memcpyq(
return(dest);
}
+
+/**************************************************************************
+Return the number of times s2 occurs in s1. Overlapping instances of s2
+are only counted once. */
+
+ulint
+ut_strcount(
+/*========*/
+ /* out: the number of times s2 occurs in s1 */
+ const char* s1, /* in: string to search in */
+ const char* s2) /* in: string to search for */
+{
+ ulint count = 0;
+ ulint len = strlen(s2);
+
+ if (len == 0) {
+
+ return(0);
+ }
+
+ for (;;) {
+ s1 = strstr(s1, s2);
+
+ if (!s1) {
+
+ break;
+ }
+
+ count++;
+ s1 += len;
+ }
+
+ return(count);
+}
+
+/**************************************************************************
+Replace every occurrence of s1 in str with s2. Overlapping instances of s1
+are only replaced once. */
+
+char *
+ut_strreplace(
+/*==========*/
+ /* out, own: modified string, must be
+ freed with mem_free() */
+ const char* str, /* in: string to operate on */
+ const char* s1, /* in: string to replace */
+ const char* s2) /* in: string to replace s1 with */
+{
+ char* new_str;
+ char* ptr;
+ const char* str_end;
+ ulint str_len = strlen(str);
+ ulint s1_len = strlen(s1);
+ ulint s2_len = strlen(s2);
+ ulint count = 0;
+ int len_delta = (int)s2_len - (int)s1_len;
+
+ str_end = str + str_len;
+
+ if (len_delta <= 0) {
+ len_delta = 0;
+ } else {
+ count = ut_strcount(str, s1);
+ }
+
+ new_str = mem_alloc(str_len + count * len_delta + 1);
+ ptr = new_str;
+
+ while (str) {
+ const char* next = strstr(str, s1);
+
+ if (!next) {
+ next = str_end;
+ }
+
+ memcpy(ptr, str, next - str);
+ ptr += next - str;
+
+ if (next == str_end) {
+
+ break;
+ }
+
+ memcpy(ptr, s2, s2_len);
+ ptr += s2_len;
+
+ str = next + s1_len;
+ }
+
+ *ptr = '\0';
+
+ return(new_str);
+}
diff --git a/storage/innobase/ut/ut0vec.c b/storage/innobase/ut/ut0vec.c
new file mode 100644
index 00000000000..3f61c8c8386
--- /dev/null
+++ b/storage/innobase/ut/ut0vec.c
@@ -0,0 +1,54 @@
+#include "ut0vec.h"
+#ifdef UNIV_NONINL
+#include "ut0vec.ic"
+#endif
+#include <string.h>
+
+/********************************************************************
+Create a new vector with the given initial size. */
+
+ib_vector_t*
+ib_vector_create(
+/*=============*/
+ /* out: vector */
+ mem_heap_t* heap, /* in: heap */
+ ulint size) /* in: initial size */
+{
+ ib_vector_t* vec;
+
+ ut_a(size > 0);
+
+ vec = mem_heap_alloc(heap, sizeof(*vec));
+
+ vec->heap = heap;
+ vec->data = mem_heap_alloc(heap, sizeof(void*) * size);
+ vec->used = 0;
+ vec->total = size;
+
+ return(vec);
+}
+
+/********************************************************************
+Push a new element to the vector, increasing its size if necessary. */
+
+void
+ib_vector_push(
+/*===========*/
+ ib_vector_t* vec, /* in: vector */
+ void* elem) /* in: data element */
+{
+ if (vec->used >= vec->total) {
+ void** new_data;
+ ulint new_total = vec->total * 2;
+
+ new_data = mem_heap_alloc(vec->heap,
+ sizeof(void*) * new_total);
+ memcpy(new_data, vec->data, sizeof(void*) * vec->total);
+
+ vec->data = new_data;
+ vec->total = new_total;
+ }
+
+ vec->data[vec->used] = elem;
+ vec->used++;
+}
diff --git a/storage/myisam/cmakelists.txt b/storage/myisam/CMakeLists.txt
index 3ba7aba4555..3ba7aba4555 100644
--- a/storage/myisam/cmakelists.txt
+++ b/storage/myisam/CMakeLists.txt
diff --git a/storage/myisam/Makefile.am b/storage/myisam/Makefile.am
index 3c6a5c22234..081d7facf3a 100644
--- a/storage/myisam/Makefile.am
+++ b/storage/myisam/Makefile.am
@@ -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
-EXTRA_DIST = mi_test_all.sh mi_test_all.res ft_stem.c cmakelists.txt
+EXTRA_DIST = mi_test_all.sh mi_test_all.res ft_stem.c CMakeLists.txt
pkgdata_DATA = mi_test_all mi_test_all.res
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
diff --git a/storage/myisam/ft_eval.c b/storage/myisam/ft_eval.c
index eab9d37af0b..459742d2aff 100644
--- a/storage/myisam/ft_eval.c
+++ b/storage/myisam/ft_eval.c
@@ -54,6 +54,7 @@ int main(int argc, char *argv[])
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[0].seg[0].type= HA_KEYTYPE_TEXT;
keyinfo[0].seg[0].flag= HA_BLOB_PART;
keyinfo[0].seg[0].start=recinfo[0].length;
diff --git a/storage/myisam/ft_test1.c b/storage/myisam/ft_test1.c
index d54b344e2cd..28dcfb2b758 100644
--- a/storage/myisam/ft_test1.c
+++ b/storage/myisam/ft_test1.c
@@ -89,6 +89,7 @@ static int run_test(const char *filename)
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
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_PART:0;
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index eb2f42697ce..0fa095a21db 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -358,7 +358,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
puts("- check key delete-chain");
param->key_file_blocks=info->s->base.keystart;
- for (key=0 ; key < info->s->state.header.max_block_size ; key++)
+ for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
if (check_k_link(param,info,key))
{
if (param->testflag & T_VERBOSE) puts("");
@@ -1411,7 +1411,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
share->state.key_root[i]= HA_OFFSET_ERROR;
/* Drop the delete chain. */
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
/*
@@ -1795,7 +1795,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
for (key=0 ; key < info->s->base.keys ; key++)
info->s->state.key_root[key]=index_pos[key];
- for (key=0 ; key < info->s->state.header.max_block_size ; key++)
+ for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
info->s->state.key_del[key]= HA_OFFSET_ERROR;
info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
@@ -2095,7 +2095,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
@@ -2463,7 +2463,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
@@ -3800,6 +3800,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
ha_rows max_records;
ulonglong file_length,tmp_length;
MI_CREATE_INFO create_info;
+ DBUG_ENTER("recreate_table");
error=1; /* Default error */
info= **org_info;
@@ -3809,7 +3810,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
(param->testflag & T_UNPACK);
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
- return 0;
+ DBUG_RETURN(0);
memcpy((byte*) keyinfo,(byte*) share.keyinfo,
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
@@ -3818,14 +3819,14 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
(key_parts+share.base.keys))))
{
my_afree((gptr) keyinfo);
- return 1;
+ DBUG_RETURN(1);
}
if (!(recdef=(MI_COLUMNDEF*)
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
{
my_afree((gptr) keyinfo);
my_afree((gptr) keysegs);
- return 1;
+ DBUG_RETURN(1);
}
if (!(uniquedef=(MI_UNIQUEDEF*)
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
@@ -3833,7 +3834,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
my_afree((gptr) recdef);
my_afree((gptr) keyinfo);
my_afree((gptr) keysegs);
- return 1;
+ DBUG_RETURN(1);
}
/* Copy the column definitions */
@@ -3903,6 +3904,11 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
create_info.language = (param->language ? param->language :
share.state.header.language);
create_info.key_file_length= status_info.key_file_length;
+ /*
+ Allow for creating an auto_increment key. This has an effect only if
+ an auto_increment key exists in the original table.
+ */
+ create_info.with_auto_increment= TRUE;
/* We don't have to handle symlinks here because we are using
HA_DONT_TOUCH_DATA */
if (mi_create(filename,
@@ -3947,7 +3953,7 @@ end:
my_afree((gptr) keyinfo);
my_afree((gptr) recdef);
my_afree((gptr) keysegs);
- return error;
+ DBUG_RETURN(error);
}
@@ -4050,6 +4056,8 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
my_bool repair_only)
{
byte *record;
+ DBUG_ENTER("update_auto_increment_key");
+
if (!info->s->base.auto_key ||
! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
{
@@ -4057,7 +4065,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_check_print_info(param,
"Table: %s doesn't have an auto increment key\n",
param->isam_file_name);
- return;
+ DBUG_VOID_RETURN;
}
if (!(param->testflag & T_SILENT) &&
!(param->testflag & T_REP))
@@ -4070,7 +4078,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
MYF(0))))
{
mi_check_print_error(param,"Not enough memory for extra record");
- return;
+ DBUG_VOID_RETURN;
}
mi_extra(info,HA_EXTRA_KEYREAD,0);
@@ -4081,7 +4089,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0));
mi_check_print_error(param,"%d when reading last record",my_errno);
- return;
+ DBUG_VOID_RETURN;
}
if (!repair_only)
info->s->state.auto_increment=param->auto_increment_value;
@@ -4097,7 +4105,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0));
update_state_info(param, info, UPDATE_AUTO_INC);
- return;
+ DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index 3be998b2c17..22cbde278be 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -28,9 +28,9 @@
#endif
#include <m_ctype.h>
- /*
- ** Old options is used when recreating database, from isamchk
- */
+/*
+ Old options is used when recreating database, from myisamchk
+*/
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
uint columns, MI_COLUMNDEF *recinfo,
@@ -45,6 +45,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_length,info_length,key_segs,options,min_key_length_skip,
base_pos,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,fulltext_keys,offset;
+ uint aligned_key_start, block_length;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
@@ -428,8 +429,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
+ /* Get block length for key, if defined by user */
+ block_length= (keydef->block_length ?
+ my_round_up_to_next_power(keydef->block_length) :
+ myisam_block_size);
+ block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
+ block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
+
keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
- pointer,MI_MAX_KEYPTR_SIZE);
+ pointer,MI_MAX_KEYPTR_SIZE,
+ block_length);
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
length >= MI_MAX_KEY_BUFF)
{
@@ -485,7 +494,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.base_pos,base_pos);
share.state.header.language= (ci->language ?
ci->language : default_charset_info->number);
- share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
+ share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
share.state.dellink = HA_OFFSET_ERROR;
share.state.process= (ulong) getpid();
@@ -512,8 +521,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
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);
+ aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
+ max_key_block_length :
+ myisam_block_size);
+
+ share.base.keystart= share.state.state.key_file_length=
+ MY_ALIGN(info_length, aligned_key_start);
share.base.max_key_block_length=max_key_block_length;
share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
share.base.records=ci->max_rows;
diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
index 36d88bd362a..9d76a1fb9a5 100644
--- a/storage/myisam/mi_dynrec.c
+++ b/storage/myisam/mi_dynrec.c
@@ -67,6 +67,11 @@ static int _mi_cmp_buffer(File file, const byte *buff, my_off_t filepos,
my_bool mi_dynmap_file(MI_INFO *info, my_off_t size)
{
DBUG_ENTER("mi_dynmap_file");
+ if (size > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
+ {
+ DBUG_PRINT("warning", ("File is too large for mmap"));
+ DBUG_RETURN(1);
+ }
info->s->file_map= (byte*)
my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
info->s->mode==O_RDONLY ? PROT_READ :
diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c
index f8463a0b6b0..526a733e724 100644
--- a/storage/myisam/mi_key.c
+++ b/storage/myisam/mi_key.c
@@ -127,7 +127,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint pack_length= keyseg->bit_start;
+ uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
pos+= pack_length; /* Skip VARCHAR length */
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index 91bf438035f..b61c1af24da 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -295,7 +295,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&share->data_file_name,strlen(data_name)+1,
&share->state.key_root,keys*sizeof(my_off_t),
&share->state.key_del,
- (share->state.header.max_block_size*sizeof(my_off_t)),
+ (share->state.header.max_block_size_index*sizeof(my_off_t)),
#ifdef THREAD
&share->key_root_lock,sizeof(rw_lock_t)*keys,
#endif
@@ -310,7 +310,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(char*) key_root, sizeof(my_off_t)*keys);
memcpy((char*) share->state.key_del,
(char*) key_del, (sizeof(my_off_t) *
- share->state.header.max_block_size));
+ share->state.header.max_block_size_index));
strmov(share->unique_file_name, name_buff);
share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name);
@@ -820,7 +820,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
uchar *ptr=buff;
uint i, keys= (uint) state->header.keys,
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
DBUG_ENTER("mi_state_info_write");
memcpy_fixed(ptr,&state->header,sizeof(state->header));
@@ -886,7 +886,7 @@ uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
ptr +=sizeof(state->header);
keys=(uint) state->header.keys;
key_parts=mi_uint2korr(state->header.key_parts);
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
state->open_count = mi_uint2korr(ptr); ptr +=2;
state->changed= (bool) *ptr++;
@@ -1059,7 +1059,7 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
keydef->minlength = mi_uint2korr(ptr); ptr +=2;
keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
- keydef->block_size = keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
+ keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
keydef->underflow_block_length=keydef->block_length/3;
keydef->version = 0; /* Not saved */
keydef->parser = &ft_default_parser;
diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c
index 5240c063fba..a5e2b01ed0f 100644
--- a/storage/myisam/mi_page.c
+++ b/storage/myisam/mi_page.c
@@ -112,8 +112,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
DBUG_ENTER("_mi_dispose");
DBUG_PRINT("enter",("pos: %ld", (long) pos));
- old_link=info->s->state.key_del[keyinfo->block_size];
- info->s->state.key_del[keyinfo->block_size]=pos;
+ old_link= info->s->state.key_del[keyinfo->block_size_index];
+ info->s->state.key_del[keyinfo->block_size_index]= pos;
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache,
@@ -132,7 +132,8 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
char buff[8];
DBUG_ENTER("_mi_new");
- if ((pos=info->s->state.key_del[keyinfo->block_size]) == HA_OFFSET_ERROR)
+ if ((pos= info->s->state.key_del[keyinfo->block_size_index]) ==
+ HA_OFFSET_ERROR)
{
if (info->state->key_file_length >=
info->s->base.max_key_file_length - keyinfo->block_length)
@@ -152,7 +153,7 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
(uint) keyinfo->block_length,0))
pos= HA_OFFSET_ERROR;
else
- info->s->state.key_del[keyinfo->block_size]=mi_sizekorr(buff);
+ info->s->state.key_del[keyinfo->block_size_index]= mi_sizekorr(buff);
}
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_PRINT("exit",("Pos: %ld",(long) pos));
diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c
index 0e62b074376..0b78ac8a7ff 100644
--- a/storage/myisam/mi_test1.c
+++ b/storage/myisam/mi_test1.c
@@ -95,6 +95,7 @@ static int run_test(const char *filename)
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= pack_seg;
diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c
index e77a37d853f..357ebb1b9bc 100644
--- a/storage/myisam/mi_test2.c
+++ b/storage/myisam/mi_test2.c
@@ -95,6 +95,7 @@ int main(int argc, char *argv[])
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = pack_type;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[1].seg= &glob_keyseg[1][0];
keyinfo[1].seg[0].start=7;
keyinfo[1].seg[0].length=6;
@@ -111,6 +112,7 @@ int main(int argc, char *argv[])
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=2;
keyinfo[1].flag =0;
+ keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH; /* Diff blocklength */
keyinfo[2].seg= &glob_keyseg[2][0];
keyinfo[2].seg[0].start=12;
keyinfo[2].seg[0].length=8;
@@ -121,6 +123,7 @@ int main(int argc, char *argv[])
keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
keyinfo[2].keysegs=1;
keyinfo[2].flag =HA_NOSAME;
+ keyinfo[2].block_length= 0; /* Default block length */
keyinfo[3].seg= &glob_keyseg[3][0];
keyinfo[3].seg[0].start=0;
keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
@@ -132,6 +135,7 @@ int main(int argc, char *argv[])
keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
keyinfo[3].keysegs=1;
keyinfo[3].flag = pack_type;
+ keyinfo[3].block_length= 0; /* Default block length */
keyinfo[4].seg= &glob_keyseg[4][0];
keyinfo[4].seg[0].start=0;
keyinfo[4].seg[0].length=5;
@@ -143,6 +147,7 @@ int main(int argc, char *argv[])
keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
keyinfo[4].keysegs=1;
keyinfo[4].flag = pack_type;
+ keyinfo[4].block_length= 0; /* Default block length */
keyinfo[5].seg= &glob_keyseg[5][0];
keyinfo[5].seg[0].start=0;
keyinfo[5].seg[0].length=4;
@@ -154,6 +159,7 @@ int main(int argc, char *argv[])
keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
keyinfo[5].keysegs=1;
keyinfo[5].flag = pack_type;
+ keyinfo[5].block_length= 0; /* Default block length */
recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[0].length=7;
@@ -813,7 +819,7 @@ end:
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);
- printf("myisam_block_size: %u\n", myisam_block_size);
+ printf("myisam_block_size: %lu\n", myisam_block_size);
if (key_cacheing)
{
puts("Key cache used");
@@ -914,13 +920,13 @@ static void get_options(int argc, char **argv)
}
break;
case 'e': /* myisam_block_length */
- if ((myisam_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
+ if ((myisam_block_size= atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
{
fprintf(stderr,"Wrong myisam_block_length\n");
exit(1);
}
- myisam_block_size=1 << my_bit_log2(myisam_block_size);
+ myisam_block_size= my_round_up_to_next_power(myisam_block_size);
break;
case 'E': /* myisam_block_length */
if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
@@ -929,7 +935,7 @@ static void get_options(int argc, char **argv)
fprintf(stderr,"Wrong key_cache_block_size\n");
exit(1);
}
- key_cache_block_size=1 << my_bit_log2(key_cache_block_size);
+ key_cache_block_size= my_round_up_to_next_power(key_cache_block_size);
break;
case 'f':
if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c
index 4e764c6f971..173fbe64cf5 100644
--- a/storage/myisam/mi_test3.c
+++ b/storage/myisam/mi_test3.c
@@ -76,6 +76,7 @@ int main(int argc,char **argv)
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = (uint8) HA_PACK_KEY;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[1].seg= &keyseg[1][0];
keyinfo[1].seg[0].start=8;
keyinfo[1].seg[0].length=4; /* Long is always 4 in myisam */
@@ -84,6 +85,7 @@ int main(int argc,char **argv)
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=1;
keyinfo[1].flag =HA_NOSAME;
+ keyinfo[1].block_length= 0; /* Default block length */
recinfo[0].type=0;
recinfo[0].length=sizeof(record.id);
diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c
index edf1af144d4..990971cface 100644
--- a/storage/myisam/myisam_ftdump.c
+++ b/storage/myisam/myisam_ftdump.c
@@ -34,20 +34,20 @@ static uint lengths[256];
static struct my_option my_long_options[] =
{
- {"dump", 'd', "Dump index (incl. data offsets and word weights).",
+ {"help", 'h', "Display help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"stats", 's', "Report global stats.",
+ {"help", '?', "Synonym for -h.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Be verbose.",
- (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"count", 'c', "Calculate per-word stats (counts and global weights).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"length", 'l', "Report length distribution.",
+ {"dump", 'd', "Dump index (incl. data offsets and word weights).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", 'h', "Display help and exit.",
+ {"length", 'l', "Report length distribution.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", '?', "Synonym for -h.",
+ {"stats", 's', "Report global stats.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"verbose", 'v', "Be verbose.",
+ (gptr*) &verbose, (gptr*) &verbose, 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}
};
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index caf6254c321..0b450de9c03 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -55,7 +55,7 @@ typedef struct st_mi_state_info
uchar keys; /* number of keys in file */
uchar uniques; /* number of UNIQUE definitions */
uchar language; /* Language for indexes */
- uchar max_block_size; /* max keyblock size */
+ uchar max_block_size_index; /* max keyblock size */
uchar fulltext_keys;
uchar not_used; /* To align to 8 */
} header;
@@ -431,7 +431,7 @@ typedef struct st_mi_sort_param
#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */
#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
-#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/myisam_block_size+1)*myisam_block_size)
+#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size))
#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */
#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */
@@ -742,6 +742,8 @@ my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
+my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
+void mi_remap_file(MI_INFO *info, my_off_t size);
/* Functions needed by mi_check */
volatile int *killed_ptr(MI_CHECK *param);
diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c
index de55b86252c..17af4ab34a2 100644
--- a/storage/myisam/myisamlog.c
+++ b/storage/myisam/myisamlog.c
@@ -475,7 +475,7 @@ static int examine_log(my_string file_name, char **table_names)
{
if (!curr_file_info->closed)
files_open--;
- VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
+ VOID(tree_delete(&tree, (gptr) curr_file_info, 0, tree.custom_arg));
}
break;
case MI_LOG_EXTRA:
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index e80a3ffacd9..5b3067cb115 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -2726,6 +2726,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
}
case FIELD_LAST:
+ case FIELD_enum_val_count:
abort(); /* Impossible */
}
start_pos+=count->max_zero_fill;
@@ -2965,7 +2966,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
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++)
+ for (key=0 ; key < share->state.header.max_block_size_index ; key++)
share->state.key_del[key]= HA_OFFSET_ERROR;
isam_file->state->checksum=crc; /* Save crc here */
share->changed=1; /* Force write of header */
diff --git a/storage/myisammrg/cmakelists.txt b/storage/myisammrg/CMakeLists.txt
index 83168f6c60c..83168f6c60c 100644
--- a/storage/myisammrg/cmakelists.txt
+++ b/storage/myisammrg/CMakeLists.txt
diff --git a/storage/myisammrg/Makefile.am b/storage/myisammrg/Makefile.am
index 0719780b366..0402f2730b9 100644
--- a/storage/myisammrg/Makefile.am
+++ b/storage/myisammrg/Makefile.am
@@ -23,7 +23,7 @@ libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \
myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \
myrg_rnext_same.c
-EXTRA_DIST = cmakelists.txt
+EXTRA_DIST = CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/ndb/home/bin/Linuxmkisofs b/storage/ndb/home/bin/Linuxmkisofs
deleted file mode 100755
index a531f4cca7b..00000000000
--- a/storage/ndb/home/bin/Linuxmkisofs
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/home/bin/Solarismkisofs b/storage/ndb/home/bin/Solarismkisofs
deleted file mode 100755
index b239eaed6ad..00000000000
--- a/storage/ndb/home/bin/Solarismkisofs
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/home/bin/cvs2cl.pl b/storage/ndb/home/bin/cvs2cl.pl
deleted file mode 100755
index 9e6da5acf5b..00000000000
--- a/storage/ndb/home/bin/cvs2cl.pl
+++ /dev/null
@@ -1,1865 +0,0 @@
-#!/bin/sh
-exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
-#!perl -w
-
-##############################################################
-### ###
-### cvs2cl.pl: produce ChangeLog(s) from `cvs log` output. ###
-### ###
-##############################################################
-
-## $Revision: 2.38 $
-## $Date: 2001/02/12 19:54:35 $
-## $Author: kfogel $
-##
-## (C) 1999 Karl Fogel <kfogel@red-bean.com>, under the GNU GPL.
-##
-## (Extensively hacked on by Melissa O'Neill <oneill@cs.sfu.ca>.)
-##
-## cvs2cl.pl is free software; you can redistribute 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.
-##
-## cvs2cl.pl is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-## GNU General Public License for more details.
-##
-## You may have received a copy of the GNU General Public License
-## along with cvs2cl.pl; see the file COPYING. If not, write to the
-## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-## Boston, MA 02111-1307, USA.
-
-
-
-use strict;
-use Text::Wrap;
-use Time::Local;
-use File::Basename;
-
-
-# The Plan:
-#
-# Read in the logs for multiple files, spit out a nice ChangeLog that
-# mirrors the information entered during `cvs commit'.
-#
-# The problem presents some challenges. In an ideal world, we could
-# detect files with the same author, log message, and checkin time --
-# each <filelist, author, time, logmessage> would be a changelog entry.
-# We'd sort them; and spit them out. Unfortunately, CVS is *not atomic*
-# so checkins can span a range of times. Also, the directory structure
-# could be hierarchical.
-#
-# Another question is whether we really want to have the ChangeLog
-# exactly reflect commits. An author could issue two related commits,
-# with different log entries, reflecting a single logical change to the
-# source. GNU style ChangeLogs group these under a single author/date.
-# We try to do the same.
-#
-# So, we parse the output of `cvs log', storing log messages in a
-# multilevel hash that stores the mapping:
-# directory => author => time => message => filelist
-# As we go, we notice "nearby" commit times and store them together
-# (i.e., under the same timestamp), so they appear in the same log
-# entry.
-#
-# When we've read all the logs, we twist this mapping into
-# a time => author => message => filelist mapping for each directory.
-#
-# If we're not using the `--distributed' flag, the directory is always
-# considered to be `./', even as descend into subdirectories.
-
-
-############### Globals ################
-
-
-# What we run to generate it:
-my $Log_Source_Command = "cvs log";
-
-# In case we have to print it out:
-my $VERSION = '$Revision: 2.38 $';
-$VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/;
-
-## Vars set by options:
-
-# Print debugging messages?
-my $Debug = 0;
-
-# Just show version and exit?
-my $Print_Version = 0;
-
-# Just print usage message and exit?
-my $Print_Usage = 0;
-
-# Single top-level ChangeLog, or one per subdirectory?
-my $Distributed = 0;
-
-# What file should we generate (defaults to "ChangeLog")?
-my $Log_File_Name = "ChangeLog";
-
-# Grab most recent entry date from existing ChangeLog file, just add
-# to that ChangeLog.
-my $Cumulative = 0;
-
-# Expand usernames to email addresses based on a map file?
-my $User_Map_File = "";
-
-# Output to a file or to stdout?
-my $Output_To_Stdout = 0;
-
-# Eliminate empty log messages?
-my $Prune_Empty_Msgs = 0;
-
-# Don't call Text::Wrap on the body of the message
-my $No_Wrap = 0;
-
-# Separates header from log message. Code assumes it is either " " or
-# "\n\n", so if there's ever an option to set it to something else,
-# make sure to go through all conditionals that use this var.
-my $After_Header = " ";
-
-# Format more for programs than for humans.
-my $XML_Output = 0;
-
-# Do some special tweaks for log data that was written in FSF
-# ChangeLog style.
-my $FSF_Style = 0;
-
-# Show times in UTC instead of local time
-my $UTC_Times = 0;
-
-# Show day of week in output?
-my $Show_Day_Of_Week = 0;
-
-# Show revision numbers in output?
-my $Show_Revisions = 0;
-
-# Show tags (symbolic names) in output?
-my $Show_Tags = 0;
-
-# Show branches by symbolic name in output?
-my $Show_Branches = 0;
-
-# Show only revisions on these branches or their ancestors.
-my @Follow_Branches;
-
-# Don't bother with files matching this regexp.
-my @Ignore_Files;
-
-# How exactly we match entries. We definitely want "o",
-# and user might add "i" by using --case-insensitive option.
-my $Case_Insensitive = 0;
-
-# Maybe only show log messages matching a certain regular expression.
-my $Regexp_Gate = "";
-
-# Pass this global option string along to cvs, to the left of `log':
-my $Global_Opts = "";
-
-# Pass this option string along to the cvs log subcommand:
-my $Command_Opts = "";
-
-# Read log output from stdin instead of invoking cvs log?
-my $Input_From_Stdin = 0;
-
-# Don't show filenames in output.
-my $Hide_Filenames = 0;
-
-# Max checkin duration. CVS checkin is not atomic, so we may have checkin
-# times that span a range of time. We assume that checkins will last no
-# longer than $Max_Checkin_Duration seconds, and that similarly, no
-# checkins will happen from the same users with the same message less
-# than $Max_Checkin_Duration seconds apart.
-my $Max_Checkin_Duration = 180;
-
-# What to put at the front of [each] ChangeLog.
-my $ChangeLog_Header = "";
-
-## end vars set by options.
-
-# In 'cvs log' output, one long unbroken line of equal signs separates
-# files:
-my $file_separator = "======================================="
- . "======================================";
-
-# In 'cvs log' output, a shorter line of dashes separates log messages
-# within a file:
-my $logmsg_separator = "----------------------------";
-
-
-############### End globals ############
-
-
-
-
-&parse_options ();
-&derive_change_log ();
-
-
-
-### Everything below is subroutine definitions. ###
-
-# If accumulating, grab the boundary date from pre-existing ChangeLog.
-sub maybe_grab_accumulation_date ()
-{
- if (! $Cumulative) {
- return "";
- }
-
- # else
-
- open (LOG, "$Log_File_Name")
- or die ("trouble opening $Log_File_Name for reading ($!)");
-
- my $boundary_date;
- while (<LOG>)
- {
- if (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/)
- {
- $boundary_date = "$1";
- last;
- }
- }
-
- close (LOG);
- return $boundary_date;
-}
-
-
-# Fills up a ChangeLog structure in the current directory.
-sub derive_change_log ()
-{
- # See "The Plan" above for a full explanation.
-
- my %grand_poobah;
-
- my $file_full_path;
- my $time;
- my $revision;
- my $author;
- my $msg_txt;
- my $detected_file_separator;
-
- # Might be adding to an existing ChangeLog
- my $accumulation_date = &maybe_grab_accumulation_date ();
- if ($accumulation_date) {
- $Log_Source_Command .= " -d\'>${accumulation_date}\'";
- }
-
- # We might be expanding usernames
- my %usermap;
-
- # In general, it's probably not very maintainable to use state
- # variables like this to tell the loop what it's doing at any given
- # moment, but this is only the first one, and if we never have more
- # than a few of these, it's okay.
- my $collecting_symbolic_names = 0;
- my %symbolic_names; # Where tag names get stored.
- my %branch_names; # We'll grab branch names while we're at it.
- my %branch_numbers; # Save some revisions for @Follow_Branches
- my @branch_roots; # For showing which files are branch ancestors.
-
- # Bleargh. Compensate for a deficiency of custom wrapping.
- if (($After_Header ne " ") and $FSF_Style)
- {
- $After_Header .= "\t";
- }
-
- if (! $Input_From_Stdin) {
- open (LOG_SOURCE, "$Log_Source_Command |")
- or die "unable to run \"${Log_Source_Command}\"";
- }
- else {
- open (LOG_SOURCE, "-") or die "unable to open stdin for reading";
- }
-
- %usermap = &maybe_read_user_map_file ();
-
- while (<LOG_SOURCE>)
- {
- # If on a new file and don't see filename, skip until we find it, and
- # when we find it, grab it.
- if ((! (defined $file_full_path)) and /^Working file: (.*)/)
- {
- $file_full_path = $1;
- if (@Ignore_Files)
- {
- my $base;
- ($base, undef, undef) = fileparse ($file_full_path);
- # Ouch, I wish trailing operators in regexps could be
- # evaluated on the fly!
- if ($Case_Insensitive) {
- if (grep ($file_full_path =~ m|$_|i, @Ignore_Files)) {
- undef $file_full_path;
- }
- }
- elsif (grep ($file_full_path =~ m|$_|, @Ignore_Files)) {
- undef $file_full_path;
- }
- }
- next;
- }
-
- # Just spin wheels if no file defined yet.
- next if (! $file_full_path);
-
- # Collect tag names in case we're asked to print them in the output.
- if (/^symbolic names:$/) {
- $collecting_symbolic_names = 1;
- next; # There's no more info on this line, so skip to next
- }
- if ($collecting_symbolic_names)
- {
- # All tag names are listed with whitespace in front in cvs log
- # output; so if see non-whitespace, then we're done collecting.
- if (/^\S/) {
- $collecting_symbolic_names = 0;
- }
- else # we're looking at a tag name, so parse & store it
- {
- # According to the Cederqvist manual, in node "Tags", tag
- # names must start with an uppercase or lowercase letter and
- # can contain uppercase and lowercase letters, digits, `-',
- # and `_'. However, it's not our place to enforce that, so
- # we'll allow anything CVS hands us to be a tag:
- /^\s+([^:]+): ([\d.]+)$/;
- my $tag_name = $1;
- my $tag_rev = $2;
-
- # A branch number either has an odd number of digit sections
- # (and hence an even number of dots), or has ".0." as the
- # second-to-last digit section. Test for these conditions.
- my $real_branch_rev = "";
- if (($tag_rev =~ /^(\d+\.\d+\.)+\d+$/) # Even number of dots...
- and (! ($tag_rev =~ /^(1\.)+1$/))) # ...but not "1.[1.]1"
- {
- $real_branch_rev = $tag_rev;
- }
- elsif ($tag_rev =~ /(\d+\.(\d+\.)+)0.(\d+)/) # Has ".0."
- {
- $real_branch_rev = $1 . $3;
- }
- # If we got a branch, record its number.
- if ($real_branch_rev)
- {
- $branch_names{$real_branch_rev} = $tag_name;
- if (@Follow_Branches) {
- if (grep ($_ eq $tag_name, @Follow_Branches)) {
- $branch_numbers{$tag_name} = $real_branch_rev;
- }
- }
- }
- else {
- # Else it's just a regular (non-branch) tag.
- push (@{$symbolic_names{$tag_rev}}, $tag_name);
- }
- }
- }
- # End of code for collecting tag names.
-
- # If have file name, but not revision, and see revision, then grab
- # it. (We collect unconditionally, even though we may or may not
- # ever use it.)
- if ((! (defined $revision)) and (/^revision (\d+\.[\d.]+)/))
- {
- $revision = $1;
-
- if (@Follow_Branches)
- {
- foreach my $branch (@Follow_Branches)
- {
- # Special case for following trunk revisions
- if (($branch =~ /^trunk$/i) and ($revision =~ /^[0-9]+\.[0-9]+$/))
- {
- goto dengo;
- }
-
- my $branch_number = $branch_numbers{$branch};
- if ($branch_number)
- {
- # Are we on one of the follow branches or an ancestor of
- # same?
- #
- # If this revision is a prefix of the branch number, or
- # possibly is less in the minormost number, OR if this
- # branch number is a prefix of the revision, then yes.
- # Otherwise, no.
- #
- # So below, we determine if any of those conditions are
- # met.
-
- # Trivial case: is this revision on the branch?
- # (Compare this way to avoid regexps that screw up Emacs
- # indentation, argh.)
- if ((substr ($revision, 0, ((length ($branch_number)) + 1)))
- eq ($branch_number . "."))
- {
- goto dengo;
- }
- # Non-trivial case: check if rev is ancestral to branch
- elsif ((length ($branch_number)) > (length ($revision)))
- {
- $revision =~ /^((?:\d+\.)+)(\d+)$/;
- my $r_left = $1; # still has the trailing "."
- my $r_end = $2;
-
- $branch_number =~ /^((?:\d+\.)+)(\d+)\.\d+$/;
- my $b_left = $1; # still has trailing "."
- my $b_mid = $2; # has no trailing "."
-
- if (($r_left eq $b_left)
- && ($r_end <= $b_mid))
- {
- goto dengo;
- }
- }
- }
- }
- }
- else # (! @Follow_Branches)
- {
- next;
- }
-
- # Else we are following branches, but this revision isn't on the
- # path. So skip it.
- undef $revision;
- dengo:
- next;
- }
-
- # If we don't have a revision right now, we couldn't possibly
- # be looking at anything useful.
- if (! (defined ($revision))) {
- $detected_file_separator = /^$file_separator$/o;
- if ($detected_file_separator) {
- # No revisions for this file; can happen, e.g. "cvs log -d DATE"
- goto CLEAR;
- }
- else {
- next;
- }
- }
-
- # If have file name but not date and author, and see date or
- # author, then grab them:
- unless (defined $time)
- {
- if (/^date: .*/)
- {
- ($time, $author) = &parse_date_and_author ($_);
- if (defined ($usermap{$author}) and $usermap{$author}) {
- $author = $usermap{$author};
- }
- }
- else {
- $detected_file_separator = /^$file_separator$/o;
- if ($detected_file_separator) {
- # No revisions for this file; can happen, e.g. "cvs log -d DATE"
- goto CLEAR;
- }
- }
- # If the date/time/author hasn't been found yet, we couldn't
- # possibly care about anything we see. So skip:
- next;
- }
-
- # A "branches: ..." line here indicates that one or more branches
- # are rooted at this revision. If we're showing branches, then we
- # want to show that fact as well, so we collect all the branches
- # that this is the latest ancestor of and store them in
- # @branch_roots. Just for reference, the format of the line we're
- # seeing at this point is:
- #
- # branches: 1.5.2; 1.5.4; ...;
- #
- # Okay, here goes:
-
- if (/^branches:\s+(.*);$/)
- {
- if ($Show_Branches)
- {
- my $lst = $1;
- $lst =~ s/(1\.)+1;|(1\.)+1$//; # ignore the trivial branch 1.1.1
- if ($lst) {
- @branch_roots = split (/;\s+/, $lst);
- }
- else {
- undef @branch_roots;
- }
- next;
- }
- else
- {
- # Ugh. This really bothers me. Suppose we see a log entry
- # like this:
- #
- # ----------------------------
- # revision 1.1
- # date: 1999/10/17 03:07:38; author: jrandom; state: Exp;
- # branches: 1.1.2;
- # Intended first line of log message begins here.
- # ----------------------------
- #
- # The question is, how we can tell the difference between that
- # log message and a *two*-line log message whose first line is
- #
- # "branches: 1.1.2;"
- #
- # See the problem? The output of "cvs log" is inherently
- # ambiguous.
- #
- # For now, we punt: we liberally assume that people don't
- # write log messages like that, and just toss a "branches:"
- # line if we see it but are not showing branches. I hope no
- # one ever loses real log data because of this.
- next;
- }
- }
-
- # If have file name, time, and author, then we're just grabbing
- # log message texts:
- $detected_file_separator = /^$file_separator$/o;
- if ($detected_file_separator && ! (defined $revision)) {
- # No revisions for this file; can happen, e.g. "cvs log -d DATE"
- goto CLEAR;
- }
- unless ($detected_file_separator || /^$logmsg_separator$/o)
- {
- $msg_txt .= $_; # Normally, just accumulate the message...
- next;
- }
- # ... until a msg separator is encountered:
- # Ensure the message contains something:
- if ((! $msg_txt)
- || ($msg_txt =~ /^\s*\.\s*$|^\s*$/)
- || ($msg_txt =~ /\*\*\* empty log message \*\*\*/))
- {
- if ($Prune_Empty_Msgs) {
- goto CLEAR;
- }
- # else
- $msg_txt = "[no log message]\n";
- }
-
- ### Store it all in the Grand Poobah:
- {
- my $dir_key; # key into %grand_poobah
- my %qunk; # complicated little jobbie, see below
-
- # Each revision of a file has a little data structure (a `qunk')
- # associated with it. That data structure holds not only the
- # file's name, but any additional information about the file
- # that might be needed in the output, such as the revision
- # number, tags, branches, etc. The reason to have these things
- # arranged in a data structure, instead of just appending them
- # textually to the file's name, is that we may want to do a
- # little rearranging later as we write the output. For example,
- # all the files on a given tag/branch will go together, followed
- # by the tag in parentheses (so trunk or otherwise non-tagged
- # files would go at the end of the file list for a given log
- # message). This rearrangement is a lot easier to do if we
- # don't have to reparse the text.
- #
- # A qunk looks like this:
- #
- # {
- # filename => "hello.c",
- # revision => "1.4.3.2",
- # time => a timegm() return value (moment of commit)
- # tags => [ "tag1", "tag2", ... ],
- # branch => "branchname" # There should be only one, right?
- # branchroots => [ "branchtag1", "branchtag2", ... ]
- # }
-
- if ($Distributed) {
- # Just the basename, don't include the path.
- ($qunk{'filename'}, $dir_key, undef) = fileparse ($file_full_path);
- }
- else {
- $dir_key = "./";
- $qunk{'filename'} = $file_full_path;
- }
-
- # This may someday be used in a more sophisticated calculation
- # of what other files are involved in this commit. For now, we
- # don't use it, because the common-commit-detection algorithm is
- # hypothesized to be "good enough" as it stands.
- $qunk{'time'} = $time;
-
- # We might be including revision numbers and/or tags and/or
- # branch names in the output. Most of the code from here to
- # loop-end deals with organizing these in qunk.
-
- $qunk{'revision'} = $revision;
-
- # Grab the branch, even though we may or may not need it:
- $qunk{'revision'} =~ /((?:\d+\.)+)\d+/;
- my $branch_prefix = $1;
- $branch_prefix =~ s/\.$//; # strip off final dot
- if ($branch_names{$branch_prefix}) {
- $qunk{'branch'} = $branch_names{$branch_prefix};
- }
-
- # If there's anything in the @branch_roots array, then this
- # revision is the root of at least one branch. We'll display
- # them as branch names instead of revision numbers, the
- # substitution for which is done directly in the array:
- if (@branch_roots) {
- my @roots = map { $branch_names{$_} } @branch_roots;
- $qunk{'branchroots'} = \@roots;
- }
-
- # Save tags too.
- if (defined ($symbolic_names{$revision})) {
- $qunk{'tags'} = $symbolic_names{$revision};
- delete $symbolic_names{$revision};
- }
-
- # Add this file to the list
- # (We use many spoonfuls of autovivication magic. Hashes and arrays
- # will spring into existence if they aren't there already.)
-
- &debug ("(pushing log msg for ${dir_key}$qunk{'filename'})\n");
-
- # Store with the files in this commit. Later we'll loop through
- # again, making sure that revisions with the same log message
- # and nearby commit times are grouped together as one commit.
- push (@{$grand_poobah{$dir_key}{$author}{$time}{$msg_txt}}, \%qunk);
- }
-
- CLEAR:
- # Make way for the next message
- undef $msg_txt;
- undef $time;
- undef $revision;
- undef $author;
- undef @branch_roots;
-
- # Maybe even make way for the next file:
- if ($detected_file_separator) {
- undef $file_full_path;
- undef %branch_names;
- undef %branch_numbers;
- undef %symbolic_names;
- }
- }
-
- close (LOG_SOURCE);
-
- ### Process each ChangeLog
-
- while (my ($dir,$authorhash) = each %grand_poobah)
- {
- &debug ("DOING DIR: $dir\n");
-
- # Here we twist our hash around, from being
- # author => time => message => filelist
- # in %$authorhash to
- # time => author => message => filelist
- # in %changelog.
- #
- # This is also where we merge entries. The algorithm proceeds
- # through the timeline of the changelog with a sliding window of
- # $Max_Checkin_Duration seconds; within that window, entries that
- # have the same log message are merged.
- #
- # (To save space, we zap %$authorhash after we've copied
- # everything out of it.)
-
- my %changelog;
- while (my ($author,$timehash) = each %$authorhash)
- {
- my $lasttime;
- my %stamptime;
- foreach my $time (sort {$main::a <=> $main::b} (keys %$timehash))
- {
- my $msghash = $timehash->{$time};
- while (my ($msg,$qunklist) = each %$msghash)
- {
- my $stamptime = $stamptime{$msg};
- if ((defined $stamptime)
- and (($time - $stamptime) < $Max_Checkin_Duration)
- and (defined $changelog{$stamptime}{$author}{$msg}))
- {
- push(@{$changelog{$stamptime}{$author}{$msg}}, @$qunklist);
- }
- else {
- $changelog{$time}{$author}{$msg} = $qunklist;
- $stamptime{$msg} = $time;
- }
- }
- }
- }
- undef (%$authorhash);
-
- ### Now we can write out the ChangeLog!
-
- my ($logfile_here, $logfile_bak, $tmpfile);
-
- if (! $Output_To_Stdout) {
- $logfile_here = $dir . $Log_File_Name;
- $logfile_here =~ s/^\.\/\//\//; # fix any leading ".//" problem
- $tmpfile = "${logfile_here}.cvs2cl$$.tmp";
- $logfile_bak = "${logfile_here}.bak";
-
- open (LOG_OUT, ">$tmpfile") or die "Unable to open \"$tmpfile\"";
- }
- else {
- open (LOG_OUT, ">-") or die "Unable to open stdout for writing";
- }
-
- print LOG_OUT $ChangeLog_Header;
-
- if ($XML_Output) {
- print LOG_OUT "<?xml version=\"1.0\"?>\n\n"
- . "<changelog xmlns=\"http://www.red-bean.com/xmlns/cvs2cl/\">\n\n";
- }
-
- foreach my $time (sort {$main::b <=> $main::a} (keys %changelog))
- {
- my $authorhash = $changelog{$time};
- while (my ($author,$mesghash) = each %$authorhash)
- {
- # If XML, escape in outer loop to avoid compound quoting:
- if ($XML_Output) {
- $author = &xml_escape ($author);
- }
-
- while (my ($msg,$qunklist) = each %$mesghash)
- {
- my $files = &pretty_file_list ($qunklist);
- my $header_line; # date and author
- my $body; # see below
- my $wholething; # $header_line + $body
-
- # Set up the date/author line.
- # kff todo: do some more XML munging here, on the header
- # part of the entry:
- my ($ignore,$min,$hour,$mday,$mon,$year,$wday)
- = $UTC_Times ? gmtime($time) : localtime($time);
-
- # XML output includes everything else, we might as well make
- # it always include Day Of Week too, for consistency.
- if ($Show_Day_Of_Week or $XML_Output) {
- $wday = ("Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday")[$wday];
- $wday = ($XML_Output) ? "<weekday>${wday}</weekday>\n" : " $wday";
- }
- else {
- $wday = "";
- }
-
- if ($XML_Output) {
- $header_line =
- sprintf ("<date>%4u-%02u-%02u</date>\n"
- . "${wday}"
- . "<time>%02u:%02u</time>\n"
- . "<author>%s</author>\n",
- $year+1900, $mon+1, $mday, $hour, $min, $author);
- }
- else {
- $header_line =
- sprintf ("%4u-%02u-%02u${wday} %02u:%02u %s\n\n",
- $year+1900, $mon+1, $mday, $hour, $min, $author);
- }
-
- # Reshape the body according to user preferences.
- if ($XML_Output)
- {
- $msg = &preprocess_msg_text ($msg);
- $body = $files . $msg;
- }
- elsif ($No_Wrap)
- {
- $msg = &preprocess_msg_text ($msg);
- $files = wrap ("\t", " ", "$files");
- $msg =~ s/\n(.*)/\n\t$1/g;
- unless ($After_Header eq " ") {
- $msg =~ s/^(.*)/\t$1/g;
- }
- $body = $files . $After_Header . $msg;
- }
- else # do wrapping, either FSF-style or regular
- {
- if ($FSF_Style)
- {
- $files = wrap ("\t", " ", "$files");
-
- my $files_last_line_len = 0;
- if ($After_Header eq " ")
- {
- $files_last_line_len = &last_line_len ($files);
- $files_last_line_len += 1; # for $After_Header
- }
-
- $msg = &wrap_log_entry
- ($msg, "\t", 69 - $files_last_line_len, 69);
- $body = $files . $After_Header . $msg;
- }
- else # not FSF-style
- {
- $msg = &preprocess_msg_text ($msg);
- $body = $files . $After_Header . $msg;
- $body = wrap ("\t", " ", "$body");
- }
- }
-
- $wholething = $header_line . $body;
-
- if ($XML_Output) {
- $wholething = "<entry>\n${wholething}</entry>\n";
- }
-
- # One last check: make sure it passes the regexp test, if the
- # user asked for that. We have to do it here, so that the
- # test can match against information in the header as well
- # as in the text of the log message.
-
- # How annoying to duplicate so much code just because I
- # can't figure out a way to evaluate scalars on the trailing
- # operator portion of a regular expression. Grrr.
- if ($Case_Insensitive) {
- unless ($Regexp_Gate && ($wholething !~ /$Regexp_Gate/oi)) {
- print LOG_OUT "${wholething}\n";
- }
- }
- else {
- unless ($Regexp_Gate && ($wholething !~ /$Regexp_Gate/o)) {
- print LOG_OUT "${wholething}\n";
- }
- }
- }
- }
- }
-
- if ($XML_Output) {
- print LOG_OUT "</changelog>\n";
- }
-
- close (LOG_OUT);
-
- if (! $Output_To_Stdout)
- {
- # If accumulating, append old data to new before renaming. But
- # don't append the most recent entry, since it's already in the
- # new log due to CVS's idiosyncratic interpretation of "log -d".
- if ($Cumulative && -f $logfile_here)
- {
- open (NEW_LOG, ">>$tmpfile")
- or die "trouble appending to $tmpfile ($!)";
-
- open (OLD_LOG, "<$logfile_here")
- or die "trouble reading from $logfile_here ($!)";
-
- my $started_first_entry = 0;
- my $passed_first_entry = 0;
- while (<OLD_LOG>)
- {
- if (! $passed_first_entry)
- {
- if ((! $started_first_entry)
- && /^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) {
- $started_first_entry = 1;
- }
- elsif (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) {
- $passed_first_entry = 1;
- print NEW_LOG $_;
- }
- }
- else {
- print NEW_LOG $_;
- }
- }
-
- close (NEW_LOG);
- close (OLD_LOG);
- }
-
- if (-f $logfile_here) {
- rename ($logfile_here, $logfile_bak);
- }
- rename ($tmpfile, $logfile_here);
- }
- }
-}
-
-
-sub parse_date_and_author ()
-{
- # Parses the date/time and author out of a line like:
- #
- # date: 1999/02/19 23:29:05; author: apharris; state: Exp;
-
- my $line = shift;
-
- my ($year, $mon, $mday, $hours, $min, $secs, $author) = $line =~
- m#(\d+)/(\d+)/(\d+)\s+(\d+):(\d+):(\d+);\s+author:\s+([^;]+);#
- or die "Couldn't parse date ``$line''";
- die "Bad date or Y2K issues" unless ($year > 1969 and $year < 2258);
- # Kinda arbitrary, but useful as a sanity check
- my $time = timegm($secs,$min,$hours,$mday,$mon-1,$year-1900);
-
- return ($time, $author);
-}
-
-
-# Here we take a bunch of qunks and convert them into printed
-# summary that will include all the information the user asked for.
-sub pretty_file_list ()
-{
- if ($Hide_Filenames and (! $XML_Output)) {
- return "";
- }
-
- my $qunksref = shift;
- my @qunkrefs = @$qunksref;
- my @filenames;
- my $beauty = ""; # The accumulating header string for this entry.
- my %non_unanimous_tags; # Tags found in a proper subset of qunks
- my %unanimous_tags; # Tags found in all qunks
- my %all_branches; # Branches found in any qunk
- my $common_dir = undef; # Dir prefix common to all files ("" if none)
- my $fbegun = 0; # Did we begin printing filenames yet?
-
- # First, loop over the qunks gathering all the tag/branch names.
- # We'll put them all in non_unanimous_tags, and take out the
- # unanimous ones later.
- foreach my $qunkref (@qunkrefs)
- {
- # Keep track of whether all the files in this commit were in the
- # same directory, and memorize it if so. We can make the output a
- # little more compact by mentioning the directory only once.
- if ((scalar (@qunkrefs)) > 1)
- {
- if (! (defined ($common_dir)))
- {
- my ($base, $dir);
- ($base, $dir, undef) = fileparse ($$qunkref{'filename'});
-
- if ((! (defined ($dir))) # this first case is sheer paranoia
- or ($dir eq "")
- or ($dir eq "./")
- or ($dir eq ".\\"))
- {
- $common_dir = "";
- }
- else
- {
- $common_dir = $dir;
- }
- }
- elsif ($common_dir ne "")
- {
- # Already have a common dir prefix, so how much of it can we preserve?
- $common_dir = &common_path_prefix ($$qunkref{'filename'}, $common_dir);
- }
- }
- else # only one file in this entry anyway, so common dir not an issue
- {
- $common_dir = "";
- }
-
- if (defined ($$qunkref{'branch'})) {
- $all_branches{$$qunkref{'branch'}} = 1;
- }
- if (defined ($$qunkref{'tags'})) {
- foreach my $tag (@{$$qunkref{'tags'}}) {
- $non_unanimous_tags{$tag} = 1;
- }
- }
- }
-
- # Any tag held by all qunks will be printed specially... but only if
- # there are multiple qunks in the first place!
- if ((scalar (@qunkrefs)) > 1) {
- foreach my $tag (keys (%non_unanimous_tags)) {
- my $everyone_has_this_tag = 1;
- foreach my $qunkref (@qunkrefs) {
- if ((! (defined ($$qunkref{'tags'})))
- or (! (grep ($_ eq $tag, @{$$qunkref{'tags'}})))) {
- $everyone_has_this_tag = 0;
- }
- }
- if ($everyone_has_this_tag) {
- $unanimous_tags{$tag} = 1;
- delete $non_unanimous_tags{$tag};
- }
- }
- }
-
- if ($XML_Output)
- {
- # If outputting XML, then our task is pretty simple, because we
- # don't have to detect common dir, common tags, branch prefixing,
- # etc. We just output exactly what we have, and don't worry about
- # redundancy or readability.
-
- foreach my $qunkref (@qunkrefs)
- {
- my $filename = $$qunkref{'filename'};
- my $revision = $$qunkref{'revision'};
- my $tags = $$qunkref{'tags'};
- my $branch = $$qunkref{'branch'};
- my $branchroots = $$qunkref{'branchroots'};
-
- $filename = &xml_escape ($filename); # probably paranoia
- $revision = &xml_escape ($revision); # definitely paranoia
-
- $beauty .= "<file>\n";
- $beauty .= "<name>${filename}</name>\n";
- $beauty .= "<revision>${revision}</revision>\n";
- if ($branch) {
- $branch = &xml_escape ($branch); # more paranoia
- $beauty .= "<branch>${branch}</branch>\n";
- }
- foreach my $tag (@$tags) {
- $tag = &xml_escape ($tag); # by now you're used to the paranoia
- $beauty .= "<tag>${tag}</tag>\n";
- }
- foreach my $root (@$branchroots) {
- $root = &xml_escape ($root); # which is good, because it will continue
- $beauty .= "<branchroot>${root}</branchroot>\n";
- }
- $beauty .= "</file>\n";
- }
-
- # Theoretically, we could go home now. But as long as we're here,
- # let's print out the common_dir and utags, as a convenience to
- # the receiver (after all, earlier code calculated that stuff
- # anyway, so we might as well take advantage of it).
-
- if ((scalar (keys (%unanimous_tags))) > 1) {
- foreach my $utag ((keys (%unanimous_tags))) {
- $utag = &xml_escape ($utag); # the usual paranoia
- $beauty .= "<utag>${utag}</utag>\n";
- }
- }
- if ($common_dir) {
- $common_dir = &xml_escape ($common_dir);
- $beauty .= "<commondir>${common_dir}</commondir>\n";
- }
-
- # That's enough for XML, time to go home:
- return $beauty;
- }
-
- # Else not XML output, so complexly compactify for chordate
- # consumption. At this point we have enough global information
- # about all the qunks to organize them non-redundantly for output.
-
- if ($common_dir) {
- # Note that $common_dir still has its trailing slash
- $beauty .= "$common_dir: ";
- }
-
- if ($Show_Branches)
- {
- # For trailing revision numbers.
- my @brevisions;
-
- foreach my $branch (keys (%all_branches))
- {
- foreach my $qunkref (@qunkrefs)
- {
- if ((defined ($$qunkref{'branch'}))
- and ($$qunkref{'branch'} eq $branch))
- {
- if ($fbegun) {
- # kff todo: comma-delimited in XML too? Sure.
- $beauty .= ", ";
- }
- else {
- $fbegun = 1;
- }
- my $fname = substr ($$qunkref{'filename'}, length ($common_dir));
- $beauty .= $fname;
- $$qunkref{'printed'} = 1; # Just setting a mark bit, basically
-
- if ($Show_Tags && (defined @{$$qunkref{'tags'}})) {
- my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}});
- if (@tags) {
- $beauty .= " (tags: ";
- $beauty .= join (', ', @tags);
- $beauty .= ")";
- }
- }
-
- if ($Show_Revisions) {
- # Collect the revision numbers' last components, but don't
- # print them -- they'll get printed with the branch name
- # later.
- $$qunkref{'revision'} =~ /.+\.([\d]+)$/;
- push (@brevisions, $1);
-
- # todo: we're still collecting branch roots, but we're not
- # showing them anywhere. If we do show them, it would be
- # nifty to just call them revision "0" on a the branch.
- # Yeah, that's the ticket.
- }
- }
- }
- $beauty .= " ($branch";
- if (@brevisions) {
- if ((scalar (@brevisions)) > 1) {
- $beauty .= ".[";
- $beauty .= (join (',', @brevisions));
- $beauty .= "]";
- }
- else {
- $beauty .= ".$brevisions[0]";
- }
- }
- $beauty .= ")";
- }
- }
-
- # Okay; any qunks that were done according to branch are taken care
- # of, and marked as printed. Now print everyone else.
-
- foreach my $qunkref (@qunkrefs)
- {
- next if (defined ($$qunkref{'printed'})); # skip if already printed
-
- if ($fbegun) {
- $beauty .= ", ";
- }
- else {
- $fbegun = 1;
- }
- $beauty .= substr ($$qunkref{'filename'}, length ($common_dir));
- # todo: Shlomo's change was this:
- # $beauty .= substr ($$qunkref{'filename'},
- # (($common_dir eq "./") ? "" : length ($common_dir)));
- $$qunkref{'printed'} = 1; # Set a mark bit.
-
- if ($Show_Revisions || $Show_Tags)
- {
- my $started_addendum = 0;
-
- if ($Show_Revisions) {
- $started_addendum = 1;
- $beauty .= " (";
- $beauty .= "$$qunkref{'revision'}";
- }
- if ($Show_Tags && (defined $$qunkref{'tags'})) {
- my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}});
- if ((scalar (@tags)) > 0) {
- if ($started_addendum) {
- $beauty .= ", ";
- }
- else {
- $beauty .= " (tags: ";
- }
- $beauty .= join (', ', @tags);
- $started_addendum = 1;
- }
- }
- if ($started_addendum) {
- $beauty .= ")";
- }
- }
- }
-
- # Unanimous tags always come last.
- if ($Show_Tags && %unanimous_tags)
- {
- $beauty .= " (utags: ";
- $beauty .= join (', ', keys (%unanimous_tags));
- $beauty .= ")";
- }
-
- # todo: still have to take care of branch_roots?
-
- $beauty = "* $beauty:";
-
- return $beauty;
-}
-
-
-sub common_path_prefix ()
-{
- my $path1 = shift;
- my $path2 = shift;
-
- my ($dir1, $dir2);
- (undef, $dir1, undef) = fileparse ($path1);
- (undef, $dir2, undef) = fileparse ($path2);
-
- # Transmogrify Windows filenames to look like Unix.
- # (It is far more likely that someone is running cvs2cl.pl under
- # Windows than that they would genuinely have backslashes in their
- # filenames.)
- $dir1 =~ tr#\\#/#;
- $dir2 =~ tr#\\#/#;
-
- my $accum1 = "";
- my $accum2 = "";
- my $last_common_prefix = "";
-
- while ($accum1 eq $accum2)
- {
- $last_common_prefix = $accum1;
- last if ($accum1 eq $dir1);
- my ($tmp1) = split (/\//, (substr ($dir1, length ($accum1))));
- my ($tmp2) = split (/\//, (substr ($dir2, length ($accum2))));
- $accum1 .= "$tmp1/" if ((defined ($tmp1)) and $tmp1);
- $accum2 .= "$tmp2/" if ((defined ($tmp2)) and $tmp2);
- }
-
- return $last_common_prefix;
-}
-
-
-sub preprocess_msg_text ()
-{
- my $text = shift;
-
- # Strip out carriage returns (as they probably result from DOSsy editors).
- $text =~ s/\r\n/\n/g;
-
- # If it *looks* like two newlines, make it *be* two newlines:
- $text =~ s/\n\s*\n/\n\n/g;
-
- if ($XML_Output)
- {
- $text = &xml_escape ($text);
- $text = "<msg>${text}</msg>\n";
- }
- elsif (! $No_Wrap)
- {
- # Strip off lone newlines, but only for lines that don't begin with
- # whitespace or a mail-quoting character, since we want to preserve
- # that kind of formatting. Also don't strip newlines that follow a
- # period; we handle those specially next. And don't strip
- # newlines that precede an open paren.
- 1 while ($text =~ s/(^|\n)([^>\s].*[^.\n])\n([^>\n])/$1$2 $3/g);
-
- # If a newline follows a period, make sure that when we bring up the
- # bottom sentence, it begins with two spaces.
- 1 while ($text =~ s/(^|\n)([^>\s].*)\n([^>\n])/$1$2 $3/g);
- }
-
- return $text;
-}
-
-
-sub last_line_len ()
-{
- my $files_list = shift;
- my @lines = split (/\n/, $files_list);
- my $last_line = pop (@lines);
- return length ($last_line);
-}
-
-
-# A custom wrap function, sensitive to some common constructs used in
-# log entries.
-sub wrap_log_entry ()
-{
- my $text = shift; # The text to wrap.
- my $left_pad_str = shift; # String to pad with on the left.
-
- # These do NOT take left_pad_str into account:
- my $length_remaining = shift; # Amount left on current line.
- my $max_line_length = shift; # Amount left for a blank line.
-
- my $wrapped_text = ""; # The accumulating wrapped entry.
- my $user_indent = ""; # Inherited user_indent from prev line.
-
- my $first_time = 1; # First iteration of the loop?
- my $suppress_line_start_match = 0; # Set to disable line start checks.
-
- my @lines = split (/\n/, $text);
- while (@lines) # Don't use `foreach' here, it won't work.
- {
- my $this_line = shift (@lines);
- chomp $this_line;
-
- if ($this_line =~ /^(\s+)/) {
- $user_indent = $1;
- }
- else {
- $user_indent = "";
- }
-
- # If it matches any of the line-start regexps, print a newline now...
- if ($suppress_line_start_match)
- {
- $suppress_line_start_match = 0;
- }
- elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/)
- || ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/)
- || ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/)
- || ($this_line =~ /^(\s+)(\S+)/)
- || ($this_line =~ /^(\s*)- +/)
- || ($this_line =~ /^()\s*$/)
- || ($this_line =~ /^(\s*)\*\) +/)
- || ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
- {
- # Make a line break immediately, unless header separator is set
- # and this line is the first line in the entry, in which case
- # we're getting the blank line for free already and shouldn't
- # add an extra one.
- unless (($After_Header ne " ") and ($first_time))
- {
- if ($this_line =~ /^()\s*$/) {
- $suppress_line_start_match = 1;
- $wrapped_text .= "\n${left_pad_str}";
- }
-
- $wrapped_text .= "\n${left_pad_str}";
- }
-
- $length_remaining = $max_line_length - (length ($user_indent));
- }
-
- # Now that any user_indent has been preserved, strip off leading
- # whitespace, so up-folding has no ugly side-effects.
- $this_line =~ s/^\s*//;
-
- # Accumulate the line, and adjust parameters for next line.
- my $this_len = length ($this_line);
- if ($this_len == 0)
- {
- # Blank lines should cancel any user_indent level.
- $user_indent = "";
- $length_remaining = $max_line_length;
- }
- elsif ($this_len >= $length_remaining) # Line too long, try breaking it.
- {
- # Walk backwards from the end. At first acceptable spot, break
- # a new line.
- my $idx = $length_remaining - 1;
- if ($idx < 0) { $idx = 0 };
- while ($idx > 0)
- {
- if (substr ($this_line, $idx, 1) =~ /\s/)
- {
- my $line_now = substr ($this_line, 0, $idx);
- my $next_line = substr ($this_line, $idx);
- $this_line = $line_now;
-
- # Clean whitespace off the end.
- chomp $this_line;
-
- # The current line is ready to be printed.
- $this_line .= "\n${left_pad_str}";
-
- # Make sure the next line is allowed full room.
- $length_remaining = $max_line_length - (length ($user_indent));
-
- # Strip next_line, but then preserve any user_indent.
- $next_line =~ s/^\s*//;
-
- # Sneak a peek at the user_indent of the upcoming line, so
- # $next_line (which will now precede it) can inherit that
- # indent level. Otherwise, use whatever user_indent level
- # we currently have, which might be none.
- my $next_next_line = shift (@lines);
- if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) {
- $next_line = $1 . $next_line if (defined ($1));
- # $length_remaining = $max_line_length - (length ($1));
- $next_next_line =~ s/^\s*//;
- }
- else {
- $next_line = $user_indent . $next_line;
- }
- if (defined ($next_next_line)) {
- unshift (@lines, $next_next_line);
- }
- unshift (@lines, $next_line);
-
- # Our new next line might, coincidentally, begin with one of
- # the line-start regexps, so we temporarily turn off
- # sensitivity to that until we're past the line.
- $suppress_line_start_match = 1;
-
- last;
- }
- else
- {
- $idx--;
- }
- }
-
- if ($idx == 0)
- {
- # We bottomed out because the line is longer than the
- # available space. But that could be because the space is
- # small, or because the line is longer than even the maximum
- # possible space. Handle both cases below.
-
- if ($length_remaining == ($max_line_length - (length ($user_indent))))
- {
- # The line is simply too long -- there is no hope of ever
- # breaking it nicely, so just insert it verbatim, with
- # appropriate padding.
- $this_line = "\n${left_pad_str}${this_line}";
- }
- else
- {
- # Can't break it here, but may be able to on the next round...
- unshift (@lines, $this_line);
- $length_remaining = $max_line_length - (length ($user_indent));
- $this_line = "\n${left_pad_str}";
- }
- }
- }
- else # $this_len < $length_remaining, so tack on what we can.
- {
- # Leave a note for the next iteration.
- $length_remaining = $length_remaining - $this_len;
-
- if ($this_line =~ /\.$/)
- {
- $this_line .= " ";
- $length_remaining -= 2;
- }
- else # not a sentence end
- {
- $this_line .= " ";
- $length_remaining -= 1;
- }
- }
-
- # Unconditionally indicate that loop has run at least once.
- $first_time = 0;
-
- $wrapped_text .= "${user_indent}${this_line}";
- }
-
- # One last bit of padding.
- $wrapped_text .= "\n";
-
- return $wrapped_text;
-}
-
-
-sub xml_escape ()
-{
- my $txt = shift;
- $txt =~ s/&/&amp;/g;
- $txt =~ s/</&lt;/g;
- $txt =~ s/>/&gt;/g;
- return $txt;
-}
-
-
-sub maybe_read_user_map_file ()
-{
- my %expansions;
-
- if ($User_Map_File)
- {
- open (MAPFILE, "<$User_Map_File")
- or die ("Unable to open $User_Map_File ($!)");
-
- while (<MAPFILE>)
- {
- next if /^\s*#/; # Skip comment lines.
- next if not /:/; # Skip lines without colons.
-
- # It is now safe to split on ':'.
- my ($username, $expansion) = split ':';
- chomp $expansion;
- $expansion =~ s/^'(.*)'$/$1/;
- $expansion =~ s/^"(.*)"$/$1/;
-
- # If it looks like the expansion has a real name already, then
- # we toss the username we got from CVS log. Otherwise, keep
- # it to use in combination with the email address.
-
- if ($expansion =~ /^\s*<{0,1}\S+@.*/) {
- # Also, add angle brackets if none present
- if (! ($expansion =~ /<\S+@\S+>/)) {
- $expansions{$username} = "$username <$expansion>";
- }
- else {
- $expansions{$username} = "$username $expansion";
- }
- }
- else {
- $expansions{$username} = $expansion;
- }
- }
-
- close (MAPFILE);
- }
-
- return %expansions;
-}
-
-
-sub parse_options ()
-{
- # Check this internally before setting the global variable.
- my $output_file;
-
- # If this gets set, we encountered unknown options and will exit at
- # the end of this subroutine.
- my $exit_with_admonishment = 0;
-
- while (my $arg = shift (@ARGV))
- {
- if ($arg =~ /^-h$|^-help$|^--help$|^--usage$|^-?$/) {
- $Print_Usage = 1;
- }
- elsif ($arg =~ /^--debug$/) { # unadvertised option, heh
- $Debug = 1;
- }
- elsif ($arg =~ /^--version$/) {
- $Print_Version = 1;
- }
- elsif ($arg =~ /^-g$|^--global-opts$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- # Don't assume CVS is called "cvs" on the user's system:
- $Log_Source_Command =~ s/(^\S*)/$1 $narg/;
- }
- elsif ($arg =~ /^-l$|^--log-opts$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $Log_Source_Command .= " $narg";
- }
- elsif ($arg =~ /^-f$|^--file$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $output_file = $narg;
- }
- elsif ($arg =~ /^--accum$/) {
- $Cumulative = 1;
- }
- elsif ($arg =~ /^--fsf$/) {
- $FSF_Style = 1;
- }
- elsif ($arg =~ /^-U$|^--usermap$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $User_Map_File = $narg;
- }
- elsif ($arg =~ /^-W$|^--window$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $Max_Checkin_Duration = $narg;
- }
- elsif ($arg =~ /^-I$|^--ignore$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- push (@Ignore_Files, $narg);
- }
- elsif ($arg =~ /^-C$|^--case-insensitive$/) {
- $Case_Insensitive = 1;
- }
- elsif ($arg =~ /^-R$|^--regexp$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $Regexp_Gate = $narg;
- }
- elsif ($arg =~ /^--stdout$/) {
- $Output_To_Stdout = 1;
- }
- elsif ($arg =~ /^--version$/) {
- $Print_Version = 1;
- }
- elsif ($arg =~ /^-d$|^--distributed$/) {
- $Distributed = 1;
- }
- elsif ($arg =~ /^-P$|^--prune$/) {
- $Prune_Empty_Msgs = 1;
- }
- elsif ($arg =~ /^-S$|^--separate-header$/) {
- $After_Header = "\n\n";
- }
- elsif ($arg =~ /^--no-wrap$/) {
- $No_Wrap = 1;
- }
- elsif ($arg =~ /^--gmt$|^--utc$/) {
- $UTC_Times = 1;
- }
- elsif ($arg =~ /^-w$|^--day-of-week$/) {
- $Show_Day_Of_Week = 1;
- }
- elsif ($arg =~ /^-r$|^--revisions$/) {
- $Show_Revisions = 1;
- }
- elsif ($arg =~ /^-t$|^--tags$/) {
- $Show_Tags = 1;
- }
- elsif ($arg =~ /^-b$|^--branches$/) {
- $Show_Branches = 1;
- }
- elsif ($arg =~ /^-F$|^--follow$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- push (@Follow_Branches, $narg);
- }
- elsif ($arg =~ /^--stdin$/) {
- $Input_From_Stdin = 1;
- }
- elsif ($arg =~ /^--header$/) {
- my $narg = shift (@ARGV) || die "$arg needs argument.\n";
- $ChangeLog_Header = &slurp_file ($narg);
- if (! defined ($ChangeLog_Header)) {
- $ChangeLog_Header = "";
- }
- }
- elsif ($arg =~ /^--xml$/) {
- $XML_Output = 1;
- }
- elsif ($arg =~ /^--hide-filenames$/) {
- $Hide_Filenames = 1;
- $After_Header = "";
- }
- else {
- # Just add a filename as argument to the log command
- $Log_Source_Command .= " $arg";
- }
- }
-
- ## Check for contradictions...
-
- if ($Output_To_Stdout && $Distributed) {
- print STDERR "cannot pass both --stdout and --distributed\n";
- $exit_with_admonishment = 1;
- }
-
- if ($Output_To_Stdout && $output_file) {
- print STDERR "cannot pass both --stdout and --file\n";
- $exit_with_admonishment = 1;
- }
-
- if ($XML_Output && $Cumulative) {
- print STDERR "cannot pass both --xml and --accum\n";
- $exit_with_admonishment = 1;
- }
-
- # Or if any other error message has already been printed out, we
- # just leave now:
- if ($exit_with_admonishment) {
- &usage ();
- exit (1);
- }
- elsif ($Print_Usage) {
- &usage ();
- exit (0);
- }
- elsif ($Print_Version) {
- &version ();
- exit (0);
- }
-
- ## Else no problems, so proceed.
-
- if ($output_file) {
- $Log_File_Name = $output_file;
- }
-}
-
-
-sub slurp_file ()
-{
- my $filename = shift || die ("no filename passed to slurp_file()");
- my $retstr;
-
- open (SLURPEE, "<${filename}") or die ("unable to open $filename ($!)");
- my $saved_sep = $/;
- undef $/;
- $retstr = <SLURPEE>;
- $/ = $saved_sep;
- close (SLURPEE);
- return $retstr;
-}
-
-
-sub debug ()
-{
- if ($Debug) {
- my $msg = shift;
- print STDERR $msg;
- }
-}
-
-
-sub version ()
-{
- print "cvs2cl.pl version ${VERSION}; distributed under the GNU GPL.\n";
-}
-
-
-sub usage ()
-{
- &version ();
- print <<'END_OF_INFO';
-Generate GNU-style ChangeLogs in CVS working copies.
-
-Notes about the output format(s):
-
- The default output of cvs2cl.pl is designed to be compact, formally
- unambiguous, but still easy for humans to read. It is largely
- self-explanatory, I hope; the one abbreviation that might not be
- obvious is "utags". That stands for "universal tags" -- a
- universal tag is one held by all the files in a given change entry.
-
- If you need output that's easy for a program to parse, use the
- --xml option. Note that with XML output, just about all available
- information is included with each change entry, whether you asked
- for it or not, on the theory that your parser can ignore anything
- it's not looking for.
-
-Notes about the options and arguments (the actual options are listed
-last in this usage message):
-
- * The -I and -F options may appear multiple times.
-
- * To follow trunk revisions, use "-F trunk" ("-F TRUNK" also works).
- This is okay because no would ever, ever be crazy enough to name a
- branch "trunk", right? Right.
-
- * For the -U option, the UFILE should be formatted like
- CVSROOT/users. That is, each line of UFILE looks like this
- jrandom:jrandom@red-bean.com
- or maybe even like this
- jrandom:'Jesse Q. Random <jrandom@red-bean.com>'
- Don't forget to quote the portion after the colon if necessary.
-
- * Many people want to filter by date. To do so, invoke cvs2cl.pl
- like this:
- cvs2cl.pl -l "-d'DATESPEC'"
- where DATESPEC is any date specification valid for "cvs log -d".
- (Note that CVS 1.10.7 and below requires there be no space between
- -d and its argument).
-
-Options/Arguments:
-
- -h, -help, --help, or -? Show this usage and exit
- --version Show version and exit
- -r, --revisions Show revision numbers in output
- -b, --branches Show branch names in revisions when possible
- -t, --tags Show tags (symbolic names) in output
- --stdin Read from stdin, don't run cvs log
- --stdout Output to stdout not to ChangeLog
- -d, --distributed Put ChangeLogs in subdirs
- -f FILE, --file FILE Write to FILE instead of "ChangeLog"
- --fsf Use this if log data is in FSF ChangeLog style
- -W SECS, --window SECS Window of time within which log entries unify
- -U UFILE, --usermap UFILE Expand usernames to email addresses from UFILE
- -R REGEXP, --regexp REGEXP Include only entries that match REGEXP
- -I REGEXP, --ignore REGEXP Ignore files whose names match REGEXP
- -C, --case-insensitive Any regexp matching is done case-insensitively
- -F BRANCH, --follow BRANCH Show only revisions on or ancestral to BRANCH
- -S, --separate-header Blank line between each header and log message
- --no-wrap Don't auto-wrap log message (recommend -S also)
- --gmt, --utc Show times in GMT/UTC instead of local time
- --accum Add to an existing ChangeLog (incompat w/ --xml)
- -w, --day-of-week Show day of week
- --header FILE Get ChangeLog header from FILE ("-" means stdin)
- --xml Output XML instead of ChangeLog format
- --hide-filenames Don't show filenames (ignored for XML output)
- -P, --prune Don't show empty log messages
- -g OPTS, --global-opts OPTS Invoke like this "cvs OPTS log ..."
- -l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS"
- FILE1 [FILE2 ...] Show only log information for the named FILE(s)
-
-See http://www.red-bean.com/cvs2cl for maintenance and bug info.
-END_OF_INFO
-}
-
-__END__
-
-=head1 NAME
-
-cvs2cl.pl - produces GNU-style ChangeLogs in CVS working copies, by
- running "cvs log" and parsing the output. Shared log entries are
- unified in an intuitive way.
-
-=head1 DESCRIPTION
-
-This script generates GNU-style ChangeLog files from CVS log
-information. Basic usage: just run it inside a working copy and a
-ChangeLog will appear. It requires repository access (i.e., 'cvs log'
-must work). Run "cvs2cl.pl --help" to see more advanced options.
-
-See http://www.red-bean.com/cvs2cl for updates, and for instructions
-on getting anonymous CVS access to this script.
-
-Maintainer: Karl Fogel <kfogel@red-bean.com>
-Please report bugs to <bug-cvs2cl@red-bean.com>.
-
-=head1 README
-
-This script generates GNU-style ChangeLog files from CVS log
-information. Basic usage: just run it inside a working copy and a
-ChangeLog will appear. It requires repository access (i.e., 'cvs log'
-must work). Run "cvs2cl.pl --help" to see more advanced options.
-
-See http://www.red-bean.com/cvs2cl for updates, and for instructions
-on getting anonymous CVS access to this script.
-
-Maintainer: Karl Fogel <kfogel@red-bean.com>
-Please report bugs to <bug-cvs2cl@red-bean.com>.
-
-=head1 PREREQUISITES
-
-This script requires C<Text::Wrap>, C<Time::Local>, and
-C<File::Basename>.
-It also seems to require C<Perl 5.004_04> or higher.
-
-=pod OSNAMES
-
-any
-
-=pod SCRIPT CATEGORIES
-
-Version_Control/CVS
-
-=cut
-
-
--*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*-
-
-Note about a bug-slash-opportunity:
------------------------------------
-
-There's a bug in Text::Wrap, which affects cvs2cl. This script
-reveals it:
-
- #!/usr/bin/perl -w
-
- use Text::Wrap;
-
- my $test_text =
- "This script demonstrates a bug in Text::Wrap. The very long line
- following this paragraph will be relocated relative to the surrounding
- text:
-
- ====================================================================
-
- See? When the bug happens, we'll get the line of equal signs below
- this paragraph, even though it should be above.";
-
-
- # Print out the test text with no wrapping:
- print "$test_text";
- print "\n";
- print "\n";
-
- # Now print it out wrapped, and see the bug:
- print wrap ("\t", " ", "$test_text");
- print "\n";
- print "\n";
-
-If the line of equal signs were one shorter, then the bug doesn't
-happen. Interesting.
-
-Anyway, rather than fix this in Text::Wrap, we might as well write a
-new wrap() which has the following much-needed features:
-
-* initial indentation, like current Text::Wrap()
-* subsequent line indentation, like current Text::Wrap()
-* user chooses among: force-break long words, leave them alone, or die()?
-* preserve existing indentation: chopped chunks from an indented line
- are indented by same (like this line, not counting the asterisk!)
-* optional list of things to preserve on line starts, default ">"
-
-Note that the last two are essentially the same concept, so unify in
-implementation and give a good interface to controlling them.
-
-And how about:
-
-Optionally, when encounter a line pre-indented by same as previous
-line, then strip the newline and refill, but indent by the same.
-Yeah...
diff --git a/storage/ndb/home/bin/fix-cvs-root b/storage/ndb/home/bin/fix-cvs-root
deleted file mode 100755
index 2c4f158f825..00000000000
--- a/storage/ndb/home/bin/fix-cvs-root
+++ /dev/null
@@ -1,17 +0,0 @@
-#! /bin/sh
-
-# change all CVS/Root to current CVSROOT
-
-[ "$CVSROOT" ] || { echo "no CVSROOT in environment" >&2; exit 1; }
-
-echo "changing all CVS/Root files under `pwd`"
-sleep 1
-
-find . -path '*/CVS/Root' -print |
-while read file; do
- echo "$file"
- chmod +w $file || exit 1
- echo $CVSROOT >$file || exit 1
-done
-
-echo "done"
diff --git a/storage/ndb/home/bin/import-from-bk.sh b/storage/ndb/home/bin/import-from-bk.sh
deleted file mode 100755
index 4e3957be6d5..00000000000
--- a/storage/ndb/home/bin/import-from-bk.sh
+++ /dev/null
@@ -1,158 +0,0 @@
-#! /bin/sh
-
-# XXX does not delete files
-# XXX does not handle nested new dirs
-# this script screams for perl, no time now
-# look for bk2cvs on the net
-
-PATH=/usr/local/bin:$PATH; export PATH
-LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
-
-batch=n
-if [ "$1" = "-batch" ]; then
- batch=y
- shift
-fi
-
-say() {
- echo "$*"
-}
-
-die() {
- case $# in
- 0) set -- "command failed" ;;
- esac
- say "$* -- aborted" >&2
- exit 1
-}
-
-usage() {
- die "usage: $0 [-batch] top -- copy from mysql/ndb to another NDB_TOP"
-}
-
-doit() {
- cmd="$*"
- if [ $batch = n ]; then
- echo -n "$cmd [y]"
- read junk
- sh -c "$cmd"
- return 0
- else
- echo "$cmd"
- sh -c "$cmd"
- return $?
- fi
-}
-
-say "======================"
-say "`date`"
-
-case $# in
-1) [ -d $1/src/CVS ] || die "$1 is not an NDB_TOP"
- top=$1 ;;
-*) usage ;;
-esac
-
-if ! fgrep ndb_kernel_version.h $top/include/kernel/CVS/Entries >/dev/null 2>&1; then
- die "$top is not an NDB_TOP"
-fi
-
-if find $top -path '*/CVS/Tag' -print | grep . >/dev/null; then
- die "$top: contains CVS/Tag files, not accepted"
-fi
-
-if [ ! -f include/SCCS/s.ndb_version.h ]; then
- die "current dir ($PWD) is not an NDB_TOP"
-fi
-
-doit "bk pull" || exit 1
-doit "bk -r clean"
-doit "bk -r get -q"
-
-files=`bk -r. sfiles -g |
- fgrep -v ' ' |
- fgrep -v /.cvsignore`
-
-n=0
-files2=
-for f in $files; do
- if [ ! -f $f ]; then
- die "$f: no such file"
- fi
- if [ -w $f ]; then
- say "$f: is writable, accept anyway"
- fi
- files2="$files2 $f"
- n=$((n+1))
-done
-files=$files2
-say "$n files..."
-
-adddirs= addfiles= updfiles=
-for f in $files; do
- d=`dirname $f`
- b=`basename $f`
- if [ ! -f $top/$d/CVS/Entries ]; then
- found=n
- for x in $adddirs; do
- if [ $x = $d ]; then found=y; break; fi
- done
- if [ $found = n ]; then
- say "$d: to create dir"
- adddirs="$adddirs $d"
- fi
- addfiles="$addfiles $f"
- say "$f: to create"
- elif ! fgrep "/$b/" $top/$d/CVS/Entries >/dev/null; then
- addfiles="$addfiles $f"
- say "$f: to create"
- else
- cmp $f $top/$f >/dev/null
- case $? in
- 0) continue ;;
- 1) ;;
- *) die "$f: unknown error" ;;
- esac
- updfiles="$updfiles $f"
- say "$f: to update"
- fi
-done
-
-for d in $adddirs; do
- doit "cd $top && mkdir -p $d" || die
-done
-
-for f in $addfiles $updfiles; do
- doit "cp -fp $f $top/$f" || die
-done
-
-for d in $adddirs; do
- # fix 1 level up
- d2=`dirname $d`
- if [ ! -d $top/$d2/CVS ]; then
- doit "cd $top && cvs add $d2" || die
- fi
- doit "cd $top && cvs add $d" || die
-done
-
-for f in $addfiles; do
- kb=
- if echo $f | perl -nle "print(-B $_)" | grep 1 >/dev/null; then
- kb="-kb"
- fi
- doit "cd $top && cvs add $kb $f" || die
-done
-
-tag=import_bk_`date +%Y_%m_%d`
-
-doit "cd $top && cvs commit -m $tag" || die
-doit "cd $top && cvs tag -F $tag" || die
-
-env="NDB_TOP=$top; export NDB_TOP"
-env="$env; USER_FLAGS='-DAPI_TRACE -fmessage-length=0'; export USER_FLAGS"
-doit "$env; cd $top && ./configure"
-doit "$env; cd $top && sh config/GuessConfig.sh"
-doit "$env; cd $top && make clean nuke-deps vim-tags"
-doit "$env; cd $top && make" || die
-
-say "imported ok"
diff --git a/storage/ndb/home/bin/ndb_deploy b/storage/ndb/home/bin/ndb_deploy
deleted file mode 100755
index 773fc9b8fd7..00000000000
--- a/storage/ndb/home/bin/ndb_deploy
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-if [ $# -eq 0 ]
-then
- for i in $DEPLOY_DST
- do
- rsync -r -v --exclude '*.a' $NDB_TOP/bin $NDB_TOP/lib $i/
- done
-else
- while [ $# -gt 0 ]
- do
- arg=$1
- shift;
- if [ `echo $arg | grep -c lib` -eq 0 ]
- then
- dst=bin/
- else
- dst=lib/
- fi
-
- for i in $DEPLOY_DST
- do
- rsync -v $arg $i/$dst
- done
- done
-fi
-
diff --git a/storage/ndb/home/bin/ndbdoxy.pl b/storage/ndb/home/bin/ndbdoxy.pl
deleted file mode 100755
index 89b7de8440e..00000000000
--- a/storage/ndb/home/bin/ndbdoxy.pl
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/local/bin/perl
-#
-# ndbdoxy.pl Executes doxygen on a checked out version of NDB Cluster
-#
-# Written by Lars Thalmann, 2003.
-
-use strict;
-umask 000;
-
-# -----------------------------------------------------------------------------
-# Settings
-# -----------------------------------------------------------------------------
-
-my $root = "/home/elathal/public_html/cvsdoxy";
-
-$ENV{LD_LIBRARY_PATH} = "/usr/local/lib:/opt/as/local/lib";
-$ENV{LD_LIBRARY_PATH} = $ENV{LD_LIBRARY_PATH} . ":/opt/as/forte6/SUNWspro/lib";
-$ENV{PATH} = $ENV{PATH} . ":/usr/local/bin:/opt/as/local/bin";
-$ENV{PATH} = $ENV{PATH} . ":/opt/as/local/teTeX/bin/sparc-sun-solaris2.8";
-
-my $DOXYGEN = "doxygen";
-my $PDFLATEX = "pdflatex";
-my $MAKEINDEX = "makeindex";
-
-# -----------------------------------------------------------------------------
-# Argument handling
-# -----------------------------------------------------------------------------
-
-if (@ARGV != 3) {
- print<<END;
-Usage:
- ndbdoxy.pl <module> <title> <version>
-
- where
- <module> is cvsdoxy module to doxgenify
- <title> is title of report
- <version> is version of NDB Cluster
-END
- exit;
-}
-my $module = $ARGV[0];
-my $title = $ARGV[1];
-my $version = $ARGV[2];
-my $destdir = ".";
-
-# -----------------------------------------------------------------------------
-# Execute Doxygen -g
-# -----------------------------------------------------------------------------
-
-if (-r "${root}/doxyfiles/${module}.doxyfile") {
- system("cd ${destdir}; \
- cp ${root}/doxyfiles/${module}.doxyfile Doxyfile");
-} elsif (-r "${root}/doxyfiles/default.doxyfile") {
- system("cd ${destdir}; \
- cp ${root}/doxyfiles/default.doxyfile Doxyfile");
-} else {
- system("cd ${destdir}; $DOXYGEN -g");
-}
-
-# -----------------------------------------------------------------------------
-# HTML Footer
-# -----------------------------------------------------------------------------
-
-if (-r "${root}/doxyfiles/htmlfooter") {
- system("cd ${destdir}; \
- cp ${root}/doxyfiles/htmlfooter footer.html");
-
- open (INFILE, "< ${destdir}/footer.html")
- or die "Error opening ${destdir}/footer.html.\n";
- open (OUTFILE, "> ${destdir}/footer.html.new")
- or die "Error opening ${destdir}/footer.html.new.\n";
- while (<INFILE>) {
- if (/(.*)DATE(.*)$/) {
- print OUTFILE $1 . localtime() . $2;
- } else {
- print OUTFILE;
- }
- }
- close INFILE;
- close OUTFILE;
-
- system("mv ${destdir}/footer.html.new ${destdir}/footer.html");
-} else {
- print("Warning: No ${root}/doxyfiles/${module}.htmlfooter");
-}
-
-# -----------------------------------------------------------------------------
-# Execute Doxygen
-# -----------------------------------------------------------------------------
-
-system("cd ${destdir}; $DOXYGEN");
-
-# -----------------------------------------------------------------------------
-# Change a little in refman.tex
-# -----------------------------------------------------------------------------
-
-open (INFILE, "< ${destdir}/latex/refman.tex")
- or die "Error opening ${destdir}/latex/refman.tex.\n";
-open (OUTFILE, "> ${destdir}/latex/refman.tex.new")
- or die "Error opening ${destdir}/latex/refman.tex.new.\n";
-
-while (<INFILE>)
-{
- if (/(.*)Reference Manual(.*)$/) {
- print OUTFILE $1 .
- "\\mbox{}\\vspace{-3cm}\\mbox{}" .
- "\\hrule\\bigskip\\bigskip\\bigskip\\bigskip" .
- "\\Huge{" . $title . "}" . $2;
- } elsif (/(.*)Generated by Doxygen 1.2.1[0-9](.*)$/) {
- print OUTFILE $1 .
- "\\begin{center}" .
- "\\LARGE{MySQL AB}" .
- "\\end{center}".
- "\\hfill\\bigskip\\bigskip\\bigskip\\hrule" .
- "\\bigskip\\bigskip\\bigskip\\bigskip\\bigskip" .
- "\\bigskip\\bigskip\\bigskip\\bigskip\\bigskip" .
- "\\bigskip\\bigskip NDB Cluster Release " . $version .
- "\\bigskip\\bigskip\\bigskip\\bigskip\\bigskip\\hfill" .
- $2;
- } elsif (/\\chapter\{File Index\}/) {
- print OUTFILE "\%\\chapter{File Index}\n";
- } elsif (/\\input{files}/) {
- print OUTFILE "\%\\input{files}\n";
- } elsif (/\\chapter\{Page Index\}/) {
- print OUTFILE "\%\\chapter{Page Index}\n";
- } elsif (/\\input{pages}/) {
- print OUTFILE "\%\\input{pages}\n";
- } else {
- print OUTFILE;
- }
-}
-
-close INFILE;
-close OUTFILE;
-
-system("mv ${destdir}/latex/refman.tex.new ${destdir}/latex/refman.tex");
-
-# -----------------------------------------------------------------------------
-# Change a little in doxygen.sty
-# -----------------------------------------------------------------------------
-
-open (INFILE, "< ${destdir}/latex/doxygen.sty")
- or die "Error opening INFILE.\n";
-open (OUTFILE, "> ${destdir}/latex/doxygen.sty.new")
- or die "Error opening OUTFILE.\n";
-
-while (<INFILE>)
-{
- if (/\\rfoot/) {
- print OUTFILE "\\rfoot[\\fancyplain{}{\\bfseries\\small \\copyright~Copyright 2003 MySQL AB\\hfill support-cluster\@mysql.com}]{}\n";
- } elsif (/\\lfoot/) {
- print OUTFILE "\\lfoot[]{\\fancyplain{}{\\bfseries\\small support-cluster\@mysql.com\\hfill \\copyright~Copyright 2003 MySQL AB}}\n";
- } else {
- print OUTFILE;
- }
-}
-
-close INFILE;
-close OUTFILE;
-
-system("mv ${destdir}/latex/doxygen.sty.new ${destdir}/latex/doxygen.sty");
-
-# -----------------------------------------------------------------------------
-# Other
-# -----------------------------------------------------------------------------
-
-#system("cd ${root}/tmp/${module}; \
-# mkdir html.tar; \
-# cd html.tar; \
-# cp -r ../html ${module}; \
-# tar cf ${module}.html.tar ${module}; \
-# /usr/local/bin/gzip ${module}.html.tar; \
-# /bin/rm -rf ${root}/tmp/${module}/html.tar/${module}");
-
-#system("cd ${destdir}/latex/; \
-# $PDFLATEX refman.tex \
-# $MAKEINDEX refman.idx \
-# $PDFLATEX refman.tex \
-# mv -f refman.pdf ${module}.pdf");
-
-print<<END;
-Execute:
- latex refman; makeindex refman; latex refman
-END
diff --git a/storage/ndb/home/bin/ngcalc b/storage/ndb/home/bin/ngcalc
deleted file mode 100755
index a289d384db9..00000000000
--- a/storage/ndb/home/bin/ngcalc
+++ /dev/null
@@ -1,78 +0,0 @@
-#! /usr/local/bin/perl
-
-use strict;
-use Getopt::Long;
-
-sub usage {
- print <<END;
-ngcalc -- calculate node groups and table fragments
-usage: ngcalc [ options ] f1 f2 ...
--g num number of node groups (default 2)
--r num number of replicas (default 2)
--n list comma-separated list of db nodes (default 1,2,...)
-fX number of fragments per node group in table X (e.g. 1,2,8)
- (all replicas count as same fragment)
-END
- exit(1);
-};
-
-use vars qw($cnoOfNodeGroups $cnoReplicas $nodeArray);
-
-$cnoOfNodeGroups = 2;
-$cnoReplicas = 2;
-GetOptions(
- "g=i" => \$cnoOfNodeGroups,
- "r=i" => \$cnoReplicas,
- "n=s" => \$nodeArray,
-) or &usage;
-
-my @tableList = @ARGV;
-
-$cnoOfNodeGroups > 0 or &usage;
-$cnoReplicas > 0 or &usage;
-if (! defined($nodeArray)) {
- $nodeArray = join(',', 1..($cnoOfNodeGroups*$cnoReplicas));
-}
-$nodeArray =~ /^\d+(,\d+)*$/ or &usage;
-my @nodeArray = split(/,/, $nodeArray);
-@nodeArray == $cnoOfNodeGroups*$cnoReplicas or &usage;
-
-my @nodeGroupRecord;
-for (my $i = 0; $i < $cnoOfNodeGroups; $i++) {
- my $rec = {};
- my $nodes = [];
- for (my $j = 0; $j < $cnoReplicas; $j++) {
- push(@$nodes, $nodeArray[$i * $cnoReplicas + $j]);
- }
- $rec->{nodesInGroup} = $nodes;
- $rec->{nodeCount} = $cnoReplicas;
- $rec->{nextReplicaNode} = 0;
- $nodeGroupRecord[$i] = $rec;
- print "NG $i: ", join(" ", @{$rec->{nodesInGroup}}), "\n";
-}
-
-# see Dbdih::execCREATE_FRAGMENTATION_REQ
-
-my $c_nextNodeGroup = 0;
-for (my $t = 0; $t < @tableList; $t++) {
- use integer;
- my $f = $tableList[$t];
- my $ng = $c_nextNodeGroup++;
- $c_nextNodeGroup = 0 if $c_nextNodeGroup == $cnoOfNodeGroups;
- my $noOfFragments = $f * $cnoOfNodeGroups;
- my @fragments;
- for (my $fragNo = 0; $fragNo < $noOfFragments; $fragNo++) {
- my $rec = $nodeGroupRecord[$ng];
- my $max = $rec->{nodeCount};
- my $ind = $rec->{nextReplicaNode};
- $rec->{nextReplicaNode} = ($ind + 1 >= $max ? 0 : $ind + 1);
- for (my $replicaNo = 0; $replicaNo < $cnoReplicas; $replicaNo++) {
- my $nodeId = $rec->{nodesInGroup}[$ind++];
- push(@fragments, $nodeId);
- $ind = ($ind == $max ? 0 : $ind);
- }
- $ng++;
- $ng = ($ng == $cnoOfNodeGroups ? 0 : $ng);
- }
- printf "%02d %s\n", $t, join(" ", @fragments);
-}
diff --git a/storage/ndb/home/bin/parseConfigFile.awk b/storage/ndb/home/bin/parseConfigFile.awk
deleted file mode 100644
index 6903949156c..00000000000
--- a/storage/ndb/home/bin/parseConfigFile.awk
+++ /dev/null
@@ -1,98 +0,0 @@
-BEGIN{
- where=0;
- n_hosts=0;
- n_api=0;
- n_ndb=0;
- n_mgm=0;
- n_ports=0;
-}
-/COMPUTERS/ {
- where=1;
-}
-/\[[ \t]*COMPUTER[ \t]*\]/ {
- where=1;
-}
-/PROCESSES/ {
- where=2;
-}
-/Type: MGMT/ {
- if(where!=1){
- where=2;
- n_mgm++;
- }
-}
-/\[[ \t]*MGM[ \t]*\]/ {
- where=2;
- n_mgm++;
-}
-/Type: DB/ {
- if(where!=1){
- where=3;
- n_ndb++;
- }
-}
-/\[[ \t]*DB[ \t]*\]/ {
- where=3;
- n_ndb++;
-}
-/Type: API/ {
- if(where!=1){
- where=4;
- n_api++;
- }
-}
-/\[[ \t]*API[ \t]*\]/ {
- where=4;
- n_api++;
-}
-/HostName:/ {
- host_names[host_ids[n_hosts]]=$2;
-}
-
-/FileSystemPath:/ {
- if (where==3){
- ndb_fs[ndb_ids[n_ndb]]=$2;
- }
-}
-
-/Id:/{
- if(where==1){
- n_hosts++;
- host_ids[n_hosts]=$2;
- }
- if(where==2){
- mgm_ids[n_mgm]=$2;
- }
- if(where==3){
- ndb_ids[n_ndb]=$2;
- }
- if(where==4){
- api_ids[n_api]=$2;
- }
-}
-/ExecuteOnComputer:/{
- if(where==2){
- mgm_hosts[mgm_ids[n_mgm]]=host_names[$2];
- }
- if(where==3){
- ndb_hosts[ndb_ids[n_ndb]]=host_names[$2];
- }
- if(where==4){
- api_hosts[api_ids[n_api]]=host_names[$2];
- }
-}
-END {
- for(i=1; i<=n_mgm; i++){
- printf("mgm_%d=%s\n", mgm_ids[i], mgm_hosts[mgm_ids[i]]);
- }
- for(i=1; i<=n_ndb; i++){
- printf("ndb_%d=%s\n", ndb_ids[i], ndb_hosts[ndb_ids[i]]);
- printf("ndbfs_%d=%s\n", ndb_ids[i], ndb_fs[ndb_ids[i]]);
- }
- for(i=1; i<=n_api; i++){
- printf("api_%d=%s\n", api_ids[i], api_hosts[api_ids[i]]);
- }
- printf("mgm_nodes=%d\n", n_mgm);
- printf("ndb_nodes=%d\n", n_ndb);
- printf("api_nodes=%d\n", n_api);
-}
diff --git a/storage/ndb/home/bin/setup-test.sh b/storage/ndb/home/bin/setup-test.sh
deleted file mode 100755
index 61097c30027..00000000000
--- a/storage/ndb/home/bin/setup-test.sh
+++ /dev/null
@@ -1,272 +0,0 @@
-#!/bin/sh
-
-# NAME
-# run-test.sh - Run a test program
-#
-# SYNOPSIS
-# setup-test.sh [ -n <ndb dir>] [ -r <run dir>]
-#
-# DESCRIPTION
-# run a test
-#
-# OPTIONS
-#
-# EXAMPLES
-#
-# ENVIRONMENT
-# NDB_PROJ_HOME Home dir for ndb
-#
-# FILES
-# $NDB_PROJ_HOME/lib/funcs.sh shell script functions
-#
-# DIAGNOSTICTS
-#
-# VERSION
-# 1.01
-#
-# AUTHOR
-# Jonas Oreland
-#
-#
-
-progname=`basename $0`
-synopsis="setup-test.sh [-x xterm] [ -n <ndb dir>] [ -r <run dir>]"
-
-: ${NDB_PROJ_HOME:?} # If undefined, exit with error message
-
-: ${RUN_NDB_NODE_OPTIONS:=--} # If undef, set to --. Keeps getopts happy.
- # You may have to experiment a bit
- # to get quoting right (if you need it).
-
-
-. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff
-
-# defaults for options related variables
-#
-
-verbose=yes
-options=""
-ndb_dir=$NDB_TOP
-if [ -z "$ndb_dir" ]
-then
- ndb_dir=`pwd`
-fi
-
-local_dir=`pwd`
-own_host=`hostname`
-uniq_id=$$.$$
-
-_xterm=$XTERM
-_rlogin="ssh -X"
-
-# used if error when parsing the options environment variable
-#
-env_opterr="options environment variable: <<$options>>"
-
-
-# Option parsing, for the options variable as well as the command line.
-#
-# We want to be able to set options in an environment variable,
-# as well as on the command line. In order not to have to repeat
-# the same getopts information twice, we loop two times over the
-# getopts while loop. The first time, we process options from
-# the options environment variable, the second time we process
-# options from the command line.
-#
-# The things to change are the actual options and what they do.
-#
-#
-for optstring in "$options" "" # 1. options variable 2. cmd line
-do
- while getopts n:r:x: i $optstring # optstring empty => no arg => cmd line
- do
- case $i in
-
- n) ndb_dir=$OPTARG;; # Ndb dir
- r) run_dir=$OPTARG;; # Run dir
- x) _xterm=$OPTARG;;
- \?) syndie $env_opterr;; # print synopsis and exit
-
- esac
- done
-
- [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options
-
- env_opterr= # Round 2 should not use the value
-
-done
-shift `expr $OPTIND - 1`
-
-# --- option parsing done ---
-
-ndb_dir=`abspath $ndb_dir`
-run_dir=`abspath $run_dir`
-
-trace "Verifying arguments"
-
-if [ ! -d $ndb_dir/bin ] || [ ! -d $ndb_dir/lib ]
-then
- msg "Ndb home path seems incorrect either $ndb_dir/bin or $ndb_dir/lib not found"
- exit 1004
-fi
-
-ndb_bin=$ndb_dir/bin/ndb
-mgm_bin=$ndb_dir/bin/mgmtsrvr
-api_lib=$ndb_dir/lib/libNDB_API.so
-
-if [ ! -x $ndb_bin ]
-then
- msg "Ndb path seems incorrect ndb binary not found: $ndb_bin"
- exit 1004
-fi
-
-if [ ! -x $mgm_bin ]
-then
- msg "Ndb path seems incorrect management server binary not found: $mgm_bin"
- exit 1004
-fi
-
-init_config=$run_dir/mgm.1/initconfig.txt
-local_config=$run_dir/mgm.1/localcfg.txt
-if [ ! -r $init_config ] || [ ! -r $local_config ]
-then
- msg "Run path seems incorrect $init_config or $local_config not found"
- exit 1004
-fi
-
-trace "Parsing $init_config"
-awk -f $NDB_PROJ_HOME/bin/parseConfigFile.awk $init_config > /tmp/run-test.$uniq_id
-. /tmp/run-test.$uniq_id
-cat /tmp/run-test.$uniq_id
-rm -f /tmp/run-test.$uniq_id
-
-trace "Parsing $local_config"
-MgmPort=`grep -v "OwnProcessId" $local_config | cut -d " " -f 2`
-
-trace "Verifying that mgm port is empty"
-telnet $mgm_1 $MgmPort > /tmp/mgm_port.$uniq_id 2>&1 <<EOF
-EOF
-
-if [ 0 -lt `grep -c -i connected /tmp/mgm_port.$uniq_id` ]
-then
- rm /tmp/mgm_port.$uniq_id
- msg "There is already something using port $mgm_1:$MgmPort"
- exit 1003
-fi
-rm /tmp/mgm_port.$uniq_id
-
-fixhost(){
- if [ "$1" != localhost ]
- then
- echo $1
- else
- uname -n
- fi
-}
-
-do_xterm(){
- title=$1
- shift
- xterm -fg black -title "$title" -e $*
-}
-
-save_profile(){
- cp $HOME/.profile /tmp/.profile.$uniq_id
-}
-
-wait_restore_profile(){
- while [ -r /tmp/.profile.$uniq_id ]
- do
- sleep 1
- done
-}
-
-start_mgm(){
- trace "Starting Management server on: $mgm_1"
- save_profile
- mgm_1=`fixhost $mgm_1`
-
- (
- echo "PATH=$ndb_dir/bin:\$PATH"
- echo "LD_LIBRARY_PATH=$ndb_dir/lib:\$LD_LIBRARY_PATH"
- echo "export PATH LD_LIBRARY_PATH"
- echo "cd $run_dir/mgm.1"
- echo "ulimit -Sc unlimited"
- echo "mv /tmp/.profile.$uniq_id $HOME/.profile"
- ) >> $HOME/.profile
- do_xterm "Mmg on $mgm_1" ${_rlogin} $mgm_1 &
- wait_restore_profile
-}
-
-start_ndb_node(){
- node_id=$1
- dir=$run_dir/ndb.$1
- ndb_host=`eval echo "\$"ndb_$node_id`
- ndb_host=`fixhost $ndb_host`
- ndb_fs=`eval echo "\$"ndbfs_$node_id`
-
- trace "Starting Ndb node $node_id on $ndb_host"
- save_profile
-
- (
- echo "PATH=$ndb_dir/bin:\$PATH"
- echo "LD_LIBRARY_PATH=$ndb_dir/lib:\$LD_LIBRARY_PATH"
- echo "mkdir -p $ndb_fs"
- echo "export PATH LD_LIBRARY_PATH"
- echo "cd $dir"
- echo "ulimit -Sc unlimited"
- echo "mv /tmp/.profile.$uniq_id $HOME/.profile"
- ) >> $HOME/.profile
- do_xterm "Ndb: $node_id on $ndb_host" ${_rlogin} $ndb_host &
- wait_restore_profile
-}
-
-start_api_node(){
- node_id=$1
- dir=$run_dir/api.$1
- api_host=`eval echo "\$"api_$node_id`
- api_host=`fixhost $api_host`
-
- trace "Starting api node $node_id on $api_host"
- save_profile
-
- (
- echo "PATH=$ndb_dir/bin:\$PATH"
- echo "LD_LIBRARY_PATH=$ndb_dir/lib:\$LD_LIBRARY_PATH"
- echo "export PATH LD_LIBRARY_PATH NDB_PROJ_HOME"
- echo "cd $dir"
- echo "ulimit -Sc unlimited"
- echo "mv /tmp/.profile.$uniq_id $HOME/.profile"
- ) >> $HOME/.profile
- do_xterm "API: $node_id on $api_host" ${_rlogin} $api_host &
- wait_restore_profile
-}
-
-for_each_ndb_node(){
- i=1
- j=`expr $mgm_nodes + 1`
- while [ $i -le $ndb_nodes ]
- do
- $* $j
- j=`expr $j + 1`
- i=`expr $i + 1`
- done
-}
-
-for_each_api_node(){
- i=1
- j=`expr $mgm_nodes + $ndb_nodes + 1`
- while [ $i -le $api_nodes ]
- do
- $* $j
- j=`expr $j + 1`
- i=`expr $i + 1`
- done
-}
-
-start_mgm
-for_each_ndb_node start_ndb_node
-for_each_api_node start_api_node
-
-exit 0
-
diff --git a/storage/ndb/home/bin/signallog2html.lib/signallog2list.awk b/storage/ndb/home/bin/signallog2html.lib/signallog2list.awk
deleted file mode 100644
index 9839f314556..00000000000
--- a/storage/ndb/home/bin/signallog2html.lib/signallog2list.awk
+++ /dev/null
@@ -1,102 +0,0 @@
-BEGIN{
- PRINT=0;
- SIGNAL_ARRAY[0]="";
- BLOCK_ID=0;
- SIGNAL_ID=-22;
-}
-{
- SIGNAL_ARRAY[SIGNAL_ID]=SIGNAL_ID;
-}
-
-/^---- Send ----- Signal ----------------/ {
- DIRECTION="S";
- SENDER="";
- SENDPROCESS="";
- RECEIVER="";
- RECPROCESS="";
- SIGNAL="";
- RECSIGID="?";
- SIGID="?";
- DELAY="N/A";
-}
-
-/^---- Send delay Signal/ {
- DIRECTION="SD";
- SENDER="";
- SENDPROCESS="";
- RECEIVER="";
- RECPROCESS="";
- SIGNAL="";
- RECSIGID="?";
- SIGID="?";
- DELAY=$5;
-
- LEN=length(DELAY);
- DELAY=substr(DELAY,2,LEN);
-}
-
-/^---- Received - Signal ----------------/ {
- DIRECTION="R";
- SENDER="";
- SENDPROCESS="";
- RECEIVER="";
- RECPROCESS="";
- SIGNAL="";
- RECSIGID="?";
- SIGID="?";
- DELAY="N/A";
-}
-
-/r.bn:/{
-
- RECEIVER=$3;
- RECPROCESS=$5;
-
- if(DIRECTION == "R"){
- SIGNAL=$10;
- RECSIGID=$7;
- }
- else
- SIGNAL=$8;
-}
-
-/s.bn:/{
-
- SENDER=$3;
- SIGID=$7;
-
- if(SIGID == SIGNAL_ARRAY[SIGID]){
- PRINT=1;
- if(DIRECTION == "R"){
- SIGNAL_ARRAY[RECSIGID]=RECSIGID;
- };
- }
-
- SENDPROCESS=$5;
-
- LEN=length(RECEIVER);
- RECEIVER=substr(RECEIVER,2,LEN-3);
-
- if(BLOCK_ID == "ALL" || RECEIVER==BLOCK_ID){PRINT=1; }
-
- LEN=length(SENDER);
- SENDER=substr(SENDER,2,LEN-3);
- if(BLOCK_ID == "ALL" || SENDER == BLOCK_ID){ PRINT=1;}
-
- LEN=length(SIGNAL);
- SIGNAL=substr(SIGNAL,2,LEN-2);
-
- LEN=length(SENDPROCESS);
- SENDPROCESS=substr(SENDPROCESS,1,LEN-1);
-
- LEN=length(RECPROCESS);
- RECPROCESS=substr(RECPROCESS,1,LEN-1);
-
- if( PRINT == 1){
- print DIRECTION" "SENDPROCESS" "SENDER" "RECPROCESS" "RECEIVER" "SIGNAL" "SIGID" "RECSIGID" "DELAY;
- }
-
- PRINT=0;
-}
-
-
diff --git a/storage/ndb/home/bin/signallog2html.lib/uniq_blocks.awk b/storage/ndb/home/bin/signallog2html.lib/uniq_blocks.awk
deleted file mode 100644
index 43f48d1cde1..00000000000
--- a/storage/ndb/home/bin/signallog2html.lib/uniq_blocks.awk
+++ /dev/null
@@ -1,29 +0,0 @@
-BEGIN{
- NAMES[""]="";
- ORDER[0]="";
- NUM=0;
-}
-
-{
- if(NAMES[$2$3]!=$2$3){
- NAMES[$2$3]=$2$3;
- ORDER[NUM]=$2$3;
- NUM++;
- }
-
- if(NAMES[$4$5]!=$4$5){
- NAMES[$4$5]=$4$5;
- ORDER[NUM]=$4$5;
- NUM++;
- }
-
-
-}
-END{
- for(i=0; i<NUM; i++){
- LIST=ORDER[i]" "LIST;
-
- }
- print LIST;
-}
-
diff --git a/storage/ndb/home/bin/signallog2html.sh b/storage/ndb/home/bin/signallog2html.sh
deleted file mode 100755
index 5665275807c..00000000000
--- a/storage/ndb/home/bin/signallog2html.sh
+++ /dev/null
@@ -1,349 +0,0 @@
-#!/bin/sh
-# NAME
-# signallog2html.sh
-#
-# SYNOPSIS
-# signallog2html.sh [ -b <block_name | ALL> ] [ -s <signal_id> ] -f signal_log_file
-#
-# DESCRIPTION
-# Creates a signal sequence diagram in HTML format that can be
-# viewed from a web browser. The HTML file is created from a signal
-# log file and it contains a big table with jpeg files in every
-# table cell. Every row in the table is a signal. The block_name
-# could be one of the following: CMVMI MISSRA NDBFS NDBCNTR DBACC
-# DBDICT DBLQH DBDIH DBTC DBTUP QMGR ALL. The signal_id is a
-# number. If no block_name or signal_id is given the default
-# block_name "ALL" is used.
-#
-#
-#
-# OPTIONS
-#
-# EXAMPLES
-#
-#
-# ENVIRONMENT
-# NDB_PROJ_HOME Home dir for ndb
-#
-# FILES
-# $NDB_PROJ_HOME/lib/funcs.sh General shell script functions.
-# uniq_blocks.awk Creates a list of unique blocks
-# in the signal_log_file.
-# signallog2list.awk Creates a list file from the signal_log_file.
-# empty.JPG Jpeg file, must exist in the HTML file
-# directory for viewing.
-# left_line.JPG
-# line.JPG
-# right_line.JPG
-# self_line.JPG
-#
-#
-# SEE ALSO
-#
-# DIAGNOSTICTS
-#
-# VERSION
-# 1.0
-#
-# DATE
-# 011029
-#
-# AUTHOR
-# Jan Markborg
-#
-
-progname=`basename $0`
-synopsis="signallog2html.sh [ -b <block_name | ALL> ] [ -s <signal_id> ] -f signal_log_file"
-block_name=""
-signal_id=""
-verbose=yes
-signal_log_file=""
-
-: ${NDB_PROJ_HOME:?} # If undefined, exit with error message
-
-: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy.
- # You may have to experiment a bit
- # to get quoting right (if you need it).
-
-
-. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff
-
-# defaults for options related variables
-#
-report_date=`date '+%Y-%m-%d'`
-
-# Option parsing for the the command line.
-#
-
-while getopts f:b:s: i
-do
- case $i in
- f) signal_log_file=$OPTARG;;
- b) block_name=$OPTARG;;
- s) signal_id=$OPTARG;;
- \?) syndie ;; # print synopsis and exit
- esac
-done
-
-# -- Verify
-trace "Verifying signal_log_file $signal_log_file"
-
-if [ x$signal_log_file = "x" ]
-then
- syndie "Invalid signal_log_file name: $signal_log_file not found"
-fi
-
-
-if [ ! -r $signal_log_file ]
-then
- syndie "Invalid signal_log_file name: $signal_log_file not found"
-fi
-
-
-
-if [ blocknameSET = 1 ]
-then
-
- trace "Verifying block_name"
- case $block_name in
- CMVMI| MISSRA| NDBFS| NDBCNTR| DBACC| DBDICT| DBLQH| DBDIH| DBTC| DBTUP| QMGR);;
- ALL) trace "Signals to/from every block will be traced!";;
- *) syndie "Unknown block name: $block_name";;
- esac
-fi
-
-if [ block_name="" -a signal_id="" ]
-then
- block_name=ALL
- trace "block_name = $block_name"
-fi
-
-trace "Arguments OK"
-
-###
-#
-# General html functions
-header(){
- cat <<EOF
-<html><head><title>$*</title></head>
-<body>
-EOF
-}
-
-footer(){
- cat <<EOF
-</body></html>
-EOF
-}
-
-heading(){
- h=$1; shift
- cat <<EOF
-<h$h>$*</h$h>
-EOF
-}
-
-table(){
- echo "<table $*>"
-}
-
-table_header(){
- echo "<th>$*</th>"
-}
-
-end_table(){
- echo "</table>"
-}
-
-row(){
- echo "<tr>"
-}
-
-end_row(){
- echo "</tr>"
-}
-
-c_column(){
- cat <<EOF
-<td valign=center align=center>$*</td>
-EOF
-}
-
-bold(){
- cat <<EOF
-<b>$*</b>
-EOF
-}
-
-column(){
- cat <<EOF
-<td align=left>$*</td>
-EOF
-}
-
-para(){
- cat <<EOF
-<p></p>
-EOF
-}
-
-hr(){
- cat <<EOF
-<hr>
-EOF
-}
-
-img_column(){
- cat <<EOF
-<td><center><$* height=100% width=100%></center></td>
-EOF
-}
-
-# Check the direction of arrow.
-# arrowDirection(){ $columnarray $sendnode$sendblock $recnode$recblock
-arrowDirection(){
-if [ $2 = $3 ]
-then
- arrow=SELF
- return;
-else
- for x in $1
- do
- if [ $x = $2 ]
- then
- arrow=RIGHT
- break
- elif [ $x = $3 ]
- then
- arrow=LEFT
- break
- fi
- done
-fi
-}
-
-drawImages(){
-for x in $columnarray
-do
- case $arrow in
- SELF)
- if [ $x = $sendnode$sendblock ]
- then
- img_column img SRC=\"self_line.JPG\"
- else
- img_column img SRC=\"empty.JPG\"
- fi;;
-
- RIGHT)
- if [ $x = $recnode$recblock ]
- then
- img_column img SRC=\"right_line.JPG\"
- weHavePassedRec=1
- elif [ $x = $sendnode$sendblock ]
- then
- img_column img SRC=\"empty.JPG\"
- weHavePassedSen=1
- elif [ $weHavePassedRec = 1 -o $weHavePassedSen = 0 ]
- then
- img_column img SRC=\"empty.JPG\"
- elif [ $weHavePassedRec = 0 -a $weHavePassedSen = 1 ]
- then
- img_column img SRC=\"line.JPG\"
- fi;;
-
- LEFT)
- if [ $x = $recnode$recblock ]
- then
- img_column img SRC=\"empty.JPG\"
- weHaveJustPassedRec=1
- weHavePassedRec=1
- continue
- fi
- if [ $x = $sendnode$sendblock -a $weHaveJustPassedRec = 1 ]
- then
- img_column img SRC=\"left_line.JPG\"
- weHaveJustPassedRec=0
- weHavePassedSen=1
- continue
- fi
- if [ $x = $sendnode$sendblock ]
- then
- img_column img SRC=\"line.JPG\"
- weHavePassedSen=1
- continue
- fi
- if [ $weHaveJustPassedRec = 1 ]
- then
- img_column img SRC=\"left_line.JPG\"
- weHaveJustPassedRec=0
- continue
- fi
- if [ $weHavePassedSen = 1 -o $weHavePassedRec = 0 ]
- then
- img_column img SRC=\"empty.JPG\"
- continue
- fi
-
- if [ $weHavePassedRec = 1 -a $weHavePassedSen = 0 ]
- then
- img_column img SRC=\"line.JPG\"
- continue
-
- fi
- column ERROR;;
-
- *)
- echo ERROR;;
- esac
-done
-column $signal
-}
-
-### Main
-trace "Making HTML file"
-(
- header "Signal sequence diagram $report_date"
- heading 1 "Signal sequence diagram $report_date"
-
- trace "Making list file"
- #make a signal list file from the signal log file.
- `awk -f /home/ndb/bin/signallog2html.lib/signallog2list.awk SIGNAL_ID=$signal_id BLOCK_ID=$block_name $signal_log_file > $signal_log_file.list`
-
- COLUMNS=`awk -f /home/ndb/bin/signallog2html.lib/uniq_blocks.awk $signal_log_file.list | wc -w`
-
- table "border=0 cellspacing=0 cellpadding=0 cols=`expr $COLUMNS + 1`"
-
- columnarray=`awk -f /home/ndb/bin/signallog2html.lib/uniq_blocks.awk $signal_log_file.list`
-
- row
- column #make an empty first column!
- for col in $columnarray
- do
- table_header $col
- done
-
- grep "" $signal_log_file.list | \
- while read direction sendnode sendblock recnode recblock signal sigid recsigid delay
- do
- if [ $direction = "R" ]
- then
- row
- weHavePassedRec=0
- weHavePassedSen=0
- weHaveJustPassedRec=0
- arrow=""
-
- # calculate the direction of the arrow.
- arrowDirection "$columnarray" "$sendnode$sendblock" "$recnode$recblock"
-
- # Draw the arrow images.
- drawImages
- end_row
- fi
- done
- end_table
-
- footer
-) > $signal_log_file.html
-
-exit 0
diff --git a/storage/ndb/home/bin/stripcr b/storage/ndb/home/bin/stripcr
deleted file mode 100755
index 540418f88cf..00000000000
--- a/storage/ndb/home/bin/stripcr
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/sh
-
-
-# NAME
-# stripcr - a program for removing carriage return chars from dos-files.
-#
-# SYNOPSIS
-# stripcr [file...]
-#
-# DESCRIPTION
-# stripcr deletes all CR characters from the given files.
-# The files are edited in place.
-# If no files are given, stdin and stdout are used instead.
-#
-# OPTIONS
-# -s extension Make a copy of the original of each file, and
-# give it the given extension (.bak, .orig, -bak, ...).
-#
-# EXAMPLES
-# stripcr file.txt innerloop.cc
-# stripcr -i.bak *.cc
-#
-# ENVIRONMENT
-# NDB_PROJ_HOME Home dir for ndb
-#
-# FILES
-# $NDB_PROJ_HOME/lib/funcs.sh Some userful functions for safe execution
-# of commands, printing, and tracing.
-#
-# VERSION
-# 1.0
-#
-# AUTHOR
-# Jonas Mölsä
-#
-
-
-progname=`basename $0`
-synopsis="stripcr [-s extension] [file...]"
-
-
-: ${NDB_PROJ_HOME:?} # If undefined, exit with error message
-
-: ${STRIPCR_OPTIONS:=--} # If undefined, set to --, to keep getopts happy.
- # You may have to experiment, to get quoting right.
-
-. $NDB_PROJ_HOME/lib/funcs.sh
-
-
-# defaults for options related variables
-#
-extension=
-options="$STRIPCR_OPTIONS"
-
-# used if error when parsing the options environment variable
-#
-env_opterr="options environment variable: <<$options>>"
-
-
-
-# We want to be able to set options in an environment variable,
-# as well as on the command line. In order not to have to repeat
-# the same getopts information twice, we loop two times over the
-# getopts while loop. The first time, we process options from
-# the options environment variable, the second time we process
-# options from the command line.
-#
-# The things to change are the actual options and what they do.
-#
-#
-for optstring in "$options" "" # 1. options variable 2. cmd line
-do
- while getopts s: i $optstring # optstring empty => no arg => cmd line
- do
- case $i in
-
- s) extension="$OPTARG";;
- \?) syndie $env_opterr;; # print synopsis and exit
-
- esac
- done
-
- [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmd line options
-
- env_opterr= # Round 2 should not use the value
-done
-shift `expr $OPTIND - 1`
-
-
-safe perl -i$extension -lpe 'tr/\r//d' $*
diff --git a/storage/ndb/home/lib/funcs.sh b/storage/ndb/home/lib/funcs.sh
deleted file mode 100644
index b7d8914035e..00000000000
--- a/storage/ndb/home/lib/funcs.sh
+++ /dev/null
@@ -1,294 +0,0 @@
-# NAME
-# safe, safe_eval, die, rawdie, syndie, msg, errmsg,
-# rawmsg, rawerrmsg, trace, errtrace, is_wordmatch
-# - functions for safe execution and convenient printing and tracing
-#
-# abspath - make a path absolute
-#
-# SYNOPSIS
-# . funcs.sh
-#
-# is_wordmatch requires perl.
-#
-# DESCRIPTION
-# Funcs.sh is a collection of somewhat related functions.
-# The main categories and their respective functions are:
-# Controlled execution - safe, safe_eval
-# Exiting with a message - die, rawdie, syndie
-# Printing messages - msg, errmsg, rawmsg, rawerrmsg
-# Tracing - trace, errtrace
-# Pattern matching - is_wordmatch
-#
-#
-# ENVIRONMENT
-# These variables are not exported, but they are still visible
-# to, and used by, these functions.
-#
-# progname basename of $0
-# verbose empty or non-emtpy, used for tracing
-# synopsis string describing the syntax of $progname
-#
-# VERSION
-# 2.0
-#
-# AUTHOR
-# Jonas Mvlsd
-# Jonas Oreland - added abspath
-
-
-
-
-
-# Safely executes the given command and exits
-# with the given commands exit code if != 0,
-# else the return value ("the functions exit
-# code") is 0. Eg: safely cd $install_dir
-#
-safely ()
-{
- "$@"
- safely_code__=$?
- [ $safely_code__ -ne 0 ] &&
- { errmsg "Command failed: $@. Exit code: $safely_code__.";
- exit $safely_code__; }
-
- : # return "exit code" 0 from function
-}
-
-
-
-
-# Safely_eval executes "eval command" and exits
-# with the given commands exit code if != 0,
-# else the return value (the functions "exit
-# code") is 0.
-#
-# Safely_eval is just like like safely, but safely_eval does
-# "eval command" instead of just "command"
-#
-# Safely_eval even works with pipes etc., but you have to quote
-# the special characters. Eg: safely_eval ls \| wc \> tst.txt 2\>\&1
-#
-#
-safely_eval ()
-{
- eval "$@"
- safely_eval_code__=$?
- [ $safely_eval_code__ -ne 0 ] &&
- { errmsg "Command failed: $@. Exit code: $safely_eval_code__.";
- exit $safely_eval_code__; }
-
- : # return "exit code" 0 from function
-}
-
-
-
-
-
-
-#
-# safe and safe_eval are deprecated, use safely and safely_eval instead
-#
-
-# Safe executes the given command and exits
-# with the given commands exit code if != 0,
-# else the return value ("the functions exit
-# code") is 0.
-#
-safe ()
-{
- "$@"
- safe_code__=$?
- [ $safe_code__ -ne 0 ] &&
- { errmsg "Command failed: $@. Exit code: $safe_code__.";
- exit $safe_code__; }
-
- : # return "exit code" 0 from function
-}
-
-
-
-
-# Safe_eval executes "eval command" and exits
-# with the given commands exit code if != 0,
-# else the return value (the functions "exit
-# code") is 0.
-#
-# Safe_eval is just like like safe, but safe_eval does
-# "eval command" instead of just "command"
-#
-# Safe_eval even works with pipes etc., but you have to quote
-# the special characters. Eg: safe_eval ls \| wc \> tst.txt 2\>\&1
-#
-#
-safe_eval ()
-{
- eval "$@"
- safe_eval_code__=$?
- [ $safe_eval_code__ -ne 0 ] &&
- { errmsg "Command failed: $@. Exit code: $safe_eval_code__.";
- exit $safe_eval_code__; }
-
- : # return "exit code" 0 from function
-}
-
-
-
-
-
-
-# die prints the supplied message to stderr,
-# prefixed with the program name, and exits
-# with the exit code given by "-e num" or
-# 1, if no -e option is present.
-#
-die ()
-{
- die_code__=1
- [ "X$1" = X-e ] && { die_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- errmsg "$@"
- exit $die_code__
-}
-
-
-
-# rawdie prints the supplied message to stderr.
-# It then exits with the exit code given with "-e num"
-# or 1, if no -e option is present.
-#
-rawdie ()
-{
- rawdie_code__=1
- [ "X$1" = X-e ] && { rawdie_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- rawerrmsg "$@"
- exit $rawdie_code__
-}
-
-
-
-
-# Syndie prints the supplied message (if present) to stderr,
-# prefixed with the program name, on the first line.
-# On the second line, it prints $synopsis.
-# It then exits with the exit code given with "-e num"
-# or 1, if no -e option is present.
-#
-syndie ()
-{
- syndie_code__=1
- [ "X$1" = X-e ] && { syndie_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- [ -n "$*" ] && msg "$*"
- rawdie -e $syndie_code__ "Synopsis: $synopsis"
-}
-
-
-
-
-# msg prints the supplied message to stdout,
-# prefixed with the program name.
-#
-msg ()
-{
- echo "${progname:-<no program name set>}:" "$@"
-}
-
-
-
-# msg prints the supplied message to stderr,
-# prefixed with the program name.
-#
-errmsg ()
-{
- echo "${progname:-<no program name set>}:" "$@" >&2
-}
-
-
-
-rawmsg () { echo "$*"; } # print the supplied message to stdout
-rawerrmsg () { echo "$*" >&2; } # print the supplied message to stderr
-
-
-
-# trace prints the supplied message to stdout if verbose is non-null
-#
-trace ()
-{
- [ -n "$verbose" ] && msg "$@"
-}
-
-
-# errtrace prints the supplied message to stderr if verbose is non-null
-#
-errtrace ()
-{
- [ -n "$verbose" ] && msg "$@" >&2
-}
-
-
-
-# SYNTAX
-# is_wordmatch candidatelist wordlist
-#
-# DESCRIPTION
-# is_wordmatch returns true if any of the words (candidates)
-# in candidatelist is present in wordlist, otherwise it
-# returns false.
-#
-# EXAMPLES
-# is_wordmatch "tuareg nixdorf low content" "xx yy zz low fgj turn roff sd"
-# returns true, since "low" in candidatelist is present in wordlist.
-#
-# is_wordmatch "tuareg nixdorf low content" "xx yy zz slow fgj turn roff sd"
-# returns false, since none of the words in candidatelist occurs in wordlist.
-#
-# is_wordmatch "tuareg nixdorf low content" "xx yy zz low fgj tuareg roff"
-# returns true, since "low" and "tuareg" in candidatelist occurs in wordlist.
-#
-is_wordmatch ()
-{
- is_wordmatch_pattern__=`echo $1 |
- sed 's/^/\\\\b/;
- s/[ ][ ]*/\\\\b|\\\\b/g;
- s/$/\\\\b/;'`
- shift
- echo "$*" |
- perl -lne "m/$is_wordmatch_pattern__/ || exit 1"
-}
-
-#
-# abspath
-#
-# Stolen from http://oase-shareware.org/shell/shelltips/script_programmer.html
-#
-abspath()
-{
- __abspath_D=`dirname "$1"`
- __abspath_B=`basename "$1"`
- echo "`cd \"$__abspath_D\" 2>/dev/null && pwd || echo \"$__abspath_D\"`/$__abspath_B"
-}
-
-#
-#
-# NdbExit
-#
-#
-NdbExit()
-{
- echo "NdbExit: $1"
- exit $1
-}
-
-NdbGetExitCode()
-{
- __res__=`echo $* | awk '{if($1=="NdbExit:") print $2;}'`
- if [ -n $__res__ ]
- then
- echo $__res__
- else
- echo 255
- fi
-}
-
diff --git a/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp b/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp
index 7cf275b1f9e..c1dbc95380c 100644
--- a/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp
+++ b/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp
@@ -150,6 +150,7 @@ struct DropFileRef {
enum ErrorCode {
NoError = 0,
Busy = 701,
+ NotMaster = 702,
NoSuchFile = 766,
DropUndoFileNotSupported = 769,
InvalidSchemaObjectVersion = 774
diff --git a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
index a37f3811b25..0dbc4094e67 100644
--- a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
+++ b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
@@ -39,6 +39,7 @@ class TcKeyReq {
friend class NdbOperation;
friend class NdbIndexOperation;
friend class NdbScanOperation;
+ friend class NdbBlob;
friend class DbUtil;
/**
diff --git a/storage/ndb/include/mgmapi/mgmapi.h b/storage/ndb/include/mgmapi/mgmapi.h
index 75cdf60f91c..5a0ffcfe2c6 100644
--- a/storage/ndb/include/mgmapi/mgmapi.h
+++ b/storage/ndb/include/mgmapi/mgmapi.h
@@ -231,6 +231,12 @@ extern "C" {
/** Could not connect to socker */
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
+ /* Alloc node id failures */
+ /** Generic error, retry may succeed */
+ NDB_MGM_ALLOCID_ERROR = 1101,
+ /** Non retriable error */
+ NDB_MGM_ALLOCID_CONFIG_MISMATCH = 1102,
+
/* Service errors - Start/Stop Node or System */
/** Start failed */
NDB_MGM_START_FAILED = 2001,
@@ -843,16 +849,6 @@ extern "C" {
enum ndb_mgm_event_category category,
int level,
struct ndb_mgm_reply* reply);
-
- /**
- * Returns the port number where statistics information is sent
- *
- * @param handle NDB management handle.
- * @param reply Reply message.
- * @return -1 on error.
- */
- int ndb_mgm_get_stat_port(NdbMgmHandle handle,
- struct ndb_mgm_reply* reply);
#endif
/**
@@ -998,7 +994,7 @@ extern "C" {
void ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *);
int ndb_mgm_alloc_nodeid(NdbMgmHandle handle,
- unsigned version, int nodetype);
+ unsigned version, int nodetype, int log_event);
/**
* End Session
diff --git a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
index 938706db331..78d34b31bbb 100644
--- a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
+++ b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
@@ -64,6 +64,7 @@
#define CFG_DB_BACKUP_DATA_BUFFER_MEM 134
#define CFG_DB_BACKUP_LOG_BUFFER_MEM 135
#define CFG_DB_BACKUP_WRITE_SIZE 136
+#define CFG_DB_BACKUP_MAX_WRITE_SIZE 139
#define CFG_LOG_DESTINATION 147
diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp
index 90dca1c3fc6..42043fbb93a 100644
--- a/storage/ndb/include/ndbapi/Ndb.hpp
+++ b/storage/ndb/include/ndbapi/Ndb.hpp
@@ -986,6 +986,7 @@ class NdbBlob;
class NdbReceiver;
class TransporterFacade;
class PollGuard;
+class Ndb_local_table_info;
template <class T> struct Ndb_free_list_t;
typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
@@ -1262,6 +1263,7 @@ public:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ int flushIncompleteEvents(Uint64 gci);
NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
Uint64 getLatestGCI();
void forceGCP();
@@ -1462,33 +1464,58 @@ public:
/**
* Return a unique tuple id for a table. The id sequence is
- * ascending but may contain gaps.
+ * ascending but may contain gaps. Methods which have no
+ * TupleIdRange argument use NDB API dict cache. They may
+ * not be called from mysqld.
*
* @param aTableName table name
*
* @param cacheSize number of values to cache in this Ndb object
*
- * @return tuple id or 0 on error
+ * @return 0 or -1 on error, and tupleId in out parameter
*/
- Uint64 getAutoIncrementValue(const char* aTableName,
- Uint32 cacheSize = 1);
- Uint64 getAutoIncrementValue(const NdbDictionary::Table * aTable,
- Uint32 cacheSize = 1);
- Uint64 readAutoIncrementValue(const char* aTableName);
- Uint64 readAutoIncrementValue(const NdbDictionary::Table * aTable);
- bool setAutoIncrementValue(const char* aTableName, Uint64 val,
- bool increase = false);
- bool setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val,
- bool increase = false);
- Uint64 getTupleIdFromNdb(const char* aTableName,
- Uint32 cacheSize = 1000);
- Uint64 getTupleIdFromNdb(Uint32 aTableId,
- Uint32 cacheSize = 1000);
- Uint64 readTupleIdFromNdb(Uint32 aTableId);
- bool setTupleIdInNdb(const char* aTableName, Uint64 val,
- bool increase);
- bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase);
- Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op);
+ struct TupleIdRange {
+ Uint64 m_first_tuple_id;
+ Uint64 m_last_tuple_id;
+ void reset() {
+ m_first_tuple_id = ~(Uint64)0;
+ m_last_tuple_id = ~(Uint64)0;
+ };
+ };
+
+ int initAutoIncrement();
+
+ int getAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId, Uint32 cacheSize);
+ int getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId, Uint32 cacheSize);
+ int getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId,
+ Uint32 cacheSize);
+ int readAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId);
+ int readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId);
+ int readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId);
+ int setAutoIncrementValue(const char* aTableName,
+ Uint64 tupleId, bool increase);
+ int setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 tupleId, bool increase);
+ int setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 tupleId,
+ bool increase);
+private:
+ int getTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId,
+ Uint32 cacheSize);
+ int readTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId);
+ int setTupleIdInNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 tupleId, bool increase);
+ int opTupleIdOnNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & opValue, Uint32 op);
+public:
/**
*/
@@ -1691,11 +1718,8 @@ private:
Uint64 the_last_check_time;
Uint64 theFirstTransId;
-
- // The tupleId is retreived from DB the
- // tupleId is unique for each tableid.
- Uint64 theFirstTupleId[2048];
- Uint64 theLastTupleId[2048];
+ // The tupleId is retrieved from DB
+ const NdbDictionary::Table *m_sys_tab_0;
Uint32 theRestartGCI; // the Restart GCI used by DIHNDBTAMPER
diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp
index 13bbfa59e50..089b70339de 100644
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp
@@ -326,6 +326,7 @@ private:
bool isWriteOp();
bool isDeleteOp();
bool isScanOp();
+ bool isTakeOverOp();
// computations
Uint32 getPartNumber(Uint64 pos);
Uint32 getPartCount();
diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp
index 28e238d6049..865fb506f05 100644
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp
@@ -798,6 +798,7 @@ public:
* Get object status
*/
virtual Object::Status getObjectStatus() const;
+ void setStatusInvalid() const;
/**
* Get object version
@@ -1131,7 +1132,8 @@ public:
_TE_NODE_FAILURE=10,
_TE_SUBSCRIBE=11,
_TE_UNSUBSCRIBE=12,
- _TE_NUL=13 // internal (e.g. INS o DEL within same GCI)
+ _TE_NUL=13, // internal (e.g. INS o DEL within same GCI)
+ _TE_ACTIVE=14 // internal (node becomes active)
};
#endif
/**
@@ -1734,6 +1736,7 @@ public:
* @return 0 if successful otherwise -1.
*/
int createIndex(const Index &index);
+ int createIndex(const Index &index, const Table &table);
/**
* Drop index with given name
@@ -1745,11 +1748,15 @@ public:
const char * tableName);
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void removeCachedTable(const Table *table);
+ void removeCachedIndex(const Index *index);
+ void invalidateTable(const Table *table);
/**
* Invalidate cached index object
*/
void invalidateIndex(const char * indexName,
const char * tableName);
+ void invalidateIndex(const Index *index);
/**
* Force gcp and wait for gcp complete
*/
@@ -1801,6 +1808,15 @@ public:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const Table * getTable(const char * name, void **data) const;
void set_local_table_data_size(unsigned sz);
+
+ const Index * getIndexGlobal(const char * indexName,
+ const Table &ndbtab) const;
+ const Table * getTableGlobal(const char * tableName) const;
+ int alterTableGlobal(const Table &f, const Table &t);
+ int dropTableGlobal(const Table &ndbtab);
+ int dropIndexGlobal(const Index &index);
+ int removeIndexGlobal(const Index &ndbidx, int invalidate) const;
+ int removeTableGlobal(const Table &ndbtab, int invalidate) const;
#endif
};
};
diff --git a/storage/ndb/include/ndbapi/NdbIndexStat.hpp b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
index c718d175864..ddd27ed24d4 100644
--- a/storage/ndb/include/ndbapi/NdbIndexStat.hpp
+++ b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
@@ -56,7 +56,7 @@ public:
* multiplied by a percentage obtained from the cache (result zero is
* returned as 1).
*/
- int records_in_range(NdbDictionary::Index* index,
+ int records_in_range(const NdbDictionary::Index* index,
NdbIndexScanOperation* op,
Uint64 table_rows,
Uint64* count,
diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp
index e747dedb84b..d64e86c3136 100644
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp
@@ -636,6 +636,10 @@ public:
bool nopad, Uint32 Label);
int branch_col_ge(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
+ /**
+ * The argument is always plain char, even if the field is varchar
+ * (changed in 5.0.22).
+ */
int branch_col_like(Uint32 ColId, const void *, Uint32 len,
bool nopad, Uint32 Label);
int branch_col_notlike(Uint32 ColId, const void *, Uint32 len,
diff --git a/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp b/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
index 01c700d14b2..a803d010e61 100644
--- a/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
+++ b/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
@@ -110,6 +110,7 @@ public:
unsigned no_db_nodes();
unsigned node_id();
+ unsigned get_connect_count() const;
void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
unsigned int get_next_node(Ndb_cluster_connection_node_iter &iter);
diff --git a/storage/ndb/include/util/NdbSqlUtil.hpp b/storage/ndb/include/util/NdbSqlUtil.hpp
index 36a75136c45..ff2d9766f81 100644
--- a/storage/ndb/include/util/NdbSqlUtil.hpp
+++ b/storage/ndb/include/util/NdbSqlUtil.hpp
@@ -45,14 +45,11 @@ public:
typedef int Cmp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full);
/**
- * 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.
+ * Prototype for "like" comparison. Defined for string types. First
+ * argument can be fixed or var* type, second argument is fixed.
+ * Returns 0 on match, +1 on no match, and -1 on bad data.
*
* Uses default special chars ( \ % _ ).
- *
- * TODO convert special chars to the cs so that ucs2 etc works
- * TODO allow user-defined escape ( \ )
*/
typedef int Like(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2);
diff --git a/storage/ndb/include/util/SocketServer.hpp b/storage/ndb/include/util/SocketServer.hpp
index e131b78baa1..c4f7e8c0ade 100644
--- a/storage/ndb/include/util/SocketServer.hpp
+++ b/storage/ndb/include/util/SocketServer.hpp
@@ -75,7 +75,7 @@ public:
/**
* Constructor / Destructor
*/
- SocketServer(int maxSessions = 32);
+ SocketServer(unsigned maxSessions = ~(unsigned)0);
~SocketServer();
/**
@@ -106,7 +106,8 @@ public:
void stopSessions(bool wait = false);
void foreachSession(void (*f)(Session*, void*), void *data);
-
+ void checkSessions();
+
private:
struct SessionInstance {
Service * m_service;
@@ -117,12 +118,13 @@ private:
Service * m_service;
NDB_SOCKET_TYPE m_socket;
};
- MutexVector<SessionInstance> m_sessions;
+ NdbLockable m_session_mutex;
+ Vector<SessionInstance> m_sessions;
MutexVector<ServiceInstance> m_services;
unsigned m_maxSessions;
void doAccept();
- void checkSessions();
+ void checkSessionsImpl();
void startSession(SessionInstance &);
/**
diff --git a/storage/ndb/include/util/ndb_opts.h b/storage/ndb/include/util/ndb_opts.h
index 787c32f06fd..08ab4a2e9df 100644
--- a/storage/ndb/include/util/ndb_opts.h
+++ b/storage/ndb/include/util/ndb_opts.h
@@ -84,7 +84,10 @@ const char *opt_debug= 0;
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}
+ GET_BOOL, NO_ARG, OPT_WANT_CORE_DEFAULT, 0, 0, 0, 0, 0},\
+ {"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
#define NDB_STD_OPTS(prog_name) \
@@ -111,6 +114,7 @@ enum ndb_std_options {
OPT_WANT_CORE,
OPT_NDB_MGMD,
OPT_NDB_NODEID,
+ OPT_CHARSETS_DIR,
NDB_STD_OPTIONS_LAST /* should always be last in this enum */
};
diff --git a/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index 97de5c7f83d..e24ed5b8ddc 100644
--- a/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -355,12 +355,14 @@ ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
if(!ndb_mgm_connect(m_handle, 0, 0, 0))
goto next;
- res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
+ res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type,
+ no_retries == 0 /* only log last retry */);
if(res >= 0)
return _ownNodeId= (Uint32)res;
next:
- if (no_retries == 0)
+ int error = ndb_mgm_get_latest_error(m_handle);
+ if (no_retries == 0 || error == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
break;
no_retries--;
NdbSleep_SecSleep(retry_delay_in_seconds);
diff --git a/storage/ndb/src/common/util/NdbSqlUtil.cpp b/storage/ndb/src/common/util/NdbSqlUtil.cpp
index f2506eda6d4..f3d70a5734a 100644
--- a/storage/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/storage/ndb/src/common/util/NdbSqlUtil.cpp
@@ -805,7 +805,9 @@ NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void*
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);
+ // strip end spaces to match (incorrect) MySQL behaviour
+ n1 = (*cs->cset->lengthsp)(cs, v1, n1);
+ 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;
}
@@ -820,16 +822,16 @@ 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) {
+ if (n1 >= 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) {
+ unsigned m2 = n2;
+ if (lb + m1 <= n1) {
const char* w1 = (const char*)v1 + lb;
- const char* w2 = (const char*)v2 + lb;
+ const char* w2 = (const char*)v2;
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);
+ 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;
}
}
@@ -847,16 +849,16 @@ 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) {
+ if (n1 >= 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) {
+ unsigned m2 = n2;
+ if (lb + m1 <= n1) {
const char* w1 = (const char*)v1 + lb;
- const char* w2 = (const char*)v2 + lb;
+ const char* w2 = (const char*)v2;
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);
+ 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;
}
}
diff --git a/storage/ndb/src/common/util/SocketServer.cpp b/storage/ndb/src/common/util/SocketServer.cpp
index 481c656b78b..f9d2c7463be 100644
--- a/storage/ndb/src/common/util/SocketServer.cpp
+++ b/storage/ndb/src/common/util/SocketServer.cpp
@@ -27,7 +27,7 @@
#define DEBUG(x) ndbout << x << endl;
-SocketServer::SocketServer(int maxSessions) :
+SocketServer::SocketServer(unsigned maxSessions) :
m_sessions(10),
m_services(5)
{
@@ -136,7 +136,7 @@ SocketServer::setup(SocketServer::Service * service,
}
DBUG_PRINT("info",("bound to %u",ntohs(servaddr.sin_port)));
- if (listen(sock, m_maxSessions) == -1){
+ if (listen(sock, m_maxSessions > 32 ? 32 : m_maxSessions) == -1){
DBUG_PRINT("error",("listen() - %d - %s",
errno, strerror(errno)));
NDB_CLOSE_SOCKET(sock);
@@ -184,9 +184,12 @@ SocketServer::doAccept(){
SessionInstance s;
s.m_service = si.m_service;
s.m_session = si.m_service->newSession(childSock);
- if(s.m_session != 0){
+ if(s.m_session != 0)
+ {
+ m_session_mutex.lock();
m_sessions.push_back(s);
startSession(m_sessions.back());
+ m_session_mutex.unlock();
}
continue;
@@ -240,10 +243,13 @@ void
SocketServer::doRun(){
while(!m_stopThread){
- checkSessions();
+ m_session_mutex.lock();
+ checkSessionsImpl();
if(m_sessions.size() < m_maxSessions){
+ m_session_mutex.unlock();
doAccept();
} else {
+ m_session_mutex.unlock();
NdbSleep_MilliSleep(200);
}
}
@@ -276,17 +282,30 @@ transfer(NDB_SOCKET_TYPE sock){
void
SocketServer::foreachSession(void (*func)(SocketServer::Session*, void *), void *data)
{
+ m_session_mutex.lock();
for(int i = m_sessions.size() - 1; i >= 0; i--){
(*func)(m_sessions[i].m_session, data);
}
- checkSessions();
+ m_session_mutex.unlock();
}
void
-SocketServer::checkSessions(){
- for(int i = m_sessions.size() - 1; i >= 0; i--){
- if(m_sessions[i].m_session->m_stopped){
- if(m_sessions[i].m_thread != 0){
+SocketServer::checkSessions()
+{
+ m_session_mutex.lock();
+ checkSessionsImpl();
+ m_session_mutex.unlock();
+}
+
+void
+SocketServer::checkSessionsImpl()
+{
+ for(int i = m_sessions.size() - 1; i >= 0; i--)
+ {
+ if(m_sessions[i].m_session->m_stopped)
+ {
+ if(m_sessions[i].m_thread != 0)
+ {
void* ret;
NdbThread_WaitFor(m_sessions[i].m_thread, &ret);
NdbThread_Destroy(&m_sessions[i].m_thread);
@@ -301,19 +320,26 @@ SocketServer::checkSessions(){
void
SocketServer::stopSessions(bool wait){
int i;
+ m_session_mutex.lock();
for(i = m_sessions.size() - 1; i>=0; i--)
{
m_sessions[i].m_session->stopSession();
m_sessions[i].m_session->m_stop = true; // to make sure
}
+ m_session_mutex.unlock();
+
for(i = m_services.size() - 1; i>=0; i--)
m_services[i].m_service->stopSessions();
if(wait){
+ m_session_mutex.lock();
while(m_sessions.size() > 0){
- checkSessions();
+ checkSessionsImpl();
+ m_session_mutex.unlock();
NdbSleep_MilliSleep(100);
+ m_session_mutex.lock();
}
+ m_session_mutex.unlock();
}
}
@@ -348,4 +374,4 @@ sessionThread_C(void* _sc){
}
template class MutexVector<SocketServer::ServiceInstance>;
-template class MutexVector<SocketServer::SessionInstance>;
+template class Vector<SocketServer::SessionInstance>;
diff --git a/storage/ndb/src/common/util/socket_io.cpp b/storage/ndb/src/common/util/socket_io.cpp
index 83a546de773..58636e6663d 100644
--- a/storage/ndb/src/common/util/socket_io.cpp
+++ b/storage/ndb/src/common/util/socket_io.cpp
@@ -48,58 +48,66 @@ read_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
extern "C"
int
-readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
+readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
char * buf, int buflen){
if(buflen <= 1)
return 0;
+ int sock_flags= fcntl(socket, F_GETFL);
+ if(fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1)
+ return -1;
+
fd_set readset;
FD_ZERO(&readset);
FD_SET(socket, &readset);
-
+
struct timeval timeout;
timeout.tv_sec = (timeout_millis / 1000);
timeout.tv_usec = (timeout_millis % 1000) * 1000;
const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
- if(selectRes == 0)
+ if(selectRes == 0){
return 0;
-
+ }
+
if(selectRes == -1){
+ fcntl(socket, F_SETFL, sock_flags);
return -1;
}
-
- int pos = 0; buf[pos] = 0;
- while(true){
- const int t = recv(socket, &buf[pos], 1, 0);
- if(t != 1){
- return -1;
- }
- if(buf[pos] == '\n'){
- buf[pos] = 0;
- if(pos > 0 && buf[pos-1] == '\r'){
- pos--;
- buf[pos] = 0;
+ buf[0] = 0;
+ const int t = recv(socket, buf, buflen, MSG_PEEK);
+
+ if(t < 1)
+ {
+ fcntl(socket, F_SETFL, sock_flags);
+ return -1;
+ }
+
+ for(int i=0; i< t;i++)
+ {
+ if(buf[i] == '\n'){
+ recv(socket, buf, i+1, 0);
+ buf[i] = 0;
+
+ if(i > 0 && buf[i-1] == '\r'){
+ i--;
+ buf[i] = 0;
}
- return pos;
- }
- pos++;
- if(pos == (buflen - 1)){
- buf[pos] = 0;
- return buflen;
- }
-
- FD_ZERO(&readset);
- FD_SET(socket, &readset);
- timeout.tv_sec = (timeout_millis / 1000);
- timeout.tv_usec = (timeout_millis % 1000) * 1000;
- const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
- if(selectRes != 1){
- return -1;
+ fcntl(socket, F_SETFL, sock_flags);
+ return t;
}
}
+
+ if(t == (buflen - 1)){
+ recv(socket, buf, t, 0);
+ buf[t] = 0;
+ fcntl(socket, F_SETFL, sock_flags);
+ return buflen;
+ }
+
+ return 0;
}
extern "C"
diff --git a/storage/ndb/src/kernel/SimBlockList.cpp b/storage/ndb/src/kernel/SimBlockList.cpp
index 00ec5e4b006..ef9897a77ea 100644
--- a/storage/ndb/src/kernel/SimBlockList.cpp
+++ b/storage/ndb/src/kernel/SimBlockList.cpp
@@ -120,8 +120,12 @@ SimBlockList::unload(){
if(theList != 0){
for(int i = 0; i<noOfBlocks; i++){
if(theList[i] != 0){
+#ifdef VM_TRACE
theList[i]->~SimulatedBlock();
free(theList[i]);
+#else
+ delete(theList[i]);
+#endif
theList[i] = 0;
}
}
diff --git a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
index 92680a5b6c9..9fa5800c120 100644
--- a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
+++ b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
@@ -144,6 +144,17 @@ struct BackupFormat {
// If TriggerEvent & 0x10000 == true then GCI is right after data
Uint32 TriggerEvent;
Uint32 FragId;
+ Uint32 Data[1]; // Len = Length - 3
+ };
+
+ /**
+ * Log Entry pre NDBD_FRAGID_VERSION
+ */
+ struct LogEntry_no_fragid {
+ Uint32 Length;
+ Uint32 TableId;
+ // If TriggerEvent & 0x10000 == true then GCI is right after data
+ Uint32 TriggerEvent;
Uint32 Data[1]; // Len = Length - 2
};
};
diff --git a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
index b22cd51e61d..5f49a1a8725 100644
--- a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -163,15 +163,16 @@ Backup::execREAD_CONFIG_REQ(Signal* signal)
Uint32 szDataBuf = (2 * 1024 * 1024);
Uint32 szLogBuf = (2 * 1024 * 1024);
- Uint32 szWrite = 32768;
+ Uint32 szWrite = 32768, maxWriteSize = (256 * 1024);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MAX_WRITE_SIZE, &maxWriteSize);
c_defaults.m_logBufferSize = szLogBuf;
c_defaults.m_dataBufferSize = szDataBuf;
c_defaults.m_minWriteSize = szWrite;
- c_defaults.m_maxWriteSize = szWrite;
+ c_defaults.m_maxWriteSize = maxWriteSize;
c_defaults.m_lcp_buffer_size = szDataBuf;
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 87bd1d7c53b..ef08c06822f 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -472,6 +472,8 @@ Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
Uint16 *data = (Uint16*)&signal->theData[25];
Uint32 count = 2 + data[0] * data[1];
w.add(DictTabInfo::ReplicaDataLen, 2*count);
+ for (Uint32 i = 0; i < count; i++)
+ data[i] = htons(data[i]);
w.add(DictTabInfo::ReplicaData, data, 2*count);
}
else
@@ -13396,6 +13398,24 @@ Dbdict::execCREATE_FILE_REQ(Signal* signal){
Uint32 requestInfo = req->requestInfo;
do {
+ if(getOwnNodeId() != c_masterNodeId){
+ jam();
+ ref->errorCode = CreateFileRef::NotMaster;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ if (c_blockState != BS_IDLE){
+ jam();
+ ref->errorCode = CreateFileRef::Busy;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
Ptr<SchemaTransaction> trans_ptr;
if (! c_Trans.seize(trans_ptr)){
ref->errorCode = CreateFileRef::Busy;
@@ -13455,6 +13475,9 @@ Dbdict::execCREATE_FILE_REQ(Signal* signal){
tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
CreateObjReq::SignalLength, JBB);
+
+ c_blockState = BS_CREATE_TAB;
+
return;
} while(0);
@@ -13480,15 +13503,6 @@ Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal){
Uint32 type = req->objType;
do {
- Ptr<SchemaTransaction> trans_ptr;
- if (! c_Trans.seize(trans_ptr)){
- ref->errorCode = CreateFilegroupRef::Busy;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
if(getOwnNodeId() != c_masterNodeId){
jam();
ref->errorCode = CreateFilegroupRef::NotMaster;
@@ -13506,6 +13520,15 @@ Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal){
ref->errorLine = __LINE__;
break;
}
+
+ Ptr<SchemaTransaction> trans_ptr;
+ if (! c_Trans.seize(trans_ptr)){
+ ref->errorCode = CreateFilegroupRef::Busy;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
const Uint32 trans_key = ++c_opRecordSequence;
trans_ptr.p->key = trans_key;
@@ -13554,6 +13577,9 @@ Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal){
tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
CreateObjReq::SignalLength, JBB);
+
+ c_blockState = BS_CREATE_TAB;
+
return;
} while(0);
@@ -13581,6 +13607,22 @@ Dbdict::execDROP_FILE_REQ(Signal* signal)
Uint32 version = req->file_version;
do {
+ if(getOwnNodeId() != c_masterNodeId){
+ jam();
+ ref->errorCode = DropFileRef::NotMaster;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ if (c_blockState != BS_IDLE){
+ jam();
+ ref->errorCode = DropFileRef::Busy;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
Ptr<File> file_ptr;
if (!c_file_hash.find(file_ptr, objId))
{
@@ -13636,6 +13678,9 @@ Dbdict::execDROP_FILE_REQ(Signal* signal)
tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
DropObjReq::SignalLength, JBB);
+
+ c_blockState = BS_CREATE_TAB;
+
return;
} while(0);
@@ -13663,6 +13708,22 @@ Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
Uint32 version = req->filegroup_version;
do {
+ if(getOwnNodeId() != c_masterNodeId){
+ jam();
+ ref->errorCode = DropFilegroupRef::NotMaster;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ if (c_blockState != BS_IDLE){
+ jam();
+ ref->errorCode = DropFilegroupRef::Busy;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
Ptr<Filegroup> filegroup_ptr;
if (!c_filegroup_hash.find(filegroup_ptr, objId))
{
@@ -13718,6 +13779,9 @@ Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
DropObjReq::SignalLength, JBB);
+
+ c_blockState = BS_CREATE_TAB;
+
return;
} while(0);
@@ -13892,6 +13956,7 @@ Dbdict::trans_commit_complete_done(Signal* signal,
//@todo check api failed
sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILEGROUP_CONF, signal,
CreateFilegroupConf::SignalLength, JBB);
+
break;
}
case GSN_CREATE_FILE_REQ:{
@@ -13935,6 +14000,7 @@ Dbdict::trans_commit_complete_done(Signal* signal,
}
c_Trans.release(trans_ptr);
+ ndbrequire(c_blockState == BS_CREATE_TAB);
c_blockState = BS_IDLE;
return;
}
@@ -14047,6 +14113,7 @@ Dbdict::trans_abort_complete_done(Signal* signal,
}
c_Trans.release(trans_ptr);
+ ndbrequire(c_blockState == BS_CREATE_TAB);
c_blockState = BS_IDLE;
return;
}
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 69db36c8517..d031f9a00bf 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -1394,6 +1394,7 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
if (! DictTabInfo::isOrderedIndex(addfragptr.p->tableType))
{
fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
+ //fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
}
else
@@ -2470,6 +2471,8 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
jamEntry();
tcConnectptr.i = tcIndex;
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
+ TcConnectionrec * regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
FragrecordPtr regFragptr;
regFragptr.i = tcConnectptr.p->fragmentptr;
@@ -2497,6 +2500,32 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
// Abort was not ready to start until this signal came back. Now we are ready
// to start the abort.
/* ------------------------------------------------------------------------- */
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ * even for before writing log...(as it's simpler)
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+ return;
+ }
+ }
+
abortCommonLab(signal);
break;
case TcConnectionrec::WAIT_ACC_ABORT:
@@ -2523,13 +2552,23 @@ void Dblqh::execTUPKEYREF(Signal* signal)
tcConnectptr.i = tupKeyRef->userRef;
terrorCode = tupKeyRef->errorCode;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+ TcConnectionrec* regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
FragrecordPtr regFragptr;
- regFragptr.i = tcConnectptr.p->fragmentptr;
+ regFragptr.i = regTcPtr->fragmentptr;
c_fragment_pool.getPtr(regFragptr);
fragptr = regFragptr;
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ ndbassert(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP ||
+ regTcPtr->transactionState ==TcConnectionrec::WAIT_TUP_TO_ABORT);
+ }
- TcConnectionrec* regTcPtr = tcConnectptr.p;
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
@@ -3767,7 +3806,7 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
jamEntry();
- execACC_ABORTCONF(signal);
+ packLqhkeyreqLab(signal);
}
}
@@ -3890,16 +3929,17 @@ Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
if (TRACENR_FLAG)
TRACENR(" performing DELETE key: "
<< dst[0] << endl);
- regTcPtr.p->tupkeyData[0] = regTcPtr.p->m_row_id.ref();
- if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
- {
- regTcPtr.p->hashValue = calculateHash(tableId, dst);
- }
- else
+
+ nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
+ ndbassert(regTcPtr.p->m_nr_delete.m_cnt);
+ regTcPtr.p->m_nr_delete.m_cnt--; // No real op is run
+ if (regTcPtr.p->m_nr_delete.m_cnt)
{
- regTcPtr.p->hashValue = md5_hash((Uint64*)dst, len);
+ jam();
+ return;
}
- goto run;
+ packLqhkeyreqLab(signal);
+ return;
}
else if (len == 0 && op == ZDELETE)
{
@@ -3993,9 +4033,7 @@ update_gci_ignore:
signal->theData[0] = regTcPtr.p->tupConnectrec;
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
- signal->theData[0] = regTcPtr.i;
- execACC_ABORTCONF(signal);
+ packLqhkeyreqLab(signal);
}
int
@@ -4149,7 +4187,6 @@ Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
op->m_gci = tcPtr.p->gci;
op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
- ndbrequire(tcPtr.p->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
@@ -4194,16 +4231,36 @@ Dblqh::nr_delete_complete(Signal* signal, Nr_op_info* op)
tcPtr.i = op->m_ptr_i;
ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
- ndbrequire(tcPtr.p->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
tcPtr.p->m_nr_delete.m_cnt--;
if (tcPtr.p->m_nr_delete.m_cnt == 0)
{
+ jam();
tcConnectptr = tcPtr;
c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
- packLqhkeyreqLab(signal);
+
+ if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
+ {
+ jam();
+ tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
+ abortCommonLab(signal);
+ }
+ else if (tcPtr.p->operation == ZDELETE &&
+ LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
+ {
+ /**
+ * This is run directly in handle_nr_copy
+ */
+ jam();
+ packLqhkeyreqLab(signal);
+ }
+ else
+ {
+ jam();
+ rwConcludedLab(signal);
+ }
return;
}
@@ -4319,7 +4376,6 @@ void Dblqh::execACCKEYCONF(Signal* signal)
return;
}//if
- // reset the activeCreat since that is only valid in cases where the record was not present.
/* ------------------------------------------------------------------------
* IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
* INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
@@ -4536,6 +4592,7 @@ Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
}
else
{
+ regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
ref->userRef= regTcPtr.i;
ref->errorCode= ~0;
@@ -4571,6 +4628,7 @@ Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
}
else
{
+ regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
ref->userRef= callbackData;
ref->errorCode= disk_page;
@@ -4592,9 +4650,11 @@ Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
* -------------------------------------------------------------------------- */
void Dblqh::tupkeyConfLab(Signal* signal)
{
-/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED ---- */
+/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED --- */
const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
+
if (regTcPtr->simpleRead) {
jam();
/* ----------------------------------------------------------------------
@@ -4616,6 +4676,34 @@ void Dblqh::tupkeyConfLab(Signal* signal)
}//if
regTcPtr->totSendlenAi = tupKeyConf->writeLength;
ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ * even for before writing log...(as it's simpler)
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+
+ return;
+ }
+ }
+
rwConcludedLab(signal);
return;
}//Dblqh::tupkeyConfLab()
@@ -5016,12 +5104,13 @@ void Dblqh::packLqhkeyreqLab(Signal* signal)
Uint32 nextNodeId = regTcPtr->nextReplica;
Uint32 nextVersion = getNodeInfo(nextNodeId).m_version;
+ UintR TAiLen = regTcPtr->reclenAiLqhkey;
UintR TapplAddressIndicator = (regTcPtr->nextSeqNoReplica == 0 ? 0 : 1);
LqhKeyReq::setApplicationAddressFlag(Treqinfo, TapplAddressIndicator);
LqhKeyReq::setInterpretedFlag(Treqinfo, regTcPtr->opExec);
LqhKeyReq::setSeqNoReplica(Treqinfo, regTcPtr->nextSeqNoReplica);
- LqhKeyReq::setAIInLqhKeyReq(Treqinfo, regTcPtr->reclenAiLqhkey);
+ LqhKeyReq::setAIInLqhKeyReq(Treqinfo, TAiLen);
if (unlikely(nextVersion < NDBD_ROWID_VERSION))
{
@@ -5124,22 +5213,32 @@ void Dblqh::packLqhkeyreqLab(Signal* signal)
lqhKeyReq->variableData[nextPos + 0] = sig0;
nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
- sig0 = regTcPtr->firstAttrinfo[0];
- sig1 = regTcPtr->firstAttrinfo[1];
- sig2 = regTcPtr->firstAttrinfo[2];
- sig3 = regTcPtr->firstAttrinfo[3];
- sig4 = regTcPtr->firstAttrinfo[4];
- UintR TAiLen = regTcPtr->reclenAiLqhkey;
BlockReference lqhRef = calcLqhBlockRef(regTcPtr->nextReplica);
+
+ if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
+ {
+ jam();
+ sig0 = regTcPtr->firstAttrinfo[0];
+ sig1 = regTcPtr->firstAttrinfo[1];
+ sig2 = regTcPtr->firstAttrinfo[2];
+ sig3 = regTcPtr->firstAttrinfo[3];
+ sig4 = regTcPtr->firstAttrinfo[4];
- lqhKeyReq->variableData[nextPos] = sig0;
- lqhKeyReq->variableData[nextPos + 1] = sig1;
- lqhKeyReq->variableData[nextPos + 2] = sig2;
- lqhKeyReq->variableData[nextPos + 3] = sig3;
- lqhKeyReq->variableData[nextPos + 4] = sig4;
-
- nextPos += TAiLen;
-
+ lqhKeyReq->variableData[nextPos] = sig0;
+ lqhKeyReq->variableData[nextPos + 1] = sig1;
+ lqhKeyReq->variableData[nextPos + 2] = sig2;
+ lqhKeyReq->variableData[nextPos + 3] = sig3;
+ lqhKeyReq->variableData[nextPos + 4] = sig4;
+
+ nextPos += TAiLen;
+ TAiLen = 0;
+ }
+ else
+ {
+ Treqinfo &= ~(Uint32)(RI_AI_IN_THIS_MASK << RI_AI_IN_THIS_SHIFT);
+ lqhKeyReq->requestInfo = Treqinfo;
+ }
+
sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
nextPos + LqhKeyReq::FixedSignalLength, JBB);
if (regTcPtr->primKeyLen > 4) {
@@ -5165,6 +5264,17 @@ void Dblqh::packLqhkeyreqLab(Signal* signal)
signal->theData[0] = sig0;
signal->theData[1] = sig1;
signal->theData[2] = sig2;
+
+ if (unlikely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength > 25))
+ {
+ jam();
+ /**
+ * 4 replicas...
+ */
+ memcpy(signal->theData+3, regTcPtr->firstAttrinfo, TAiLen << 2);
+ sendSignal(lqhRef, GSN_ATTRINFO, signal, 3 + TAiLen, JBB);
+ }
+
AttrbufPtr regAttrinbufptr;
regAttrinbufptr.i = regTcPtr->firstAttrinbuf;
while (regAttrinbufptr.i != RNIL) {
@@ -6303,27 +6413,19 @@ Dblqh::tupcommit_conf(Signal* signal,
/*SEND ANY COMMIT OR COMPLETE MESSAGES TO OTHER NODES. THEY WILL MERELY SEND */
/*THOSE SIGNALS INTERNALLY. */
/* ------------------------------------------------------------------------- */
- if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE) {
+ if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE)
+ {
jam();
- if (activeCreat == Fragrecord::AC_NR_COPY &&
- tcPtrP->m_nr_delete.m_cnt > 1)
+ if (activeCreat == Fragrecord::AC_NR_COPY)
{
jam();
- /**
- * Nr delete waiting for disk delete to complete...
- */
-#ifdef VM_TRACE
- TablerecPtr tablePtr;
- tablePtr.i = tcPtrP->tableref;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- ndbrequire(tablePtr.p->m_disk_table);
-#endif
- tcPtrP->m_nr_delete.m_cnt--;
- tcPtrP->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
- return;
+ ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
+ ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
}
packLqhkeyreqLab(signal);
- } else {
+ }
+ else
+ {
ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
jam();
sendLqhTransconf(signal, LqhTransConf::Committed);
@@ -6527,7 +6629,7 @@ void Dblqh::execABORT(Signal* signal)
}//if
TcConnectionrec * const regTcPtr = tcConnectptr.p;
-
+ Uint32 activeCreat = regTcPtr->activeCreat;
if (ERROR_INSERTED(5100))
{
SET_ERROR_INSERT_VALUE(5101);
@@ -6552,10 +6654,10 @@ void Dblqh::execABORT(Signal* signal)
sendSignal(TLqhRef, GSN_ABORT, signal, 4, JBB);
}//if
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if(commitAckMarker != RNIL){
+ if(commitAckMarker != RNIL)
+ {
jam();
#ifdef MARKER_TRACE
{
@@ -6605,6 +6707,7 @@ void Dblqh::execABORTREQ(Signal* signal)
return;
}//if
TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
warningReport(signal, 10);
return;
@@ -6612,7 +6715,7 @@ void Dblqh::execABORTREQ(Signal* signal)
regTcPtr->reqBlockref = reqBlockref;
regTcPtr->reqRef = reqPtr;
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
+
abortCommonLab(signal);
return;
}//Dblqh::execABORTREQ()
@@ -6682,42 +6785,26 @@ void Dblqh::execACCKEYREF(Signal* signal)
}
- if (tcPtr->activeCreat == Fragrecord::AC_NR_COPY)
- {
- jam();
- Uint32 op = tcPtr->operation;
- switch(errCode){
- case ZNO_TUPLE_FOUND:
- ndbrequire(op == ZDELETE);
- break;
- break;
- default:
- ndbrequire(false);
- }
- tcPtr->activeCreat = Fragrecord::AC_IGNORED;
- }
- else
- {
- ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
-
- /**
- * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
- *
- * Unless it's a simple or dirty read
- *
- * NOT TRUE!
- * 1) op1 - primary insert ok
- * 2) op1 - backup insert fail (log full or what ever)
- * 3) op1 - delete ok @ primary
- * 4) op1 - delete fail @ backup
- *
- * -> ZNO_TUPLE_FOUND is possible
- */
- ndbrequire
- (tcPtr->seqNoReplica == 0 ||
- errCode != ZTUPLE_ALREADY_EXIST ||
- (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
- }
+ ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
+ ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
+
+ /**
+ * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
+ *
+ * Unless it's a simple or dirty read
+ *
+ * NOT TRUE!
+ * 1) op1 - primary insert ok
+ * 2) op1 - backup insert fail (log full or what ever)
+ * 3) op1 - delete ok @ primary
+ * 4) op1 - delete fail @ backup
+ *
+ * -> ZNO_TUPLE_FOUND is possible
+ */
+ ndbrequire
+ (tcPtr->seqNoReplica == 0 ||
+ errCode != ZTUPLE_ALREADY_EXIST ||
+ (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
abortCommonLab(signal);
@@ -6731,7 +6818,6 @@ void Dblqh::localAbortStateHandlerLab(Signal* signal)
jam();
return;
}//if
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
regTcPtr->errorCode = terrorCode;
abortStateHandlerLab(signal);
@@ -6907,11 +6993,6 @@ void Dblqh::abortErrorLab(Signal* signal)
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
regTcPtr->errorCode = terrorCode;
}//if
- /* -----------------------------------------------------------------------
- * ACTIVE CREATION IS RESET FOR ALL ERRORS WHICH SHOULD BE HANDLED
- * WITH NORMAL ABORT HANDLING.
- * ----------------------------------------------------------------------- */
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
abortCommonLab(signal);
return;
}//Dblqh::abortErrorLab()
@@ -6920,8 +7001,9 @@ void Dblqh::abortCommonLab(Signal* signal)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if(regTcPtr->activeCreat != Fragrecord::AC_IGNORED &&
- commitAckMarker != RNIL){
+ const Uint32 activeCreat = regTcPtr->activeCreat;
+ if (commitAckMarker != RNIL)
+ {
/**
* There is no NR ongoing and we have a marker
*/
@@ -6936,6 +7018,29 @@ void Dblqh::abortCommonLab(Signal* signal)
m_commitAckMarkerHash.release(commitAckMarker);
regTcPtr->commitAckMarker = RNIL;
}
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+ return;
+ }
+ }
fragptr.i = regTcPtr->fragmentptr;
if (fragptr.i != RNIL) {
@@ -7012,25 +7117,6 @@ void Dblqh::execACC_ABORTCONF(Signal* signal)
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
TcConnectionrec * const regTcPtr = tcConnectptr.p;
ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
- if (regTcPtr->activeCreat == Fragrecord::AC_IGNORED) {
- /* ----------------------------------------------------------------------
- * A NORMAL EVENT DURING CREATION OF A FRAGMENT. WE NOW NEED TO CONTINUE
- * WITH NORMAL COMMIT PROCESSING.
- * --------------------------------------------------------------------- */
- if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) {
- jam();
- regTcPtr->abortState = TcConnectionrec::ABORT_IDLE;
- fragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- rwConcludedLab(signal);
- return;
- } else {
- ndbrequire(regTcPtr->currTupAiLen < regTcPtr->totReclenAi);
- jam();
- regTcPtr->transactionState = TcConnectionrec::WAIT_AI_AFTER_ABORT;
- return;
- }//if
- }//if
continueAbortLab(signal);
return;
}//Dblqh::execACC_ABORTCONF()
@@ -9428,7 +9514,7 @@ void Dblqh::initScanTc(const ScanFragReq* req,
tcConnectptr.p->m_offset_current_keybuf = 0;
tcConnectptr.p->m_scan_curr_range_no = 0;
tcConnectptr.p->m_dealloc = 0;
-
+ tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
TablerecPtr tTablePtr;
tTablePtr.i = tabptr.p->primaryTableId;
ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
@@ -9907,16 +9993,21 @@ void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
*/
fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
- if (0)
+ scanptr.i = tcConnectptr.p->tcScanRec;
+ c_scanRecordPool.getPtr(scanptr);
+
+ if (false && fragptr.p->tabRef > 4)
{
- ndbout_c("STOPPING COPY (%d -> %d %d %d)",
- scanptr.p->scanBlockref,
+ ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
+ refToBlock(scanptr.p->scanBlockref),
scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
+
+ /**
+ * RESTART: > DUMP 7020 332 X
+ */
return;
}
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_NEXT;
@@ -18329,6 +18420,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
<< " tcBlockref = " << hex << tcRec.p->tcBlockref
<< " reqBlockref = " << hex << tcRec.p->reqBlockref
<< " primKeyLen = " << tcRec.p->primKeyLen
+ << " nrcopyflag = " << LqhKeyReq::getNrCopyFlag(tcRec.p->reqinfo)
<< endl;
ndbout << " nextReplica = " << tcRec.p->nextReplica
<< " tcBlockref = " << hex << tcRec.p->tcBlockref
@@ -18399,6 +18491,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
<< endl;
ndbout << " tupkeyData2 = " << tcRec.p->tupkeyData[2]
<< " tupkeyData3 = " << tcRec.p->tupkeyData[3]
+ << " m_nr_delete.m_cnt = " << tcRec.p->m_nr_delete.m_cnt
<< endl;
switch (tcRec.p->transactionState) {
diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index bcda7bee5a9..419754e2d08 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -1411,7 +1411,7 @@ private:
const UintR scanParallel,
const UintR noOprecPerFrag);
void initScanfragrec(Signal* signal);
- void releaseScanResources(ScanRecordPtr);
+ void releaseScanResources(ScanRecordPtr, bool not_started = false);
ScanRecordPtr seizeScanrec(Signal* signal);
void sendScanFragReq(Signal*, ScanRecord*, ScanFragRec*);
void sendScanTabConf(Signal* signal, ScanRecordPtr);
@@ -1558,7 +1558,8 @@ private:
void signalErrorRefuseLab(Signal* signal);
void abort080Lab(Signal* signal);
void packKeyData000Lab(Signal* signal, BlockReference TBRef, Uint32 len);
- void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode);
+ void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode,
+ bool not_started = false);
void sendAbortedAfterTimeout(Signal* signal, int Tcheck);
void abort010Lab(Signal* signal);
void abort015Lab(Signal* signal);
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 5a9d6b9f053..8dee75398ed 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -179,7 +179,7 @@ Dbtc::Dbtc(Block_context& ctx):
ndb_mgm_get_int_parameter(p, CFG_DB_TRANS_BUFFER_MEM,
&transactionBufferMemory);
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_UNIQUE_HASH_INDEXES,
+ ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE,
&maxNoOfIndexes);
ndb_mgm_get_int_parameter(p, CFG_DB_NO_INDEX_OPS,
&maxNoOfConcurrentIndexOperations);
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 369ba53126e..0989807db4a 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -8845,17 +8845,17 @@ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
scanAttrinfo_attrbuf_error:
jam();
- abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
+ abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
return;
scanAttrinfo_attrbuf2_error:
jam();
- abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
+ abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
return;
scanAttrinfo_len_error:
jam();
- abortScanLab(signal, scanptr, ZLENGTH_ERROR);
+ abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
return;
}//Dbtc::scanAttrinfoLab()
@@ -8871,7 +8871,8 @@ void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
;
} else {
abortScanLab(signal, scanptr,
- tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
+ tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
+ true);
return;
}
@@ -8942,13 +8943,13 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
if (apiConnectptr.p->apiFailState == ZTRUE) {
jam();
- releaseScanResources(scanptr);
+ releaseScanResources(scanptr, true);
handleApiFailState(signal, apiConnectptr.i);
return;
}//if
if (tfragCount == 0) {
jam();
- abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR);
+ abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
return;
}//if
@@ -8962,7 +8963,8 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
;
} else {
abortScanLab(signal, scanptr,
- tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
+ tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
+ true);
return;
}
@@ -9027,20 +9029,22 @@ void Dbtc::execDI_FCOUNTREF(Signal* signal)
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
if (apiConnectptr.p->apiFailState == ZTRUE) {
jam();
- releaseScanResources(scanptr);
+ releaseScanResources(scanptr, true);
handleApiFailState(signal, apiConnectptr.i);
return;
}//if
- abortScanLab(signal, scanptr, errCode);
+ abortScanLab(signal, scanptr, errCode, true);
}//Dbtc::execDI_FCOUNTREF()
-void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode)
+void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
+ bool not_started)
{
scanTabRefLab(signal, errCode);
- releaseScanResources(scanptr);
+ releaseScanResources(scanptr, not_started);
}//Dbtc::abortScanLab()
-void Dbtc::releaseScanResources(ScanRecordPtr scanPtr)
+void Dbtc::releaseScanResources(ScanRecordPtr scanPtr,
+ bool not_started)
{
if (apiConnectptr.p->cachePtr != RNIL) {
cachePtr.i = apiConnectptr.p->cachePtr;
@@ -9052,6 +9056,15 @@ void Dbtc::releaseScanResources(ScanRecordPtr scanPtr)
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
releaseTcCon();
+ if (not_started)
+ {
+ jam();
+ ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
+ ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
+ run.release();
+ queue.release();
+ }
+
ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
index 4e507d1b690..aa55985c1f2 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
@@ -118,7 +118,8 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
PagePtr page;
Tuple_header *tuple_ptr= (Tuple_header*)
get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
-
+
+ Uint32 bits= tuple_ptr->m_header_bits;
if(regOperPtr.p->op_struct.op_type != ZDELETE)
{
Tuple_header *copy= (Tuple_header*)
@@ -132,7 +133,7 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
disk_page_abort_prealloc(signal, regFragPtr.p, &key, key.m_page_idx);
}
- Uint32 bits= tuple_ptr->m_header_bits;
+
Uint32 copy_bits= copy->m_header_bits;
if(! (bits & Tuple_header::ALLOC))
{
@@ -170,7 +171,15 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
/**
* Aborting last operation that performed ALLOC
*/
- ndbout_c("clearing ALLOC");
+ tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
+ tuple_ptr->m_header_bits |= Tuple_header::FREED;
+ }
+ }
+ else if (regOperPtr.p->is_first_operation() &&
+ regOperPtr.p->is_last_operation())
+ {
+ if (bits & Tuple_header::ALLOC)
+ {
tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
tuple_ptr->m_header_bits |= Tuple_header::FREED;
}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
index 782679eac18..fc3419e694a 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
@@ -473,13 +473,16 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec);
PagePtr page;
- Tuple_header* tuple_ptr= 0;
+ Tuple_header* tuple_ptr= (Tuple_header*)
+ get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
+
+ bool get_page = false;
if(regOperPtr.p->op_struct.m_load_diskpage_on_commit)
{
+ Page_cache_client::Request req;
ndbassert(regOperPtr.p->is_first_operation() &&
regOperPtr.p->is_last_operation());
- Page_cache_client::Request req;
/**
* Check for page
*/
@@ -490,15 +493,33 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
memcpy(&req.m_page,
tmp->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
+
+ if (unlikely(regOperPtr.p->op_struct.op_type == ZDELETE &&
+ tmp->m_header_bits & Tuple_header::DISK_ALLOC))
+ {
+ jam();
+ /**
+ * Insert+Delete
+ */
+ regOperPtr.p->op_struct.m_load_diskpage_on_commit = 0;
+ regOperPtr.p->op_struct.m_wait_log_buffer = 0;
+ disk_page_abort_prealloc(signal, regFragPtr.p,
+ &req.m_page, req.m_page.m_page_idx);
+
+ c_lgman->free_log_space(regFragPtr.p->m_logfile_group_id,
+ regOperPtr.p->m_undo_buffer_space);
+ ndbout_c("insert+delete");
+ goto skip_disk;
+ }
}
else
{
// initial delete
ndbassert(regOperPtr.p->op_struct.op_type == ZDELETE);
- tuple_ptr= (Tuple_header*)
- get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
memcpy(&req.m_page,
tuple_ptr->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
+
+ ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
}
req.m_callback.m_callbackData= regOperPtr.i;
req.m_callback.m_callbackFunction =
@@ -522,6 +543,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
ndbrequire("NOT YET IMPLEMENTED" == 0);
break;
}
+ get_page = true;
disk_page_set_dirty(*(Ptr<Page>*)&m_pgman.m_ptr);
regOperPtr.p->m_commit_disk_callback_page= res;
regOperPtr.p->op_struct.m_load_diskpage_on_commit= 0;
@@ -555,6 +577,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
tuple_ptr = (Tuple_header*)
get_ptr(&page, &regOperPtr.p->m_tuple_location,regTabPtr.p);
}
+skip_disk:
req_struct.m_tuple_ptr = tuple_ptr;
if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
@@ -599,6 +622,8 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
else
{
removeActiveOpList(regOperPtr.p, tuple_ptr);
+ if (get_page)
+ ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
dealloc_tuple(signal, gci, page.p, tuple_ptr,
regOperPtr.p, regFragPtr.p, regTabPtr.p);
}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
index d74e4b6811e..56f7fb1dd1e 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
@@ -1062,6 +1062,9 @@ Dbtup::disk_page_abort_prealloc_callback_1(Signal* signal,
PagePtr pagePtr,
Uint32 sz)
{
+ jam();
+ disk_page_set_dirty(pagePtr);
+
Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
Uint32 page_idx = pagePtr.p->list_index;
Uint32 used = pagePtr.p->uncommitted_used_space;
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 7305827b6ac..1b6fef9de37 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -483,6 +483,14 @@ Dbtup::load_diskpage(Signal* signal,
req.m_callback.m_callbackData= opRec;
req.m_callback.m_callbackFunction=
safe_cast(&Dbtup::disk_page_load_callback);
+
+#ifdef ERROR_INSERT
+ if (ERROR_INSERTED(4022))
+ {
+ flags |= Page_cache_client::DELAY_REQ;
+ req.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)3000;
+ }
+#endif
if((res= m_pgman.get_page(signal, req, flags)) > 0)
{
@@ -1382,8 +1390,9 @@ int Dbtup::handleInsertReq(Signal* signal,
regOperPtr.p->userpointer,
&regOperPtr.p->m_tuple_location);
- ((Tuple_header*)ptr)->m_operation_ptr_i= regOperPtr.i;
- ((Tuple_header*)ptr)->m_header_bits= Tuple_header::ALLOC |
+ base = (Tuple_header*)ptr;
+ base->m_operation_ptr_i= regOperPtr.i;
+ base->m_header_bits= Tuple_header::ALLOC |
(varsize ? Tuple_header::CHAINED_ROW : 0);
regOperPtr.p->m_tuple_location.m_page_no = real_page_id;
}
@@ -1422,6 +1431,9 @@ int Dbtup::handleInsertReq(Signal* signal,
ndbrequire(false);
}
}
+
+ base->m_header_bits |= Tuple_header::ALLOC &
+ (regOperPtr.p->is_first_operation() ? ~0 : 1);
if (disk_insert)
{
@@ -1467,7 +1479,7 @@ int Dbtup::handleInsertReq(Signal* signal,
size_change_error:
jam();
terrorCode = ZMEM_NOMEM_ERROR;
- goto disk_prealloc_error;
+ goto exit_error;
undo_buffer_error:
jam();
@@ -1501,9 +1513,13 @@ update_error:
regOperPtr.p->op_struct.in_active_list = false;
regOperPtr.p->m_tuple_location.setNull();
}
-disk_prealloc_error:
+exit_error:
tupkeyErrorLab(signal);
return -1;
+
+disk_prealloc_error:
+ base->m_header_bits |= Tuple_header::FREED;
+ goto exit_error;
}
/* ---------------------------------------------------------------- */
@@ -1910,6 +1926,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
// word read. Thus we set the register to be a 32 bit register.
/* ------------------------------------------------------------- */
TregMemBuffer[theRegister]= 0x50;
+ // arithmetic conversion if big-endian
* (Int64*)(TregMemBuffer+theRegister+2)=
TregMemBuffer[theRegister+1];
} else if (TnoDataRW == 3) {
@@ -1969,6 +1986,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
Tlen= TattrNoOfWords + 1;
if (Toptype == ZUPDATE) {
if (TattrNoOfWords <= 2) {
+ if (TattrNoOfWords == 1) {
+ // arithmetic conversion if big-endian
+ TdataForUpdate[1] = *(Int64*)&TregMemBuffer[theRegister + 2];
+ TdataForUpdate[2] = 0;
+ }
if (TregType == 0) {
/* --------------------------------------------------------- */
// Write a NULL value into the attribute
@@ -2879,7 +2901,7 @@ Dbtup::handle_size_change_after_update(KeyReqStruct* req_struct,
if(needed <= alloc)
{
- ndbassert(!regOperPtr->is_first_operation());
+ //ndbassert(!regOperPtr->is_first_operation());
ndbout_c(" no grow");
return 0;
}
@@ -3111,6 +3133,35 @@ Dbtup::nr_delete(Signal* signal, Uint32 senderData,
preq.m_callback.m_callbackFunction =
safe_cast(&Dbtup::nr_delete_page_callback);
int flags = Page_cache_client::COMMIT_REQ;
+
+#ifdef ERROR_INSERT
+ if (ERROR_INSERTED(4023) || ERROR_INSERTED(4024))
+ {
+ int rnd = rand() % 100;
+ int slp = 0;
+ if (ERROR_INSERTED(4024))
+ {
+ slp = 3000;
+ }
+ else if (rnd > 90)
+ {
+ slp = 3000;
+ }
+ else if (rnd > 70)
+ {
+ slp = 100;
+ }
+
+ ndbout_c("rnd: %d slp: %d", rnd, slp);
+
+ if (slp)
+ {
+ flags |= Page_cache_client::DELAY_REQ;
+ preq.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)slp;
+ }
+ }
+#endif
+
res = m_pgman.get_page(signal, preq, flags);
if (res == 0)
{
@@ -3122,6 +3173,7 @@ Dbtup::nr_delete(Signal* signal, Uint32 senderData,
}
PagePtr disk_page = *(PagePtr*)&m_pgman.m_ptr;
+ disk_page_set_dirty(disk_page);
preq.m_callback.m_callbackFunction =
safe_cast(&Dbtup::nr_delete_logbuffer_callback);
@@ -3156,7 +3208,7 @@ Dbtup::nr_delete_page_callback(Signal* signal,
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, page_id);
PagePtr pagePtr= *(PagePtr*)&gpage;
-
+ disk_page_set_dirty(pagePtr);
Dblqh::Nr_op_info op;
op.m_ptr_i = userpointer;
op.m_disk_ref.m_page_no = pagePtr.p->m_page_no;
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
index ed37622657d..e38c82c634f 100644
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
@@ -25,7 +25,10 @@
void Ndbcntr::initData()
{
-
+ c_start.reset();
+ cmasterNodeId = 0;
+ cnoStartNodes = 0;
+ cnoWaitrep = 0;
// Records with constant sizes
ndbBlocksRec = new NdbBlocksRec[ZSIZE_NDB_BLOCKS_REC];
}//Ndbcntr::initData()
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index b0372ec89a2..7c48ebb5e8b 100644
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -1645,10 +1645,9 @@ void Ndbcntr::systemErrorLab(Signal* signal, int line)
/* |-2048| # 1 00000001 | */
/* | : | : | */
/* | -1 | # 1 00000001 | */
-/* | 0 | 0 | */
-/* | 1 | 0 | */
-/* | : | : | */
-/* | 2047| 0 | */
+/* | 1 | 0 | tupleid sequence now created on first use */
+/* | : | : | v */
+/* | 2048| 0 | v */
/*---------------------------------------------------------------------------*/
void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
{
@@ -1859,8 +1858,7 @@ void Ndbcntr::crSystab8Lab(Signal* signal)
jam();
ckey = 1;
ctransidPhase = ZFALSE;
- crSystab7Lab(signal);
- return;
+ // skip 2nd loop - tupleid sequence now created on first use
}//if
signal->theData[0] = ctcConnectionP;
signal->theData[1] = reference();
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index e0324c2c8ea..b0a4d6264fb 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -312,11 +312,12 @@ void AsyncFile::openReq(Request* request)
Uint32 new_flags = 0;
// Convert file open flags from Solaris to Liux
- if(flags & FsOpenReq::OM_CREATE){
+ if (flags & FsOpenReq::OM_CREATE)
+ {
new_flags |= O_CREAT;
}
-
- if(flags & FsOpenReq::OM_TRUNCATE){
+
+ if (flags & FsOpenReq::OM_TRUNCATE){
#if 0
if(Global_unlinkO_CREAT){
unlink(theFileName.c_str());
@@ -330,25 +331,25 @@ void AsyncFile::openReq(Request* request)
m_syncFrequency = 1024*1024; // Hard coded to 1M
}
- if(flags & FsOpenReq::OM_APPEND){
+ if (flags & FsOpenReq::OM_APPEND){
new_flags |= O_APPEND;
}
- if((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
+ if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
{
#ifdef O_SYNC
new_flags |= O_SYNC;
#endif
}
-#ifndef NDB_NO_O_DIRECT /* to allow tmpfs */
+//#ifndef NDB_NO_O_DIRECT /* to allow tmpfs */
#ifdef O_DIRECT
if (flags & FsOpenReq::OM_DIRECT)
{
new_flags |= O_DIRECT;
}
#endif
-#endif
+//#endif
switch(flags & 0x3){
case FsOpenReq::OM_READONLY:
@@ -370,44 +371,73 @@ void AsyncFile::openReq(Request* request)
const int mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
- if(flags & FsOpenReq::OM_CREATE_IF_NONE){
- if((theFd = ::open(theFileName.c_str(), new_flags, mode)) != -1) {
+ if (flags & FsOpenReq::OM_CREATE_IF_NONE)
+ {
+ Uint32 tmp_flags = new_flags;
+#ifdef O_DIRECT
+ tmp_flags &= ~O_DIRECT;
+#endif
+ if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1)
+ {
close(theFd);
request->error = FsRef::fsErrFileExists;
return;
}
new_flags |= O_CREAT;
}
-
- if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) {
+
+no_odirect:
+ if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode)))
+ {
PRINT_ERRORANDFLAGS(new_flags);
- if( (errno == ENOENT ) && (new_flags & O_CREAT ) ) {
+ if ((errno == ENOENT) && (new_flags & O_CREAT))
+ {
createDirectories();
- if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) {
+ if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode)))
+ {
+#ifdef O_DIRECT
+ if (new_flags & O_DIRECT)
+ {
+ new_flags &= ~O_DIRECT;
+ goto no_odirect;
+ }
+#endif
PRINT_ERRORANDFLAGS(new_flags);
request->error = errno;
return;
}
- } else {
+ }
+#ifdef O_DIRECT
+ else if (new_flags & O_DIRECT)
+ {
+ new_flags &= ~O_DIRECT;
+ goto no_odirect;
+ }
+#endif
+ else
+ {
request->error = errno;
return;
}
}
- if(flags & FsOpenReq::OM_CHECK_SIZE)
+ if (flags & FsOpenReq::OM_CHECK_SIZE)
{
struct stat buf;
- if((fstat(theFd, &buf) == -1))
+ if ((fstat(theFd, &buf) == -1))
{
request->error = errno;
- } else if(buf.st_size != request->par.open.file_size){
+ }
+ else if(buf.st_size != request->par.open.file_size)
+ {
request->error = FsRef::fsErrInvalidFileSize;
}
- if(request->error)
+ if (request->error)
return;
}
-
- if(flags & FsOpenReq::OM_INIT){
+
+ if (flags & FsOpenReq::OM_INIT)
+ {
off_t off = 0;
const off_t sz = request->par.open.file_size;
Uint32 tmp[sizeof(SignalHeader)+25];
diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp
index be661433ef6..addbd5e4ba2 100644
--- a/storage/ndb/src/kernel/blocks/pgman.cpp
+++ b/storage/ndb/src/kernel/blocks/pgman.cpp
@@ -944,12 +944,16 @@ Pgman::process_callback(Signal* signal)
int max_count = 1;
Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
- while (! pl_callback.isEmpty() && --max_count >= 0)
+ Ptr<Page_entry> ptr;
+ pl_callback.first(ptr);
+
+ while (! ptr.isNull() && --max_count >= 0)
{
jam();
- Ptr<Page_entry> ptr;
- pl_callback.first(ptr);
- if (! process_callback(signal, ptr))
+ Ptr<Page_entry> curr = ptr;
+ pl_callback.next(ptr);
+
+ if (! process_callback(signal, curr))
{
jam();
break;
@@ -987,6 +991,18 @@ Pgman::process_callback(Signal* signal, Ptr<Page_entry> ptr)
#ifdef VM_TRACE
debugOut << "PGMAN: " << req_ptr << " : process_callback" << endl;
#endif
+
+#ifdef ERROR_INSERT
+ if (req_ptr.p->m_flags & Page_request::DELAY_REQ)
+ {
+ Uint64 now = NdbTick_CurrentMillisecond();
+ if (now < req_ptr.p->m_delay_until_time)
+ {
+ break;
+ }
+ }
+#endif
+
b = globalData.getBlock(req_ptr.p->m_block);
callback = req_ptr.p->m_callback;
@@ -1314,6 +1330,24 @@ Pgman::fsreadconf(Signal* signal, Ptr<Page_entry> ptr)
state |= Page_entry::MAPPED;
set_page_state(ptr, state);
+ {
+ /**
+ * Update lsn record on page
+ * as it can be modified/flushed wo/ update_lsn has been called
+ * (e.g. prealloc) and it then would get lsn 0, which is bad
+ * when running undo and following SR
+ */
+ Ptr<GlobalPage> pagePtr;
+ m_global_page_pool.getPtr(pagePtr, ptr.p->m_real_page_i);
+ File_formats::Datafile::Data_page* page =
+ (File_formats::Datafile::Data_page*)pagePtr.p;
+
+ Uint64 lsn = 0;
+ lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
+ lsn += page->m_page_header.m_page_lsn_lo;
+ ptr.p->m_lsn = lsn;
+ }
+
ndbrequire(m_stats.m_current_io_waits > 0);
m_stats.m_current_io_waits--;
@@ -1575,7 +1609,13 @@ Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
}
bool only_request = ptr.p->m_requests.isEmpty();
-
+#ifdef ERROR_INSERT
+ if (req_flags & Page_request::DELAY_REQ)
+ {
+ jam();
+ only_request = false;
+ }
+#endif
if (only_request &&
state & Page_entry::MAPPED)
{
@@ -1623,7 +1663,10 @@ Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
req_ptr.p->m_block = page_req.m_block;
req_ptr.p->m_flags = page_req.m_flags;
req_ptr.p->m_callback = page_req.m_callback;
-
+#ifdef ERROR_INSERT
+ req_ptr.p->m_delay_until_time = page_req.m_delay_until_time;
+#endif
+
state |= Page_entry::REQUEST;
if (only_request && req_flags & Page_request::EMPTY_PAGE)
{
diff --git a/storage/ndb/src/kernel/blocks/pgman.hpp b/storage/ndb/src/kernel/blocks/pgman.hpp
index 5a6a5f319bd..ae7736025ab 100644
--- a/storage/ndb/src/kernel/blocks/pgman.hpp
+++ b/storage/ndb/src/kernel/blocks/pgman.hpp
@@ -256,12 +256,18 @@ private:
,DIRTY_REQ = 0x0200 // make page dirty wo/ update_lsn
,UNLOCK_PAGE = 0x0400
,CORR_REQ = 0x0800 // correlated request (no LIRS update)
+#ifdef ERROR_INSERT
+ ,DELAY_REQ = 0x1000 // Force request to be delayed
+#endif
};
-
+
Uint16 m_block;
Uint16 m_flags;
SimulatedBlock::Callback m_callback;
+#ifdef ERROR_INSERT
+ Uint64 m_delay_until_time;
+#endif
Uint32 nextList;
Uint32 m_magic;
};
@@ -508,6 +514,10 @@ public:
struct Request {
Local_key m_page;
SimulatedBlock::Callback m_callback;
+
+#ifdef ERROR_INSERT
+ Uint64 m_delay_until_time;
+#endif
};
Ptr<GlobalPage> m_ptr; // TODO remove
@@ -520,6 +530,9 @@ public:
,DIRTY_REQ = Pgman::Page_request::DIRTY_REQ
,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE
,CORR_REQ = Pgman::Page_request::CORR_REQ
+#ifdef ERROR_INSERT
+ ,DELAY_REQ = Pgman::Page_request::DELAY_REQ
+#endif
};
/**
@@ -588,7 +601,10 @@ Page_cache_client::get_page(Signal* signal, Request& req, Uint32 flags)
page_req.m_block = m_block;
page_req.m_flags = flags;
page_req.m_callback = req.m_callback;
-
+#ifdef ERROR_INSERT
+ page_req.m_delay_until_time = req.m_delay_until_time;
+#endif
+
int i = m_pgman->get_page(signal, entry_ptr, page_req);
if (i > 0)
{
diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 8772e00f027..4d5ac377a5a 100644
--- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -827,7 +827,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
ndbrequire(c_start.m_gsn == GSN_CM_REGREQ);
- ndbrequire(myNodePtr.p->phase = ZSTARTING);
+ ndbrequire(myNodePtr.p->phase == ZSTARTING);
cpdistref = cmRegConf->presidentBlockRef;
cpresident = cmRegConf->presidentNodeId;
diff --git a/storage/ndb/src/kernel/blocks/restore.cpp b/storage/ndb/src/kernel/blocks/restore.cpp
index ce38af2a64f..a8b3ebb17f4 100644
--- a/storage/ndb/src/kernel/blocks/restore.cpp
+++ b/storage/ndb/src/kernel/blocks/restore.cpp
@@ -547,9 +547,10 @@ Restore::restore_next(Signal* signal, FilePtr file_ptr)
parse_gcp_entry(signal, file_ptr, data, len);
break;
case 0x4e444242: // 'NDBB'
- if(ntohl(* (data+2)) != NDB_VERSION)
- parse_error(signal, file_ptr, __LINE__, ntohl(* (data+2)));
- break;
+ if (check_file_version(signal, ntohl(* (data+2))) == 0)
+ {
+ break;
+ }
default:
parse_error(signal, file_ptr, __LINE__, ntohl(* data));
}
@@ -719,7 +720,7 @@ Restore::parse_file_header(Signal* signal,
return;
}
- if(ntohl(fh->NdbVersion) != NDB_VERSION)
+ if (check_file_version(signal, ntohl(fh->NdbVersion)))
{
parse_error(signal, file_ptr, __LINE__, ntohl(fh->NdbVersion));
return;
@@ -1227,3 +1228,23 @@ operator << (NdbOut& ndbout, const Restore::Column& col)
return ndbout;
}
+
+int
+Restore::check_file_version(Signal* signal, Uint32 file_version)
+{
+ if (file_version < MAKE_VERSION(5,1,6))
+ {
+ char buf[255];
+ char verbuf[255];
+ getVersionString(file_version, 0, verbuf, sizeof(verbuf));
+ BaseString::snprintf(buf, sizeof(buf),
+ "Unsupported version of LCP files found on disk, "
+ " found: %s", verbuf);
+
+ progError(__LINE__,
+ NDBD_EXIT_SR_RESTARTCONFLICT,
+ buf);
+ return -1;
+ }
+ return 0;
+}
diff --git a/storage/ndb/src/kernel/blocks/restore.hpp b/storage/ndb/src/kernel/blocks/restore.hpp
index 02b204155ab..609040e0280 100644
--- a/storage/ndb/src/kernel/blocks/restore.hpp
+++ b/storage/ndb/src/kernel/blocks/restore.hpp
@@ -140,6 +140,7 @@ private:
Uint32 calulate_hash(Uint32 tableId, const Uint32 *src);
void parse_error(Signal*, FilePtr, Uint32 line, Uint32 extra);
+ int check_file_version(Signal*, Uint32 file_version);
public:
private:
diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
index 867b13e1e40..91f0fab06f8 100644
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -2649,6 +2649,22 @@ Suma::reportAllSubscribers(Signal *signal,
SubscriptionPtr subPtr,
SubscriberPtr subbPtr)
{
+ SubTableData * data = (SubTableData*)signal->getDataPtrSend();
+
+ if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE)
+ {
+ data->gci = m_last_complete_gci + 1;
+ data->tableId = subPtr.p->m_tableId;
+ data->operation = NdbDictionary::Event::_TE_ACTIVE;
+ data->ndbd_nodeid = refToNode(reference());
+ data->changeMask = 0;
+ data->totalLen = 0;
+ data->req_nodeid = refToNode(subbPtr.p->m_senderRef);
+ data->senderData = subbPtr.p->m_senderData;
+ sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
+ SubTableData::SignalLength, JBB);
+ }
+
if (!(subPtr.p->m_options & Subscription::REPORT_SUBSCRIBE))
{
return;
@@ -2663,7 +2679,6 @@ Suma::reportAllSubscribers(Signal *signal,
ndbout_c("reportAllSubscribers subPtr.i: %d subPtr.p->n_subscribers: %d",
subPtr.i, subPtr.p->n_subscribers);
//#endif
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();
data->gci = m_last_complete_gci + 1;
data->tableId = subPtr.p->m_tableId;
data->operation = table_event;
diff --git a/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp
index 227ad6d6893..12badffe0e0 100644
--- a/storage/ndb/src/kernel/vm/Configuration.cpp
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp
@@ -49,7 +49,9 @@ extern EventLogger g_eventLogger;
enum ndbd_options {
OPT_INITIAL = NDB_STD_OPTIONS_LAST,
OPT_NODAEMON,
- OPT_FOREGROUND
+ OPT_FOREGROUND,
+ OPT_NOWAIT_NODES,
+ OPT_INITIAL_START
};
NDB_STD_OPTS_VARS;
@@ -88,11 +90,11 @@ static struct my_option my_long_options[] =
" (implies --nodaemon)",
(gptr*) &_foreground, (gptr*) &_foreground, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "nowait-nodes", NO_ARG,
+ { "nowait-nodes", OPT_NOWAIT_NODES,
"Nodes that will not be waited for during start",
(gptr*) &_nowait_nodes, (gptr*) &_nowait_nodes, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
- { "initial-start", NO_ARG,
+ { "initial-start", OPT_INITIAL_START,
"Perform initial start",
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
@@ -210,9 +212,13 @@ Configuration::Configuration()
m_config_retriever= 0;
m_clusterConfig= 0;
m_clusterConfigIter= 0;
+ m_logLevel= 0;
}
Configuration::~Configuration(){
+ if (opt_connect_str)
+ free(_connectString);
+
if(_programName != NULL)
free(_programName);
@@ -225,6 +231,10 @@ Configuration::~Configuration(){
if (m_config_retriever) {
delete m_config_retriever;
}
+
+ if(m_logLevel) {
+ delete m_logLevel;
+ }
}
void
@@ -278,7 +288,8 @@ Configuration::fetch_configuration(){
if (globalData.ownId)
cr.setNodeId(globalData.ownId);
- globalData.ownId = cr.allocNodeId(2 /*retry*/,3 /*delay*/);
+ globalData.ownId = cr.allocNodeId(globalData.ownId ? 10 : 2 /*retry*/,
+ 3 /*delay*/);
if(globalData.ownId == 0){
ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp
index 22f3d2524a9..6dfb48667aa 100644
--- a/storage/ndb/src/mgmapi/mgmapi.cpp
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp
@@ -701,10 +701,12 @@ ndb_mgm_get_status(NdbMgmHandle handle)
Vector<BaseString> split;
tmp.split(split, ":");
if(split.size() != 2){
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
}
if(!(split[0].trim() == "nodes")){
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
}
@@ -752,6 +754,7 @@ ndb_mgm_get_status(NdbMgmHandle handle)
if(i+1 != noOfNodes){
free(state);
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch");
return NULL;
}
@@ -1305,33 +1308,6 @@ ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
extern "C"
int
-ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
-{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_stat_port");
- const ParserRow<ParserDummy> stat_reply[] = {
- MGM_CMD("error", NULL, ""),
- MGM_ARG("result", String, Mandatory, "Error message"),
- MGM_CMD("get statport reply", NULL, ""),
- MGM_ARG("tcpport", Int, Mandatory, "TCP port for statistics"),
- MGM_END()
- };
- CHECK_HANDLE(handle, -1);
- CHECK_CONNECTED(handle, -1);
-
- Properties args;
- const Properties *reply;
- reply = ndb_mgm_call(handle, stat_reply, "get statport", &args);
- CHECK_REPLY(reply, -1);
-
- Uint32 port;
- reply->get("tcpport", &port);
-
- delete reply;
- return port;
-}
-
-extern "C"
-int
ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args,
int _num_args, struct ndb_mgm_reply* /* reply */)
{
@@ -1874,7 +1850,8 @@ const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz
extern "C"
int
-ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
+ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype,
+ int log_event)
{
CHECK_HANDLE(handle, 0);
CHECK_CONNECTED(handle, 0);
@@ -1894,9 +1871,11 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
if (handle->m_name)
args.put("name", handle->m_name);
+ args.put("log_event", log_event);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("get nodeid reply", NULL, ""),
+ MGM_ARG("error_code", Int, Optional, "Error code"),
MGM_ARG("nodeid", Int, Optional, "Error message"),
MGM_ARG("result", String, Mandatory, "Error message"),
MGM_END()
@@ -1909,14 +1888,16 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
nodeid= -1;
do {
const char * buf;
- if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
+ {
const char *hostname= ndb_mgm_get_connected_host(handle);
unsigned port= ndb_mgm_get_connected_port(handle);
BaseString err;
+ Uint32 error_code= NDB_MGM_ALLOCID_ERROR;
err.assfmt("Could not alloc node id at %s port %d: %s",
hostname, port, buf);
- setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
- err.c_str());
+ prop->get("error_code", &error_code);
+ setError(handle, error_code, __LINE__, err.c_str());
break;
}
Uint32 _nodeid;
diff --git a/storage/ndb/src/mgmsrv/ConfigInfo.cpp b/storage/ndb/src/mgmsrv/ConfigInfo.cpp
index 5b3efa28d35..8705b640809 100644
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -1235,7 +1235,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
false,
ConfigInfo::CI_INT,
"32K",
- "0",
+ "2K",
+ STR_VALUE(MAX_INT_RNIL) },
+
+ {
+ CFG_DB_BACKUP_MAX_WRITE_SIZE,
+ "BackupMaxWriteSize",
+ DB_TOKEN,
+ "Max size of filesystem writes made by backup (in bytes)",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ "256K",
+ "2K",
STR_VALUE(MAX_INT_RNIL) },
{
diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp
index 48094800f9a..1e655c29517 100644
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -503,9 +503,10 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
if (_ownNodeId == 0) // we did not get node id from other server
{
NodeId tmp= m_config_retriever->get_configuration_nodeid();
+ int error_code;
if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
- 0, 0, error_string)){
+ 0, 0, error_code, error_string)){
ndbout << "Unable to obtain requested nodeid: "
<< error_string.c_str() << endl;
require(false);
@@ -1113,31 +1114,16 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
- ndbout_c("Node %d fail completed", rep->failedNodeId);
+ ndbout_c("sendSTOP_REQ Node %d fail completed", rep->failedNodeId);
#endif
+ nodes.clear(rep->failedNodeId); // clear the failed node
+ if (singleUserNodeId == 0)
+ stoppedNodes.set(rep->failedNodeId);
break;
}
case GSN_NODE_FAILREP:{
const NodeFailRep * const rep =
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
- NodeBitmask failedNodes;
- failedNodes.assign(NodeBitmask::Size, rep->theNodes);
-#ifdef VM_TRACE
- {
- ndbout << "Failed nodes:";
- for (unsigned i = 0; i < 32*NodeBitmask::Size; i++)
- if(failedNodes.get(i))
- ndbout << " " << i;
- ndbout << endl;
- }
-#endif
- failedNodes.bitAND(nodes);
- if (!failedNodes.isclear())
- {
- nodes.bitANDC(failedNodes); // clear the failed nodes
- if (singleUserNodeId == 0)
- stoppedNodes.bitOR(failedNodes);
- }
break;
}
default:
@@ -1258,11 +1244,47 @@ int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
abort,
false,
true,
- nostart,
+ true,
initialStart);
+
+ if (ret)
+ return ret;
+
if (stopCount)
*stopCount = nodes.count();
- return ret;
+
+ // start up the nodes again
+ int waitTime = 12000;
+ NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime;
+ for (unsigned i = 0; i < node_ids.size(); i++)
+ {
+ NodeId nodeId= node_ids[i];
+ enum ndb_mgm_node_status s;
+ s = NDB_MGM_NODE_STATUS_NO_CONTACT;
+#ifdef VM_TRACE
+ ndbout_c("Waiting for %d not started", nodeId);
+#endif
+ while (s != NDB_MGM_NODE_STATUS_NOT_STARTED && waitTime > 0)
+ {
+ Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0;
+ Uint32 connectCount = 0;
+ bool system;
+ const char *address;
+ status(nodeId, &s, &version, &startPhase,
+ &system, &dynamicId, &nodeGroup, &connectCount, &address);
+ NdbSleep_MilliSleep(100);
+ waitTime = (maxTime - NdbTick_CurrentMillisecond());
+ }
+ }
+
+ if (nostart)
+ return 0;
+
+ for (unsigned i = 0; i < node_ids.size(); i++)
+ {
+ int result = start(node_ids[i]);
+ }
+ return 0;
}
/*
@@ -1991,7 +2013,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
enum ndb_mgm_node_type type,
struct sockaddr *client_addr,
SOCKET_SIZE_TYPE *client_addr_len,
- BaseString &error_string)
+ int &error_code, BaseString &error_string,
+ int log_event)
{
DBUG_ENTER("MgmtSrvr::alloc_node_id");
DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d",
@@ -2000,6 +2023,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
if (*nodeId == 0) {
error_string.appfmt("no-nodeid-checks set in management server.\n"
"node id must be set explicitly in connectstring");
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
DBUG_RETURN(true);
@@ -2024,8 +2048,10 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
if(NdbMutex_Lock(m_configMutex))
{
+ // should not happen
error_string.appfmt("unable to lock configuration mutex");
- return false;
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ DBUG_RETURN(false);
}
ndb_mgm_configuration_iterator
iter(* _config->m_configValues, CFG_SECTION_NODE);
@@ -2096,6 +2122,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"or specifying unique host names in config file.",
id_found, tmp);
NdbMutex_Unlock(m_configMutex);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
if (config_hostname == 0) {
@@ -2104,6 +2131,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"or specifying unique host names in config file,\n"
"or specifying just one mgmt server in config file.",
tmp);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
id_found= tmp; // mgmt server matched, check for more matches
@@ -2178,8 +2206,9 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
char tmp_str[128];
m_reserved_nodes.getText(tmp_str);
- g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, m_reserved_nodes %s.",
- id_found, get_connect_address(id_found), tmp_str);
+ g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, "
+ "m_reserved_nodes %s.",
+ id_found, get_connect_address(id_found), tmp_str);
DBUG_RETURN(true);
}
@@ -2199,26 +2228,48 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
type_c_string.assfmt("%s(%s)", alias, str);
}
- if (*nodeId == 0) {
+ if (*nodeId == 0)
+ {
if (found_matching_id)
+ {
if (found_matching_type)
+ {
if (found_free_node)
+ {
error_string.appfmt("Connection done from wrong host ip %s.",
(client_addr)?
- inet_ntoa(((struct sockaddr_in *)
+ inet_ntoa(((struct sockaddr_in *)
(client_addr))->sin_addr):"");
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
else
+ {
error_string.appfmt("No free node id found for %s.",
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
+ }
else
+ {
error_string.appfmt("No %s node defined in config file.",
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
else
+ {
error_string.append("No nodes defined in config file.");
- } else {
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
+ else
+ {
if (found_matching_id)
+ {
if (found_matching_type)
- if (found_free_node) {
+ {
+ if (found_free_node)
+ {
// have to split these into two since inet_ntoa overwrites itself
error_string.appfmt("Connection with id %d done from wrong host ip %s,",
*nodeId, inet_ntoa(((struct sockaddr_in *)
@@ -2226,27 +2277,44 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
error_string.appfmt(" expected %s(%s).", config_hostname,
r_config_addr ?
"lookup failed" : inet_ntoa(config_addr));
- } else
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ else
+ {
error_string.appfmt("Id %d already allocated by another node.",
*nodeId);
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
+ }
else
+ {
error_string.appfmt("Id %d configured as %s, connect attempted as %s.",
*nodeId, type_c_string.c_str(),
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
else
+ {
error_string.appfmt("No node defined with id=%d in config file.",
*nodeId);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
}
- g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s. "
- "Returned error string \"%s\"",
- *nodeId,
- client_addr != 0 ? inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr) : "<none>",
- error_string.c_str());
-
- NodeBitmask connected_nodes2;
- get_connected_nodes(connected_nodes2);
+ if (log_event || error_code == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
{
+ g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s."
+ " Returned error string \"%s\"",
+ *nodeId,
+ client_addr != 0
+ ? inet_ntoa(((struct sockaddr_in *)
+ (client_addr))->sin_addr)
+ : "<none>",
+ error_string.c_str());
+
+ NodeBitmask connected_nodes2;
+ get_connected_nodes(connected_nodes2);
BaseString tmp_connected, tmp_not_connected;
for(Uint32 i = 0; i < MAX_NODES; i++)
{
@@ -2446,6 +2514,7 @@ int
MgmtSrvr::abortBackup(Uint32 backupId)
{
SignalSender ss(theFacade);
+ ss.lock(); // lock will be released on exit
bool next;
NodeId nodeId = 0;
@@ -2473,6 +2542,8 @@ MgmtSrvr::abortBackup(Uint32 backupId)
MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m)
: m_mgmsrv(m)
{
+ m_reserved_nodes.clear();
+ m_alloc_timeout= 0;
}
MgmtSrvr::Allocated_resources::~Allocated_resources()
@@ -2491,9 +2562,22 @@ MgmtSrvr::Allocated_resources::~Allocated_resources()
}
void
-MgmtSrvr::Allocated_resources::reserve_node(NodeId id)
+MgmtSrvr::Allocated_resources::reserve_node(NodeId id, NDB_TICKS timeout)
{
m_reserved_nodes.set(id);
+ m_alloc_timeout= NdbTick_CurrentMillisecond() + timeout;
+}
+
+bool
+MgmtSrvr::Allocated_resources::is_timed_out(NDB_TICKS tick)
+{
+ if (m_alloc_timeout && tick > m_alloc_timeout)
+ {
+ g_eventLogger.info("Mgmt server state: nodeid %d timed out.",
+ get_nodeid());
+ return true;
+ }
+ return false;
}
NodeId
diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp
index ddd5247b446..63134991ffe 100644
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -106,7 +106,8 @@ public:
~Allocated_resources();
// methods to reserve/allocate resources which
// will be freed when running destructor
- void reserve_node(NodeId id);
+ void reserve_node(NodeId id, NDB_TICKS timeout);
+ bool is_timed_out(NDB_TICKS tick);
bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId); }
bool is_reserved(NodeBitmask mask) { return !mask.bitAND(m_reserved_nodes).isclear(); }
bool isclear() { return m_reserved_nodes.isclear(); }
@@ -114,6 +115,7 @@ public:
private:
MgmtSrvr &m_mgmsrv;
NodeBitmask m_reserved_nodes;
+ NDB_TICKS m_alloc_timeout;
};
NdbMutex *m_node_id_mutex;
@@ -427,8 +429,10 @@ public:
*/
bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ;
bool alloc_node_id(NodeId * _nodeId, enum ndb_mgm_node_type type,
- struct sockaddr *client_addr, SOCKET_SIZE_TYPE *client_addr_len,
- BaseString &error_string);
+ struct sockaddr *client_addr,
+ SOCKET_SIZE_TYPE *client_addr_len,
+ int &error_code, BaseString &error_string,
+ int log_event = 1);
/**
*
diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp
index 7b17cfa21e2..2731bfd422b 100644
--- a/storage/ndb/src/mgmsrv/Services.cpp
+++ b/storage/ndb/src/mgmsrv/Services.cpp
@@ -121,8 +121,6 @@ static const unsigned int MAX_WRITE_TIMEOUT = 100 ;
const
ParserRow<MgmApiSession> commands[] = {
- MGM_CMD("get statport", &MgmApiSession::getStatPort, ""),
-
MGM_CMD("get config", &MgmApiSession::getConfig, ""),
MGM_ARG("version", Int, Mandatory, "Configuration version number"),
MGM_ARG("node", Int, Optional, "Node ID"),
@@ -137,6 +135,8 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("public key", String, Mandatory, "Public key"),
MGM_ARG("endian", String, Optional, "Endianness"),
MGM_ARG("name", String, Optional, "Name of connection"),
+ MGM_ARG("timeout", Int, Optional, "Timeout in seconds"),
+ MGM_ARG("log_event", Int, Optional, "Log failure in cluster log"),
MGM_CMD("get version", &MgmApiSession::getVersion, ""),
@@ -259,6 +259,15 @@ ParserRow<MgmApiSession> commands[] = {
MGM_END()
};
+struct PurgeStruct
+{
+ NodeBitmask free_nodes;/* free nodes as reported
+ * by ndbd in apiRegReqConf
+ */
+ BaseString *str;
+ NDB_TICKS tick;
+};
+
MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
: SocketServer::Session(sock), m_mgmsrv(mgm)
{
@@ -408,12 +417,15 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
{
const char *cmd= "get nodeid reply";
Uint32 version, nodeid= 0, nodetype= 0xff;
+ Uint32 timeout= 20; // default seconds timeout
const char * transporter;
const char * user;
const char * password;
const char * public_key;
const char * endian= NULL;
const char * name= NULL;
+ Uint32 log_event= 1;
+ bool log_event_version;
union { long l; char c[sizeof(long)]; } endian_check;
args.get("version", &version);
@@ -425,6 +437,9 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
args.get("public key", &public_key);
args.get("endian", &endian);
args.get("name", &name);
+ args.get("timeout", &timeout);
+ /* for backwards compatability keep track if client uses new protocol */
+ log_event_version= args.get("log_event", &log_event);
endian_check.l = 1;
if(endian
@@ -464,14 +479,40 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
NodeId tmp= nodeid;
if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
BaseString error_string;
- if (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
- (struct sockaddr*)&addr, &addrlen, error_string)){
+ int error_code;
+ NDB_TICKS tick= 0;
+ /* only report error on second attempt as not to clog the cluster log */
+ while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
+ (struct sockaddr*)&addr, &addrlen,
+ error_code, error_string,
+ tick == 0 ? 0 : log_event))
+ {
+ /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */
+ if (tick == 0 && error_code != NDB_MGM_ALLOCID_CONFIG_MISMATCH)
+ {
+ // attempt to free any timed out reservations
+ tick= NdbTick_CurrentMillisecond();
+ struct PurgeStruct ps;
+ m_mgmsrv.get_connected_nodes(ps.free_nodes);
+ // invert connected_nodes to get free nodes
+ ps.free_nodes.bitXORC(NodeBitmask());
+ ps.str= 0;
+ ps.tick= tick;
+ m_mgmsrv.get_socket_server()->
+ foreachSession(stop_session_if_timed_out,&ps);
+ m_mgmsrv.get_socket_server()->checkSessions();
+ error_string = "";
+ continue;
+ }
const char *alias;
const char *str;
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
nodetype, &str);
m_output->println(cmd);
m_output->println("result: %s", error_string.c_str());
+ /* only use error_code protocol if client knows about it */
+ if (log_event_version)
+ m_output->println("error_code: %d", error_code);
m_output->println("");
return;
}
@@ -491,7 +532,7 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
m_output->println("nodeid: %u", tmp);
m_output->println("result: Ok");
m_output->println("");
- m_allocated_resources->reserve_node(tmp);
+ m_allocated_resources->reserve_node(tmp, timeout*1000);
if (name)
g_eventLogger.info("Node %d: %s", tmp, name);
@@ -607,15 +648,6 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
}
void
-MgmApiSession::getStatPort(Parser_t::Context &,
- const class Properties &) {
-
- m_output->println("get statport reply");
- m_output->println("tcpport: %d", 0);
- m_output->println("");
-}
-
-void
MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
Properties const &args) {
Uint32 node = 0, error = 0;
@@ -1480,14 +1512,6 @@ done:
m_output->println("");
}
-struct PurgeStruct
-{
- NodeBitmask free_nodes;/* free nodes as reported
- * by ndbd in apiRegReqConf
- */
- BaseString *str;
-};
-
void
MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data)
{
@@ -1495,7 +1519,20 @@ MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *da
struct PurgeStruct &ps= *(struct PurgeStruct *)data;
if (s->m_allocated_resources->is_reserved(ps.free_nodes))
{
- ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
+ if (ps.str)
+ ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
+ s->stopSession();
+ }
+}
+
+void
+MgmApiSession::stop_session_if_timed_out(SocketServer::Session *_s, void *data)
+{
+ MgmApiSession *s= (MgmApiSession *)_s;
+ struct PurgeStruct &ps= *(struct PurgeStruct *)data;
+ if (s->m_allocated_resources->is_reserved(ps.free_nodes) &&
+ s->m_allocated_resources->is_timed_out(ps.tick))
+ {
s->stopSession();
}
}
@@ -1512,6 +1549,7 @@ MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx,
ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes
m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps);
+ m_mgmsrv.get_socket_server()->checkSessions();
m_output->println("purge stale sessions reply");
if (str.length() > 0)
diff --git a/storage/ndb/src/mgmsrv/Services.hpp b/storage/ndb/src/mgmsrv/Services.hpp
index f97223750a1..abe0233cb33 100644
--- a/storage/ndb/src/mgmsrv/Services.hpp
+++ b/storage/ndb/src/mgmsrv/Services.hpp
@@ -30,6 +30,7 @@
class MgmApiSession : public SocketServer::Session
{
+ static void stop_session_if_timed_out(SocketServer::Session *_s, void *data);
static void stop_session_if_not_connected(SocketServer::Session *_s, void *data);
private:
typedef Parser<MgmApiSession> Parser_t;
@@ -52,7 +53,6 @@ public:
virtual ~MgmApiSession();
void runSession();
- void getStatPort(Parser_t::Context &ctx, const class Properties &args);
void getConfig(Parser_t::Context &ctx, const class Properties &args);
#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
void getConfig_old(Parser_t::Context &ctx);
diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp
index 2ff403d53b3..b108ed3fd41 100644
--- a/storage/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp
@@ -70,6 +70,8 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade):
noOfAliveNodes= 0;
noOfConnectedNodes= 0;
theClusterMgrThread= 0;
+ m_connect_count = 0;
+ m_cluster_state = CS_waiting_for_clean_cache;
DBUG_VOID_RETURN;
}
@@ -174,6 +176,16 @@ ClusterMgr::threadMain( ){
int send_heartbeat_now= global_flag_send_heartbeat_now;
global_flag_send_heartbeat_now= 0;
+ if (m_cluster_state == CS_waiting_for_clean_cache)
+ {
+ theFacade.m_globalDictCache.lock();
+ unsigned sz= theFacade.m_globalDictCache.get_size();
+ theFacade.m_globalDictCache.unlock();
+ if (sz)
+ goto next;
+ m_cluster_state = CS_waiting_for_first_connect;
+ }
+
theFacade.lock_mutex();
for (int i = 1; i < MAX_NODES; i++){
/**
@@ -222,6 +234,7 @@ ClusterMgr::threadMain( ){
*/
theFacade.unlock_mutex();
+next:
// Sleep for 100 ms between each Registration Heartbeat
Uint64 before = now;
NdbSleep_MilliSleep(100);
@@ -445,6 +458,11 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
theNode.nfCompleteRep = false;
if(noOfAliveNodes == 0)
{
+ theFacade.m_globalDictCache.lock();
+ theFacade.m_globalDictCache.invalidate_all();
+ theFacade.m_globalDictCache.unlock();
+ m_connect_count ++;
+ m_cluster_state = CS_waiting_for_clean_cache;
NFCompleteRep rep;
for(Uint32 i = 1; i<MAX_NODES; i++){
if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){
diff --git a/storage/ndb/src/ndbapi/ClusterMgr.hpp b/storage/ndb/src/ndbapi/ClusterMgr.hpp
index 31682885f90..ca879e7948e 100644
--- a/storage/ndb/src/ndbapi/ClusterMgr.hpp
+++ b/storage/ndb/src/ndbapi/ClusterMgr.hpp
@@ -57,6 +57,11 @@ private:
class TransporterFacade & theFacade;
public:
+ enum Cluster_state {
+ CS_waiting_for_clean_cache = 0,
+ CS_waiting_for_first_connect,
+ CS_connected
+ };
struct Node {
Node();
bool defined;
@@ -80,12 +85,13 @@ public:
bool isClusterAlive() const;
void hb_received(NodeId);
+ Uint32 m_connect_count;
private:
Uint32 noOfAliveNodes;
Uint32 noOfConnectedNodes;
Node theNodes[MAX_NODES];
NdbThread* theClusterMgrThread;
-
+ enum Cluster_state m_cluster_state;
/**
* Used for controlling start/stop of the thread
*/
diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp
index fc276472c48..8a0bf2f8e8b 100644
--- a/storage/ndb/src/ndbapi/DictCache.cpp
+++ b/storage/ndb/src/ndbapi/DictCache.cpp
@@ -47,6 +47,7 @@ Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl)
{
assert(! is_ndb_blob_table(table_impl));
m_table_impl= table_impl;
+ m_tuple_id_range.reset();
}
Ndb_local_table_info::~Ndb_local_table_info()
@@ -63,6 +64,7 @@ LocalDictCache::~LocalDictCache(){
Ndb_local_table_info *
LocalDictCache::get(const char * name){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
const Uint32 len = strlen(name);
return m_tableHash.getData(name, len);
@@ -70,6 +72,7 @@ LocalDictCache::get(const char * name){
void
LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
const Uint32 id = tab_info->m_table_impl->m_id;
m_tableHash.insertKey(name, strlen(name), id, tab_info);
@@ -77,6 +80,7 @@ LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
void
LocalDictCache::drop(const char * name){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
Ndb_local_table_info *info= m_tableHash.deleteKey(name, strlen(name));
DBUG_ASSERT(info != 0);
@@ -100,8 +104,15 @@ GlobalDictCache::~GlobalDictCache(){
Vector<TableVersion> * vers = curr->theData;
const unsigned sz = vers->size();
for(unsigned i = 0; i<sz ; i++){
- if((* vers)[i].m_impl != 0)
+ TableVersion tv= (*vers)[i];
+ DBUG_PRINT(" ", ("vers[%d]: ver: %d, refCount: %d, status: %d",
+ i, 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()));
delete (* vers)[i].m_impl;
+ }
}
delete curr->theData;
curr->theData= NULL;
@@ -124,8 +135,8 @@ void GlobalDictCache::printCache()
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));
+ DBUG_PRINT(" ", ("impl: %p vers[%d]: ver: %d, refCount: %d, status: %d",
+ tv.m_impl, i, tv.m_version, tv.m_refCount, tv.m_status));
if(tv.m_impl != 0)
{
DBUG_PRINT(" ", ("m_impl: internalname: %s",
@@ -164,11 +175,23 @@ GlobalDictCache::get(const char * name)
TableVersion * ver = & versions->back();
switch(ver->m_status){
case OK:
+ if (ver->m_impl->m_status == NdbDictionary::Object::Invalid)
+ {
+ ver->m_status = DROPPED;
+ retreive = true; // Break loop
+ if (ver->m_refCount == 0)
+ {
+ delete ver->m_impl;
+ versions->erase(versions->size() - 1);
+ }
+ break;
+ }
ver->m_refCount++;
- DBUG_PRINT("info", ("Table OK version=%x.%x refCount=%u",
- ver->m_impl->m_version & 0xFFFFFF,
- ver->m_impl->m_version >> 24,
- ver->m_refCount));
+ DBUG_PRINT("info", ("Table OK tab: %p version=%x.%x refCount=%u",
+ ver->m_impl,
+ ver->m_impl->m_version & 0xFFFFFF,
+ ver->m_impl->m_version >> 24,
+ ver->m_refCount));
DBUG_RETURN(ver->m_impl);
case DROPPED:
retreive = true; // Break loop
@@ -197,8 +220,8 @@ NdbTableImpl *
GlobalDictCache::put(const char * name, NdbTableImpl * tab)
{
DBUG_ENTER("GlobalDictCache::put");
- DBUG_PRINT("enter", ("name: %s, internal_name: %s version: %x.%x",
- name,
+ DBUG_PRINT("enter", ("tab: %p name: %s, internal_name: %s version: %x.%x",
+ tab, name,
tab ? tab->m_internalName.c_str() : "tab NULL",
tab ? tab->m_version & 0xFFFFFF : 0,
tab ? tab->m_version >> 24 : 0));
@@ -263,67 +286,51 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
DBUG_RETURN(tab);
}
-void
-GlobalDictCache::drop(NdbTableImpl * tab)
+unsigned
+GlobalDictCache::get_size()
{
- DBUG_ENTER("GlobalDictCache::drop");
- DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
- assert(! is_ndb_blob_table(tab));
-
- 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 thus there should be a record
- abort();
+ NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
+ int sz = 0;
+ while(curr != 0){
+ sz += curr->theData->size();
+ curr = m_tableHash.getNext(curr);
}
-
- const Uint32 sz = vers->size();
- if(sz == 0){
- // Should always tried to retreive it first
- // and thus there should be a record
- abort();
+ if (sz)
+ {
+ printCache();
}
+ return sz;
+}
- for(i = 0; i < sz; i++){
- TableVersion & ver = (* vers)[i];
- if(ver.m_impl == tab){
- if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
- ver.m_version != tab->m_version){
- 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);
+void
+GlobalDictCache::invalidate_all()
+{
+ DBUG_ENTER("GlobalDictCache::invalidate_all");
+ NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
+ while(curr != 0){
+ Vector<TableVersion> * vers = curr->theData;
+ if (vers->size())
+ {
+ TableVersion * ver = & vers->back();
+ ver->m_impl->m_status = NdbDictionary::Object::Invalid;
+ ver->m_status = DROPPED;
+ if (ver->m_refCount == 0)
+ {
+ delete ver->m_impl;
+ vers->erase(vers->size() - 1);
}
- DBUG_VOID_RETURN;
}
+ curr = m_tableHash.getNext(curr);
}
-
- 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);
- }
-
- abort();
+ DBUG_VOID_RETURN;
}
void
-GlobalDictCache::release(NdbTableImpl * tab)
+GlobalDictCache::release(NdbTableImpl * tab, int invalidate)
{
DBUG_ENTER("GlobalDictCache::release");
- DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+ DBUG_PRINT("enter", ("tab: %p internal_name: %s",
+ tab, tab->m_internalName.c_str()));
assert(! is_ndb_blob_table(tab));
unsigned i;
@@ -354,6 +361,17 @@ GlobalDictCache::release(NdbTableImpl * tab)
}
ver.m_refCount--;
+ if (ver.m_impl->m_status == NdbDictionary::Object::Invalid || invalidate)
+ {
+ ver.m_impl->m_status = NdbDictionary::Object::Invalid;
+ ver.m_status = DROPPED;
+ }
+ if (ver.m_refCount == 0 && ver.m_status == DROPPED)
+ {
+ DBUG_PRINT("info", ("refCount is zero, deleting m_impl"));
+ delete ver.m_impl;
+ vers->erase(i);
+ }
DBUG_VOID_RETURN;
}
}
@@ -374,6 +392,7 @@ GlobalDictCache::alter_table_rep(const char * name,
Uint32 tableVersion,
bool altered)
{
+ DBUG_ENTER("GlobalDictCache::alter_table_rep");
assert(! is_ndb_blob_table(name));
const Uint32 len = strlen(name);
Vector<TableVersion> * vers =
@@ -381,13 +400,13 @@ GlobalDictCache::alter_table_rep(const char * name,
if(vers == 0)
{
- return;
+ DBUG_VOID_RETURN;
}
const Uint32 sz = vers->size();
if(sz == 0)
{
- return;
+ DBUG_VOID_RETURN;
}
for(Uint32 i = 0; i < sz; i++)
@@ -399,15 +418,21 @@ GlobalDictCache::alter_table_rep(const char * name,
ver.m_status = DROPPED;
ver.m_impl->m_status = altered ?
NdbDictionary::Object::Altered : NdbDictionary::Object::Invalid;
- return;
+ if (ver.m_refCount == 0)
+ {
+ delete ver.m_impl;
+ vers->erase(i);
+ }
+ DBUG_VOID_RETURN;
}
if(i == sz - 1 && ver.m_status == RETREIVING)
{
ver.m_impl = altered ? &f_altered_table : &f_invalid_table;
- return;
+ DBUG_VOID_RETURN;
}
}
+ DBUG_VOID_RETURN;
}
template class Vector<GlobalDictCache::TableVersion>;
diff --git a/storage/ndb/src/ndbapi/DictCache.hpp b/storage/ndb/src/ndbapi/DictCache.hpp
index 2df6a139542..e909590e03e 100644
--- a/storage/ndb/src/ndbapi/DictCache.hpp
+++ b/storage/ndb/src/ndbapi/DictCache.hpp
@@ -33,6 +33,10 @@ public:
static Ndb_local_table_info *create(NdbTableImpl *table_impl, Uint32 sz=0);
static void destroy(Ndb_local_table_info *);
NdbTableImpl *m_table_impl;
+
+ // range of cached tuple ids per thread
+ Ndb::TupleIdRange m_tuple_id_range;
+
Uint64 m_local_data[1]; // Must be last member. Used to access extra space.
private:
Ndb_local_table_info(NdbTableImpl *table_impl);
@@ -63,14 +67,17 @@ public:
GlobalDictCache();
~GlobalDictCache();
+ NdbTableImpl * get(NdbTableImpl *tab);
NdbTableImpl * get(const char * name);
NdbTableImpl* put(const char * name, NdbTableImpl *);
- void drop(NdbTableImpl *);
- void release(NdbTableImpl *);
+ void release(NdbTableImpl *, int invalidate = 0);
void alter_table_rep(const char * name,
Uint32 tableId, Uint32 tableVersion, bool altered);
+
+ unsigned get_size();
+ void invalidate_all();
public:
enum Status {
OK = 0,
diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp
index ed54b894b64..60fdef8111e 100644
--- a/storage/ndb/src/ndbapi/Ndb.cpp
+++ b/storage/ndb/src/ndbapi/Ndb.cpp
@@ -747,188 +747,317 @@ 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.
****************************************************************************/
-Uint64
-Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
+int
+Ndb::getAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getAutoIncrementValue");
+ DBUG_ENTER("Ndb::getAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
BaseString internal_tabname(internalize_table_name(aTableName));
Ndb_local_table_info *info=
theDictionary->get_local_table_info(internal_tabname);
- if (info == 0)
- DBUG_RETURN(~(Uint64)0);
- const NdbTableImpl *table= info->m_table_impl;
- Uint64 tupleId = getTupleIdFromNdb(table->m_id, cacheSize);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ const NdbTableImpl* table = info->m_table_impl;
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize)
+int
+Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getAutoIncrementValue");
- if (aTable == 0)
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::getAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = getTupleIdFromNdb(table->m_id, cacheSize);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ const BaseString& internal_tabname = table->m_internalName;
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize)
+int
+Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId,
+ Uint32 cacheSize)
{
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0)
- return ~(Uint64)0;
- return getTupleIdFromNdb(table->m_id, cacheSize);
+ DBUG_ENTER("Ndb::getAutoIncrementValue");
+ assert(aTable != 0);
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+
+ if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize)
+int
+Ndb::getTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getTupleIdFromNdb");
- if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] )
+ DBUG_ENTER("Ndb::getTupleIdFromNdb");
+ if (range.m_first_tuple_id != range.m_last_tuple_id)
{
- theFirstTupleId[aTableId]++;
- DBUG_PRINT("info", ("next cached value %ul",
- (ulong) theFirstTupleId[aTableId]));
- DBUG_RETURN(theFirstTupleId[aTableId]);
+ assert(range.m_first_tuple_id < range.m_last_tuple_id);
+ tupleId = ++range.m_first_tuple_id;
+ DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId));
}
- else // theFirstTupleId == theLastTupleId
+ else
{
- DBUG_PRINT("info",("reading %u values from database",
- (cacheSize == 0) ? 1 : cacheSize));
- DBUG_RETURN(opTupleIdOnNdb(aTableId, (cacheSize == 0) ? 1 : cacheSize, 0));
+ if (cacheSize == 0)
+ cacheSize = 1;
+ DBUG_PRINT("info", ("reading %u values from database", (uint)cacheSize));
+ /*
+ * reserve next cacheSize entries in db. adds cacheSize to NEXTID
+ * and returns first tupleId in the new range.
+ */
+ Uint64 opValue = cacheSize;
+ if (opTupleIdOnNdb(table, range, opValue, 0) == -1)
+ DBUG_RETURN(-1);
+ tupleId = opValue;
}
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readAutoIncrementValue(const char* aTableName)
+int
+Ndb::readAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId)
{
- DBUG_ENTER("readAutoIncrementValue");
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0) {
- theError= theDictionary->getNdbError();
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::readAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
}
- Uint64 tupleId = readTupleIdFromNdb(table->m_id);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ const NdbTableImpl* table = info->m_table_impl;
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (readTupleIdFromNdb(table, range, tupleId) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable)
+int
+Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId)
{
- DBUG_ENTER("readAutoIncrementValue");
- if (aTable == 0)
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::readAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = readTupleIdFromNdb(table->m_id);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ const BaseString& internal_tabname = table->m_internalName;
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (readTupleIdFromNdb(table, range, tupleId) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readTupleIdFromNdb(Uint32 aTableId)
+int
+Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId)
{
- if ( theFirstTupleId[aTableId] == theLastTupleId[aTableId] )
- // Cache is empty, check next in database
- return opTupleIdOnNdb(aTableId, 0, 3);
+ DBUG_ENTER("Ndb::readAutoIncrementValue");
+ assert(aTable != 0);
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- return theFirstTupleId[aTableId] + 1;
+ if (readTupleIdFromNdb(table, range, tupleId) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-bool
-Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase)
+int
+Ndb::readTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId)
{
- DBUG_ENTER("setAutoIncrementValue");
+ DBUG_ENTER("Ndb::readTupleIdFromNdb");
+ if (range.m_first_tuple_id != range.m_last_tuple_id)
+ {
+ assert(range.m_first_tuple_id < range.m_last_tuple_id);
+ tupleId = range.m_first_tuple_id + 1;
+ }
+ else
+ {
+ /*
+ * peek at NEXTID. does not reserve it so the value is valid
+ * only if no other transactions are allowed.
+ */
+ Uint64 opValue = 0;
+ if (opTupleIdOnNdb(table, range, opValue, 3) == -1)
+ DBUG_RETURN(-1);
+ tupleId = opValue;
+ }
+ DBUG_RETURN(0);
+}
+
+int
+Ndb::setAutoIncrementValue(const char* aTableName,
+ Uint64 tupleId, bool increase)
+{
+ DBUG_ENTER("Ndb::setAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
BaseString internal_tabname(internalize_table_name(aTableName));
Ndb_local_table_info *info=
theDictionary->get_local_table_info(internal_tabname);
if (info == 0) {
- theError= theDictionary->getNdbError();
- DBUG_RETURN(false);
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
}
- const NdbTableImpl* table= info->m_table_impl;
- DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
+ const NdbTableImpl* table = info->m_table_impl;
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
}
-bool
-Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase)
+int
+Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 tupleId, bool increase)
{
- DBUG_ENTER("setAutoIncrementValue");
- if (aTable == 0)
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::setAutoIncrementValue");
+ ASSERT_NOT_MYSQLD;
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
+ const BaseString& internal_tabname = table->m_internalName;
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ TupleIdRange & range = info->m_tuple_id_range;
+ if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
}
-bool
-Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase )
+int
+Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 tupleId,
+ bool increase)
{
- DBUG_ENTER("setTupleIdInNdb(const char*, ...)");
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0) {
- theError= theDictionary->getNdbError();
- DBUG_RETURN(false);
- }
- DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
+ DBUG_ENTER("Ndb::setAutoIncrementValue");
+ assert(aTable != 0);
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+
+ if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
}
-bool
-Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase )
+int
+Ndb::setTupleIdInNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 tupleId, bool increase)
{
- DBUG_ENTER("setTupleIdInNdb(Uint32, ...)");
+ DBUG_ENTER("Ndb::setTupleIdInNdb");
if (increase)
{
- if (theFirstTupleId[aTableId] != theLastTupleId[aTableId])
+ if (range.m_first_tuple_id != range.m_last_tuple_id)
{
- // We have a cache sequence
- if (val <= theFirstTupleId[aTableId]+1)
- DBUG_RETURN(false);
- if (val <= theLastTupleId[aTableId])
+ assert(range.m_first_tuple_id < range.m_last_tuple_id);
+ if (tupleId <= range.m_first_tuple_id + 1)
+ DBUG_RETURN(0);
+ if (tupleId <= range.m_last_tuple_id)
{
- theFirstTupleId[aTableId] = val - 1;
- DBUG_RETURN(true);
+ range.m_first_tuple_id = tupleId - 1;
+ DBUG_PRINT("info",
+ ("Setting next auto increment cached value to %llu",
+ (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
- // else continue;
}
- DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 2) == val));
+ /*
+ * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to
+ * tupleId and set cached range to first = last = tupleId - 1.
+ */
+ if (opTupleIdOnNdb(table, range, tupleId, 2) == -1)
+ DBUG_RETURN(-1);
}
else
- DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 1) == val));
+ {
+ /*
+ * update NEXTID to given value. reset cached range.
+ */
+ if (opTupleIdOnNdb(table, range, tupleId, 1) == -1)
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+}
+
+int Ndb::initAutoIncrement()
+{
+ if (m_sys_tab_0)
+ return 0;
+
+ BaseString currentDb(getDatabaseName());
+ BaseString currentSchema(getDatabaseSchemaName());
+
+ setDatabaseName("sys");
+ setDatabaseSchemaName("def");
+
+ m_sys_tab_0 = getDictionary()->getTableGlobal("SYSTAB_0");
+
+ // Restore current name space
+ setDatabaseName(currentDb.c_str());
+ setDatabaseSchemaName(currentSchema.c_str());
+
+
+ return (m_sys_tab_0 == NULL);
}
-Uint64
-Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
+int
+Ndb::opTupleIdOnNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & opValue, Uint32 op)
{
DBUG_ENTER("Ndb::opTupleIdOnNdb");
+ Uint32 aTableId = table->m_id;
DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op));
NdbTransaction* tConnection;
NdbOperation* tOperation= 0; // Compiler warning if not initialized
Uint64 tValue;
NdbRecAttr* tRecAttrResult;
- int result;
- Uint64 ret;
CHECK_STATUS_MACRO_ZERO;
- BaseString currentDb(getDatabaseName());
- BaseString currentSchema(getDatabaseSchemaName());
+ if (initAutoIncrement())
+ goto error_return;
- setDatabaseName("sys");
- setDatabaseSchemaName("def");
tConnection = this->startTransaction();
if (tConnection == NULL)
goto error_return;
- if (usingFullyQualifiedNames())
- tOperation = tConnection->getNdbOperation("SYSTAB_0");
- else
- tOperation = tConnection->getNdbOperation("sys/def/SYSTAB_0");
+ tOperation = tConnection->getNdbOperation(m_sys_tab_0);
if (tOperation == NULL)
goto error_handler;
@@ -945,42 +1074,44 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
tValue = tRecAttrResult->u_64_value();
- theFirstTupleId[aTableId] = tValue - opValue;
- theLastTupleId[aTableId] = tValue - 1;
- ret = theFirstTupleId[aTableId];
+ range.m_first_tuple_id = tValue - opValue;
+ range.m_last_tuple_id = tValue - 1;
+ opValue = range.m_first_tuple_id; // out
break;
case 1:
- tOperation->updateTuple();
+ // create on first use
+ tOperation->writeTuple();
tOperation->equal("SYSKEY_0", aTableId );
tOperation->setValue("NEXTID", opValue);
if (tConnection->execute( Commit ) == -1 )
goto error_handler;
- theFirstTupleId[aTableId] = ~(Uint64)0;
- theLastTupleId[aTableId] = ~(Uint64)0;
- ret = opValue;
+ range.reset();
break;
case 2:
tOperation->interpretedUpdateTuple();
tOperation->equal("SYSKEY_0", aTableId );
tOperation->load_const_u64(1, opValue);
tOperation->read_attr("NEXTID", 2);
+ // compare NEXTID >= opValue
tOperation->branch_le(2, 1, 0);
tOperation->write_attr("NEXTID", 1);
tOperation->interpret_exit_ok();
tOperation->def_label(0);
tOperation->interpret_exit_nok(9999);
- if ( (result = tConnection->execute( Commit )) == -1 )
- goto error_handler;
-
- if (result == 9999)
- ret = ~(Uint64)0;
+ if (tConnection->execute( Commit ) == -1)
+ {
+ if (tConnection->theError.code != 9999)
+ goto error_handler;
+ }
else
{
- theFirstTupleId[aTableId] = theLastTupleId[aTableId] = opValue - 1;
- ret = opValue;
+ DBUG_PRINT("info",
+ ("Setting next auto increment value (db) to %llu",
+ (ulonglong)opValue));
+ range.m_first_tuple_id = range.m_last_tuple_id = opValue - 1;
}
break;
case 3:
@@ -989,7 +1120,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
tRecAttrResult = tOperation->getValue("NEXTID");
if (tConnection->execute( Commit ) == -1 )
goto error_handler;
- ret = tRecAttrResult->u_64_value();
+ opValue = tRecAttrResult->u_64_value(); // out
break;
default:
goto error_handler;
@@ -997,25 +1128,17 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
this->closeTransaction(tConnection);
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
- DBUG_RETURN(ret);
+ DBUG_RETURN(0);
error_handler:
theError.code = tConnection->theError.code;
this->closeTransaction(tConnection);
error_return:
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
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);
+ DBUG_RETURN(-1);
}
Uint32
@@ -1279,6 +1402,7 @@ NdbEventOperation* Ndb::createEventOperation(const char* eventName)
int Ndb::dropEventOperation(NdbEventOperation* tOp)
{
DBUG_ENTER("Ndb::dropEventOperation");
+ DBUG_PRINT("info", ("name: %s", tOp->getEvent()->getTable()->getName()));
// remove it from list
NdbEventOperationImpl *op=
NdbEventBuffer::getEventOperationImpl(tOp);
@@ -1289,6 +1413,8 @@ int Ndb::dropEventOperation(NdbEventOperation* tOp)
else
theImpl->m_ev_op= op->m_next;
+ DBUG_PRINT("info", ("first: %s",
+ theImpl->m_ev_op ? theImpl->m_ev_op->getEvent()->getTable()->getName() : "<empty>"));
assert(theImpl->m_ev_op == 0 || theImpl->m_ev_op->m_prev == 0);
theEventBuffer->dropEventOperation(tOp);
@@ -1313,6 +1439,12 @@ Ndb::pollEvents(int aMillisecondNumber, Uint64 *latestGCI)
return theEventBuffer->pollEvents(aMillisecondNumber, latestGCI);
}
+int
+Ndb::flushIncompleteEvents(Uint64 gci)
+{
+ return theEventBuffer->flushIncompleteEvents(gci);
+}
+
NdbEventOperation *Ndb::nextEvent()
{
return theEventBuffer->nextEvent();
diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp
index 00f71a2f85b..4e3e13b59bf 100644
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp
@@ -23,6 +23,7 @@
#include <NdbBlob.hpp>
#include "NdbBlobImpl.hpp"
#include <NdbScanOperation.hpp>
+#include <signaldata/TcKeyReq.hpp>
#include <NdbEventOperationImpl.hpp>
/*
@@ -392,6 +393,13 @@ NdbBlob::isScanOp()
theNdbOp->theOperationType == NdbOperation::OpenRangeScanRequest;
}
+inline bool
+NdbBlob::isTakeOverOp()
+{
+ return
+ TcKeyReq::getTakeOverScanFlag(theNdbOp->theScanInfo);
+}
+
// computations (inline)
inline Uint32
@@ -1527,8 +1535,22 @@ NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch)
if (isUpdateOp() || isWriteOp() || isDeleteOp()) {
// add operation before this one to read head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable, theNdbOp);
+ /*
+ * If main op is from take over scan lock, the added read is done
+ * as committed read:
+ *
+ * In normal transactional case, the row is locked by us and
+ * committed read returns same as normal read.
+ *
+ * In current TRUNCATE TABLE, the deleting trans is committed in
+ * batches and then restarted with new trans id. A normal read
+ * would hang on the scan delete lock and then fail.
+ */
+ NdbOperation::LockMode lockMode =
+ ! isTakeOverOp() ?
+ NdbOperation::LM_Read : NdbOperation::LM_CommittedRead;
if (tOp == NULL ||
- tOp->readTuple() == -1 ||
+ tOp->readTuple(lockMode) == -1 ||
setTableKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp
index 0c9243887d0..e844dc3369e 100644
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp
@@ -559,6 +559,11 @@ NdbDictionary::Table::getObjectStatus() const {
return m_impl.m_status;
}
+void
+NdbDictionary::Table::setStatusInvalid() const {
+ m_impl.m_status = NdbDictionary::Object::Invalid;
+}
+
int
NdbDictionary::Table::getObjectVersion() const {
return m_impl.m_version;
@@ -772,17 +777,17 @@ NdbDictionary::Index::getLogging() const {
NdbDictionary::Object::Status
NdbDictionary::Index::getObjectStatus() const {
- return m_impl.m_status;
+ return m_impl.m_table->m_status;
}
int
NdbDictionary::Index::getObjectVersion() const {
- return m_impl.m_version;
+ return m_impl.m_table->m_version;
}
int
NdbDictionary::Index::getObjectId() const {
- return m_impl.m_id;
+ return m_impl.m_table->m_id;
}
@@ -1331,6 +1336,11 @@ NdbDictionary::Dictionary::dropTable(Table & t){
}
int
+NdbDictionary::Dictionary::dropTableGlobal(const Table & t){
+ return m_impl.dropTableGlobal(NdbTableImpl::getImpl(t));
+}
+
+int
NdbDictionary::Dictionary::dropTable(const char * name){
return m_impl.dropTable(name);
}
@@ -1340,6 +1350,14 @@ NdbDictionary::Dictionary::alterTable(const Table & t){
return m_impl.alterTable(NdbTableImpl::getImpl(t));
}
+int
+NdbDictionary::Dictionary::alterTableGlobal(const Table & f,
+ const Table & t)
+{
+ return m_impl.alterTableGlobal(NdbTableImpl::getImpl(f),
+ NdbTableImpl::getImpl(t));
+}
+
const NdbDictionary::Table *
NdbDictionary::Dictionary::getTable(const char * name, void **data) const
{
@@ -1349,6 +1367,40 @@ NdbDictionary::Dictionary::getTable(const char * name, void **data) const
return 0;
}
+const NdbDictionary::Index *
+NdbDictionary::Dictionary::getIndexGlobal(const char * indexName,
+ const Table &ndbtab) const
+{
+ NdbIndexImpl * i = m_impl.getIndexGlobal(indexName,
+ NdbTableImpl::getImpl(ndbtab));
+ if(i)
+ return i->m_facade;
+ return 0;
+}
+
+const NdbDictionary::Table *
+NdbDictionary::Dictionary::getTableGlobal(const char * name) const
+{
+ NdbTableImpl * t = m_impl.getTableGlobal(name);
+ if(t)
+ return t->m_facade;
+ return 0;
+}
+
+int
+NdbDictionary::Dictionary::removeIndexGlobal(const Index &ndbidx,
+ int invalidate) const
+{
+ return m_impl.releaseIndexGlobal(NdbIndexImpl::getImpl(ndbidx), invalidate);
+}
+
+int
+NdbDictionary::Dictionary::removeTableGlobal(const Table &ndbtab,
+ int invalidate) const
+{
+ return m_impl.releaseTableGlobal(NdbTableImpl::getImpl(ndbtab), invalidate);
+}
+
void NdbDictionary::Dictionary::putTable(const NdbDictionary::Table * table)
{
NdbDictionary::Table *copy_table = new NdbDictionary::Table;
@@ -1396,18 +1448,37 @@ NdbDictionary::Dictionary::invalidateTable(const char * name){
}
void
+NdbDictionary::Dictionary::invalidateTable(const Table *table){
+ NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+ m_impl.invalidateObject(t);
+}
+
+void
NdbDictionary::Dictionary::removeCachedTable(const char * name){
NdbTableImpl * t = m_impl.getTable(name);
if(t)
m_impl.removeCachedObject(* t);
}
+void
+NdbDictionary::Dictionary::removeCachedTable(const Table *table){
+ NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+ m_impl.removeCachedObject(t);
+}
+
int
NdbDictionary::Dictionary::createIndex(const Index & ind)
{
return m_impl.createIndex(NdbIndexImpl::getImpl(ind));
}
+int
+NdbDictionary::Dictionary::createIndex(const Index & ind, const Table & tab)
+{
+ return m_impl.createIndex(NdbIndexImpl::getImpl(ind),
+ NdbTableImpl::getImpl(tab));
+}
+
int
NdbDictionary::Dictionary::dropIndex(const char * indexName,
const char * tableName)
@@ -1415,6 +1486,12 @@ NdbDictionary::Dictionary::dropIndex(const char * indexName,
return m_impl.dropIndex(indexName, tableName);
}
+int
+NdbDictionary::Dictionary::dropIndexGlobal(const Index &ind)
+{
+ return m_impl.dropIndexGlobal(NdbIndexImpl::getImpl(ind));
+}
+
const NdbDictionary::Index *
NdbDictionary::Dictionary::getIndex(const char * indexName,
const char * tableName) const
@@ -1426,6 +1503,15 @@ NdbDictionary::Dictionary::getIndex(const char * indexName,
}
void
+NdbDictionary::Dictionary::invalidateIndex(const Index *index){
+ DBUG_ENTER("NdbDictionary::Dictionary::invalidateIndex");
+ NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+ assert(i.m_table != 0);
+ m_impl.invalidateObject(* i.m_table);
+ DBUG_VOID_RETURN;
+}
+
+void
NdbDictionary::Dictionary::invalidateIndex(const char * indexName,
const char * tableName){
DBUG_ENTER("NdbDictionaryImpl::invalidateIndex");
@@ -1444,6 +1530,15 @@ NdbDictionary::Dictionary::forceGCPWait()
}
void
+NdbDictionary::Dictionary::removeCachedIndex(const Index *index){
+ DBUG_ENTER("NdbDictionary::Dictionary::removeCachedIndex");
+ NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+ assert(i.m_table != 0);
+ m_impl.removeCachedObject(* i.m_table);
+ DBUG_VOID_RETURN;
+}
+
+void
NdbDictionary::Dictionary::removeCachedIndex(const char * indexName,
const char * tableName){
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 07895648107..42428c49e26 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -43,13 +43,21 @@
#include <my_sys.h>
#include <NdbEnv.h>
#include <NdbMem.h>
+#include <ndb_version.h>
#define DEBUG_PRINT 0
#define INCOMPATIBLE_VERSION -2
#define DICT_WAITFOR_TIMEOUT (7*24*60*60*1000)
+#define ERR_RETURN(a,b) \
+{\
+ DBUG_PRINT("exit", ("error %d", (a).code));\
+ DBUG_RETURN(b);\
+}
+
extern Uint64 g_latest_trans_gci;
+int ndb_dictionary_is_mysqld = 0;
bool
is_ndb_blob_table(const char* name, Uint32* ptab_id, Uint32* pcol_no)
@@ -71,18 +79,26 @@ is_ndb_blob_table(const NdbTableImpl* t)
NdbColumnImpl::NdbColumnImpl()
: NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
{
+ DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
: NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
{
+ DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbColumnImpl&
NdbColumnImpl::operator=(const NdbColumnImpl& col)
{
+ DBUG_ENTER("NdbColumnImpl::operator=");
+ DBUG_PRINT("info", ("this: %p &col: %p", this, &col));
m_attrId = col.m_attrId;
m_name = col.m_name;
m_type = col.m_type;
@@ -104,13 +120,14 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
if (col.m_blobTable == NULL)
m_blobTable = NULL;
else {
- m_blobTable = new NdbTableImpl();
+ if (m_blobTable == NULL)
+ m_blobTable = new NdbTableImpl();
m_blobTable->assign(*col.m_blobTable);
}
m_column_no = col.m_column_no;
// Do not copy m_facade !!
- return *this;
+ DBUG_RETURN(*this);
}
void
@@ -253,15 +270,19 @@ NdbColumnImpl::init(Type t)
NdbColumnImpl::~NdbColumnImpl()
{
+ DBUG_ENTER("NdbColumnImpl::~NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
if (m_blobTable != NULL)
delete m_blobTable;
m_blobTable = NULL;
+ DBUG_VOID_RETURN;
}
bool
NdbColumnImpl::equal(const NdbColumnImpl& col) const
{
DBUG_ENTER("NdbColumnImpl::equal");
+ DBUG_PRINT("info", ("this: %p &col: %p", this, &col));
if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
DBUG_RETURN(false);
}
@@ -369,24 +390,33 @@ NdbTableImpl::NdbTableImpl()
: NdbDictionary::Table(* this),
NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
{
+ DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
: NdbDictionary::Table(* this),
NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
{
+ DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbTableImpl::~NdbTableImpl()
{
+ DBUG_ENTER("NdbTableImpl::~NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
if (m_index != 0) {
delete m_index;
m_index = 0;
}
for (unsigned i = 0; i < m_columns.size(); i++)
- delete m_columns[i];
+ delete m_columns[i];
+ DBUG_VOID_RETURN;
}
void
@@ -628,6 +658,8 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
void
NdbTableImpl::assign(const NdbTableImpl& org)
{
+ DBUG_ENTER("NdbColumnImpl::assign");
+ DBUG_PRINT("info", ("this: %p &org: %p", this, &org));
/* m_changeMask intentionally not copied */
m_primaryTableId = org.m_primaryTableId;
m_internalName.assign(org.m_internalName);
@@ -654,7 +686,14 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
is state calculated by computeAggregates and buildColumnHash
*/
- for(unsigned i = 0; i<org.m_columns.size(); i++){
+ unsigned i;
+ for(i = 0; i < m_columns.size(); i++)
+ {
+ delete m_columns[i];
+ }
+ m_columns.clear();
+ for(i = 0; i < org.m_columns.size(); i++)
+ {
NdbColumnImpl * col = new NdbColumnImpl();
const NdbColumnImpl * iorg = org.m_columns[i];
(* col) = (* iorg);
@@ -694,6 +733,7 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_tablespace_name = org.m_tablespace_name;
m_tablespace_id= org.m_tablespace_id;
m_tablespace_version = org.m_tablespace_version;
+ DBUG_VOID_RETURN;
}
void NdbTableImpl::setName(const char * name)
@@ -1014,7 +1054,7 @@ NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
*/
NdbIndexImpl::NdbIndexImpl() :
- NdbDictionary::Index(* this),
+ NdbDictionary::Index(* this),
NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(this)
{
init();
@@ -1077,14 +1117,20 @@ NdbEventImpl::NdbEventImpl() :
NdbDictionary::Event(* this),
NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
{
+ DBUG_ENTER("NdbEventImpl::NdbEventImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
NdbDictionary::Event(* this),
NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
{
+ DBUG_ENTER("NdbEventImpl::NdbEventImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
void NdbEventImpl::init()
@@ -1100,10 +1146,13 @@ void NdbEventImpl::init()
NdbEventImpl::~NdbEventImpl()
{
+ DBUG_ENTER("NdbEventImpl::~NdbEventImpl");
+ DBUG_PRINT("info", ("this: %p", this));
for (unsigned i = 0; i < m_columns.size(); i++)
delete m_columns[i];
if (m_tableImpl)
delete m_tableImpl;
+ DBUG_VOID_RETURN;
}
void NdbEventImpl::setName(const char * name)
@@ -1126,11 +1175,14 @@ NdbEventImpl::setTable(const NdbDictionary::Table& table)
void
NdbEventImpl::setTable(NdbTableImpl *tableImpl)
{
+ DBUG_ENTER("NdbEventImpl::setTable");
+ DBUG_PRINT("info", ("this: %p tableImpl: %p", this, tableImpl));
DBUG_ASSERT(tableImpl->m_status != NdbDictionary::Object::Invalid);
if (!m_tableImpl)
m_tableImpl = new NdbTableImpl();
// Copy table, since event might be accessed from different threads
m_tableImpl->assign(*tableImpl);
+ DBUG_VOID_RETURN;
}
const NdbDictionary::Table *
@@ -1287,44 +1339,30 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
}
}
-Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
+NdbTableImpl *
+NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
{
+ DBUG_ENTER("fetchGlobalTableImplRef");
NdbTableImpl *impl;
m_globalHash->lock();
- impl = m_globalHash->get(internalTableName.c_str());
+ impl = m_globalHash->get(obj.m_name.c_str());
m_globalHash->unlock();
if (impl == 0){
- impl = m_receiver.getTable(internalTableName,
+ impl = m_receiver.getTable(obj.m_name.c_str(),
m_ndb.usingFullyQualifiedNames());
- if (impl != 0) {
- int ret = getBlobTables(*impl);
- if (ret != 0) {
- delete impl;
- impl = 0;
- }
+ if (impl != 0 && obj.init(*impl))
+ {
+ delete impl;
+ impl = 0;
}
-
m_globalHash->lock();
- m_globalHash->put(internalTableName.c_str(), impl);
+ m_globalHash->put(obj.m_name.c_str(), impl);
m_globalHash->unlock();
-
- if(impl == 0){
- return 0;
- }
}
- Ndb_local_table_info *info=
- Ndb_local_table_info::create(impl, m_local_table_data_size);
-
- m_localHash.put(internalTableName.c_str(), info);
-
- m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
- m_ndb.theLastTupleId[impl->getTableId()] = ~0;
-
- return info;
+ DBUG_RETURN(impl);
}
void
@@ -1349,9 +1387,6 @@ NdbDictionaryImpl::putTable(NdbTableImpl *impl)
Ndb_local_table_info::create(impl, m_local_table_data_size);
m_localHash.put(impl->m_internalName.c_str(), info);
-
- m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
- m_ndb.theLastTupleId[impl->getTableId()] = ~0;
}
int
@@ -1963,7 +1998,8 @@ indexTypeMapping[] = {
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const Uint32 * data, Uint32 len,
- bool fullyQualifiedNames)
+ bool fullyQualifiedNames,
+ Uint32 version)
{
SimplePropertiesLinearReader it(data, len);
DictTabInfo::Table *tableDesc;
@@ -2110,15 +2146,15 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
if(tableDesc->ReplicaDataLen > 0)
{
- Uint16 replicaCount = tableDesc->ReplicaData[0];
- Uint16 fragCount = tableDesc->ReplicaData[1];
+ Uint16 replicaCount = ntohs(tableDesc->ReplicaData[0]);
+ Uint16 fragCount = ntohs(tableDesc->ReplicaData[1]);
impl->m_replicaCount = replicaCount;
impl->m_fragmentCount = fragCount;
DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
for(i = 0; i < (Uint32) (fragCount*replicaCount); i++)
{
- impl->m_fragments.push_back(tableDesc->ReplicaData[i+2]);
+ impl->m_fragments.push_back(ntohs(tableDesc->ReplicaData[i+2]));
}
Uint32 topBit = (1 << 31);
@@ -2142,7 +2178,14 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
* ret = impl;
NdbMem_Free((void*)tableDesc);
- DBUG_ASSERT(impl->m_fragmentCount > 0);
+ if (version < MAKE_VERSION(5,1,3))
+ {
+ ;
+ }
+ else
+ {
+ DBUG_ASSERT(impl->m_fragmentCount > 0);
+ }
DBUG_RETURN(0);
}
@@ -2203,11 +2246,11 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t)
}
if (autoIncrement) {
// XXX unlikely race condition - t.m_id may no longer be same table
- if (! m_ndb.setTupleIdInNdb(t.m_id, initialValue, false)) {
- if (m_ndb.theError.code)
- m_error.code = m_ndb.theError.code;
- else
- m_error.code = 4336;
+ // the tuple id range is not used on input
+ Ndb::TupleIdRange range;
+ if (m_ndb.setTupleIdInNdb(&t, range, initialValue, false) == -1) {
+ assert(m_ndb.theError.code != 0);
+ m_error.code = m_ndb.theError.code;
delete t2;
DBUG_RETURN(-1);
}
@@ -2267,18 +2310,30 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
}
// Alter the table
- int ret = m_receiver.alterTable(m_ndb, impl);
- if(ret == 0){
- // Remove cached information and let it be refreshed at next access
+ int ret = alterTableGlobal(*local->m_table_impl, impl);
+ if(ret == 0)
+ {
m_globalHash->lock();
- local->m_table_impl->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(local->m_table_impl);
+ m_globalHash->release(local->m_table_impl, 1);
m_globalHash->unlock();
m_localHash.drop(originalInternalName);
}
DBUG_RETURN(ret);
}
+int NdbDictionaryImpl::alterTableGlobal(NdbTableImpl &old_impl,
+ NdbTableImpl &impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::alterTableGlobal");
+ // Alter the table
+ int ret = m_receiver.alterTable(m_ndb, impl);
+ old_impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0){
+ DBUG_RETURN(ret);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
int
NdbDictInterface::alterTable(Ndb & ndb,
NdbTableImpl & impl)
@@ -2722,6 +2777,7 @@ NdbDictionaryImpl::dropTable(const char * name)
{
DBUG_ENTER("NdbDictionaryImpl::dropTable");
DBUG_PRINT("enter",("name: %s", name));
+ ASSERT_NOT_MYSQLD;
NdbTableImpl * tab = getTable(name);
if(tab == 0){
DBUG_RETURN(-1);
@@ -2734,8 +2790,7 @@ NdbDictionaryImpl::dropTable(const char * name)
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->release(tab, 1);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
@@ -2783,8 +2838,7 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
- impl.m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(&impl);
+ m_globalHash->release(&impl, 1);
m_globalHash->unlock();
return 0;
@@ -2794,6 +2848,50 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
}
int
+NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
+{
+ int res;
+ const char * name = impl.getName();
+ DBUG_ENTER("NdbDictionaryImpl::dropTableGlobal");
+ DBUG_ASSERT(impl.m_status != NdbDictionary::Object::New);
+ DBUG_ASSERT(impl.m_indexType == NdbDictionary::Object::TypeUndefined);
+
+ List list;
+ if ((res = listIndexes(list, impl.m_id)) == -1){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ for (unsigned i = 0; i < list.count; i++) {
+ const List::Element& element = list.elements[i];
+ NdbIndexImpl *idx= getIndexGlobal(element.name, impl);
+ if (idx == NULL)
+ {
+ ERR_RETURN(getNdbError(), -1);
+ }
+ if ((res = dropIndexGlobal(*idx)) == -1)
+ {
+ releaseIndexGlobal(*idx, 1);
+ ERR_RETURN(getNdbError(), -1);
+ }
+ releaseIndexGlobal(*idx, 1);
+ }
+
+ if (impl.m_noOfBlobs != 0) {
+ if (dropBlobTables(impl) != 0){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ }
+
+ int ret = m_receiver.dropTable(impl);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0 || m_error.code == 709 || m_error.code == 723)
+ {
+ DBUG_RETURN(0);
+ }
+
+ ERR_RETURN(getNdbError(), ret);
+}
+
+int
NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
DBUG_ENTER("NdbDictionaryImpl::dropBlobTables");
@@ -2813,7 +2911,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
DBUG_PRINT("info", ("col %s: blob table %s: error %d",
c.m_name.c_str(), bt->m_internalName.c_str(), m_error.code));
if (! (ret == 709 || ret == 723)) // "force" mode on
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
// leave c.m_blobTable defined
}
@@ -2882,8 +2980,7 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
- impl.m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(&impl);
+ m_globalHash->release(&impl, 1);
m_globalHash->unlock();
DBUG_RETURN(0);
}
@@ -2902,53 +2999,12 @@ NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
DBUG_RETURN(0);
}
-/*****************************************************************
- * Get index info
- */
-NdbIndexImpl*
-NdbDictionaryImpl::getIndexImpl(const char * externalName,
- const BaseString& internalName)
-{
- Ndb_local_table_info * info = get_local_table_info(internalName);
- if(info == 0){
- m_error.code = 4243;
- return 0;
- }
- NdbTableImpl * tab = info->m_table_impl;
-
- if(tab->m_indexType == NdbDictionary::Object::TypeUndefined)
- {
- // Not an index
- m_error.code = 4243;
- return 0;
- }
-
- NdbTableImpl* prim = getTable(tab->m_primaryTable.c_str());
- if(prim == 0){
- m_error.code = 4243;
- return 0;
- }
-
- /**
- * Create index impl
- */
- NdbIndexImpl* idx;
- if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
- idx->m_table = tab;
- idx->m_externalName.assign(externalName);
- idx->m_internalName.assign(internalName);
- // TODO Assign idx to tab->m_index
- // Don't do it right now since assign can't asign a table with index
- // tab->m_index = idx;
- return idx;
- }
- return 0;
-}
-
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
NdbTableImpl* tab,
- const NdbTableImpl* prim){
+ const NdbTableImpl* prim)
+{
+ DBUG_ENTER("NdbDictInterface::create_index_obj_from_table");
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
idx->m_status = tab->m_status;
@@ -3000,9 +3056,12 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
tab->m_columns[i]->m_distributionKey = 0;
}
+ idx->m_table_id = prim->getObjectId();
+ idx->m_table_version = prim->getObjectVersion();
+
* dst = idx;
-
- return 0;
+ DBUG_PRINT("exit", ("m_id: %d m_version: %d", idx->m_id, idx->m_version));
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -3011,6 +3070,7 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
int
NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
{
+ ASSERT_NOT_MYSQLD;
NdbTableImpl* tab = getTable(ix.getTable());
if(tab == 0){
m_error.code = 4249;
@@ -3020,6 +3080,12 @@ NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
return m_receiver.createIndex(m_ndb, ix, * tab);
}
+int
+NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, NdbTableImpl &tab)
+{
+ return m_receiver.createIndex(m_ndb, ix, tab);
+}
+
int
NdbDictInterface::createIndex(Ndb & ndb,
const NdbIndexImpl & impl,
@@ -3126,6 +3192,7 @@ int
NdbDictionaryImpl::dropIndex(const char * indexName,
const char * tableName)
{
+ ASSERT_NOT_MYSQLD;
NdbIndexImpl * idx = getIndex(indexName, tableName);
if (idx == 0) {
m_error.code = 4243;
@@ -3143,8 +3210,7 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
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->release(idx->m_table, 1);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
@@ -3174,13 +3240,13 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
return dropIndex(indexName, tableName);
}
- int ret = m_receiver.dropIndex(impl, *timpl);
- if(ret == 0){
- m_localHash.drop(internalIndexName.c_str());
+ int ret= dropIndexGlobal(impl);
+ if (ret == 0)
+ {
m_globalHash->lock();
- impl.m_table->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(impl.m_table);
+ m_globalHash->release(impl.m_table, 1);
m_globalHash->unlock();
+ m_localHash.drop(internalIndexName.c_str());
}
return ret;
}
@@ -3190,9 +3256,25 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
}
int
+NdbDictionaryImpl::dropIndexGlobal(NdbIndexImpl & impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::dropIndexGlobal");
+ int ret = m_receiver.dropIndex(impl, *impl.m_table);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0)
+ {
+ DBUG_RETURN(0);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
+int
NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
const NdbTableImpl & timpl)
{
+ DBUG_ENTER("NdbDictInterface::dropIndex");
+ DBUG_PRINT("enter", ("indexId: %d indexVersion: %d",
+ timpl.m_id, timpl.m_version));
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_INDX_REQ;
@@ -3214,9 +3296,9 @@ NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
errCodes);
if(m_error.code == DropIndxRef::InvalidIndexVersion) {
// Clear caches and try again
- return INCOMPATIBLE_VERSION;
+ ERR_RETURN(m_error, INCOMPATIBLE_VERSION);
}
- return r;
+ ERR_RETURN(m_error, r);
}
void
@@ -3253,7 +3335,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
if(tab == 0){
DBUG_PRINT("info",("NdbDictionaryImpl::createEvent: table not found: %s",
evnt.getTableName()));
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
evnt.setTable(tab);
}
@@ -3272,7 +3354,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
evnt.getTableName());
m_error.code= 4713;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
}
@@ -3293,7 +3375,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
m_error.code= 4247;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
// Copy column definition
*evnt.m_columns[i] = *col;
@@ -3319,7 +3401,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
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;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
}
@@ -3331,14 +3413,14 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
// NdbDictInterface m_receiver;
if (m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */) != 0)
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
// Create blob events
if (evnt.m_mergeEvents && createBlobEvents(evnt) != 0) {
int save_code = m_error.code;
(void)dropEvent(evnt.m_name.c_str());
m_error.code = save_code;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
DBUG_RETURN(0);
}
@@ -3358,7 +3440,7 @@ NdbDictionaryImpl::createBlobEvents(NdbEventImpl& evnt)
NdbEventImpl blob_evnt;
NdbBlob::getBlobEvent(blob_evnt, &evnt, &c);
if (createEvent(blob_evnt) != 0)
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
DBUG_RETURN(0);
}
@@ -3409,7 +3491,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
const size_t len = strlen(evnt.m_name.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code= 4241;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
@@ -3433,7 +3515,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
0, -1);
if (ret) {
- DBUG_RETURN(ret);
+ ERR_RETURN(getNdbError(), ret);
}
char *dataPtr = (char *)m_buffer.get_data();
@@ -3459,7 +3541,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
evnt.mi_type != evntConf->getEventType()) {
ndbout_c("ERROR*************");
- DBUG_RETURN(1);
+ ERR_RETURN(getNdbError(), 1);
}
}
@@ -3546,7 +3628,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
DBUG_ENTER("NdbDictionaryImpl::getEvent");
DBUG_PRINT("enter",("eventName= %s", eventName));
- NdbEventImpl *ev = new NdbEventImpl();
+ NdbEventImpl *ev = new NdbEventImpl();
if (ev == NULL) {
DBUG_RETURN(NULL);
}
@@ -3560,35 +3642,39 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
DBUG_RETURN(NULL);
}
- if (tab == NULL) {
- // We only have the table name with internal name
- DBUG_PRINT("info",("table %s", ev->getTableName()));
- Ndb_local_table_info *info;
- info= get_local_table_info(ev->getTableName());
- if (info == 0)
+ // We only have the table name with internal name
+ DBUG_PRINT("info",("table %s", ev->getTableName()));
+ if (tab == NULL)
+ {
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
{
DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
delete ev;
DBUG_RETURN(NULL);
}
- if ((info->m_table_impl->m_status != NdbDictionary::Object::Retrieved) ||
- (info->m_table_impl->m_id != ev->m_table_id) ||
- (table_version_major(info->m_table_impl->m_version) !=
+ if ((tab->m_status != NdbDictionary::Object::Retrieved) ||
+ (tab->m_id != ev->m_table_id) ||
+ (table_version_major(tab->m_version) !=
table_version_major(ev->m_table_version)))
{
- removeCachedObject(*info->m_table_impl);
- info= get_local_table_info(ev->getTableName());
- if (info == 0)
+ DBUG_PRINT("info", ("mismatch on verison in cache"));
+ releaseTableGlobal(*tab, 1);
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
{
DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
delete ev;
DBUG_RETURN(NULL);
}
}
- tab = info->m_table_impl;
+ ev->setTable(tab);
+ releaseTableGlobal(*tab, 0);
}
+ else
+ ev->setTable(tab);
+ tab = 0;
- ev->setTable(tab);
ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
// get the columns from the attrListBitmask
NdbTableImpl &table = *ev->m_tableImpl;
@@ -3844,9 +3930,11 @@ NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt)
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
n--;
- char bename[MAX_TAB_NAME_SIZE];
- NdbBlob::getBlobEventName(bename, &evnt, &c);
- (void)dropEvent(bename);
+ NdbEventImpl* blob_evnt = getBlobEvent(evnt, i);
+ if (blob_evnt == NULL)
+ continue;
+ (void)dropEvent(*blob_evnt);
+ delete blob_evnt;
}
} else {
// loop over MAX_ATTRIBUTES_IN_TABLE ...
@@ -4400,7 +4488,7 @@ NdbDictInterface::create_file(const NdbFileImpl & file,
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
- int err[] = { CreateFileRef::Busy, 0};
+ int err[] = { CreateFileRef::Busy, CreateFileRef::NotMaster, 0};
/*
Send signal without time-out since creating files can take a very long
time if the file is very big.
@@ -4444,7 +4532,7 @@ NdbDictInterface::drop_file(const NdbFileImpl & file){
req->file_id = file.m_id;
req->file_version = file.m_version;
- int err[] = { DropFileRef::Busy, 0};
+ int err[] = { DropFileRef::Busy, DropFileRef::NotMaster, 0};
DBUG_RETURN(dictSignal(&tSignal, 0, 0,
0, // master
WAIT_CREATE_INDX_REQ,
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 01aa6b09c90..9b63acf6d36 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -35,6 +35,9 @@ is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
bool
is_ndb_blob_table(const class NdbTableImpl* t);
+extern int ndb_dictionary_is_mysqld;
+#define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
+
class NdbDictObjectImpl {
public:
int m_id;
@@ -253,6 +256,8 @@ public:
BaseString m_internalName;
BaseString m_externalName;
BaseString m_tableName;
+ Uint32 m_table_id;
+ Uint32 m_table_version;
Vector<NdbColumnImpl *> m_columns;
Vector<int> m_key_ids;
@@ -454,7 +459,8 @@ public:
static int parseTableInfo(NdbTableImpl ** dst,
const Uint32 * data, Uint32 len,
- bool fullyQualifiedNames);
+ bool fullyQualifiedNames,
+ Uint32 version= 0xFFFFFFFF);
static int parseFileInfo(NdbFileImpl &dst,
const Uint32 * data, Uint32 len);
@@ -538,6 +544,21 @@ private:
UtilBuffer m_buffer;
};
+class NdbDictionaryImpl;
+class GlobalCacheInitObject
+{
+public:
+ NdbDictionaryImpl *m_dict;
+ const BaseString &m_name;
+ GlobalCacheInitObject(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ m_dict(dict),
+ m_name(name)
+ {}
+ virtual ~GlobalCacheInitObject() {}
+ virtual int init(NdbTableImpl &tab) const = 0;
+};
+
class NdbDictionaryImpl : public NdbDictionary::Dictionary {
public:
NdbDictionaryImpl(Ndb &ndb);
@@ -557,6 +578,7 @@ public:
int removeCachedObject(NdbTableImpl &);
int createIndex(NdbIndexImpl &ix);
+ int createIndex(NdbIndexImpl &ix, NdbTableImpl & tab);
int dropIndex(const char * indexName,
const char * tableName);
int dropIndex(NdbIndexImpl &, const char * tableName);
@@ -577,6 +599,15 @@ public:
int listObjects(List& list, NdbDictionary::Object::Type type);
int listIndexes(List& list, Uint32 indexId);
+ NdbTableImpl * getTableGlobal(const char * tableName);
+ NdbIndexImpl * getIndexGlobal(const char * indexName,
+ NdbTableImpl &ndbtab);
+ int alterTableGlobal(NdbTableImpl &orig_impl, NdbTableImpl &impl);
+ int dropTableGlobal(NdbTableImpl &);
+ int dropIndexGlobal(NdbIndexImpl & impl);
+ int releaseTableGlobal(NdbTableImpl & impl, int invalidate);
+ int releaseIndexGlobal(NdbIndexImpl & impl, int invalidate);
+
NdbTableImpl * getTable(const char * tableName, void **data= 0);
NdbTableImpl * getBlobTable(const NdbTableImpl&, uint col_no);
NdbTableImpl * getBlobTable(uint tab_id, uint col_no);
@@ -586,6 +617,7 @@ public:
get_local_table_info(const BaseString& internalTableName);
NdbIndexImpl * getIndex(const char * indexName,
const char * tableName);
+ NdbIndexImpl * getIndex(const char * indexName, const NdbTableImpl& prim);
NdbEventImpl * getEvent(const char * eventName, NdbTableImpl* = NULL);
NdbEventImpl * getBlobEvent(const NdbEventImpl& ev, uint col_no);
NdbEventImpl * getEventImpl(const char * internalName);
@@ -615,10 +647,14 @@ public:
NdbDictInterface m_receiver;
Ndb & m_ndb;
-private:
+ NdbIndexImpl* getIndexImpl(const char * externalName,
+ const BaseString& internalName,
+ NdbTableImpl &tab,
+ NdbTableImpl &prim);
NdbIndexImpl * getIndexImpl(const char * name,
const BaseString& internalName);
- Ndb_local_table_info * fetchGlobalTableImpl(const BaseString& internalName);
+private:
+ NdbTableImpl * fetchGlobalTableImplRef(const GlobalCacheInitObject &obj);
};
inline
@@ -851,6 +887,27 @@ NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
* Inline:d getters
*/
+class InitTable : public GlobalCacheInitObject
+{
+public:
+ InitTable(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ GlobalCacheInitObject(dict, name)
+ {}
+ int init(NdbTableImpl &tab) const
+ {
+ return m_dict->getBlobTables(tab);
+ }
+};
+
+inline
+NdbTableImpl *
+NdbDictionaryImpl::getTableGlobal(const char * table_name)
+{
+ const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
+ return fetchGlobalTableImplRef(InitTable(this, internal_tabname));
+}
+
inline
NdbTableImpl *
NdbDictionaryImpl::getTable(const char * table_name, void **data)
@@ -884,45 +941,164 @@ NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName)
DBUG_PRINT("enter", ("table: %s", internalTableName.c_str()));
Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
- if (info == 0) {
- info= fetchGlobalTableImpl(internalTableName);
- if (info == 0) {
- DBUG_RETURN(0);
+ if (info == 0)
+ {
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitTable(this, internalTableName));
+ if (tab)
+ {
+ info= Ndb_local_table_info::create(tab, m_local_table_data_size);
+ if (info)
+ {
+ m_localHash.put(internalTableName.c_str(), info);
+ }
}
}
DBUG_RETURN(info); // autoincrement already initialized
}
+class InitIndex : public GlobalCacheInitObject
+{
+public:
+ const char *m_index_name;
+ const NdbTableImpl &m_prim;
+
+ InitIndex(const BaseString &internal_indexname,
+ const char *index_name,
+ const NdbTableImpl &prim) :
+ GlobalCacheInitObject(0, internal_indexname),
+ m_index_name(index_name),
+ m_prim(prim)
+ {}
+
+ int init(NdbTableImpl &tab) const {
+ DBUG_ENTER("InitIndex::init");
+ DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
+ /**
+ * Create index impl
+ */
+ NdbIndexImpl* idx;
+ if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &m_prim) == 0)
+ {
+ idx->m_table = &tab;
+ idx->m_externalName.assign(m_index_name);
+ idx->m_internalName.assign(m_name);
+ tab.m_index = idx;
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(1);
+ }
+};
+
inline
NdbIndexImpl *
-NdbDictionaryImpl::getIndex(const char * index_name,
- const char * table_name)
+NdbDictionaryImpl::getIndexGlobal(const char * index_name,
+ NdbTableImpl &ndbtab)
{
- if (table_name || m_ndb.usingFullyQualifiedNames())
+ DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
+ const BaseString
+ internal_indexname(m_ndb.internalize_index_name(&ndbtab, index_name));
+ int retry= 2;
+
+ while (retry)
{
- 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())
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitIndex(internal_indexname,
+ index_name, ndbtab));
+ if (tab)
{
- Ndb_local_table_info * info=
- get_local_table_info(internal_indexname);
- if (info)
+ // tab->m_index sould be set. otherwise tab == 0
+ NdbIndexImpl *idx= tab->m_index;
+ if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
+ idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
{
- NdbTableImpl * tab= info->m_table_impl;
- if (tab->m_index == 0)
- tab->m_index= getIndexImpl(index_name, internal_indexname);
- if (tab->m_index != 0)
- tab->m_index->m_table= tab;
- return tab->m_index;
+ releaseIndexGlobal(*idx, 1);
+ retry--;
+ continue;
}
+ DBUG_RETURN(idx);
}
+ break;
+ }
+ m_error.code= 4243;
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseTableGlobal(NdbTableImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseTableGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(&impl, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseIndexGlobal(NdbIndexImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseIndexGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(impl.m_table, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+
+inline
+NdbIndexImpl *
+NdbDictionaryImpl::getIndex(const char * index_name,
+ const char * table_name)
+{
+ if (table_name == 0)
+ {
+ assert(0);
+ m_error.code= 4243;
+ return 0;
+ }
+
+
+ NdbTableImpl* prim = getTable(table_name);
+ if (prim == 0)
+ {
+ m_error.code= 4243;
+ return 0;
}
+ return getIndex(index_name, *prim);
+}
+
+inline
+NdbIndexImpl *
+NdbDictionaryImpl::getIndex(const char* index_name,
+ const NdbTableImpl& prim)
+{
+
+ const BaseString
+ internal_indexname(m_ndb.internalize_index_name(&prim, index_name));
+
+ Ndb_local_table_info *info= m_localHash.get(internal_indexname.c_str());
+ NdbTableImpl *tab;
+ if (info == 0)
+ {
+ tab= fetchGlobalTableImplRef(InitIndex(internal_indexname,
+ index_name,
+ prim));
+ if (!tab)
+ goto err;
+
+ info= Ndb_local_table_info::create(tab, 0);
+ if (!info)
+ goto err;
+ m_localHash.put(internal_indexname.c_str(), info);
+ }
+ else
+ tab= info->m_table_impl;
+
+ return tab->m_index;
+
+err:
m_error.code= 4243;
return 0;
}
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index f282ab825f0..a5fbd84e5b0 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -46,7 +46,7 @@
#include <EventLogger.hpp>
extern EventLogger g_eventLogger;
-static Gci_container g_empty_gci_container;
+static Gci_container_pod g_empty_gci_container;
static const Uint32 ACTIVE_GCI_DIRECTORY_SIZE = 4;
static const Uint32 ACTIVE_GCI_MASK = ACTIVE_GCI_DIRECTORY_SIZE - 1;
@@ -70,21 +70,6 @@ print_std(const SubTableData * sdata, LinearSectionPtr ptr[3])
*
*/
-//#define EVENT_DEBUG
-#ifdef EVENT_DEBUG
-#define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
-#define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
-#define DBUG_VOID_RETURN_EVENT DBUG_VOID_RETURN
-#define DBUG_PRINT_EVENT(A,B) DBUG_PRINT(A,B)
-#define DBUG_DUMP_EVENT(A,B,C) DBUG_DUMP(A,B,C)
-#else
-#define DBUG_ENTER_EVENT(A)
-#define DBUG_RETURN_EVENT(A) return(A)
-#define DBUG_VOID_RETURN_EVENT return
-#define DBUG_PRINT_EVENT(A,B)
-#define DBUG_DUMP_EVENT(A,B,C)
-#endif
-
// todo handle several ndb objects
// todo free allocated data when closing NdbEventBuffer
@@ -168,11 +153,14 @@ NdbEventOperationImpl::init(NdbEventImpl& evnt)
m_state= EO_CREATED;
+ m_node_bit_mask.clear();
#ifdef ndb_event_stores_merge_events_flag
m_mergeEvents = m_eventImpl->m_mergeEvents;
#else
- m_mergeEvents = false;
+ m_mergeEvents = false;
#endif
+ m_ref_count = 0;
+ DBUG_PRINT("info", ("m_ref_count = 0 for op: %p", this));
m_has_error= 0;
@@ -189,6 +177,17 @@ NdbEventOperationImpl::~NdbEventOperationImpl()
// m_bufferHandle->dropSubscribeEvent(m_bufferId);
; // ToDo? We should send stop signal here
+ if (theMainOp == NULL)
+ {
+ NdbEventOperationImpl* tBlobOp = theBlobOpList;
+ while (tBlobOp != NULL)
+ {
+ NdbEventOperationImpl *op = tBlobOp;
+ tBlobOp = tBlobOp->m_next;
+ delete op;
+ }
+ }
+
m_ndb->theImpl->theNdbObjectIdMap.unmap(m_oid, this);
DBUG_PRINT("exit",("this: %p/%p oid: %u main: %p",
this, m_facade, m_oid, theMainOp));
@@ -534,7 +533,11 @@ NdbEventOperationImpl::execute_nolock()
}
}
if (r == 0)
+ {
+ m_ref_count++;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", m_ref_count, this));
DBUG_RETURN(0);
+ }
}
//Error
m_state= EO_ERROR;
@@ -661,80 +664,79 @@ NdbEventOperationImpl::execSUB_TABLE_DATA(NdbApiSignal * signal,
int
NdbEventOperationImpl::receive_event()
{
- DBUG_ENTER_EVENT("NdbEventOperationImpl::receive_event");
-
Uint32 operation= (Uint32)m_data_item->sdata->operation;
- DBUG_PRINT_EVENT("info",("sdata->operation %u",operation));
-
- if (operation == NdbDictionary::Event::_TE_ALTER)
- {
- // Parse the new table definition and
- // create a table object
- NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
- NdbDictionaryImpl *dict = & NdbDictionaryImpl::getImpl(*myDict);
- NdbError error;
- NdbDictInterface dif(error);
- NdbTableImpl *at;
- m_change_mask = m_data_item->sdata->changeMask;
- error.code = dif.parseTableInfo(&at,
- (Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4,
- true);
- m_buffer.clear();
- if (at)
- at->buildColumnHash();
- else
- {
- DBUG_PRINT_EVENT("info", ("Failed to parse DictTabInfo error %u",
- error.code));
- DBUG_RETURN_EVENT(1);
- }
-
- NdbTableImpl *tmp_table_impl= m_eventImpl->m_tableImpl;
- m_eventImpl->m_tableImpl = at;
-
- DBUG_PRINT("info", ("switching table impl 0x%x -> 0x%x",
- tmp_table_impl, at));
-
- // change the rec attrs to refer to the new table object
- int i;
- for (i = 0; i < 2; i++)
+ if (unlikely(operation >= NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT))
+ {
+ DBUG_ENTER("NdbEventOperationImpl::receive_event");
+ DBUG_PRINT("info",("sdata->operation %u this: %p", operation, this));
+ if (operation == NdbDictionary::Event::_TE_ALTER)
{
- NdbRecAttr *p = theFirstPkAttrs[i];
- while (p)
+ // Parse the new table definition and
+ // create a table object
+ NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
+ NdbDictionaryImpl *dict = & NdbDictionaryImpl::getImpl(*myDict);
+ NdbError error;
+ NdbDictInterface dif(error);
+ NdbTableImpl *at;
+ m_change_mask = m_data_item->sdata->changeMask;
+ error.code = dif.parseTableInfo(&at,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4,
+ true);
+ m_buffer.clear();
+ if (unlikely(!at))
{
- int no = p->getColumn()->getColumnNo();
- NdbColumnImpl *tAttrInfo = at->getColumn(no);
- DBUG_PRINT("info", ("rec_attr: 0x%x "
- "switching column impl 0x%x -> 0x%x",
- p, p->m_column, tAttrInfo));
- p->m_column = tAttrInfo;
- p = p->next();
+ DBUG_PRINT("info", ("Failed to parse DictTabInfo error %u",
+ error.code));
+ ndbout_c("Failed to parse DictTabInfo error %u", error.code);
+ DBUG_RETURN(1);
}
- }
- for (i = 0; i < 2; i++)
- {
- NdbRecAttr *p = theFirstDataAttrs[i];
- while (p)
+ at->buildColumnHash();
+
+ NdbTableImpl *tmp_table_impl= m_eventImpl->m_tableImpl;
+ m_eventImpl->m_tableImpl = at;
+
+ DBUG_PRINT("info", ("switching table impl 0x%x -> 0x%x",
+ tmp_table_impl, at));
+
+ // change the rec attrs to refer to the new table object
+ int i;
+ for (i = 0; i < 2; i++)
{
- int no = p->getColumn()->getColumnNo();
- NdbColumnImpl *tAttrInfo = at->getColumn(no);
- DBUG_PRINT("info", ("rec_attr: 0x%x "
- "switching column impl 0x%x -> 0x%x",
- p, p->m_column, tAttrInfo));
- p->m_column = tAttrInfo;
- p = p->next();
+ NdbRecAttr *p = theFirstPkAttrs[i];
+ while (p)
+ {
+ int no = p->getColumn()->getColumnNo();
+ NdbColumnImpl *tAttrInfo = at->getColumn(no);
+ DBUG_PRINT("info", ("rec_attr: 0x%x "
+ "switching column impl 0x%x -> 0x%x",
+ p, p->m_column, tAttrInfo));
+ p->m_column = tAttrInfo;
+ p = p->next();
+ }
+ }
+ for (i = 0; i < 2; i++)
+ {
+ NdbRecAttr *p = theFirstDataAttrs[i];
+ while (p)
+ {
+ int no = p->getColumn()->getColumnNo();
+ NdbColumnImpl *tAttrInfo = at->getColumn(no);
+ DBUG_PRINT("info", ("rec_attr: 0x%x "
+ "switching column impl 0x%x -> 0x%x",
+ p, p->m_column, tAttrInfo));
+ p->m_column = tAttrInfo;
+ p = p->next();
+ }
}
+ if (tmp_table_impl)
+ delete tmp_table_impl;
}
- if (tmp_table_impl)
- delete tmp_table_impl;
- }
-
- if (unlikely(operation >= NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT))
- {
- DBUG_RETURN_EVENT(1);
+ DBUG_RETURN(1);
}
+ DBUG_ENTER_EVENT("NdbEventOperationImpl::receive_event");
+ DBUG_PRINT_EVENT("info",("sdata->operation %u this: %p", operation, this));
// now move the data into the RecAttrs
int is_update= operation == NdbDictionary::Event::_TE_UPDATE;
@@ -966,7 +968,22 @@ NdbEventBuffer::NdbEventBuffer(Ndb *ndb) :
NdbEventBuffer::~NdbEventBuffer()
{
// todo lock? what if receive thread writes here?
- for (unsigned j= 0; j < m_allocated_data.size(); j++)
+ NdbEventOperationImpl* op= m_dropped_ev_op;
+ while ((op = m_dropped_ev_op))
+ {
+ m_dropped_ev_op = m_dropped_ev_op->m_next;
+ delete op->m_facade;
+ }
+
+ unsigned j;
+ Uint32 sz= m_active_gci.size();
+ Gci_container* array = (Gci_container*)m_active_gci.getBase();
+ for(j = 0; j < sz; j++)
+ {
+ array[j].~Gci_container();
+ }
+
+ for (j= 0; j < m_allocated_data.size(); j++)
{
unsigned sz= m_allocated_data[j]->sz;
EventBufData *data= m_allocated_data[j]->data;
@@ -1078,6 +1095,33 @@ NdbEventBuffer::pollEvents(int aMillisecondNumber, Uint64 *latestGCI)
return ret;
}
+int
+NdbEventBuffer::flushIncompleteEvents(Uint64 gci)
+{
+ /**
+ * Find min complete gci
+ */
+ Uint32 i;
+ Uint32 sz= m_active_gci.size();
+ Gci_container* array = (Gci_container*)m_active_gci.getBase();
+ for(i = 0; i < sz; i++)
+ {
+ Gci_container* tmp = array + i;
+ if (tmp->m_gci && tmp->m_gci < gci)
+ {
+ // we have found an old not-completed gci, remove it
+ ndbout_c("ndb: flushing incomplete epoch %lld (<%lld)", tmp->m_gci, gci);
+ if(!tmp->m_data.is_empty())
+ {
+ free_list(tmp->m_data);
+ }
+ tmp->~Gci_container();
+ bzero(tmp, sizeof(Gci_container));
+ }
+ }
+ return 0;
+}
+
NdbEventOperation *
NdbEventBuffer::nextEvent()
{
@@ -1146,7 +1190,10 @@ NdbEventBuffer::nextEvent()
}
EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
while (gci_ops && op->getGCI() > gci_ops->m_gci)
+ {
+ deleteUsedEventOperations();
gci_ops = m_available_data.next_gci_ops();
+ }
assert(gci_ops && (op->getGCI() == gci_ops->m_gci));
DBUG_RETURN_EVENT(op->m_facade);
}
@@ -1166,7 +1213,10 @@ NdbEventBuffer::nextEvent()
// free all "per gci unique" collected operations
EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
while (gci_ops)
+ {
+ deleteUsedEventOperations();
gci_ops = m_available_data.next_gci_ops();
+ }
DBUG_RETURN_EVENT(0);
}
@@ -1180,31 +1230,37 @@ NdbEventBuffer::getGCIEventOperations(Uint32* iter, Uint32* event_types)
EventBufData_list::Gci_op g = gci_ops->m_gci_op_list[(*iter)++];
if (event_types != NULL)
*event_types = g.event_types;
- DBUG_PRINT("info", ("gci: %d", (unsigned)gci_ops->m_gci));
+ DBUG_PRINT("info", ("gci: %d g.op: %x g.event_types: %x",
+ (unsigned)gci_ops->m_gci, g.op, g.event_types));
DBUG_RETURN(g.op);
}
DBUG_RETURN(NULL);
}
void
-NdbEventBuffer::lock()
-{
- NdbMutex_Lock(m_mutex);
-}
-void
-NdbEventBuffer::unlock()
-{
- NdbMutex_Unlock(m_mutex);
-}
-void
-NdbEventBuffer::add_drop_lock()
-{
- NdbMutex_Lock(p_add_drop_mutex);
-}
-void
-NdbEventBuffer::add_drop_unlock()
+NdbEventBuffer::deleteUsedEventOperations()
{
- NdbMutex_Unlock(p_add_drop_mutex);
+ Uint32 iter= 0;
+ const NdbEventOperation *op_f;
+ while ((op_f= getGCIEventOperations(&iter, NULL)) != NULL)
+ {
+ NdbEventOperationImpl *op = &op_f->m_impl;
+ DBUG_ASSERT(op->m_ref_count > 0);
+ op->m_ref_count--;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+ if (op->m_ref_count == 0)
+ {
+ DBUG_PRINT("info", ("deleting op: %p", op));
+ DBUG_ASSERT(op->m_node_bit_mask.isclear());
+ if (op->m_next)
+ op->m_next->m_prev = op->m_prev;
+ if (op->m_prev)
+ op->m_prev->m_next = op->m_next;
+ else
+ m_dropped_ev_op = op->m_next;
+ delete op->m_facade;
+ }
+ }
}
static
@@ -1224,11 +1280,21 @@ operator<<(NdbOut& out, const Gci_container& gci)
}
static
+NdbOut&
+operator<<(NdbOut& out, const Gci_container_pod& gci)
+{
+ Gci_container* ptr = (Gci_container*)&gci;
+ out << *ptr;
+ return out;
+}
+
+
+static
Gci_container*
-find_bucket_chained(Vector<Gci_container> * active, Uint64 gci)
+find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci)
{
Uint32 pos = (gci & ACTIVE_GCI_MASK);
- Gci_container *bucket= active->getBase() + pos;
+ Gci_container *bucket= ((Gci_container*)active->getBase()) + pos;
if(gci > bucket->m_gci)
{
@@ -1237,8 +1303,9 @@ find_bucket_chained(Vector<Gci_container> * active, Uint64 gci)
do
{
active->fill(move_pos, g_empty_gci_container);
- bucket = active->getBase() + pos; // Needs to recomputed after fill
- move = active->getBase() + move_pos;
+ // Needs to recomputed after fill
+ bucket = ((Gci_container*)active->getBase()) + pos;
+ move = ((Gci_container*)active->getBase()) + move_pos;
if(move->m_gcp_complete_rep_count == 0)
{
memcpy(move, bucket, sizeof(Gci_container));
@@ -1269,16 +1336,33 @@ find_bucket_chained(Vector<Gci_container> * active, Uint64 gci)
inline
Gci_container*
-find_bucket(Vector<Gci_container> * active, Uint64 gci)
+find_bucket(Vector<Gci_container_pod> * active, Uint64 gci)
{
Uint32 pos = (gci & ACTIVE_GCI_MASK);
- Gci_container *bucket= active->getBase() + pos;
+ Gci_container *bucket= ((Gci_container*)active->getBase()) + pos;
if(likely(gci == bucket->m_gci))
return bucket;
return find_bucket_chained(active,gci);
}
+static
+void
+crash_on_invalid_SUB_GCP_COMPLETE_REP(const Gci_container* bucket,
+ const SubGcpCompleteRep * const rep,
+ Uint32 nodes)
+{
+ Uint32 old_cnt = bucket->m_gcp_complete_rep_count;
+
+ ndbout_c("INVALID SUB_GCP_COMPLETE_REP");
+ ndbout_c("gci: %d", rep->gci);
+ ndbout_c("sender: %x", rep->senderRef);
+ ndbout_c("count: %d", rep->gcp_complete_rep_count);
+ ndbout_c("bucket count: %u", old_cnt);
+ ndbout_c("nodes: %u", nodes);
+ abort();
+}
+
void
NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep)
{
@@ -1317,9 +1401,13 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep)
old_cnt = m_system_nodes;
}
- assert(old_cnt >= cnt);
+ //assert(old_cnt >= cnt);
+ if (unlikely(! (old_cnt >= cnt)))
+ {
+ crash_on_invalid_SUB_GCP_COMPLETE_REP(bucket, rep, m_system_nodes);
+ }
bucket->m_gcp_complete_rep_count = old_cnt - cnt;
-
+
if(old_cnt == cnt)
{
if(likely(gci == m_latestGCI + 1 || m_latestGCI == 0))
@@ -1349,7 +1437,8 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep)
{
/** out of order something */
ndbout_c("out of order bucket: %d gci: %lld m_latestGCI: %lld",
- bucket-m_active_gci.getBase(), gci, m_latestGCI);
+ bucket-(Gci_container*)m_active_gci.getBase(),
+ gci, m_latestGCI);
bucket->m_state = Gci_container::GC_COMPLETE;
bucket->m_gcp_complete_rep_count = 1; // Prevent from being reused
m_latest_complete_GCI = gci;
@@ -1366,7 +1455,7 @@ NdbEventBuffer::complete_outof_order_gcis()
Uint64 stop_gci = m_latest_complete_GCI;
const Uint32 size = m_active_gci.size();
- Gci_container* array= m_active_gci.getBase();
+ Gci_container* array= (Gci_container*)m_active_gci.getBase();
ndbout_c("complete_outof_order_gcis");
for(Uint32 i = 0; i<size; i++)
@@ -1425,6 +1514,10 @@ NdbEventBuffer::complete_outof_order_gcis()
void
NdbEventBuffer::report_node_failure(Uint32 node_id)
{
+ NdbEventOperation* op= m_ndb->getEventOperation(0);
+ if (op == 0)
+ return;
+
DBUG_ENTER("NdbEventBuffer::report_node_failure");
SubTableData data;
LinearSectionPtr ptr[3];
@@ -1436,15 +1529,24 @@ NdbEventBuffer::report_node_failure(Uint32 node_id)
data.req_nodeid = (Uint8)node_id;
data.ndbd_nodeid = (Uint8)node_id;
data.logType = SubTableData::LOG;
+ data.gci = m_latestGCI + 1;
/**
* Insert this event for each operation
*/
- NdbEventOperation* op= 0;
- while((op = m_ndb->getEventOperation(op)))
{
- NdbEventOperationImpl* impl= &op->m_impl;
- data.senderData = impl->m_oid;
- insertDataL(impl, &data, ptr);
+ // no need to lock()/unlock(), receive thread calls this
+ NdbEventOperationImpl* impl = &op->m_impl;
+ do if (!impl->m_node_bit_mask.isclear())
+ {
+ data.senderData = impl->m_oid;
+ insertDataL(impl, &data, ptr);
+ } while((impl = impl->m_next));
+ for (impl = m_dropped_ev_op; impl; impl = impl->m_next)
+ if (!impl->m_node_bit_mask.isclear())
+ {
+ data.senderData = impl->m_oid;
+ insertDataL(impl, &data, ptr);
+ }
}
DBUG_VOID_RETURN;
}
@@ -1452,8 +1554,11 @@ NdbEventBuffer::report_node_failure(Uint32 node_id)
void
NdbEventBuffer::completeClusterFailed()
{
- DBUG_ENTER("NdbEventBuffer::completeClusterFailed");
+ NdbEventOperation* op= m_ndb->getEventOperation(0);
+ if (op == 0)
+ return;
+ DBUG_ENTER("NdbEventBuffer::completeClusterFailed");
SubTableData data;
LinearSectionPtr ptr[3];
bzero(&data, sizeof(data));
@@ -1462,73 +1567,79 @@ NdbEventBuffer::completeClusterFailed()
data.tableId = ~0;
data.operation = NdbDictionary::Event::_TE_CLUSTER_FAILURE;
data.logType = SubTableData::LOG;
-
+ data.gci = m_latestGCI + 1;
+
/**
- * Find min not completed GCI
+ * Insert this event for each operation
*/
- Uint32 sz= m_active_gci.size();
- Uint64 gci= ~0;
- Gci_container* bucket = 0;
- Gci_container* array = m_active_gci.getBase();
- for(Uint32 i = 0; i<sz; i++)
{
- if(array[i].m_gcp_complete_rep_count && array[i].m_gci < gci)
+ // no need to lock()/unlock(), receive thread calls this
+ NdbEventOperationImpl* impl = &op->m_impl;
+ do if (!impl->m_node_bit_mask.isclear())
{
- bucket= array + i;
- gci = bucket->m_gci;
- }
- }
-
- if(bucket == 0)
- {
- /**
- * Did not find any not completed GCI's
- * lets fake one...
- */
- gci = m_latestGCI + 1;
- bucket = array + ( gci & ACTIVE_GCI_MASK );
- bucket->m_gcp_complete_rep_count = 1;
+ data.senderData = impl->m_oid;
+ insertDataL(impl, &data, ptr);
+ } while((impl = impl->m_next));
+ for (impl = m_dropped_ev_op; impl; impl = impl->m_next)
+ if (!impl->m_node_bit_mask.isclear())
+ {
+ data.senderData = impl->m_oid;
+ insertDataL(impl, &data, ptr);
+ }
}
- const Uint32 cnt= bucket->m_gcp_complete_rep_count = 1;
-
/**
- * Release all GCI's
+ * Release all GCI's with m_gci > gci
*/
- for(Uint32 i = 0; i<sz; i++)
+ Uint32 i;
+ Uint32 sz= m_active_gci.size();
+ Uint64 gci= data.gci;
+ Gci_container* bucket = 0;
+ Gci_container* array = (Gci_container*)m_active_gci.getBase();
+ for(i = 0; i < sz; i++)
{
Gci_container* tmp = array + i;
- if(!tmp->m_data.is_empty())
+ if (tmp->m_gci > gci)
{
- free_list(tmp->m_data);
-#if 0
- m_free_data_count++;
- EventBufData* loop= tmp->m_head;
- while(loop != tmp->m_tail)
+ if(!tmp->m_data.is_empty())
{
- m_free_data_count++;
- loop = loop->m_next;
+ free_list(tmp->m_data);
}
-#endif
+ tmp->~Gci_container();
+ bzero(tmp, sizeof(Gci_container));
+ }
+ else if (tmp->m_gcp_complete_rep_count)
+ {
+ if (tmp->m_gci == gci)
+ {
+ bucket= tmp;
+ continue;
+ }
+ // we have found an old not-completed gci
+ // something is wrong, assert in debug, but try so salvage
+ // in release
+ ndbout_c("out of order bucket detected at cluster disconnect, "
+ "data.gci: %u. tmp->m_gci: %u",
+ (unsigned)data.gci, (unsigned)tmp->m_gci);
+ assert(false);
+ if(!tmp->m_data.is_empty())
+ {
+ free_list(tmp->m_data);
+ }
+ tmp->~Gci_container();
+ bzero(tmp, sizeof(Gci_container));
}
- bzero(tmp, sizeof(Gci_container));
}
-
- bucket->m_gci = gci;
- bucket->m_gcp_complete_rep_count = cnt;
-
- data.gci = gci;
-
- /**
- * Insert this event for each operation
- */
- NdbEventOperation* op= 0;
- while((op = m_ndb->getEventOperation(op)))
+
+ if (bucket == 0)
{
- NdbEventOperationImpl* impl= &op->m_impl;
- data.senderData = impl->m_oid;
- insertDataL(impl, &data, ptr);
+ // no bucket to complete
+ DBUG_VOID_RETURN;
}
+
+ const Uint32 cnt= bucket->m_gcp_complete_rep_count = 1;
+ bucket->m_gci = gci;
+ bucket->m_gcp_complete_rep_count = cnt;
/**
* And finally complete this GCI
@@ -1554,6 +1665,40 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op,
{
DBUG_ENTER_EVENT("NdbEventBuffer::insertDataL");
Uint64 gci= sdata->gci;
+ const bool is_data_event =
+ sdata->operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
+
+ if (!is_data_event)
+ {
+ switch (sdata->operation)
+ {
+ case NdbDictionary::Event::_TE_NODE_FAILURE:
+ op->m_node_bit_mask.clear(sdata->ndbd_nodeid);
+ break;
+ case NdbDictionary::Event::_TE_ACTIVE:
+ op->m_node_bit_mask.set(sdata->ndbd_nodeid);
+ // internal event, do not relay to user
+ DBUG_RETURN_EVENT(0);
+ break;
+ case NdbDictionary::Event::_TE_CLUSTER_FAILURE:
+ op->m_node_bit_mask.clear();
+ DBUG_ASSERT(op->m_ref_count > 0);
+ op->m_ref_count--;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+ break;
+ case NdbDictionary::Event::_TE_STOP:
+ op->m_node_bit_mask.clear(sdata->ndbd_nodeid);
+ if (op->m_node_bit_mask.isclear())
+ {
+ DBUG_ASSERT(op->m_ref_count > 0);
+ op->m_ref_count--;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+ }
+ break;
+ default:
+ break;
+ }
+ }
if ( likely((Uint32)op->mi_type & (1 << (Uint32)sdata->operation)) )
{
@@ -1574,8 +1719,6 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op,
}
const bool is_blob_event = (op->theMainOp != NULL);
- const bool is_data_event =
- sdata->operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
const bool use_hash = op->m_mergeEvents && is_data_event;
if (! is_data_event && is_blob_event)
@@ -1878,12 +2021,16 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata,
// loop twice where first loop only sets sizes
int loop;
+ int result = 0;
for (loop = 0; loop <= 1; loop++)
{
if (loop == 1)
{
if (alloc_mem(data, ptr) != 0)
- DBUG_RETURN_EVENT(-1);
+ {
+ result = -1;
+ goto end;
+ }
*data->sdata = *sdata;
data->sdata->operation = tp->t3;
}
@@ -1997,10 +2144,13 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata,
}
}
+end:
// free old data
NdbMem_Free((char*)olddata.memory);
+ assert(m_total_alloc >= olddata.sz);
+ m_total_alloc -= olddata.sz;
- DBUG_RETURN_EVENT(0);
+ DBUG_RETURN_EVENT(result);
}
/*
@@ -2196,6 +2346,8 @@ void EventBufData_list::append_list(EventBufData_list *list, Uint64 gci)
void
EventBufData_list::add_gci_op(Gci_op g, bool del)
{
+ DBUG_ENTER_EVENT("EventBufData_list::add_gci_op");
+ DBUG_PRINT_EVENT("info", ("p.op: %p g.event_types: %x", g.op, g.event_types));
assert(g.op != NULL);
Uint32 i;
for (i = 0; i < m_gci_op_count; i++) {
@@ -2215,19 +2367,33 @@ EventBufData_list::add_gci_op(Gci_op g, bool del)
if (m_gci_op_alloc != 0) {
Uint32 bytes = m_gci_op_alloc * sizeof(Gci_op);
memcpy(m_gci_op_list, old_list, bytes);
+ DBUG_PRINT_EVENT("info", ("this: %p delete m_gci_op_list: %p",
+ this, old_list));
delete [] old_list;
}
+ DBUG_PRINT_EVENT("info", ("this: %p new m_gci_op_list: %p",
+ this, m_gci_op_list));
m_gci_op_alloc = n;
}
assert(m_gci_op_count < m_gci_op_alloc);
assert(! del);
+#ifndef DBUG_OFF
+ i = m_gci_op_count;
+#endif
+ g.op->m_ref_count++;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", g.op->m_ref_count, g.op));
m_gci_op_list[m_gci_op_count++] = g;
}
+ DBUG_PRINT_EVENT("exit", ("m_gci_op_list[%u].event_types: %x", i, m_gci_op_list[i].event_types));
+ DBUG_VOID_RETURN_EVENT;
}
void
EventBufData_list::move_gci_ops(EventBufData_list *list, Uint64 gci)
{
+ DBUG_ENTER_EVENT("EventBufData_list::move_gci_ops");
+ DBUG_PRINT_EVENT("info", ("this: %p list: %p gci: %llu",
+ this, list, gci));
assert(!m_is_not_multi_list);
if (!list->m_is_not_multi_list)
{
@@ -2243,6 +2409,8 @@ EventBufData_list::move_gci_ops(EventBufData_list *list, Uint64 gci)
}
{
Gci_ops *new_gci_ops = new Gci_ops;
+ DBUG_PRINT_EVENT("info", ("this: %p m_gci_op_list: %p",
+ new_gci_ops, list->m_gci_op_list));
if (m_gci_ops_list_tail)
m_gci_ops_list_tail->m_next = new_gci_ops;
else
@@ -2261,6 +2429,7 @@ end:
list->m_gci_op_list = 0;
list->m_gci_ops_list_tail = 0;
list->m_gci_op_alloc = 0;
+ DBUG_VOID_RETURN_EVENT;
}
NdbEventOperation*
@@ -2279,6 +2448,9 @@ NdbEventBuffer::createEventOperation(const char* eventName,
delete tOp;
DBUG_RETURN(NULL);
}
+ getEventOperationImpl(tOp)->m_ref_count = 1;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p",
+ getEventOperationImpl(tOp)->m_ref_count, getEventOperationImpl(tOp)));
DBUG_RETURN(tOp);
}
@@ -2304,16 +2476,10 @@ NdbEventBuffer::createEventOperation(NdbEventImpl& evnt,
void
NdbEventBuffer::dropEventOperation(NdbEventOperation* tOp)
{
+ DBUG_ENTER("NdbEventBuffer::dropEventOperation");
NdbEventOperationImpl* op= getEventOperationImpl(tOp);
op->stop();
-
- op->m_next= m_dropped_ev_op;
- op->m_prev= 0;
- if (m_dropped_ev_op)
- m_dropped_ev_op->m_prev= op;
- m_dropped_ev_op= op;
-
// stop blob event ops
if (op->theMainOp == NULL)
{
@@ -2333,11 +2499,24 @@ NdbEventBuffer::dropEventOperation(NdbEventOperation* tOp)
}
}
- // ToDo, take care of these to be deleted at the
- // appropriate time, after we are sure that there
- // are _no_ more events coming
-
- // delete tOp;
+ DBUG_ASSERT(op->m_ref_count > 0);
+ op->m_ref_count--;
+ DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+ if (op->m_ref_count == 0)
+ {
+ DBUG_PRINT("info", ("deleting op: %p", op));
+ DBUG_ASSERT(op->m_node_bit_mask.isclear());
+ delete op->m_facade;
+ }
+ else
+ {
+ op->m_next= m_dropped_ev_op;
+ op->m_prev= 0;
+ if (m_dropped_ev_op)
+ m_dropped_ev_op->m_prev= op;
+ m_dropped_ev_op= op;
+ }
+ DBUG_VOID_RETURN;
}
void
@@ -2517,5 +2696,5 @@ EventBufData_hash::search(Pos& hpos, NdbEventOperationImpl* op, LinearSectionPtr
DBUG_VOID_RETURN_EVENT;
}
-template class Vector<Gci_container>;
+template class Vector<Gci_container_pod>;
template class Vector<NdbEventBuffer::EventBufData_chunk*>;
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index bffc2174be5..bcae650bf44 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -25,6 +25,20 @@
#include <UtilBuffer.hpp>
#define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4
+//#define EVENT_DEBUG
+#ifdef EVENT_DEBUG
+#define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
+#define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
+#define DBUG_VOID_RETURN_EVENT DBUG_VOID_RETURN
+#define DBUG_PRINT_EVENT(A,B) DBUG_PRINT(A,B)
+#define DBUG_DUMP_EVENT(A,B,C) DBUG_DUMP(A,B,C)
+#else
+#define DBUG_ENTER_EVENT(A)
+#define DBUG_RETURN_EVENT(A) return(A)
+#define DBUG_VOID_RETURN_EVENT return
+#define DBUG_PRINT_EVENT(A,B)
+#define DBUG_DUMP_EVENT(A,B,C)
+#endif
class NdbEventOperationImpl;
@@ -149,19 +163,29 @@ EventBufData_list::EventBufData_list()
m_gci_ops_list_tail(0),
m_gci_op_alloc(0)
{
+ DBUG_ENTER_EVENT("EventBufData_list::EventBufData_list");
+ DBUG_PRINT_EVENT("info", ("this: %p", this));
+ DBUG_VOID_RETURN_EVENT;
}
inline
EventBufData_list::~EventBufData_list()
{
+ DBUG_ENTER_EVENT("EventBufData_list::~EventBufData_list");
+ DBUG_PRINT_EVENT("info", ("this: %p m_is_not_multi_list: %u",
+ this, m_is_not_multi_list));
if (m_is_not_multi_list)
+ {
+ DBUG_PRINT_EVENT("info", ("delete m_gci_op_list: %p", m_gci_op_list));
delete [] m_gci_op_list;
+ }
else
{
Gci_ops *op = first_gci_ops();
while (op)
op = next_gci_ops();
}
+ DBUG_VOID_RETURN_EVENT;
}
inline
@@ -223,7 +247,11 @@ EventBufData_list::next_gci_ops()
Gci_ops *first = m_gci_ops_list;
m_gci_ops_list = first->m_next;
if (first->m_gci_op_list)
+ {
+ DBUG_PRINT_EVENT("info", ("this: %p delete m_gci_op_list: %p",
+ this, first->m_gci_op_list));
delete [] first->m_gci_op_list;
+ }
delete first;
if (m_gci_ops_list == 0)
m_gci_ops_list_tail = 0;
@@ -272,6 +300,11 @@ struct Gci_container
EventBufData_hash m_data_hash;
};
+struct Gci_container_pod
+{
+ char data[sizeof(Gci_container)];
+};
+
class NdbEventOperationImpl : public NdbEventOperation {
public:
NdbEventOperationImpl(NdbEventOperation &f,
@@ -334,6 +367,8 @@ public:
Uint32 m_eventId;
Uint32 m_oid;
+ Bitmask<(unsigned int)_NDB_NODE_BITMASK_SIZE> m_node_bit_mask;
+ int m_ref_count;
bool m_mergeEvents;
EventBufData *m_data_item;
@@ -365,7 +400,7 @@ public:
~NdbEventBuffer();
const Uint32 &m_system_nodes;
- Vector<Gci_container> m_active_gci;
+ Vector<Gci_container_pod> m_active_gci;
NdbEventOperation *createEventOperation(const char* eventName,
NdbError &);
NdbEventOperationImpl *createEventOperation(NdbEventImpl& evnt,
@@ -373,10 +408,10 @@ public:
void dropEventOperation(NdbEventOperation *);
static NdbEventOperationImpl* getEventOperationImpl(NdbEventOperation* tOp);
- void add_drop_lock();
- void add_drop_unlock();
- void lock();
- void unlock();
+ void add_drop_lock() { NdbMutex_Lock(p_add_drop_mutex); }
+ void add_drop_unlock() { NdbMutex_Unlock(p_add_drop_mutex); }
+ void lock() { NdbMutex_Lock(m_mutex); }
+ void unlock() { NdbMutex_Unlock(m_mutex); }
void add_op();
void remove_op();
@@ -397,9 +432,11 @@ public:
Uint32 getEventId(int bufferId);
int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);
+ int flushIncompleteEvents(Uint64 gci);
NdbEventOperation *nextEvent();
NdbEventOperationImpl* getGCIEventOperations(Uint32* iter,
Uint32* event_types);
+ void deleteUsedEventOperations();
NdbEventOperationImpl *move_data();
diff --git a/storage/ndb/src/ndbapi/NdbIndexStat.cpp b/storage/ndb/src/ndbapi/NdbIndexStat.cpp
index 8740b80a81d..e490290b6a2 100644
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp
@@ -377,7 +377,7 @@ NdbIndexStat::stat_select(const Uint32* key1, Uint32 keylen1, const Uint32* key2
}
int
-NdbIndexStat::records_in_range(NdbDictionary::Index* index, NdbIndexScanOperation* op, Uint64 table_rows, Uint64* count, int flags)
+NdbIndexStat::records_in_range(const NdbDictionary::Index* index, NdbIndexScanOperation* op, Uint64 table_rows, Uint64* count, int flags)
{
DBUG_ENTER("NdbIndexStat::records_in_range");
Uint64 rows;
diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
index ea7fbe4077d..6a4e657d172 100644
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -1106,6 +1106,11 @@ int
NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
int type, const void* aValue)
{
+ if (!tAttrInfo)
+ {
+ setErrorCodeAbort(4318); // Invalid attribute
+ return -1;
+ }
if (theOperationType == OpenRangeScanRequest &&
(0 <= type && type <= 4)) {
// insert bound type
diff --git a/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp
index 3d98dea7edc..3158dca5c40 100644
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp
@@ -1192,9 +1192,9 @@ NdbTransaction::getNdbIndexScanOperation(const NdbIndexImpl* index,
if(tOp)
{
tOp->m_currentTable = table;
+ // Mark that this really an NdbIndexScanOperation
+ tOp->m_type = NdbOperation::OrderedIndexScan;
}
- // Mark that this really an NdbIndexScanOperation
- tOp->m_type = NdbOperation::OrderedIndexScan;
return tOp;
} else {
setOperationErrorCodeAbort(4271);
diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp
index b0692eb8236..7799a71749e 100644
--- a/storage/ndb/src/ndbapi/Ndbif.cpp
+++ b/storage/ndb/src/ndbapi/Ndbif.cpp
@@ -1435,8 +1435,7 @@ NdbTransaction::sendTC_COMMIT_ACK(TransporterFacade *tp,
Uint32 * dataPtr = aSignal->getDataPtrSend();
dataPtr[0] = transId1;
dataPtr[1] = transId2;
-
- tp->sendSignal(aSignal, refToNode(aTCRef));
+ tp->sendSignalUnCond(aSignal, refToNode(aTCRef));
}
int
diff --git a/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp
index b502ec27b9d..91567e99c01 100644
--- a/storage/ndb/src/ndbapi/Ndbinit.cpp
+++ b/storage/ndb/src/ndbapi/Ndbinit.cpp
@@ -99,10 +99,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
for (i = 0; i < MAX_NDB_NODES ; i++) {
theConnectionArray[i] = NULL;
}//forg
- for (i = 0; i < 2048 ; i++) {
- theFirstTupleId[i] = 0;
- theLastTupleId[i] = 0;
- }//for
+ m_sys_tab_0 = NULL;
theImpl->m_dbname.assign(aDataBase);
theImpl->m_schemaname.assign(aSchema);
@@ -137,6 +134,9 @@ Ndb::~Ndb()
DBUG_ENTER("Ndb::~Ndb()");
DBUG_PRINT("enter",("this=0x%x",this));
+ if (m_sys_tab_0)
+ getDictionary()->removeTableGlobal(*m_sys_tab_0, 0);
+
assert(theImpl->m_ev_op == 0); // user should return NdbEventOperation's
for (NdbEventOperationImpl *op= theImpl->m_ev_op; op; op=op->m_next)
{
diff --git a/storage/ndb/src/ndbapi/SignalSender.cpp b/storage/ndb/src/ndbapi/SignalSender.cpp
index a29fe68937b..0ecc98f5f29 100644
--- a/storage/ndb/src/ndbapi/SignalSender.cpp
+++ b/storage/ndb/src/ndbapi/SignalSender.cpp
@@ -75,7 +75,9 @@ SignalSender::SignalSender(TransporterFacade *facade)
{
m_cond = NdbCondition_Create();
theFacade = facade;
+ lock();
m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
+ unlock();
assert(m_blockNo > 0);
}
diff --git a/storage/ndb/src/ndbapi/TransporterFacade.cpp b/storage/ndb/src/ndbapi/TransporterFacade.cpp
index 7005d5d2325..15127953051 100644
--- a/storage/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp
@@ -343,7 +343,7 @@ execute(void * callbackObj, SignalHeader * const header,
Uint32 aNodeId= refToNode(ref);
tSignal.theReceiversBlockNumber= refToBlock(ref);
tSignal.theVerId_signalNumber= GSN_SUB_GCP_COMPLETE_ACK;
- theFacade->sendSignal(&tSignal, aNodeId);
+ theFacade->sendSignalUnCond(&tSignal, aNodeId);
}
break;
}
@@ -987,7 +987,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){
LinearSectionPtr ptr[3];
signalLogger.sendSignal(* aSignal,
1,
- aSignal->getDataPtr(),
+ tDataPtr,
aNode, ptr, 0);
signalLogger.flushSignalLog();
aSignal->theSendersBlockRef = tmp;
@@ -1014,6 +1014,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){
int
TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){
+ Uint32* tDataPtr = aSignal->getDataPtrSend();
#ifdef API_TRACE
if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
Uint32 tmp = aSignal->theSendersBlockRef;
@@ -1021,7 +1022,7 @@ TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){
LinearSectionPtr ptr[3];
signalLogger.sendSignal(* aSignal,
0,
- aSignal->getDataPtr(),
+ tDataPtr,
aNode, ptr, 0);
signalLogger.flushSignalLog();
aSignal->theSendersBlockRef = tmp;
@@ -1032,7 +1033,7 @@ TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){
(aSignal->theReceiversBlockNumber != 0));
SendStatus ss = theTransporterRegistry->prepareSend(aSignal,
0,
- aSignal->getDataPtr(),
+ tDataPtr,
aNode,
0);
diff --git a/storage/ndb/src/ndbapi/TransporterFacade.hpp b/storage/ndb/src/ndbapi/TransporterFacade.hpp
index b64ce2e8614..2d47a2febf8 100644
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp
@@ -175,7 +175,8 @@ private:
friend class GrepSS;
friend class Ndb;
friend class Ndb_cluster_connection_impl;
-
+ friend class NdbTransaction;
+
int sendSignalUnCond(NdbApiSignal *, NodeId nodeId);
bool isConnected(NodeId aNodeId);
@@ -318,6 +319,12 @@ TransporterFacade::unlock_mutex()
#include "ClusterMgr.hpp"
inline
+unsigned Ndb_cluster_connection_impl::get_connect_count() const
+{
+ return m_transporter_facade->theClusterMgr->m_connect_count;
+}
+
+inline
bool
TransporterFacade::check_send_size(Uint32 node_id, Uint32 send_size)
{
diff --git a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
index 544f7424a82..a7e645f5100 100644
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
@@ -253,6 +253,12 @@ Ndb_cluster_connection::wait_until_ready(int timeout,
} while (1);
}
+unsigned Ndb_cluster_connection::get_connect_count() const
+{
+ return m_impl.get_connect_count();
+}
+
+
/*
diff --git a/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp b/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
index db6e1f9e6ed..6f0df0403d9 100644
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
@@ -40,6 +40,7 @@ class Ndb_cluster_connection_impl : public Ndb_cluster_connection
void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
Uint32 get_next_node(Ndb_cluster_connection_node_iter &iter);
+ inline unsigned get_connect_count() const;
private:
friend class Ndb;
friend class NdbImpl;
diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c
index 8185bf38c3e..c05924dacf8 100644
--- a/storage/ndb/src/ndbapi/ndberror.c
+++ b/storage/ndb/src/ndbapi/ndberror.c
@@ -600,7 +600,6 @@ ErrorBundle ErrorCodes[] = {
{ 4269, DMEC, IE, "No connection to ndb management server" },
{ 4270, DMEC, IE, "Unknown blob error" },
{ 4335, DMEC, 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" },
- { 4336, DMEC, AE, "Auto-increment value set below current value" },
{ 4271, DMEC, AE, "Invalid index object, not retrieved via getIndex()" },
{ 4272, DMEC, AE, "Table definition has undefined column" },
{ 4273, DMEC, IE, "No blob table in dict cache" },
diff --git a/storage/ndb/test/ndbapi/Makefile.am b/storage/ndb/test/ndbapi/Makefile.am
index 9a1e1c5e9ea..b55acd2420d 100644
--- a/storage/ndb/test/ndbapi/Makefile.am
+++ b/storage/ndb/test/ndbapi/Makefile.am
@@ -24,6 +24,7 @@ testOIBasic \
testOperations \
testRestartGci \
testScan \
+testInterpreter \
testScanInterpreter \
testScanPerf \
testSystemRestart \
@@ -64,6 +65,7 @@ testOIBasic_SOURCES = testOIBasic.cpp
testOperations_SOURCES = testOperations.cpp
testRestartGci_SOURCES = testRestartGci.cpp
testScan_SOURCES = testScan.cpp ScanFunctions.hpp
+testInterpreter_SOURCES = testInterpreter.cpp
testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp
testScanPerf_SOURCES = testScanPerf.cpp
testSystemRestart_SOURCES = testSystemRestart.cpp
diff --git a/storage/ndb/test/ndbapi/bank/Bank.cpp b/storage/ndb/test/ndbapi/bank/Bank.cpp
index 5ef01533e07..80edbef7e74 100644
--- a/storage/ndb/test/ndbapi/bank/Bank.cpp
+++ b/storage/ndb/test/ndbapi/bank/Bank.cpp
@@ -22,7 +22,8 @@
Bank::Bank(Ndb_cluster_connection& con, bool _init, const char * dbase):
m_ndb(&con, dbase),
m_maxAccount(-1),
- m_initialized(false)
+ m_initialized(false),
+ m_skip_create(false)
{
if(_init)
init();
diff --git a/storage/ndb/test/ndbapi/bank/Bank.hpp b/storage/ndb/test/ndbapi/bank/Bank.hpp
index 60ec7745b59..494f39930eb 100644
--- a/storage/ndb/test/ndbapi/bank/Bank.hpp
+++ b/storage/ndb/test/ndbapi/bank/Bank.hpp
@@ -29,6 +29,7 @@ public:
Bank(Ndb_cluster_connection&, bool init = true, const char *dbase="BANK");
+ int setSkipCreate(bool skip) { m_skip_create = skip; }
int createAndLoadBank(bool overWrite, bool disk= false, int num_accounts=10);
int dropBank();
@@ -140,6 +141,7 @@ private:
Ndb m_ndb;
int m_maxAccount;
bool m_initialized;
+ bool m_skip_create;
};
#endif
diff --git a/storage/ndb/test/ndbapi/bank/BankLoad.cpp b/storage/ndb/test/ndbapi/bank/BankLoad.cpp
index 45d6a860a3d..5a81a4d2498 100644
--- a/storage/ndb/test/ndbapi/bank/BankLoad.cpp
+++ b/storage/ndb/test/ndbapi/bank/BankLoad.cpp
@@ -58,7 +58,7 @@ int Bank::createAndLoadBank(bool ovrWrt, bool disk, int num_accounts){
m_ndb.init();
if (m_ndb.waitUntilReady() != 0)
return NDBT_FAILED;
-
+
const NdbDictionary::Table* pSysValTab =
m_ndb.getDictionary()->getTable("SYSTEM_VALUES");
if (pSysValTab != NULL){
@@ -69,7 +69,7 @@ int Bank::createAndLoadBank(bool ovrWrt, bool disk, int num_accounts){
}
}
- if (createTables(disk) != NDBT_OK)
+ if (!m_skip_create && createTables(disk) != NDBT_OK)
return NDBT_FAILED;
if (clearTables() != NDBT_OK)
diff --git a/storage/ndb/test/ndbapi/bank/bankCreator.cpp b/storage/ndb/test/ndbapi/bank/bankCreator.cpp
index 39e4920867f..30c024d799c 100644
--- a/storage/ndb/test/ndbapi/bank/bankCreator.cpp
+++ b/storage/ndb/test/ndbapi/bank/bankCreator.cpp
@@ -31,10 +31,12 @@ int main(int argc, const char** argv){
int _help = 0;
char * _database = "BANK";
int disk = 0;
+ int skip_create = 0;
struct getargs args[] = {
{ "database", 'd', arg_string, &_database, "Database name", ""},
{ "disk", 0, arg_flag, &disk, "Use disk tables", "" },
+ { "skip-create", 0, arg_flag, &skip_create, "Skip create", "" },
{ "usage", '?', arg_flag, &_help, "Print help", "" }
};
int num_args = sizeof(args) / sizeof(args[0]);
@@ -55,6 +57,7 @@ int main(int argc, const char** argv){
Bank bank(con,_database);
int overWriteExisting = true;
+ bank.setSkipCreate(skip_create);
if (bank.createAndLoadBank(overWriteExisting, disk) != NDBT_OK)
return NDBT_ProgramExit(NDBT_FAILED);
return NDBT_ProgramExit(NDBT_OK);
diff --git a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp
index 879a4979220..d45a8ecb7b1 100644
--- a/storage/ndb/test/ndbapi/testBasic.cpp
+++ b/storage/ndb/test/ndbapi/testBasic.cpp
@@ -1034,6 +1034,76 @@ runMassiveRollback2(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int
+runMassiveRollback3(NDBT_Context* ctx, NDBT_Step* step){
+
+ int result = NDBT_OK;
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ const Uint32 BATCH = 10;
+ const Uint32 OPS_TOTAL = 50;
+ const Uint32 LOOPS = 100;
+
+ for(Uint32 loop = 0; loop<LOOPS; loop++)
+ {
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ bool ok = true;
+ for (Uint32 i = 0; i<OPS_TOTAL; i+= BATCH)
+ {
+ CHECK(hugoOps.pkInsertRecord(pNdb, i, BATCH, 0) == 0);
+ if (hugoOps.execute_NoCommit(pNdb) != 0)
+ {
+ ok = false;
+ break;
+ }
+ }
+ hugoOps.execute_Rollback(pNdb);
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ }
+
+ hugoOps.closeTransaction(pNdb);
+ return result;
+}
+
+int
+runMassiveRollback4(NDBT_Context* ctx, NDBT_Step* step){
+
+ int result = NDBT_OK;
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ const Uint32 BATCH = 10;
+ const Uint32 OPS_TOTAL = 20;
+ const Uint32 LOOPS = 100;
+
+ for(Uint32 loop = 0; loop<LOOPS; loop++)
+ {
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ bool ok = true;
+ for (Uint32 i = 0; i<OPS_TOTAL; i+= BATCH)
+ {
+ CHECK(hugoOps.pkInsertRecord(pNdb, i, BATCH, 0) == 0);
+ CHECK(hugoOps.pkDeleteRecord(pNdb, i, BATCH) == 0);
+ if (hugoOps.execute_NoCommit(pNdb) != 0)
+ {
+ ok = false;
+ break;
+ }
+ if (hugoOps.execute_NoCommit(pNdb) != 0)
+ {
+ ok = false;
+ break;
+ }
+ }
+ hugoOps.execute_Rollback(pNdb);
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ }
+
+ hugoOps.closeTransaction(pNdb);
+ return result;
+}
+
/**
* TUP errors
*/
@@ -1360,6 +1430,20 @@ TESTCASE("MassiveRollback2",
INITIALIZER(runMassiveRollback2);
FINALIZER(runClearTable2);
}
+TESTCASE("MassiveRollback3",
+ "Test rollback of 4096 operations"){
+ INITIALIZER(runClearTable2);
+ STEP(runMassiveRollback3);
+ STEP(runMassiveRollback3);
+ FINALIZER(runClearTable2);
+}
+TESTCASE("MassiveRollback4",
+ "Test rollback of 4096 operations"){
+ INITIALIZER(runClearTable2);
+ STEP(runMassiveRollback4);
+ STEP(runMassiveRollback4);
+ FINALIZER(runClearTable2);
+}
TESTCASE("MassiveTransaction",
"Test very large insert transaction"){
INITIALIZER(runLoadTable2);
diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp
index a1b0c89652e..bf9a8b1bce9 100644
--- a/storage/ndb/test/ndbapi/testBlobs.cpp
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp
@@ -44,6 +44,7 @@ struct Opt {
bool m_dbg;
bool m_dbgall;
const char* m_dbug;
+ bool m_fac;
bool m_full;
unsigned m_loop;
unsigned m_parts;
@@ -72,6 +73,7 @@ struct Opt {
m_dbg(false),
m_dbgall(false),
m_dbug(0),
+ m_fac(false),
m_full(false),
m_loop(1),
m_parts(10),
@@ -110,6 +112,7 @@ printusage()
<< " -dbg print debug" << endl
<< " -dbgall print also NDB API debug (if compiled in)" << endl
<< " -dbug opt dbug options" << endl
+ << " -fac fetch across commit in scan delete [" << d.m_fac << "]" << endl
<< " -full read/write only full blob values" << endl
<< " -loop N loop N times 0=forever [" << d.m_loop << "]" << endl
<< " -parts N max parts in blob value [" << d.m_parts << "]" << endl
@@ -1255,23 +1258,11 @@ deleteScan(bool idx)
CHK((ret = g_ops->nextResult(false)) == 0 || ret == 1 || ret == 2);
if (++n == g_opt.m_batch || ret == 2) {
DBG("execute batch: n=" << n << " ret=" << ret);
- switch (0) {
- case 0: // works normally
+ if (! g_opt.m_fac) {
CHK(g_con->execute(NoCommit) == 0);
- CHK(true || g_con->restart() == 0);
- break;
- case 1: // nonsense - g_con is invalid for 2nd batch
- CHK(g_con->execute(Commit) == 0);
- CHK(true || g_con->restart() == 0);
- break;
- case 2: // DBTC sendSignalErrorRefuseLab
- CHK(g_con->execute(NoCommit) == 0);
- CHK(g_con->restart() == 0);
- break;
- case 3: // 266 time-out
+ } else {
CHK(g_con->execute(Commit) == 0);
CHK(g_con->restart() == 0);
- break;
}
n = 0;
}
@@ -1817,6 +1808,10 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
continue;
}
}
+ if (strcmp(arg, "-fac") == 0) {
+ g_opt.m_fac = true;
+ continue;
+ }
if (strcmp(arg, "-full") == 0) {
g_opt.m_full = true;
continue;
diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp
index 0176db8d4fd..b015e16bae1 100644
--- a/storage/ndb/test/ndbapi/testDict.cpp
+++ b/storage/ndb/test/ndbapi/testDict.cpp
@@ -109,7 +109,7 @@ int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -151,7 +151,7 @@ int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
}
// Try to create table in db
- if (pTab->createTableInDb(pNdb) == 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) == 0){
result = NDBT_FAILED;
}
@@ -203,7 +203,7 @@ int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
ndbout << i << ": ";
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -254,7 +254,8 @@ int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
while (i < loops){
ndbout << i << ": ";
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -336,7 +337,7 @@ int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
g_debug << "Creating table" << endl;
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
g_err << "createTableInDb failed" << endl;
result = NDBT_FAILED;
continue;
@@ -357,7 +358,6 @@ int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
g_debug << "Dropping table" << endl;
-
if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
result = NDBT_FAILED;
@@ -1139,9 +1139,13 @@ runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
for (int i = 0; i < 16; i++) {
- Uint64 value = myNdb->getAutoIncrementValue(tabname, 1);
-
- if (value != (startvalue+i)) {
+ Uint64 value;
+ if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) {
+ g_err << "getAutoIncrementValue failed on " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+ else if (value != (startvalue+i)) {
g_err << "value = " << value << " expected " << startvalue+i << endl;;
APIERROR(myNdb->getNdbError());
// ret = NDBT_FAILED;
diff --git a/storage/ndb/test/ndbapi/testInterpreter.cpp b/storage/ndb/test/ndbapi/testInterpreter.cpp
index 0baba33d2b2..5d930d3d555 100644
--- a/storage/ndb/test/ndbapi/testInterpreter.cpp
+++ b/storage/ndb/test/ndbapi/testInterpreter.cpp
@@ -79,46 +79,46 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
- NdbConnection* pTrans = pNdb->startTransaction();
- if (pTrans == NULL){
- ERR(pNdb->getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- int check = pOp->interpretedUpdateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
-
- // Primary keys
- Uint32 pkVal = 1;
- check = pOp->equal("KOL1", pkVal );
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // Attributes
-
- // Update column
- Uint32 valToIncWith = 1;
- check = pOp->incValue("KOL2", valToIncWith);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
+ NdbConnection* pTrans = pNdb->startTransaction();
+ if (pTrans == NULL){
+ ERR(pNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ int check = pOp->interpretedUpdateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+
+ // Primary keys
+ Uint32 pkVal = 1;
+ check = pOp->equal("KOL1", pkVal );
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Attributes
+
+ // Update column
+ Uint32 valToIncWith = 1;
+ check = pOp->incValue("KOL2", valToIncWith);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
NdbRecAttr* valueRec = pOp->getValue("KOL2");
if( valueRec == NULL ) {
@@ -142,6 +142,122 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table * pTab = ctx->getTab();
+ Ndb* pNdb = GETNDB(step);
+
+ if (strcmp(pTab->getName(), "T1") != 0) {
+ g_err << "runTestBug19537: skip, table != T1" << endl;
+ return NDBT_OK;
+ }
+
+
+ NdbConnection* pTrans = pNdb->startTransaction();
+ if (pTrans == NULL){
+ ERR(pNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (pOp->interpretedUpdateTuple() == -1) {
+ ERR(pOp->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+
+ // Primary keys
+ const Uint32 pkVal = 1;
+ if (pOp->equal("KOL1", pkVal) == -1) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Load 64-bit constant into register 1 and
+ // write from register 1 to 32-bit column KOL2
+ const Uint64 reg_val = 0x0102030405060708ULL;
+
+ const Uint32* reg_ptr32 = (const Uint32*)&reg_val;
+ if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
+ g_err << "runTestBug19537: platform is LITTLE endian" << endl;
+ } else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {
+ g_err << "runTestBug19537: platform is BIG endian" << endl;
+ } else {
+ g_err << "runTestBug19537: impossible platform"
+ << hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (pOp->load_const_u64(1, reg_val) == -1 ||
+ pOp->write_attr("KOL2", 1) == -1) {
+ ERR(pOp->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (pTrans->execute(Commit) == -1) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Read value via a new transaction
+
+ pTrans = pNdb->startTransaction();
+ if (pTrans == NULL){
+ ERR(pNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ pOp = pTrans->getNdbOperation(pTab->getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 kol2 = 0x09090909;
+ if (pOp->readTuple() == -1 ||
+ pOp->equal("KOL1", pkVal) == -1 ||
+ pOp->getValue("KOL2", (char*)&kol2) == 0) {
+ ERR(pOp->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (pTrans->execute(Commit) == -1) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Expected conversion as in C - truncate to lower (logical) word
+
+ if (kol2 == 0x01020304) {
+ g_err << "runTestBug19537: the bug manifests itself !" << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (kol2 != 0x05060708) {
+ g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pTrans);
+ return NDBT_OK;
+}
+
NDBT_TESTSUITE(testInterpreter);
TESTCASE("IncValue32",
@@ -156,6 +272,12 @@ TESTCASE("IncValue64",
INITIALIZER(runTestIncValue64);
FINALIZER(runClearTable);
}
+TESTCASE("Bug19537",
+ "Test big-endian write_attr of 32 bit integer\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runTestBug19537);
+ FINALIZER(runClearTable);
+}
#if 0
TESTCASE("MaxTransactions",
"Start transactions until no more can be created\n"){
diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
index 08467a652f0..3fead45533f 100644
--- a/storage/ndb/test/run-test/daily-basic-tests.txt
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt
@@ -201,11 +201,19 @@ args: -n PkDeleteAsynch
max-time: 500
cmd: testBasic
-args: -n MassiveRollback T1 T6 T13 D1 D2
+args: -n MassiveRollback T1 T7 D1 D2
max-time: 500
cmd: testBasic
-args: -n MassiveRollback2 T1 T6 T13 D1 D2
+args: -n MassiveRollback2 T1 T7 D1 D2
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback3 T1 T7 D1 D2
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback4 T1 T7 D1 D2
max-time: 500
cmd: testBasic
diff --git a/storage/ndb/tools/delete_all.cpp b/storage/ndb/tools/delete_all.cpp
index feedded06ad..fcf9b425bd0 100644
--- a/storage/ndb/tools/delete_all.cpp
+++ b/storage/ndb/tools/delete_all.cpp
@@ -23,17 +23,21 @@
#include <NDBT.hpp>
static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
- bool commit_across_open_cursor, int parallelism=240);
+ bool fetch_across_commit, int parallelism=240);
NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
+static my_bool _transactional = false;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
{ "database", 'd', "Name of database table is in",
(gptr*) &_dbname, (gptr*) &_dbname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "transactional", 't', "Single transaction (may run out of operations)",
+ (gptr*) &_transactional, (gptr*) &_transactional, 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}
};
static void usage()
@@ -84,18 +88,11 @@ int main(int argc, char** argv){
ndbout << " Table " << argv[i] << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- // Check if we have any blobs
- bool commit_across_open_cursor = true;
- for (int j = 0; j < pTab->getNoOfColumns(); j++) {
- NdbDictionary::Column::Type t = pTab->getColumn(j)->getType();
- if (t == NdbDictionary::Column::Blob ||
- t == NdbDictionary::Column::Text) {
- commit_across_open_cursor = false;
- break;
- }
- }
- ndbout << "Deleting all from " << argv[i] << "...";
- if(clear_table(&MyNdb, pTab, commit_across_open_cursor) == NDBT_FAILED){
+ ndbout << "Deleting all from " << argv[i];
+ if (! _transactional)
+ ndbout << " (non-transactional)";
+ ndbout << " ...";
+ if(clear_table(&MyNdb, pTab, ! _transactional) == NDBT_FAILED){
res = NDBT_FAILED;
ndbout << "FAILED" << endl;
}
@@ -105,7 +102,7 @@ int main(int argc, char** argv){
int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
- bool commit_across_open_cursor, int parallelism)
+ bool fetch_across_commit, int parallelism)
{
// Scan all records exclusive and delete
// them one by one
@@ -136,7 +133,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
}
goto failed;
}
-
+
pOp = pTrans->getNdbScanOperation(pTab->getName());
if (pOp == NULL) {
goto failed;
@@ -167,7 +164,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
} while((check = pOp->nextResult(false)) == 0);
if(check != -1){
- if (commit_across_open_cursor) {
+ if (fetch_across_commit) {
check = pTrans->execute(NdbTransaction::Commit);
pTrans->restart(); // new tx id
} else {
@@ -198,7 +195,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
}
goto failed;
}
- if (! commit_across_open_cursor &&
+ if (! fetch_across_commit &&
pTrans->execute(NdbTransaction::Commit) != 0) {
err = pTrans->getNdbError();
goto failed;
diff --git a/storage/ndb/tools/desc.cpp b/storage/ndb/tools/desc.cpp
index 37157ef9eec..7c5ce68c950 100644
--- a/storage/ndb/tools/desc.cpp
+++ b/storage/ndb/tools/desc.cpp
@@ -18,6 +18,7 @@
#include <ndb_opts.h>
#include <NDBT.hpp>
#include <NdbApi.hpp>
+#include <NdbSleep.h>
void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags);
int desc_logfilegroup(Ndb *myndb, char* name);
@@ -31,6 +32,7 @@ NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
static int _unqualified = 0;
static int _partinfo = 0;
+static int _retries = 0;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -43,6 +45,9 @@ static struct my_option my_long_options[] =
{ "extra-partition-info", 'p', "Print more info per partition",
(gptr*) &_partinfo, (gptr*) &_partinfo, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "retries", 'r', "Retry every second for # retries",
+ (gptr*) &_retries, (gptr*) &_retries, 0,
+ GET_INT, 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 void usage()
@@ -231,7 +236,8 @@ int desc_datafile(Ndb_cluster_connection &con, Ndb *myndb, char* name)
int desc_table(Ndb *myndb, char* name)
{
NdbDictionary::Dictionary * dict= myndb->getDictionary();
- NDBT_Table* pTab = (NDBT_Table*)dict->getTable(name);
+ NDBT_Table* pTab;
+ while ((pTab = (NDBT_Table*)dict->getTable(name)) == NULL && --_retries >= 0) NdbSleep_SecSleep(1);
if (!pTab)
return 0;
diff --git a/storage/ndb/tools/listTables.cpp b/storage/ndb/tools/listTables.cpp
index ef51b66bb10..a221156280d 100644
--- a/storage/ndb/tools/listTables.cpp
+++ b/storage/ndb/tools/listTables.cpp
@@ -188,6 +188,8 @@ list(const char * tabname,
ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
}
}
+ if (_parsable)
+ exit(0);
}
NDB_STD_OPTS_VARS;
diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp
index 928cfbc6580..7762785ef61 100644
--- a/storage/ndb/tools/restore/Restore.cpp
+++ b/storage/ndb/tools/restore/Restore.cpp
@@ -25,6 +25,7 @@
#include <SimpleProperties.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <ndb_limits.h>
+#include <NdbAutoPtr.hpp>
#include "../../../../sql/ha_ndbcluster_tables.h"
@@ -291,6 +292,7 @@ RestoreMetaData::markSysTables()
strcmp(tableName, "NDB$EVENTS_0") == 0 ||
strcmp(tableName, "sys/def/SYSTAB_0") == 0 ||
strcmp(tableName, "sys/def/NDB$EVENTS_0") == 0 ||
+ strcmp(tableName, "cluster_replication/def/" NDB_APPLY_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 )
table->isSysTable = true;
@@ -377,7 +379,8 @@ bool
RestoreMetaData::parseTableDescriptor(const Uint32 * data, Uint32 len)
{
NdbTableImpl* tableImpl = 0;
- int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len, false);
+ int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len, false,
+ m_fileHeader.NdbVersion);
if (ret != 0) {
err << "parseTableInfo " << " failed" << endl;
@@ -956,14 +959,17 @@ RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md)
}
const LogEntry *
-RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
+RestoreLogIterator::getNextLogEntry(int & res) {
// Read record length
- typedef BackupFormat::LogFile::LogEntry LogE;
-
- LogE * logE= 0;
- Uint32 len= ~0;
const Uint32 stopGCP = m_metaData.getStopGCP();
+ Uint32 tableId;
+ Uint32 triggerEvent;
+ Uint32 frag_id;
+ Uint32 *attr_data;
+ Uint32 attr_data_len;
do {
+ Uint32 len;
+ Uint32 *logEntryPtr;
if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
res= -1;
return 0;
@@ -971,7 +977,7 @@ RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
len= ntohl(len);
Uint32 data_len = sizeof(Uint32) + len*4;
- if (buffer_get_ptr((void **)(&logE), 1, data_len) != data_len) {
+ if (buffer_get_ptr((void **)(&logEntryPtr), 1, data_len) != data_len) {
res= -2;
return 0;
}
@@ -980,7 +986,8 @@ RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
res= 0;
return 0;
}
- if (m_metaData.getFileHeader().NdbVersion < NDBD_FRAGID_VERSION)
+
+ if (unlikely(m_metaData.getFileHeader().NdbVersion < NDBD_FRAGID_VERSION))
{
/*
FragId was introduced in LogEntry in version
@@ -989,35 +996,37 @@ RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
do not support restore of user defined partitioned
tables.
*/
- int i;
- LogE *tmpLogE = (LogE*)NdbMem_Allocate(data_len + 4);
- if (!tmpLogE)
- {
- res = -2;
- return 0;
- }
- tmpLogE->Length = logE->Length;
- tmpLogE->TableId = logE->TableId;
- tmpLogE->TriggerEvent = logE->TriggerEvent;
- tmpLogE->FragId = 0;
- for (i = 0; i < len - 3; i++)
- tmpLogE->Data[i] = logE->Data[i-1];
- *alloc_flag= true;
+ typedef BackupFormat::LogFile::LogEntry_no_fragid LogE_no_fragid;
+ LogE_no_fragid * logE_no_fragid= (LogE_no_fragid *)logEntryPtr;
+ tableId= ntohl(logE_no_fragid->TableId);
+ triggerEvent= ntohl(logE_no_fragid->TriggerEvent);
+ frag_id= 0;
+ attr_data= &logE_no_fragid->Data[0];
+ attr_data_len= len - ((offsetof(LogE_no_fragid, Data) >> 2) - 1);
+ }
+ else /* normal case */
+ {
+ typedef BackupFormat::LogFile::LogEntry LogE;
+ LogE * logE= (LogE *)logEntryPtr;
+ tableId= ntohl(logE->TableId);
+ triggerEvent= ntohl(logE->TriggerEvent);
+ frag_id= ntohl(logE->FragId);
+ attr_data= &logE->Data[0];
+ attr_data_len= len - ((offsetof(LogE, Data) >> 2) - 1);
}
- logE->TableId= ntohl(logE->TableId);
- logE->TriggerEvent= ntohl(logE->TriggerEvent);
-
- const bool hasGcp= (logE->TriggerEvent & 0x10000) != 0;
- logE->TriggerEvent &= 0xFFFF;
+ const bool hasGcp= (triggerEvent & 0x10000) != 0;
+ triggerEvent &= 0xFFFF;
+
if(hasGcp){
- len--;
- m_last_gci = ntohl(logE->Data[len-2]);
+ // last attr_data is gci info
+ attr_data_len--;
+ m_last_gci = ntohl(*(attr_data + attr_data_len));
}
} while(m_last_gci > stopGCP + 1);
-
- m_logEntry.m_table = m_metaData.getTable(logE->TableId);
- switch(logE->TriggerEvent){
+
+ m_logEntry.m_table = m_metaData.getTable(tableId);
+ switch(triggerEvent){
case TriggerEvent::TE_INSERT:
m_logEntry.m_type = LogEntry::LE_INSERT;
break;
@@ -1035,10 +1044,10 @@ RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
const TableS * tab = m_logEntry.m_table;
m_logEntry.clear();
- AttributeHeader * ah = (AttributeHeader *)&logE->Data[0];
- AttributeHeader *end = (AttributeHeader *)&logE->Data[len - 2];
+ AttributeHeader * ah = (AttributeHeader *)attr_data;
+ AttributeHeader *end = (AttributeHeader *)(attr_data + attr_data_len);
AttributeS * attr;
- m_logEntry.m_frag_id = ntohl(logE->FragId);
+ m_logEntry.m_frag_id = frag_id;
while(ah < end){
attr= m_logEntry.add_attr();
if(attr == NULL) {
@@ -1047,6 +1056,9 @@ RestoreLogIterator::getNextLogEntry(int & res, bool *alloc_flag) {
return 0;
}
+ if(unlikely(!m_hostByteOrder))
+ *(Uint32*)ah = Twiddle32(*(Uint32*)ah);
+
attr->Desc = (* tab)[ah->getAttributeId()];
assert(attr->Desc != 0);
diff --git a/storage/ndb/tools/restore/Restore.hpp b/storage/ndb/tools/restore/Restore.hpp
index 516225cfab6..8698d0943e2 100644
--- a/storage/ndb/tools/restore/Restore.hpp
+++ b/storage/ndb/tools/restore/Restore.hpp
@@ -386,7 +386,7 @@ public:
RestoreLogIterator(const RestoreMetaData &);
virtual ~RestoreLogIterator() {};
- const LogEntry * getNextLogEntry(int & res, bool *alloc_flag);
+ const LogEntry * getNextLogEntry(int & res);
};
NdbOut& operator<<(NdbOut& ndbout, const TableS&);
diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp
index 3b39a1373a0..6b0d42ee0d2 100644
--- a/storage/ndb/tools/restore/consumer_restore.cpp
+++ b/storage/ndb/tools/restore/consumer_restore.cpp
@@ -151,9 +151,12 @@ BackupRestore::finalize_table(const TableS & table){
if (table.have_auto_inc())
{
Uint64 max_val= table.get_max_auto_val();
- Uint64 auto_val= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable));
- if (max_val+1 > auto_val || auto_val == ~(Uint64)0)
- ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false);
+ Uint64 auto_val;
+ int r= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable), auto_val);
+ if (r == -1 && m_ndb->getNdbError().code != 626)
+ ret= false;
+ else if (r == -1 || max_val+1 > auto_val)
+ ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != -1;
}
return ret;
}
diff --git a/storage/ndb/tools/restore/restore_main.cpp b/storage/ndb/tools/restore/restore_main.cpp
index bf57664ba9b..d76cf441dd6 100644
--- a/storage/ndb/tools/restore/restore_main.cpp
+++ b/storage/ndb/tools/restore/restore_main.cpp
@@ -483,10 +483,29 @@ main(int argc, char** argv)
char buf[NDB_VERSION_STRING_BUF_SZ];
info << "Ndb version in backup files: "
<< getVersionString(version, 0, buf, sizeof(buf)) << endl;
-
+
/**
* check wheater we can restore the backup (right version).
*/
+ // in these versions there was an error in how replica info was
+ // stored on disk
+ if (version >= MAKE_VERSION(5,1,3) && version <= MAKE_VERSION(5,1,9))
+ {
+ err << "Restore program incompatible with backup versions between "
+ << getVersionString(MAKE_VERSION(5,1,3), 0, buf, sizeof(buf))
+ << " and "
+ << getVersionString(MAKE_VERSION(5,1,9), 0, buf, sizeof(buf))
+ << endl;
+ exitHandler(NDBT_FAILED);
+ }
+
+ if (version > NDB_VERSION)
+ {
+ err << "Restore program older than backup version. Not supported. "
+ << "Use new restore program" << endl;
+ exitHandler(NDBT_FAILED);
+ }
+
debug << "Load content" << endl;
int res = metaData.loadContent();
@@ -615,14 +634,11 @@ main(int argc, char** argv)
}
const LogEntry * logEntry = 0;
- bool alloc_flag = false;
- while ((logEntry = logIter.getNextLogEntry(res= 0, &alloc_flag)) != 0)
+ while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
{
if (checkSysTable(logEntry->m_table))
for(Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->logEntry(* logEntry);
- if (alloc_flag)
- NdbMem_Free((void*)logEntry);
}
if (res < 0)
{
diff --git a/storage/ndb/tools/waiter.cpp b/storage/ndb/tools/waiter.cpp
index db90bd8bd90..cb02d5e7c36 100644
--- a/storage/ndb/tools/waiter.cpp
+++ b/storage/ndb/tools/waiter.cpp
@@ -124,6 +124,12 @@ getStatus(){
ndbout << "status==NULL, retries="<<retries<<endl;
MGMERR(handle);
retries++;
+ ndb_mgm_disconnect(handle);
+ if (ndb_mgm_connect(handle,0,0,1)) {
+ MGMERR(handle);
+ g_err << "Reconnect failed" << endl;
+ break;
+ }
continue;
}
int count = status->no_of_nodes;
diff --git a/strings/CHARSET_INFO.txt b/strings/CHARSET_INFO.txt
index f7a10f95880..40f171440a4 100644
--- a/strings/CHARSET_INFO.txt
+++ b/strings/CHARSET_INFO.txt
@@ -172,7 +172,7 @@ mb_wc - converts the left multibyte sequence into it Unicode code.
mc_mb - converts the given Unicode code into multibyte sequence.
-Case and sort convertion
+Case and sort conversion
------------------------
caseup_str - converts the given 0-terminated string into the upper case
casedn_str - converts the given 0-terminated string into the lower case
@@ -227,4 +227,4 @@ hash_sort() - calculates hash value taking in account
the collation rules, e.g. case-insensitivity,
accent sensitivity, etc.
- \ No newline at end of file
+
diff --git a/strings/cmakelists.txt b/strings/CMakeLists.txt
index ab4031f071a..ab4031f071a 100644
--- a/strings/cmakelists.txt
+++ b/strings/CMakeLists.txt
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 1183fcae01a..1cba4bab3f0 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -54,7 +54,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc
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 my_strchr.c cmakelists.txt
+ t_ctype.h my_strchr.c CMakeLists.txt
libmystrings_a_LIBADD=
conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 0e036c2bbcd..e4302f50c58 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -27,6 +27,7 @@
%#[l]d
%#[l]u
%#[l]x
+ %#.#b Local format; note first # is ignored and second is REQUIRED
%#.#s Note first # is ignored
RETURN
@@ -40,7 +41,7 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
for (; *fmt ; fmt++)
{
- if (fmt[0] != '%')
+ if (*fmt != '%')
{
if (to == end) /* End of buffer */
break;
@@ -95,6 +96,16 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
to=strnmov(to,par,plen);
continue;
}
+ else if (*fmt == 'b') /* Buffer parameter */
+ {
+ char *par = va_arg(ap, char *);
+ DBUG_ASSERT(to <= end);
+ if (to + abs(width) + 1 > end)
+ width= end - to - 1; /* sign doesn't matter */
+ memmove(to, par, abs(width));
+ to+= width;
+ continue;
+ }
else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */
{
register long larg;
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index bf17375c0eb..bd16297f8e7 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -265,7 +265,10 @@ case "$mode" in
then
# Give extra arguments to mysqld with the my.cnf file. This script may
# be overwritten at next upgrade.
- $manager --user=$user --pid-file=$pid_file >/dev/null 2>&1 &
+ "$manager" \
+ --mysqld-safe-compatible \
+ --user="$user" \
+ --pid-file="$pid_file" >/dev/null 2>&1 &
wait_for_pid created
# Make lock for RedHat / SuSE
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 4bff95b29fa..01746d3156e 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -217,8 +217,9 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \
--with-fast-mutexes \
--with-mysqld-user=%{mysqld_user} \
--with-unix-socket-path=/var/lib/mysql/mysql.sock \
+ --with-pic \
--prefix=/ \
- --with-extra-charsets=complex \
+ --with-extra-charsets=all \
%if %{YASSL_BUILD}
--with-yassl \
%endif
@@ -319,7 +320,7 @@ BuildMySQL "--enable-shared \
--with-example-storage-engine \
--with-blackhole-storage-engine \
--with-federated-storage-engine \
- --with-big-tables \
+ --with-big-tables \
--with-comment=\"MySQL Community Server - Max (GPL)\"")
# We might want to save the config log file
@@ -388,22 +389,12 @@ install -d $RBR%{_sbindir}
mv $RBR/%{_libdir}/mysql/*.so* $RBR/%{_libdir}/
# install "mysqld-debug" and "mysqld-max"
-if test -f $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-debug-%{mysql_version}/sql/.libs/mysqld
-then
- install -m 755 $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-debug-%{mysql_version}/sql/.libs/mysqld \
+./libtool --mode=execute install -m 755 \
+ $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-debug-%{mysql_version}/sql/mysqld \
$RBR%{_sbindir}/mysqld-debug
-else
- install -m 755 $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-debug-%{mysql_version}/sql/mysqld \
- $RBR%{_sbindir}/mysqld-debug
-fi
-if test -f $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-max-%{mysql_version}/sql/.libs/mysqld
-then
- install -m 755 $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-max-%{mysql_version}/sql/.libs/mysqld \
- $RBR%{_sbindir}/mysqld-max
-else
- install -m 755 $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-max-%{mysql_version}/sql/mysqld \
+./libtool --mode=execute install -m 755 \
+ $RPM_BUILD_DIR/mysql-%{mysql_version}/mysql-max-%{mysql_version}/sql/mysqld \
$RBR%{_sbindir}/mysqld-max
-fi
# install saved perror binary with NDB support (BUG#13740)
install -m 755 $MBD/extra/perror $RBR%{_bindir}/perror
@@ -473,9 +464,12 @@ usermod -g %{mysqld_group} %{mysqld_user} 2> /dev/null || true
# owns all database files.
chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
-# Initiate databases
+# Initiate databases if needed
%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
+# Upgrade databases if needed
+%{_bindir}/mysql_upgrade --user=%{mysqld_user}
+
# Change permissions again to fix any new files.
chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
@@ -541,6 +535,7 @@ fi
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1*
+%doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1*
@@ -552,30 +547,30 @@ fi
%ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf
%ghost %config(noreplace,missingok) %{_sysconfdir}/mysqlmanager.passwd
-%attr(755, root, root) %{_bindir}/myisamchk
+%attr(755, root, root) %{_bindir}/my_print_defaults
%attr(755, root, root) %{_bindir}/myisam_ftdump
+%attr(755, root, root) %{_bindir}/myisamchk
%attr(755, root, root) %{_bindir}/myisamlog
%attr(755, root, root) %{_bindir}/myisampack
-%attr(755, root, root) %{_bindir}/my_print_defaults
-%attr(755, root, root) %{_bindir}/mysqlbug
%attr(755, root, root) %{_bindir}/mysql_convert_table_format
%attr(755, root, root) %{_bindir}/mysql_create_system_tables
-%attr(755, root, root) %{_bindir}/mysqld_multi
-%attr(755, root, root) %{_bindir}/mysqld_safe
-%attr(755, root, root) %{_bindir}/mysql_explain_log
%attr(755, root, root) %{_bindir}/mysql_fix_extensions
%attr(755, root, root) %{_bindir}/mysql_fix_privilege_tables
-%attr(755, root, root) %{_bindir}/mysqlhotcopy
%attr(755, root, root) %{_bindir}/mysql_install_db
%attr(755, root, root) %{_bindir}/mysql_secure_installation
%attr(755, root, root) %{_bindir}/mysql_setpermission
-%attr(755, root, root) %{_bindir}/mysqltest
%attr(755, root, root) %{_bindir}/mysql_tzinfo_to_sql
+%attr(755, root, root) %{_bindir}/mysql_upgrade
%attr(755, root, root) %{_bindir}/mysql_zap
+%attr(755, root, root) %{_bindir}/mysqlbug
+%attr(755, root, root) %{_bindir}/mysqld_multi
+%attr(755, root, root) %{_bindir}/mysqld_safe
+%attr(755, root, root) %{_bindir}/mysqlhotcopy
+%attr(755, root, root) %{_bindir}/mysqltest
%attr(755, root, root) %{_bindir}/perror
%attr(755, root, root) %{_bindir}/replace
-%attr(755, root, root) %{_bindir}/resolveip
%attr(755, root, root) %{_bindir}/resolve_stack_dump
+%attr(755, root, root) %{_bindir}/resolveip
%attr(755, root, root) %{_bindir}/safe_mysqld
%attr(755, root, root) %{_sbindir}/mysqld
@@ -641,6 +636,7 @@ fi
%attr(755, root, root) %{_bindir}/ndb_desc
%attr(755, root, root) %{_bindir}/ndb_show_tables
%attr(755, root, root) %{_bindir}/ndb_test_platform
+%attr(755, root, root) %{_bindir}/ndb_config
%files ndb-extra
%defattr(-,root,root,0755)
@@ -687,6 +683,24 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Sat May 20 2006 Kent Boortz <kent@mysql.com>
+
+- Always compile for PIC, position independent code.
+
+* Wed May 10 2006 Kent Boortz <kent@mysql.com>
+
+- Use character set "all" when compiling with Cluster, to make Cluster
+ nodes independent on the character set directory, and the problem
+ that two RPM sub packages both wants to install this directory.
+
+* Mon May 01 2006 Kent Boortz <kent@mysql.com>
+
+- Use "./libtool --mode=execute" instead of searching for the
+ executable in current directory and ".libs".
+
+* Fri Apr 28 2006 Kent Boortz <kent@mysql.com>
+
+- Install and run "mysql_upgrade"
* Wed Apr 12 2006 Jim Winstead <jimw@mysql.com>
@@ -696,7 +710,6 @@ fi
* Tue Apr 11 2006 Jim Winstead <jimw@mysql.com>
- Remove old mysqltestmanager and related programs
-
* Sat Apr 01 2006 Kent Boortz <kent@mysql.com>
- Set $LDFLAGS from $MYSQL_BUILD_LDFLAGS
diff --git a/tests/cmakelists.txt b/tests/CMakeLists.txt
index c9b0b8735a2..46c42d461f3 100644
--- a/tests/cmakelists.txt
+++ b/tests/CMakeLists.txt
@@ -6,4 +6,4 @@ ADD_DEFINITIONS("-DMYSQL_CLIENT")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(mysql_client_test mysql_client_test.c)
-TARGET_LINK_LIBRARIES(mysql_client_test dbug mysqlclient yassl taocrypt zlib wsock32)
+TARGET_LINK_LIBRARIES(mysql_client_test dbug mysys mysqlclient yassl taocrypt zlib wsock32)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ba0a7ad73d0..8ee64f8179c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,13 @@ if HAVE_YASSL
else
yassl_dummy_link_fix=
endif
+
+if THREAD_SAFE_CLIENT
+LIBMYSQLCLIENT_LA = $(top_builddir)/libmysql_r/libmysqlclient_r.la
+else
+LIBMYSQLCLIENT_LA = $(top_builddir)/libmysql/libmysqlclient.la
+endif
+
EXTRA_DIST = auto_increment.res auto_increment.tst \
function.res function.tst lock_test.pl lock_test.res \
export.pl big_record.pl \
@@ -30,7 +37,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
grant.pl grant.res test_delayed_insert.pl \
pmail.pl mail_to_db.pl table_types.pl \
udf_test udf_test.res myisam-big-rows.tst \
- cmakelists.txt
+ CMakeLists.txt
bin_PROGRAMS = mysql_client_test
noinst_PROGRAMS = insert_test select_test thread_test
@@ -42,8 +49,8 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes)
LIBS = @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ \
- $(top_builddir)/libmysql/libmysqlclient.la
-mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
+ $(LIBMYSQLCLIENT_LA)
+mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys
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)
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 5730efced35..e3159cfa5e5 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -12794,25 +12794,26 @@ from t2);");
static void test_bug8378()
{
#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
- MYSQL *lmysql;
+ MYSQL *old_mysql=mysql;
char out[9]; /* strlen(TEST_BUG8378)*2+1 */
- int len;
+ char buf[256];
+ int len, rc;
myheader("test_bug8378");
if (!opt_silent)
fprintf(stdout, "\n Establishing a test connection ...");
- if (!(lmysql= mysql_init(NULL)))
+ if (!(mysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
exit(1);
}
- if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk"))
+ if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk"))
{
myerror("mysql_options() failed");
exit(1);
}
- if (!(mysql_real_connect(lmysql, opt_host, opt_user,
+ if (!(mysql_real_connect(mysql, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket, 0)))
{
@@ -12822,12 +12823,18 @@ static void test_bug8378()
if (!opt_silent)
fprintf(stdout, " OK");
- len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4);
+ len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
/* No escaping should have actually happened. */
DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0);
- mysql_close(lmysql);
+ sprintf(buf, "SELECT '%s'", out);
+ rc=mysql_real_query(mysql, buf, strlen(buf));
+ myquery(rc);
+
+ mysql_close(mysql);
+
+ mysql=old_mysql;
#endif
}
@@ -14839,6 +14846,73 @@ static void test_bug15613()
myquery(rc);
mysql_stmt_close(stmt);
}
+
+/*
+ Bug#17667: An attacker has the opportunity to bypass query logging.
+*/
+static void test_bug17667()
+{
+ int rc;
+ struct buffer_and_length {
+ const char *buffer;
+ const uint length;
+ } statements[]= {
+ { "drop table if exists bug17667", 29 },
+ { "create table bug17667 (c varchar(20))", 37 },
+ { "insert into bug17667 (c) values ('regular') /* NUL=\0 with comment */", 68 },
+ { "insert into bug17667 (c) values ('NUL=\0 in value')", 50 },
+ { "insert into bug17667 (c) values ('5 NULs=\0\0\0\0\0')", 48 },
+ { "/* NUL=\0 with comment */ insert into bug17667 (c) values ('encore')", 67 },
+ { "drop table bug17667", 19 },
+ { NULL, 0 } };
+
+ struct buffer_and_length *statement_cursor;
+ FILE *log_file;
+
+ myheader("test_bug17667");
+
+ for (statement_cursor= statements; statement_cursor->buffer != NULL;
+ statement_cursor++) {
+ rc= mysql_real_query(mysql, statement_cursor->buffer,
+ statement_cursor->length);
+ myquery(rc);
+ }
+
+ sleep(1); /* The server may need time to flush the data to the log. */
+ log_file= fopen("var/log/master.log", "r");
+ if (log_file != NULL) {
+
+ for (statement_cursor= statements; statement_cursor->buffer != NULL;
+ statement_cursor++) {
+ char line_buffer[MAX_TEST_QUERY_LENGTH*2];
+ /* more than enough room for the query and some marginalia. */
+
+ do {
+ memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
+
+ DIE_UNLESS(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) !=
+ NULL);
+ /* If we reach EOF before finishing the statement list, then we failed. */
+
+ } while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2,
+ statement_cursor->buffer, statement_cursor->length) == NULL);
+ }
+
+ printf("success. All queries found intact in the log.\n");
+
+ } else {
+ fprintf(stderr, "Could not find the log file, var/log/master.log, so "
+ "test_bug17667 is \ninconclusive. Run test from the "
+ "mysql-test/mysql-test-run* program \nto set up the correct "
+ "environment for this test.\n\n");
+ }
+
+ if (log_file != NULL)
+ fclose(log_file);
+
+}
+
+
/*
Bug#14169: type of group_concat() result changed to blob if tmp_table was used
*/
@@ -15139,6 +15213,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 },
{ "test_bug14169", test_bug14169 },
+ { "test_bug17667", test_bug17667 },
{ 0, 0 }
};
diff --git a/unittest/examples/no_plan.t.c b/unittest/examples/no_plan.t.c
index 67029c7962f..98e4d06def6 100644
--- a/unittest/examples/no_plan.t.c
+++ b/unittest/examples/no_plan.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include <stdlib.h>
#include <tap.h>
diff --git a/unittest/examples/skip_all.t.c b/unittest/examples/skip_all.t.c
index bbde6b63f1c..19b8c1fddaf 100644
--- a/unittest/examples/skip_all.t.c
+++ b/unittest/examples/skip_all.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include <stdlib.h>
#include <tap.h>
diff --git a/unittest/examples/todo.t.c b/unittest/examples/todo.t.c
index 13a0c950b54..82601bee41c 100644
--- a/unittest/examples/todo.t.c
+++ b/unittest/examples/todo.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include <stdlib.h>
#include <tap.h>
diff --git a/unittest/mytap/t/basic.t.c b/unittest/mytap/t/basic.t.c
index eb820d6c651..bf4c1a9a664 100644
--- a/unittest/mytap/t/basic.t.c
+++ b/unittest/mytap/t/basic.t.c
@@ -1,6 +1,8 @@
+#include "my_config.h"
+
#include <stdlib.h>
-#include <tap.h>
+#include "../tap.h"
int main() {
plan(5);
diff --git a/vio/cmakelists.txt b/vio/CMakeLists.txt
index a3cbb304289..a3cbb304289 100644
--- a/vio/cmakelists.txt
+++ b/vio/CMakeLists.txt
diff --git a/vio/Makefile.am b/vio/Makefile.am
index b7e002a3033..e1830fdc636 100644
--- a/vio/Makefile.am
+++ b/vio/Makefile.am
@@ -38,7 +38,7 @@ test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs) $(yassl_libs)
libvio_a_SOURCES= vio.c viosocket.c viossl.c viosslfactories.c
-EXTRA_DIST= cmakelists.txt
+EXTRA_DIST= CMakeLists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/vio/test-ssl.c b/vio/test-ssl.c
index a94eb1a21ff..f8172426e38 100644
--- a/vio/test-ssl.c
+++ b/vio/test-ssl.c
@@ -57,8 +57,8 @@ main(int argc, char** argv)
char* cipher=0;
int child_pid,sv[2];
my_bool unused;
- struct st_VioSSLAcceptorFd* ssl_acceptor=0;
- struct st_VioSSLConnectorFd* ssl_connector=0;
+ struct st_VioSSLFd* ssl_acceptor= 0;
+ struct st_VioSSLFd* ssl_connector= 0;
Vio* client_vio=0, *server_vio=0;
MY_INIT(argv[0]);
DBUG_PROCESS(argv[0]);
diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c
index 3811ba0fb6a..49d6768c884 100644
--- a/vio/test-sslclient.c
+++ b/vio/test-sslclient.c
@@ -46,7 +46,7 @@ main( int argc __attribute__((unused)),
{
char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem";
char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0;
- struct st_VioSSLConnectorFd* ssl_connector=0;
+ struct st_VioSSLFd* ssl_connector= 0;
struct sockaddr_in sa;
Vio* client_vio=0;
int err;
diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c
index e4d32a75264..daec3a6e6f9 100644
--- a/vio/test-sslserver.c
+++ b/vio/test-sslserver.c
@@ -44,7 +44,7 @@ fatal_error( const char* r)
typedef struct {
int sd;
- struct st_VioSSLAcceptorFd* ssl_acceptor;
+ struct st_VioSSLFd* ssl_acceptor;
} TH_ARGS;
static void
@@ -82,7 +82,7 @@ main(int argc __attribute__((unused)), char** argv)
char ca_file[] = "../SSL/cacert.pem",
*ca_path = 0,
*cipher = 0;
- struct st_VioSSLAcceptorFd* ssl_acceptor;
+ struct st_VioSSLFd* ssl_acceptor;
pthread_t th;
TH_ARGS th_args;
diff --git a/vio/vio.c b/vio/vio.c
index 9ace22e3780..f20acb249ef 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
if (type == VIO_TYPE_SSL)
{
vio->viodelete =vio_delete;
- vio->vioerrno =vio_ssl_errno;
+ vio->vioerrno =vio_errno;
vio->read =vio_ssl_read;
vio->write =vio_ssl_write;
- vio->fastsend =vio_ssl_fastsend;
- vio->viokeepalive =vio_ssl_keepalive;
- vio->should_retry =vio_ssl_should_retry;
- vio->was_interrupted=vio_ssl_was_interrupted;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_ssl_close;
- vio->peer_addr =vio_ssl_peer_addr;
- vio->in_addr =vio_ssl_in_addr;
+ vio->peer_addr =vio_peer_addr;
+ vio->in_addr =vio_in_addr;
vio->vioblocking =vio_ssl_blocking;
vio->is_blocking =vio_is_blocking;
- vio->timeout =vio_ssl_timeout;
+ vio->timeout =vio_timeout;
}
else /* default is VIO_TYPE_TCPIP */
#endif /* HAVE_OPENSSL */
@@ -233,3 +233,16 @@ void vio_delete(Vio* vio)
my_free((gptr) vio,MYF(0));
}
}
+
+
+/*
+ Cleanup memory allocated by vio or the
+ components below it when application finish
+
+*/
+void vio_end(void)
+{
+#ifdef HAVE_YASSL
+ yaSSL_CleanUp();
+#endif
+}
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index eb495025ddd..db331abdea8 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -30,28 +30,10 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout);
int vio_ssl_read(Vio *vio,gptr buf, int size);
int vio_ssl_write(Vio *vio,const gptr buf,int size);
-void vio_ssl_timeout(Vio *vio, uint which, uint timeout);
-
-/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */
-int vio_ssl_fastsend(Vio *vio);
-/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */
-int vio_ssl_keepalive(Vio *vio, my_bool onoff);
-/* Whenever we should retry the last read/write operation. */
-my_bool vio_ssl_should_retry(Vio *vio);
-/* Check that operation was timed out */
-my_bool vio_ssl_was_interrupted(Vio *vio);
+
/* When the workday is over... */
int vio_ssl_close(Vio *vio);
-/* Return last error number */
-int vio_ssl_errno(Vio *vio);
-my_bool vio_ssl_peer_addr(Vio *vio, char *buf, uint16 *port);
-void vio_ssl_in_addr(Vio *vio, struct in_addr *in);
+
int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode);
-/* Single copy for server */
-enum vio_ssl_acceptorfd_state
-{
- state_connect = 1,
- state_accept = 2
-};
#endif /* HAVE_OPENSSL */
diff --git a/vio/viossl.c b/vio/viossl.c
index a0262a79209..e869493c604 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -51,384 +51,240 @@ static int SSL_set_fd_bsd(SSL *s, int fd)
static void
-report_errors()
+report_errors(SSL* ssl)
{
unsigned long l;
- const char* file;
- const char* data;
- int line,flags;
+ const char *file;
+ const char *data;
+ int line, flags;
+#ifndef DBUG_OFF
+ char buf[512];
+#endif
+
DBUG_ENTER("report_errors");
- while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)))
+ while ((l= ERR_get_error_line_data(&file,&line,&data,&flags)))
{
- char buf[512];
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
- DBUG_PRINT("info", ("errno: %d", socket_errno));
- DBUG_VOID_RETURN;
-}
+ if (ssl)
+ DBUG_PRINT("error", ("error: %s",
+ ERR_error_string(SSL_get_error(ssl, l), buf)));
-int vio_ssl_errno(Vio *vio __attribute__((unused)))
-{
- return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
+ DBUG_PRINT("info", ("socket_errno: %d", socket_errno));
+ DBUG_VOID_RETURN;
}
-int vio_ssl_read(Vio * vio, gptr buf, int size)
+int vio_ssl_read(Vio *vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_read");
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)
- {
- int err= SSL_get_error((SSL*) vio->ssl_arg, r);
- DBUG_PRINT("error",("SSL_read(): %d SSL_get_error(): %d", r, err));
- report_errors();
- }
+ r= SSL_read((SSL*) vio->ssl_arg, buf, size);
+#ifndef DBUG_OFF
+ if (r < 0)
+ report_errors((SSL*) vio->ssl_arg);
+#endif
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
-int vio_ssl_write(Vio * vio, const gptr buf, int size)
+int vio_ssl_write(Vio *vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_write");
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();
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-int vio_ssl_fastsend(Vio * vio __attribute__((unused)))
-{
- int r=0;
- DBUG_ENTER("vio_ssl_fastsend");
-
-#if defined(IPTOS_THROUGHPUT)
- {
- int tos= IPTOS_THROUGHPUT;
- r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
- }
-#endif /* IPTOS_THROUGHPUT */
- if (!r)
- {
-#ifdef __WIN__
- BOOL nodelay= 1;
- r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay,
- sizeof(nodelay));
-#else
- int nodelay= 1;
- r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
- sizeof(nodelay));
-#endif /* __WIN__ */
- }
- if (r)
- {
- DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
- r= -1;
- }
+ r= SSL_write((SSL*) vio->ssl_arg, buf, size);
+#ifndef DBUG_OFF
+ if (r < 0)
+ report_errors((SSL*) vio->ssl_arg);
+#endif
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
-int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive)
+int vio_ssl_close(Vio *vio)
{
- int r=0;
- DBUG_ENTER("vio_ssl_keepalive");
- DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
- set_keep_alive));
- if (vio->type != VIO_TYPE_NAMEDPIPE)
- {
- uint opt = (set_keep_alive) ? 1 : 0;
- r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
- sizeof(opt));
- }
- DBUG_RETURN(r);
-}
-
-
-my_bool
-vio_ssl_should_retry(Vio * vio __attribute__((unused)))
-{
- int en = socket_errno;
- return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
- en == SOCKET_EWOULDBLOCK);
-}
-
-
-my_bool
-vio_ssl_was_interrupted(Vio *vio __attribute__((unused)))
-{
- int en= socket_errno;
- return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
- en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
-}
-
-
-int vio_ssl_close(Vio * vio)
-{
- int r;
+ int r= 0;
+ SSL *ssl= (SSL*)vio->ssl_arg;
DBUG_ENTER("vio_ssl_close");
- r=0;
- if ((SSL*) vio->ssl_arg)
- {
- r = SSL_shutdown((SSL*) vio->ssl_arg);
- SSL_free((SSL*) vio->ssl_arg);
- vio->ssl_arg= 0;
- }
- if (vio->sd >= 0)
- {
- if (shutdown(vio->sd, 2))
- r= -1;
- if (closesocket(vio->sd))
- r= -1;
- }
- if (r)
- {
- DBUG_PRINT("error", ("close() failed, error: %d",socket_errno));
- report_errors();
- /* FIXME: error handling (not critical for MySQL) */
- }
- vio->type= VIO_CLOSED;
- vio->sd= -1;
- DBUG_RETURN(r);
-}
-
-const char *vio_ssl_description(Vio * vio)
-{
- return vio->desc;
-}
-
-enum enum_vio_type vio_ssl_type(Vio* vio)
-{
- return vio->type;
-}
-
-my_socket vio_ssl_fd(Vio* vio)
-{
- return vio->sd;
-}
-
-
-my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
-{
- DBUG_ENTER("vio_ssl_peer_addr");
- DBUG_PRINT("enter", ("sd: %d", vio->sd));
- if (vio->localhost)
- {
- strmov(buf,"127.0.0.1");
- *port=0;
- }
- else
+ if (ssl)
{
- size_socket addrLen = sizeof(struct sockaddr);
- if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
- &addrLen) != 0)
+ switch ((r= SSL_shutdown(ssl)))
{
- DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
- DBUG_RETURN(1);
+ case 1: /* Shutdown successful */
+ break;
+ case 0: /* Shutdown not yet finished, call it again */
+ if ((r= SSL_shutdown(ssl) >= 0))
+ break;
+ /* Fallthrough */
+ default: /* Shutdown failed */
+ DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s",
+ SSL_get_error(ssl, r)));
+ break;
}
-#ifdef TO_BE_FIXED
- my_inet_ntoa(vio->remote.sin_addr,buf);
- *port= 0;
-#else
- strmov(buf, "unknown");
- *port= 0;
-#endif
+ SSL_free(ssl);
+ vio->ssl_arg= 0;
}
- DBUG_PRINT("exit", ("addr: %s", buf));
- DBUG_RETURN(0);
+ DBUG_RETURN(vio_close(vio));
}
-void vio_ssl_in_addr(Vio *vio, struct in_addr *in)
+int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
{
- DBUG_ENTER("vio_ssl_in_addr");
- if (vio->localhost)
- bzero((char*) in, sizeof(*in));
- else
- *in=vio->remote.sin_addr;
- DBUG_VOID_RETURN;
-}
-
-
-/*
- TODO: Add documentation
-*/
-
-int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
-{
- char *str;
- char buf[1024];
- X509* client_cert;
+ SSL *ssl;
my_bool unused;
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
- DBUG_PRINT("enter", ("sd: %d ptr: Ox%p, timeout: %d",
+ DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d",
vio->sd, ptr, timeout));
old_type= vio->type;
- net_blocking = vio_is_blocking(vio);
+ net_blocking= vio_is_blocking(vio);
vio_blocking(vio, 1, &unused); /* Must be called before reset */
- vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
- vio->ssl_arg= 0;
- if (!(vio->ssl_arg= (void*) SSL_new(ptr->ssl_context)))
+ vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE);
+
+ if (!(ssl= SSL_new(ptr->ssl_context)))
{
DBUG_PRINT("error", ("SSL_new failure"));
- report_errors();
+ report_errors(ssl);
vio_reset(vio, old_type,vio->sd,0,FALSE);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
- 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);
- SSL_set_accept_state((SSL*) vio->ssl_arg);
- if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1)
+ vio->ssl_arg= (void*)ssl;
+ DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout));
+ SSL_clear(ssl);
+ SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
+ SSL_set_fd(ssl, vio->sd);
+ SSL_set_accept_state(ssl);
+ if (SSL_do_handshake(ssl) < 1)
{
DBUG_PRINT("error", ("SSL_do_handshake failure"));
- report_errors();
- SSL_free((SSL*) vio->ssl_arg);
+ report_errors(ssl);
+ SSL_free(ssl);
vio->ssl_arg= 0;
vio_reset(vio, old_type,vio->sd,0,FALSE);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
+
#ifndef DBUG_OFF
- DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
- ,SSL_get_cipher_name((SSL*) vio->ssl_arg)));
- client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg);
- if (client_cert != NULL)
{
- DBUG_PRINT("info",("Client certificate:"));
- str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
- DBUG_PRINT("info",("\t subject: %s", str));
- free (str);
+ char buf[1024];
+ X509 *client_cert;
+ DBUG_PRINT("info",("cipher_name= '%s'", SSL_get_cipher_name(ssl)));
- str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
- DBUG_PRINT("info",("\t issuer: %s", str));
- free (str);
+ if ((client_cert= SSL_get_peer_certificate (ssl)))
+ {
+ DBUG_PRINT("info",("Client certificate:"));
+ X509_NAME_oneline (X509_get_subject_name (client_cert),
+ buf, sizeof(buf));
+ DBUG_PRINT("info",("\t subject: %s", buf));
- X509_free (client_cert);
- }
- else
- DBUG_PRINT("info",("Client does not have certificate."));
+ X509_NAME_oneline (X509_get_issuer_name (client_cert),
+ buf, sizeof(buf));
+ DBUG_PRINT("info",("\t issuer: %s", buf));
- str=SSL_get_shared_ciphers((SSL*) vio->ssl_arg, buf, sizeof(buf));
- if (str)
- {
- DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str));
- }
- else
- {
- DBUG_PRINT("info",("no shared ciphers!"));
- }
+ X509_free (client_cert);
+ }
+ else
+ DBUG_PRINT("info",("Client does not have certificate."));
+ if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
+ {
+ DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
+ }
+ else
+ DBUG_PRINT("info",("no shared ciphers!"));
+ }
#endif
+
DBUG_RETURN(0);
}
-int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
+int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
{
- char *str;
- X509* server_cert;
+ SSL *ssl;
my_bool unused;
my_bool net_blocking;
- enum enum_vio_type old_type;
+ enum enum_vio_type old_type;
+
DBUG_ENTER("sslconnect");
- DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p",
- vio->sd,ptr,ptr->ssl_context));
+ DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p",
+ vio->sd, ptr, ptr->ssl_context));
old_type= vio->type;
- net_blocking = vio_is_blocking(vio);
+ net_blocking= vio_is_blocking(vio);
vio_blocking(vio, 1, &unused); /* Must be called before reset */
- vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
- vio->ssl_arg= 0;
- if (!(vio->ssl_arg = SSL_new(ptr->ssl_context)))
+ vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE);
+ if (!(ssl= SSL_new(ptr->ssl_context)))
{
DBUG_PRINT("error", ("SSL_new failure"));
- report_errors();
- vio_reset(vio, old_type,vio->sd,0,FALSE);
- vio_blocking(vio, net_blocking, &unused);
+ report_errors(ssl);
+ vio_reset(vio, old_type, vio->sd, 0, FALSE);
+ vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
- 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_ssl_fd(vio));
- SSL_set_connect_state((SSL*) vio->ssl_arg);
- if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1)
+ vio->ssl_arg= (void*)ssl;
+ DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout));
+ SSL_clear(ssl);
+ SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
+ SSL_set_fd(ssl, vio->sd);
+ SSL_set_connect_state(ssl);
+ if (SSL_do_handshake(ssl) < 1)
{
DBUG_PRINT("error", ("SSL_do_handshake failure"));
- report_errors();
- SSL_free((SSL*) vio->ssl_arg);
+ report_errors(ssl);
+ SSL_free(ssl);
vio->ssl_arg= 0;
- vio_reset(vio, old_type,vio->sd,0,FALSE);
+ vio_reset(vio, old_type, vio->sd, 0, FALSE);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
- }
+ }
#ifndef DBUG_OFF
- DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
- ,SSL_get_cipher_name((SSL*) vio->ssl_arg)));
- server_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg);
- if (server_cert != NULL)
{
- DBUG_PRINT("info",("Server certificate:"));
- str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0);
- DBUG_PRINT("info",("\t subject: %s", str));
- free(str);
-
- str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0);
- DBUG_PRINT("info",("\t issuer: %s", str));
- free(str);
-
- /*
- We could do all sorts of certificate verification stuff here before
- deallocating the certificate.
- */
- X509_free (server_cert);
+ X509 *server_cert;
+ DBUG_PRINT("info",("cipher_name: '%s'" , SSL_get_cipher_name(ssl)));
+
+ if ((server_cert= SSL_get_peer_certificate (ssl)))
+ {
+ char buf[256];
+ DBUG_PRINT("info",("Server certificate:"));
+ X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf));
+ DBUG_PRINT("info",("\t subject: %s", buf));
+ X509_NAME_oneline (X509_get_issuer_name(server_cert), buf, sizeof(buf));
+ DBUG_PRINT("info",("\t issuer: %s", buf));
+ X509_free (server_cert);
+ }
+ else
+ DBUG_PRINT("info",("Server does not have certificate."));
}
- else
- DBUG_PRINT("info",("Server does not have certificate."));
#endif
+
DBUG_RETURN(0);
}
-int vio_ssl_blocking(Vio * vio __attribute__((unused)),
+int vio_ssl_blocking(Vio *vio __attribute__((unused)),
my_bool set_blocking_mode,
my_bool *old_mode)
{
+ /* Mode is always blocking */
+ *old_mode= 1;
/* Return error if we try to change to non_blocking mode */
- *old_mode=1; /* Mode is always blocking */
- return set_blocking_mode ? 0 : 1;
+ return (set_blocking_mode ? 0 : 1);
}
-
-void vio_ssl_timeout(Vio *vio __attribute__((unused)),
- uint which __attribute__((unused)),
- uint timeout __attribute__((unused)))
-{
-#ifdef __WIN__
- ulong wait_timeout= (ulong) timeout * 1000;
- (void) setsockopt(vio->sd, SOL_SOCKET,
- which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout,
- sizeof(wait_timeout));
-#endif /* __WIN__ */
-}
#endif /* HAVE_OPENSSL */
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 4ee27f1e491..ca7a96d5801 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -21,7 +21,6 @@
static bool ssl_algorithms_added = FALSE;
static bool ssl_error_strings_loaded= FALSE;
static int verify_depth = 0;
-static int verify_error = X509_V_OK;
static unsigned char dh512_p[]=
{
@@ -82,30 +81,31 @@ 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",
ctx, cert_file, key_file));
- if (cert_file != NULL)
+ if (cert_file)
{
- if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0)
+ if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0)
{
- DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file));
+ DBUG_PRINT("error",("unable to get certificate from '%s'\n", cert_file));
/* FIX stderr */
fprintf(stderr,"Error when connection to server using SSL:");
ERR_print_errors_fp(stderr);
fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file);
fflush(stderr);
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
- if (key_file == NULL)
- key_file = cert_file;
- if (SSL_CTX_use_PrivateKey_file(ctx,key_file,
- SSL_FILETYPE_PEM) <= 0)
+
+ if (!key_file)
+ key_file= cert_file;
+
+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
{
- DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file));
+ DBUG_PRINT("error", ("unable to get private key from '%s'\n", key_file));
/* FIX stderr */
fprintf(stderr,"Error when connection to server using SSL:");
ERR_print_errors_fp(stderr);
- fprintf(stderr,"Unable to get private key from '%s'\n", cert_file);
- fflush(stderr);
- DBUG_RETURN(0);
+ fprintf(stderr,"Unable to get private key from '%s'\n", key_file);
+ fflush(stderr);
+ DBUG_RETURN(1);
}
/*
@@ -116,45 +116,45 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_PRINT("error",
("Private key does not match the certificate public key\n"));
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
}
- DBUG_RETURN(1);
+ DBUG_RETURN(0);
}
static int
vio_verify_callback(int ok, X509_STORE_CTX *ctx)
{
- char buf[256];
- X509* err_cert;
- int err,depth;
+ char buf[256];
+ X509 *err_cert;
DBUG_ENTER("vio_verify_callback");
- 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);
+ DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx));
- X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
+ err_cert= X509_STORE_CTX_get_current_cert(ctx);
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+ DBUG_PRINT("info", ("cert: %s", buf));
if (!ok)
{
- DBUG_PRINT("error",("verify error: num: %d : '%s'\n",err,
+ int err, depth;
+ err= X509_STORE_CTX_get_error(ctx);
+ depth= X509_STORE_CTX_get_error_depth(ctx);
+
+ DBUG_PRINT("error",("verify error: %d, '%s'",err,
X509_verify_cert_error_string(err)));
+ /*
+ Approve cert if depth is greater then "verify_depth", currently
+ verify_depth is always 0 and there is no way to increase it.
+ */
if (verify_depth >= depth)
- {
- ok=1;
- verify_error=X509_V_OK;
- }
- else
- {
- verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
- }
+ ok= 1;
}
- switch (ctx->error) {
+ switch (ctx->error)
+ {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
- DBUG_PRINT("info",("issuer= %s\n",buf));
+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
+ DBUG_PRINT("info",("issuer= %s\n", buf));
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
@@ -198,193 +198,156 @@ static void netware_ssl_init()
#endif /* __NETWARE__ */
-/************************ VioSSLConnectorFd **********************************/
-/*
- TODO:
- Add option --verify to mysql to be able to change verification mode
-*/
-
-struct st_VioSSLConnectorFd *
-new_VioSSLConnectorFd(const char* key_file,
- const char* cert_file,
- const char* ca_file,
- const char* ca_path,
- const char* cipher)
+static void check_ssl_init()
{
- int verify = SSL_VERIFY_NONE;
- struct st_VioSSLConnectorFd* ptr;
- int result;
- DH *dh;
- DBUG_ENTER("new_VioSSLConnectorFd");
-
- if (!(ptr=((struct st_VioSSLConnectorFd*)
- my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0)))))
- DBUG_RETURN(0);
-
- ptr->ssl_context= 0;
- ptr->ssl_method= 0;
- /* FIXME: constants! */
-
if (!ssl_algorithms_added)
{
- DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
- ssl_algorithms_added = TRUE;
+ ssl_algorithms_added= TRUE;
SSL_library_init();
OpenSSL_add_all_algorithms();
+
}
+
#ifdef __NETWARE__
netware_ssl_init();
#endif
if (!ssl_error_strings_loaded)
{
- DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
- ssl_error_strings_loaded = TRUE;
+ ssl_error_strings_loaded= TRUE;
SSL_load_error_strings();
}
- ptr->ssl_method = TLSv1_client_method();
- ptr->ssl_context = SSL_CTX_new(ptr->ssl_method);
- DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context));
- if (ptr->ssl_context == 0)
+}
+
+/************************ VioSSLFd **********************************/
+static struct st_VioSSLFd *
+new_VioSSLFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher, SSL_METHOD *method)
+{
+ DH *dh;
+ struct st_VioSSLFd *ssl_fd;
+ DBUG_ENTER("new_VioSSLFd");
+
+ check_ssl_init();
+
+ if (!(ssl_fd= ((struct st_VioSSLFd*)
+ my_malloc(sizeof(struct st_VioSSLFd),MYF(0)))))
+ DBUG_RETURN(0);
+
+ if (!(ssl_fd->ssl_context= SSL_CTX_new(method)))
{
DBUG_PRINT("error", ("SSL_CTX_new failed"));
report_errors();
- goto ctor_failure;
- }
- /*
- SSL_CTX_set_options
- SSL_CTX_set_info_callback
- */
- if (cipher)
- {
- result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
- DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
}
- SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
- if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
+
+ /* Set the ciphers that can be used */
+ if (cipher && SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher))
{
- DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
+ DBUG_PRINT("error", ("failed to set ciphers to use"));
report_errors();
- goto ctor_failure;
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
}
- if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0)
+
+ /* Load certs from the trusted ca */
+ if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0)
{
DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
- if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0)
+ if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0)
{
DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
report_errors();
- goto ctor_failure;
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
}
- }
+ }
+
+ if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file))
+ {
+ DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
+ report_errors();
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
+ }
/* DH stuff */
dh=get_dh512();
- SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
+ SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh);
DH_free(dh);
- DBUG_RETURN(ptr);
-ctor_failure:
- DBUG_PRINT("exit", ("there was an error"));
- my_free((gptr)ptr,MYF(0));
- DBUG_RETURN(0);
+ DBUG_PRINT("exit", ("OK 1"));
+
+ DBUG_RETURN(ssl_fd);
}
-/************************ VioSSLAcceptorFd **********************************/
-/*
- TODO:
- Add option --verify to mysqld to be able to change verification mode
-*/
-struct st_VioSSLAcceptorFd*
-new_VioSSLAcceptorFd(const char *key_file,
- const char *cert_file,
- const char *ca_file,
- const char *ca_path,
- const char *cipher)
+/************************ VioSSLConnectorFd **********************************/
+struct st_VioSSLFd *
+new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher)
{
- int verify = (SSL_VERIFY_PEER |
- SSL_VERIFY_CLIENT_ONCE);
- struct st_VioSSLAcceptorFd* ptr;
- int result;
- DH *dh;
- DBUG_ENTER("new_VioSSLAcceptorFd");
+ struct st_VioSSLFd *ssl_fd;
+ int verify= SSL_VERIFY_PEER;
+ if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
+ ca_path, cipher, TLSv1_client_method())))
+ {
+ return 0;
+ }
- ptr= ((struct st_VioSSLAcceptorFd*)
- my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0)));
- ptr->ssl_context=0;
- ptr->ssl_method=0;
- /* FIXME: constants! */
- ptr->session_id_context= ptr;
+ /* Init the VioSSLFd as a "connector" ie. the client side */
- if (!ssl_algorithms_added)
- {
- DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
- ssl_algorithms_added = TRUE;
- SSL_library_init();
- OpenSSL_add_all_algorithms();
+ /*
+ The verify_callback function is used to control the behaviour
+ when the SSL_VERIFY_PEER flag is set.
+ */
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
- }
-#ifdef __NETWARE__
- netware_ssl_init();
-#endif
+ return ssl_fd;
+}
- if (!ssl_error_strings_loaded)
- {
- DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
- ssl_error_strings_loaded = TRUE;
- SSL_load_error_strings();
- }
- ptr->ssl_method= TLSv1_server_method();
- ptr->ssl_context= SSL_CTX_new(ptr->ssl_method);
- if (ptr->ssl_context == 0)
- {
- DBUG_PRINT("error", ("SSL_CTX_new failed"));
- report_errors();
- goto ctor_failure;
- }
- if (cipher)
+
+/************************ VioSSLAcceptorFd **********************************/
+struct st_VioSSLFd *
+new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher)
+{
+ struct st_VioSSLFd *ssl_fd;
+ int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+ if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
+ ca_path, cipher, TLSv1_server_method())))
{
- result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
- DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
+ return 0;
}
- /* SSL_CTX_set_quiet_shutdown(ctx,1); */
- SSL_CTX_sess_set_cache_size(ptr->ssl_context,128);
+ /* Init the the VioSSLFd as a "acceptor" ie. the server side */
- /* DH? */
- SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
- SSL_CTX_set_session_id_context(ptr->ssl_context,
- (const uchar*) &(ptr->session_id_context),
- sizeof(ptr->session_id_context));
+ /* Set max number of cached sessions, returns the previous size */
+ SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128);
/*
- SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
+ The verify_callback function is used to control the behaviour
+ when the SSL_VERIFY_PEER flag is set.
*/
- if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
- {
- DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
- report_errors();
- goto ctor_failure;
- }
- if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0)
- {
- DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
- if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0)
- {
- DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
- report_errors();
- goto ctor_failure;
- }
- }
- /* DH stuff */
- dh=get_dh512();
- SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
- DH_free(dh);
- DBUG_RETURN(ptr);
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
-ctor_failure:
- DBUG_PRINT("exit", ("there was an error"));
- my_free((gptr) ptr,MYF(0));
- DBUG_RETURN(0);
+ /*
+ Set session_id - an identifier for this server session
+ Use the ssl_fd pointer
+ */
+ SSL_CTX_set_session_id_context(ssl_fd->ssl_context,
+ (const unsigned char *)ssl_fd,
+ sizeof(ssl_fd));
+
+ return ssl_fd;
+}
+
+void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd)
+{
+ SSL_CTX_free(fd->ssl_context);
+ my_free((gptr) fd, MYF(0));
}
#endif /* HAVE_OPENSSL */
diff --git a/zlib/cmakelists.txt b/zlib/CMakeLists.txt
index 53560adf6d1..53560adf6d1 100644
--- a/zlib/cmakelists.txt
+++ b/zlib/CMakeLists.txt
diff --git a/zlib/Makefile.am b/zlib/Makefile.am
index cc3777b1e88..40258ec589a 100644
--- a/zlib/Makefile.am
+++ b/zlib/Makefile.am
@@ -29,4 +29,4 @@ libz_la_SOURCES= adler32.c compress.c crc32.c deflate.c gzio.c \
infback.c inffast.c inflate.c inftrees.c trees.c \
uncompr.c zutil.c
-EXTRA_DIST= README FAQ INDEX ChangeLog algorithm.txt zlib.3 cmakelists.txt
+EXTRA_DIST= README FAQ INDEX ChangeLog algorithm.txt zlib.3 CMakeLists.txt