summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore22
-rwxr-xr-xBUILD/compile-dist2
-rw-r--r--VC++Files/client/mysql.dsp4
-rw-r--r--VC++Files/client/mysql_ia64.dsp4
-rw-r--r--client/mysql.cc1
-rw-r--r--client/mysqldump.c920
-rw-r--r--configure.in6
-rw-r--r--extra/yassl/README16
-rw-r--r--extra/yassl/include/openssl/engine.h5
-rw-r--r--extra/yassl/include/openssl/pkcs12.h5
-rw-r--r--extra/yassl/src/handshake.cpp38
-rw-r--r--extra/yassl/src/socket_wrapper.cpp13
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp3
-rw-r--r--include/Makefile.am2
-rw-r--r--include/config-win.h1
-rw-r--r--include/my_global.h4
-rw-r--r--include/my_libwrap.h28
-rw-r--r--innobase/row/row0mysql.c20
-rw-r--r--innobase/row/row0sel.c3
-rw-r--r--myisam/mi_check.c34
-rw-r--r--myisam/mi_key.c14
-rw-r--r--myisam/mi_update.c3
-rw-r--r--myisam/mi_write.c3
-rw-r--r--myisam/myisamdef.h2
-rw-r--r--mysql-test/lib/mtr_process.pl17
-rwxr-xr-xmysql-test/mysql-test-run.pl117
-rw-r--r--mysql-test/r/archive.result2
-rw-r--r--mysql-test/r/auto_increment.result22
-rw-r--r--mysql-test/r/bdb.result34
-rw-r--r--mysql-test/r/create_not_windows.result14
-rw-r--r--mysql-test/r/ctype_sjis.result4
-rw-r--r--mysql-test/r/ctype_utf8.result40
-rw-r--r--mysql-test/r/delayed.result30
-rw-r--r--mysql-test/r/fulltext_left_join.result17
-rw-r--r--mysql-test/r/func_concat.result14
-rw-r--r--mysql-test/r/func_group.result35
-rw-r--r--mysql-test/r/func_str.result15
-rw-r--r--mysql-test/r/func_time.result64
-rw-r--r--mysql-test/r/func_timestamp.result2
-rw-r--r--mysql-test/r/im_daemon_life_cycle.result1
-rw-r--r--mysql-test/r/im_life_cycle.result76
-rw-r--r--mysql-test/r/im_utils.result3
-rw-r--r--mysql-test/r/information_schema.result45
-rw-r--r--mysql-test/r/insert.result26
-rw-r--r--mysql-test/r/insert_select.result9
-rw-r--r--mysql-test/r/join.result20
-rw-r--r--mysql-test/r/key.result10
-rw-r--r--mysql-test/r/lock_multi.result14
-rw-r--r--mysql-test/r/lowercase_table2.result9
-rw-r--r--mysql-test/r/merge.result6
-rw-r--r--mysql-test/r/multi_update.result5
-rw-r--r--mysql-test/r/myisam.result21
-rw-r--r--mysql-test/r/mysqldump.result100
-rw-r--r--mysql-test/r/ndb_condition_pushdown.result24
-rw-r--r--mysql-test/r/ndb_loaddatalocal.result46
-rw-r--r--mysql-test/r/ndb_lock.result80
-rw-r--r--mysql-test/r/ndb_replace.result23
-rw-r--r--mysql-test/r/ndb_truncate.result23
-rw-r--r--mysql-test/r/replace.result6
-rw-r--r--mysql-test/r/rpl_auto_increment_11932.result47
-rw-r--r--mysql-test/r/rpl_log.result17
-rw-r--r--mysql-test/r/select.result139
-rw-r--r--mysql-test/r/sp-prelocking.result18
-rw-r--r--mysql-test/r/sp.result21
-rw-r--r--mysql-test/r/sql_mode.result4
-rw-r--r--mysql-test/r/sysdate_is_now.result2
-rw-r--r--mysql-test/r/trigger.result32
-rw-r--r--mysql-test/r/type_newdecimal.result11
-rw-r--r--mysql-test/r/type_timestamp.result2
-rw-r--r--mysql-test/r/udf.result18
-rw-r--r--mysql-test/r/union.result45
-rw-r--r--mysql-test/r/view_grant.result41
-rw-r--r--mysql-test/t/archive.test2
-rw-r--r--mysql-test/t/auto_increment.test17
-rw-r--r--mysql-test/t/bdb.test35
-rw-r--r--mysql-test/t/create_not_windows.test20
-rw-r--r--mysql-test/t/ctype_sjis.test2
-rw-r--r--mysql-test/t/ctype_utf8.test26
-rw-r--r--mysql-test/t/delayed.test49
-rw-r--r--mysql-test/t/fulltext_left_join.test15
-rw-r--r--mysql-test/t/func_concat.test15
-rw-r--r--mysql-test/t/func_group.test28
-rw-r--r--mysql-test/t/func_str.test12
-rw-r--r--mysql-test/t/func_time.test37
-rw-r--r--mysql-test/t/func_timestamp.test6
-rw-r--r--mysql-test/t/im_daemon_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_daemon_life_cycle.imtest18
-rw-r--r--mysql-test/t/im_life_cycle-im.opt1
-rw-r--r--mysql-test/t/im_life_cycle.imtest138
-rw-r--r--mysql-test/t/im_utils-im.opt1
-rw-r--r--mysql-test/t/im_utils.imtest16
-rw-r--r--mysql-test/t/information_schema.test46
-rw-r--r--mysql-test/t/innodb.test13
-rw-r--r--mysql-test/t/insert.test23
-rw-r--r--mysql-test/t/insert_select.test22
-rw-r--r--mysql-test/t/join.test25
-rw-r--r--mysql-test/t/key.test11
-rwxr-xr-xmysql-test/t/kill_n_check.sh109
-rw-r--r--mysql-test/t/lock_multi.test59
-rw-r--r--mysql-test/t/lowercase_table2.test11
-rw-r--r--mysql-test/t/merge.test9
-rw-r--r--mysql-test/t/multi_update.test8
-rw-r--r--mysql-test/t/myisam.test22
-rw-r--r--mysql-test/t/mysqldump.test50
-rw-r--r--mysql-test/t/ndb_condition_pushdown.test22
-rw-r--r--mysql-test/t/ndb_loaddatalocal.test70
-rw-r--r--mysql-test/t/ndb_lock.test113
-rw-r--r--mysql-test/t/ndb_replace.test30
-rw-r--r--mysql-test/t/ndb_truncate.test23
-rw-r--r--mysql-test/t/replace.test10
-rw-r--r--mysql-test/t/rpl_auto_increment_11932.test63
-rw-r--r--mysql-test/t/rpl_log.test14
-rw-r--r--mysql-test/t/select.test146
-rw-r--r--mysql-test/t/sp-prelocking.test31
-rw-r--r--mysql-test/t/sp.test27
-rw-r--r--mysql-test/t/sql_mode.test3
-rw-r--r--mysql-test/t/trigger.test40
-rw-r--r--mysql-test/t/type_newdecimal.test9
-rw-r--r--mysql-test/t/type_timestamp.test6
-rw-r--r--mysql-test/t/udf.test12
-rw-r--r--mysql-test/t/union.test48
-rw-r--r--mysql-test/t/view_grant.test59
-rwxr-xr-xmysql-test/t/wait_for_process.sh66
-rw-r--r--mysql-test/t/wait_timeout.test1
-rw-r--r--mysql-test/valgrind.supp27
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/mf_dirname.c4
-rw-r--r--mysys/mf_fn_ext.c6
-rw-r--r--mysys/my_lib.c2
-rw-r--r--mysys/my_libwrap.c42
-rw-r--r--ndb/Makefile.am3
-rw-r--r--ndb/include/kernel/GlobalSignalNumbers.h10
-rw-r--r--ndb/include/kernel/signaldata/AlterTable.hpp1
-rw-r--r--ndb/include/kernel/signaldata/CreateTable.hpp1
-rw-r--r--ndb/include/kernel/signaldata/DictLock.hpp78
-rw-r--r--ndb/include/kernel/signaldata/DropTable.hpp1
-rw-r--r--ndb/include/mgmapi/mgmapi.h57
-rw-r--r--ndb/include/ndb_version.h.in2
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp50
-rw-r--r--ndb/include/ndbapi/NdbIndexScanOperation.hpp7
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp37
-rw-r--r--ndb/include/util/ConfigValues.hpp1
-rw-r--r--ndb/src/common/debugger/SignalLoggerManager.cpp2
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp6
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp2
-rw-r--r--ndb/src/common/util/ConfigValues.cpp8
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt6
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp5
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp314
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp98
-rw-r--r--ndb/src/kernel/blocks/dbdict/DictLock.txt94
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp28
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihInit.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp179
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp3
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp4
-rw-r--r--ndb/src/kernel/error/ndbd_exit_codes.c7
-rw-r--r--ndb/src/kernel/main.cpp4
-rw-r--r--ndb/src/kernel/vm/DLFifoList.hpp14
-rw-r--r--ndb/src/kernel/vm/pc.hpp2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp242
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp239
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp9
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp208
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp24
-rw-r--r--ndb/src/mgmsrv/Services.cpp111
-rw-r--r--ndb/src/mgmsrv/Services.hpp9
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp56
-rw-r--r--ndb/src/ndbapi/NdbBlobImpl.hpp6
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp2
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp1
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp22
-rw-r--r--ndb/src/ndbapi/ndberror.c9
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp131
-rw-r--r--ndb/test/ndbapi/testDict.cpp321
-rwxr-xr-xnetware/BUILD/compile-netware-END5
-rw-r--r--netware/Makefile.am4
-rw-r--r--netware/mysql_install.def10
-rw-r--r--regex/regexec.c2
-rw-r--r--scripts/make_win_src_distribution.sh64
-rw-r--r--server-tools/instance-manager/guardian.cc3
-rw-r--r--server-tools/instance-manager/instance_map.cc2
-rw-r--r--server-tools/instance-manager/instance_options.cc9
-rw-r--r--server-tools/instance-manager/manager.cc43
-rw-r--r--sql/field.cc126
-rw-r--r--sql/field.h11
-rw-r--r--sql/ha_archive.cc2
-rw-r--r--sql/ha_innodb.cc11
-rw-r--r--sql/ha_myisammrg.h3
-rw-r--r--sql/ha_ndbcluster.cc159
-rw-r--r--sql/ha_ndbcluster.h5
-rw-r--r--sql/item.h16
-rw-r--r--sql/item_buff.cc2
-rw-r--r--sql/item_cmpfunc.cc147
-rw-r--r--sql/item_cmpfunc.h7
-rw-r--r--sql/item_func.cc4
-rw-r--r--sql/item_strfunc.cc35
-rw-r--r--sql/item_strfunc.h1
-rw-r--r--sql/item_timefunc.cc66
-rw-r--r--sql/item_timefunc.h13
-rw-r--r--sql/log.cc22
-rw-r--r--sql/log_event.cc27
-rw-r--r--sql/log_event.h21
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc26
-rw-r--r--sql/net_serv.cc4
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/opt_sum.cc21
-rw-r--r--sql/slave.cc20
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sql_base.cc24
-rw-r--r--sql/sql_class.cc13
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_db.cc60
-rw-r--r--sql/sql_insert.cc51
-rw-r--r--sql/sql_lex.cc31
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc98
-rw-r--r--sql/sql_select.cc16
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc26
-rw-r--r--sql/sql_udf.h2
-rw-r--r--sql/sql_update.cc9
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/structs.h8
-rw-r--r--sql/table.cc21
-rw-r--r--strings/ctype-mb.c20
-rw-r--r--support-files/mysql.server.sh19
-rw-r--r--support-files/mysql.spec.sh17
-rw-r--r--tests/mysql_client_test.c21
231 files changed, 6303 insertions, 1720 deletions
diff --git a/.bzrignore b/.bzrignore
index 80ed7872005..ef02a085144 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -276,6 +276,7 @@ bkpush.log
bkpush.log*
build.log
build_tags.sh
+client/#mysql.cc#
client/*.ds?
client/*.vcproj
client/completion_hash.cpp
@@ -290,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
@@ -365,6 +367,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
@@ -382,6 +387,7 @@ include/my_global.h
include/mysql_version.h
include/mysqld_ername.h
include/mysqld_error.h
+include/openssl
include/readline
include/readline/*.h
include/readline/readline.h
@@ -672,6 +678,7 @@ mysql-test/r/bdb-alter-table-2.err
mysql-test/r/bdb-crash.err
mysql-test/r/bdb-deadlock.err
mysql-test/r/bdb.err
+mysql-test/r/bdb.log
mysql-test/r/bdb_cache.err
mysql-test/r/client_test.err
mysql-test/r/csv.err
@@ -679,6 +686,7 @@ mysql-test/r/ctype_ucs.err
mysql-test/r/derived.err
mysql-test/r/exampledb.err
mysql-test/r/func_encrypt.err
+mysql-test/r/im_client_port.log
mysql-test/r/index_merge_load.result
mysql-test/r/isam.err
mysql-test/r/lowercase_table2.err
@@ -727,6 +735,7 @@ mysql-test/r/rpl000016.eval
mysql-test/r/rpl_log.eval
mysql-test/r/slave-running.eval
mysql-test/r/slave-stopped.eval
+mysql-test/r/udf.log
mysql-test/share/mysql
mysql-test/std_data/*.pem
mysql-test/t/index_merge.load
@@ -1051,6 +1060,7 @@ scripts/mysql_install_db
scripts/mysql_secure_installation
scripts/mysql_setpermission
scripts/mysql_tableinfo
+scripts/mysql_upgrade
scripts/mysql_zap
scripts/mysqlaccess
scripts/mysqlbug
@@ -1142,7 +1152,9 @@ sql/pack.c
sql/safe_to_cache_query.txt
sql/share/*.sys
sql/share/charsets/gmon.out
+sql/share/fixerrmsg.pl
sql/share/gmon.out
+sql/share/iso639-2.txt
sql/share/mysql
sql/share/norwegian-ny/errmsg.sys
sql/share/norwegian/errmsg.sys
@@ -1273,12 +1285,4 @@ vio/viotest-sslconnect.cpp
vio/viotest.cpp
zlib/*.ds?
zlib/*.vcproj
-scripts/mysql_upgrade
-include/openssl
-mysql-test/r/bdb.log
-mysql-test/r/im_client_port.log
-mysql-test/r/udf.log
-extra/yassl/taocrypt/benchmark/benchmark
-extra/yassl/taocrypt/test/test
-extra/yassl/testsuite/testsuite
-client/mysql_upgrade
+BitKeeper/etc/RESYNC_TREE
diff --git a/BUILD/compile-dist b/BUILD/compile-dist
index 39095f59ffa..613f2643c56 100755
--- a/BUILD/compile-dist
+++ b/BUILD/compile-dist
@@ -6,7 +6,7 @@
# tree can then be picked up by "make dist" to create the "pristine source
# package" that is used as the basis for all other binary builds.
#
-make distclean
+test -f Makefile && make distclean
aclocal
autoheader
libtoolize --automake --force --copy
diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp
index ac74515b588..510107c8308 100644
--- a/VC++Files/client/mysql.dsp
+++ b/VC++Files/client/mysql.dsp
@@ -144,6 +144,10 @@ SOURCE=.\readline.cpp
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_conio.c
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_string.cpp
# End Source File
# End Target
diff --git a/VC++Files/client/mysql_ia64.dsp b/VC++Files/client/mysql_ia64.dsp
index 3fe2e2a2328..8de283d1e0b 100644
--- a/VC++Files/client/mysql_ia64.dsp
+++ b/VC++Files/client/mysql_ia64.dsp
@@ -130,6 +130,10 @@ SOURCE=.\readline.cpp
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_conio.c
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_string.cpp
# End Source File
# End Target
diff --git a/client/mysql.cc b/client/mysql.cc
index 900df825b25..6fcda6d766f 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -823,6 +823,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_NOPAGER:
printf("WARNING: option deprecated; use --disable-pager instead.\n");
opt_nopager= 1;
+ break;
case OPT_MYSQL_PROTOCOL:
{
if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
diff --git a/client/mysqldump.c b/client/mysqldump.c
index c0a3c55746e..53cb06be6f3 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -21,7 +21,7 @@
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
** DATE: December 3, 1994
** WARRANTY: None, expressed, impressed, implied
-** or other
+** or other
** STATUS: Public domain
** Adapted and optimized for MySQL by
** Michael Widenius, Sinisa Milivojevic, Jani Tolonen
@@ -77,22 +77,22 @@
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
static char *add_load_option(char *ptr, const char *object,
- const char *statement);
+ const char *statement);
static ulong find_set(TYPELIB *lib, const char *x, uint length,
- char **err_pos, uint *err_len);
+ char **err_pos, uint *err_len);
static char *alloc_query_str(ulong size);
static char *field_escape(char *to,const char *from,uint length);
static my_bool verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
- lock_tables=1,ignore_errors=0,flush_logs=0,
- opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
+ lock_tables=1,ignore_errors=0,flush_logs=0,
+ opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
opt_set_charset=0,
- opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
- opt_delete_master_logs=0, tty_password=0,
- opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
- opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
+ opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
+ opt_delete_master_logs=0, tty_password=0,
+ opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
+ opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
opt_complete_insert= 0, opt_drop_database= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
@@ -129,8 +129,8 @@ static const char *mysql_universal_client_charset=
static char *default_charset;
static CHARSET_INFO *charset_info= &my_charset_latin1;
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
-/* do we met VIEWs during tables scaning */
-my_bool was_views= 0;
+/* have we seen any VIEWs during table scanning? */
+my_bool seen_views= 0;
const char *compatible_mode_names[]=
{
@@ -149,7 +149,7 @@ const char *compatible_mode_names[]=
(1<<10) /* ANSI */\
)
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
- "", compatible_mode_names, NULL};
+ "", compatible_mode_names, NULL};
HASH ignore_table;
@@ -276,7 +276,7 @@ static struct my_option my_long_options[] =
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
(gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"lock-all-tables", 'x', "Locks all tables across all databases. This "
+ {"lock-all-tables", 'x', "Locks all tables across all databases. This "
"is achieved by taking a global read lock for the duration of the whole "
"dump. Automatically turns --single-transaction and --lock-tables off.",
(gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
@@ -297,7 +297,7 @@ static struct my_option my_long_options[] =
GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
(gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
- GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
+ GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
(longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
(gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
@@ -411,8 +411,8 @@ static const char *load_default_groups[]= { "mysqldump","client",0 };
static void safe_exit(int error);
static void write_header(FILE *sql_file, char *db_name);
static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
- const char *prefix,const char *name,
- int string_value);
+ const char *prefix,const char *name,
+ int string_value);
static int dump_selected_tables(char *db, char **table_names, int tables);
static int dump_all_tables_in_db(char *db);
static int init_dumping(char *);
@@ -428,10 +428,10 @@ static my_bool dump_all_views_in_db(char *database);
/*
exit with message if ferror(file)
-
+
SYNOPSIS
check_io()
- file - checked file
+ file - checked file
*/
void check_io(FILE *file)
@@ -456,7 +456,7 @@ static void short_usage_sub(void)
{
printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
- my_progname);
+ my_progname);
printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
NETWARE_SET_SCREEN_MODE(1);
}
@@ -501,12 +501,12 @@ static void write_header(FILE *sql_file, char *db_name)
{
fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
fprintf(sql_file, "-- Host: %s Database: %s\n",
- current_host ? current_host : "localhost", db_name ? db_name :
- "");
+ current_host ? current_host : "localhost", db_name ? db_name :
+ "");
fputs("-- ------------------------------------------------------\n",
- sql_file);
+ sql_file);
fprintf(sql_file, "-- Server version\t%s\n",
- mysql_get_server_info(&mysql_connection));
+ mysql_get_server_info(&mysql_connection));
}
if (opt_set_charset)
fprintf(sql_file,
@@ -529,10 +529,10 @@ static void write_header(FILE *sql_file, char *db_name)
");
}
fprintf(sql_file,
- "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n"
- "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n",
- path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
- compatible_mode_normal_str);
+ "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n"
+ "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n",
+ path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
+ compatible_mode_normal_str);
check_io(sql_file);
}
} /* write_header */
@@ -563,7 +563,7 @@ static void write_footer(FILE *sql_file)
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
fprintf(sql_file,
- "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
+ "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
fputs("\n", sql_file);
check_io(sql_file);
}
@@ -577,7 +577,7 @@ static void free_table_ent(char *key)
byte* get_table_key(const char *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+ my_bool not_used __attribute__((unused)))
{
*length= strlen(entry);
return (byte*) entry;
@@ -594,7 +594,7 @@ void init_table_rule_hash(HASH* h)
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
+ char *argument)
{
switch (optid) {
#ifdef __NETWARE__
@@ -608,9 +608,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *start=argument;
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
opt_password=my_strdup(argument,MYF(MY_FAE));
- while (*argument) *argument++= 'x'; /* Destroy argument */
+ while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
- start[1]=0; /* Cut length of argument */
+ start[1]=0; /* Cut length of argument */
tty_password= 0;
}
else
@@ -618,7 +618,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'r':
if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY,
- MYF(MY_WME))))
+ MYF(MY_WME))))
exit(1);
break;
case 'W':
@@ -639,7 +639,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'V': print_version(); exit(0);
case 'X':
opt_xml = 1;
- extended_insert= opt_drop= opt_lock=
+ extended_insert= opt_drop= opt_lock=
opt_disable_keys= opt_autocommit= opt_create_db= 0;
break;
case 'I':
@@ -692,36 +692,36 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_set_charset= 0;
opt_compatible_mode_str= argument;
opt_compatible_mode= find_set(&compatible_mode_typelib,
- argument, strlen(argument),
- &err_ptr, &err_len);
+ argument, strlen(argument),
+ &err_ptr, &err_len);
if (err_len)
{
- strmake(buff, err_ptr, min(sizeof(buff), err_len));
- fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
- exit(1);
+ strmake(buff, err_ptr, min(sizeof(buff), err_len));
+ fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
+ exit(1);
}
#if !defined(DBUG_OFF)
{
- uint size_for_sql_mode= 0;
- const char **ptr;
- for (ptr= compatible_mode_names; *ptr; ptr++)
- size_for_sql_mode+= strlen(*ptr);
- size_for_sql_mode+= sizeof(compatible_mode_names)-1;
- DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
+ uint size_for_sql_mode= 0;
+ const char **ptr;
+ for (ptr= compatible_mode_names; *ptr; ptr++)
+ size_for_sql_mode+= strlen(*ptr);
+ size_for_sql_mode+= sizeof(compatible_mode_names)-1;
+ DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
}
#endif
mode= opt_compatible_mode;
for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
{
- if (mode & 1)
- {
- end= strmov(end, compatible_mode_names[i]);
- end= strmov(end, ",");
- }
+ if (mode & 1)
+ {
+ end= strmov(end, compatible_mode_names[i]);
+ end= strmov(end, ",");
+ }
}
if (end!=compatible_mode_normal_str)
- end[-1]= 0;
- /*
+ end[-1]= 0;
+ /*
Set charset to the default compiled value if it hasn't
been reset yet by --default-character-set=xxx.
*/
@@ -733,8 +733,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
{
- fprintf(stderr, "Unknown option to protocol: %s\n", argument);
- exit(1);
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
}
break;
}
@@ -760,12 +760,12 @@ static int get_options(int *argc, char ***argv)
*mysql_params->p_net_buffer_length= opt_net_buffer_length;
if (opt_delayed)
- opt_lock=0; /* Can't have lock with delayed */
+ opt_lock=0; /* Can't have lock with delayed */
if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
- fields_terminated))
+ fields_terminated))
{
fprintf(stderr,
- "%s: You must use option --tab with --fields-...\n", my_progname);
+ "%s: You must use option --tab with --fields-...\n", my_progname);
return(1);
}
@@ -777,7 +777,7 @@ static int get_options(int *argc, char ***argv)
fprintf(stderr, "%s: You can't use --single-transaction and "
"--lock-all-tables at the same time.\n", my_progname);
return(1);
- }
+ }
if (opt_master_data)
opt_lock_all_tables= !opt_single_transaction;
if (opt_single_transaction || opt_lock_all_tables)
@@ -790,13 +790,13 @@ static int get_options(int *argc, char ***argv)
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
- "%s: --databases or --all-databases can't be used with --tab.\n",
- my_progname);
+ "%s: --databases or --all-databases can't be used with --tab.\n",
+ my_progname);
return(1);
}
if (strcmp(default_charset, charset_info->csname) &&
- !(charset_info= get_charset_by_csname(default_charset,
- MY_CS_PRIMARY, MYF(MY_WME))))
+ !(charset_info= get_charset_by_csname(default_charset,
+ MY_CS_PRIMARY, MYF(MY_WME))))
exit(1);
if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
{
@@ -816,7 +816,7 @@ static void DB_error(MYSQL *mysql, const char *when)
{
DBUG_ENTER("DB_error");
my_printf_error(0,"Got error: %d: %s %s", MYF(0),
- mysql_errno(mysql), mysql_error(mysql), when);
+ mysql_errno(mysql), mysql_error(mysql), when);
safe_exit(EX_MYSQLERR);
DBUG_VOID_RETURN;
} /* DB_error */
@@ -830,14 +830,14 @@ static void DB_error(MYSQL *mysql, const char *when)
mysql_query_with_error_report()
mysql_con connection to use
res if non zero, result will be put there with
- mysql_store_result()
+ mysql_store_result()
query query to send to server
RETURN VALUES
0 query sending and (if res!=0) result reading went ok
1 error
*/
-
+
static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
const char *query)
{
@@ -869,7 +869,7 @@ static FILE* open_sql_file_for_table(const char* table)
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
convert_dirname(tmp_path,path,NullS);
res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
- O_WRONLY, MYF(MY_WME));
+ O_WRONLY, MYF(MY_WME));
return res;
}
@@ -904,7 +904,7 @@ static int dbConnect(char *host, char *user,char *passwd)
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath, opt_ssl_cipher);
+ opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif
@@ -933,7 +933,7 @@ static int dbConnect(char *host, char *user,char *passwd)
*/
sock->reconnect= 0;
my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
- compatible_mode_normal_str);
+ compatible_mode_normal_str);
if (mysql_query_with_error_report(sock, 0, buff))
{
mysql_close(sock);
@@ -941,7 +941,7 @@ static int dbConnect(char *host, char *user,char *passwd)
return 1;
}
/*
- set time_zone to UTC to allow dumping date types between servers with
+ set time_zone to UTC to allow dumping date types between servers with
different time zone settings
*/
if (opt_tz_utc)
@@ -975,8 +975,8 @@ static void unescape(FILE *file,char *pos,uint length)
DBUG_ENTER("unescape");
if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
{
- ignore_errors=0; /* Fatal error */
- safe_exit(EX_MYSQLERR); /* Force exit */
+ ignore_errors=0; /* Fatal error */
+ safe_exit(EX_MYSQLERR); /* Force exit */
}
mysql_real_escape_string(&mysql_connection, tmp, pos, length);
fputc('\'', file);
@@ -1003,13 +1003,13 @@ static my_bool test_if_special_chars(const char *str)
/*
quote_name(name, buff, force)
- Quotes char string, taking into account compatible mode
+ Quotes char string, taking into account compatible mode
Args
name Unquoted string containing that which will be quoted
buff The buffer that contains the quoted value, also returned
- force Flag to make it ignore 'test_if_special_chars'
+ force Flag to make it ignore 'test_if_special_chars'
Returns
@@ -1082,13 +1082,13 @@ static char *quote_for_like(const char *name, char *buff)
/*
Quote and print a string.
-
+
SYNOPSIS
print_quoted_xml()
- output - output file
- str - string to print
- len - its length
-
+ output - output file
+ str - string to print
+ len - its length
+
DESCRIPTION
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
*/
@@ -1096,7 +1096,7 @@ static char *quote_for_like(const char *name, char *buff)
static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
{
const char *end;
-
+
for (end= str + len; str != end; str++)
{
switch (*str) {
@@ -1123,15 +1123,15 @@ static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
/*
Print xml tag with one attribute.
-
+
SYNOPSIS
print_xml_tag1()
- xml_file - output file
- sbeg - line beginning
- stag_atr - tag and attribute
- sval - value of attribute
- send - line ending
-
+ xml_file - output file
+ sbeg - line beginning
+ stag_atr - tag and attribute
+ sval - value of attribute
+ send - line ending
+
DESCRIPTION
Print tag with one attribute to the xml_file. Format is:
sbeg<stag_atr="sval">send
@@ -1141,8 +1141,8 @@ static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
*/
static void print_xml_tag1(FILE * xml_file, const char* sbeg,
- const char* stag_atr, const char* sval,
- const char* send)
+ const char* stag_atr, const char* sval,
+ const char* send)
{
fputs(sbeg, xml_file);
fputs("<", xml_file);
@@ -1160,11 +1160,11 @@ static void print_xml_tag1(FILE * xml_file, const char* sbeg,
SYNOPSIS
print_xml_null_tag()
- xml_file - output file
- sbeg - line beginning
- stag_atr - tag and attribute
- sval - value of attribute
- send - line ending
+ xml_file - output file
+ sbeg - line beginning
+ stag_atr - tag and attribute
+ sval - value of attribute
+ send - line ending
DESCRIPTION
Print tag with one attribute to the xml_file. Format is:
@@ -1194,11 +1194,11 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
SYNOPSIS
print_xml_row()
- xml_file - output file
- row_name - xml tag name
- tableRes - query result
- row - result row
-
+ xml_file - output file
+ row_name - xml tag name
+ tableRes - query result
+ row - result row
+
DESCRIPTION
Print tag with many attribute to the xml_file. Format is:
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
@@ -1207,7 +1207,7 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
*/
static void print_xml_row(FILE *xml_file, const char *row_name,
- MYSQL_RES *tableRes, MYSQL_ROW *row)
+ MYSQL_RES *tableRes, MYSQL_ROW *row)
{
uint i;
MYSQL_FIELD *field;
@@ -1324,7 +1324,7 @@ static uint dump_routines_for_db(char *db)
*/
definer_begin= strstr(row[2], " DEFINER");
-
+
if (definer_begin)
{
char *definer_end= strstr(definer_begin, " PROCEDURE");
@@ -1388,7 +1388,7 @@ static uint dump_routines_for_db(char *db)
ARGS
table - table name
db - db name
- table_type - table type ie "InnoDB"
+ table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
RETURN
@@ -1400,10 +1400,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
my_bool init=0, delayed, write_data, complete_insert;
my_ulonglong num_fields;
- char *result_table, *opt_quoted_table;
+ char *result_table, *opt_quoted_table;
const char *insert_option;
- char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
- char table_buff2[NAME_LEN*2+3], query_buff[512];
+ char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
+ char table_buff2[NAME_LEN*2+3], query_buff[512];
FILE *sql_file = md_result_file;
int len;
MYSQL_RES *result;
@@ -1473,34 +1473,49 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (!(sql_file= open_sql_file_for_table(table)))
{
- safe_exit(EX_MYSQLERR);
- DBUG_RETURN(0);
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
}
write_header(sql_file, db);
}
if (!opt_xml && opt_comments)
{
+ if (strcmp (table_type, "VIEW") == 0) /* view */
+ fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
+ result_table);
+ else
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
- result_table);
- check_io(sql_file);
+ result_table);
+ check_io(sql_file);
}
if (opt_drop)
{
- fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
- check_io(sql_file);
+ /*
+ Even if the "table" is a view, we do a DROP TABLE here. The
+ view-specific code below fills in the DROP VIEW.
+ */
+ fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
+ opt_quoted_table);
+ check_io(sql_file);
}
result= mysql_store_result(sock);
field= mysql_fetch_field_direct(result, 0);
if (strcmp(field->name, "View") == 0)
{
+ char *scv_buff = NULL;
+
if (verbose)
fprintf(stderr, "-- It's a view, create dummy table for view\n");
+ /* save "show create" statement for later */
+ if ((row= mysql_fetch_row(result)) && (scv_buff=row[1]))
+ scv_buff= my_strdup(scv_buff, MYF(0));
+
mysql_free_result(result);
/*
- Create a table with the same name as the view and with columns of
+ Create a table with the same name as the view and with columns of
the same name in order to satisfy views that depend on this view.
The table will be removed when the actual view is created.
@@ -1514,9 +1529,22 @@ static uint get_table_structure(char *table, char *db, char *table_type,
"SHOW FIELDS FROM %s", result_table);
if (mysql_query_with_error_report(sock, 0, query_buff))
{
+ /*
+ View references invalid or privileged table/col/fun (err 1356),
+ so we cannot create a stand-in table. Be defensive and dump
+ a comment with the view's 'show create' statement. (Bug #17371)
+ */
+
+ if (mysql_errno(sock) == ER_VIEW_INVALID)
+ fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");
+
+ my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
+
safe_exit(EX_MYSQLERR);
- DBUG_RETURN(0);
+ DBUG_RETURN(0);
}
+ else
+ my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
if ((result= mysql_store_result(sock)))
{
@@ -1524,10 +1552,13 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (opt_drop)
{
+ /*
+ We have already dropped any table of the same name
+ above, so here we just drop the view.
+ */
+
fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
opt_quoted_table);
- fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n",
- opt_quoted_table);
check_io(sql_file);
}
@@ -1554,7 +1585,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
}
mysql_free_result(result);
- was_views= 1;
+ if (path)
+ my_fclose(sql_file, MYF(MY_WME));
+
+ seen_views= 1;
DBUG_RETURN(0);
}
@@ -1564,11 +1598,11 @@ static uint get_table_structure(char *table, char *db, char *table_type,
mysql_free_result(result);
}
my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
- result_table);
+ result_table);
if (mysql_query_with_error_report(sock, &result, query_buff))
{
if (path)
- my_fclose(sql_file, MYF(MY_WME));
+ my_fclose(sql_file, MYF(MY_WME));
safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -1621,7 +1655,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_progname, mysql_error(sock));
my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
- result_table);
+ result_table);
if (mysql_query_with_error_report(sock, &result, query_buff))
{
safe_exit(EX_MYSQLERR);
@@ -1635,18 +1669,18 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (!(sql_file= open_sql_file_for_table(table)))
{
- safe_exit(EX_MYSQLERR);
- DBUG_RETURN(0);
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
}
write_header(sql_file, db);
}
if (!opt_xml && opt_comments)
- fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
- result_table);
+ fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
+ result_table);
if (opt_drop)
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
if (!opt_xml)
- fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
+ fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
else
print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n");
check_io(sql_file);
@@ -1674,10 +1708,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (init)
{
if (!opt_xml && !tFlag)
- {
- fputs(",\n",sql_file);
- check_io(sql_file);
- }
+ {
+ fputs(",\n",sql_file);
+ check_io(sql_file);
+ }
if (complete_insert)
dynstr_append_mem(&insert_pat, ", ", 2);
}
@@ -1687,30 +1721,30 @@ static uint get_table_structure(char *table, char *db, char *table_type,
quote_name(row[SHOW_FIELDNAME], name_buff, 0));
if (!tFlag)
{
- if (opt_xml)
- {
- print_xml_row(sql_file, "field", result, &row);
- continue;
- }
+ if (opt_xml)
+ {
+ print_xml_row(sql_file, "field", result, &row);
+ continue;
+ }
if (opt_keywords)
- fprintf(sql_file, " %s.%s %s", result_table,
- quote_name(row[SHOW_FIELDNAME],name_buff, 0),
- row[SHOW_TYPE]);
+ fprintf(sql_file, " %s.%s %s", result_table,
+ quote_name(row[SHOW_FIELDNAME],name_buff, 0),
+ row[SHOW_TYPE]);
else
- fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
- name_buff, 0),
- row[SHOW_TYPE]);
+ fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
+ name_buff, 0),
+ row[SHOW_TYPE]);
if (row[SHOW_DEFAULT])
{
- fputs(" DEFAULT ", sql_file);
- unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
+ fputs(" DEFAULT ", sql_file);
+ unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
}
if (!row[SHOW_NULL][0])
- fputs(" NOT NULL", sql_file);
+ fputs(" NOT NULL", sql_file);
if (row[SHOW_EXTRA][0])
- fprintf(sql_file, " %s",row[SHOW_EXTRA]);
- check_io(sql_file);
+ fprintf(sql_file, " %s",row[SHOW_EXTRA]);
+ check_io(sql_file);
}
}
num_fields= mysql_num_rows(result);
@@ -1730,9 +1764,9 @@ static uint get_table_structure(char *table, char *db, char *table_type,
goto continue_xml;
}
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
- my_progname, result_table, mysql_error(sock));
+ my_progname, result_table, mysql_error(sock));
if (path)
- my_fclose(sql_file, MYF(MY_WME));
+ my_fclose(sql_file, MYF(MY_WME));
safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -1744,102 +1778,102 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (atoi(row[3]) == 1)
{
- keynr++;
+ keynr++;
#ifdef FORCE_PRIMARY_KEY
- if (atoi(row[1]) == 0 && primary_key == INT_MAX)
- primary_key=keynr;
+ if (atoi(row[1]) == 0 && primary_key == INT_MAX)
+ primary_key=keynr;
#endif
- if (!strcmp(row[2],"PRIMARY"))
- {
- primary_key=keynr;
- break;
- }
+ if (!strcmp(row[2],"PRIMARY"))
+ {
+ primary_key=keynr;
+ break;
+ }
}
}
mysql_data_seek(result,0);
keynr=0;
while ((row= mysql_fetch_row(result)))
{
- if (opt_xml)
- {
- print_xml_row(sql_file, "key", result, &row);
- continue;
- }
+ if (opt_xml)
+ {
+ print_xml_row(sql_file, "key", result, &row);
+ continue;
+ }
if (atoi(row[3]) == 1)
{
- if (keynr++)
- putc(')', sql_file);
- if (atoi(row[1])) /* Test if duplicate key */
- /* Duplicate allowed */
- fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
- else if (keynr == primary_key)
- fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
- else
- fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
- 0));
+ if (keynr++)
+ putc(')', sql_file);
+ if (atoi(row[1])) /* Test if duplicate key */
+ /* Duplicate allowed */
+ fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
+ else if (keynr == primary_key)
+ fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
+ else
+ fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
+ 0));
}
else
- putc(',', sql_file);
+ putc(',', sql_file);
fputs(quote_name(row[4], name_buff, 0), sql_file);
if (row[7])
- fprintf(sql_file, " (%s)",row[7]); /* Sub key */
- check_io(sql_file);
+ fprintf(sql_file, " (%s)",row[7]); /* Sub key */
+ check_io(sql_file);
}
if (!opt_xml)
{
- if (keynr)
- putc(')', sql_file);
- fputs("\n)",sql_file);
- check_io(sql_file);
+ if (keynr)
+ putc(')', sql_file);
+ fputs("\n)",sql_file);
+ check_io(sql_file);
}
/* Get MySQL specific create options */
if (create_options)
{
- char show_name_buff[NAME_LEN*2+2+24];
+ char show_name_buff[NAME_LEN*2+2+24];
- /* Check memory for quote_for_like() */
+ /* Check memory for quote_for_like() */
my_snprintf(buff, sizeof(buff), "show table status like %s",
- quote_for_like(table, show_name_buff));
+ quote_for_like(table, show_name_buff));
if (mysql_query_with_error_report(sock, &result, buff))
{
- if (mysql_errno(sock) != ER_PARSE_ERROR)
- { /* If old MySQL version */
- if (verbose)
- fprintf(stderr,
- "-- Warning: Couldn't get status information for table %s (%s)\n",
- result_table,mysql_error(sock));
- }
+ if (mysql_errno(sock) != ER_PARSE_ERROR)
+ { /* If old MySQL version */
+ if (verbose)
+ fprintf(stderr,
+ "-- Warning: Couldn't get status information for table %s (%s)\n",
+ result_table,mysql_error(sock));
+ }
}
else if (!(row= mysql_fetch_row(result)))
{
- fprintf(stderr,
- "Error: Couldn't read status information for table %s (%s)\n",
- result_table,mysql_error(sock));
+ fprintf(stderr,
+ "Error: Couldn't read status information for table %s (%s)\n",
+ result_table,mysql_error(sock));
}
else
{
- if (opt_xml)
- print_xml_row(sql_file, "options", result, &row);
- else
- {
- fputs("/*!",sql_file);
- print_value(sql_file,result,row,"engine=","Engine",0);
- print_value(sql_file,result,row,"","Create_options",0);
- print_value(sql_file,result,row,"comment=","Comment",1);
- fputs(" */",sql_file);
- check_io(sql_file);
- }
+ if (opt_xml)
+ print_xml_row(sql_file, "options", result, &row);
+ else
+ {
+ fputs("/*!",sql_file);
+ print_value(sql_file,result,row,"engine=","Engine",0);
+ print_value(sql_file,result,row,"","Create_options",0);
+ print_value(sql_file,result,row,"comment=","Comment",1);
+ fputs(" */",sql_file);
+ check_io(sql_file);
+ }
}
- mysql_free_result(result); /* Is always safe to free */
+ mysql_free_result(result); /* Is always safe to free */
}
continue_xml:
if (!opt_xml)
- fputs(";\n", sql_file);
+ fputs(";\n", sql_file);
else
- fputs("\t</table_structure>\n", sql_file);
+ fputs("\t</table_structure>\n", sql_file);
check_io(sql_file);
}
}
@@ -1871,8 +1905,8 @@ continue_xml:
static void dump_triggers_for_table (char *table, char *db)
{
- char *result_table;
- char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
+ char *result_table;
+ char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
char query_buff[512];
uint old_opt_compatible_mode=opt_compatible_mode;
FILE *sql_file = md_result_file;
@@ -1921,7 +1955,7 @@ DELIMITER ;;\n");
uint host_name_len;
char host_name_str[HOSTNAME_LENGTH + 1];
char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
-
+
parse_user(row[7], strlen(row[7]), user_name_str, &user_name_len,
host_name_str, &host_name_len);
@@ -1937,7 +1971,7 @@ DELIMITER ;;\n");
row[4], /* Timing */
row[1], /* Event */
result_table,
- (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
+ (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
row[3] /* Statement */);
}
if (mysql_num_rows(result))
@@ -1946,7 +1980,7 @@ DELIMITER ;;\n");
"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n");
mysql_free_result(result);
/*
- make sure to set back opt_compatible mode to
+ make sure to set back opt_compatible mode to
original value
*/
opt_compatible_mode=old_opt_compatible_mode;
@@ -1954,7 +1988,7 @@ DELIMITER ;;\n");
}
static char *add_load_option(char *ptr,const char *object,
- const char *statement)
+ const char *statement)
{
if (object)
{
@@ -1993,7 +2027,7 @@ static char *field_escape(char *to,const char *from,uint length)
else
{
if (*from == '\'' && !end_backslashes)
- *to++= *from; /* We want a duplicate of "'" for MySQL */
+ *to++= *from; /* We want a duplicate of "'" for MySQL */
end_backslashes=0;
}
}
@@ -2010,8 +2044,8 @@ static char *alloc_query_str(ulong size)
if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
{
- ignore_errors= 0; /* Fatal error */
- safe_exit(EX_MYSQLERR); /* Force exit */
+ ignore_errors= 0; /* Fatal error */
+ safe_exit(EX_MYSQLERR); /* Force exit */
}
return query;
}
@@ -2040,11 +2074,11 @@ static void dump_table(char *table, char *db)
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
char *query= query_buf;
int error= 0;
- ulong rownr, row_break, total_length, init_length;
+ ulong rownr, row_break, total_length, init_length;
uint num_fields;
- MYSQL_RES *res;
- MYSQL_FIELD *field;
- MYSQL_ROW row;
+ MYSQL_RES *res;
+ MYSQL_FIELD *field;
+ MYSQL_ROW row;
DBUG_ENTER("dump_table");
/*
@@ -2053,13 +2087,19 @@ static void dump_table(char *table, char *db)
*/
num_fields= get_table_structure(table, db, table_type, &ignore_flag);
+ /*
+ The "table" could be a view. If so, we don't do anything here.
+ */
+ if (strcmp (table_type, "VIEW") == 0)
+ return;
+
/* Check --no-data flag */
if (dFlag)
{
if (verbose)
fprintf(stderr,
"-- Skipping dump data for table '%s', --no-data was used\n",
- table);
+ table);
DBUG_VOID_RETURN;
}
@@ -2074,8 +2114,8 @@ static void dump_table(char *table, char *db)
{
if (verbose)
fprintf(stderr,
- "-- Warning: Skipping data for table '%s' because it's of type %s\n",
- table, table_type);
+ "-- Warning: Skipping data for table '%s' because it's of type %s\n",
+ table, table_type);
DBUG_VOID_RETURN;
}
/* Check that there are any fields in the table */
@@ -2083,8 +2123,8 @@ static void dump_table(char *table, char *db)
{
if (verbose)
fprintf(stderr,
- "-- Skipping dump data for table '%s', it has no fields\n",
- table);
+ "-- Skipping dump data for table '%s', it has no fields\n",
+ table);
DBUG_VOID_RETURN;
}
@@ -2100,11 +2140,11 @@ static void dump_table(char *table, char *db)
my_load_path(tmp_path, tmp_path, NULL);
fn_format(filename, table, tmp_path, ".txt", 4);
my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
- filename wasn't deleted */
+ filename wasn't deleted */
to_unix_path(filename);
- my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
- filename);
+ my_snprintf(query, QUERY_LENGTH,
+ "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
+ filename);
end= strend(query);
if (fields_terminated || enclosed || opt_enclosed || escaped)
@@ -2141,12 +2181,12 @@ static void dump_table(char *table, char *db)
if (!opt_xml && opt_comments)
{
fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
- result_table);
+ result_table);
check_io(md_result_file);
}
my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
- result_table);
+ "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
+ result_table);
if (where || order_by)
{
query = alloc_query_str((ulong) (strlen(query) + 1 +
@@ -2194,7 +2234,7 @@ static void dump_table(char *table, char *db)
if (mysql_num_fields(res) != num_fields)
{
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
- my_progname, result_table);
+ my_progname, result_table);
error= EX_CONSCHECK;
goto err;
}
@@ -2202,7 +2242,7 @@ static void dump_table(char *table, char *db)
if (opt_disable_keys)
{
fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
- opt_quoted_table);
+ opt_quoted_table);
check_io(md_result_file);
}
if (opt_lock)
@@ -2211,7 +2251,7 @@ static void dump_table(char *table, char *db)
check_io(md_result_file);
}
- total_length= opt_net_buffer_length; /* Force row break */
+ total_length= opt_net_buffer_length; /* Force row break */
row_break=0;
rownr=0;
init_length=(uint) insert_pat.length+4;
@@ -2231,15 +2271,15 @@ static void dump_table(char *table, char *db)
rownr++;
if (!extended_insert && !opt_xml)
{
- fputs(insert_pat.str,md_result_file);
- check_io(md_result_file);
+ fputs(insert_pat.str,md_result_file);
+ check_io(md_result_file);
}
mysql_field_seek(res,0);
if (opt_xml)
{
fputs("\t<row>\n", md_result_file);
- check_io(md_result_file);
+ check_io(md_result_file);
}
for (i = 0; i < mysql_num_fields(res); i++)
@@ -2247,21 +2287,21 @@ static void dump_table(char *table, char *db)
int is_blob;
ulong length= lengths[i];
- if (!(field = mysql_fetch_field(res)))
- {
- my_snprintf(query, QUERY_LENGTH,
- "%s: Not enough fields from table %s! Aborting.\n",
- my_progname, result_table);
- fputs(query,stderr);
- error= EX_CONSCHECK;
- goto err;
- }
-
- /*
- 63 is my_charset_bin. If charsetnr is not 63,
- we have not a BLOB but a TEXT column.
- we'll dump in hex only BLOB columns.
- */
+ if (!(field = mysql_fetch_field(res)))
+ {
+ my_snprintf(query, QUERY_LENGTH,
+ "%s: Not enough fields from table %s! Aborting.\n",
+ my_progname, result_table);
+ fputs(query,stderr);
+ error= EX_CONSCHECK;
+ goto err;
+ }
+
+ /*
+ 63 is my_charset_bin. If charsetnr is not 63,
+ we have not a BLOB but a TEXT column.
+ we'll dump in hex only BLOB columns.
+ */
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
(field->type == MYSQL_TYPE_BIT ||
field->type == MYSQL_TYPE_STRING ||
@@ -2271,36 +2311,36 @@ static void dump_table(char *table, char *db)
field->type == MYSQL_TYPE_LONG_BLOB ||
field->type == MYSQL_TYPE_MEDIUM_BLOB ||
field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
- if (extended_insert)
- {
- if (i == 0)
- dynstr_set(&extended_row,"(");
- else
- dynstr_append(&extended_row,",");
-
- if (row[i])
- {
- if (length)
- {
- if (!IS_NUM_FIELD(field))
- {
- /*
- "length * 2 + 2" is OK for both HEX and non-HEX modes:
- - In HEX mode we need exactly 2 bytes per character
- plus 2 bytes for '0x' prefix.
- - In non-HEX mode we need up to 2 bytes per character,
- plus 2 bytes for leading and trailing '\'' characters.
- */
- if (dynstr_realloc(&extended_row,length * 2+2))
- {
- fputs("Aborting dump (out of memory)",stderr);
- error= EX_EOM;
- goto err;
- }
+ if (extended_insert)
+ {
+ if (i == 0)
+ dynstr_set(&extended_row,"(");
+ else
+ dynstr_append(&extended_row,",");
+
+ if (row[i])
+ {
+ if (length)
+ {
+ if (!IS_NUM_FIELD(field))
+ {
+ /*
+ "length * 2 + 2" is OK for both HEX and non-HEX modes:
+ - In HEX mode we need exactly 2 bytes per character
+ plus 2 bytes for '0x' prefix.
+ - In non-HEX mode we need up to 2 bytes per character,
+ plus 2 bytes for leading and trailing '\'' characters.
+ */
+ if (dynstr_realloc(&extended_row,length * 2+2))
+ {
+ fputs("Aborting dump (out of memory)",stderr);
+ error= EX_EOM;
+ goto err;
+ }
if (opt_hex_blob && is_blob)
{
dynstr_append(&extended_row, "0x");
- extended_row.length+= mysql_hex_string(extended_row.str +
+ extended_row.length+= mysql_hex_string(extended_row.str +
extended_row.length,
row[i], length);
extended_row.str[extended_row.length]= '\0';
@@ -2315,94 +2355,94 @@ static void dump_table(char *table, char *db)
extended_row.str[extended_row.length]='\0';
dynstr_append(&extended_row,"'");
}
- }
- else
- {
- /* change any strings ("inf", "-inf", "nan") into NULL */
- char *ptr = row[i];
- if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
- my_isalpha(charset_info, ptr[1])))
- dynstr_append(&extended_row, "NULL");
- else
- {
- if (field->type == FIELD_TYPE_DECIMAL)
- {
- /* add " signs around */
- dynstr_append(&extended_row, "'");
- dynstr_append(&extended_row, ptr);
- dynstr_append(&extended_row, "'");
- }
- else
- dynstr_append(&extended_row, ptr);
- }
- }
- }
- else
- dynstr_append(&extended_row,"''");
- }
- else if (dynstr_append(&extended_row,"NULL"))
- {
- fputs("Aborting dump (out of memory)",stderr);
- error= EX_EOM;
- goto err;
- }
- }
- else
- {
- if (i && !opt_xml)
- {
- fputc(',', md_result_file);
- check_io(md_result_file);
- }
- if (row[i])
- {
- if (!IS_NUM_FIELD(field))
- {
- if (opt_xml)
- {
- print_xml_tag1(md_result_file, "\t\t", "field name=",
- field->name, "");
- print_quoted_xml(md_result_file, row[i], length);
- fputs("</field>\n", md_result_file);
- }
- else if (opt_hex_blob && is_blob && length)
+ }
+ else
+ {
+ /* change any strings ("inf", "-inf", "nan") into NULL */
+ char *ptr = row[i];
+ if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
+ my_isalpha(charset_info, ptr[1])))
+ dynstr_append(&extended_row, "NULL");
+ else
+ {
+ if (field->type == FIELD_TYPE_DECIMAL)
+ {
+ /* add " signs around */
+ dynstr_append(&extended_row, "'");
+ dynstr_append(&extended_row, ptr);
+ dynstr_append(&extended_row, "'");
+ }
+ else
+ dynstr_append(&extended_row, ptr);
+ }
+ }
+ }
+ else
+ dynstr_append(&extended_row,"''");
+ }
+ else if (dynstr_append(&extended_row,"NULL"))
+ {
+ fputs("Aborting dump (out of memory)",stderr);
+ error= EX_EOM;
+ goto err;
+ }
+ }
+ else
+ {
+ if (i && !opt_xml)
+ {
+ fputc(',', md_result_file);
+ check_io(md_result_file);
+ }
+ if (row[i])
+ {
+ if (!IS_NUM_FIELD(field))
+ {
+ if (opt_xml)
+ {
+ print_xml_tag1(md_result_file, "\t\t", "field name=",
+ field->name, "");
+ print_quoted_xml(md_result_file, row[i], length);
+ fputs("</field>\n", md_result_file);
+ }
+ else if (opt_hex_blob && is_blob && length)
{
/* sakaik got the idea to to provide blob's in hex notation. */
char *ptr= row[i], *end= ptr + length;
fputs("0x", md_result_file);
for (; ptr < end ; ptr++)
- fprintf(md_result_file, "%02X", *((uchar *)ptr));
+ fprintf(md_result_file, "%02X", *((uchar *)ptr));
}
else
unescape(md_result_file, row[i], length);
- }
- else
- {
- /* change any strings ("inf", "-inf", "nan") into NULL */
- char *ptr = row[i];
- if (opt_xml)
- {
- print_xml_tag1(md_result_file, "\t\t", "field name=",
- field->name, "");
- fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
- md_result_file);
- fputs("</field>\n", md_result_file);
- }
- else if (my_isalpha(charset_info, *ptr) ||
- (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
- fputs("NULL", md_result_file);
- else if (field->type == FIELD_TYPE_DECIMAL)
- {
- /* add " signs around */
- fputc('\'', md_result_file);
- fputs(ptr, md_result_file);
- fputc('\'', md_result_file);
- }
- else
- fputs(ptr, md_result_file);
- }
- }
- else
+ }
+ else
+ {
+ /* change any strings ("inf", "-inf", "nan") into NULL */
+ char *ptr = row[i];
+ if (opt_xml)
+ {
+ print_xml_tag1(md_result_file, "\t\t", "field name=",
+ field->name, "");
+ fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
+ md_result_file);
+ fputs("</field>\n", md_result_file);
+ }
+ else if (my_isalpha(charset_info, *ptr) ||
+ (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
+ fputs("NULL", md_result_file);
+ else if (field->type == FIELD_TYPE_DECIMAL)
+ {
+ /* add " signs around */
+ fputc('\'', md_result_file);
+ fputs(ptr, md_result_file);
+ fputc('\'', md_result_file);
+ }
+ else
+ fputs(ptr, md_result_file);
+ }
+ }
+ else
{
/* The field value is NULL */
if (!opt_xml)
@@ -2412,61 +2452,61 @@ static void dump_table(char *table, char *db)
field->name, "\n");
}
check_io(md_result_file);
- }
+ }
}
if (opt_xml)
{
fputs("\t</row>\n", md_result_file);
- check_io(md_result_file);
+ check_io(md_result_file);
}
if (extended_insert)
{
- ulong row_length;
- dynstr_append(&extended_row,")");
+ ulong row_length;
+ dynstr_append(&extended_row,")");
row_length = 2 + extended_row.length;
if (total_length + row_length < opt_net_buffer_length)
{
- total_length += row_length;
- fputc(',',md_result_file); /* Always row break */
- fputs(extended_row.str,md_result_file);
- }
+ total_length += row_length;
+ fputc(',',md_result_file); /* Always row break */
+ fputs(extended_row.str,md_result_file);
+ }
else
{
- if (row_break)
- fputs(";\n", md_result_file);
- row_break=1; /* This is first row */
+ if (row_break)
+ fputs(";\n", md_result_file);
+ row_break=1; /* This is first row */
fputs(insert_pat.str,md_result_file);
fputs(extended_row.str,md_result_file);
- total_length = row_length+init_length;
+ total_length = row_length+init_length;
}
- check_io(md_result_file);
+ check_io(md_result_file);
}
else if (!opt_xml)
{
- fputs(");\n", md_result_file);
- check_io(md_result_file);
+ fputs(");\n", md_result_file);
+ check_io(md_result_file);
}
}
/* XML - close table tag and supress regular output */
if (opt_xml)
- fputs("\t</table_data>\n", md_result_file);
+ fputs("\t</table_data>\n", md_result_file);
else if (extended_insert && row_break)
- fputs(";\n", md_result_file); /* If not empty table */
+ fputs(";\n", md_result_file); /* If not empty table */
fflush(md_result_file);
check_io(md_result_file);
if (mysql_errno(sock))
{
my_snprintf(query, QUERY_LENGTH,
- "%s: Error %d: %s when dumping table %s at row: %ld\n",
- my_progname,
- mysql_errno(sock),
- mysql_error(sock),
- result_table,
- rownr);
+ "%s: Error %d: %s when dumping table %s at row: %ld\n",
+ my_progname,
+ mysql_errno(sock),
+ mysql_error(sock),
+ result_table,
+ rownr);
fputs(query,stderr);
error= EX_CONSCHECK;
goto err;
@@ -2479,7 +2519,7 @@ static void dump_table(char *table, char *db)
if (opt_disable_keys)
{
fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
- opt_quoted_table);
+ opt_quoted_table);
check_io(md_result_file);
}
if (opt_autocommit)
@@ -2538,7 +2578,7 @@ static int dump_all_databases()
if (dump_all_tables_in_db(row[0]))
result=1;
}
- if (was_views)
+ if (seen_views)
{
if (mysql_query(sock, "SHOW DATABASES") ||
!(tableres = mysql_store_result(sock)))
@@ -2567,7 +2607,7 @@ static int dump_databases(char **db_names)
if (dump_all_tables_in_db(*db))
result=1;
}
- if (!result && was_views)
+ if (!result && seen_views)
{
for (db= db_names ; *db ; db++)
{
@@ -2583,26 +2623,26 @@ static int init_dumping(char *database)
{
if (mysql_get_server_version(sock) >= 50003 &&
!my_strcasecmp(&my_charset_latin1, database, "information_schema"))
- return 1;
+ return 1;
if (mysql_select_db(sock, database))
{
DB_error(sock, "when selecting the database");
- return 1; /* If --force */
+ return 1; /* If --force */
}
if (!path && !opt_xml)
{
if (opt_databases || opt_alldbs)
{
/*
- length of table name * 2 (if name contains quotes), 2 quotes and 0
+ length of table name * 2 (if name contains quotes), 2 quotes and 0
*/
char quoted_database_buf[64*2+3];
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
if (opt_comments)
{
- fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
- check_io(md_result_file);
+ fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
+ check_io(md_result_file);
}
if (!opt_create_db)
{
@@ -2610,9 +2650,9 @@ static int init_dumping(char *database)
MYSQL_ROW row;
MYSQL_RES *dbinfo;
- my_snprintf(qbuf, sizeof(qbuf),
- "SHOW CREATE DATABASE IF NOT EXISTS %s",
- qdatabase);
+ my_snprintf(qbuf, sizeof(qbuf),
+ "SHOW CREATE DATABASE IF NOT EXISTS %s",
+ qdatabase);
if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
{
@@ -2621,22 +2661,22 @@ static int init_dumping(char *database)
fprintf(md_result_file,
"\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n",
qdatabase);
- fprintf(md_result_file,
- "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
- qdatabase);
- }
- else
+ fprintf(md_result_file,
+ "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
+ qdatabase);
+ }
+ else
{
if (opt_drop_database)
fprintf(md_result_file,
"\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
qdatabase);
- row = mysql_fetch_row(dbinfo);
- if (row[1])
- {
- fprintf(md_result_file,"\n%s;\n",row[1]);
+ row = mysql_fetch_row(dbinfo);
+ if (row[1])
+ {
+ fprintf(md_result_file,"\n%s;\n",row[1]);
}
- }
+ }
}
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
check_io(md_result_file);
@@ -2741,8 +2781,6 @@ static my_bool dump_all_views_in_db(char *database)
uint numrows;
char table_buff[NAME_LEN*2+3];
- if (init_dumping(database))
- return 1;
if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", database, "\n");
if (lock_tables)
@@ -2801,7 +2839,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
/* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
- quote_for_like(old_table_name, show_name_buff));
+ quote_for_like(old_table_name, show_name_buff));
if (mysql_query_with_error_report(sock, 0, query))
{
@@ -2896,7 +2934,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
/* Dump each selected view */
- if (was_views)
+ if (seen_views)
{
for (pos= dump_tables; pos < end; pos++)
get_view_structure(*pos, db);
@@ -2946,14 +2984,14 @@ static int do_show_master_status(MYSQL *mysql_con)
"recovery from\n--\n\n");
fprintf(md_result_file,
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
- comment_prefix, row[0], row[1]);
+ comment_prefix, row[0], row[1]);
check_io(md_result_file);
}
else if (!ignore_errors)
{
/* SHOW MASTER STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Binlogging on server not active",
- MYF(0));
+ my_printf_error(0, "Error: Binlogging on server not active",
+ MYF(0));
mysql_free_result(master);
return 1;
}
@@ -2973,7 +3011,7 @@ static int do_flush_tables_read_lock(MYSQL *mysql_con)
and most client connections are stalled. Of course, if a second long
update starts between the two FLUSHes, we have that bad stall.
*/
- return
+ return
( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
mysql_query_with_error_report(mysql_con, 0,
"FLUSH TABLES WITH READ LOCK") );
@@ -3015,7 +3053,7 @@ static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
static ulong find_set(TYPELIB *lib, const char *x, uint length,
- char **err_pos, uint *err_len)
+ char **err_pos, uint *err_len)
{
const char *end= x + length;
ulong found= 0;
@@ -3057,10 +3095,10 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length,
/* Print a value with a prefix on file */
static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
- const char *prefix, const char *name,
- int string_value)
+ const char *prefix, const char *name,
+ int string_value)
{
- MYSQL_FIELD *field;
+ MYSQL_FIELD *field;
mysql_field_seek(result, 0);
for ( ; (field = mysql_fetch_field(result)) ; row++)
@@ -3069,18 +3107,18 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
{
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
{
- fputc(' ',file);
- fputs(prefix, file);
- if (string_value)
- unescape(file,row[0],(uint) strlen(row[0]));
- else
- fputs(row[0], file);
- check_io(file);
- return;
+ fputc(' ',file);
+ fputs(prefix, file);
+ if (string_value)
+ unescape(file,row[0],(uint) strlen(row[0]));
+ else
+ fputs(row[0], file);
+ check_io(file);
+ return;
}
}
}
- return; /* This shouldn't happen */
+ return; /* This shouldn't happen */
} /* print_value */
@@ -3091,19 +3129,19 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
Check if we the table is one of the table types that should be ignored:
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
If the table should be altogether ignored, it returns a TRUE, FALSE if it
- should not be ignored. If the user has selected to use INSERT DELAYED, it
- sets the value of the bool pointer supports_delayed_inserts to 0 if not
+ should not be ignored. If the user has selected to use INSERT DELAYED, it
+ sets the value of the bool pointer supports_delayed_inserts to 0 if not
supported, 1 if it is supported.
ARGS
check_if_ignore_table()
- table_name Table name to check
+ table_name Table name to check
table_type Type of table
GLOBAL VARIABLES
- sock MySQL socket
- verbose Write warning messages
+ sock MySQL socket
+ verbose Write warning messages
RETURN
char (bit value) See IGNORE_ values at top
@@ -3120,23 +3158,23 @@ char check_if_ignore_table(const char *table_name, char *table_type)
/* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff));
my_snprintf(buff, sizeof(buff), "show table status like %s",
- quote_for_like(table_name, show_name_buff));
+ quote_for_like(table_name, show_name_buff));
if (mysql_query_with_error_report(sock, &res, buff))
{
if (mysql_errno(sock) != ER_PARSE_ERROR)
- { /* If old MySQL version */
+ { /* If old MySQL version */
if (verbose)
- fprintf(stderr,
- "-- Warning: Couldn't get status information for table %s (%s)\n",
- table_name,mysql_error(sock));
+ fprintf(stderr,
+ "-- Warning: Couldn't get status information for table %s (%s)\n",
+ table_name,mysql_error(sock));
DBUG_RETURN(result); /* assume table is ok */
}
}
if (!(row= mysql_fetch_row(res)))
{
fprintf(stderr,
- "Error: Couldn't read status information for table %s (%s)\n",
- table_name, mysql_error(sock));
+ "Error: Couldn't read status information for table %s (%s)\n",
+ table_name, mysql_error(sock));
mysql_free_result(res);
DBUG_RETURN(result); /* assume table is ok */
}
@@ -3199,8 +3237,8 @@ static char *primary_key_fields(const char *table_name)
uint result_length = 0;
char *result = 0;
- my_snprintf(show_keys_buff, sizeof(show_keys_buff),
- "SHOW KEYS FROM %s", table_name);
+ my_snprintf(show_keys_buff, sizeof(show_keys_buff),
+ "SHOW KEYS FROM %s", table_name);
if (mysql_query(sock, show_keys_buff) ||
!(res = mysql_store_result(sock)))
{
@@ -3276,7 +3314,7 @@ static int replace(DYNAMIC_STRING *ds_str,
if (!start)
return 1;
init_dynamic_string(&ds_tmp, "",
- ds_str->length + replace_len, 256);
+ ds_str->length + replace_len, 256);
dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
dynstr_append_mem(&ds_tmp, replace_str, replace_len);
dynstr_append(&ds_tmp, start + search_len);
@@ -3304,9 +3342,9 @@ static my_bool get_view_structure(char *table, char* db)
MYSQL_RES *table_res;
MYSQL_ROW row;
MYSQL_FIELD *field;
- char *result_table, *opt_quoted_table;
- char table_buff[NAME_LEN*2+3];
- char table_buff2[NAME_LEN*2+3];
+ char *result_table, *opt_quoted_table;
+ char table_buff[NAME_LEN*2+3];
+ char table_buff2[NAME_LEN*2+3];
char query[QUERY_LENGTH];
FILE *sql_file = md_result_file;
DBUG_ENTER("get_view_structure");
@@ -3319,7 +3357,7 @@ static my_bool get_view_structure(char *table, char* db)
#ifdef NOT_REALLY_USED_YET
sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
- (opt_quoted || opt_keywords));
+ (opt_quoted || opt_keywords));
#endif
result_table= quote_name(table, table_buff, 1);
@@ -3354,7 +3392,7 @@ static my_bool get_view_structure(char *table, char* db)
if (!opt_xml && opt_comments)
{
- fprintf(sql_file, "\n--\n-- View structure for view %s\n--\n\n",
+ fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n",
result_table);
check_io(sql_file);
}
@@ -3435,7 +3473,7 @@ static my_bool get_view_structure(char *table, char* db)
char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
parse_user(row[1], lengths[1], user_name_str, &user_name_len,
- host_name_str, &host_name_len);
+ host_name_str, &host_name_len);
ptr= search_buf;
search_len=
diff --git a/configure.in b/configure.in
index 3c335089688..fd2cf3baf97 100644
--- a/configure.in
+++ b/configure.in
@@ -1137,7 +1137,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 libmysql/Makefile.in libmysql_r/Makefile.in extra/Makefile.in strings/Makefile.in client/Makefile.in
do
# echo "#### $file ####"
filedir="`dirname $file`"
@@ -1163,9 +1163,9 @@ s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux,
s%\(mysqld_DEPENDENCIES = \) %\1$lib_DEPENDENCIES %
EOF
;;
- sql/share/Makefile.in)
+ extra/Makefile.in)
cat > $filesed << EOF
-s,\(extra/comp_err\),\1.linux,
+s,\(extra/comp_err\)\$(EXEEXT),\1.linux,
EOF
;;
libmysql/Makefile.in)
diff --git a/extra/yassl/README b/extra/yassl/README
index 62209723f66..a5ff70aa6f6 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -1,4 +1,14 @@
-yaSSL Release notes, version 1.3.0 (04/26/06)
+yaSSL Release notes, version 1.3.5 (06/01/06)
+
+
+ This release of yaSSL contains bug fixes, portability enhancements,
+ better libcurl support, and improved non-blocking I/O.
+
+See normal build instructions below under 1.0.6.
+See libcurl build instructions below under 1.3.0.
+
+
+********************yaSSL Release notes, version 1.3.0 (04/26/06)
This release of yaSSL contains minor bug fixes, portability enhancements,
@@ -17,8 +27,8 @@ See normal build instructions below under 1.0.6.
make
make openssl-links
- (then go to your libcurl home and tell libcurl about yaSSL)
- ./configure --with-ssl=/yaSSL-HomeDir
+ (then go to your libcurl home and tell libcurl about yaSSL build dir)
+ ./configure --with-ssl=/yaSSL-BuildDir LDFLAGS=-lm
make
diff --git a/extra/yassl/include/openssl/engine.h b/extra/yassl/include/openssl/engine.h
new file mode 100644
index 00000000000..39952fcae84
--- /dev/null
+++ b/extra/yassl/include/openssl/engine.h
@@ -0,0 +1,5 @@
+/* engine.h for libcurl */
+
+#undef HAVE_OPENSSL_ENGINE_H
+
+
diff --git a/extra/yassl/include/openssl/pkcs12.h b/extra/yassl/include/openssl/pkcs12.h
new file mode 100644
index 00000000000..e452fc879c4
--- /dev/null
+++ b/extra/yassl/include/openssl/pkcs12.h
@@ -0,0 +1,5 @@
+/* pkcs12.h for libcurl */
+
+
+#undef HAVE_OPENSSL_PKCS12_H
+
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
index 2b099af930c..66ec64f4af8 100644
--- a/extra/yassl/src/handshake.cpp
+++ b/extra/yassl/src/handshake.cpp
@@ -458,6 +458,11 @@ void ProcessOldClientHello(input_buffer& input, SSL& ssl)
uint16 sz = ((b0 & 0x7f) << 8) | b1;
+ if (sz > input.get_remaining()) {
+ ssl.SetError(bad_input);
+ return;
+ }
+
// hashHandShake manually
const opaque* buffer = input.get_buffer() + input.get_current();
ssl.useHashes().use_MD5().update(buffer, sz);
@@ -681,25 +686,38 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
// old style sslv2 client hello?
if (ssl.getSecurity().get_parms().entity_ == server_end &&
ssl.getStates().getServer() == clientNull)
- if (buffer.peek() != handshake)
+ if (buffer.peek() != handshake) {
ProcessOldClientHello(buffer, ssl);
+ if (ssl.GetError()) {
+ buffered.reset(0);
+ return buffered;
+ }
+ }
while(!buffer.eof()) {
// each record
RecordLayerHeader hdr;
+ bool needHdr = false;
+
+ if (static_cast<uint>(RECORD_HEADER) > buffer.get_remaining())
+ needHdr = true;
+ else {
buffer >> hdr;
ssl.verifyState(hdr);
+ }
// make sure we have enough input in buffer to process this record
- if (hdr.length_ > buffer.get_remaining()) {
- uint sz = buffer.get_remaining() + RECORD_HEADER;
+ if (needHdr || hdr.length_ > buffer.get_remaining()) {
+ // put header in front for next time processing
+ uint extra = needHdr ? 0 : RECORD_HEADER;
+ uint sz = buffer.get_remaining() + extra;
buffered.reset(NEW_YS input_buffer(sz, buffer.get_buffer() +
- buffer.get_current() - RECORD_HEADER, sz));
+ buffer.get_current() - extra, sz));
break;
}
while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) {
- // each message in record
+ // each message in record, can be more than 1 if not encrypted
if (ssl.getSecurity().get_parms().pending_ == false) // cipher on
decrypt_message(ssl, buffer, hdr.length_);
mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_), ysDelete);
@@ -717,7 +735,7 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
}
offset += hdr.length_ + RECORD_HEADER;
}
- return buffered; // done, don't call again
+ return buffered;
}
@@ -862,7 +880,7 @@ int sendData(SSL& ssl, const void* buffer, int sz)
ssl.SetError(no_error);
ssl.verfiyHandShakeComplete();
- if (ssl.GetError()) return 0;
+ if (ssl.GetError()) return -1;
int sent = 0;
for (;;) {
@@ -873,7 +891,7 @@ int sendData(SSL& ssl, const void* buffer, int sz)
buildMessage(ssl, out, data);
ssl.Send(out.get_buffer(), out.get_size());
- if (ssl.GetError()) return 0;
+ if (ssl.GetError()) return -1;
sent += len;
if (sent == sz) break;
}
@@ -900,14 +918,14 @@ int receiveData(SSL& ssl, Data& data)
ssl.SetError(no_error);
ssl.verfiyHandShakeComplete();
- if (ssl.GetError()) return 0;
+ if (ssl.GetError()) return -1;
if (!ssl.bufferedData())
processReply(ssl);
ssl.fillData(data);
ssl.useLog().ShowData(data.get_length());
- if (ssl.GetError()) return 0;
+ if (ssl.GetError()) return -1;
if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) {
ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
index 803f4b01249..06b403c999d 100644
--- a/extra/yassl/src/socket_wrapper.cpp
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -113,13 +113,22 @@ uint Socket::get_ready() const
uint Socket::send(const byte* buf, unsigned int sz, int flags) const
{
+ const byte* pos = buf;
+ const byte* end = pos + sz;
+
assert(socket_ != INVALID_SOCKET);
- int sent = ::send(socket_, reinterpret_cast<const char *>(buf), sz, flags);
+
+ while (pos != end) {
+ int sent = ::send(socket_, reinterpret_cast<const char *>(pos),
+ static_cast<int>(end - pos), flags);
if (sent == -1)
return 0;
- return sent;
+ pos += sent;
+ }
+
+ return sz;
}
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
index 3a5cf62865a..88559cb0ca0 100644
--- a/extra/yassl/taocrypt/include/runtime.hpp
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -28,6 +28,9 @@
#ifndef yaSSL_NEW_HPP
#define yaSSL_NEW_HPP
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#ifdef __sun
diff --git a/include/Makefile.am b/include/Makefile.am
index 07c32e3127b..2dbea3fe07f 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -31,7 +31,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \
my_aes.h my_tree.h hash.h thr_alarm.h \
thr_lock.h t_ctype.h violite.h md5.h base64.h \
mysql_version.h.in my_handler.h my_time.h decimal.h \
- my_user.h
+ my_user.h my_libwrap.h
# mysql_version.h are generated
CLEANFILES = mysql_version.h my_config.h readline openssl
diff --git a/include/config-win.h b/include/config-win.h
index 8d937ffed22..75133ddc837 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -384,6 +384,7 @@ inline double ulonglong2double(ulonglong value)
#define FN_LIBCHAR '\\'
#define FN_ROOTDIR "\\"
+#define FN_DEVCHAR ':'
#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */
#define FN_NO_CASE_SENCE /* Files are not case-sensitive */
#define OS_FILE_LIMIT 2048
diff --git a/include/my_global.h b/include/my_global.h
index 7adf4845984..c9f27e0031e 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -599,7 +599,6 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */
#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */
#define FN_PARENTDIR ".." /* Parent directory; Must be a string */
-#define FN_DEVCHAR ':'
#ifndef FN_LIBCHAR
#ifdef __EMX__
@@ -736,6 +735,9 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define DBL_MAX 1.79769313486231470e+308
#define FLT_MAX ((float)3.40282346638528860e+38)
#endif
+#ifndef SSIZE_MAX
+#define SSIZE_MAX ((~((size_t) 0)) / 2)
+#endif
#if !defined(HAVE_ISINF) && !defined(isinf)
#define isinf(X) 0
diff --git a/include/my_libwrap.h b/include/my_libwrap.h
new file mode 100644
index 00000000000..6437cbaed84
--- /dev/null
+++ b/include/my_libwrap.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+#ifdef NEED_SYS_SYSLOG_H
+#include <sys/syslog.h>
+#endif /* NEED_SYS_SYSLOG_H */
+
+extern void my_fromhost(struct request_info *req);
+extern int my_hosts_access(struct request_info *req);
+extern char *my_eval_client(struct request_info *req);
+
+#endif /* HAVE_LIBWRAP */
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 89b82882d93..9e922a3e04a 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -2570,14 +2570,14 @@ do not allow the discard. We also reserve the data dictionary latch. */
}
}
funct_exit:
+ trx_commit_for_mysql(trx);
+
row_mysql_unlock_data_dictionary(trx);
if (graph) {
que_graph_free(graph);
}
- trx_commit_for_mysql(trx);
-
trx->op_info = "";
return((int) err);
@@ -2707,10 +2707,10 @@ row_import_tablespace_for_mysql(
}
funct_exit:
- row_mysql_unlock_data_dictionary(trx);
-
trx_commit_for_mysql(trx);
+ row_mysql_unlock_data_dictionary(trx);
+
trx->op_info = "";
return((int) err);
@@ -3398,6 +3398,8 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
}
funct_exit:
+ trx_commit_for_mysql(trx);
+
if (locked_dictionary) {
row_mysql_unlock_data_dictionary(trx);
}
@@ -3408,8 +3410,6 @@ funct_exit:
que_graph_free(graph);
- trx_commit_for_mysql(trx);
-
trx->op_info = "";
#ifndef UNIV_HOTBACKUP
@@ -3488,10 +3488,10 @@ loop:
}
}
- row_mysql_unlock_data_dictionary(trx);
-
trx_commit_for_mysql(trx);
+ row_mysql_unlock_data_dictionary(trx);
+
trx->op_info = "";
return(err);
@@ -3905,6 +3905,8 @@ row_rename_table_for_mysql(
}
}
funct_exit:
+ trx_commit_for_mysql(trx);
+
if (!recovering_temp_table) {
row_mysql_unlock_data_dictionary(trx);
}
@@ -3917,8 +3919,6 @@ funct_exit:
mem_heap_free(heap);
}
- trx_commit_for_mysql(trx);
-
trx->op_info = "";
return((int) err);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 1402d3aaba6..23971767e7e 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -1064,11 +1064,12 @@ row_sel_try_search_shortcut(
ut_ad(plan->pcur.latch_mode == node->latch_mode);
plan->n_rows_fetched++;
+ ret = SEL_FOUND;
func_exit:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
- return(SEL_FOUND);
+ return(ret);
}
/*************************************************************************
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 7d87ecd8595..e0f04965650 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -453,25 +453,24 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
if ((uint) share->base.auto_key -1 == key)
{
/* Check that auto_increment key is bigger than max key value */
- ulonglong save_auto_value=info->s->state.auto_increment;
- info->s->state.auto_increment=0;
+ ulonglong auto_increment;
info->lastinx=key;
_mi_read_key_record(info, 0L, info->rec_buff);
- update_auto_increment(info, info->rec_buff);
- if (info->s->state.auto_increment > save_auto_value)
+ auto_increment= retrieve_auto_increment(info, info->rec_buff);
+ if (auto_increment > info->s->state.auto_increment)
{
- mi_check_print_warning(param,
- "Auto-increment value: %s is smaller than max used value: %s",
- llstr(save_auto_value,buff2),
- llstr(info->s->state.auto_increment, buff));
+ mi_check_print_warning(param, "Auto-increment value: %s is smaller "
+ "than max used value: %s",
+ llstr(info->s->state.auto_increment,buff2),
+ llstr(auto_increment, buff));
}
if (param->testflag & T_AUTO_INC)
{
- set_if_bigger(info->s->state.auto_increment,
- param->auto_increment_value);
+ set_if_bigger(info->s->state.auto_increment,
+ auto_increment);
+ set_if_bigger(info->s->state.auto_increment,
+ param->auto_increment_value);
}
- else
- info->s->state.auto_increment=save_auto_value;
/* Check that there isn't a row with auto_increment = 0 in the table */
mi_extra(info,HA_EXTRA_KEYREAD,0);
@@ -481,8 +480,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
{
/* Don't count this as a real warning, as myisamchk can't correct it */
uint save=param->warning_printed;
- mi_check_print_warning(param,
- "Found row where the auto_increment column has the value 0");
+ mi_check_print_warning(param, "Found row where the auto_increment "
+ "column has the value 0");
param->warning_printed=save;
}
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
@@ -4099,11 +4098,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
}
else
{
- ulonglong auto_increment= (repair_only ? info->s->state.auto_increment :
- param->auto_increment_value);
- info->s->state.auto_increment=0;
- update_auto_increment(info, record);
+ ulonglong auto_increment= retrieve_auto_increment(info, record);
set_if_bigger(info->s->state.auto_increment,auto_increment);
+ if (!repair_only)
+ set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
}
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0));
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 717a5dbd56e..17ea56f0210 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -507,22 +507,21 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
return(-1); /* Wrong data to read */
}
-
+
/*
- Update auto_increment info
+ Retrieve auto_increment info
SYNOPSIS
- update_auto_increment()
+ retrieve_auto_increment()
info MyISAM handler
record Row to update
IMPLEMENTATION
- Only replace the auto_increment value if it is higher than the previous
- one. For signed columns we don't update the auto increment value if it's
+ For signed columns we don't retrieve the auto increment value if it's
less than zero.
*/
-void update_auto_increment(MI_INFO *info,const byte *record)
+ulonglong retrieve_auto_increment(MI_INFO *info,const byte *record)
{
ulonglong value= 0; /* Store unsigned values here */
longlong s_value= 0; /* Store signed values here */
@@ -587,6 +586,5 @@ void update_auto_increment(MI_INFO *info,const byte *record)
and if s_value == 0 then value will contain either s_value or the
correct value.
*/
- set_if_bigger(info->s->state.auto_increment,
- (s_value > 0) ? (ulonglong) s_value : value);
+ return (s_value > 0) ? (ulonglong) s_value : value;
}
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index 937c9983b45..f8b5cf55406 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -164,7 +164,8 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
key_changed|= HA_STATE_CHANGED; /* Must update index file */
}
if (auto_key_changed)
- update_auto_increment(info,newrec);
+ set_if_bigger(info->s->state.auto_increment,
+ retrieve_auto_increment(info, newrec));
if (share->calc_checksum)
info->state->checksum+=(info->checksum - old_checksum);
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index 5e79b2937cc..9ab8753f6d7 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -149,7 +149,8 @@ int mi_write(MI_INFO *info, byte *record)
info->state->checksum+=info->checksum;
}
if (share->base.auto_key)
- update_auto_increment(info,record);
+ set_if_bigger(info->s->state.auto_increment,
+ retrieve_auto_increment(info, record));
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
HA_STATE_ROW_CHANGED);
info->state->records++;
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 6ccb52aff22..d589173f0e7 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -582,7 +582,7 @@ extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
uint length,int re_read_if_possibly);
-extern void update_auto_increment(MI_INFO *info,const byte *record);
+extern ulonglong retrieve_auto_increment(MI_INFO *info,const byte *record);
extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
#define mi_get_rec_buff_ptr(info,buf) \
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 6fa6bc73bdb..0ca16b61fc2 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -890,19 +890,28 @@ sub mtr_kill_processes ($) {
sub mtr_kill_process ($$$$) {
my $pid= shift;
my $signal= shift;
- my $retries= shift;
+ my $total_retries= shift;
my $timeout= shift;
- while (1)
+ for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt)
{
+ mtr_debug("Sending $signal to $pid...");
+
kill($signal, $pid);
- last unless kill (0, $pid) and $retries--;
+ unless (kill (0, $pid))
+ {
+ mtr_debug("Process $pid died.");
+ return;
+ }
- mtr_debug("Sleep $timeout second waiting for processes to die");
+ mtr_debug("Sleeping $timeout second(s) waiting for processes to die...");
sleep($timeout);
}
+
+ mtr_debug("Process $pid is still alive after $total_retries " .
+ "of sending signal $signal.");
}
##############################################################################
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 4a9628c0721..3293487a0ac 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -286,7 +286,7 @@ our $opt_user_test;
our $opt_valgrind= 0;
our $opt_valgrind_mysqld= 0;
our $opt_valgrind_mysqltest= 0;
-our $opt_valgrind_all= 0;
+our $default_valgrind_options= "-v --show-reachable=yes";
our $opt_valgrind_options;
our $opt_valgrind_path;
@@ -597,10 +597,9 @@ sub command_line_setup () {
# Coverage, profiling etc
'gcov' => \$opt_gcov,
'gprof' => \$opt_gprof,
- 'valgrind' => \$opt_valgrind,
+ 'valgrind|valgrind-all' => \$opt_valgrind,
'valgrind-mysqltest' => \$opt_valgrind_mysqltest,
'valgrind-mysqld' => \$opt_valgrind_mysqld,
- 'valgrind-all' => \$opt_valgrind_all,
'valgrind-options=s' => \$opt_valgrind_options,
'valgrind-path=s' => \$opt_valgrind_path,
@@ -671,6 +670,12 @@ sub command_line_setup () {
{
push(@opt_extra_mysqld_opt, $arg);
}
+ elsif ( $arg =~ /^--$/ )
+ {
+ # It is an effect of setting 'pass_through' in option processing
+ # that the lone '--' separating options from arguments survives,
+ # simply ignore it.
+ }
elsif ( $arg =~ /^-/ )
{
usage("Invalid option \"$arg\"");
@@ -801,20 +806,32 @@ sub command_line_setup () {
$opt_with_ndbcluster= 0;
}
- # Turn on valgrinding of all executables if "valgrind" or "valgrind-all"
- if ( $opt_valgrind or $opt_valgrind_all )
+ # Check valgrind arguments
+ if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options)
{
mtr_report("Turning on valgrind for all executables");
$opt_valgrind= 1;
$opt_valgrind_mysqld= 1;
$opt_valgrind_mysqltest= 1;
}
- elsif ( $opt_valgrind_mysqld or $opt_valgrind_mysqltest )
+ elsif ( $opt_valgrind_mysqld )
+ {
+ mtr_report("Turning on valgrind for mysqld(s) only");
+ $opt_valgrind= 1;
+ }
+ elsif ( $opt_valgrind_mysqltest )
{
- # If test's are run for a specific executable, turn on
- # verbose and show-reachable
+ mtr_report("Turning on valgrind for mysqltest only");
$opt_valgrind= 1;
- $opt_valgrind_all= 1;
+ }
+
+ if ( $opt_valgrind )
+ {
+ # Set valgrind_options to default unless already defined
+ $opt_valgrind_options=$default_valgrind_options
+ unless defined $opt_valgrind_options;
+
+ mtr_report("Running valgrind with options \"$opt_valgrind_options\"");
}
if ( ! $opt_testcase_timeout )
@@ -2843,22 +2860,58 @@ sub im_stop($) {
# Try graceful shutdown.
+ mtr_debug("IM-main pid: $instance_manager->{'pid'}");
+ mtr_debug("Stopping IM-main...");
+
mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1);
+ # If necessary, wait for angel process to die.
+
+ if (defined $instance_manager->{'angel_pid'})
+ {
+ mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}");
+ mtr_debug("Waiting for IM-angel to die...");
+
+ my $total_attempts= 10;
+
+ for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt)
+ {
+ unless (kill (0, $instance_manager->{'angel_pid'}))
+ {
+ mtr_debug("IM-angel died.");
+ last;
+ }
+
+ sleep(1);
+ }
+ }
+
# Check that all processes died.
my $clean_shutdown= 0;
while (1)
{
- last if kill (0, $instance_manager->{'pid'});
+ if (kill (0, $instance_manager->{'pid'}))
+ {
+ mtr_debug("IM-main is still alive.");
+ last;
+ }
- last if (defined $instance_manager->{'angel_pid'}) &&
- kill (0, $instance_manager->{'angel_pid'});
+ if (defined $instance_manager->{'angel_pid'} &&
+ kill (0, $instance_manager->{'angel_pid'}))
+ {
+ mtr_debug("IM-angel is still alive.");
+ last;
+ }
foreach my $pid (@mysqld_pids)
{
- last if kill (0, $pid);
+ if (kill (0, $pid))
+ {
+ mtr_debug("Guarded mysqld ($pid) is still alive.");
+ last;
+ }
}
$clean_shutdown= 1;
@@ -2869,15 +2922,21 @@ sub im_stop($) {
unless ($clean_shutdown)
{
- mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
- if defined $instance_manager->{'angel_pid'};
+
+ if (defined $instance_manager->{'angel_pid'})
+ {
+ mtr_debug("Killing IM-angel...");
+ mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
+ }
+ mtr_debug("Killing IM-main...");
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_debug("Killing guarded mysqld(s)...");
mtr_kill_processes(\@mysqld_pids);
# Complain in error log so that a warning will be shown.
@@ -3403,17 +3462,8 @@ sub valgrind_arguments {
mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
if -f "$glob_mysql_test_dir/valgrind.supp";
- if ( $opt_valgrind_all )
- {
- mtr_add_arg($args, "-v");
- mtr_add_arg($args, "--show-reachable=yes");
- }
-
- if ( $opt_valgrind_options )
- {
- mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
- }
-
+ # Add valgrind options, can be overriden by user
+ mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
mtr_add_arg($args, $$exe);
@@ -3428,6 +3478,13 @@ sub valgrind_arguments {
##############################################################################
sub usage ($) {
+ my $message= shift;
+
+ if ( $message )
+ {
+ print STDERR "$message \n";
+ }
+
print STDERR <<HERE;
mysql-test-run [ OPTIONS ] [ TESTCASE ]
@@ -3506,12 +3563,12 @@ Options for coverage, profiling etc
gcov FIXME
gprof FIXME
- valgrind Run the "mysqltest" and "mysqld" executables using valgrind
- valgrind-all Same as "valgrind" but will also add "verbose" and "--show-reachable"
- flags to valgrind
+ valgrind Run the "mysqltest" and "mysqld" executables using
+ valgrind with options($default_valgrind_options)
+ valgrind-all Synonym for --valgrind
valgrind-mysqltest Run the "mysqltest" executable with valgrind
valgrind-mysqld Run the "mysqld" executable with valgrind
- valgrind-options=ARGS Extra options to give valgrind
+ valgrind-options=ARGS Options to give valgrind, replaces default options
valgrind-path=[EXE] Path to the valgrind executable
Misc options
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 88bb3126fb6..3be1cdcf15a 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -6254,6 +6254,7 @@ auto fld1 companynr fld3 fld4 fld5 fld6
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
DELETE FROM t2;
+ERROR HY000: Table storage engine for 't2' doesn't have this option
SELECT * FROM t2;
auto fld1 companynr fld3 fld4 fld5 fld6
1 000001 00 Omaha teethe neat
@@ -8685,6 +8686,7 @@ auto fld1 companynr fld3 fld4 fld5 fld6
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
TRUNCATE TABLE t2;
+ERROR HY000: Table storage engine for 't2' doesn't have this option
SELECT * FROM t2;
auto fld1 companynr fld3 fld4 fld5 fld6
1 000001 00 Omaha teethe neat
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index b12c73f8cca..3797af11a11 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -378,6 +378,28 @@ t1 CREATE TABLE `t1` (
KEY `t1_name` (`t1_name`)
) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1
DROP TABLE `t1`;
+create table t1(a int not null auto_increment primary key);
+create table t2(a int not null auto_increment primary key, t1a int);
+insert into t1 values(NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+select * from t2;
+a t1a
+1 1
+2 1
+3 2
+4 2
+5 2
+6 3
+7 3
+8 3
+9 3
+drop table t1, t2;
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);
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index af6319afe99..588644a6c66 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -1928,4 +1928,38 @@ create table t1 (a int) engine=bdb;
commit;
alter table t1 add primary key(a);
drop table t1;
+set autocommit=1;
+reset master;
+create table bug16206 (a int) engine= blackhole;
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+show binlog events;
+Log_name Pos Event_type Server_id End_log_pos Info
+f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
+f n Query 1 n use `test`; create table bug16206 (a int) engine= blackhole
+f n Query 1 n use `test`; insert into bug16206 values(1)
+f n Query 1 n use `test`; insert into bug16206 values(2)
+drop table bug16206;
+reset master;
+create table bug16206 (a int) engine= bdb;
+insert into bug16206 values(0);
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+insert into bug16206 values(3);
+show binlog events;
+Log_name Pos Event_type Server_id End_log_pos Info
+f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
+f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb
+f n Query 1 n use `test`; insert into bug16206 values(0)
+f n Query 1 n use `test`; insert into bug16206 values(1)
+f n Query 1 n use `test`; BEGIN
+f n Query 1 n use `test`; insert into bug16206 values(2)
+f n Query 1 n use `test`; COMMIT
+f n Query 1 n use `test`; insert into bug16206 values(3)
+drop table bug16206;
+set autocommit=0;
End of 5.0 tests
diff --git a/mysql-test/r/create_not_windows.result b/mysql-test/r/create_not_windows.result
new file mode 100644
index 00000000000..b975c98c2b1
--- /dev/null
+++ b/mysql-test/r/create_not_windows.result
@@ -0,0 +1,14 @@
+drop table if exists `about:text`;
+create table `about:text` (
+_id int not null auto_increment,
+`about:text` varchar(255) not null default '',
+primary key (_id)
+);
+show create table `about:text`;
+Table Create Table
+about:text CREATE TABLE `about:text` (
+ `_id` int(11) NOT NULL auto_increment,
+ `about:text` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table `about:text`;
diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result
index d1976a516d2..dab5991b505 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_utf8.result b/mysql-test/r/ctype_utf8.result
index d745de43f3e..991d1711a9e 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1112,6 +1112,46 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+SET NAMES utf8;
+CREATE TABLE t1 (id int PRIMARY KEY,
+a varchar(16) collate utf8_unicode_ci NOT NULL default '',
+b int,
+f varchar(128) default 'XXX',
+INDEX (a(4))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t1(id, a, b) VALUES
+(1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30),
+(4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40),
+(7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50),
+(10, 'eeeee', 40), (11, 'bbbbbb', 60);
+SELECT id, a, b FROM t1;
+id a b
+1 cccc 50
+2 cccc 70
+3 cccc 30
+4 cccc 30
+5 cccc 20
+6 bbbbbb 40
+7 dddd 30
+8 aaaa 10
+9 aaaa 50
+10 eeeee 40
+11 bbbbbb 60
+SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb';
+id a b
+8 aaaa 10
+9 aaaa 50
+6 bbbbbb 40
+11 bbbbbb 60
+SELECT id, a FROM t1 WHERE a='bbbbbb';
+id a
+6 bbbbbb
+11 bbbbbb
+SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
+id a
+6 bbbbbb
+11 bbbbbb
+DROP TABLE t1;
CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa');
SELECT id FROM t1;
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index f8ae61b03fb..a336f3b4108 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -39,3 +39,33 @@ select * from t1;
a
1
drop table t1;
+CREATE TABLE t1 ( a int(10) NOT NULL auto_increment, PRIMARY KEY (a));
+insert delayed into t1 values(null);
+insert into t1 values(null);
+insert into t1 values(null);
+insert delayed into t1 values(null);
+insert delayed into t1 values(null);
+insert delayed into t1 values(null);
+insert into t1 values(null);
+insert into t1 values(null);
+insert into t1 values(null);
+delete from t1 where a=6;
+insert delayed into t1 values(null);
+insert delayed into t1 values(null);
+insert delayed into t1 values(null);
+insert delayed into t1 values(null);
+select * from t1 order by a;
+a
+1
+2
+3
+4
+5
+7
+8
+9
+10
+11
+12
+13
+DROP TABLE t1;
diff --git a/mysql-test/r/fulltext_left_join.result b/mysql-test/r/fulltext_left_join.result
index f3dad290525..68a424fa3a5 100644
--- a/mysql-test/r/fulltext_left_join.result
+++ b/mysql-test/r/fulltext_left_join.result
@@ -50,3 +50,20 @@ venue_id venue_text dt name entity_id
1 a1 2003-05-23 19:30:00 aberdeen town hall 1
NULL a2 2003-05-23 19:30:00 NULL NULL
drop table t1,t2;
+create table t1 (id int not null primary key, d char(200) not null, e char(200));
+insert into t1 values (1, 'aword', null), (2, 'aword', 'bword'), (3, 'bword', null), (4, 'bword', 'aword'), (5, 'aword and bword', null);
+select * from t1 where match(d, e) against ('+aword +bword' in boolean mode);
+id d e
+2 aword bword
+4 bword aword
+5 aword and bword NULL
+create table t2 (m_id int not null, f char(200), key (m_id));
+insert into t2 values (1, 'bword'), (3, 'aword'), (5, '');
+select * from t1 left join t2 on m_id = id where match(d, e, f) against ('+aword +bword' in boolean mode);
+id d e m_id f
+1 aword NULL 1 bword
+2 aword bword NULL NULL
+3 bword NULL 3 aword
+4 bword aword NULL NULL
+5 aword and bword NULL 5
+drop table t1,t2;
diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result
index 0bd53b32dd7..66808afd4e9 100644
--- a/mysql-test/r/func_concat.result
+++ b/mysql-test/r/func_concat.result
@@ -68,3 +68,17 @@ select 'a' union select concat('a', -0.0000);
a
a
a0.0000
+select concat((select x from (select 'a' as x) as t1 ),
+(select y from (select 'b' as y) as t2 )) from (select 1 union select 2 )
+as t3;
+concat((select x from (select 'a' as x) as t1 ),
+(select y from (select 'b' as y) as t2 ))
+ab
+ab
+create table t1(f1 varchar(6)) charset=utf8;
+insert into t1 values ("123456");
+select concat(f1, 2) a from t1 union select 'x' a from t1;
+a
+1234562
+x
+drop table t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 1542794798a..f693c6190d5 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -821,6 +821,41 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
MAX(id)
NULL
DROP TABLE t1;
+CREATE TABLE t1 (id int PRIMARY KEY, b char(3), INDEX(b));
+INSERT INTO t1 VALUES (1,'xx'), (2,'aa');
+SELECT * FROM t1;
+id b
+1 xx
+2 aa
+SELECT MAX(b) FROM t1 WHERE b < 'ppppp';
+MAX(b)
+aa
+SHOW WARNINGS;
+Level Code Message
+SELECT MAX(b) FROM t1 WHERE b < 'pp';
+MAX(b)
+aa
+DROP TABLE t1;
+CREATE TABLE t1 (id int PRIMARY KEY, b char(16), INDEX(b(4)));
+INSERT INTO t1 VALUES (1, 'xxxxbbbb'), (2, 'xxxxaaaa');
+SELECT MAX(b) FROM t1;
+MAX(b)
+xxxxbbbb
+EXPLAIN SELECT MAX(b) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+DROP TABLE t1;
+CREATE TABLE t1 (id int , b varchar(512), INDEX(b(250))) COLLATE latin1_bin;
+INSERT INTO t1 VALUES
+(1,CONCAT(REPEAT('_', 250), "qq")), (1,CONCAT(REPEAT('_', 250), "zz")),
+(1,CONCAT(REPEAT('_', 250), "aa")), (1,CONCAT(REPEAT('_', 250), "ff"));
+SELECT MAX(b) FROM t1;
+MAX(b)
+__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________zz
+EXPLAIN SELECT MAX(b) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+DROP TABLE t1;
create table t2 (ff double);
insert into t2 values (2.2);
select cast(sum(distinct ff) as decimal(5,2)) from t2;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index a17661d26d0..1485809ba70 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1023,6 +1023,21 @@ NULL
select ifnull(load_file("lkjlkj"),"it's null");
ifnull(load_file("lkjlkj"),"it's null")
it's null
+create table t1 (f1 varchar(4), f2 varchar(64), unique key k1 (f1,f2));
+insert into t1 values ( 'test',md5('test')), ('test', sha('test'));
+select * from t1 where f1='test' and (f2= md5("test") or f2= md5("TEST"));
+f1 f2
+test 098f6bcd4621d373cade4e832627b4f6
+select * from t1 where f1='test' and (f2= md5("TEST") or f2= md5("test"));
+f1 f2
+test 098f6bcd4621d373cade4e832627b4f6
+select * from t1 where f1='test' and (f2= sha("test") or f2= sha("TEST"));
+f1 f2
+test a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
+select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test"));
+f1 f2
+test a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
+drop table t1;
End of 4.1 tests
create table t1 (d decimal default null);
insert into t1 values (null);
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 0e029802555..aaa86378626 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2,t3;
+set time_zone="+03:00";
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
from_days(to_days("960101")) to_days(960201)-to_days("19960101") to_days(date_add(curdate(), interval 1 day))-to_days(curdate()) weekday("1997-11-29")
1996-01-01 31 1 5
@@ -7,20 +8,20 @@ period_add("9602",-12) period_diff(199505,"9404")
199502 13
select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now());
now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(now())
-0 0 0
+0.000000 0 0
select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0;
from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0
-1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112
+1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112.000000
select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"),
sec_to_time(time_to_sec("0:30:47")/6.21);
sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(time_to_sec("0:30:47")/6.21)
-02:30:01 23001 54742 00:04:57
+02:30:01 23001.000000 54742 00:04:57
select sec_to_time(time_to_sec('-838:59:59'));
sec_to_time(time_to_sec('-838:59:59'))
-838:59:59
select now()-curdate()*1000000-curtime();
now()-curdate()*1000000-curtime()
-0
+0.000000
select strcmp(current_timestamp(),concat(current_date()," ",current_time()));
strcmp(current_timestamp(),concat(current_date()," ",current_time()))
0
@@ -751,6 +752,60 @@ 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
+create table t1(f1 date, f2 time, f3 datetime);
+insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01");
+insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02");
+select f1 from t1 where f1 between "2006-1-1" and 20060101;
+f1
+2006-01-01
+select f1 from t1 where f1 between "2006-1-1" and "2006.1.1";
+f1
+2006-01-01
+select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1";
+f1
+2006-01-01
+select f2 from t1 where f2 between "12:1:2" and "12:2:2";
+f2
+12:01:02
+select f2 from t1 where time(f2) between "12:1:2" and "12:2:2";
+f2
+12:01:02
+select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+f3
+2006-01-01 12:01:01
+select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+f3
+2006-01-01 12:01:01
+select f1 from t1 where "2006-1-1" between f1 and f3;
+f1
+2006-01-01
+select f1 from t1 where "2006-1-1" between date(f1) and date(f3);
+f1
+2006-01-01
+select f1 from t1 where "2006-1-1" between f1 and 'zzz';
+f1
+Warnings:
+Warning 1292 Incorrect date value: 'zzz' for column 'f1' at row 1
+Warning 1292 Truncated incorrect DOUBLE value: 'zzz'
+Warning 1292 Truncated incorrect DOUBLE value: 'zzz'
+select f1 from t1 where makedate(2006,1) between date(f1) and date(f3);
+f1
+2006-01-01
+select f1 from t1 where makedate(2006,2) between date(f1) and date(f3);
+f1
+2006-01-02
+drop table t1;
+create table t1 select now() - now(), curtime() - curtime(),
+sec_to_time(1) + 0, from_unixtime(1) + 0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `now() - now()` double(23,6) NOT NULL default '0.000000',
+ `curtime() - curtime()` double(23,6) NOT NULL default '0.000000',
+ `sec_to_time(1) + 0` double(23,6) default NULL,
+ `from_unixtime(1) + 0` double(23,6) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+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
@@ -891,3 +946,4 @@ id day id day
1 2005-06-01 3 2005-07-15
3 2005-07-01 3 2005-07-15
DROP TABLE t1,t2;
+set time_zone= @@global.time_zone;
diff --git a/mysql-test/r/func_timestamp.result b/mysql-test/r/func_timestamp.result
index d9912f08b72..495fedea9e6 100644
--- a/mysql-test/r/func_timestamp.result
+++ b/mysql-test/r/func_timestamp.result
@@ -1,4 +1,5 @@
drop table if exists t1;
+set time_zone="+03:00";
create table t1 (Zeit time, Tag tinyint not null, Monat tinyint not null,
Jahr smallint not null, index(Tag), index(Monat), index(Jahr) );
insert into t1 values ("09:26:00",16,9,1998),("09:26:00",16,9,1998);
@@ -9,3 +10,4 @@ Date Unix
1998-9-16 09:26:00 905927160
1998-9-16 09:26:00 905927160
drop table t1;
+set time_zone= @@global.time_zone;
diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result
index d0a76b450fe..ea27fcb6db1 100644
--- a/mysql-test/r/im_daemon_life_cycle.result
+++ b/mysql-test/r/im_daemon_life_cycle.result
@@ -1,3 +1,4 @@
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result
index 36277f6aa28..a9f78aea7d3 100644
--- a/mysql-test/r/im_life_cycle.result
+++ b/mysql-test/r/im_life_cycle.result
@@ -1,44 +1,45 @@
+
+--------------------------------------------------------------------
+-- 1.1.1.
+--------------------------------------------------------------------
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 offline VERSION
+
+--------------------------------------------------------------------
+-- 1.1.2.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 online VERSION
+Success: the process has been started.
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
-mysqld1 online
-mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version
-mysqld1 online VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version
-mysqld2 offline VERSION
+Success: the process has been stopped.
+
+--------------------------------------------------------------------
+-- 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
mysqld1 online
@@ -50,20 +51,25 @@ SHOW INSTANCES;
instance_name status
mysqld1 online
mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.7.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
+Success: the process has been started.
Killing the process...
Sleeping...
Success: the process was killed.
-SHOW INSTANCES;
-instance_name status
-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_utils.result b/mysql-test/r/im_utils.result
index fbfaeaebcac..e6a5e007ed4 100644
--- a/mysql-test/r/im_utils.result
+++ b/mysql-test/r/im_utils.result
@@ -1,3 +1,4 @@
+Success: the process has been started.
SHOW INSTANCES;
instance_name status
mysqld1 online
@@ -42,7 +43,9 @@ skip-innodb VALUE
skip-bdb VALUE
skip-ndbcluster VALUE
START INSTANCE mysqld2;
+Success: the process has been started.
STOP INSTANCE mysqld2;
+Success: the process has been stopped.
SHOW mysqld1 LOG FILES;
Logfile Path File size
ERROR LOG PATH FILE_SIZE
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index e2d265d7ab9..6da07922251 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -866,58 +866,62 @@ grant select (f1) on mysqltest.t1 to user1@localhost;
grant select on mysqltest.t2 to user2@localhost;
grant select on mysqltest.* to user3@localhost;
grant select on *.* to user4@localhost;
-select * from information_schema.column_privileges;
+select * from information_schema.column_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
'user1'@'localhost' NULL mysqltest t1 f1 SELECT NO
-select * from information_schema.table_privileges;
+select * from information_schema.table_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.schema_privileges;
+select * from information_schema.schema_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.user_privileges;
+select * from information_schema.user_privileges order by grantee;
GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'user1'@'localhost' NULL USAGE NO
show grants;
Grants for user1@localhost
GRANT USAGE ON *.* TO 'user1'@'localhost'
GRANT SELECT (f1) ON `mysqltest`.`t1` TO 'user1'@'localhost'
-select * from information_schema.column_privileges;
+select * from information_schema.column_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.table_privileges;
+select * from information_schema.table_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
'user2'@'localhost' NULL mysqltest t2 SELECT NO
-select * from information_schema.schema_privileges;
+select * from information_schema.schema_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.user_privileges;
+select * from information_schema.user_privileges order by grantee;
GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'user2'@'localhost' NULL USAGE NO
show grants;
Grants for user2@localhost
GRANT USAGE ON *.* TO 'user2'@'localhost'
GRANT SELECT ON `mysqltest`.`t2` TO 'user2'@'localhost'
-select * from information_schema.column_privileges;
+select * from information_schema.column_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.table_privileges;
+select * from information_schema.table_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
-select * from information_schema.schema_privileges;
+select * from information_schema.schema_privileges order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
'user3'@'localhost' NULL mysqltest SELECT NO
-select * from information_schema.user_privileges;
+select * from information_schema.user_privileges order by grantee;
GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'user3'@'localhost' NULL USAGE NO
show grants;
Grants for user3@localhost
GRANT USAGE ON *.* TO 'user3'@'localhost'
GRANT SELECT ON `mysqltest`.* TO 'user3'@'localhost'
-select * from information_schema.column_privileges where grantee like '%user%';
+select * from information_schema.column_privileges where grantee like '%user%'
+order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
'user1'@'localhost' NULL mysqltest t1 f1 SELECT NO
-select * from information_schema.table_privileges where grantee like '%user%';
+select * from information_schema.table_privileges where grantee like '%user%'
+order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
'user2'@'localhost' NULL mysqltest t2 SELECT NO
-select * from information_schema.schema_privileges where grantee like '%user%';
+select * from information_schema.schema_privileges where grantee like '%user%'
+order by grantee;
GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
'user3'@'localhost' NULL mysqltest SELECT NO
-select * from information_schema.user_privileges where grantee like '%user%';
+select * from information_schema.user_privileges where grantee like '%user%'
+order by grantee;
GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'user1'@'localhost' NULL USAGE NO
'user2'@'localhost' NULL USAGE NO
@@ -1121,3 +1125,12 @@ 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;
+set @a:= '.';
+create table t1(f1 char(5));
+create table t2(f1 char(5));
+select concat(@a, table_name), @a, table_name
+from information_schema.tables where table_schema = 'test';
+concat(@a, table_name) @a table_name
+.t1 . t1
+.t2 . t2
+drop table t1,t2;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 00a987c9254..82fad8e912c 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -305,3 +305,29 @@ insert delayed into v1 values (1);
ERROR HY000: 'test.v1' is not BASE TABLE
drop table t1;
drop view v1;
+create table t1 (id int primary key, data int);
+insert into t1 values (1, 1), (2, 2), (3, 3);
+select row_count();
+row_count()
+3
+insert ignore into t1 values (1, 1);
+select row_count();
+row_count()
+0
+replace into t1 values (1, 11);
+select row_count();
+row_count()
+2
+replace into t1 values (4, 4);
+select row_count();
+row_count()
+1
+insert into t1 values (2, 2) on duplicate key update data= data + 10;
+select row_count();
+row_count()
+2
+insert into t1 values (5, 5) on duplicate key update data= data + 10;
+select row_count();
+row_count()
+1
+drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 434dddb3049..49d9c3594db 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -686,3 +686,12 @@ ERROR 42S22: Unknown column 'z' in 'field list'
insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x);
ERROR 42S22: Unknown column 't2.x' in 'field list'
drop table t1,t2;
+CREATE TABLE t1 (a int PRIMARY KEY);
+INSERT INTO t1 values (1), (2);
+INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1;
+DROP TABLE t1;
+CREATE TABLE t1 (x int, y int);
+CREATE TABLE t2 (z int, y int);
+CREATE TABLE t3 (a int, b int);
+INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1);
+DROP TABLE IF EXISTS t1,t2,t3;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 86288caf398..48b7730481f 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -744,3 +744,23 @@ select a2 from ((t1 natural join t2) join t3 on b=c1) natural join t4;
a2
1
drop table t1,t2,t3,t4;
+create table t1 (c int, b int);
+create table t2 (a int, b int);
+create table t3 (b int, c int);
+create table t4 (y int, c int);
+create table t5 (y int, z int);
+insert into t1 values (3,2);
+insert into t2 values (1,2);
+insert into t3 values (2,3);
+insert into t4 values (1,3);
+insert into t5 values (1,4);
+prepare stmt1 from "select * from ((t3 natural join (t1 natural join t2))
+natural join t4) natural join t5";
+execute stmt1;
+y c b a z
+1 3 2 1 4
+select * from ((t3 natural join (t1 natural join t2)) natural join t4)
+natural join t5;
+y c b a z
+1 3 2 1 4
+drop table t1, t2, t3, t4, t5;
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index bc9d3935bc4..a6f05143b3e 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -330,6 +330,16 @@ alter table t1 add key (c1,c1,c2);
ERROR 42S21: Duplicate column name 'c1'
drop table t1;
create table t1 (
+i1 INT NOT NULL,
+i2 INT NOT NULL,
+UNIQUE i1idx (i1),
+UNIQUE i2idx (i2));
+desc t1;
+Field Type Null Key Default Extra
+i1 int(11) NO UNI
+i2 int(11) NO UNI
+drop table t1;
+create table t1 (
c1 int,
c2 varchar(20) not null,
primary key (c1),
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index 89428ed6a9b..2188d58e526 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -43,6 +43,14 @@ Field Type Null Key Default Extra
a int(11) YES NULL
unlock tables;
drop table t1;
+CREATE DATABASE mysqltest_1;
+FLUSH TABLES WITH READ LOCK;
+ DROP DATABASE mysqltest_1;
+DROP DATABASE mysqltest_1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+UNLOCK TABLES;
+DROP DATABASE mysqltest_1;
+ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist
use mysql;
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
FLUSH TABLES;
@@ -59,3 +67,9 @@ Select_priv
N
use test;
use test;
+create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
+lock tables t1 write;
+ alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+ alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result
index 44235cbf900..e369fb7e482 100644
--- a/mysql-test/r/lowercase_table2.result
+++ b/mysql-test/r/lowercase_table2.result
@@ -165,3 +165,12 @@ create table t1Aa (col1 int);
select t1Aa.col1 from t1aA,t2Aa where t1Aa.col1 = t2aA.col1;
col1
drop table t2aA, t1Aa;
+create database mysqltest_LC2;
+use mysqltest_LC2;
+create table myUC (i int);
+select TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES
+where TABLE_SCHEMA ='mysqltest_LC2';
+TABLE_SCHEMA TABLE_NAME
+mysqltest_LC2 myUC
+use test;
+drop database mysqltest_LC2;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 9a34d6fba58..568f83b7d6d 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -776,3 +776,9 @@ 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;
+create table t1 (b bit(1));
+create table t2 (b bit(1));
+create table tm (b bit(1)) engine = merge union = (t1,t2);
+select * from tm;
+b
+drop table tm, t1, t2;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index ea02a703c65..b4a7aa5cb76 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -476,6 +476,11 @@ aclid bigint, index idx_acl(aclid)
insert into t2 values(1,null);
delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1';
drop table t1, t2;
+create table t1(a int);
+create table t2(a int);
+delete from t1,t2 using t1,t2 where t1.a=(select a from t1);
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
+drop table t1, t2;
create table t1 ( c char(8) not null ) engine=innodb;
insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 14195447b54..780287fb807 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -747,6 +747,27 @@ select count(id1) from t1 where id2 = 10;
count(id1)
5
drop table t1;
+CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(1);
+SELECT MAX(a) FROM t1 IGNORE INDEX(a);
+MAX(a)
+1
+ALTER TABLE t1 DISABLE KEYS;
+SELECT MAX(a) FROM t1;
+MAX(a)
+1
+SELECT MAX(a) FROM t1 IGNORE INDEX(a);
+MAX(a)
+1
+DROP TABLE t1;
+CREATE TABLE t1(a CHAR(9), b VARCHAR(7)) ENGINE=MyISAM;
+INSERT INTO t1(a) VALUES('xxxxxxxxx'),('xxxxxxxxx');
+UPDATE t1 AS ta1,t1 AS ta2 SET ta1.b='aaaaaa',ta2.b='bbbbbb';
+SELECT * FROM t1;
+a b
+xxxxxxxxx bbbbbb
+xxxxxxxxx bbbbbb
+DROP TABLE t1;
set storage_engine=MyISAM;
drop table if exists t1,t2,t3;
--- Testing varchar ---
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index eff46ecc2d6..f9714e067e6 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -1458,7 +1458,6 @@ UNLOCK TABLES;
/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
-/*!50001 DROP TABLE IF EXISTS `v2`*/;
/*!50001 CREATE TABLE `v2` (
`a` varchar(30)
) */;
@@ -1764,7 +1763,6 @@ UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
-/*!50001 DROP TABLE IF EXISTS `v1`*/;
/*!50001 CREATE TABLE `v1` (
`a` int(11)
) */;
@@ -1822,7 +1820,6 @@ UNLOCK TABLES;
/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
-/*!50001 DROP TABLE IF EXISTS `v2`*/;
/*!50001 CREATE TABLE `v2` (
`a` varchar(30)
) */;
@@ -1915,7 +1912,6 @@ UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
-/*!50001 DROP TABLE IF EXISTS `v1`*/;
/*!50001 CREATE TABLE `v1` (
`a` int(11),
`b` int(11),
@@ -1923,13 +1919,11 @@ DROP TABLE IF EXISTS `v1`;
) */;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
-/*!50001 DROP TABLE IF EXISTS `v2`*/;
/*!50001 CREATE TABLE `v2` (
`a` int(11)
) */;
DROP TABLE IF EXISTS `v3`;
/*!50001 DROP VIEW IF EXISTS `v3`*/;
-/*!50001 DROP TABLE IF EXISTS `v3`*/;
/*!50001 CREATE TABLE `v3` (
`a` int(11),
`b` int(11),
@@ -2490,7 +2484,6 @@ UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
DROP TABLE IF EXISTS `v0`;
/*!50001 DROP VIEW IF EXISTS `v0`*/;
-/*!50001 DROP TABLE IF EXISTS `v0`*/;
/*!50001 CREATE TABLE `v0` (
`a` int(11),
`b` varchar(32),
@@ -2498,7 +2491,6 @@ DROP TABLE IF EXISTS `v0`;
) */;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
-/*!50001 DROP TABLE IF EXISTS `v1`*/;
/*!50001 CREATE TABLE `v1` (
`a` int(11),
`b` varchar(32),
@@ -2506,16 +2498,11 @@ DROP TABLE IF EXISTS `v1`;
) */;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
-/*!50001 DROP TABLE IF EXISTS `v2`*/;
/*!50001 CREATE TABLE `v2` (
`a` int(11),
`b` varchar(32),
`c` varchar(32)
) */;
-
-CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
-
-USE `test`;
/*!50001 DROP TABLE IF EXISTS `v0`*/;
/*!50001 DROP VIEW IF EXISTS `v0`*/;
/*!50001 CREATE ALGORITHM=UNDEFINED */
@@ -2756,6 +2743,25 @@ end AFTER # root@localhost
drop trigger tr1;
drop trigger tr2;
drop table t1, t2;
+create table t (qty int, price int);
+insert into t values(3, 50);
+insert into t values(5, 51);
+create view v1 as select qty, price, qty*price as value from t;
+create view v2 as select qty from v1;
+mysqldump {
+/*!50001 CREATE ALGORITHM=UNDEFINED */
+/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
+/*!50001 VIEW `v1` AS select `t`.`qty` AS `qty`,`t`.`price` AS `price`,(`t`.`qty` * `t`.`price`) AS `value` from `t` */;
+
+} mysqldump {
+/*!50001 CREATE ALGORITHM=UNDEFINED */
+/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
+/*!50001 VIEW `v2` AS select `v1`.`qty` AS `qty` from `v1` */;
+
+} mysqldump
+drop view v1;
+drop view v2;
+drop table t;
/*!50003 CREATE FUNCTION `f`() RETURNS bigint(20)
return 42 */|
/*!50003 CREATE PROCEDURE `p`()
@@ -2770,3 +2776,71 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
select 42
drop function f;
drop procedure p;
+create table t1 ( id serial );
+create view v1 as select * from t1;
+drop table t1;
+mysqldump {
+
+-- failed on view `v1`: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`t1`.`id` AS `id` from `t1`
+
+} mysqldump
+drop view v1;
+create database mysqldump_test_db;
+use mysqldump_test_db;
+create table t1 (id int);
+create view v1 as select * from t1;
+insert into t1 values (1232131);
+insert into t1 values (4711);
+insert into t1 values (3231);
+insert into t1 values (0815);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+/*!40000 DROP DATABASE IF EXISTS `mysqldump_test_db`*/;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `mysqldump_test_db`;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `id` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1232131),(4711),(3231),(815);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+DROP TABLE IF EXISTS `v1`;
+/*!50001 DROP VIEW IF EXISTS `v1`*/;
+/*!50001 CREATE TABLE `v1` (
+ `id` int(11)
+) */;
+/*!50001 DROP TABLE IF EXISTS `v1`*/;
+/*!50001 DROP VIEW IF EXISTS `v1`*/;
+/*!50001 CREATE ALGORITHM=UNDEFINED */
+/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
+/*!50001 VIEW `v1` AS select `t1`.`id` AS `id` from `t1` */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop view v1;
+drop table t1;
+drop database mysqldump_test_db;
diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result
index 27a510b252f..4e5597a4851 100644
--- a/mysql-test/r/ndb_condition_pushdown.result
+++ b/mysql-test/r/ndb_condition_pushdown.result
@@ -1842,5 +1842,29 @@ a b
select * from t1 where b like 'abc' or b like 'abc';
a b
3 abc
+drop table t1;
+create table t1 ( fname varchar(255), lname varchar(255) )
+engine=ndbcluster;
+insert into t1 values ("Young","Foo");
+set engine_condition_pushdown = 0;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+fname lname
+Young Foo
+set engine_condition_pushdown = 1;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+fname lname
+Young Foo
+insert into t1 values ("aaa", "aaa");
+insert into t1 values ("bbb", "bbb");
+insert into t1 values ("ccc", "ccc");
+insert into t1 values ("ddd", "ddd");
+set engine_condition_pushdown = 0;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+fname lname
+Young Foo
+set engine_condition_pushdown = 1;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+fname lname
+Young Foo
set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5;
diff --git a/mysql-test/r/ndb_loaddatalocal.result b/mysql-test/r/ndb_loaddatalocal.result
new file mode 100644
index 00000000000..1d15c608f03
--- /dev/null
+++ b/mysql-test/r/ndb_loaddatalocal.result
@@ -0,0 +1,46 @@
+DROP TABLE IF EXISTS t1;
+create table t1(a int) engine=myisam;
+select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int) engine=ndb;
+load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+select count(*) from t1;
+count(*)
+10000
+drop table t1;
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (2), (2), (3);
+select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int primary key) engine=ndb;
+load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+select * from t1 order by a;
+a
+1
+2
+3
+drop table t1;
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (1), (2), (3);
+select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int primary key) engine=ndb;
+load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+select * from t1 order by a;
+a
+1
+2
+3
+drop table t1;
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (2), (3), (3);
+select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int primary key) engine=ndb;
+load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+select * from t1 order by a;
+a
+1
+2
+3
+drop table t1;
diff --git a/mysql-test/r/ndb_lock.result b/mysql-test/r/ndb_lock.result
index b8c2c58aac4..3b433023843 100644
--- a/mysql-test/r/ndb_lock.result
+++ b/mysql-test/r/ndb_lock.result
@@ -63,3 +63,83 @@ pk u o
5 5 5
insert into t1 values (1,1,1);
drop table t1;
+create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
+insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
+begin;
+select * from t1 where x = 1 for update;
+x y z
+1 one 1
+begin;
+select * from t1 where x = 2 for update;
+x y z
+2 two 2
+select * from t1 where x = 1 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+begin;
+select * from t1 where y = 'one' or y = 'three' order by x for update;
+x y z
+1 one 1
+3 three 3
+begin;
+select * from t1 where x = 1 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+begin;
+select * from t1 where z > 1 and z < 3 for update;
+x y z
+2 two 2
+begin;
+select * from t1 where x = 1 for update;
+x y z
+1 one 1
+select * from t1 where x = 2 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+begin;
+select * from t1 where x = 1 lock in share mode;
+x y z
+1 one 1
+begin;
+select * from t1 where x = 1 lock in share mode;
+x y z
+1 one 1
+select * from t1 where x = 2 for update;
+x y z
+2 two 2
+select * from t1 where x = 1 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+begin;
+select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
+x y z
+1 one 1
+3 three 3
+begin;
+select * from t1 where y = 'one' lock in share mode;
+x y z
+1 one 1
+select * from t1 where x = 1 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+begin;
+select * from t1 where z > 1 and z < 3 lock in share mode;
+x y z
+2 two 2
+begin;
+select * from t1 where z = 1 lock in share mode;
+x y z
+1 one 1
+select * from t1 where x = 1 for update;
+x y z
+1 one 1
+select * from t1 where x = 2 for update;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+commit;
+drop table t1;
diff --git a/mysql-test/r/ndb_replace.result b/mysql-test/r/ndb_replace.result
index 5d772620b2c..cdfcd6a7a43 100644
--- a/mysql-test/r/ndb_replace.result
+++ b/mysql-test/r/ndb_replace.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
CREATE TABLE t1 (
gesuchnr int(11) DEFAULT '0' NOT NULL,
benutzer_id int(11) DEFAULT '0' NOT NULL,
@@ -31,3 +31,24 @@ SELECT * from t1 ORDER BY i;
i j k
3 1 42
17 2 24
+CREATE TABLE t2 (a INT(11) NOT NULL,
+b INT(11) NOT NULL,
+c INT(11) NOT NULL,
+x TEXT,
+y TEXT,
+z TEXT,
+id INT(10) unsigned NOT NULL AUTO_INCREMENT,
+i INT(11) DEFAULT NULL,
+PRIMARY KEY (id),
+UNIQUE KEY a (a,b,c)
+) ENGINE=ndbcluster;
+REPLACE INTO t2 (a,b,c,x,y,z,i) VALUES (1,1,1,'a','a','a',1),(1,1,1,'b','b','b',2), (1,1,1,'c','c','c',3);
+SELECT * FROM t2 ORDER BY id;
+a b c x y z id i
+1 1 1 c c c 3 3
+REPLACE INTO t2(a,b,c,x,y,z,i) values (1,1,1,'a','a','a',1);
+REPLACE INTO t2(a,b,c,x,y,z,i) values (1,1,1,'b','b','b',2);
+SELECT * FROM t2 ORDER BY id;
+a b c x y z id i
+1 1 1 b b b 5 2
+DROP TABLE t2;
diff --git a/mysql-test/r/ndb_truncate.result b/mysql-test/r/ndb_truncate.result
index 38f3a78029c..811e5e3afeb 100644
--- a/mysql-test/r/ndb_truncate.result
+++ b/mysql-test/r/ndb_truncate.result
@@ -1,14 +1,23 @@
-DROP TABLE IF EXISTS t2;
-CREATE TABLE t2 (
-a bigint unsigned NOT NULL PRIMARY KEY,
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+a bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
b int unsigned not null,
c int unsigned
) engine=ndbcluster;
-select count(*) from t2;
+select count(*) from t1;
count(*)
5000
-truncate table t2;
-select count(*) from t2;
+select * from t1 order by a limit 2;
+a b c
+1 509 2500
+2 510 7
+truncate table t1;
+select count(*) from t1;
count(*)
0
-drop table t2;
+insert into t1 values(NULL,1,1),(NULL,2,2);
+select * from t1 order by a;
+a b c
+1 1 1
+2 2 2
+drop table t1;
diff --git a/mysql-test/r/replace.result b/mysql-test/r/replace.result
index a7d59fcfa62..5a5e4571ba9 100644
--- a/mysql-test/r/replace.result
+++ b/mysql-test/r/replace.result
@@ -24,3 +24,9 @@ a b
63 default_value
127 last
drop table t1;
+CREATE TABLE t1 (f1 INT);
+CREATE VIEW v1 AS SELECT f1 FROM t1 WHERE f1 = 0 WITH CHECK OPTION;
+REPLACE INTO v1 (f1) VALUES (1);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+DROP TABLE t1;
+DROP VIEW v1;
diff --git a/mysql-test/r/rpl_auto_increment_11932.result b/mysql-test/r/rpl_auto_increment_11932.result
new file mode 100644
index 00000000000..25eda6ee454
--- /dev/null
+++ b/mysql-test/r/rpl_auto_increment_11932.result
@@ -0,0 +1,47 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop database if exists test1;
+create database test1;
+use test1;
+CREATE TABLE `t1` (
+`id` int(10) unsigned NOT NULL auto_increment,
+`fname` varchar(100) default NULL,
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+INSERT INTO `t1` VALUES (1, 'blablabla');
+CREATE TABLE `t2` (
+`id` int(10) NOT NULL auto_increment,
+`comment` varchar(255) NOT NULL default '',
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 ;
+INSERT INTO `t2` VALUES (1, 'testtest 1');
+INSERT INTO `t2` VALUES (2, 'test 2');
+CREATE PROCEDURE simpleproc3 ()
+NOT DETERMINISTIC
+BEGIN
+INSERT INTO t1 (fname) (SELECT t2.comment FROM t2 WHERE t2.id = '1');
+INSERT INTO t1 (fname) VALUES('test');
+END
+$
+CALL simpleproc3();
+select * from t2;
+id comment
+1 testtest 1
+2 test 2
+TRUNCATE TABLE `t1`;
+CALL simpleproc3();
+select * from t1;
+id fname
+1 testtest 1
+2 test
+use test1;
+select * from t1;
+id fname
+1 testtest 1
+2 test
+drop database test1;
+drop database test1;
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 93c2cac3bec..6ee0eb283b5 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -101,3 +101,20 @@ Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File
# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 510 # # master-bin.000002 Yes Yes 0 0 510 # None 0 No #
show binlog events in 'slave-bin.000005' from 4;
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
+create table t1(a int auto_increment primary key, b int);
+insert into t1 values (NULL, 1);
+reset master;
+set insert_id=5;
+insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id());
+show binlog events;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 4 Format_desc 2 98 Server ver: VERSION, Binlog ver: 4
+slave-bin.000001 98 Intvar 2 126 LAST_INSERT_ID=1
+slave-bin.000001 126 Intvar 2 154 INSERT_ID=5
+slave-bin.000001 154 Query 2 289 use `test`; insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id())
+select * from t1;
+a b
+1 1
+5 1
+6 1
+drop table t1;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 86e1a8ada19..e6c590489a0 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2656,16 +2656,6 @@ t11 MyISAM 10 Dynamic 0 0 X X X X X X X X latin1_swedish_ci NULL
select 123 as a from t1 where f1 is null;
a
drop table t1,t11;
-CREATE TABLE t1 (a INT, b INT);
-(SELECT a, b AS c FROM t1) ORDER BY c+1;
-a c
-(SELECT a, b AS c FROM t1) ORDER BY b+1;
-a c
-SELECT a, b AS c FROM t1 ORDER BY c+1;
-a c
-SELECT a, b AS c FROM t1 ORDER BY b+1;
-a c
-drop table t1;
CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL, UNIQUE idx (a,b) );
INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
CREATE TABLE t2 ( a INT NOT NULL, b INT NOT NULL, e INT );
@@ -2716,6 +2706,20 @@ select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 fro
f1 f2
1 1
drop table t1,t2;
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
+where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
+t2.b like '%%' order by t2.b limit 0,1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b,c b 5 const 1 Using where; Using temporary; Using filesort
+1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
+DROP TABLE t1,t2,t3;
CREATE TABLE t1 (a int, INDEX idx(a));
INSERT INTO t1 VALUES (2), (3), (1);
EXPLAIN SELECT * FROM t1 IGNORE INDEX (idx);
@@ -2726,61 +2730,12 @@ ERROR HY000: Key 'a' doesn't exist in table 't1'
EXPLAIN SELECT * FROM t1 FORCE INDEX (a);
ERROR HY000: Key 'a' doesn't exist in table 't1'
DROP TABLE t1;
-CREATE TABLE t1 ( city char(30) );
-INSERT INTO t1 VALUES ('London');
-INSERT INTO t1 VALUES ('Paris');
-SELECT * FROM t1 WHERE city='London';
-city
-London
-SELECT * FROM t1 WHERE city='london';
-city
-London
-EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
-SELECT * FROM t1 WHERE city='London' AND city='london';
-city
-London
-EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
-SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-city
-London
+CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (10);
+SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1;
+i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01')
+0 1 1 1
DROP TABLE t1;
-create table t1 (a int(11) unsigned, b int(11) unsigned);
-insert into t1 values (1,0), (1,1), (1,2);
-select a-b from t1 order by 1;
-a-b
-0
-1
-18446744073709551615
-select a-b , (a-b < 0) from t1 order by 1;
-a-b (a-b < 0)
-0 0
-1 0
-18446744073709551615 0
-select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
-d (a-b >= 0) b
-1 1 0
-0 1 1
-18446744073709551615 1 2
-select cast((a - b) as unsigned) from t1 order by 1;
-cast((a - b) as unsigned)
-0
-1
-18446744073709551615
-drop table t1;
-create table t1 (a int(11));
-select all all * from t1;
-a
-select distinct distinct * from t1;
-a
-select all distinct * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-select distinct all * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-drop table t1;
CREATE TABLE t1 (
K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
@@ -2814,19 +2769,6 @@ WART 0100 1
WART 0200 1
WART 0300 3
DROP TABLE t1;
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 5
-1 SIMPLE t2 ref a a 23 test.t1.a 2
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 5
-1 SIMPLE t2 ref a a 23 test.t1.a 2
-DROP TABLE t1, t2;
create table t1 (a int, b int);
create table t2 like t1;
select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
@@ -2857,29 +2799,6 @@ x
NULL
1.0000
drop table t1;
-create table t1 (a int(11));
-select all all * from t1;
-a
-select distinct distinct * from t1;
-a
-select all distinct * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-select distinct all * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-drop table t1;
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 5
-1 SIMPLE t2 ref a a 23 test.t1.a 2
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 5
-1 SIMPLE t2 ref a a 23 test.t1.a 2
-DROP TABLE t1, t2;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a int);
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
@@ -3456,3 +3375,23 @@ 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;
+create table t1 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c bit not null
+);
+create table t2 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c int unsigned not null,
+d varchar(50)
+);
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+a t1.b + 0 t1.c + 0 a t2.b + 0 c d
+1 0 1 1 0 1 NULL
+2 0 1 NULL NULL NULL NULL
+drop table t1,t2;
diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result
index 2335513b28a..7d8dd862748 100644
--- a/mysql-test/r/sp-prelocking.result
+++ b/mysql-test/r/sp-prelocking.result
@@ -237,3 +237,21 @@ deallocate prepare stmt;
drop table t1;
drop view v1, v2, v3;
drop function bug15683;
+drop table if exists t1, t2, t3;
+drop function if exists bug19634;
+create table t1 (id int, data int);
+create table t2 (id int);
+create table t3 (data int);
+create function bug19634() returns int return (select count(*) from t3);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop function bug19634;
+drop table t1, t2, t3;
+End of 5.0 tests
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index a2b36b11a2e..96bf2f01f86 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -5036,4 +5036,25 @@ mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET utf8 */
drop database mysqltest1|
drop database mysqltest2|
use test|
+drop table if exists t3|
+drop procedure if exists bug15217|
+create table t3 as select 1|
+create procedure bug15217()
+begin
+declare var1 char(255);
+declare cur1 cursor for select * from t3;
+open cur1;
+fetch cur1 into var1;
+select concat('data was: /', var1, '/');
+close cur1;
+end |
+call bug15217()|
+concat('data was: /', var1, '/')
+data was: /1/
+flush tables |
+call bug15217()|
+concat('data was: /', var1, '/')
+data was: /1/
+drop table t3|
+drop procedure bug15217|
drop table t1,t2;
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index b05680f9c54..474659f7dfc 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -485,6 +485,10 @@ set sql_mode=2097152;
select @@sql_mode;
@@sql_mode
STRICT_TRANS_TABLES
+set sql_mode=4194304;
+select @@sql_mode;
+@@sql_mode
+STRICT_ALL_TABLES
set sql_mode=16384+(65536*4);
select @@sql_mode;
@@sql_mode
diff --git a/mysql-test/r/sysdate_is_now.result b/mysql-test/r/sysdate_is_now.result
index 82861436ff6..1ebbb8c1588 100644
--- a/mysql-test/r/sysdate_is_now.result
+++ b/mysql-test/r/sysdate_is_now.result
@@ -1,4 +1,4 @@
set timestamp=1;
SELECT sleep(1),NOW()-SYSDATE() as zero;
sleep(1) zero
-0 0
+0 0.000000
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 8b4aba367fb..d4791c6b117 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -169,21 +169,22 @@ select @log;
@log
(BEFORE_INSERT: new=(id=1, data=2))
set @log:= "";
-replace t1 values (1, 3), (2, 2);
+insert into t1 (id, data) values (1, 3), (2, 2) on duplicate key update data= data + 1;
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=3))(BEFORE_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(AFTER_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(BEFORE_INSERT: new=(id=2, data=2))(AFTER_INSERT: new=(id=2, data=2))
-alter table t1 add ts timestamp default now();
+(BEFORE_INSERT: new=(id=1, data=3))(BEFORE_UPDATE: old=(id=1, data=1) new=(id=1, data=2))(AFTER_UPDATE: old=(id=1, data=1) new=(id=1, data=2))(BEFORE_INSERT: new=(id=2, data=2))(AFTER_INSERT: new=(id=2, data=2))
set @log:= "";
-replace t1 (id, data) values (1, 4);
+replace t1 values (1, 4), (3, 3);
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=4))(BEFORE_DELETE: old=(id=1, data=3))(AFTER_DELETE: old=(id=1, data=3))(AFTER_INSERT: new=(id=1, data=4))
+(BEFORE_INSERT: new=(id=1, data=4))(BEFORE_DELETE: old=(id=1, data=2))(AFTER_DELETE: old=(id=1, data=2))(AFTER_INSERT: new=(id=1, data=4))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
+drop trigger t1_bd;
+drop trigger t1_ad;
set @log:= "";
-insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+replace t1 values (1, 5);
select @log;
@log
-(BEFORE_INSERT: new=(id=1, data=5))(BEFORE_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(AFTER_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
+(BEFORE_INSERT: new=(id=1, data=5))(AFTER_INSERT: new=(id=1, data=5))
drop table t1;
create table t1 (id int primary key, data varchar(10), fk int);
create table t2 (event varchar(100));
@@ -493,15 +494,9 @@ select * from t1;
i k
3 13
replace into t1 values (3, 3);
-ERROR 42S22: Unknown column 'at' in 'NEW'
-select * from t1;
-i k
-3 3
-alter table t1 add ts timestamp default now();
-replace into t1 (i, k) values (3, 13);
ERROR 42S22: Unknown column 'at' in 'OLD'
select * from t1;
-i k ts
+i k
drop table t1, t2;
create table t1 (i int, bt int, k int, key(k)) engine=myisam;
create table t2 (i int);
@@ -574,18 +569,11 @@ i k
1 1
2 2
replace into t1 values (2, 4);
-ERROR 42S22: Unknown column 'bt' in 'NEW'
+ERROR 42S22: Unknown column 'bt' in 'OLD'
select * from t1;
i k
1 1
2 2
-alter table t1 add ts timestamp default now();
-replace into t1 (i, k) values (2, 11);
-ERROR 42S22: Unknown column 'bt' in 'OLD'
-select * from t1;
-i k ts
-1 1 0000-00-00 00:00:00
-2 2 0000-00-00 00:00:00
drop table t1, t2;
drop function if exists bug5893;
create table t1 (col1 int, col2 int);
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 968c6d3ec6f..4caec152a1f 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -1397,3 +1397,14 @@ c1
9999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999
drop table t1;
+create table t1 (i int, j int);
+insert into t1 values (1,1), (1,2), (2,3), (2,4);
+select i, count(distinct j) from t1 group by i;
+i count(distinct j)
+1 2
+2 2
+select i+0.0 as i2, count(distinct j) from t1 group by i2;
+i2 count(distinct j)
+1.0 2
+2.0 2
+drop table t1;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 61ed6bbabf3..0817cc3b6c7 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
+set time_zone="+03:00";
CREATE TABLE t1 (a int, t timestamp);
CREATE TABLE t2 (a int, t datetime);
SET TIMESTAMP=1234;
@@ -491,3 +492,4 @@ a b c
5 NULL 2001-09-09 04:46:59
6 NULL 2006-06-06 06:06:06
drop table t1;
+set time_zone= @@global.time_zone;
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index be52fd7f87c..484c42c41bf 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -76,6 +76,24 @@ call XXX2();
metaphon(testval)
HL
drop procedure xxx2;
+CREATE TABLE bug19904(n INT, v varchar(10));
+INSERT INTO bug19904 VALUES (1,'one'),(2,'two'),(NULL,NULL),(3,'three'),(4,'four');
+SELECT myfunc_double(n) AS f FROM bug19904;
+f
+49.00
+50.00
+NULL
+51.00
+52.00
+SELECT metaphon(v) AS f FROM bug19904;
+f
+ON
+TW
+NULL
+0R
+FR
+DROP TABLE bug19904;
+End of 5.0 tests.
DROP FUNCTION metaphon;
DROP FUNCTION myfunc_double;
DROP FUNCTION myfunc_nonexist;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index eb9e10aa58d..426387e04f5 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -1306,3 +1306,48 @@ id
5
99
drop table t1;
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1));
+avg(1)
+NULL
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
index f6559e6f838..0431957f602 100644
--- a/mysql-test/r/view_grant.result
+++ b/mysql-test/r/view_grant.result
@@ -618,3 +618,44 @@ ERROR HY000: There is no 'no-such-user'@'localhost' registered
DROP VIEW v;
DROP TABLE t1;
USE test;
+CREATE USER mysqltest_db1@localhost identified by 'PWD';
+GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION;
+CREATE SCHEMA mysqltest_db1 ;
+USE mysqltest_db1 ;
+CREATE TABLE t1 (f1 INTEGER);
+CREATE VIEW view1 AS
+SELECT * FROM t1;
+SHOW CREATE VIEW view1;
+View Create View
+view1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view1` AS select `t1`.`f1` AS `f1` from `t1`
+CREATE VIEW view2 AS
+SELECT * FROM view1;
+# Here comes a suspicious warning
+SHOW CREATE VIEW view2;
+View Create View
+view2 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `view1`.`f1` AS `f1` from `view1`
+# But the view view2 is usable
+SELECT * FROM view2;
+f1
+CREATE VIEW view3 AS
+SELECT * FROM view2;
+SELECT * from view3;
+f1
+DROP VIEW mysqltest_db1.view3;
+DROP VIEW mysqltest_db1.view2;
+DROP VIEW mysqltest_db1.view1;
+DROP TABLE mysqltest_db1.t1;
+DROP SCHEMA mysqltest_db1;
+DROP USER mysqltest_db1@localhost;
+CREATE DATABASE test1;
+CREATE DATABASE test2;
+CREATE TABLE test1.t0 (a VARCHAR(20));
+CREATE TABLE test2.t1 (a VARCHAR(20));
+CREATE VIEW test2.t3 AS SELECT * FROM test1.t0;
+CREATE OR REPLACE VIEW test.v1 AS
+SELECT ta.a AS col1, tb.a AS col2 FROM test2.t3 ta, test2.t1 tb;
+DROP VIEW test.v1;
+DROP VIEW test2.t3;
+DROP TABLE test2.t1, test1.t0;
+DROP DATABASE test2;
+DROP DATABASE test1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index ba2ad3ed8aa..f712a770712 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1330,12 +1330,14 @@ SELECT * FROM t2;
#
# For bug #12836
# Delete was allowing all rows to be removed
+--error 1031
DELETE FROM t2;
SELECT * FROM t2;
INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
SELECT * FROM t2;
+--error 1031
TRUNCATE TABLE t2;
SELECT * FROM t2;
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index 26b103b0107..5d22bdd46a0 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -238,6 +238,23 @@ SHOW CREATE TABLE `t1`;
DROP TABLE `t1`;
+#
+# Bug #6880: LAST_INSERT_ID() within a statement
+#
+
+create table t1(a int not null auto_increment primary key);
+create table t2(a int not null auto_increment primary key, t1a int);
+insert into t1 values(NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+select * from t2;
+drop table t1, t2;
+
--echo End of 4.1 tests
#
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index d017d91bfb1..d2e3ca5f36e 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -1019,4 +1019,39 @@ commit;
alter table t1 add primary key(a);
drop table t1;
+
+#
+# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode
+#
+set autocommit=1;
+
+let $VERSION=`select version()`;
+
+reset master;
+create table bug16206 (a int) engine= blackhole;
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+--replace_result $VERSION VERSION
+--replace_column 1 f 2 n 5 n
+show binlog events;
+drop table bug16206;
+
+reset master;
+create table bug16206 (a int) engine= bdb;
+insert into bug16206 values(0);
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+insert into bug16206 values(3);
+--replace_result $VERSION VERSION
+--replace_column 1 f 2 n 5 n
+show binlog events;
+drop table bug16206;
+
+set autocommit=0;
+
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/create_not_windows.test b/mysql-test/t/create_not_windows.test
new file mode 100644
index 00000000000..71ad9ccd7fe
--- /dev/null
+++ b/mysql-test/t/create_not_windows.test
@@ -0,0 +1,20 @@
+# Non-windows specific create tests.
+
+--source include/not_windows.inc
+
+#
+# Bug#19479:mysqldump creates invalid dump
+#
+--disable_warnings
+drop table if exists `about:text`;
+--enable_warnings
+create table `about:text` (
+_id int not null auto_increment,
+`about:text` varchar(255) not null default '',
+primary key (_id)
+);
+
+show create table `about:text`;
+drop table `about:text`;
+
+# End of 5.0 tests
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_utf8.test b/mysql-test/t/ctype_utf8.test
index 5ca1f58d233..b58a2cf97d4 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -912,6 +912,32 @@ INSERT INTO t1 VALUES('uUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbb
check table t1;
drop table t1;
+#
+# Bug#14896: Comparison with a key in a partial index over mb chararacter field
+#
+
+SET NAMES utf8;
+CREATE TABLE t1 (id int PRIMARY KEY,
+ a varchar(16) collate utf8_unicode_ci NOT NULL default '',
+ b int,
+ f varchar(128) default 'XXX',
+ INDEX (a(4))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t1(id, a, b) VALUES
+ (1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30),
+ (4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40),
+ (7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50),
+ (10, 'eeeee', 40), (11, 'bbbbbb', 60);
+
+SELECT id, a, b FROM t1;
+
+SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb';
+
+SELECT id, a FROM t1 WHERE a='bbbbbb';
+SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
+
+DROP TABLE t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 5ae757b1fde..55e8f81f763 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -50,3 +50,52 @@ insert into t1 values (1);
insert delayed into t1 values (1);
select * from t1;
drop table t1;
+
+#
+# Bug #20195: INSERT DELAYED with auto_increment is assigned wrong values
+#
+CREATE TABLE t1 ( a int(10) NOT NULL auto_increment, PRIMARY KEY (a));
+
+# Make one delayed insert to start the separate thread
+insert delayed into t1 values(null);
+
+# Do some normal inserts
+insert into t1 values(null);
+insert into t1 values(null);
+
+# Discarded, since the delayed-counter is 2, which is already used
+insert delayed into t1 values(null);
+
+# Discarded, since the delayed-counter is 3, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 4, which is unused
+insert delayed into t1 values(null);
+
+# Do some more inserts
+insert into t1 values(null);
+insert into t1 values(null);
+insert into t1 values(null);
+
+# Delete one of the above to make a hole
+delete from t1 where a=6;
+
+# Discarded, since the delayed-counter is 5, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 6, which is unused (the row we deleted)
+insert delayed into t1 values(null);
+
+# Discarded, since the delayed-counter is 7, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 8, which is unused
+insert delayed into t1 values(null);
+
+# Check what we have now
+# must wait so that the delayed thread finishes
+# Note: this must be increased if the test fails
+--sleep 1
+select * from t1 order by a;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/fulltext_left_join.test b/mysql-test/t/fulltext_left_join.test
index 3bb1f0b7309..7c22f49ed8c 100644
--- a/mysql-test/t/fulltext_left_join.test
+++ b/mysql-test/t/fulltext_left_join.test
@@ -32,7 +32,7 @@ select match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
drop table t1, t2;
#
-# Bug #484, reported by Stephen Brandon <stephen@brandonitconsulting.co.uk>
+# BUG#484, reported by Stephen Brandon <stephen@brandonitconsulting.co.uk>
#
create table t1 (venue_id int(11) default null, venue_text varchar(255) default null, dt datetime default null) engine=myisam;
@@ -45,4 +45,17 @@ select * from t1 left join t2 on (venue_id = entity_id and match(name) against('
select * from t1 left join t2 on (venue_id = entity_id and match(name) against('aberdeen')) where dt = '2003-05-23 19:30:00';
drop table t1,t2;
+#
+# BUG#14708
+# Inconsistent treatment of NULLs in LEFT JOINed FULLTEXT matching without index
+#
+
+create table t1 (id int not null primary key, d char(200) not null, e char(200));
+insert into t1 values (1, 'aword', null), (2, 'aword', 'bword'), (3, 'bword', null), (4, 'bword', 'aword'), (5, 'aword and bword', null);
+select * from t1 where match(d, e) against ('+aword +bword' in boolean mode);
+create table t2 (m_id int not null, f char(200), key (m_id));
+insert into t2 values (1, 'bword'), (3, 'aword'), (5, '');
+select * from t1 left join t2 on m_id = id where match(d, e, f) against ('+aword +bword' in boolean mode);
+drop table t1,t2;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test
index 37fc0e105b8..5487ad9c56b 100644
--- a/mysql-test/t/func_concat.test
+++ b/mysql-test/t/func_concat.test
@@ -52,4 +52,19 @@ select 'a' union select concat('a', -0.0);
--replace_result a-0.0000 a0.0000
select 'a' union select concat('a', -0.0000);
+#
+# Bug#16716: subselect in concat() may lead to a wrong result
+#
+select concat((select x from (select 'a' as x) as t1 ),
+ (select y from (select 'b' as y) as t2 )) from (select 1 union select 2 )
+ as t3;
+
# End of 4.1 tests
+
+#
+# Bug#15962: CONCAT() in UNION may lead to a data trucation.
+#
+create table t1(f1 varchar(6)) charset=utf8;
+insert into t1 values ("123456");
+select concat(f1, 2) a from t1 union select 'x' a from t1;
+drop table t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index fb9470c16dd..e8c5fa18a25 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -539,6 +539,34 @@ INSERT INTO t1 VALUES
SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
DROP TABLE t1;
+#
+# Bug #18206: min/max optimization cannot be applied to partial index
+#
+
+CREATE TABLE t1 (id int PRIMARY KEY, b char(3), INDEX(b));
+INSERT INTO t1 VALUES (1,'xx'), (2,'aa');
+SELECT * FROM t1;
+
+SELECT MAX(b) FROM t1 WHERE b < 'ppppp';
+SHOW WARNINGS;
+SELECT MAX(b) FROM t1 WHERE b < 'pp';
+DROP TABLE t1;
+
+CREATE TABLE t1 (id int PRIMARY KEY, b char(16), INDEX(b(4)));
+INSERT INTO t1 VALUES (1, 'xxxxbbbb'), (2, 'xxxxaaaa');
+SELECT MAX(b) FROM t1;
+EXPLAIN SELECT MAX(b) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (id int , b varchar(512), INDEX(b(250))) COLLATE latin1_bin;
+INSERT INTO t1 VALUES
+ (1,CONCAT(REPEAT('_', 250), "qq")), (1,CONCAT(REPEAT('_', 250), "zz")),
+ (1,CONCAT(REPEAT('_', 250), "aa")), (1,CONCAT(REPEAT('_', 250), "ff"));
+
+SELECT MAX(b) FROM t1;
+EXPLAIN SELECT MAX(b) FROM t1;
+DROP TABLE t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 7f809dbc4a1..b13fe039261 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -673,6 +673,18 @@ drop table t1;
select load_file("lkjlkj");
select ifnull(load_file("lkjlkj"),"it's null");
+#
+# Bug#15351: Wrong collation used for comparison of md5() and sha()
+# parameter can lead to a wrong result.
+#
+create table t1 (f1 varchar(4), f2 varchar(64), unique key k1 (f1,f2));
+insert into t1 values ( 'test',md5('test')), ('test', sha('test'));
+select * from t1 where f1='test' and (f2= md5("test") or f2= md5("TEST"));
+select * from t1 where f1='test' and (f2= md5("TEST") or f2= md5("test"));
+select * from t1 where f1='test' and (f2= sha("test") or f2= sha("TEST"));
+select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test"));
+drop table t1;
+
--echo End of 4.1 tests
#
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 1c7f387e354..05c033f2b22 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -5,6 +5,9 @@
drop table if exists t1,t2,t3;
--enable_warnings
+# Set timezone to GMT-3, to make it possible to use "interval 3 hour"
+set time_zone="+03:00";
+
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
select period_add("9602",-12),period_diff(199505,"9404") ;
@@ -335,6 +338,7 @@ select last_day("1997-12-1")+0.0;
# Test SAPDB UTC_% functions. This part is TZ dependant (It is supposed that
# TZ variable set to GMT-3
+
select strcmp(date_sub(localtimestamp(), interval 3 hour), utc_timestamp())=0;
select strcmp(date_format(date_sub(localtimestamp(), interval 3 hour),"%T"), utc_time())=0;
select strcmp(date_format(date_sub(localtimestamp(), interval 3 hour),"%Y-%m-%d"), utc_date())=0;
@@ -367,6 +371,36 @@ select last_day('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'));
+#
+# Bug#16377 result of DATE/TIME functions were compared as strings which
+# can lead to a wrong result.
+#
+create table t1(f1 date, f2 time, f3 datetime);
+insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01");
+insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02");
+select f1 from t1 where f1 between "2006-1-1" and 20060101;
+select f1 from t1 where f1 between "2006-1-1" and "2006.1.1";
+select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1";
+select f2 from t1 where f2 between "12:1:2" and "12:2:2";
+select f2 from t1 where time(f2) between "12:1:2" and "12:2:2";
+select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+select f1 from t1 where "2006-1-1" between f1 and f3;
+select f1 from t1 where "2006-1-1" between date(f1) and date(f3);
+select f1 from t1 where "2006-1-1" between f1 and 'zzz';
+select f1 from t1 where makedate(2006,1) between date(f1) and date(f3);
+select f1 from t1 where makedate(2006,2) between date(f1) and date(f3);
+drop table t1;
+
+#
+# Bug #16546
+#
+
+create table t1 select now() - now(), curtime() - curtime(),
+ sec_to_time(1) + 0, from_unixtime(1) + 0;
+show create table t1;
+drop table t1;
+
# End of 4.1 tests
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
@@ -483,3 +517,6 @@ SELECT * FROM t1, t2
DROP TABLE t1,t2;
# End of 5.0 tests
+
+# Restore timezone to default
+set time_zone= @@global.time_zone;
diff --git a/mysql-test/t/func_timestamp.test b/mysql-test/t/func_timestamp.test
index e1bb7e878ee..05a91b06d28 100644
--- a/mysql-test/t/func_timestamp.test
+++ b/mysql-test/t/func_timestamp.test
@@ -6,6 +6,9 @@
drop table if exists t1;
--enable_warnings
+# Set timezone to GMT-3, to make it possible to use "interval 3 hour"
+set time_zone="+03:00";
+
create table t1 (Zeit time, Tag tinyint not null, Monat tinyint not null,
Jahr smallint not null, index(Tag), index(Monat), index(Jahr) );
insert into t1 values ("09:26:00",16,9,1998),("09:26:00",16,9,1998);
@@ -15,3 +18,6 @@ FROM t1;
drop table t1;
# End of 4.1 tests
+
+# Restore timezone to default
+set time_zone= @@global.time_zone;
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..3afc36935f8 100644
--- a/mysql-test/t/im_daemon_life_cycle.imtest
+++ b/mysql-test/t/im_daemon_life_cycle.imtest
@@ -10,6 +10,22 @@
###########################################################################
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted
+###########################################################################
+
+# Kill the IM main process and check that the IM Angel will restart the main
+# process.
+
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30
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 445ae7f72fa..2cbe53a7b28 100644
--- a/mysql-test/t/im_life_cycle.imtest
+++ b/mysql-test/t/im_life_cycle.imtest
@@ -17,11 +17,23 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.1.
+--echo --------------------------------------------------------------------
+
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
###########################################################################
#
@@ -33,20 +45,24 @@ SHOW INSTANCE STATUS mysqld2;
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.2.
+--echo --------------------------------------------------------------------
+
START INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
-SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
---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,15 +77,19 @@ SHOW VARIABLES LIKE 'port';
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.3.
+--echo --------------------------------------------------------------------
+
STOP INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: STOP INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
-SHOW INSTANCES;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION
-SHOW INSTANCE STATUS mysqld2;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
###########################################################################
#
@@ -81,16 +101,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,27 +122,40 @@ 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
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30
+
+# Give some time to IM to detect that mysqld was restarted. It should be longer
+# than monitoring interval.
+
+--sleep 3
+
+SHOW INSTANCES;
###########################################################################
#
@@ -129,17 +163,26 @@ SHOW INSTANCES;
#
###########################################################################
-SHOW INSTANCES;
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.7.
+--echo --------------------------------------------------------------------
START INSTANCE mysqld2;
-# FIXME
---sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
-SHOW INSTANCES;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10
-SHOW INSTANCES;
+# FIXME: SHOW INSTANCES is not deterministic unless START INSTANCE is
+# synchronous. Even waiting for mysqld to start by looking at its pid file is
+# not enough, because IM may not detect that mysqld has started.
+# SHOW INSTANCES;
###########################################################################
#
@@ -147,7 +190,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 +208,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_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..47902eeba52 100644
--- a/mysql-test/t/im_utils.imtest
+++ b/mysql-test/t/im_utils.imtest
@@ -17,6 +17,17 @@
# - the second instance is offline;
#
+# Wait for mysqld1 (guarded instance) to start.
+
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started
+
+# Let IM detect that mysqld1 is online. This delay should be longer than
+# monitoring interval.
+
+--sleep 3
+
+# Check that start conditions are as expected.
+
SHOW INSTANCES;
#
@@ -40,11 +51,10 @@ SHOW INSTANCE OPTIONS mysqld2;
#
START INSTANCE mysqld2;
-
-# FIXME
--- sleep 3
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
STOP INSTANCE mysqld2;
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
#
# Check 'SHOW LOG FILES' command:
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 48dd28bf6da..0bcd9ef8c0b 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -576,28 +576,32 @@ connect (con2,localhost,user2,,mysqltest);
connect (con3,localhost,user3,,mysqltest);
connect (con4,localhost,user4,,);
connection con1;
-select * from information_schema.column_privileges;
-select * from information_schema.table_privileges;
-select * from information_schema.schema_privileges;
-select * from information_schema.user_privileges;
+select * from information_schema.column_privileges order by grantee;
+select * from information_schema.table_privileges order by grantee;
+select * from information_schema.schema_privileges order by grantee;
+select * from information_schema.user_privileges order by grantee;
show grants;
connection con2;
-select * from information_schema.column_privileges;
-select * from information_schema.table_privileges;
-select * from information_schema.schema_privileges;
-select * from information_schema.user_privileges;
+select * from information_schema.column_privileges order by grantee;
+select * from information_schema.table_privileges order by grantee;
+select * from information_schema.schema_privileges order by grantee;
+select * from information_schema.user_privileges order by grantee;
show grants;
connection con3;
-select * from information_schema.column_privileges;
-select * from information_schema.table_privileges;
-select * from information_schema.schema_privileges;
-select * from information_schema.user_privileges;
+select * from information_schema.column_privileges order by grantee;
+select * from information_schema.table_privileges order by grantee;
+select * from information_schema.schema_privileges order by grantee;
+select * from information_schema.user_privileges order by grantee;
show grants;
connection con4;
-select * from information_schema.column_privileges where grantee like '%user%';
-select * from information_schema.table_privileges where grantee like '%user%';
-select * from information_schema.schema_privileges where grantee like '%user%';
-select * from information_schema.user_privileges where grantee like '%user%';
+select * from information_schema.column_privileges where grantee like '%user%'
+order by grantee;
+select * from information_schema.table_privileges where grantee like '%user%'
+order by grantee;
+select * from information_schema.schema_privileges where grantee like '%user%'
+order by grantee;
+select * from information_schema.user_privileges where grantee like '%user%'
+order by grantee;
show grants;
connection default;
drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost;
@@ -838,3 +842,13 @@ connection default;
drop view v1, v2;
drop table t1;
drop user mysqltest_1@localhost;
+
+#
+# Bug#19599 duplication of information_schema column value in a CONCAT expr with user var
+#
+set @a:= '.';
+create table t1(f1 char(5));
+create table t2(f1 char(5));
+select concat(@a, table_name), @a, table_name
+from information_schema.tables where table_schema = 'test';
+drop table t1,t2;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index e4c8bf89cca..71b178d0e57 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -2196,3 +2196,16 @@ drop table t2, t1;
#
--error ER_TABLE_CANT_HANDLE_SPKEYS
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
+
+#######################################################################
+# #
+# 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). #
+# #
+#######################################################################
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 0c64dd80bec..ac43d0bc818 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -187,3 +187,26 @@ create view v1 as select * from t1;
insert delayed into v1 values (1);
drop table t1;
drop view v1;
+
+#
+# Test for values returned by ROW_COUNT() function
+# (and thus for values returned by mysql_affected_rows())
+# for various forms of INSERT
+#
+create table t1 (id int primary key, data int);
+insert into t1 values (1, 1), (2, 2), (3, 3);
+select row_count();
+insert ignore into t1 values (1, 1);
+select row_count();
+# Reports that 2 rows are affected (1 deleted + 1 inserted)
+replace into t1 values (1, 11);
+select row_count();
+replace into t1 values (4, 4);
+select row_count();
+# Reports that 2 rows are affected. This conforms to documentation.
+# (Useful for differentiating inserts from updates).
+insert into t1 values (2, 2) on duplicate key update data= data + 10;
+select row_count();
+insert into t1 values (5, 5) on duplicate key update data= data + 10;
+select row_count();
+drop table t1;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 5dd6f338865..05953a1fd49 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -224,4 +224,26 @@ insert into t1(x,y) select x,z from t2 on duplicate key update x=values(z);
insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x);
drop table t1,t2;
+#
+# Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big
+# tables
+#
+
+#Note: not an exsaustive test : just a check of the code path.
+CREATE TABLE t1 (a int PRIMARY KEY);
+INSERT INTO t1 values (1), (2);
+
+INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1;
+
+DROP TABLE t1;
+
# End of 4.1 tests
+
+#
+# Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error
+#
+CREATE TABLE t1 (x int, y int);
+CREATE TABLE t2 (z int, y int);
+CREATE TABLE t3 (a int, b int);
+INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1);
+DROP TABLE IF EXISTS t1,t2,t3;
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index f6a57d5e230..27558a31d68 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -563,4 +563,29 @@ select a2 from ((t1 natural join t2) join t3 on b=c1) natural join t4;
drop table t1,t2,t3,t4;
+#
+# BUG#15355: Common natural join column not resolved in prepared statement nested query
+#
+create table t1 (c int, b int);
+create table t2 (a int, b int);
+create table t3 (b int, c int);
+create table t4 (y int, c int);
+create table t5 (y int, z int);
+
+insert into t1 values (3,2);
+insert into t2 values (1,2);
+insert into t3 values (2,3);
+insert into t4 values (1,3);
+insert into t5 values (1,4);
+
+-- this fails
+prepare stmt1 from "select * from ((t3 natural join (t1 natural join t2))
+natural join t4) natural join t5";
+execute stmt1;
+
+-- this works
+select * from ((t3 natural join (t1 natural join t2)) natural join t4)
+ natural join t5;
+drop table t1, t2, t3, t4, t5;
+
# End of tests for WL#2486 - natural/using join
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index 31763b84379..e7072ae29f6 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -326,6 +326,17 @@ alter table t1 add key (c1,c1,c2);
drop table t1;
#
+# Bug#11228: DESC shows arbitrary column as "PRI"
+#
+create table t1 (
+ i1 INT NOT NULL,
+ i2 INT NOT NULL,
+ UNIQUE i1idx (i1),
+ UNIQUE i2idx (i2));
+desc t1;
+drop table t1;
+
+#
# Bug#12565 - ERROR 1034 when running simple UPDATE or DELETE
# on large MyISAM table
#
diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh
index e722b3a180d..64cc869d1ec 100755
--- a/mysql-test/t/kill_n_check.sh
+++ b/mysql-test/t/kill_n_check.sh
@@ -1,66 +1,115 @@
#!/bin/sh
-if [ $# -ne 2 ]; then
- echo "Usage: kill_n_check.sh <pid file path> killed|restarted"
+###########################################################################
+
+# NOTE: this script returns 0 (success) even in case of failure. This is
+# because this script is executed under mysql-test-run[.pl] and it's better to
+# examine particular problem in log file, than just having said that the test
+# case has failed.
+
+###########################################################################
+
+check_restart()
+{
+ if [ ! -r "$pid_path" ]; then
+ user_msg='the process was killed'
+ return 1
+ fi
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
+ if [ $? -eq 0 -a "$original_pid" = "$new_pid" ]; then
+ user_msg='the process was not restarted'
+ return 1
+ fi
+
+ user_msg='the process was restarted'
+ return 0
+}
+
+###########################################################################
+
+if [ $# -ne 3 ]; then
+ echo "Usage: kill_n_check.sh <pid file path> killed|restarted <timeout>"
exit 0
fi
pid_path="$1"
expected_result="$2"
+total_timeout="$3"
-if [ -z "$pid_path" -o ! -r "$pid_path" ]; then
- echo "Error: invalid PID path ($pid_path) or PID file does not exist."
+if [ "$expected_result" != 'killed' -a \
+ "$expected_result" != 'restarted' ]; then
+ echo "Error: invalid second argument ('killed' or 'restarted' expected)."
exit 0
fi
-if [ "$expected_result" != "killed" -a \
- "$expected_result" != "restarted" ]; then
- echo "Error: expected result must be either 'killed' or 'restarted'."
+if [ -z "$pid_path" ]; then
+ echo "Error: invalid PID path ($pid_path)."
exit 0
fi
-# echo "PID path: '$pid_path'"
+if [ $expected_result = 'killed' -a ! -r "$pid_path" ]; then
+ echo "Error: PID file ($pid_path) does not exist."
+ exit 0
+fi
-original_pid=`cat "$pid_path"`
+if [ -z "$total_timeout" ]; then
+ echo "Error: timeout is not specified."
+ exit 0
+fi
-# echo "Original PID: $original_pid"
+###########################################################################
+
+original_pid=`cat "$pid_path"`
echo "Killing the process..."
kill -9 $original_pid
+###########################################################################
+
echo "Sleeping..."
-sleep 3
+if [ "$expected_result" = "restarted" ]; then
-new_pid=""
+ # Wait for the process to restart.
-[ -r "$pid_path" ] && new_pid=`cat "$pid_path"`
+ cur_attempt=1
-# echo "New PID: $new_pid"
+ while true; do
-if [ "$expected_result" = "restarted" ]; then
+ if check_restart; then
+ echo "Success: $user_msg."
+ exit 0
+ fi
- if [ -z "$new_pid" ]; then
- echo "Error: the process was killed."
- exit 0
- fi
+ [ $cur_attempt -ge $total_timeout ] && break
- if [ "$original_pid" -eq "$new_pid" ]; then
- echo "Error: the process was not restarted."
- exit 0
- fi
-
- echo "Success: the process was restarted."
+ sleep 1
+
+ cur_attempt=`expr $cur_attempt + 1`
+
+ done
+
+ echo "Error: $user_msg."
exit 0
-
-else # $expected_result = killed
-
+
+else # $expected_result == killed
+
+ # Here we have to sleep for some long time to ensure that the process will
+ # not be restarted.
+
+ sleep $total_timeout
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
if [ "$new_pid" -a "$new_pid" -ne "$original_pid" ]; then
echo "Error: the process was restarted."
- exit 0
+ else
+ echo "Success: the process was killed."
fi
- echo "Success: the process was killed."
exit 0
+
fi
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index 3c829848bf3..905d0699e6a 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -109,6 +109,39 @@ unlock tables;
drop table t1;
#
+# Bug#19815 - CREATE/RENAME/DROP DATABASE can deadlock on a global read lock
+#
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+#
+connection con1;
+CREATE DATABASE mysqltest_1;
+FLUSH TABLES WITH READ LOCK;
+#
+# With bug in place: acquire LOCK_mysql_create_table and
+# wait in wait_if_global_read_lock().
+connection con2;
+send DROP DATABASE mysqltest_1;
+--sleep 1
+#
+# With bug in place: try to acquire LOCK_mysql_create_table...
+# When fixed: Reject dropping db because of the read lock.
+connection con1;
+--error ER_CANT_UPDATE_WITH_READLOCK
+DROP DATABASE mysqltest_1;
+UNLOCK TABLES;
+#
+connection con2;
+reap;
+#
+connection default;
+disconnect con1;
+disconnect con2;
+# This must have been dropped by connection 2 already,
+# which waited until the global read lock was released.
+--error ER_DB_DROP_EXISTS
+DROP DATABASE mysqltest_1;
+
# Bug#16986 - Deadlock condition with MyISAM tables
#
connection locker;
@@ -138,4 +171,30 @@ use test;
#
connection default;
+#
+# Bug #17264: MySQL Server freeze
+#
+connection locker;
+create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
+lock tables t1 write;
+connection writer;
+--sleep 2
+delimiter //;
+send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+delimiter ;//
+connection reader;
+--sleep 2
+delimiter //;
+send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+delimiter ;//
+connection locker;
+--sleep 2
+unlock tables;
+connection writer;
+reap;
+connection reader;
+reap;
+connection locker;
+drop table t1;
+
# End of 5.0 tests
diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test
index c02ae8f5073..521df01cc9b 100644
--- a/mysql-test/t/lowercase_table2.test
+++ b/mysql-test/t/lowercase_table2.test
@@ -139,3 +139,14 @@ select t1Aa.col1 from t1aA,t2Aa where t1Aa.col1 = t2aA.col1;
drop table t2aA, t1Aa;
# End of 4.1 tests
+
+#
+# Bug#17661 information_schema.SCHEMATA returns uppercase with lower_case_table_names = 1
+#
+create database mysqltest_LC2;
+use mysqltest_LC2;
+create table myUC (i int);
+select TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES
+where TABLE_SCHEMA ='mysqltest_LC2';
+use test;
+drop database mysqltest_LC2;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 7ea14a811ed..400279a826b 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -390,4 +390,13 @@ insert into t1 values ("Monty"),("WAX"),("Walrus");
alter table t1 engine=MERGE;
drop table t1;
+#
+# BUG#19648 - Merge table does not work with bit types
+#
+create table t1 (b bit(1));
+create table t2 (b bit(1));
+create table tm (b bit(1)) engine = merge union = (t1,t2);
+select * from tm;
+drop table tm, t1, t2;
+
# End of 5.0 tests
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 5e3be6d45eb..da19a18c73a 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -452,6 +452,14 @@ insert into t2 values(1,null);
delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1';
drop table t1, t2;
+#
+# Bug#19225: unchecked error leads to server crash
+#
+create table t1(a int);
+create table t2(a int);
+--error 1093
+delete from t1,t2 using t1,t2 where t1.a=(select a from t1);
+drop table t1, t2;
# End of 4.1 tests
#
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 15533ca00e6..56e799f00b6 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -697,6 +697,27 @@ select count(*) from t1 where id2 = 10;
select count(id1) from t1 where id2 = 10;
drop table t1;
+#
+# BUG##20357 - Got error 124 from storage engine using MIN and MAX functions
+# in queries
+#
+CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(1);
+SELECT MAX(a) FROM t1 IGNORE INDEX(a);
+ALTER TABLE t1 DISABLE KEYS;
+SELECT MAX(a) FROM t1;
+SELECT MAX(a) FROM t1 IGNORE INDEX(a);
+DROP TABLE t1;
+
+#
+# BUG#18036 - update of table joined to self reports table as crashed
+#
+CREATE TABLE t1(a CHAR(9), b VARCHAR(7)) ENGINE=MyISAM;
+INSERT INTO t1(a) VALUES('xxxxxxxxx'),('xxxxxxxxx');
+UPDATE t1 AS ta1,t1 AS ta2 SET ta1.b='aaaaaa',ta2.b='bbbbbb';
+SELECT * FROM t1;
+DROP TABLE t1;
+
# End of 4.1 tests
#
@@ -823,4 +844,3 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
--error 1064
create table t4 (c1 int) engine=myisam pack_keys=2;
drop table t1, t2, t3;
-
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index d53022665a0..b6a552adbde 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -1146,6 +1146,27 @@ drop table t1, t2;
#
+# Bug#18462 mysqldump does not dump view structures correctly
+#
+#
+create table t (qty int, price int);
+insert into t values(3, 50);
+insert into t values(5, 51);
+create view v1 as select qty, price, qty*price as value from t;
+create view v2 as select qty from v1;
+--echo mysqldump {
+--exec $MYSQL_DUMP --compact -F --tab . test
+--exec cat v1.sql
+--echo } mysqldump {
+--exec cat v2.sql
+--echo } mysqldump
+--rm v.sql t.sql t.txt
+drop view v1;
+drop view v2;
+drop table t;
+
+
+#
# Bug#14857 Reading dump files with single statement stored routines fails.
# fixed by patch for bug#16878
#
@@ -1161,3 +1182,32 @@ show create procedure p;
drop function f;
drop procedure p;
+#
+# Bug #17371 Unable to dump a schema with invalid views
+#
+#
+create table t1 ( id serial );
+create view v1 as select * from t1;
+drop table t1;
+# mysqldump gets 1356 from server, but gives us 2
+--echo mysqldump {
+--error 2
+--exec $MYSQL_DUMP --force -N --compact --skip-comments test
+--echo } mysqldump
+drop view v1;
+# BUG#17201 Spurious 'DROP DATABASE' in output,
+# also confusion between tables and views.
+# Example code from Markus Popp
+
+create database mysqldump_test_db;
+use mysqldump_test_db;
+create table t1 (id int);
+create view v1 as select * from t1;
+insert into t1 values (1232131);
+insert into t1 values (4711);
+insert into t1 values (3231);
+insert into t1 values (0815);
+--exec $MYSQL_DUMP --skip-comments --add-drop-database --databases mysqldump_test_db
+drop view v1;
+drop table t1;
+drop database mysqldump_test_db;
diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test
index 398ca3c502c..cc138b32b7e 100644
--- a/mysql-test/t/ndb_condition_pushdown.test
+++ b/mysql-test/t/ndb_condition_pushdown.test
@@ -1686,5 +1686,27 @@ 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#20406 (maybe same as bug#17421 -1, not seen on 32-bit x86)
+drop table t1;
+create table t1 ( fname varchar(255), lname varchar(255) )
+engine=ndbcluster;
+insert into t1 values ("Young","Foo");
+
+set engine_condition_pushdown = 0;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+set engine_condition_pushdown = 1;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+
+# make sure optimizer does not do some crazy shortcut
+insert into t1 values ("aaa", "aaa");
+insert into t1 values ("bbb", "bbb");
+insert into t1 values ("ccc", "ccc");
+insert into t1 values ("ddd", "ddd");
+
+set engine_condition_pushdown = 0;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+set engine_condition_pushdown = 1;
+SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
+
set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5;
diff --git a/mysql-test/t/ndb_loaddatalocal.test b/mysql-test/t/ndb_loaddatalocal.test
new file mode 100644
index 00000000000..47054ecfbf5
--- /dev/null
+++ b/mysql-test/t/ndb_loaddatalocal.test
@@ -0,0 +1,70 @@
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+create table t1(a int) engine=myisam;
+let $1=10000;
+disable_query_log;
+set SQL_LOG_BIN=0;
+while ($1)
+{
+ insert into t1 values(1);
+ dec $1;
+}
+set SQL_LOG_BIN=1;
+enable_query_log;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+#This will generate a 20KB file, now test LOAD DATA LOCAL
+drop table t1;
+
+create table t1(a int) engine=ndb;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+select count(*) from t1;
+system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile ;
+drop table t1;
+
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (2), (2), (3);
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+
+create table t1(a int primary key) engine=ndb;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
+select * from t1 order by a;
+drop table t1;
+
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (1), (2), (3);
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+
+create table t1(a int primary key) engine=ndb;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
+select * from t1 order by a;
+drop table t1;
+
+create table t1(a int) engine=myisam;
+insert into t1 values (1), (2), (3), (3);
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
+drop table t1;
+
+create table t1(a int primary key) engine=ndb;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
+system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
+select * from t1 order by a;
+drop table t1;
+
+# End of 4.1 tests
diff --git a/mysql-test/t/ndb_lock.test b/mysql-test/t/ndb_lock.test
index 6945f91ee39..54214ee72ec 100644
--- a/mysql-test/t/ndb_lock.test
+++ b/mysql-test/t/ndb_lock.test
@@ -69,4 +69,117 @@ insert into t1 values (1,1,1);
drop table t1;
+# Lock for update
+
+create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
+
+insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
+
+# PK access
+connection con1;
+begin;
+select * from t1 where x = 1 for update;
+
+connection con2;
+begin;
+select * from t1 where x = 2 for update;
+--error 1205
+select * from t1 where x = 1 for update;
+rollback;
+
+connection con1;
+commit;
+
+# table scan
+connection con1;
+begin;
+select * from t1 where y = 'one' or y = 'three' order by x for update;
+
+connection con2;
+begin;
+# Have to check with pk access here since scans take locks on
+# all rows and then release them in chunks
+# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
+#select * from t1 where x = 2 for update;
+--error 1205
+select * from t1 where x = 1 for update;
+rollback;
+
+connection con1;
+commit;
+
+# index scan
+connection con1;
+begin;
+select * from t1 where z > 1 and z < 3 for update;
+
+connection con2;
+begin;
+# Have to check with pk access here since scans take locks on
+# all rows and then release them in chunks
+select * from t1 where x = 1 for update;
+--error 1205
+select * from t1 where x = 2 for update;
+rollback;
+
+connection con1;
+commit;
+
+# share locking
+
+# PK access
+connection con1;
+begin;
+select * from t1 where x = 1 lock in share mode;
+
+connection con2;
+begin;
+select * from t1 where x = 1 lock in share mode;
+select * from t1 where x = 2 for update;
+--error 1205
+select * from t1 where x = 1 for update;
+rollback;
+
+connection con1;
+commit;
+
+# table scan
+connection con1;
+begin;
+select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
+
+connection con2;
+begin;
+select * from t1 where y = 'one' lock in share mode;
+# Have to check with pk access here since scans take locks on
+# all rows and then release them in chunks
+# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
+#select * from t1 where x = 2 for update;
+--error 1205
+select * from t1 where x = 1 for update;
+rollback;
+
+connection con1;
+commit;
+
+# index scan
+connection con1;
+begin;
+select * from t1 where z > 1 and z < 3 lock in share mode;
+
+connection con2;
+begin;
+select * from t1 where z = 1 lock in share mode;
+# Have to check with pk access here since scans take locks on
+# all rows and then release them in chunks
+select * from t1 where x = 1 for update;
+--error 1205
+select * from t1 where x = 2 for update;
+rollback;
+
+connection con1;
+commit;
+
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/ndb_replace.test b/mysql-test/t/ndb_replace.test
index 6cad80ef8ea..94a11f7dfb2 100644
--- a/mysql-test/t/ndb_replace.test
+++ b/mysql-test/t/ndb_replace.test
@@ -6,7 +6,7 @@
#
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
CREATE TABLE t1 (
@@ -27,6 +27,8 @@ replace into t1 (gesuchnr,benutzer_id) values (1,1);
select * from t1 order by gesuchnr;
drop table t1;
+# End of 4.1 tests
+
# bug#17431
CREATE TABLE t1(i INT PRIMARY KEY AUTO_INCREMENT,
j INT,
@@ -38,4 +40,28 @@ REPLACE INTO t1 (j,k) VALUES (1,42);
REPLACE INTO t1 (i,j) VALUES (17,2);
SELECT * from t1 ORDER BY i;
-# End of 4.1 tests
+# bug#19906
+CREATE TABLE t2 (a INT(11) NOT NULL,
+ b INT(11) NOT NULL,
+ c INT(11) NOT NULL,
+ x TEXT,
+ y TEXT,
+ z TEXT,
+ id INT(10) unsigned NOT NULL AUTO_INCREMENT,
+ i INT(11) DEFAULT NULL,
+ PRIMARY KEY (id),
+ UNIQUE KEY a (a,b,c)
+) ENGINE=ndbcluster;
+
+REPLACE INTO t2 (a,b,c,x,y,z,i) VALUES (1,1,1,'a','a','a',1),(1,1,1,'b','b','b',2), (1,1,1,'c','c','c',3);
+
+SELECT * FROM t2 ORDER BY id;
+
+REPLACE INTO t2(a,b,c,x,y,z,i) values (1,1,1,'a','a','a',1);
+REPLACE INTO t2(a,b,c,x,y,z,i) values (1,1,1,'b','b','b',2);
+
+SELECT * FROM t2 ORDER BY id;
+
+DROP TABLE t2;
+
+
diff --git a/mysql-test/t/ndb_truncate.test b/mysql-test/t/ndb_truncate.test
index 73af70d0d0f..a1ef4be0d48 100644
--- a/mysql-test/t/ndb_truncate.test
+++ b/mysql-test/t/ndb_truncate.test
@@ -2,12 +2,11 @@
-- source include/not_embedded.inc
--disable_warnings
-DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t1, t2;
--enable_warnings
-
-CREATE TABLE t2 (
- a bigint unsigned NOT NULL PRIMARY KEY,
+CREATE TABLE t1 (
+ a bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
b int unsigned not null,
c int unsigned
) engine=ndbcluster;
@@ -20,17 +19,23 @@ let $1=500;
disable_query_log;
while ($1)
{
- eval insert into t2 values($1*10, $1+9, 5*$1), ($1*10+1, $1+10, 7),($1*10+2, $1+10, 7*$1), ($1*10+3, $1+10, 10+$1), ($1*10+4, $1+10, 70*$1), ($1*10+5, $1+10, 7), ($1*10+6, $1+10, 9), ($1*10+7, $1+299, 899), ($1*10+8, $1+10, 12), ($1*10+9, $1+10, 14*$1);
+ eval insert into t1 values(NULL, $1+9, 5*$1), (NULL, $1+10, 7),(NULL, $1+10, 7*$1), (NULL, $1+10, 10+$1), (NULL, $1+10, 70*$1), (NULL, $1+10, 7), (NULL, $1+10, 9), (NULL, $1+299, 899), (NULL, $1+10, 12), (NULL, $1+10, 14*$1);
dec $1;
}
enable_query_log;
-select count(*) from t2;
+select count(*) from t1;
+
+select * from t1 order by a limit 2;
+
+truncate table t1;
+
+select count(*) from t1;
-truncate table t2;
+insert into t1 values(NULL,1,1),(NULL,2,2);
-select count(*) from t2;
+select * from t1 order by a;
-drop table t2;
+drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/replace.test b/mysql-test/t/replace.test
index 10703eaafb8..269854fb180 100644
--- a/mysql-test/t/replace.test
+++ b/mysql-test/t/replace.test
@@ -35,3 +35,13 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug#19789: REPLACE was allowed for a VIEW with CHECK OPTION enabled.
+#
+CREATE TABLE t1 (f1 INT);
+CREATE VIEW v1 AS SELECT f1 FROM t1 WHERE f1 = 0 WITH CHECK OPTION;
+--error 1369
+REPLACE INTO v1 (f1) VALUES (1);
+DROP TABLE t1;
+DROP VIEW v1;
diff --git a/mysql-test/t/rpl_auto_increment_11932.test b/mysql-test/t/rpl_auto_increment_11932.test
new file mode 100644
index 00000000000..d4b7872fb2b
--- /dev/null
+++ b/mysql-test/t/rpl_auto_increment_11932.test
@@ -0,0 +1,63 @@
+#
+# Test of auto_increment
+# BUG#11932
+#
+# Bug reported that master and slave get out of sync after TRUNCATE
+# TABLE.
+#
+# Test supplied by Are Casilla
+
+source include/master-slave.inc;
+--disable_warnings
+connection master;
+drop database if exists test1;
+--enable_warnings
+create database test1;
+use test1;
+
+CREATE TABLE `t1` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `fname` varchar(100) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
+INSERT INTO `t1` VALUES (1, 'blablabla');
+
+CREATE TABLE `t2` (
+ `id` int(10) NOT NULL auto_increment,
+ `comment` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 ;
+
+INSERT INTO `t2` VALUES (1, 'testtest 1');
+INSERT INTO `t2` VALUES (2, 'test 2');
+
+DELIMITER $;
+CREATE PROCEDURE simpleproc3 ()
+ NOT DETERMINISTIC
+ BEGIN
+ INSERT INTO t1 (fname) (SELECT t2.comment FROM t2 WHERE t2.id = '1');
+ INSERT INTO t1 (fname) VALUES('test');
+ END
+ $
+DELIMITER ;$
+
+CALL simpleproc3();
+
+select * from t2;
+
+TRUNCATE TABLE `t1`;
+CALL simpleproc3();
+
+select * from t1;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+use test1;
+select * from t1;
+
+drop database test1;
+connection master;
+drop database test1;
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
index 6e614991d36..578a39efd6e 100644
--- a/mysql-test/t/rpl_log.test
+++ b/mysql-test/t/rpl_log.test
@@ -109,5 +109,19 @@ show slave status;
--error 1220
show binlog events in 'slave-bin.000005' from 4;
+#
+# Bug #6880: LAST_INSERT_ID() within a statement
+#
+
+create table t1(a int auto_increment primary key, b int);
+insert into t1 values (NULL, 1);
+reset master;
+set insert_id=5;
+insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id());
+--replace_result $VERSION VERSION
+show binlog events;
+select * from t1;
+drop table t1;
+
# End of 4.1 tests
# Adding comment for force manual merge 5.0 -> wl1012: Delete me
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 8cd15463c62..b75d0dd8bb6 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2217,15 +2217,6 @@ show table status like 't1%';
select 123 as a from t1 where f1 is null;
drop table t1,t11;
-# Bug 7672 Unknown column error in order clause
-#
-CREATE TABLE t1 (a INT, b INT);
-(SELECT a, b AS c FROM t1) ORDER BY c+1;
-(SELECT a, b AS c FROM t1) ORDER BY b+1;
-SELECT a, b AS c FROM t1 ORDER BY c+1;
-SELECT a, b AS c FROM t1 ORDER BY b+1;
-drop table t1;
-
#
# Bug #3874 (function in GROUP and LEFT JOIN)
#
@@ -2265,6 +2256,21 @@ select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 fro
drop table t1,t2;
#
+# Bug #4981: 4.x and 5.x produce non-optimal execution path, 3.23 regression test failure
+#
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+# must have "range checked" for t2
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
+ where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
+ t2.b like '%%' order by t2.b limit 0,1;
+DROP TABLE t1,t2,t3;
+
+#
# Bug #17873: confusing error message when IGNORE INDEX refers a column name
#
@@ -2279,49 +2285,26 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX (a);
DROP TABLE t1;
-# End of 4.1 tests
-
#
-# Test case for bug 7098: substitution of a constant for a string field
+# Bug #18759 "Incorrect string to numeric conversion"
#
-
-CREATE TABLE t1 ( city char(30) );
-INSERT INTO t1 VALUES ('London');
-INSERT INTO t1 VALUES ('Paris');
-
-SELECT * FROM t1 WHERE city='London';
-SELECT * FROM t1 WHERE city='london';
-EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
-SELECT * FROM t1 WHERE city='London' AND city='london';
-EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-
-DROP TABLE t1;
-
+# This test is here so that the behavior will not be changed to 4.1
+# and not to 5.0 either. In 4.1 and 5.0 sending an integer as a string
+# will be converted internally to real (double) value and it is not
+# as accurate as bigint (longlong) for integers. Thus the results may
+# vary. In 5.1 internally it is decimal, which is a string type and
+# will be more accurate. Due to rather big changes needed to fix this
+# in 4.1 or 5.0 it is not desired to do it in the stable versions.
#
-# Bug#7425 inconsistent sort order on unsigned columns result of substraction
+# This test is here only to make sure that behavior is not changed in
+# 4.1 and 5.0
#
+CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (10);
+SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1;
+DROP TABLE t1;
-create table t1 (a int(11) unsigned, b int(11) unsigned);
-insert into t1 values (1,0), (1,1), (1,2);
-select a-b from t1 order by 1;
-select a-b , (a-b < 0) from t1 order by 1;
-select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
-select cast((a - b) as unsigned) from t1 order by 1;
-drop table t1;
-
-
-#
-# Bug#8733 server accepts malformed query (multiply mentioned distinct)
-#
-create table t1 (a int(11));
-select all all * from t1;
-select distinct distinct * from t1;
---error 1221
-select all distinct * from t1;
---error 1221
-select distinct all * from t1;
-drop table t1;
+# End of 4.1 tests
#
# Test for bug #6474
@@ -2358,21 +2341,6 @@ SELECT K2C4, K4N4, F2I4 FROM t1
DROP TABLE t1;
#
-# Test case for bug 7520: a wrong cost of the index for a BLOB field
-#
-
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-
-DROP TABLE t1, t2;
-
-#
# Bug#8670
#
create table t1 (a int, b int);
@@ -2411,34 +2379,6 @@ drop table t1;
#
-# Bug#8733 server accepts malformed query (multiply mentioned distinct)
-#
-create table t1 (a int(11));
-select all all * from t1;
-select distinct distinct * from t1;
---error 1221
-select all distinct * from t1;
---error 1221
-select distinct all * from t1;
-drop table t1;
-
-
-#
-# Test case for bug 7520: a wrong cost of the index for a BLOB field
-#
-
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-
-DROP TABLE t1, t2;
-
-#
# Test for bug #10084: STRAIGHT_JOIN with ON expression
#
@@ -2935,3 +2875,29 @@ 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;
+
+#
+# Bug #18895: BIT values cause joins to fail
+#
+create table t1 (
+ a int unsigned not null auto_increment primary key,
+ b bit not null,
+ c bit not null
+);
+
+create table t2 (
+ a int unsigned not null auto_increment primary key,
+ b bit not null,
+ c int unsigned not null,
+ d varchar(50)
+);
+
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+
+-- Row 1 should succeed. Row 2 should fail. Both fail.
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+
+drop table t1,t2;
diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test
index a7215462afb..b94de6236d3 100644
--- a/mysql-test/t/sp-prelocking.test
+++ b/mysql-test/t/sp-prelocking.test
@@ -272,3 +272,34 @@ drop table t1;
drop view v1, v2, v3;
drop function bug15683;
+
+#
+# Bug#19634 "Re-execution of multi-delete which involve trigger/stored
+# function crashes server"
+#
+--disable_warnings
+drop table if exists t1, t2, t3;
+drop function if exists bug19634;
+--enable_warnings
+create table t1 (id int, data int);
+create table t2 (id int);
+create table t3 (data int);
+create function bug19634() returns int return (select count(*) from t3);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()";
+# This should not crash server
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id";
+
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+drop function bug19634;
+drop table t1, t2, t3;
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index c0dd785a8ce..25c96042e6f 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -5934,6 +5934,33 @@ drop database mysqltest2|
#
# Restore the old environemnt
use test|
+#
+# Bug#15217 "Using a SP cursor on a table created with PREPARE fails with
+# weird error". Check that the code that is supposed to work at
+# the first execution of a stored procedure actually works for
+# sp_instr_copen.
+
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug15217|
+--enable_warnings
+create table t3 as select 1|
+create procedure bug15217()
+begin
+ declare var1 char(255);
+ declare cur1 cursor for select * from t3;
+ open cur1;
+ fetch cur1 into var1;
+ select concat('data was: /', var1, '/');
+ close cur1;
+end |
+# Returns expected result
+call bug15217()|
+flush tables |
+# Returns error with garbage as column name
+call bug15217()|
+drop table t3|
+drop procedure bug15217|
#
# BUG#NNNN: New bug synopsis
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index b67f1a73db6..2699cb66471 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -258,6 +258,9 @@ drop table t1, t2;
select @@sql_mode;
set sql_mode=2097152;
select @@sql_mode;
+# BUG#14675
+set sql_mode=4194304;
+select @@sql_mode;
set sql_mode=16384+(65536*4);
select @@sql_mode;
--error 1231
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index a5bd2ba0b38..3743d8f5c76 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -185,24 +185,26 @@ select @log;
set @log:= "";
insert ignore t1 values (1, 2);
select @log;
-# REPLACE: before insert trigger should be called for both records,
-# but then for first one update will be executed (and both update
-# triggers should fire). For second after insert trigger will be
-# called as for usual insert
+# INSERT ... ON DUPLICATE KEY UPDATE ...
set @log:= "";
-replace t1 values (1, 3), (2, 2);
+insert into t1 (id, data) values (1, 3), (2, 2) on duplicate key update data= data + 1;
select @log;
-# Now let us change table in such way that REPLACE on won't be executed
-# using update.
-alter table t1 add ts timestamp default now();
+# REPLACE (also test for bug#13479 "REPLACE activates UPDATE trigger,
+# not the DELETE and INSERT triggers")
+# We define REPLACE as INSERT which DELETEs old rows which conflict with
+# row being inserted. So for the first record in statement below we will
+# call before insert trigger, then delete will be executed (and both delete
+# triggers should fire). Finally after insert trigger will be called.
+# For the second record we will just call both on insert triggers.
set @log:= "";
-# This REPLACE should be executed via DELETE and INSERT so proper
-# triggers should be invoked.
-replace t1 (id, data) values (1, 4);
+replace t1 values (1, 4), (3, 3);
select @log;
-# Finally let us test INSERT ... ON DUPLICATE KEY UPDATE ...
+# Now we will drop ON DELETE triggers to test REPLACE which is internally
+# executed via update
+drop trigger t1_bd;
+drop trigger t1_ad;
set @log:= "";
-insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+replace t1 values (1, 5);
select @log;
# This also drops associated triggers
@@ -531,14 +533,11 @@ alter table t1 add primary key (i);
--error 1054
insert into t1 values (3, 4) on duplicate key update k= k + 10;
select * from t1;
+# The following statement will delete old row and won't
+# insert new one since after delete trigger will fail.
--error 1054
replace into t1 values (3, 3);
select * from t1;
-# Change table in such way that REPLACE will delete row
-alter table t1 add ts timestamp default now();
---error 1054
-replace into t1 (i, k) values (3, 13);
-select * from t1;
# Also drops all triggers
drop table t1, t2;
@@ -594,11 +593,6 @@ select * from t1;
--error 1054
replace into t1 values (2, 4);
select * from t1;
-# Change table in such way that REPLACE will delete row
-alter table t1 add ts timestamp default now();
---error 1054
-replace into t1 (i, k) values (2, 11);
-select * from t1;
# Also drops all triggers
drop table t1, t2;
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index 74782a5bddb..35aff8b3c5a 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -1095,3 +1095,12 @@ insert into t1 values(
insert into t1 values(1e100);
select * from t1;
drop table t1;
+
+#
+# Bug#19667 group by a decimal expression yields wrong result
+#
+create table t1 (i int, j int);
+insert into t1 values (1,1), (1,2), (2,3), (2,4);
+select i, count(distinct j) from t1 group by i;
+select i+0.0 as i2, count(distinct j) from t1 group by i2;
+drop table t1;
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index f96beedbebc..ddfc3f11665 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -6,6 +6,9 @@
drop table if exists t1,t2;
--enable_warnings
+# Set timezone to GMT-3, to make it possible to use "interval 3 hour"
+set time_zone="+03:00";
+
CREATE TABLE t1 (a int, t timestamp);
CREATE TABLE t2 (a int, t datetime);
SET TIMESTAMP=1234;
@@ -322,3 +325,6 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+# Restore timezone to default
+set time_zone= @@global.time_zone;
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index e2556692612..f3be08c8537 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -99,6 +99,17 @@ delimiter ;//
call XXX2();
drop procedure xxx2;
+#
+# Bug#19904: UDF: not initialized *is_null per row
+#
+
+CREATE TABLE bug19904(n INT, v varchar(10));
+INSERT INTO bug19904 VALUES (1,'one'),(2,'two'),(NULL,NULL),(3,'three'),(4,'four');
+SELECT myfunc_double(n) AS f FROM bug19904;
+SELECT metaphon(v) AS f FROM bug19904;
+DROP TABLE bug19904;
+
+--echo End of 5.0 tests.
#
# Drop the example functions from udf_example
@@ -114,3 +125,4 @@ DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
+
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 692f1f509fa..7dfe4ac482f 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -793,3 +793,51 @@ select id from t1 union all select 99 order by 1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug#18175: Union select over 129 tables with a sum function fails.
+#
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1));
+
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index 4663a667d25..429a2af6bac 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -807,3 +807,62 @@ SELECT * FROM v;
DROP VIEW v;
DROP TABLE t1;
USE test;
+
+#
+# Bug#20363: Create view on just created view is now denied
+#
+eval CREATE USER mysqltest_db1@localhost identified by 'PWD';
+eval GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION;
+
+# The session with the non root user is needed.
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+connect (session1,localhost,mysqltest_db1,PWD,test);
+
+CREATE SCHEMA mysqltest_db1 ;
+USE mysqltest_db1 ;
+
+CREATE TABLE t1 (f1 INTEGER);
+
+CREATE VIEW view1 AS
+SELECT * FROM t1;
+SHOW CREATE VIEW view1;
+
+CREATE VIEW view2 AS
+SELECT * FROM view1;
+--echo # Here comes a suspicious warning
+SHOW CREATE VIEW view2;
+--echo # But the view view2 is usable
+SELECT * FROM view2;
+
+CREATE VIEW view3 AS
+SELECT * FROM view2;
+
+SELECT * from view3;
+
+connection default;
+DROP VIEW mysqltest_db1.view3;
+DROP VIEW mysqltest_db1.view2;
+DROP VIEW mysqltest_db1.view1;
+DROP TABLE mysqltest_db1.t1;
+DROP SCHEMA mysqltest_db1;
+DROP USER mysqltest_db1@localhost;
+#
+# BUG#20482: failure on Create join view with sources views/tables
+# in different schemas
+#
+--disable_warnings
+CREATE DATABASE test1;
+CREATE DATABASE test2;
+--enable_warnings
+
+CREATE TABLE test1.t0 (a VARCHAR(20));
+CREATE TABLE test2.t1 (a VARCHAR(20));
+CREATE VIEW test2.t3 AS SELECT * FROM test1.t0;
+CREATE OR REPLACE VIEW test.v1 AS
+ SELECT ta.a AS col1, tb.a AS col2 FROM test2.t3 ta, test2.t1 tb;
+
+DROP VIEW test.v1;
+DROP VIEW test2.t3;
+DROP TABLE test2.t1, test1.t0;
+DROP DATABASE test2;
+DROP DATABASE test1;
diff --git a/mysql-test/t/wait_for_process.sh b/mysql-test/t/wait_for_process.sh
new file mode 100755
index 00000000000..df0f4a17e3a
--- /dev/null
+++ b/mysql-test/t/wait_for_process.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+###########################################################################
+
+pid_path="$1"
+total_attempts="$2"
+event="$3"
+
+case "$3" in
+ started)
+ check_fn='check_started';
+ ;;
+
+ stopped)
+ check_fn='check_stopped';
+ ;;
+
+ *)
+ echo "Error: invalid third argument ('started' or 'stopped' expected)."
+ exit 0
+esac
+
+###########################################################################
+
+check_started()
+{
+ [ ! -r "$pid_path" ] && return 1
+
+ new_pid=`cat "$pid_path" 2>/dev/null`
+
+ [ $? -eq 0 -a "$original_pid" = "$new_pid" ] && return 1
+
+ return 0
+}
+
+###########################################################################
+
+check_stopped()
+{
+ [ -r "$pid_path" ] && return 1
+
+ return 0
+}
+
+###########################################################################
+
+cur_attempt=1
+
+while true; do
+
+ if ( eval $check_fn ); then
+ echo "Success: the process has been $event."
+ exit 0
+ fi
+
+ [ $cur_attempt -ge $total_attempts ] && break
+
+ sleep 1
+
+ cur_attempt=`expr $cur_attempt + 1`
+
+done
+
+echo "Error: the process has not been $event in $total_attempts secs."
+exit 0
+
diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index 9310c3502b9..8387c08c902 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -11,6 +11,7 @@
connect (wait_con,localhost,root,,test,,);
flush status; # Reset counters
connection wait_con;
+set session wait_timeout=100;
let $retries=300;
let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`;
set @aborted_clients= 0;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 3c2ac1a7ea5..24426727968 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -134,6 +134,18 @@
}
#
+# Warning from my_thread_init becasue mysqld dies before kill thread exists
+#
+
+{
+ my_thread_init kill thread memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:my_thread_init
+ fun:kill_server_thread
+}
+
+#
# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2.
#
@@ -292,3 +304,18 @@
futex(utime)
fun:__lll_mutex_unlock_wake
}
+
+#
+# BUG#19940: NDB sends uninitialized parts of field buffers across the wire.
+# This is "works as designed"; the uninitialized part is not used at the
+# other end (but Valgrind cannot see this).
+#
+{
+ bug19940
+ Memcheck:Param
+ socketcall.sendto(msg)
+ fun:send
+ fun:_ZN15TCP_Transporter6doSendEv
+ fun:_ZN19TransporterRegistry11performSendEv
+ fun:_ZN19TransporterRegistry14forceSendCheckEi
+}
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index d046b2fa3f8..bc84f44cd29 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -56,7 +56,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.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
+ my_windac.c my_access.c base64.c my_libwrap.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c
index 9206aa28078..4d78f039799 100644
--- a/mysys/mf_dirname.c
+++ b/mysys/mf_dirname.c
@@ -72,7 +72,9 @@ uint dirname_part(my_string to, const char *name)
SYNPOSIS
convert_dirname()
- to Store result here
+ to Store result here. Must be at least of size
+ min(FN_REFLEN, strlen(from) + 1) to make room
+ for adding FN_LIBCHAR at the end.
from Original filename
from_end Pointer at end of filename (normally end \0)
diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c
index 9c86a8072ef..d7b1f8c1d61 100644
--- a/mysys/mf_fn_ext.c
+++ b/mysys/mf_fn_ext.c
@@ -40,14 +40,14 @@ my_string fn_ext(const char *name)
DBUG_ENTER("fn_ext");
DBUG_PRINT("mfunkt",("name: '%s'",name));
-#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR)
+#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) || defined(BASKSLASH_MBTAIL)
{
char buff[FN_REFLEN];
gpos=(my_string) name+dirname_part(buff,(char*) name);
}
#else
- if (!(gpos=strrchr(name,FNLIBCHAR)))
- gpos=name;
+ if (!(gpos= strrchr(name, FN_LIBCHAR)))
+ gpos= (my_string) name;
#endif
pos=strchr(gpos,FN_EXTCHAR);
DBUG_RETURN (pos ? pos : strend(gpos));
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 03f2d91916d..1c5630ad14e 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -501,7 +501,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
if (!(MyFlags & MY_DONT_SORT))
qsort((void *) result->dir_entry, result->number_off_files,
sizeof(FILEINFO), (qsort_cmp) comp_names);
- DBUG_PRINT(exit, ("found %d files", result->number_off_files));
+ DBUG_PRINT("exit", ("found %d files", result->number_off_files));
DBUG_RETURN(result);
error:
my_errno=errno;
diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c
new file mode 100644
index 00000000000..be8adbab0a1
--- /dev/null
+++ b/mysys/my_libwrap.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This is needed to be able to compile with original libwrap header
+ files that don't have the prototypes
+*/
+
+#include <my_global.h>
+#include <my_libwrap.h>
+
+#ifdef HAVE_LIBWRAP
+
+void my_fromhost(struct request_info *req)
+{
+ fromhost(req);
+}
+
+int my_hosts_access(struct request_info *req)
+{
+ hosts_access(req);
+}
+
+char *my_eval_client(struct request_info *req)
+{
+ eval_client(req);
+}
+
+#endif /* HAVE_LIBWRAP */
diff --git a/ndb/Makefile.am b/ndb/Makefile.am
index 3aac54b38ee..ead70766e97 100644
--- a/ndb/Makefile.am
+++ b/ndb/Makefile.am
@@ -20,7 +20,8 @@ dist-hook:
done
windoze:
- for i in `find . -name 'Makefile.am'`; do make -C `dirname $$i` windoze-dsp; done
+ for i in `find . -name 'old_dirs' -prune -o -name 'Makefile.am' -print`; \
+ do make -C `dirname $$i` windoze-dsp; done
windoze-dsp:
diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h
index 98b6ce7d949..d60f7a2c582 100644
--- a/ndb/include/kernel/GlobalSignalNumbers.h
+++ b/ndb/include/kernel/GlobalSignalNumbers.h
@@ -507,16 +507,12 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TEST_ORD 407
#define GSN_TESTSIG 408
#define GSN_TIME_SIGNAL 409
-/* 410 unused */
-/* 411 unused */
-/* 412 unused */
#define GSN_TUP_ABORTREQ 414
#define GSN_TUP_ADD_ATTCONF 415
#define GSN_TUP_ADD_ATTRREF 416
#define GSN_TUP_ADD_ATTRREQ 417
#define GSN_TUP_ATTRINFO 418
#define GSN_TUP_COMMITREQ 419
-/* 420 unused */
#define GSN_TUP_LCPCONF 421
#define GSN_TUP_LCPREF 422
#define GSN_TUP_LCPREQ 423
@@ -938,4 +934,10 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_ACC_LOCKREQ 711
#define GSN_READ_PSUEDO_REQ 712
+/* DICT LOCK signals */
+#define GSN_DICT_LOCK_REQ 410
+#define GSN_DICT_LOCK_CONF 411
+#define GSN_DICT_LOCK_REF 412
+#define GSN_DICT_UNLOCK_ORD 420
+
#endif
diff --git a/ndb/include/kernel/signaldata/AlterTable.hpp b/ndb/include/kernel/signaldata/AlterTable.hpp
index 16c9eb204c9..f5006c27fdb 100644
--- a/ndb/include/kernel/signaldata/AlterTable.hpp
+++ b/ndb/include/kernel/signaldata/AlterTable.hpp
@@ -114,6 +114,7 @@ public:
InvalidTableVersion = 241,
DropInProgress = 283,
Busy = 701,
+ BusyWithNR = 711,
NotMaster = 702,
InvalidFormat = 703,
AttributeNameTooLong = 704,
diff --git a/ndb/include/kernel/signaldata/CreateTable.hpp b/ndb/include/kernel/signaldata/CreateTable.hpp
index 481b323fdb0..7d3189cc126 100644
--- a/ndb/include/kernel/signaldata/CreateTable.hpp
+++ b/ndb/include/kernel/signaldata/CreateTable.hpp
@@ -77,6 +77,7 @@ public:
enum ErrorCode {
NoError = 0,
Busy = 701,
+ BusyWithNR = 711,
NotMaster = 702,
InvalidFormat = 703,
AttributeNameTooLong = 704,
diff --git a/ndb/include/kernel/signaldata/DictLock.hpp b/ndb/include/kernel/signaldata/DictLock.hpp
new file mode 100644
index 00000000000..3e29d762962
--- /dev/null
+++ b/ndb/include/kernel/signaldata/DictLock.hpp
@@ -0,0 +1,78 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef DICT_LOCK_HPP
+#define DICT_LOCK_HPP
+
+#include "SignalData.hpp"
+
+// see comments in Dbdict.hpp
+
+class DictLockReq {
+ friend class Dbdict;
+ friend class Dbdih;
+public:
+ STATIC_CONST( SignalLength = 3 );
+ enum LockType {
+ NoLock = 0,
+ NodeRestartLock = 1
+ };
+private:
+ Uint32 userPtr;
+ Uint32 lockType;
+ Uint32 userRef;
+};
+
+class DictLockConf {
+ friend class Dbdict;
+ friend class Dbdih;
+public:
+ STATIC_CONST( SignalLength = 3 );
+private:
+ Uint32 userPtr;
+ Uint32 lockType;
+ Uint32 lockPtr;
+};
+
+class DictLockRef {
+ friend class Dbdict;
+ friend class Dbdih;
+public:
+ STATIC_CONST( SignalLength = 3 );
+ enum ErrorCode {
+ NotMaster = 1,
+ InvalidLockType = 2,
+ BadUserRef = 3,
+ TooLate = 4,
+ TooManyRequests = 5
+ };
+private:
+ Uint32 userPtr;
+ Uint32 lockType;
+ Uint32 errorCode;
+};
+
+class DictUnlockOrd {
+ friend class Dbdict;
+ friend class Dbdih;
+public:
+ STATIC_CONST( SignalLength = 2 );
+private:
+ Uint32 lockPtr;
+ Uint32 lockType;
+};
+
+#endif
diff --git a/ndb/include/kernel/signaldata/DropTable.hpp b/ndb/include/kernel/signaldata/DropTable.hpp
index cae6aff8754..e762446d2b8 100644
--- a/ndb/include/kernel/signaldata/DropTable.hpp
+++ b/ndb/include/kernel/signaldata/DropTable.hpp
@@ -53,6 +53,7 @@ public:
enum ErrorCode {
Busy = 701,
+ BusyWithNR = 711,
NotMaster = 702,
NoSuchTable = 709,
InvalidTableVersion = 241,
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 0f3d75d50fb..4e015cc3d7e 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -701,6 +701,28 @@ extern "C" {
const int * node_list, int abort);
/**
+ * Stops cluster nodes
+ *
+ * @param handle Management handle.
+ * @param no_of_nodes Number of database nodes to stop<br>
+ * -1: All database and management nodes<br>
+ * 0: All database nodes in cluster<br>
+ * n: Stop the <var>n</var> node(s) specified in
+ * the array node_list
+ * @param node_list List of node IDs of database nodes to be stopped
+ * @param abort Don't perform graceful stop,
+ * but rather stop immediately
+ * @param disconnect Returns true if you need to disconnect to apply
+ * the stop command (e.g. stopping the mgm server
+ * that handle is connected to)
+ *
+ * @return Number of nodes stopped (-1 on error).
+ */
+ int ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes,
+ const int * node_list, int abort, int *disconnect);
+
+
+ /**
* Restart database nodes
*
* @param handle Management handle.
@@ -740,6 +762,31 @@ extern "C" {
int nostart, int abort);
/**
+ * Restart nodes
+ *
+ * @param handle Management handle.
+ * @param no_of_nodes Number of database nodes to be restarted:<br>
+ * 0: Restart all database nodes in the cluster<br>
+ * n: Restart the <var>n</var> node(s) specified in the
+ * array node_list
+ * @param node_list List of node IDs of database nodes to be restarted
+ * @param initial Remove filesystem from restarting node(s)
+ * @param nostart Don't actually start node(s) but leave them
+ * waiting for start command
+ * @param abort Don't perform graceful restart,
+ * but rather restart immediately
+ * @param disconnect Returns true if mgmapi client must disconnect from
+ * server to apply the requested operation. (e.g.
+ * restart the management server)
+ *
+ *
+ * @return Number of nodes stopped (-1 on error).
+ */
+ int ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes,
+ const int * node_list, int initial,
+ int nostart, int abort, int *disconnect);
+
+ /**
* Start database nodes
*
* @param handle Management handle.
@@ -1030,6 +1077,16 @@ extern "C" {
Uint32 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle);
/**
+ * Get the version of the mgm server we're talking to.
+ * Designed to allow switching of protocol depending on version
+ * so that new clients can speak to old servers in a compat mode
+ */
+ int ndb_mgm_get_version(NdbMgmHandle handle,
+ int *major, int *minor, int* build,
+ int len, char* str);
+
+
+ /**
* Config iterator
*/
typedef struct ndb_mgm_configuration_iterator ndb_mgm_configuration_iterator;
diff --git a/ndb/include/ndb_version.h.in b/ndb/include/ndb_version.h.in
index 38b72306d03..7e878803f46 100644
--- a/ndb/include/ndb_version.h.in
+++ b/ndb/include/ndb_version.h.in
@@ -60,5 +60,7 @@ char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ];
#define NDBD_INCL_NODECONF_VERSION_4 MAKE_VERSION(4,1,17)
#define NDBD_INCL_NODECONF_VERSION_5 MAKE_VERSION(5,0,18)
+#define NDBD_DICT_LOCK_VERSION_5 MAKE_VERSION(5,0,23)
+
#endif
diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp
index 76aa8e710ac..6d2c493d1ed 100644
--- a/ndb/include/ndbapi/NdbBlob.hpp
+++ b/ndb/include/ndbapi/NdbBlob.hpp
@@ -74,19 +74,41 @@ class NdbColumnImpl;
* NdbBlob methods return -1 on error and 0 on success, and use output
* parameters when necessary.
*
- * Operation types:
- * - insertTuple must use setValue if blob column is non-nullable
- * - readTuple with exclusive lock can also update existing value
- * - updateTuple can overwrite with setValue or update existing value
- * - writeTuple always overwrites and must use setValue if non-nullable
+ * Usage notes for different operation types:
+ *
+ * - insertTuple must use setValue if blob attribute is non-nullable
+ *
+ * - readTuple or scan readTuples with lock mode LM_CommittedRead is
+ * automatically upgraded to lock mode LM_Read if any blob attributes
+ * are accessed (to guarantee consistent view)
+ *
+ * - readTuple (with any lock mode) can only read blob value
+ *
+ * - updateTuple can either overwrite existing value with setValue or
+ * update it in active phase
+ *
+ * - writeTuple always overwrites blob value and must use setValue if
+ * blob attribute is non-nullable
+ *
* - deleteTuple creates implicit non-accessible blob handles
- * - scan with exclusive lock can also update existing value
- * - scan "lock takeover" update op must do its own getBlobHandle
+ *
+ * - scan readTuples (any lock mode) can use its blob handles only
+ * to read blob value
+ *
+ * - scan readTuples with lock mode LM_Exclusive can update row and blob
+ * value using updateCurrentTuple, where the operation returned must
+ * create its own blob handles explicitly
+ *
+ * - scan readTuples with lock mode LM_Exclusive can delete row (and
+ * therefore blob values) using deleteCurrentTuple, which creates
+ * implicit non-accessible blob handles
+ *
+ * - the operation returned by lockCurrentTuple cannot update blob value
*
* Bugs / limitations:
- * - lock mode upgrade should be handled automatically
- * - lock mode vs allowed operation is not checked
+ *
* - too many pending blob ops can blow up i/o buffers
+ *
* - table and its blob part tables are not created atomically
*/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
@@ -194,6 +216,9 @@ public:
/**
* Return error object. The error may be blob specific (below) or may
* be copied from a failed implicit operation.
+ *
+ * The error code is copied back to the operation unless the operation
+ * already has a non-zero error code.
*/
const NdbError& getNdbError() const;
/**
@@ -290,6 +315,7 @@ private:
bool isWriteOp();
bool isDeleteOp();
bool isScanOp();
+ bool isReadOnlyOp();
bool isTakeOverOp();
// computations
Uint32 getPartNumber(Uint64 pos);
@@ -323,9 +349,9 @@ private:
int preCommit();
int atNextResult();
// errors
- void setErrorCode(int anErrorCode, bool invalidFlag = true);
- void setErrorCode(NdbOperation* anOp, bool invalidFlag = true);
- void setErrorCode(NdbTransaction* aCon, bool invalidFlag = true);
+ void setErrorCode(int anErrorCode, bool invalidFlag = false);
+ void setErrorCode(NdbOperation* anOp, bool invalidFlag = false);
+ void setErrorCode(NdbTransaction* aCon, bool invalidFlag = false);
#ifdef VM_TRACE
int getOperationType() const;
friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
index e9f92d84d1c..638ecb17779 100644
--- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -61,11 +61,14 @@ public:
Uint32 parallel,
bool order_by,
bool order_desc = false,
- bool read_range_no = false) {
+ bool read_range_no = false,
+ bool keyinfo = false) {
Uint32 scan_flags =
(SF_OrderBy & -(Int32)order_by) |
(SF_Descending & -(Int32)order_desc) |
- (SF_ReadRangeNo & -(Int32)read_range_no);
+ (SF_ReadRangeNo & -(Int32)read_range_no) |
+ (SF_KeyInfo & -(Int32)keyinfo);
+
return readTuples(lock_mode, scan_flags, parallel);
}
#endif
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index 77b255dc2f4..5581e830f82 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -41,10 +41,11 @@ public:
* readTuples.
*/
enum ScanFlag {
- SF_TupScan = (1 << 16), // scan TUP - only LM_CommittedRead
+ SF_TupScan = (1 << 16), // scan TUP
SF_OrderBy = (1 << 24), // index scan in order
SF_Descending = (2 << 24), // index scan in descending order
- SF_ReadRangeNo = (4 << 24) // enable @ref get_range_no
+ SF_ReadRangeNo = (4 << 24), // enable @ref get_range_no
+ SF_KeyInfo = 1 // request KeyInfo to be sent back
};
/**
@@ -61,15 +62,14 @@ public:
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* readTuples
- *
* @param lock_mode Lock mode
* @param batch No of rows to fetch from each fragment at a time
* @param parallel No of fragments to scan in parallell
- * @note specifying 0 for batch and parallall means max performance
+ * @note specifying 0 for batch and parallell means max performance
*/
#ifdef ndb_readtuples_impossible_overload
int readTuples(LockMode lock_mode = LM_Read,
- Uint32 batch = 0, Uint32 parallel = 0);
+ Uint32 batch = 0, Uint32 parallel = 0, bool keyinfo = false);
#endif
inline int readTuples(int parallell){
@@ -142,6 +142,20 @@ public:
void close(bool forceSend = false, bool releaseOp = false);
/**
+ * Lock current tuple
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* lockCurrentTuple();
+ /**
+ * Lock current tuple
+ *
+ * @param lockTrans Transaction that should perform the lock
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* lockCurrentTuple(NdbTransaction* lockTrans);
+ /**
* Update current tuple
*
* @return an NdbOperation or NULL.
@@ -251,6 +265,19 @@ protected:
inline
NdbOperation*
+NdbScanOperation::lockCurrentTuple(){
+ return lockCurrentTuple(m_transConnection);
+}
+
+inline
+NdbOperation*
+NdbScanOperation::lockCurrentTuple(NdbTransaction* takeOverTrans){
+ return takeOverScanOp(NdbOperation::ReadRequest,
+ takeOverTrans);
+}
+
+inline
+NdbOperation*
NdbScanOperation::updateCurrentTuple(){
return updateCurrentTuple(m_transConnection);
}
diff --git a/ndb/include/util/ConfigValues.hpp b/ndb/include/util/ConfigValues.hpp
index 457488e3c42..8dfb3c83df3 100644
--- a/ndb/include/util/ConfigValues.hpp
+++ b/ndb/include/util/ConfigValues.hpp
@@ -96,6 +96,7 @@ public:
public:
ConfigValuesFactory(Uint32 keys = 50, Uint32 data = 10); // Initial
ConfigValuesFactory(ConfigValues * m_cfg); //
+ ~ConfigValuesFactory();
ConfigValues * m_cfg;
ConfigValues * getConfigValues();
diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp
index d8710d2058f..67e13dc805a 100644
--- a/ndb/src/common/debugger/SignalLoggerManager.cpp
+++ b/ndb/src/common/debugger/SignalLoggerManager.cpp
@@ -139,7 +139,7 @@ SignalLoggerManager::log(LogMode logMode, const char * params)
} else {
for (int i = 0; i < count; ++i){
BlockNumber number = getBlockNo(blocks[i]);
- cnt += log(SLM_ON, number-MIN_BLOCK_NO, logMode);
+ cnt += log(SLM_ON, number, logMode);
}
}
for(int i = 0; i<count; i++){
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 984d28819c0..5162679017a 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -647,6 +647,12 @@ const GsnName SignalNames [] = {
,{ GSN_TUX_MAINT_REF, "TUX_MAINT_REF" }
,{ GSN_TUX_BOUND_INFO, "TUX_BOUND_INFO" }
,{ GSN_ACC_LOCKREQ, "ACC_LOCKREQ" }
+
+ /* DICT LOCK */
+ ,{ GSN_DICT_LOCK_REQ, "DICT_LOCK_REQ" }
+ ,{ GSN_DICT_LOCK_CONF, "DICT_LOCK_CONF" }
+ ,{ GSN_DICT_LOCK_REF, "DICT_LOCK_REF" }
+ ,{ GSN_DICT_UNLOCK_ORD, "DICT_UNLOCK_ORD" }
};
const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName);
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index f0e50729f8d..cd78bc52027 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -1322,7 +1322,7 @@ TransporterRegistry::start_clients_thread()
else
{
ndbout_c("Management server closed connection early. "
- "It is probably being shut down (or has crashed). "
+ "It is probably being shut down (or has problems). "
"We will retry the connection.");
}
}
diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp
index 5c4b17c73ca..ae4fbfd2f71 100644
--- a/ndb/src/common/util/ConfigValues.cpp
+++ b/ndb/src/common/util/ConfigValues.cpp
@@ -294,6 +294,12 @@ ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
}
}
+ConfigValuesFactory::~ConfigValuesFactory()
+{
+ if(m_cfg)
+ free(m_cfg);
+}
+
ConfigValues *
ConfigValuesFactory::create(Uint32 keys, Uint32 data){
Uint32 sz = sizeof(ConfigValues);
@@ -528,7 +534,7 @@ ConfigValuesFactory::extractCurrentSection(const ConfigValues::ConstIterator & c
}
}
- ConfigValues * ret = fac->m_cfg;
+ ConfigValues * ret = fac->getConfigValues();
delete fac;
return ret;
}
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index f8e3d11f222..ddb99cb6b56 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -5,7 +5,7 @@ Next DBACC 3002
Next DBTUP 4013
Next DBLQH 5043
Next DBDICT 6007
-Next DBDIH 7174
+Next DBDIH 7177
Next DBTC 8037
Next CMVMI 9000
Next BACKUP 10022
@@ -312,6 +312,10 @@ Test Crashes in handling node restarts
7170: Crash when receiving START_PERMREF (InitialStartRequired)
+7174: Crash starting node before sending DICT_LOCK_REQ
+7175: Master sends one fake START_PERMREF (ZNODE_ALREADY_STARTING_ERROR)
+7176: Slave NR pretends master does not support DICT lock (rolling upgrade)
+
DICT:
6000 Crash during NR when receiving DICTSTARTREQ
6001 Crash during NR when receiving SCHEMA_INFO
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index 908e2a81345..d2f9150ade0 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -234,6 +234,7 @@ void Cmvmi::execEVENT_REP(Signal* signal)
void
Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
+ Uint32 senderRef = signal->getSendersBlockRef();
SubscriberPtr ptr;
jamEntry();
DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
@@ -251,7 +252,7 @@ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
* Create a new one
*/
if(subscribers.seize(ptr) == false){
- sendSignal(subReq->blockRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
+ sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
return;
}
ptr.p->logLevel.clear();
@@ -278,7 +279,7 @@ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
}
signal->theData[0] = ptr.i;
- sendSignal(ptr.p->blockRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
+ sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
DBUG_VOID_RETURN;
}
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index ca9daca428b..3cdba251492 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -203,6 +203,11 @@ void Dbdict::execCONTINUEB(Signal* signal)
sendGetTabResponse(signal);
break;
+ case ZDICT_LOCK_POLL:
+ jam();
+ checkDictLockQueue(signal, true);
+ break;
+
default :
ndbrequire(false);
break;
@@ -1208,7 +1213,9 @@ Dbdict::Dbdict(const class Configuration & conf):
c_opCreateTrigger(c_opRecordPool),
c_opDropTrigger(c_opRecordPool),
c_opAlterTrigger(c_opRecordPool),
- c_opRecordSequence(0)
+ c_opRecordSequence(0),
+ c_dictLockQueue(c_dictLockPool),
+ c_dictLockPoll(false)
{
BLOCK_CONSTRUCTOR(Dbdict);
@@ -1352,6 +1359,9 @@ Dbdict::Dbdict(const class Configuration & conf):
addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ);
+
+ addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
+ addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
}//Dbdict::Dbdict()
Dbdict::~Dbdict()
@@ -1764,6 +1774,8 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_opCreateTrigger.setSize(8);
c_opDropTrigger.setSize(8);
c_opAlterTrigger.setSize(8);
+
+ c_dictLockPool.setSize(32);
// Initialize schema file copies
c_schemaFile[0].schemaPage =
@@ -2821,6 +2833,10 @@ void Dbdict::execNODE_FAILREP(Signal* signal)
c_blockState = BS_NODE_FAILURE;
ok = true;
break;
+ case BS_NODE_RESTART:
+ jam();
+ ok = true;
+ break;
}
ndbrequire(ok);
@@ -2843,6 +2859,15 @@ void Dbdict::execNODE_FAILREP(Signal* signal)
}//if
}//for
+ /*
+ * NODE_FAILREP guarantees that no "in flight" signal from
+ * a dead node is accepted, and also that the job buffer contains
+ * no such (un-executed) signals. Therefore no DICT_UNLOCK_ORD
+ * from a dead node (leading to master crash) is possible after
+ * this clean-up removes the lock record.
+ */
+ removeStaleDictLocks(signal, theFailedNodes);
+
}//execNODE_FAILREP()
@@ -2911,6 +2936,12 @@ Dbdict::execCREATE_TABLE_REQ(Signal* signal){
break;
}
+ if (c_blockState == BS_NODE_RESTART){
+ jam();
+ parseRecord.errorCode = CreateTableRef::BusyWithNR;
+ break;
+ }
+
if (c_blockState != BS_IDLE){
jam();
parseRecord.errorCode = CreateTableRef::Busy;
@@ -3060,6 +3091,12 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal)
return;
}
+ if(c_blockState == BS_NODE_RESTART){
+ jam();
+ alterTableRef(signal, req, AlterTableRef::BusyWithNR);
+ return;
+ }
+
if(c_blockState != BS_IDLE){
jam();
alterTableRef(signal, req, AlterTableRef::Busy);
@@ -5372,6 +5409,12 @@ Dbdict::execDROP_TABLE_REQ(Signal* signal){
return;
}
+ if(c_blockState == BS_NODE_RESTART){
+ jam();
+ dropTableRef(signal, req, DropTableRef::BusyWithNR);
+ return;
+ }
+
if(c_blockState != BS_IDLE){
jam();
dropTableRef(signal, req, DropTableRef::Busy);
@@ -12170,6 +12213,275 @@ Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
}
}
+// DICT lock master
+
+const Dbdict::DictLockType*
+Dbdict::getDictLockType(Uint32 lockType)
+{
+ static const DictLockType lt[] = {
+ { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
+ };
+ for (int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
+ if (lt[i].lockType == lockType)
+ return &lt[i];
+ }
+ return NULL;
+}
+
+void
+Dbdict::sendDictLockInfoEvent(Uint32 pollCount)
+{
+ DictLockPtr loopPtr;
+ c_dictLockQueue.first(loopPtr);
+ unsigned count = 0;
+
+ char queue_buf[100];
+ char *p = &queue_buf[0];
+ const char *const q = &queue_buf[sizeof(queue_buf)];
+ *p = 0;
+
+ while (loopPtr.i != RNIL) {
+ jam();
+ my_snprintf(p, q-p, "%s%u%s",
+ ++count == 1 ? "" : " ",
+ (unsigned)refToNode(loopPtr.p->req.userRef),
+ loopPtr.p->locked ? "L" : "");
+ p += strlen(p);
+ c_dictLockQueue.next(loopPtr);
+ }
+
+ infoEvent("DICT: lock bs: %d ops: %d poll: %d cnt: %d queue: %s",
+ (int)c_blockState,
+ c_opRecordPool.getSize() - c_opRecordPool.getNoOfFree(),
+ c_dictLockPoll, (int)pollCount, queue_buf);
+}
+
+void
+Dbdict::sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text)
+{
+ infoEvent("DICT: %s %u for %s",
+ text,
+ (unsigned)refToNode(lockPtr.p->req.userRef), lockPtr.p->lt->text);
+}
+
+void
+Dbdict::execDICT_LOCK_REQ(Signal* signal)
+{
+ jamEntry();
+ const DictLockReq* req = (const DictLockReq*)&signal->theData[0];
+
+ // make sure bad request crashes slave, not master (us)
+
+ if (getOwnNodeId() != c_masterNodeId) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::NotMaster);
+ return;
+ }
+
+ const DictLockType* lt = getDictLockType(req->lockType);
+ if (lt == NULL) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::InvalidLockType);
+ return;
+ }
+
+ if (req->userRef != signal->getSendersBlockRef() ||
+ getNodeInfo(refToNode(req->userRef)).m_type != NodeInfo::DB) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::BadUserRef);
+ return;
+ }
+
+ if (c_aliveNodes.get(refToNode(req->userRef))) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::TooLate);
+ return;
+ }
+
+ DictLockPtr lockPtr;
+ if (! c_dictLockQueue.seize(lockPtr)) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::TooManyRequests);
+ return;
+ }
+
+ lockPtr.p->req = *req;
+ lockPtr.p->locked = false;
+ lockPtr.p->lt = lt;
+
+ checkDictLockQueue(signal, false);
+
+ if (! lockPtr.p->locked)
+ sendDictLockInfoEvent(lockPtr, "lock request by node");
+}
+
+void
+Dbdict::checkDictLockQueue(Signal* signal, bool poll)
+{
+ Uint32 pollCount = ! poll ? 0 : signal->theData[1];
+
+ DictLockPtr lockPtr;
+
+ do {
+ if (! c_dictLockQueue.first(lockPtr)) {
+ jam();
+ setDictLockPoll(signal, false, pollCount);
+ return;
+ }
+
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ break;
+ }
+
+ if (c_opRecordPool.getNoOfFree() != c_opRecordPool.getSize()) {
+ jam();
+ break;
+ }
+
+ ndbrequire(c_blockState == BS_IDLE);
+ lockPtr.p->locked = true;
+ c_blockState = lockPtr.p->lt->blockState;
+ sendDictLockConf(signal, lockPtr);
+
+ sendDictLockInfoEvent(lockPtr, "locked by node");
+ } while (0);
+
+ // poll while first request is open
+ // this routine is called again when it is removed for any reason
+
+ bool on = ! lockPtr.p->locked;
+ setDictLockPoll(signal, on, pollCount);
+}
+
+void
+Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
+{
+ jamEntry();
+ const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
+
+ DictLockPtr lockPtr;
+ c_dictLockQueue.getPtr(lockPtr, ord->lockPtr);
+ ndbrequire(lockPtr.p->lt->lockType == ord->lockType);
+
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize());
+ ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
+
+ c_blockState = BS_IDLE;
+ sendDictLockInfoEvent(lockPtr, "unlocked by node");
+ } else {
+ sendDictLockInfoEvent(lockPtr, "lock request removed by node");
+ }
+
+ c_dictLockQueue.release(lockPtr);
+
+ checkDictLockQueue(signal, false);
+}
+
+void
+Dbdict::sendDictLockConf(Signal* signal, DictLockPtr lockPtr)
+{
+ DictLockConf* conf = (DictLockConf*)&signal->theData[0];
+ const DictLockReq& req = lockPtr.p->req;
+
+ conf->userPtr = req.userPtr;
+ conf->lockType = req.lockType;
+ conf->lockPtr = lockPtr.i;
+
+ sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
+ DictLockConf::SignalLength, JBB);
+}
+
+void
+Dbdict::sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode)
+{
+ DictLockRef* ref = (DictLockRef*)&signal->theData[0];
+
+ ref->userPtr = req.userPtr;
+ ref->lockType = req.lockType;
+ ref->errorCode = errorCode;
+
+ sendSignal(req.userRef, GSN_DICT_LOCK_REF, signal,
+ DictLockRef::SignalLength, JBB);
+}
+
+// control polling
+
+void
+Dbdict::setDictLockPoll(Signal* signal, bool on, Uint32 pollCount)
+{
+ if (on) {
+ jam();
+ signal->theData[0] = ZDICT_LOCK_POLL;
+ signal->theData[1] = pollCount + 1;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
+ }
+
+ bool change = (c_dictLockPoll != on);
+
+ if (change) {
+ jam();
+ c_dictLockPoll = on;
+ }
+
+ // avoid too many messages if master is stuck busy (BS_NODE_FAILURE)
+ bool periodic =
+ pollCount < 8 ||
+ pollCount < 64 && pollCount % 8 == 0 ||
+ pollCount < 512 && pollCount % 64 == 0 ||
+ pollCount < 4096 && pollCount % 512 == 0 ||
+ pollCount % 4096 == 0; // about every 6 minutes
+
+ if (change || periodic)
+ sendDictLockInfoEvent(pollCount);
+}
+
+// NF handling
+
+void
+Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
+{
+ DictLockPtr loopPtr;
+ c_dictLockQueue.first(loopPtr);
+
+ if (getOwnNodeId() != c_masterNodeId) {
+ ndbrequire(loopPtr.i == RNIL);
+ return;
+ }
+
+ while (loopPtr.i != RNIL) {
+ jam();
+ DictLockPtr lockPtr = loopPtr;
+ c_dictLockQueue.next(loopPtr);
+
+ Uint32 nodeId = refToNode(lockPtr.p->req.userRef);
+
+ if (NodeBitmask::get(theFailedNodes, nodeId)) {
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize());
+ ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
+
+ c_blockState = BS_IDLE;
+
+ sendDictLockInfoEvent(lockPtr, "remove lock by failed node");
+ } else {
+ sendDictLockInfoEvent(lockPtr, "remove lock request by failed node");
+ }
+
+ c_dictLockQueue.release(lockPtr);
+ }
+ }
+
+ checkDictLockQueue(signal, false);
+}
+
+
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: STORE/RESTORE SCHEMA FILE---------------------- */
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 6b78fb86534..9c0bf65b69c 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -26,6 +26,7 @@
#include <pc.hpp>
#include <ArrayList.hpp>
#include <DLHashTable.hpp>
+#include <DLFifoList.hpp>
#include <CArray.hpp>
#include <KeyTable2.hpp>
#include <SimulatedBlock.hpp>
@@ -50,6 +51,7 @@
#include <signaldata/CreateTrig.hpp>
#include <signaldata/DropTrig.hpp>
#include <signaldata/AlterTrig.hpp>
+#include <signaldata/DictLock.hpp>
#include "SchemaFile.hpp"
#include <blocks/mutexes.hpp>
#include <SafeCounter.hpp>
@@ -63,6 +65,7 @@
/*--------------------------------------------------------------*/
#define ZPACK_TABLE_INTO_PAGES 0
#define ZSEND_GET_TAB_RESPONSE 3
+#define ZDICT_LOCK_POLL 4
/*--------------------------------------------------------------*/
@@ -587,6 +590,9 @@ private:
void execALTER_TAB_CONF(Signal* signal);
bool check_ndb_versions() const;
+ void execDICT_LOCK_REQ(Signal* signal);
+ void execDICT_UNLOCK_ORD(Signal* signal);
+
/*
* 2.4 COMMON STORED VARIABLES
*/
@@ -817,12 +823,43 @@ private:
// State variables
/* ----------------------------------------------------------------------- */
+#ifndef ndb_dbdict_log_block_state
enum BlockState {
BS_IDLE = 0,
BS_CREATE_TAB = 1,
BS_BUSY = 2,
- BS_NODE_FAILURE = 3
+ BS_NODE_FAILURE = 3,
+ BS_NODE_RESTART = 4
+ };
+#else // quick hack to log changes
+ enum {
+ BS_IDLE = 0,
+ BS_CREATE_TAB = 1,
+ BS_BUSY = 2,
+ BS_NODE_FAILURE = 3,
+ BS_NODE_RESTART = 4
+ };
+ struct BlockState;
+ friend struct BlockState;
+ struct BlockState {
+ BlockState() :
+ m_value(BS_IDLE) {
+ }
+ BlockState(int value) :
+ m_value(value) {
+ }
+ operator int() const {
+ return m_value;
+ }
+ BlockState& operator=(const BlockState& bs) {
+ Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
+ dict->infoEvent("DICT: bs %d->%d", m_value, bs.m_value);
+ m_value = bs.m_value;
+ return *this;
+ }
+ int m_value;
};
+#endif
BlockState c_blockState;
struct PackTable {
@@ -1722,6 +1759,65 @@ private:
// Unique key for operation XXX move to some system table
Uint32 c_opRecordSequence;
+ /*
+ * Master DICT can be locked in 2 mutually exclusive ways:
+ *
+ * 1) for schema ops, via operation records
+ * 2) against schema ops, via a lock queue
+ *
+ * Current use of 2) is by a starting node, to prevent schema ops
+ * until started. The ops are refused (BlockState != BS_IDLE),
+ * not queued.
+ *
+ * Master failure is not handled, in node start case the starting
+ * node will crash too anyway. Use lock table in future..
+ *
+ * The lock queue is "serial" but other behaviour is possible
+ * by checking lock types e.g. to allow parallel node starts.
+ *
+ * Checking release of last op record is not convenient with
+ * current structure (5.0). Instead we poll via continueB.
+ *
+ * XXX only table ops check BlockState
+ */
+
+ struct DictLockType {
+ DictLockReq::LockType lockType;
+ BlockState blockState;
+ const char* text;
+ };
+
+ struct DictLockRecord {
+ DictLockReq req;
+ const DictLockType* lt;
+ bool locked;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+
+ typedef Ptr<DictLockRecord> DictLockPtr;
+ ArrayPool<DictLockRecord> c_dictLockPool;
+ DLFifoList<DictLockRecord> c_dictLockQueue;
+ bool c_dictLockPoll;
+
+ static const DictLockType* getDictLockType(Uint32 lockType);
+ void sendDictLockInfoEvent(Uint32 pollCount);
+ void sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text);
+
+ void checkDictLockQueue(Signal* signal, bool poll);
+ void sendDictLockConf(Signal* signal, DictLockPtr lockPtr);
+ void sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode);
+
+ // control polling i.e. continueB loop
+ void setDictLockPoll(Signal* signal, bool on, Uint32 pollCount);
+
+ // NF handling
+ void removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes);
+
+
// Statement blocks
/* ------------------------------------------------------------ */
diff --git a/ndb/src/kernel/blocks/dbdict/DictLock.txt b/ndb/src/kernel/blocks/dbdict/DictLock.txt
new file mode 100644
index 00000000000..17f24119e9d
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbdict/DictLock.txt
@@ -0,0 +1,94 @@
+Lock master DICT against schema operations
+
+Implementation
+--------------
+
+[ see comments in Dbdict.hpp ]
+
+Use case: Node startup INR / NR
+-------------------------------
+
+Master DICT (like any block) keeps list of alive nodes (c_aliveNodes).
+These are participants in schema ops.
+
+(1) c_aliveNodes is initialized when DICT starts
+ in sp3 in READ_NODESCONF from CNTR
+
+(2) when slave node fails (in any sp of the slave node)
+ it is removed from c_aliveNodes in NODE_FAILREP
+
+(3) when slave starts, it is added to c_aliveNodes
+ in sp4 of the starting node in INCL_NODEREQ
+
+Slave DIH locks master DICT in sp2 and releases the lock when started.
+Based on the constraints:
+
+- the lock is taken when master DICT is known
+ DIH reads this in sp2 in READ_NODESCONF
+
+- the lock is taken before (3)
+
+- the lock is taken before copying starts and held until it is done
+ in sp4 DIH meta, DICT meta, tuple data
+
+- on INR in sp2 in START_PERMREQ the LCP info of the slave is erased
+ in all DIH in invalidateNodeLCP() - not safe under schema ops
+
+Signals:
+
+All but DICT_LOCK are standard v5.0 signals.
+s=starting node, m=master, a=all participants, l=local block.
+
+* sp2 - DICT_LOCK and START_PERM
+
+DIH/s
+ DICT_LOCK_REQ
+ DICT/m
+ DICT_LOCK_CONF
+DIH/s
+ START_PERMREQ
+ DIH/m
+ START_INFOREQ
+ DIH/a
+ invalidateNodeLCP() if INR
+ DIH/a
+ START_INFOCONF
+ DIH/m
+ START_PERMCONF
+DIH/s
+
+* sp4 - START_ME (copy metadata, no changes)
+
+DIH/s
+ START_MEREQ
+ DIH/m
+ COPY_TABREQ
+ DIH/s
+ COPY_TABCONF
+ DIH/m
+ DICTSTARTREQ
+ DICT/s
+ GET_SCHEMA_INFOREQ
+ DICT/m
+ SCHEMA_INFO
+ DICT/s
+ DICTSTARTCONF
+ DIH/m
+ INCL_NODEREQ
+ DIH/a
+ INCL_NODEREQ
+ ANY/l
+ INCL_NODECONF
+ DIH/a
+ INCL_NODECONF
+ DIH/m
+ START_MECONF
+DIH/s
+
+* sp7 - release DICT lock
+
+DIH/s
+ DICT_UNLOCK_ORD
+ DICT/m
+
+# vim: set et sw=4:
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index 78acf1ffd19..f4a33df9805 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -718,6 +718,9 @@ private:
void checkPrepDropTabComplete(Signal *, TabRecordPtr tabPtr);
void checkWaitDropTabFailedLqh(Signal *, Uint32 nodeId, Uint32 tableId);
+ void execDICT_LOCK_CONF(Signal* signal);
+ void execDICT_LOCK_REF(Signal* signal);
+
// Statement blocks
//------------------------------------
// Methods that send signals
@@ -935,6 +938,7 @@ private:
void initialStartCompletedLab(Signal *);
void allNodesLcpCompletedLab(Signal *);
void nodeRestartPh2Lab(Signal *);
+ void nodeRestartPh2Lab2(Signal *);
void initGciFilesLab(Signal *);
void dictStartConfLab(Signal *);
void nodeDictStartConfLab(Signal *);
@@ -1594,6 +1598,30 @@ private:
* Reply from nodeId
*/
void startInfoReply(Signal *, Uint32 nodeId);
+
+ /*
+ * Lock master DICT. Only current use is by starting node
+ * during NR. A pool of slave records is convenient anyway.
+ */
+ struct DictLockSlaveRecord {
+ Uint32 lockPtr;
+ Uint32 lockType;
+ bool locked;
+ Callback callback;
+ Uint32 nextPool;
+ };
+
+ typedef Ptr<DictLockSlaveRecord> DictLockSlavePtr;
+ ArrayPool<DictLockSlaveRecord> c_dictLockSlavePool;
+
+ // slave
+ void sendDictLockReq(Signal* signal, Uint32 lockType, Callback c);
+ void recvDictLockConf(Signal* signal);
+ void sendDictUnlockOrd(Signal* signal, Uint32 lockSlavePtrI);
+
+ // NR
+ Uint32 c_dictLockSlavePtrI_nodeRestart; // userPtr for NR
+ void recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret);
};
#if (DIH_CDATA_SIZE < _SYSFILE_SIZE32)
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
index cd987048577..2b878034258 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
@@ -66,6 +66,9 @@ void Dbdih::initData()
waitGCPProxyPool.setSize(ZPROXY_FILE_SIZE);
waitGCPMasterPool.setSize(ZPROXY_MASTER_FILE_SIZE);
+ c_dictLockSlavePool.setSize(1); // assert single usage
+ c_dictLockSlavePtrI_nodeRestart = RNIL;
+
cgcpOrderBlocked = 0;
c_lcpState.ctcCounter = 0;
cwaitLcpSr = false;
@@ -264,6 +267,9 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_CREATE_FRAGMENTATION_REQ,
&Dbdih::execCREATE_FRAGMENTATION_REQ);
+ addRecSignal(GSN_DICT_LOCK_CONF, &Dbdih::execDICT_LOCK_CONF);
+ addRecSignal(GSN_DICT_LOCK_REF, &Dbdih::execDICT_LOCK_REF);
+
apiConnectRecord = 0;
connectRecord = 0;
fileRecord = 0;
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 3ebad7f0cd2..c8a33715b9c 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -67,6 +67,7 @@
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/LqhFrag.hpp>
#include <signaldata/FsOpenReq.hpp>
+#include <signaldata/DictLock.hpp>
#include <DebuggerNames.hpp>
#include <EventLogger.hpp>
@@ -544,7 +545,7 @@ void Dbdih::execCONTINUEB(Signal* signal)
break;
case DihContinueB::ZSTART_PERMREQ_AGAIN:
jam();
- nodeRestartPh2Lab(signal);
+ nodeRestartPh2Lab2(signal);
return;
break;
case DihContinueB::SwitchReplica:
@@ -1284,6 +1285,7 @@ void Dbdih::execNDB_STTOR(Signal* signal)
case NodeState::ST_INITIAL_NODE_RESTART:
case NodeState::ST_NODE_RESTART:
jam();
+
/***********************************************************************
* When starting nodes while system is operational we must be controlled
* by the master since only one node restart is allowed at a time.
@@ -1294,7 +1296,7 @@ void Dbdih::execNDB_STTOR(Signal* signal)
req->startingRef = reference();
req->startingVersion = 0; // Obsolete
sendSignal(cmasterdihref, GSN_START_MEREQ, signal,
- StartMeReq::SignalLength, JBB);
+ StartMeReq::SignalLength, JBB);
return;
}
ndbrequire(false);
@@ -1354,6 +1356,24 @@ void Dbdih::execNDB_STTOR(Signal* signal)
}
ndbrequire(false);
break;
+ case ZNDB_SPH7:
+ jam();
+ switch (typestart) {
+ case NodeState::ST_INITIAL_START:
+ case NodeState::ST_SYSTEM_RESTART:
+ jam();
+ ndbsttorry10Lab(signal, __LINE__);
+ return;
+ case NodeState::ST_NODE_RESTART:
+ case NodeState::ST_INITIAL_NODE_RESTART:
+ jam();
+ sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart);
+ c_dictLockSlavePtrI_nodeRestart = RNIL;
+ ndbsttorry10Lab(signal, __LINE__);
+ return;
+ }
+ ndbrequire(false);
+ break;
default:
jam();
ndbsttorry10Lab(signal, __LINE__);
@@ -1564,6 +1584,34 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
/*---------------------------------------------------------------------------*/
void Dbdih::nodeRestartPh2Lab(Signal* signal)
{
+ /*
+ * Lock master DICT to avoid metadata operations during INR/NR.
+ * Done just before START_PERMREQ.
+ *
+ * It would be more elegant to do this just before START_MEREQ.
+ * The problem is, on INR we end up in massive invalidateNodeLCP
+ * which is not fully protected against metadata ops.
+ */
+ ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL);
+
+ // check that we are not yet taking part in schema ops
+ CRASH_INSERTION(7174);
+
+ Uint32 lockType = DictLockReq::NodeRestartLock;
+ Callback c = { safe_cast(&Dbdih::recvDictLockConf_nodeRestart), 0 };
+ sendDictLockReq(signal, lockType, c);
+}
+
+void Dbdih::recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret)
+{
+ ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL);
+ c_dictLockSlavePtrI_nodeRestart = data;
+
+ nodeRestartPh2Lab2(signal);
+}
+
+void Dbdih::nodeRestartPh2Lab2(Signal* signal)
+{
/*------------------------------------------------------------------------*/
// REQUEST FOR PERMISSION FROM MASTER TO START A NODE IN AN ALREADY
// RUNNING SYSTEM.
@@ -1574,7 +1622,7 @@ void Dbdih::nodeRestartPh2Lab(Signal* signal)
req->nodeId = cownNodeId;
req->startType = cstarttype;
sendSignal(cmasterdihref, GSN_START_PERMREQ, signal, 3, JBB);
-}//Dbdih::nodeRestartPh2Lab()
+}
void Dbdih::execSTART_PERMCONF(Signal* signal)
{
@@ -1696,12 +1744,12 @@ void Dbdih::execSTART_PERMREQ(Signal* signal)
const BlockReference retRef = req->blockRef;
const Uint32 nodeId = req->nodeId;
const Uint32 typeStart = req->startType;
-
CRASH_INSERTION(7122);
ndbrequire(isMaster());
ndbrequire(refToNode(retRef) == nodeId);
if ((c_nodeStartMaster.activeState) ||
- (c_nodeStartMaster.wait != ZFALSE)) {
+ (c_nodeStartMaster.wait != ZFALSE) ||
+ ERROR_INSERTED_CLEAR(7175)) {
jam();
signal->theData[0] = nodeId;
signal->theData[1] = StartPermRef::ZNODE_ALREADY_STARTING_ERROR;
@@ -8354,7 +8402,7 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){
*--------_----------------------------------------------------- */
const Uint32 nextCrashed = noCrashedReplicas + 1;
replicaPtr.p->noCrashedReplicas = nextCrashed;
- arrGuard(nextCrashed, 8);
+ arrGuardErr(nextCrashed, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS);
replicaPtr.p->createGci[nextCrashed] = newestRestorableGCI + 1;
ndbrequire(newestRestorableGCI + 1 != 0xF1F1F1F1);
replicaPtr.p->replicaLastGci[nextCrashed] = (Uint32)-1;
@@ -10448,6 +10496,10 @@ void Dbdih::crashSystemAtGcpStop(Signal* signal)
c_copyGCIMaster.m_copyReason,
c_copyGCIMaster.m_waiting);
break;
+ case GCP_READY: // shut up lint
+ case GCP_PREPARE_SENT:
+ case GCP_COMMIT_SENT:
+ break;
}
ndbout_c("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d",
@@ -14639,3 +14691,118 @@ Dbdih::NodeRecord::NodeRecord(){
copyCompleted = false;
allowNodeStart = true;
}
+
+// DICT lock slave
+
+void
+Dbdih::sendDictLockReq(Signal* signal, Uint32 lockType, Callback c)
+{
+ DictLockReq* req = (DictLockReq*)&signal->theData[0];
+ DictLockSlavePtr lockPtr;
+
+ c_dictLockSlavePool.seize(lockPtr);
+ ndbrequire(lockPtr.i != RNIL);
+
+ req->userPtr = lockPtr.i;
+ req->lockType = lockType;
+ req->userRef = reference();
+
+ lockPtr.p->lockPtr = RNIL;
+ lockPtr.p->lockType = lockType;
+ lockPtr.p->locked = false;
+ lockPtr.p->callback = c;
+
+ // handle rolling upgrade
+ {
+ Uint32 masterVersion = getNodeInfo(cmasterNodeId).m_version;
+
+ unsigned int get_major = getMajor(masterVersion);
+ unsigned int get_minor = getMinor(masterVersion);
+ unsigned int get_build = getBuild(masterVersion);
+
+ ndbrequire(get_major == 4 || get_major == 5);
+
+ if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
+ ERROR_INSERTED(7176)) {
+ jam();
+
+ infoEvent("DIH: detect upgrade: master node %u old version %u.%u.%u",
+ (unsigned int)cmasterNodeId, get_major, get_minor, get_build);
+
+ DictLockConf* conf = (DictLockConf*)&signal->theData[0];
+ conf->userPtr = lockPtr.i;
+ conf->lockType = lockType;
+ conf->lockPtr = ZNIL;
+
+ sendSignal(reference(), GSN_DICT_LOCK_CONF, signal,
+ DictLockConf::SignalLength, JBB);
+ return;
+ }
+ }
+
+ BlockReference dictMasterRef = calcDictBlockRef(cmasterNodeId);
+ sendSignal(dictMasterRef, GSN_DICT_LOCK_REQ, signal,
+ DictLockReq::SignalLength, JBB);
+}
+
+void
+Dbdih::execDICT_LOCK_CONF(Signal* signal)
+{
+ jamEntry();
+ recvDictLockConf(signal);
+}
+
+void
+Dbdih::execDICT_LOCK_REF(Signal* signal)
+{
+ jamEntry();
+ ndbrequire(false);
+}
+
+void
+Dbdih::recvDictLockConf(Signal* signal)
+{
+ const DictLockConf* conf = (const DictLockConf*)&signal->theData[0];
+
+ DictLockSlavePtr lockPtr;
+ c_dictLockSlavePool.getPtr(lockPtr, conf->userPtr);
+
+ lockPtr.p->lockPtr = conf->lockPtr;
+ ndbrequire(lockPtr.p->lockType == conf->lockType);
+ ndbrequire(lockPtr.p->locked == false);
+ lockPtr.p->locked = true;
+
+ lockPtr.p->callback.m_callbackData = lockPtr.i;
+ execute(signal, lockPtr.p->callback, 0);
+}
+
+void
+Dbdih::sendDictUnlockOrd(Signal* signal, Uint32 lockSlavePtrI)
+{
+ DictUnlockOrd* ord = (DictUnlockOrd*)&signal->theData[0];
+
+ DictLockSlavePtr lockPtr;
+ c_dictLockSlavePool.getPtr(lockPtr, lockSlavePtrI);
+
+ ord->lockPtr = lockPtr.p->lockPtr;
+ ord->lockType = lockPtr.p->lockType;
+
+ c_dictLockSlavePool.release(lockPtr);
+
+ // handle rolling upgrade
+ {
+ Uint32 masterVersion = getNodeInfo(cmasterNodeId).m_version;
+
+ unsigned int get_major = getMajor(masterVersion);
+ ndbrequire(get_major == 4 || get_major == 5);
+
+ if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
+ ERROR_INSERTED(7176)) {
+ return;
+ }
+ }
+
+ BlockReference dictMasterRef = calcDictBlockRef(cmasterNodeId);
+ sendSignal(dictMasterRef, GSN_DICT_UNLOCK_ORD, signal,
+ DictUnlockOrd::SignalLength, JBB);
+}
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 19a003f00fc..56e93e6ee01 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -17989,7 +17989,8 @@ void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
logFilePtr.p->currentLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logFilePtr.p->currentFilepage++;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
+ ptrCheckGuardErr(logPagePtr, clogPageFileSize, logPageRecord,
+ NDBD_EXIT_SR_REDOLOG);
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
logPartPtr.p->execSrPagesRead--;
logPartPtr.p->execSrPagesExecuted++;
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 9a7256b4a55..b9bf522f7c8 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -2477,7 +2477,7 @@ void Qmgr::execDISCONNECT_REP(Signal* signal)
{
jam();
CRASH_INSERTION(932);
- BaseString::snprintf(buf, 100, "Node %u disconected", nodeId);
+ BaseString::snprintf(buf, 100, "Node %u disconnected", nodeId);
progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
ndbrequire(false);
}
@@ -2500,7 +2500,7 @@ void Qmgr::execDISCONNECT_REP(Signal* signal)
ndbrequire(false);
case ZAPI_INACTIVE:
{
- BaseString::snprintf(buf, 100, "Node %u disconected", nodeId);
+ BaseString::snprintf(buf, 100, "Node %u disconnected", nodeId);
progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
ndbrequire(false);
}
diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c
index 6a14d8b7ffd..257af4c5b1b 100644
--- a/ndb/src/kernel/error/ndbd_exit_codes.c
+++ b/ndb/src/kernel/error/ndbd_exit_codes.c
@@ -51,8 +51,9 @@ static const ErrStruct errArray[] =
{NDBD_EXIT_SYSTEM_ERROR, XIE,
"System error, node killed during node restart by other node"},
{NDBD_EXIT_INDEX_NOTINRANGE, XIE, "Array index out of range"},
- {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Arbitrator shutdown, "
- "please investigate error(s) on other node(s)"},
+ {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Node lost connection to other nodes and "
+ "can not form a unpartitioned cluster, please investigate if there are "
+ "error(s) on other node(s)"},
{NDBD_EXIT_POINTER_NOTINRANGE, XIE, "Pointer too large"},
{NDBD_EXIT_SR_OTHERNODEFAILED, XRE, "Another node failed during system "
"restart, please investigate error(s) on other node(s)"},
@@ -94,7 +95,7 @@ static const ErrStruct errArray[] =
{NDBD_EXIT_WATCHDOG_TERMINATE, XIE, "WatchDog terminate, internal error "
"or massive overload on the machine running this node"},
{NDBD_EXIT_SIGNAL_LOST_SEND_BUFFER_FULL, XCR,
- "Signal lost, out of send buffer memory, please increase SendBufferMemory"},
+ "Signal lost, out of send buffer memory, please increase SendBufferMemory or lower the load"},
{NDBD_EXIT_SIGNAL_LOST, XIE, "Signal lost (unknown reason)"},
{NDBD_EXIT_ILLEGAL_SIGNAL, XIE,
"Illegal signal (version mismatch a possibility)"},
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index 7c1763485ce..649ae7cae3f 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -420,6 +420,10 @@ int main(int argc, char** argv)
FILE * signalLog = fopen(buf, "a");
globalSignalLoggers.setOwnNodeId(globalData.ownId);
globalSignalLoggers.setOutputStream(signalLog);
+#if 0 // to log startup
+ globalSignalLoggers.log(SignalLoggerManager::LogInOut, "BLOCK=DBDICT,DBDIH");
+ globalData.testOn = 1;
+#endif
#endif
catchsigs(false);
diff --git a/ndb/src/kernel/vm/DLFifoList.hpp b/ndb/src/kernel/vm/DLFifoList.hpp
index b139ade831d..963ab007b65 100644
--- a/ndb/src/kernel/vm/DLFifoList.hpp
+++ b/ndb/src/kernel/vm/DLFifoList.hpp
@@ -115,6 +115,13 @@ public:
*/
bool hasNext(const Ptr<T> &) const;
+ /**
+ * Check if prev exists i.e. this is not first
+ *
+ * NOTE ptr must be both p & i
+ */
+ bool hasPrev(const Ptr<T> &) const;
+
Uint32 noOfElements() const {
Uint32 c = 0;
Uint32 i = head.firstItem;
@@ -357,4 +364,11 @@ DLFifoList<T>::hasNext(const Ptr<T> & p) const {
return p.p->nextList != RNIL;
}
+template <class T>
+inline
+bool
+DLFifoList<T>::hasPrev(const Ptr<T> & p) const {
+ return p.p->prevList != RNIL;
+}
+
#endif
diff --git a/ndb/src/kernel/vm/pc.hpp b/ndb/src/kernel/vm/pc.hpp
index 6aeda59224f..95839c48e4e 100644
--- a/ndb/src/kernel/vm/pc.hpp
+++ b/ndb/src/kernel/vm/pc.hpp
@@ -125,11 +125,13 @@
#ifdef ERROR_INSERT
#define ERROR_INSERT_VARIABLE UintR cerrorInsert
#define ERROR_INSERTED(x) (cerrorInsert == (x))
+#define ERROR_INSERTED_CLEAR(x) (cerrorInsert == (x) ? (cerrorInsert = 0, true) : false)
#define SET_ERROR_INSERT_VALUE(x) cerrorInsert = x
#define CLEAR_ERROR_INSERT_VALUE cerrorInsert = 0
#else
#define ERROR_INSERT_VARIABLE typedef void * cerrorInsert // Will generate compiler error if used
#define ERROR_INSERTED(x) false
+#define ERROR_INSERTED_CLEAR(x) false
#define SET_ERROR_INSERT_VALUE(x)
#define CLEAR_ERROR_INSERT_VALUE
#endif
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index 061360428af..4428b158b6b 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -27,6 +27,7 @@
#include <mgmapi_debug.h>
#include "mgmapi_configuration.hpp"
#include <socket_io.h>
+#include <version.h>
#include <NdbOut.hpp>
#include <SocketServer.hpp>
@@ -103,6 +104,9 @@ struct ndb_mgm_handle {
#endif
FILE *errstream;
char *m_name;
+ int mgmd_version_major;
+ int mgmd_version_minor;
+ int mgmd_version_build;
};
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
@@ -168,6 +172,10 @@ ndb_mgm_create_handle()
h->logfile = 0;
#endif
+ h->mgmd_version_major= -1;
+ h->mgmd_version_minor= -1;
+ h->mgmd_version_build= -1;
+
DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h));
DBUG_RETURN(h);
}
@@ -361,8 +369,9 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
* Print some info about why the parser returns NULL
*/
fprintf(handle->errstream,
- "Error in mgm protocol parser. cmd: >%s< status: %d curr: %d\n",
- cmd, (Uint32)ctx.m_status, ctx.m_currentToken);
+ "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n",
+ cmd, (Uint32)ctx.m_status,
+ (ctx.m_currentToken)?ctx.m_currentToken:"NULL");
DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
ctx.m_status, ctx.m_currentToken));
}
@@ -678,7 +687,11 @@ ndb_mgm_get_status(NdbMgmHandle handle)
out.println("");
char buf[1024];
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
+ return NULL;
+ }
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
@@ -687,7 +700,11 @@ ndb_mgm_get_status(NdbMgmHandle handle)
return NULL;
}
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
+ return NULL;
+ }
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
@@ -710,6 +727,13 @@ ndb_mgm_get_status(NdbMgmHandle handle)
malloc(sizeof(ndb_mgm_cluster_state)+
noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
+ if(!state)
+ {
+ SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
+ "Allocating ndb_mgm_cluster_state");
+ return NULL;
+ }
+
state->no_of_nodes= noOfNodes;
ndb_mgm_node_state * ptr = &state->node_states[0];
int nodeId = 0;
@@ -719,7 +743,13 @@ ndb_mgm_get_status(NdbMgmHandle handle)
}
i = -1; ptr--;
for(; i<noOfNodes; ){
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ free(state);
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
+ "Probably disconnected");
+ return NULL;
+ }
tmp.assign(buf);
if(tmp.trim() == ""){
@@ -829,37 +859,81 @@ ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
}
-
extern "C"
-int
+int
ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
int abort)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop2");
- const ParserRow<ParserDummy> stop_reply[] = {
+ int disconnect;
+ return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect);
+}
+
+
+extern "C"
+int
+ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
+ int abort, int *disconnect)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3");
+ const ParserRow<ParserDummy> stop_reply_v1[] = {
+ MGM_CMD("stop reply", NULL, ""),
+ MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+ const ParserRow<ParserDummy> stop_reply_v2[] = {
MGM_CMD("stop reply", NULL, ""),
MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"),
MGM_END()
};
+
CHECK_HANDLE(handle, -1);
CHECK_CONNECTED(handle, -1);
- if(no_of_nodes < 0){
+ if(handle->mgmd_version_build==-1)
+ {
+ char verstr[50];
+ if(!ndb_mgm_get_version(handle,
+ &(handle->mgmd_version_major),
+ &(handle->mgmd_version_minor),
+ &(handle->mgmd_version_build),
+ sizeof(verstr),
+ verstr))
+ {
+ return -1;
+ }
+ }
+ int use_v2= ((handle->mgmd_version_major==5)
+ && (
+ (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
+ ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
+ ||(handle->mgmd_version_minor>1)
+ )
+ )
+ || (handle->mgmd_version_major>5);
+
+ if(no_of_nodes < -1){
SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES,
"Negative number of nodes requested to stop");
return -1;
}
Uint32 stoppedNoOfNodes = 0;
- if(no_of_nodes == 0){
+ if(no_of_nodes <= 0){
/**
- * All database nodes should be stopped
+ * All nodes should be stopped (all or just db)
*/
Properties args;
args.put("abort", abort);
+ if(use_v2)
+ args.put("stop", (no_of_nodes==-1)?"mgm,db":"db");
const Properties *reply;
- reply = ndb_mgm_call(handle, stop_reply, "stop all", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args);
+ else
+ reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args);
CHECK_REPLY(reply, -1);
if(!reply->get("stopped", &stoppedNoOfNodes)){
@@ -868,6 +942,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
delete reply;
return -1;
}
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
BaseString result;
reply->get("result", result);
if(strcmp(result.c_str(), "Ok") != 0) {
@@ -893,7 +971,11 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
args.put("abort", abort);
const Properties *reply;
- reply = ndb_mgm_call(handle, stop_reply, "stop", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args);
+ else
+ reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args);
+
CHECK_REPLY(reply, stoppedNoOfNodes);
if(!reply->get("stopped", &stoppedNoOfNodes)){
SET_ERROR(handle, NDB_MGM_STOP_FAILED,
@@ -901,6 +983,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
delete reply;
return -1;
}
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
BaseString result;
reply->get("result", result);
if(strcmp(result.c_str(), "Ok") != 0) {
@@ -914,20 +1000,69 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
extern "C"
int
+ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
+ return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
+}
+
+extern "C"
+int
ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
int initial, int nostart, int abort)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart2");
+ int disconnect;
+
+ return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart,
+ abort, &disconnect);
+}
+
+extern "C"
+int
+ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
+ int initial, int nostart, int abort, int *disconnect)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3");
Uint32 restarted = 0;
- const ParserRow<ParserDummy> restart_reply[] = {
+ const ParserRow<ParserDummy> restart_reply_v1[] = {
MGM_CMD("restart reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
MGM_END()
};
+ const ParserRow<ParserDummy> restart_reply_v2[] = {
+ MGM_CMD("restart reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
+ MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"),
+ MGM_END()
+ };
+
CHECK_HANDLE(handle, -1);
CHECK_CONNECTED(handle, -1);
-
+
+ if(handle->mgmd_version_build==-1)
+ {
+ char verstr[50];
+ if(!ndb_mgm_get_version(handle,
+ &(handle->mgmd_version_major),
+ &(handle->mgmd_version_minor),
+ &(handle->mgmd_version_build),
+ sizeof(verstr),
+ verstr))
+ {
+ return -1;
+ }
+ }
+ int use_v2= ((handle->mgmd_version_major==5)
+ && (
+ (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
+ ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
+ ||(handle->mgmd_version_minor>1)
+ )
+ )
+ || (handle->mgmd_version_major>5);
+
if(no_of_nodes < 0){
SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
"Restart requested of negative number of nodes");
@@ -942,7 +1077,7 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
const Properties *reply;
const int timeout = handle->read_timeout;
handle->read_timeout= 5*60*1000; // 5 minutes
- reply = ndb_mgm_call(handle, restart_reply, "restart all", &args);
+ reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args);
handle->read_timeout= timeout;
CHECK_REPLY(reply, -1);
@@ -978,7 +1113,10 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
const Properties *reply;
const int timeout = handle->read_timeout;
handle->read_timeout= 5*60*1000; // 5 minutes
- reply = ndb_mgm_call(handle, restart_reply, "restart node", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args);
+ else
+ reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args);
handle->read_timeout= timeout;
if(reply != NULL) {
BaseString result;
@@ -989,20 +1127,16 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
return -1;
}
reply->get("restarted", &restarted);
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
delete reply;
}
return restarted;
}
-extern "C"
-int
-ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
-{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
- return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
-}
-
static const char *clusterlog_severity_names[]=
{ "enabled", "debug", "info", "warning", "error", "critical", "alert" };
@@ -1811,7 +1945,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
}
delete prop;
- return (ndb_mgm_configuration*)cvf.m_cfg;
+ return (ndb_mgm_configuration*)cvf.getConfigValues();
} while(0);
delete prop;
@@ -2361,4 +2495,56 @@ int ndb_mgm_end_session(NdbMgmHandle handle)
DBUG_RETURN(0);
}
+extern "C"
+int ndb_mgm_get_version(NdbMgmHandle handle,
+ int *major, int *minor, int *build, int len, char* str)
+{
+ DBUG_ENTER("ndb_mgm_get_version");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("version", NULL, ""),
+ MGM_ARG("id", Int, Mandatory, "ID"),
+ MGM_ARG("major", Int, Mandatory, "Major"),
+ MGM_ARG("minor", Int, Mandatory, "Minor"),
+ MGM_ARG("string", String, Mandatory, "String"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get version", &args);
+ CHECK_REPLY(prop, 0);
+
+ Uint32 id;
+ if(!prop->get("id",&id)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+ *build= getBuild(id);
+
+ if(!prop->get("major",(Uint32*)major)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ if(!prop->get("minor",(Uint32*)minor)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ BaseString result;
+ if(!prop->get("string", result)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ strncpy(str, result.c_str(), len);
+
+ delete prop;
+ DBUG_RETURN(1);
+}
+
template class Vector<const ParserRow<ParserDummy>*>;
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index 14cd3fba42b..58b98671b14 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -162,6 +162,7 @@ private:
NdbMgmHandle m_mgmsrv;
NdbMgmHandle m_mgmsrv2;
+ const char *m_constr;
bool m_connected;
int m_verbose;
int try_reconnect;
@@ -390,22 +391,7 @@ convert(const char* s, int& val) {
CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
: m_verbose(verbose)
{
- m_mgmsrv = ndb_mgm_create_handle();
- if(m_mgmsrv == NULL) {
- ndbout_c("Cannot create handle to management server.");
- exit(-1);
- }
- m_mgmsrv2 = ndb_mgm_create_handle();
- if(m_mgmsrv2 == NULL) {
- ndbout_c("Cannot create 2:nd handle to management server.");
- exit(-1);
- }
- if (ndb_mgm_set_connectstring(m_mgmsrv, _host))
- {
- printError();
- exit(-1);
- }
-
+ m_constr= _host;
m_connected= false;
m_event_thread= 0;
try_reconnect = 0;
@@ -422,8 +408,6 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
CommandInterpreter::~CommandInterpreter()
{
disconnect();
- ndb_mgm_destroy_handle(&m_mgmsrv);
- ndb_mgm_destroy_handle(&m_mgmsrv2);
}
static bool
@@ -445,15 +429,14 @@ emptyString(const char* s)
void
CommandInterpreter::printError()
{
- if (ndb_mgm_check_connection(m_mgmsrv))
- {
- m_connected= false;
- disconnect();
- }
ndbout_c("* %5d: %s",
ndb_mgm_get_latest_error(m_mgmsrv),
ndb_mgm_get_latest_error_msg(m_mgmsrv));
ndbout_c("* %s", ndb_mgm_get_latest_error_desc(m_mgmsrv));
+ if (ndb_mgm_check_connection(m_mgmsrv))
+ {
+ disconnect();
+ }
}
//*****************************************************************************
@@ -497,78 +480,97 @@ event_thread_run(void* m)
}
bool
-CommandInterpreter::connect()
+CommandInterpreter::connect()
{
DBUG_ENTER("CommandInterpreter::connect");
- if(!m_connected)
+
+ if(m_connected)
+ DBUG_RETURN(m_connected);
+
+ m_mgmsrv = ndb_mgm_create_handle();
+ if(m_mgmsrv == NULL) {
+ ndbout_c("Cannot create handle to management server.");
+ exit(-1);
+ }
+ m_mgmsrv2 = ndb_mgm_create_handle();
+ if(m_mgmsrv2 == NULL) {
+ ndbout_c("Cannot create 2:nd handle to management server.");
+ exit(-1);
+ }
+
+ if (ndb_mgm_set_connectstring(m_mgmsrv, m_constr))
{
- if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
+ printError();
+ exit(-1);
+ }
+
+ if(ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
+ DBUG_RETURN(m_connected); // couldn't connect, always false
+
+ const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
+ unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
+ BaseString constr;
+ constr.assfmt("%s:%d",host,port);
+ if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
+ !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
+ {
+ DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
+ host, port));
+ assert(m_event_thread == 0);
+ assert(do_event_thread == 0);
+ do_event_thread= 0;
+ m_event_thread = NdbThread_Create(event_thread_run,
+ (void**)&m_mgmsrv2,
+ 32768,
+ "CommandInterpreted_event_thread",
+ NDB_THREAD_PRIO_LOW);
+ if (m_event_thread != 0)
{
- const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
- unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
- BaseString constr;
- constr.assfmt("%s:%d",host,port);
- if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
- !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
- {
- DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
- host, port));
- assert(m_event_thread == 0);
- assert(do_event_thread == 0);
- do_event_thread= 0;
- m_event_thread = NdbThread_Create(event_thread_run,
- (void**)&m_mgmsrv2,
- 32768,
- "CommandInterpreted_event_thread",
- NDB_THREAD_PRIO_LOW);
- if (m_event_thread != 0)
- {
- DBUG_PRINT("info",("Thread created ok, waiting for started..."));
- int iter= 1000; // try for 30 seconds
- while(do_event_thread == 0 &&
- iter-- > 0)
- NdbSleep_MilliSleep(30);
- }
- if (m_event_thread == 0 ||
- do_event_thread == 0 ||
- do_event_thread == -1)
- {
- DBUG_PRINT("info",("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d",
- errno));
- printf("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d\n", errno);
- do_event_thread= 0;
- if (m_event_thread)
- {
- void *res;
- NdbThread_WaitFor(m_event_thread, &res);
- NdbThread_Destroy(&m_event_thread);
- }
- ndb_mgm_disconnect(m_mgmsrv2);
- }
- }
- else
- {
- DBUG_PRINT("warning",
- ("Could not do 2:nd connect to mgmtserver for event listening"));
- DBUG_PRINT("info", ("code: %d, msg: %s",
- ndb_mgm_get_latest_error(m_mgmsrv2),
- ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
- printf("Warning, event connect failed, degraded printouts as result\n");
- printf("code: %d, msg: %s\n",
- ndb_mgm_get_latest_error(m_mgmsrv2),
- ndb_mgm_get_latest_error_msg(m_mgmsrv2));
- }
- m_connected= true;
- DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port));
- if (m_verbose)
+ DBUG_PRINT("info",("Thread created ok, waiting for started..."));
+ int iter= 1000; // try for 30 seconds
+ while(do_event_thread == 0 &&
+ iter-- > 0)
+ NdbSleep_MilliSleep(30);
+ }
+ if (m_event_thread == 0 ||
+ do_event_thread == 0 ||
+ do_event_thread == -1)
+ {
+ DBUG_PRINT("info",("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d",
+ errno));
+ printf("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d\n", errno);
+ do_event_thread= 0;
+ if (m_event_thread)
{
- printf("Connected to Management Server at: %s:%d\n",
- host, port);
+ void *res;
+ NdbThread_WaitFor(m_event_thread, &res);
+ NdbThread_Destroy(&m_event_thread);
}
+ ndb_mgm_disconnect(m_mgmsrv2);
}
}
+ else
+ {
+ DBUG_PRINT("warning",
+ ("Could not do 2:nd connect to mgmtserver for event listening"));
+ DBUG_PRINT("info", ("code: %d, msg: %s",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
+ printf("Warning, event connect failed, degraded printouts as result\n");
+ printf("code: %d, msg: %s\n",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2));
+ }
+ m_connected= true;
+ DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port));
+ if (m_verbose)
+ {
+ printf("Connected to Management Server at: %s:%d\n",
+ host, port);
+ }
+
DBUG_RETURN(m_connected);
}
@@ -576,20 +578,18 @@ bool
CommandInterpreter::disconnect()
{
DBUG_ENTER("CommandInterpreter::disconnect");
+
if (m_event_thread) {
void *res;
do_event_thread= 0;
NdbThread_WaitFor(m_event_thread, &res);
NdbThread_Destroy(&m_event_thread);
m_event_thread= 0;
- ndb_mgm_disconnect(m_mgmsrv2);
+ ndb_mgm_destroy_handle(&m_mgmsrv2);
}
if (m_connected)
{
- if (ndb_mgm_disconnect(m_mgmsrv) == -1) {
- ndbout_c("Could not disconnect from management server");
- printError();
- }
+ ndb_mgm_destroy_handle(&m_mgmsrv);
m_connected= false;
}
DBUG_RETURN(true);
@@ -1057,7 +1057,8 @@ CommandInterpreter::executeShutdown(char* parameters)
NdbAutoPtr<char> ap1((char*)state);
int result = 0;
- result = ndb_mgm_stop(m_mgmsrv, 0, 0);
+ int need_disconnect;
+ result = ndb_mgm_stop3(m_mgmsrv, -1, 0, 0, &need_disconnect);
if (result < 0) {
ndbout << "Shutdown of NDB Cluster node(s) failed." << endl;
printError();
@@ -1066,28 +1067,11 @@ CommandInterpreter::executeShutdown(char* parameters)
ndbout << result << " NDB Cluster node(s) have shutdown." << endl;
- int mgm_id= 0;
- mgm_id= ndb_mgm_get_mgmd_nodeid(m_mgmsrv);
- if (mgm_id == 0)
- {
- ndbout << "Unable to locate management server, "
- << "shutdown manually with <id> STOP"
+ if(need_disconnect) {
+ ndbout << "Disconnecting to allow management server to shutdown."
<< endl;
- return 1;
- }
-
- result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id);
- if (result <= 0) {
- ndbout << "Shutdown of NDB Cluster management server failed." << endl;
- printError();
- if (result == 0)
- return 1;
- return result;
+ disconnect();
}
-
- m_connected= false;
- disconnect();
- ndbout << "NDB Cluster management server shutdown." << endl;
return 0;
}
@@ -1311,12 +1295,7 @@ CommandInterpreter::executeConnect(char* parameters)
{
disconnect();
if (!emptyString(parameters)) {
- if (ndb_mgm_set_connectstring(m_mgmsrv,
- BaseString(parameters).trim().c_str()))
- {
- printError();
- return;
- }
+ m_constr= BaseString(parameters).trim().c_str();
}
connect();
}
@@ -1481,6 +1460,7 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
unsigned command_pos,
int *node_ids, int no_of_nodes)
{
+ int need_disconnect;
int abort= 0;
for (; command_pos < command_list.size(); command_pos++)
{
@@ -1495,7 +1475,8 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
return;
}
- int result= ndb_mgm_stop2(m_mgmsrv, no_of_nodes, node_ids, abort);
+ int result= ndb_mgm_stop3(m_mgmsrv, no_of_nodes, node_ids, abort,
+ &need_disconnect);
if (result < 0)
{
ndbout_c("Shutdown failed.");
@@ -1509,10 +1490,17 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
{
ndbout << "Node";
for (int i= 0; i < no_of_nodes; i++)
- ndbout << " " << node_ids[i];
+ ndbout << " " << node_ids[i];
ndbout_c(" has shutdown.");
}
}
+
+ if(need_disconnect)
+ {
+ ndbout << "Disconnecting to allow Management Server to shutdown" << endl;
+ disconnect();
+ }
+
}
void
@@ -1603,6 +1591,7 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
int nostart= 0;
int initialstart= 0;
int abort= 0;
+ int need_disconnect= 0;
for (; command_pos < command_list.size(); command_pos++)
{
@@ -1627,9 +1616,9 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
return;
}
- result= ndb_mgm_restart2(m_mgmsrv, no_of_nodes, node_ids,
- initialstart, nostart, abort);
-
+ result= ndb_mgm_restart3(m_mgmsrv, no_of_nodes, node_ids,
+ initialstart, nostart, abort, &need_disconnect);
+
if (result <= 0) {
ndbout_c("Restart failed.");
printError();
@@ -1645,6 +1634,8 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
ndbout << " " << node_ids[i];
ndbout_c(" is being restarted");
}
+ if(need_disconnect)
+ disconnect();
}
}
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index e9093d59494..dfe4f9aa63e 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -2241,11 +2241,11 @@ ConfigInfo::ConfigInfo()
if (!m_info.getCopy(param._section, &section)) {
Properties newsection(true);
m_info.put(param._section, &newsection);
+
+ // Get copy of section
+ m_info.getCopy(param._section, &section);
}
-
- // Get copy of section
- m_info.getCopy(param._section, &section);
-
+
// Create pinfo (parameter info) entry
Properties pinfo(true);
pinfo.put("Id", param._paramId);
@@ -2299,6 +2299,7 @@ ConfigInfo::ConfigInfo()
// Replace section with modified section
m_info.put(param._section, section, true);
+ delete section;
if(param._type != ConfigInfo::CI_SECTION){
Properties * p;
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index b713a3908ab..b9466ed1173 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -60,9 +60,6 @@
#include <SignalSender.hpp>
-extern bool g_StopServer;
-extern bool g_RestartServer;
-
//#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0)
@@ -122,41 +119,50 @@ MgmtSrvr::logLevelThreadRun()
/**
* Handle started nodes
*/
- EventSubscribeReq req;
- req = m_event_listner[0].m_logLevel;
- req.blockRef = _ownReference;
-
- SetLogLevelOrd ord;
-
m_started_nodes.lock();
- while(m_started_nodes.size() > 0){
- Uint32 node = m_started_nodes[0];
- m_started_nodes.erase(0, false);
- m_started_nodes.unlock();
+ if (m_started_nodes.size() > 0)
+ {
+ // calculate max log level
+ EventSubscribeReq req;
+ {
+ LogLevel tmp;
+ m_event_listner.lock();
+ for(int i = m_event_listner.m_clients.size() - 1; i >= 0; i--)
+ tmp.set_max(m_event_listner[i].m_logLevel);
+ m_event_listner.unlock();
+ req = tmp;
+ }
+ req.blockRef = _ownReference;
+ while (m_started_nodes.size() > 0)
+ {
+ Uint32 node = m_started_nodes[0];
+ m_started_nodes.erase(0, false);
+ m_started_nodes.unlock();
- setEventReportingLevelImpl(node, req);
-
- ord = m_nodeLogLevel[node];
- setNodeLogLevelImpl(node, ord);
-
- m_started_nodes.lock();
- }
+ setEventReportingLevelImpl(node, req);
+
+ SetLogLevelOrd ord;
+ ord = m_nodeLogLevel[node];
+ setNodeLogLevelImpl(node, ord);
+
+ m_started_nodes.lock();
+ }
+ }
m_started_nodes.unlock();
m_log_level_requests.lock();
- while(m_log_level_requests.size() > 0){
- req = m_log_level_requests[0];
+ while (m_log_level_requests.size() > 0)
+ {
+ EventSubscribeReq req = m_log_level_requests[0];
m_log_level_requests.erase(0, false);
m_log_level_requests.unlock();
-
- LogLevel tmp;
- tmp = req;
-
+
if(req.blockRef == 0){
req.blockRef = _ownReference;
setEventReportingLevelImpl(0, req);
} else {
- ord = req;
+ SetLogLevelOrd ord;
+ ord = req;
setNodeLogLevelImpl(req.blockRef, ord);
}
m_log_level_requests.lock();
@@ -933,6 +939,13 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId,
* client connection to that mgmd and stop it that way.
* This allows us to stop mgm servers when there isn't any real
* distributed communication up.
+ *
+ * node_ids.size()==0 means to stop all DB nodes.
+ * MGM nodes will *NOT* be stopped.
+ *
+ * If we work out we should be stopping or restarting ourselves,
+ * we return <0 in stopSelf for restart, >0 for stop
+ * and 0 for do nothing.
*/
int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
@@ -942,7 +955,8 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
bool stop,
bool restart,
bool nostart,
- bool initialStart)
+ bool initialStart,
+ int* stopSelf)
{
int error = 0;
DBUG_ENTER("MgmtSrvr::sendSTOP_REQ");
@@ -991,12 +1005,13 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
NodeId nodeId= 0;
int use_master_node= 0;
int do_send= 0;
- int do_stop_self= 0;
+ *stopSelf= 0;
NdbNodeBitmask nodes_to_stop;
{
for (unsigned i= 0; i < node_ids.size(); i++)
{
nodeId= node_ids[i];
+ ndbout << "asked to stop " << nodeId << endl;
if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
nodes_to_stop.set(nodeId);
else if (nodeId != getOwnNodeId())
@@ -1007,7 +1022,11 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
stoppedNodes.set(nodeId);
}
else
- do_stop_self= 1;;
+ {
+ ndbout << "which is me" << endl;
+ *stopSelf= (restart)? -1 : 1;
+ stoppedNodes.set(nodeId);
+ }
}
}
int no_of_nodes_to_stop= nodes_to_stop.count();
@@ -1040,14 +1059,6 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
nodes.set(nodeId);
}
}
- nodeId= 0;
- while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM))
- {
- if(nodeId==getOwnNodeId())
- continue;
- if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0)
- stoppedNodes.set(nodeId);
- }
}
// now wait for the replies
@@ -1139,11 +1150,9 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
}
}
- if (!error && do_stop_self)
+ if (error && *stopSelf)
{
- if (restart)
- g_RestartServer= true;
- g_StopServer= true;
+ *stopSelf= 0;
}
DBUG_RETURN(error);
}
@@ -1153,7 +1162,7 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
*/
int MgmtSrvr::stopNodes(const Vector<NodeId> &node_ids,
- int *stopCount, bool abort)
+ int *stopCount, bool abort, int* stopSelf)
{
if (!abort)
{
@@ -1175,20 +1184,46 @@ int MgmtSrvr::stopNodes(const Vector<NodeId> &node_ids,
false,
false,
false,
- false);
+ false,
+ stopSelf);
if (stopCount)
*stopCount= nodes.count();
return ret;
}
+int MgmtSrvr::shutdownMGM(int *stopCount, bool abort, int *stopSelf)
+{
+ NodeId nodeId = 0;
+ int error;
+
+ while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM))
+ {
+ if(nodeId==getOwnNodeId())
+ continue;
+ error= sendStopMgmd(nodeId, abort, true, false,
+ false, false);
+ if (error == 0)
+ *stopCount++;
+ }
+
+ *stopSelf= 1;
+ *stopCount++;
+
+ return 0;
+}
+
/*
- * Perform system shutdown
+ * Perform DB nodes shutdown.
+ * MGM servers are left in their current state
*/
-int MgmtSrvr::stop(int * stopCount, bool abort)
+int MgmtSrvr::shutdownDB(int * stopCount, bool abort)
{
NodeBitmask nodes;
Vector<NodeId> node_ids;
+
+ int tmp;
+
int ret = sendSTOP_REQ(node_ids,
nodes,
0,
@@ -1196,7 +1231,8 @@ int MgmtSrvr::stop(int * stopCount, bool abort)
true,
false,
false,
- false);
+ false,
+ &tmp);
if (stopCount)
*stopCount = nodes.count();
return ret;
@@ -1221,6 +1257,7 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
}
NodeBitmask nodes;
Vector<NodeId> node_ids;
+ int stopSelf;
int ret = sendSTOP_REQ(node_ids,
nodes,
singleUserNodeId,
@@ -1228,7 +1265,8 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
false,
false,
false,
- false);
+ false,
+ &stopSelf);
if (stopCount)
*stopCount = nodes.count();
return ret;
@@ -1240,7 +1278,8 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
int * stopCount, bool nostart,
- bool initialStart, bool abort)
+ bool initialStart, bool abort,
+ int *stopSelf)
{
NodeBitmask nodes;
int ret= sendSTOP_REQ(node_ids,
@@ -1250,7 +1289,8 @@ int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
false,
true,
true,
- initialStart);
+ initialStart,
+ stopSelf);
if (ret)
return ret;
@@ -1293,14 +1333,16 @@ int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
}
/*
- * Perform system restart
+ * Perform restart of all DB nodes
*/
-int MgmtSrvr::restart(bool nostart, bool initialStart,
- bool abort, int * stopCount )
+int MgmtSrvr::restartDB(bool nostart, bool initialStart,
+ bool abort, int * stopCount)
{
NodeBitmask nodes;
Vector<NodeId> node_ids;
+ int tmp;
+
int ret = sendSTOP_REQ(node_ids,
nodes,
0,
@@ -1308,7 +1350,8 @@ int MgmtSrvr::restart(bool nostart, bool initialStart,
true,
true,
true,
- initialStart);
+ initialStart,
+ &tmp);
if (ret)
return ret;
@@ -1504,7 +1547,8 @@ int
MgmtSrvr::setEventReportingLevelImpl(int nodeId,
const EventSubscribeReq& ll)
{
- INIT_SIGNAL_SENDER(ss,nodeId);
+ SignalSender ss(theFacade);
+ ss.lock();
SimpleSignal ssig;
EventSubscribeReq * dst =
@@ -1513,41 +1557,54 @@ MgmtSrvr::setEventReportingLevelImpl(int nodeId,
EventSubscribeReq::SignalLength);
*dst = ll;
- send(ss,ssig,nodeId,NODE_TYPE_DB);
+ NodeBitmask nodes;
+ nodes.clear();
+ Uint32 max = (nodeId == 0) ? (nodeId = 1, MAX_NDB_NODES) : nodeId;
+ for(; nodeId <= max; nodeId++)
+ {
+ if (nodeTypes[nodeId] != NODE_TYPE_DB)
+ continue;
+ if (okToSendTo(nodeId, true))
+ continue;
+ if (ss.sendSignal(nodeId, &ssig) == SEND_OK)
+ {
+ nodes.set(nodeId);
+ }
+ }
-#if 0
- while (1)
+ int error = 0;
+ while (!nodes.isclear())
{
SimpleSignal *signal = ss.waitFor();
int gsn = signal->readSignalNumber();
- switch (gsn) {
+ nodeId = refToNode(signal->header.theSendersBlockRef);
+ switch (gsn) {
case GSN_EVENT_SUBSCRIBE_CONF:{
+ nodes.clear(nodeId);
break;
}
case GSN_EVENT_SUBSCRIBE_REF:{
- return SEND_OR_RECEIVE_FAILED;
+ nodes.clear(nodeId);
+ error = 1;
+ break;
}
case GSN_NF_COMPLETEREP:{
const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
- if (rep->failedNodeId == nodeId)
- return SEND_OR_RECEIVE_FAILED;
+ nodes.clear(rep->failedNodeId);
break;
}
case GSN_NODE_FAILREP:{
- const NodeFailRep * const rep =
- CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
- if (NodeBitmask::get(rep->theNodes,nodeId))
- return SEND_OR_RECEIVE_FAILED;
+ // ignore, NF_COMPLETEREP will arrive later
break;
}
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
}
-
}
-#endif
+ if (error)
+ return SEND_OR_RECEIVE_FAILED;
return 0;
}
@@ -1567,19 +1624,6 @@ MgmtSrvr::setNodeLogLevelImpl(int nodeId, const SetLogLevelOrd & ll)
return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
}
-int
-MgmtSrvr::send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type){
- Uint32 max = (node == 0) ? MAX_NODES : node + 1;
-
- for(; node < max; node++){
- while(nodeTypes[node] != (int)node_type && node < max) node++;
- if(nodeTypes[node] != (int)node_type)
- break;
- ss.sendSignal(node, &ssig);
- }
- return 0;
-}
-
//****************************************************************************
//****************************************************************************
@@ -1819,7 +1863,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
break;
case GSN_EVENT_REP:
{
- EventReport *rep = CAST_PTR(EventReport, signal->getDataPtrSend());
+ EventReport *rep = (EventReport*) signal->getDataPtr();
if (rep->getNodeId() == 0)
rep->setNodeId(refToNode(signal->theSendersBlockRef));
eventReport(signal->getDataPtr());
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index 007494a277d..7811cf0e5d1 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -255,12 +255,15 @@ public:
* @param processId: Id of the DB process to stop
* @return 0 if succeeded, otherwise: as stated above, plus:
*/
- int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort);
+ int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort,
+ int *stopSelf);
+
+ int shutdownMGM(int *stopCount, bool abort, int *stopSelf);
/**
- * Stop the system
+ * shutdown the DB nodes
*/
- int stop(int * cnt = 0, bool abort = false);
+ int shutdownDB(int * cnt = 0, bool abort = false);
/**
* print version info about a node
@@ -294,14 +297,14 @@ public:
*/
int restartNodes(const Vector<NodeId> &node_ids,
int *stopCount, bool nostart,
- bool initialStart, bool abort);
+ bool initialStart, bool abort, int *stopSelf);
/**
- * Restart the system
+ * Restart all DB nodes
*/
- int restart(bool nostart, bool initialStart,
- bool abort = false,
- int * stopCount = 0);
+ int restartDB(bool nostart, bool initialStart,
+ bool abort = false,
+ int * stopCount = 0);
struct BackupEvent {
enum Event {
@@ -491,8 +494,6 @@ public:
private:
//**************************************************************************
- int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type);
-
int sendStopMgmd(NodeId nodeId,
bool abort,
bool stop,
@@ -507,7 +508,8 @@ private:
bool stop,
bool restart,
bool nostart,
- bool initialStart);
+ bool initialStart,
+ int *stopSelf);
/**
* Check if it is possible to send a signal to a (DB) process
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 5b08b930e2e..0524aba4c32 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -35,6 +35,7 @@
#include <base64.h>
extern bool g_StopServer;
+extern bool g_RestartServer;
extern EventLogger g_eventLogger;
static const unsigned int MAX_READ_TIMEOUT = 1000 ;
@@ -146,7 +147,13 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
- MGM_CMD("restart node", &MgmApiSession::restart, ""),
+ MGM_CMD("restart node", &MgmApiSession::restart_v1, ""),
+ MGM_ARG("node", String, Mandatory, "Nodes to restart"),
+ MGM_ARG("initialstart", Int, Optional, "Initial start"),
+ MGM_ARG("nostart", Int, Optional, "No start"),
+ MGM_ARG("abort", Int, Optional, "Abort"),
+
+ MGM_CMD("restart node v2", &MgmApiSession::restart_v2, ""),
MGM_ARG("node", String, Mandatory, "Nodes to restart"),
MGM_ARG("initialstart", Int, Optional, "Initial start"),
MGM_ARG("nostart", Int, Optional, "No start"),
@@ -187,13 +194,18 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
MGM_ARG("id", Int, Mandatory, "Backup id"),
- MGM_CMD("stop", &MgmApiSession::stop, ""),
+ MGM_CMD("stop", &MgmApiSession::stop_v1, ""),
+ MGM_ARG("node", String, Mandatory, "Node"),
+ MGM_ARG("abort", Int, Mandatory, "Node"),
+
+ MGM_CMD("stop v2", &MgmApiSession::stop_v2, ""),
MGM_ARG("node", String, Mandatory, "Node"),
MGM_ARG("abort", Int, Mandatory, "Node"),
MGM_CMD("stop all", &MgmApiSession::stopAll, ""),
MGM_ARG("abort", Int, Mandatory, "Node"),
-
+ MGM_ARG("stop", String, Optional, "MGM/DB or both"),
+
MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""),
MGM_ARG("nodeId", Int, Mandatory, "Node"),
@@ -278,6 +290,7 @@ MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
m_output = new SocketOutputStream(sock);
m_parser = new Parser_t(commands, *m_input, true, true, true);
m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
+ m_stopSelf= 0;
DBUG_VOID_RETURN;
}
@@ -297,6 +310,10 @@ MgmApiSession::~MgmApiSession()
NDB_CLOSE_SOCKET(m_socket);
m_socket= NDB_INVALID_SOCKET;
}
+ if(m_stopSelf < 0)
+ g_RestartServer= true;
+ if(m_stopSelf)
+ g_StopServer= true;
DBUG_VOID_RETURN;
}
@@ -823,9 +840,8 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
m_mgmsrv.m_event_listner.unlock();
{
- LogLevel ll;
- ll.setLogLevel(category,level);
- m_mgmsrv.m_event_listner.update_max_log_level(ll);
+ LogLevel tmp;
+ m_mgmsrv.m_event_listner.update_max_log_level(tmp);
}
m_output->println(reply);
@@ -886,8 +902,19 @@ MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &,
}
void
-MgmApiSession::restart(Parser<MgmApiSession>::Context &,
+MgmApiSession::restart_v1(Parser<MgmApiSession>::Context &,
Properties const &args) {
+ restart(args,1);
+}
+
+void
+MgmApiSession::restart_v2(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ restart(args,2);
+}
+
+void
+MgmApiSession::restart(Properties const &args, int version) {
Uint32
nostart = 0,
initialstart = 0,
@@ -912,7 +939,8 @@ MgmApiSession::restart(Parser<MgmApiSession>::Context &,
&restarted,
nostart != 0,
initialstart != 0,
- abort != 0);
+ abort != 0,
+ &m_stopSelf);
m_output->println("restart reply");
if(result != 0){
@@ -920,6 +948,8 @@ MgmApiSession::restart(Parser<MgmApiSession>::Context &,
} else
m_output->println("result: Ok");
m_output->println("restarted: %d", restarted);
+ if(version>1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
}
@@ -936,7 +966,7 @@ MgmApiSession::restartAll(Parser<MgmApiSession>::Context &,
args.get("nostart", &nostart);
int count = 0;
- int result = m_mgmsrv.restart(nostart, initialstart, abort, &count);
+ int result = m_mgmsrv.restartDB(nostart, initialstart, abort, &count);
m_output->println("restart reply");
if(result != 0)
@@ -1029,8 +1059,19 @@ MgmApiSession::getInfoClusterLog(Parser<MgmApiSession>::Context &,
}
void
-MgmApiSession::stop(Parser<MgmApiSession>::Context &,
- Properties const &args) {
+MgmApiSession::stop_v1(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ stop(args,1);
+}
+
+void
+MgmApiSession::stop_v2(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ stop(args,2);
+}
+
+void
+MgmApiSession::stop(Properties const &args, int version) {
Uint32 abort;
char *nodes_str;
Vector<NodeId> nodes;
@@ -1055,7 +1096,7 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
int stopped= 0;
int result= 0;
if (nodes.size())
- result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0);
+ result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0, &m_stopSelf);
m_output->println("stop reply");
if(result != 0)
@@ -1063,25 +1104,41 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
else
m_output->println("result: Ok");
m_output->println("stopped: %d", stopped);
+ if(version>1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
}
-
void
MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
- Properties const &args) {
- int stopped = 0;
+ Properties const &args) {
+ int stopped[2] = {0,0};
Uint32 abort;
args.get("abort", &abort);
- int result = m_mgmsrv.stop(&stopped, abort != 0);
+ BaseString stop;
+ const char* tostop= "db";
+ int ver=1;
+ if (args.get("stop", stop))
+ {
+ tostop= stop.c_str();
+ ver= 2;
+ }
+
+ int result= 0;
+ if(strstr(tostop,"db"))
+ result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0);
+ if(!result && strstr(tostop,"mgm"))
+ result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf);
m_output->println("stop reply");
if(result != 0)
m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
- m_output->println("stopped: %d", stopped);
+ m_output->println("stopped: %d", stopped[0]+stopped[1]);
+ if(ver >1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
}
@@ -1312,21 +1369,23 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
void
Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level)
{
- LogLevel tmp= m_logLevel;
- tmp.set_max(log_level);
+ LogLevel tmp = log_level;
+ m_clients.lock();
+ for(int i = m_clients.size() - 1; i >= 0; i--)
+ tmp.set_max(m_clients[i].m_logLevel);
+ m_clients.unlock();
update_log_level(tmp);
}
void
Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp)
{
- if(!(tmp == m_logLevel)){
- m_logLevel = tmp;
- EventSubscribeReq req;
- req = tmp;
- req.blockRef = 0;
- m_mgmsrv->m_log_level_requests.push_back(req);
- }
+ m_logLevel = tmp;
+ EventSubscribeReq req;
+ req = tmp;
+ // send update to all nodes
+ req.blockRef = 0;
+ m_mgmsrv->m_log_level_requests.push_back(req);
}
void
diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp
index 975202b96df..6e0bb701d7b 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -41,6 +41,7 @@ private:
Parser_t *m_parser;
MgmtSrvr::Allocated_resources *m_allocated_resources;
char m_err_str[1024];
+ int m_stopSelf; // -1 is restart, 0 do nothing, 1 stop
void getConfig_common(Parser_t::Context &ctx,
const class Properties &args,
@@ -63,7 +64,9 @@ public:
void getVersion(Parser_t::Context &ctx, const class Properties &args);
void getStatus(Parser_t::Context &ctx, const class Properties &args);
void getInfoClusterLog(Parser_t::Context &ctx, const class Properties &args);
- void restart(Parser_t::Context &ctx, const class Properties &args);
+ void restart(const class Properties &args, int version);
+ void restart_v1(Parser_t::Context &ctx, const class Properties &args);
+ void restart_v2(Parser_t::Context &ctx, const class Properties &args);
void restartAll(Parser_t::Context &ctx, const class Properties &args);
void insertError(Parser_t::Context &ctx, const class Properties &args);
void setTrace(Parser_t::Context &ctx, const class Properties &args);
@@ -75,7 +78,9 @@ public:
void abortBackup(Parser_t::Context &ctx, const class Properties &args);
void enterSingleUser(Parser_t::Context &ctx, const class Properties &args);
void exitSingleUser(Parser_t::Context &ctx, const class Properties &args);
- void stop(Parser_t::Context &ctx, const class Properties &args);
+ void stop_v1(Parser_t::Context &ctx, const class Properties &args);
+ void stop_v2(Parser_t::Context &ctx, const class Properties &args);
+ void stop(const class Properties &args, int version);
void stopAll(Parser_t::Context &ctx, const class Properties &args);
void start(Parser_t::Context &ctx, const class Properties &args);
void startAll(Parser_t::Context &ctx, const class Properties &args);
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index 7d2793047c2..fdee8961337 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -266,6 +266,16 @@ NdbBlob::isScanOp()
}
inline bool
+NdbBlob::isReadOnlyOp()
+{
+ return ! (
+ theNdbOp->theOperationType == NdbOperation::InsertRequest ||
+ theNdbOp->theOperationType == NdbOperation::UpdateRequest ||
+ theNdbOp->theOperationType == NdbOperation::WriteRequest
+ );
+}
+
+inline bool
NdbBlob::isTakeOverOp()
{
return
@@ -438,12 +448,12 @@ NdbBlob::getValue(void* data, Uint32 bytes)
{
DBUG_ENTER("NdbBlob::getValue");
DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
- if (theGetFlag || theState != Prepared) {
- setErrorCode(NdbBlobImpl::ErrState);
+ if (! isReadOp() && ! isScanOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
DBUG_RETURN(-1);
}
- if (! isReadOp() && ! isScanOp()) {
- setErrorCode(NdbBlobImpl::ErrUsage);
+ if (theGetFlag || theState != Prepared) {
+ setErrorCode(NdbBlobImpl::ErrState);
DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
@@ -461,12 +471,12 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
{
DBUG_ENTER("NdbBlob::setValue");
DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
- if (theSetFlag || theState != Prepared) {
- setErrorCode(NdbBlobImpl::ErrState);
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
DBUG_RETURN(-1);
}
- if (! isInsertOp() && ! isUpdateOp() && ! isWriteOp()) {
- setErrorCode(NdbBlobImpl::ErrUsage);
+ if (theSetFlag || theState != Prepared) {
+ setErrorCode(NdbBlobImpl::ErrState);
DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
@@ -533,6 +543,10 @@ int
NdbBlob::setNull()
{
DBUG_ENTER("NdbBlob::setNull");
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theNullFlag == -1) {
if (theState == Prepared) {
DBUG_RETURN(setValue(0, 0));
@@ -571,6 +585,10 @@ NdbBlob::truncate(Uint64 length)
{
DBUG_ENTER("NdbBlob::truncate");
DBUG_PRINT("info", ("length=%llu", length));
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
DBUG_RETURN(-1);
@@ -628,12 +646,14 @@ NdbBlob::setPos(Uint64 pos)
int
NdbBlob::readData(void* data, Uint32& bytes)
{
+ DBUG_ENTER("NdbBlob::readData");
if (theState != Active) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
char* buf = static_cast<char*>(data);
- return readDataPrivate(buf, bytes);
+ int ret = readDataPrivate(buf, bytes);
+ DBUG_RETURN(ret);
}
int
@@ -722,12 +742,18 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
int
NdbBlob::writeData(const void* data, Uint32 bytes)
{
+ DBUG_ENTER("NdbBlob::writeData");
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theState != Active) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
const char* buf = static_cast<const char*>(data);
- return writeDataPrivate(buf, bytes);
+ int ret = writeDataPrivate(buf, bytes);
+ DBUG_RETURN(ret);
}
int
@@ -1130,6 +1156,9 @@ NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl
}
}
if (isReadOp()) {
+ // upgrade lock mode
+ if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
+ theNdbOp->theLockMode = NdbOperation::LM_Read;
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
DBUG_RETURN(-1);
@@ -1148,6 +1177,9 @@ NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl
supportedOp = true;
}
if (isScanOp()) {
+ // upgrade lock mode
+ if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
+ theNdbOp->theLockMode = NdbOperation::LM_Read;
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
DBUG_RETURN(-1);
diff --git a/ndb/src/ndbapi/NdbBlobImpl.hpp b/ndb/src/ndbapi/NdbBlobImpl.hpp
index 0030e910c52..b56aabfd84e 100644
--- a/ndb/src/ndbapi/NdbBlobImpl.hpp
+++ b/ndb/src/ndbapi/NdbBlobImpl.hpp
@@ -24,7 +24,7 @@ public:
STATIC_CONST( ErrTable = 4263 );
// "Invalid usage of blob attribute"
STATIC_CONST( ErrUsage = 4264 );
- // "Method is not valid in current blob state"
+ // "The blob method is not valid in current blob state"
STATIC_CONST( ErrState = 4265 );
// "Invalid blob seek position"
STATIC_CONST( ErrSeek = 4266 );
@@ -33,7 +33,9 @@ public:
// "Error in blob head update forced rollback of transaction"
STATIC_CONST( ErrAbort = 4268 );
// "Unknown blob error"
- STATIC_CONST( ErrUnknown = 4269 );
+ STATIC_CONST( ErrUnknown = 4270 );
+ // "The blob method is incompatible with operation type or lock mode"
+ STATIC_CONST( ErrCompat = 4275 );
};
#endif
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index a3e2e69ce14..bd50440b3c0 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -2267,7 +2267,7 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
m_error.code = 4243;
return -1;
}
- int ret = dropIndex(*idx); //, tableName);
+ int ret = dropIndex(*idx);
// If index stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index b0b7adf25f3..bc9894497f8 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -395,7 +395,6 @@ public:
int createIndex(NdbIndexImpl &ix);
int dropIndex(const char * indexName,
const char * tableName);
- // int dropIndex(NdbIndexImpl &, const char * tableName);
int dropIndex(NdbIndexImpl &);
NdbTableImpl * getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table);
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index 869704c7bb3..7d0712e117d 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -160,7 +160,7 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
return -1;
}
- m_keyInfo = lockExcl ? 1 : 0;
+ m_keyInfo = ((scan_flags & SF_KeyInfo) || lockExcl) ? 1 : 0;
bool rangeScan = false;
if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex)
@@ -924,18 +924,28 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* pTrans)
if (newOp == NULL){
return NULL;
}
+ if (!m_keyInfo)
+ {
+ // Cannot take over lock if no keyinfo was requested
+ setErrorCodeAbort(4604);
+ return NULL;
+ }
pTrans->theSimpleState = 0;
const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1;
newOp->theTupKeyLen = len;
newOp->theOperationType = opType;
- if (opType == DeleteRequest) {
- newOp->theStatus = GetValue;
- } else {
- newOp->theStatus = SetValue;
+ switch (opType) {
+ case (ReadRequest):
+ newOp->theLockMode = theLockMode;
+ // Fall through
+ case (DeleteRequest):
+ newOp->theStatus = GetValue;
+ break;
+ default:
+ newOp->theStatus = SetValue;
}
-
const Uint32 * src = (Uint32*)tRecAttr->aRef();
const Uint32 tScanInfo = src[len] & 0x3FFFF;
const Uint32 tTakeOverFragment = src[len] >> 20;
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 5ca8ad7be60..946e6fe4cc2 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -266,6 +266,7 @@ ErrorBundle ErrorCodes[] = {
/**
* Application error
*/
+ { 763, AE, "Alter table requires cluster nodes to have exact same version" },
{ 823, AE, "Too much attrinfo from application in tuple manager" },
{ 831, AE, "Too many nullable/bitfields in table definition" },
{ 876, AE, "876" },
@@ -290,7 +291,7 @@ ErrorBundle ErrorCodes[] = {
{ 4601, AE, "Transaction is not started"},
{ 4602, AE, "You must call getNdbOperation before executeScan" },
{ 4603, AE, "There can only be ONE operation in a scan transaction" },
- { 4604, AE, "takeOverScanOp, opType must be UpdateRequest or DeleteRequest" },
+ { 4604, AE, "takeOverScanOp, to take over a scanned row one must explicitly request keyinfo in readTuples call" },
{ 4605, AE, "You may only call openScanRead or openScanExclusive once for each operation"},
{ 4607, AE, "There may only be one operation in a scan transaction"},
{ 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"},
@@ -325,6 +326,7 @@ ErrorBundle ErrorCodes[] = {
* SchemaError
*/
{ 701, SE, "System busy with other schema operation" },
+ { 711, SE, "System busy with node restart, schema operations not allowed" },
{ 703, SE, "Invalid table format" },
{ 704, SE, "Attribute name too long" },
{ 705, SE, "Table name too long" },
@@ -513,14 +515,15 @@ ErrorBundle ErrorCodes[] = {
{ 4262, UD, "NdbScanFilter: Condition is out of bounds"},
{ 4263, IE, "Invalid blob attributes or invalid blob parts table" },
{ 4264, AE, "Invalid usage of blob attribute" },
- { 4265, AE, "Method is not valid in current blob state" },
+ { 4265, AE, "The blob method is not valid in current blob state" },
{ 4266, AE, "Invalid blob seek position" },
{ 4267, IE, "Corrupted blob value" },
{ 4268, IE, "Error in blob head update forced rollback of transaction" },
{ 4269, IE, "No connection to ndb management server" },
{ 4270, IE, "Unknown blob error" },
{ 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" },
- { 4271, AE, "Invalid index object, not retrieved via getIndex()" }
+ { 4271, AE, "Invalid index object, not retrieved via getIndex()" },
+ { 4275, AE, "The blob method is incompatible with operation type or lock mode" }
};
static
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index c2a06c9ffa0..fae3a662ff9 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -226,7 +226,7 @@ dropTable()
{
NdbDictionary::Table tab(g_opt.m_tname);
if (g_dic->getTable(g_opt.m_tname) != 0)
- CHK(g_dic->dropTable(tab) == 0);
+ CHK(g_dic->dropTable(g_opt.m_tname) == 0);
return 0;
}
@@ -297,13 +297,15 @@ createTable()
struct Bval {
char* m_val;
unsigned m_len;
- char* m_buf;
+ char* m_buf; // read/write buffer
unsigned m_buflen;
+ int m_error_code; // for testing expected error code
Bval() :
m_val(0),
m_len(0),
- m_buf(0), // read/write buffer
- m_buflen(0)
+ m_buf(0),
+ m_buflen(0),
+ m_error_code(0)
{}
~Bval() { delete [] m_val; delete [] m_buf; }
void alloc(unsigned buflen) {
@@ -459,19 +461,23 @@ getBlobLength(NdbBlob* h, unsigned& len)
// setValue / getValue
static int
-setBlobValue(NdbBlob* h, const Bval& v)
+setBlobValue(NdbBlob* h, const Bval& v, int error_code = 0)
{
bool null = (v.m_val == 0);
bool isNull;
unsigned len;
DBG("setValue " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
if (null) {
- CHK(h->setNull() == 0);
+ CHK(h->setNull() == 0 || h->getNdbError().code == error_code);
+ if (error_code)
+ return 0;
isNull = false;
CHK(h->getNull(isNull) == 0 && isNull == true);
CHK(getBlobLength(h, len) == 0 && len == 0);
} else {
- CHK(h->setValue(v.m_val, v.m_len) == 0);
+ CHK(h->setValue(v.m_val, v.m_len) == 0 || h->getNdbError().code == error_code);
+ if (error_code)
+ return 0;
CHK(h->getNull(isNull) == 0 && isNull == false);
CHK(getBlobLength(h, len) == 0 && len == v.m_len);
}
@@ -479,11 +485,11 @@ setBlobValue(NdbBlob* h, const Bval& v)
}
static int
-setBlobValue(const Tup& tup)
+setBlobValue(const Tup& tup, int error_code = 0)
{
- CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
+ CHK(setBlobValue(g_bh1, tup.m_blob1, error_code) == 0);
if (! g_opt.m_oneblob)
- CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ CHK(setBlobValue(g_bh2, tup.m_blob2, error_code) == 0);
return 0;
}
@@ -543,13 +549,18 @@ writeBlobData(NdbBlob* h, const Bval& v)
bool isNull;
unsigned len;
DBG("write " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ int error_code = v.m_error_code;
if (null) {
- CHK(h->setNull() == 0);
+ CHK(h->setNull() == 0 || h->getNdbError().code == error_code);
+ if (error_code)
+ return 0;
isNull = false;
CHK(h->getNull(isNull) == 0 && isNull == true);
CHK(getBlobLength(h, len) == 0 && len == 0);
} else {
- CHK(h->truncate(v.m_len) == 0);
+ CHK(h->truncate(v.m_len) == 0 || h->getNdbError().code == error_code);
+ if (error_code)
+ return 0;
unsigned n = 0;
do {
unsigned m = g_opt.m_full ? v.m_len : urandom(v.m_len + 1);
@@ -568,11 +579,14 @@ writeBlobData(NdbBlob* h, const Bval& v)
}
static int
-writeBlobData(const Tup& tup)
+writeBlobData(Tup& tup, int error_code = 0)
{
+ tup.m_blob1.m_error_code = error_code;
CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
+ if (! g_opt.m_oneblob) {
+ tup.m_blob2.m_error_code = error_code;
CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ }
return 0;
}
@@ -635,19 +649,20 @@ blobWriteHook(NdbBlob* h, void* arg)
}
static int
-setBlobWriteHook(NdbBlob* h, Bval& v)
+setBlobWriteHook(NdbBlob* h, Bval& v, int error_code = 0)
{
DBG("setBlobWriteHook");
+ v.m_error_code = error_code;
CHK(h->setActiveHook(blobWriteHook, &v) == 0);
return 0;
}
static int
-setBlobWriteHook(Tup& tup)
+setBlobWriteHook(Tup& tup, int error_code = 0)
{
- CHK(setBlobWriteHook(g_bh1, tup.m_blob1) == 0);
+ CHK(setBlobWriteHook(g_bh1, tup.m_blob1, error_code) == 0);
if (! g_opt.m_oneblob)
- CHK(setBlobWriteHook(g_bh2, tup.m_blob2) == 0);
+ CHK(setBlobWriteHook(g_bh2, tup.m_blob2, error_code) == 0);
return 0;
}
@@ -869,7 +884,10 @@ readPk(int style)
DBG("readPk pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
- CHK(g_opr->readTuple() == 0);
+ if (urandom(2) == 0)
+ CHK(g_opr->readTuple() == 0);
+ else
+ CHK(g_opr->readTuple(NdbOperation::LM_CommittedRead) == 0);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2len != 0)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
@@ -883,6 +901,8 @@ readPk(int style)
CHK(readBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
+ // verify lock mode upgrade
+ CHK(g_opr->getLockMode() == NdbOperation::LM_Read);
if (style == 0 || style == 1) {
CHK(verifyBlobValue(tup) == 0);
}
@@ -900,23 +920,40 @@ updatePk(int style)
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
DBG("updatePk pk1=" << hex << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
- CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
- CHK(g_opr->updateTuple() == 0);
- CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
- if (g_opt.m_pk2len != 0)
- CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK(getBlobHandles(g_opr) == 0);
- if (style == 0) {
- CHK(setBlobValue(tup) == 0);
- } else if (style == 1) {
- CHK(setBlobWriteHook(tup) == 0);
- } else {
- CHK(g_con->execute(NoCommit) == 0);
- CHK(writeBlobData(tup) == 0);
+ while (1) {
+ int mode = urandom(3);
+ int error_code = mode == 0 ? 0 : 4275;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ if (mode == 0) {
+ DBG("using updateTuple");
+ CHK(g_opr->updateTuple() == 0);
+ } else if (mode == 1) {
+ DBG("using readTuple exclusive");
+ CHK(g_opr->readTuple(NdbOperation::LM_Exclusive) == 0);
+ } else {
+ DBG("using readTuple - will fail and retry");
+ CHK(g_opr->readTuple() == 0);
+ }
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup, error_code) == 0);
+ } else if (style == 1) {
+ CHK(setBlobWriteHook(tup, error_code) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(tup, error_code) == 0);
+ }
+ if (error_code == 0) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ break;
+ }
+ g_ndb->closeTransaction(g_con);
}
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
g_opr = 0;
g_con = 0;
tup.m_exists = true;
@@ -1002,7 +1039,10 @@ readIdx(int style)
DBG("readIdx pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
- CHK(g_opx->readTuple() == 0);
+ if (urandom(2) == 0)
+ CHK(g_opx->readTuple() == 0);
+ else
+ CHK(g_opx->readTuple(NdbOperation::LM_CommittedRead) == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
CHK(getBlobHandles(g_opx) == 0);
if (style == 0) {
@@ -1014,6 +1054,8 @@ readIdx(int style)
CHK(readBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
+ // verify lock mode upgrade (already done by NdbIndexOperation)
+ CHK(g_opx->getLockMode() == NdbOperation::LM_Read);
if (style == 0 || style == 1) {
CHK(verifyBlobValue(tup) == 0);
}
@@ -1031,6 +1073,7 @@ updateIdx(int style)
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
DBG("updateIdx pk1=" << hex << tup.m_pk1);
+ // skip 4275 testing
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
CHK(g_opx->updateTuple() == 0);
@@ -1128,7 +1171,10 @@ readScan(int style, bool idx)
} else {
CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0);
+ if (urandom(2) == 0)
+ CHK(g_ops->readTuples(NdbOperation::LM_Read) == 0);
+ else
+ CHK(g_ops->readTuples(NdbOperation::LM_CommittedRead) == 0);
CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
if (g_opt.m_pk2len != 0)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
@@ -1139,6 +1185,8 @@ readScan(int style, bool idx)
CHK(setBlobReadHook(tup) == 0);
}
CHK(g_con->execute(NoCommit) == 0);
+ // verify lock mode upgrade
+ CHK(g_ops->getLockMode() == NdbOperation::LM_Read);
unsigned rows = 0;
while (1) {
int ret;
@@ -1180,7 +1228,7 @@ updateScan(int style, bool idx)
} else {
CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK(g_ops->readTuples(NdbScanOperation::LM_Exclusive) == 0);
+ CHK(g_ops->readTuples(NdbOperation::LM_Exclusive) == 0);
CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
if (g_opt.m_pk2len != 0)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
@@ -1199,6 +1247,7 @@ updateScan(int style, bool idx)
// calculate new blob values
calcBval(g_tups[k], false);
tup.copyfrom(g_tups[k]);
+ // cannot do 4275 testing, scan op error code controls execution
CHK((g_opr = g_ops->updateCurrentTuple()) != 0);
CHK(getBlobHandles(g_opr) == 0);
if (style == 0) {
@@ -1232,7 +1281,7 @@ deleteScan(bool idx)
} else {
CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK(g_ops->readTuples(NdbScanOperation::LM_Exclusive) == 0);
+ CHK(g_ops->readTuples(NdbOperation::LM_Exclusive) == 0);
CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
if (g_opt.m_pk2len != 0)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
@@ -1651,7 +1700,7 @@ testperf()
char b[20];
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
- CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0);
+ CHK(g_ops->readTuples(NdbOperation::LM_Read) == 0);
CHK(g_ops->getValue(cA, (char*)&a) != 0);
CHK(g_ops->getValue(cB, b) != 0);
CHK(g_con->execute(NoCommit) == 0);
@@ -1680,7 +1729,7 @@ testperf()
char c[20];
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
- CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0);
+ CHK(g_ops->readTuples(NdbOperation::LM_Read) == 0);
CHK(g_ops->getValue(cA, (char*)&a) != 0);
CHK((g_bh1 = g_ops->getBlobHandle(cC)) != 0);
CHK(g_con->execute(NoCommit) == 0);
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index 710a47bf3dc..397f41b3d4e 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -1551,6 +1551,299 @@ end:
return result;
}
+// NFNR
+
+// Restarter controls dict ops : 1-run 2-pause 3-stop
+// synced by polling...
+
+static bool
+send_dict_ops_cmd(NDBT_Context* ctx, Uint32 cmd)
+{
+ ctx->setProperty("DictOps_CMD", cmd);
+ while (1) {
+ if (ctx->isTestStopped())
+ return false;
+ if (ctx->getProperty("DictOps_ACK") == cmd)
+ break;
+ NdbSleep_MilliSleep(100);
+ }
+ return true;
+}
+
+static bool
+recv_dict_ops_run(NDBT_Context* ctx)
+{
+ while (1) {
+ if (ctx->isTestStopped())
+ return false;
+ Uint32 cmd = ctx->getProperty("DictOps_CMD");
+ ctx->setProperty("DictOps_ACK", cmd);
+ if (cmd == 1)
+ break;
+ if (cmd == 3)
+ return false;
+ NdbSleep_MilliSleep(100);
+ }
+ return true;
+}
+
+int
+runRestarts(NDBT_Context* ctx, NDBT_Step* step)
+{
+ static int errlst_master[] = { // non-crashing
+ 7175, // send one fake START_PERMREF
+ 0
+ };
+ static int errlst_node[] = {
+ 7174, // crash before sending DICT_LOCK_REQ
+ 7176, // pretend master does not support DICT lock
+ 7121, // crash at receive START_PERMCONF
+ 0
+ };
+ const uint errcnt_master = sizeof(errlst_master)/sizeof(errlst_master[0]);
+ const uint errcnt_node = sizeof(errlst_node)/sizeof(errlst_node[0]);
+
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ NdbRestarter restarter;
+ int result = NDBT_OK;
+ const int loops = ctx->getNumLoops();
+
+ for (int l = 0; l < loops && result == NDBT_OK; l++) {
+ g_info << "1: === loop " << l << " ===" << endl;
+
+ // assuming 2-way replicated
+
+ int numnodes = restarter.getNumDbNodes();
+ CHECK(numnodes >= 1);
+ if (numnodes == 1)
+ break;
+
+ int masterNodeId = restarter.getMasterNodeId();
+ CHECK(masterNodeId != -1);
+
+ // for more complex cases need more restarter support methods
+
+ int nodeIdList[2] = { 0, 0 };
+ int nodeIdCnt = 0;
+
+ if (numnodes >= 2) {
+ int rand = myRandom48(numnodes);
+ int nodeId = restarter.getRandomNotMasterNodeId(rand);
+ CHECK(nodeId != -1);
+ nodeIdList[nodeIdCnt++] = nodeId;
+ }
+
+ if (numnodes >= 4 && myRandom48(2) == 0) {
+ int rand = myRandom48(numnodes);
+ int nodeId = restarter.getRandomNodeOtherNodeGroup(nodeIdList[0], rand);
+ CHECK(nodeId != -1);
+ if (nodeId != masterNodeId)
+ nodeIdList[nodeIdCnt++] = nodeId;
+ }
+
+ g_info << "1: master=" << masterNodeId << " nodes=" << nodeIdList[0] << "," << nodeIdList[1] << endl;
+
+ const uint timeout = 60; //secs for node wait
+ const unsigned maxsleep = 2000; //ms
+
+ bool NF_ops = ctx->getProperty("Restart_NF_ops");
+ uint NF_type = ctx->getProperty("Restart_NF_type");
+ bool NR_ops = ctx->getProperty("Restart_NR_ops");
+ bool NR_error = ctx->getProperty("Restart_NR_error");
+
+ g_info << "1: " << (NF_ops ? "run" : "pause") << " dict ops" << endl;
+ if (! send_dict_ops_cmd(ctx, NF_ops ? 1 : 2))
+ break;
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ {
+ for (int i = 0; i < nodeIdCnt; i++) {
+ int nodeId = nodeIdList[i];
+
+ bool nostart = true;
+ bool abort = NF_type == 0 ? myRandom48(2) : (NF_type == 2);
+ bool initial = myRandom48(2);
+
+ char flags[40];
+ strcpy(flags, "flags: nostart");
+ if (abort)
+ strcat(flags, ",abort");
+ if (initial)
+ strcat(flags, ",initial");
+
+ g_info << "1: restart " << nodeId << " " << flags << endl;
+ CHECK(restarter.restartOneDbNode(nodeId, initial, nostart, abort) == 0);
+ }
+ }
+
+ g_info << "1: wait for nostart" << endl;
+ CHECK(restarter.waitNodesNoStart(nodeIdList, nodeIdCnt, timeout) == 0);
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ int err_master = 0;
+ int err_node[2] = { 0, 0 };
+
+ if (NR_error) {
+ err_master = errlst_master[l % errcnt_master];
+
+ // limitation: cannot have 2 node restarts and crash_insert
+ // one node may die for real (NF during startup)
+
+ for (int i = 0; i < nodeIdCnt && nodeIdCnt == 1; i++) {
+ err_node[i] = errlst_node[l % errcnt_node];
+
+ // 7176 - no DICT lock protection
+
+ if (err_node[i] == 7176) {
+ g_info << "1: no dict ops due to error insert "
+ << err_node[i] << endl;
+ NR_ops = false;
+ }
+ }
+ }
+
+ g_info << "1: " << (NR_ops ? "run" : "pause") << " dict ops" << endl;
+ if (! send_dict_ops_cmd(ctx, NR_ops ? 1 : 2))
+ break;
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "1: start nodes" << endl;
+ CHECK(restarter.startNodes(nodeIdList, nodeIdCnt) == 0);
+
+ if (NR_error) {
+ {
+ int err = err_master;
+ if (err != 0) {
+ g_info << "1: insert master error " << err << endl;
+ CHECK(restarter.insertErrorInNode(masterNodeId, err) == 0);
+ }
+ }
+
+ for (int i = 0; i < nodeIdCnt; i++) {
+ int nodeId = nodeIdList[i];
+
+ int err = err_node[i];
+ if (err != 0) {
+ g_info << "1: insert node " << nodeId << " error " << err << endl;
+ CHECK(restarter.insertErrorInNode(nodeId, err) == 0);
+ }
+ }
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "1: wait cluster started" << endl;
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "1: restart done" << endl;
+ }
+
+ g_info << "1: stop dict ops" << endl;
+ send_dict_ops_cmd(ctx, 3);
+
+ return result;
+}
+
+int
+runDictOps(NDBT_Context* ctx, NDBT_Step* step)
+{
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ int result = NDBT_OK;
+
+ for (int l = 0; result == NDBT_OK; l++) {
+ if (! recv_dict_ops_run(ctx))
+ break;
+
+ g_info << "2: === loop " << l << " ===" << endl;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ const char* tabName = pTab->getName();
+
+ const unsigned long maxsleep = 100; //ms
+
+ g_info << "2: create table" << endl;
+ {
+ uint count = 0;
+ try_create:
+ count++;
+ if (pDic->createTable(*pTab) != 0) {
+ const NdbError err = pDic->getNdbError();
+ if (count == 1)
+ g_err << "2: " << tabName << ": create failed: " << err << endl;
+ if (err.code != 711) {
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+ goto try_create;
+ }
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "2: verify create" << endl;
+ const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
+ if (pTab2 == NULL) {
+ const NdbError err = pDic->getNdbError();
+ g_err << "2: " << tabName << ": verify create: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ // replace by the Retrieved table
+ pTab = pTab2;
+
+ int records = myRandom48(ctx->getNumRecords());
+ g_info << "2: load " << records << " records" << endl;
+ HugoTransactions hugoTrans(*pTab);
+ if (hugoTrans.loadTable(pNdb, records) != 0) {
+ // XXX get error code from hugo
+ g_err << "2: " << tabName << ": load failed" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "2: drop" << endl;
+ {
+ uint count = 0;
+ try_drop:
+ count++;
+ if (pDic->dropTable(tabName) != 0) {
+ const NdbError err = pDic->getNdbError();
+ if (count == 1)
+ g_err << "2: " << tabName << ": drop failed: " << err << endl;
+ if (err.code != 711) {
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+ goto try_drop;
+ }
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+
+ g_info << "2: verify drop" << endl;
+ const NdbDictionary::Table* pTab3 = pDic->getTable(tabName);
+ if (pTab3 != NULL) {
+ g_err << "2: " << tabName << ": verify drop: table exists" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ if (pDic->getNdbError().code != 709) {
+ const NdbError err = pDic->getNdbError();
+ g_err << "2: " << tabName << ": verify drop: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_MilliSleep(myRandom48(maxsleep));
+ }
+
+ return result;
+}
+
NDBT_TESTSUITE(testDict);
TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){
@@ -1655,6 +1948,34 @@ TESTCASE("FailAddFragment",
"Fail add fragment or attribute in ACC or TUP or TUX\n"){
INITIALIZER(runFailAddFragment);
}
+TESTCASE("Restart_NF1",
+ "DICT ops during node graceful shutdown (not master)"){
+ TC_PROPERTY("Restart_NF_ops", 1);
+ TC_PROPERTY("Restart_NF_type", 1);
+ STEP(runRestarts);
+ STEP(runDictOps);
+}
+TESTCASE("Restart_NF2",
+ "DICT ops during node shutdown abort (not master)"){
+ TC_PROPERTY("Restart_NF_ops", 1);
+ TC_PROPERTY("Restart_NF_type", 2);
+ STEP(runRestarts);
+ STEP(runDictOps);
+}
+TESTCASE("Restart_NR1",
+ "DICT ops during node startup (not master)"){
+ TC_PROPERTY("Restart_NR_ops", 1);
+ STEP(runRestarts);
+ STEP(runDictOps);
+}
+TESTCASE("Restart_NR2",
+ "DICT ops during node startup with crash inserts (not master)"){
+ TC_PROPERTY("Restart_NR_ops", 1);
+ TC_PROPERTY("Restart_NR_error", 1);
+ STEP(runRestarts);
+ STEP(runDictOps);
+}
+
NDBT_TESTSUITE_END(testDict);
int main(int argc, const char** argv){
diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END
index f7da0d9596e..c5c08cea908 100755
--- a/netware/BUILD/compile-netware-END
+++ b/netware/BUILD/compile-netware-END
@@ -21,11 +21,6 @@ rm -rf Makefile.in.bk
# run auto tools
. $path/compile-AUTOTOOLS
-# For NetWare there is no comp_err but comp_err.linux
-sed -e "s/comp_err/comp_err.linux/g" extra/Makefile.am > extra/Makefile.am.$$
-sed -e "s/replace comp_err.linux/replace comp_err/g" extra/Makefile.am.$$ > extra/Makefile.am
-rm extra/Makefile.am.$$
-
# configure
./configure $base_configs $extra_configs
diff --git a/netware/Makefile.am b/netware/Makefile.am
index ab88d97f9bc..2d34283c4b3 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -29,7 +29,7 @@ netware_build_files = client/mysql.def client/mysqladmin.def \
client/mysqlbinlog.def client/mysqlcheck.def \
client/mysqldump.def client/mysqlimport.def \
client/mysqlshow.def client/mysqltest.def \
- extra/mysql_install.def extra/my_print_defaults.def \
+ extra/my_print_defaults.def \
extra/perror.def extra/replace.def \
extra/resolveip.def extra/comp_err.def \
libmysqld/libmysqld.def myisam/myisamchk.def \
@@ -50,7 +50,7 @@ EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \
libmysqlmain.c my_manage.c my_manage.h \
my_print_defaults.def myisam_ftdump.def myisamchk.def \
myisamlog.def myisampack.def mysql.def mysql.xdc \
- mysql_fix_privilege_tables.pl mysql_install.def \
+ mysql_fix_privilege_tables.pl \
mysql_install_db.c mysql_install_db.def \
mysql_secure_installation.pl mysql_test_run.c \
mysql_test_run.def mysql_waitpid.def mysqladmin.def \
diff --git a/netware/mysql_install.def b/netware/mysql_install.def
deleted file mode 100644
index 3392afb7298..00000000000
--- a/netware/mysql_install.def
+++ /dev/null
@@ -1,10 +0,0 @@
-#------------------------------------------------------------------------------
-# My Print Defaults
-#------------------------------------------------------------------------------
-MODULE libc.nlm
-COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
-DESCRIPTION "MySQL Install Tool"
-VERSION 4, 0
-XDCDATA ../netware/mysql.xdc
-#DEBUG
-
diff --git a/regex/regexec.c b/regex/regexec.c
index b7ad83ba883..88bcc02323d 100644
--- a/regex/regexec.c
+++ b/regex/regexec.c
@@ -19,7 +19,7 @@ static int nope = 0; /* for use in asserts; shuts lint up */
/* macros for manipulating states, small version */
#define states long
-#define states1 states /* for later use in regexec() decision */
+#define states1 long /* for later use in regexec() decision. Ensure Win64 definition is correct.*/
#define CLEAR(v) ((v) = 0)
#define SET0(v, n) ((v) &= ~((states) 1 << (n)))
#define SET1(v, n) ((v) |= (states) 1 << (n))
diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh
index bb1243aa998..c677db6a537 100644
--- a/scripts/make_win_src_distribution.sh
+++ b/scripts/make_win_src_distribution.sh
@@ -1,11 +1,14 @@
#!/bin/sh
+# Terminate loudly on error, we don't want partial package
+set -e
+trap "echo '*** script failed ***'" 0
+
#
# Script to create a Windows src package
#
version=@VERSION@
-export version
CP="cp -p"
DEBUG=0
@@ -74,7 +77,7 @@ show_usage()
echo " --tmp Specify the temporary location"
echo " --suffix Suffix name for the package"
echo " --dirname Directory name to copy files (intermediate)"
- echo " --silent Do not list verbosely files processed"
+ echo " --silent Show no progress information"
echo " --tar Create tar.gz package"
echo " --zip Create zip package"
echo " --help Show this help message"
@@ -140,10 +143,11 @@ unix_to_dos()
# Create a tmp dest directory to copy files
#
-BASE=$TMP/my_win_dist$SUFFIX
+BASE=$TMP/my_win_dist$SUFFIX.$$
+trap "rm -r -f $BASE; echo '*** interrupted ***'; exit 1" 1 2 3 13 15
if [ -d $BASE ] ; then
- print_debug "Destination directory '$BASE' already exists, deleting it"
+ echo "WARNING: Destination directory '$BASE' already exists, deleting it"
rm -r -f $BASE
fi
@@ -199,7 +203,7 @@ copy_dir_files()
print_debug "Creating directory '$arg'"
mkdir $BASE/$arg
fi
- for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp \
+ for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.yy \
README INSTALL* LICENSE AUTHORS NEWS ChangeLog \
*.inc *.test *.result *.pem Moscow_leap des_key_file \
*.vcproj *.sln *.dat *.000001 *.require *.opt
@@ -260,7 +264,7 @@ done
#
# Create project files for ndb
#
-make -C $SOURCE/ndb windoze
+make -C $SOURCE/ndb windoze || true
#
# Input directories to be copied recursively
@@ -298,8 +302,6 @@ do
fi
done
-cp extra/sql_state.h extra/mysqld_error.h $BASE/include
-
#
# support files
#
@@ -336,8 +338,17 @@ done
# Fix some windows files to avoid compiler warnings
#
-./extra/replace std:: "" < $BASE/sql/sql_yacc.cpp | sed '/^ *switch (yytype)$/ { N; /\n *{$/ { N; /\n *default:$/ { N; /\n *break;$/ { N; /\n *}$/ d; };};};} ' > $BASE/sql/sql_yacc.cpp-new
-mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp
+if [ -x extra/replace ] ; then
+ ./extra/replace std:: "" < $BASE/sql/sql_yacc.cpp | \
+ sed '/^ *switch (yytype)$/ { N; /\n *{$/ { N; /\n *default:$/ { N; /\n *break;$/ { N; /\n *}$/ d; };};};} ' \
+ > $BASE/sql/sql_yacc.cpp-new
+ mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp
+else
+ if [ "$SILENT" = "0" ] ; then
+ echo 'WARNING: "extra/replace" not built, can not filter "sql_yacc.ccp"'
+ echo 'WARNING: to reduce the number of warnings when building'
+ fi
+fi
#
# Search the tree for plain text files and adapt the line end marker
@@ -351,8 +362,6 @@ find $BASE \( -name "*.cnf" -o -name "*.ini" \
do
unix_to_dos $v
done
-# File extension '.txt' matches too many other files, error messages etc.
-unix_to_dos $BASE/Docs/*.txt
mv $BASE/README $BASE/README.txt
@@ -360,19 +369,23 @@ mv $BASE/README $BASE/README.txt
# Clean up if we did this from a bk tree
#
-if [ -d $BASE/SSL/SCCS ]
-then
- find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f
-fi
-find $BASE/ -type d -name .deps -printf " \"%p\"" | xargs rm -r -f
-find $BASE/ -type d -name .libs -printf " \"%p\"" | xargs rm -r -f
+find $BASE -type d \( -name SCCS -o -name .deps -o -name .libs \) -print0 | \
+xargs -0 rm -r -f
rm -r -f "$BASE/mysql-test/var"
#
# Initialize the initial data directory
#
-if [ -f scripts/mysql_install_db ]; then
+if [ ! -f scripts/mysql_install_db ] ; then
+ if [ "$SILENT" = "0" ] ; then
+ echo 'WARNING: "scripts/mysql_install_db" is not built, can not initiate databases'
+ fi
+elif [ ! -f extra/my_print_defaults ]; then
+ if [ "$SILENT" = "0" ] ; then
+ echo 'WARNING: "extra/my_print_defaults" is not built, can not initiate databases'
+ fi
+else
print_debug "Initializing the 'data' directory"
scripts/mysql_install_db --no-defaults --windows --datadir=$BASE/data
if test "$?" = 1
@@ -450,21 +463,15 @@ set_tarzip_options()
if [ "$arg" = "tar" ]; then
ZIPFILE1=gnutar
ZIPFILE2=gtar
- OPT=cvf
+ OPT=cf
EXT=".tar"
NEED_COMPRESS=1
- if [ "$SILENT" = "1" ] ; then
- OPT=cf
- fi
else
ZIPFILE1=zip
ZIPFILE2=""
- OPT="-r"
+ OPT="-r -q"
EXT=".zip"
NEED_COMPRESS=0
- if [ "$SILENT" = "1" ] ; then
- OPT="$OPT -q"
- fi
fi
done
}
@@ -525,4 +532,7 @@ fi
print_debug "Removing temporary directory"
rm -r -f $BASE
+# No need to report anything if we got here
+trap "" 0
+
# End of script
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
index fa9d877fde6..24844e05776 100644
--- a/server-tools/instance-manager/guardian.cc
+++ b/server-tools/instance-manager/guardian.cc
@@ -271,10 +271,7 @@ int Guardian_thread::init()
{
if (!(instance->options.nonguarded))
if (guard(instance, TRUE)) /* do not lock guardian */
- {
- instance_map->unlock();
return 1;
- }
}
return 0;
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc
index 543c9c31bfa..3b7f58d8a09 100644
--- a/server-tools/instance-manager/instance_map.cc
+++ b/server-tools/instance-manager/instance_map.cc
@@ -215,7 +215,7 @@ int Instance_map::flush_instances()
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0);
rc= load();
- guardian->init();
+ guardian->init(); // TODO: check error status.
pthread_mutex_unlock(&LOCK_instance_map);
guardian->unlock();
return rc;
diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc
index 9389694822a..72621ed1662 100644
--- a/server-tools/instance-manager/instance_options.cc
+++ b/server-tools/instance-manager/instance_options.cc
@@ -391,8 +391,13 @@ int Instance_options::complete_initialization(const char *default_path,
const char *tmp;
char *end;
- if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path)))
- goto err;
+ if (!mysqld_path)
+ {
+ // Need one extra byte, as convert_dirname() adds a slash at the end.
+ if (!(mysqld_path= alloc_root(&alloc, strlen(default_path) + 2)))
+ goto err;
+ strcpy((char *)mysqld_path, default_path);
+ }
// 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);
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 00ef50a84e1..353dfcf64dc 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -147,6 +147,25 @@ void manager(const Options &options)
if (create_pid_file(options.pid_file_name, manager_pid))
return;
+ /*
+ Initialize signals and alarm-infrastructure.
+
+ NOTE: To work nicely with LinuxThreads, the signal thread is the first
+ thread in the process.
+
+ NOTE:
+ After init_thr_alarm() call it's possible to call thr_alarm() (from
+ different threads), that results in sending ALARM signal to the alarm
+ thread (which can be the main thread). That signal can interrupt
+ blocking calls.
+
+ In other words, a blocking call can be interrupted in the main thread
+ after init_thr_alarm().
+ */
+
+ sigset_t mask;
+ set_signals(&mask);
+
/* create guardian thread */
{
pthread_t guardian_thd_id;
@@ -154,9 +173,16 @@ void manager(const Options &options)
int rc;
/*
- NOTE: Guardian should be shutdown first. Only then all other threads
- need to be stopped. This should be done, as guardian is responsible for
- shutting down the instances, and this is a long operation.
+ NOTE: Guardian should be shutdown first. Only then all other threads
+ need to be stopped. This should be done, as guardian is responsible
+ for shutting down the instances, and this is a long operation.
+
+ NOTE: Guardian uses thr_alarm() when detects current state of
+ instances (is_running()), but it is not interfere with
+ flush_instances() later in the code, because until flush_instances()
+ complete in the main thread, Guardian thread is not permitted to
+ process instances. And before flush_instances() there is no instances
+ to proceed.
*/
pthread_attr_init(&guardian_thd_attr);
@@ -172,10 +198,8 @@ void manager(const Options &options)
}
- /*
- To work nicely with LinuxThreads, the signal thread is the first thread
- in the process.
- */
+ /* Load instances. */
+
int signo;
bool shutdown_complete;
@@ -189,11 +213,6 @@ void manager(const Options &options)
return;
}
- /* Initialize signals and alarm-infrastructure. */
-
- sigset_t mask;
- set_signals(&mask);
-
/* create the listener */
{
pthread_t listener_thd_id;
diff --git a/sql/field.cc b/sql/field.cc
index a920d6d91b1..7c25e4ad9f7 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4530,11 +4530,11 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
int error;
bool have_smth_to_conv;
my_bool in_dst_time_gap;
- THD *thd= table->in_use;
+ THD *thd= table ? table->in_use : current_thd;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
have_smth_to_conv= (str_to_datetime(from, len, &l_time,
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
MODE_NO_ZERO_DATE) |
MODE_NO_ZERO_IN_DATE, &error) >
MYSQL_TIMESTAMP_ERROR);
@@ -4566,7 +4566,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
}
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -4599,7 +4599,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
my_time_t timestamp= 0;
int error;
my_bool in_dst_time_gap;
- THD *thd= table->in_use;
+ THD *thd= table ? table->in_use : current_thd;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
longlong tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
@@ -4632,7 +4632,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
nr, MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int4store(ptr,timestamp);
}
@@ -4653,10 +4653,10 @@ longlong Field_timestamp::val_int(void)
{
uint32 temp;
TIME time_tmp;
- THD *thd= table->in_use;
+ THD *thd= table ? table->in_use : current_thd;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
@@ -4678,7 +4678,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
{
uint32 temp, temp2;
TIME time_tmp;
- THD *thd= table->in_use;
+ THD *thd= table ? table->in_use : current_thd;
char *to;
val_buffer->alloc(field_length+1);
@@ -4686,7 +4686,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
@@ -4749,9 +4749,9 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate)
{
long temp;
- THD *thd= table->in_use;
+ THD *thd= table ? table->in_use : current_thd;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
@@ -4788,7 +4788,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
a=sint4korr(a_ptr);
b=sint4korr(b_ptr);
@@ -4806,7 +4806,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->s->db_low_byte_first)
+ if (!table || !table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -4832,10 +4832,11 @@ void Field_timestamp::sql_type(String &res) const
void Field_timestamp::set_time()
{
- long tmp= (long) table->in_use->query_start();
+ THD *thd= table ? table->in_use : current_thd;
+ long tmp= (long) thd->query_start();
set_notnull();
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -5024,12 +5025,13 @@ String *Field_time::val_str(String *val_buffer,
bool Field_time::get_date(TIME *ltime, uint fuzzydate)
{
long tmp;
+ THD *thd= table ? table->in_use : current_thd;
if (!(fuzzydate & TIME_FUZZY_DATE))
{
- push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
- table->in_use->row_count);
+ thd->row_count);
return 1;
}
tmp=(long) sint3korr(ptr);
@@ -5217,9 +5219,10 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
TIME l_time;
uint32 tmp;
int error;
+ THD *thd= table ? table->in_use : current_thd;
if (str_to_datetime(from, len, &l_time, TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
MODE_INVALID_DATES)),
&error) <= MYSQL_TIMESTAMP_ERROR)
@@ -5235,7 +5238,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
from, len, MYSQL_TIMESTAMP_DATE, 1);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -5272,9 +5275,10 @@ int Field_date::store(longlong nr, bool unsigned_val)
TIME not_used;
int error;
longlong initial_nr= nr;
+ THD *thd= table ? table->in_use : current_thd;
nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE |
MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))), &error);
@@ -5295,7 +5299,7 @@ int Field_date::store(longlong nr, bool unsigned_val)
MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int4store(ptr, nr);
}
@@ -5321,7 +5325,7 @@ double Field_date::val_real(void)
{
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -5334,7 +5338,7 @@ longlong Field_date::val_int(void)
{
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -5350,7 +5354,7 @@ String *Field_date::val_str(String *val_buffer,
val_buffer->alloc(field_length);
int32 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
tmp=sint4korr(ptr);
else
#endif
@@ -5368,7 +5372,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
a=sint4korr(a_ptr);
b=sint4korr(b_ptr);
@@ -5386,7 +5390,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr)
void Field_date::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->s->db_low_byte_first)
+ if (!table || !table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -5420,9 +5424,10 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
TIME l_time;
long tmp;
int error;
+ THD *thd= table ? table->in_use : current_thd;
if (str_to_datetime(from, len, &l_time,
(TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))),
&error) <= MYSQL_TIMESTAMP_ERROR)
@@ -5460,9 +5465,10 @@ int Field_newdate::store(longlong nr, bool unsigned_val)
TIME l_time;
longlong tmp;
int error;
+ THD *thd= table ? table->in_use : current_thd;
if (number_to_datetime(nr, &l_time,
(TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))),
&error) == LL(-1))
@@ -5605,10 +5611,11 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
int error;
ulonglong tmp= 0;
enum enum_mysql_timestamp_type func_res;
+ THD *thd= table ? table->in_use : current_thd;
func_res= str_to_datetime(from, len, &time_tmp,
(TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))),
&error);
@@ -5623,7 +5630,7 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
from, len, MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int8store(ptr,tmp);
}
@@ -5655,9 +5662,10 @@ int Field_datetime::store(longlong nr, bool unsigned_val)
TIME not_used;
int error;
longlong initial_nr= nr;
+ THD *thd= table ? table->in_use : current_thd;
nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
- (table->in_use->variables.sql_mode &
+ (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE |
MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))), &error);
@@ -5675,7 +5683,7 @@ int Field_datetime::store(longlong nr, bool unsigned_val)
MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int8store(ptr,nr);
}
@@ -5704,7 +5712,7 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
int8store(ptr,tmp);
}
@@ -5731,7 +5739,7 @@ longlong Field_datetime::val_int(void)
{
longlong j;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
j=sint8korr(ptr);
else
#endif
@@ -5751,7 +5759,7 @@ String *Field_datetime::val_str(String *val_buffer,
int part3;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
tmp=sint8korr(ptr);
else
#endif
@@ -5816,7 +5824,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr)
{
longlong a,b;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
{
a=sint8korr(a_ptr);
b=sint8korr(b_ptr);
@@ -5834,7 +5842,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr)
void Field_datetime::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->s->db_low_byte_first)
+ if (!table || !table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -6044,17 +6052,6 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
uint a_len, b_len;
- if (field_charset->strxfrm_multiply > 1)
- {
- /*
- We have to remove end space to be able to compare multi-byte-characters
- like in latin_de 'ae' and 0xe4
- */
- return field_charset->coll->strnncollsp(field_charset,
- (const uchar*) a_ptr, field_length,
- (const uchar*) b_ptr,
- field_length, 0);
- }
if (field_charset->mbmaxlen != 1)
{
uint char_len= field_length/field_charset->mbmaxlen;
@@ -6063,8 +6060,14 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
}
else
a_len= b_len= field_length;
- return my_strnncoll(field_charset,(const uchar*) a_ptr, a_len,
- (const uchar*) b_ptr, b_len);
+ /*
+ We have to remove end space to be able to compare multi-byte-characters
+ like in latin_de 'ae' and 0xe4
+ */
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a_ptr, a_len,
+ (const uchar*) b_ptr, b_len,
+ 0);
}
@@ -9037,7 +9040,11 @@ bool
Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
int cuted_increment)
{
- THD *thd= table->in_use;
+ /*
+ If this field was created only for type conversion purposes it
+ will have table == NULL.
+ */
+ THD *thd= table ? table->in_use : current_thd;
if (thd->count_cuted_fields)
{
thd->cuted_fields+= cuted_increment;
@@ -9072,9 +9079,10 @@ Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
const char *str, uint str_length,
timestamp_type ts_type, int cuted_increment)
{
- if (table->in_use->really_abort_on_warning() ||
+ THD *thd= table ? table->in_use : current_thd;
+ if (thd->really_abort_on_warning() ||
set_warning(level, code, cuted_increment))
- make_truncated_value_warning(table->in_use, str, str_length, ts_type,
+ make_truncated_value_warning(thd, str, str_length, ts_type,
field_name);
}
@@ -9101,13 +9109,13 @@ Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
longlong nr, timestamp_type ts_type,
int cuted_increment)
{
- if (table->in_use->really_abort_on_warning() ||
+ THD *thd= table ? table->in_use : current_thd;
+ if (thd->really_abort_on_warning() ||
set_warning(level, code, cuted_increment))
{
char str_nr[22];
char *str_end= longlong10_to_str(nr, str_nr, -10);
- make_truncated_value_warning(table->in_use, str_nr,
- (uint) (str_end - str_nr),
+ make_truncated_value_warning(thd, str_nr, (uint) (str_end - str_nr),
ts_type, field_name);
}
}
@@ -9133,13 +9141,15 @@ void
Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
double nr, timestamp_type ts_type)
{
- if (table->in_use->really_abort_on_warning() ||
+ THD *thd= table ? table->in_use : current_thd;
+ if (thd->really_abort_on_warning() ||
set_warning(level, code, 1))
{
/* DBL_DIG is enough to print '-[digits].E+###' */
char str_nr[DBL_DIG + 8];
uint str_len= my_sprintf(str_nr, (str_nr, "%g", nr));
- make_truncated_value_warning(table->in_use, str_nr, str_len, ts_type,
+ make_truncated_value_warning(thd, str_nr, str_len, ts_type,
field_name);
}
}
+
diff --git a/sql/field.h b/sql/field.h
index f4d27e46877..ed13372df71 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -124,7 +124,7 @@ public:
static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types);
- bool eq(Field *field)
+ virtual bool eq(Field *field)
{
return (ptr == field->ptr && null_ptr == field->null_ptr &&
null_bit == field->null_bit);
@@ -813,7 +813,7 @@ public:
if ((*null_value= is_null()))
return 0;
#ifdef WORDS_BIGENDIAN
- if (table->s->db_low_byte_first)
+ if (table && table->s->db_low_byte_first)
return sint4korr(ptr);
#endif
long tmp;
@@ -1358,6 +1358,13 @@ public:
bit_ptr= bit_ptr_arg;
bit_ofs= bit_ofs_arg;
}
+ bool eq(Field *field)
+ {
+ return (Field::eq(field) &&
+ field->type() == type() &&
+ bit_ptr == ((Field_bit *)field)->bit_ptr &&
+ bit_ofs == ((Field_bit *)field)->bit_ofs);
+ }
};
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index bfb90b607ee..3885defb4d5 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -1131,7 +1131,7 @@ int ha_archive::end_bulk_insert()
int ha_archive::delete_all_rows()
{
DBUG_ENTER("ha_archive::delete_all_rows");
- DBUG_RETURN(0);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
/*
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 28cdfd23b6a..6aadce0191a 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -6684,6 +6684,17 @@ ha_innobase::store_lock(
&& !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_OPTIMIZE
+#ifdef __WIN__
+ /*
+ for alter table on win32 for succesfull operation
+ completion it is used TL_WRITE(=10) lock instead of
+ TL_WRITE_ALLOW_READ(=6), however here in innodb handler
+ TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes
+ race condition when several clients do alter table
+ simultaneously (bug #17264). This fix avoids the problem.
+ */
+ && thd->lex->sql_command != SQLCOM_ALTER_TABLE
+#endif
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE;
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index c762b7c286e..a73f368c51d 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -37,7 +37,8 @@ class ha_myisammrg: public handler
{
return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME |
HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED |
- HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE);
+ HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE |
+ HA_CAN_BIT_FIELD);
}
ulong index_flags(uint inx, uint part, bool all_parts) const
{
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 19b321ff3ca..46ab5b88624 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -70,7 +70,7 @@ handlerton ndbcluster_hton = {
NULL, /* create_cursor_read_view */
NULL, /* set_cursor_read_view */
NULL, /* close_cursor_read_view */
- HTON_NO_FLAGS
+ HTON_CAN_RECREATE
};
#define NDB_AUTO_INCREMENT_RETRIES 10
@@ -771,10 +771,11 @@ int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg)
if (ndb_blob->blobsNextBlob() != NULL)
DBUG_RETURN(0);
ha_ndbcluster *ha= (ha_ndbcluster *)arg;
- DBUG_RETURN(ha->get_ndb_blobs_value(ndb_blob));
+ DBUG_RETURN(ha->get_ndb_blobs_value(ndb_blob, ha->m_blobs_offset));
}
-int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob)
+int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob,
+ my_ptrdiff_t ptrdiff)
{
DBUG_ENTER("get_ndb_blobs_value");
@@ -807,7 +808,10 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob)
if (ndb_blob->readData(buf, len) != 0)
DBUG_RETURN(-1);
DBUG_ASSERT(len == blob_len);
+ // Ugly hack assumes only ptr needs to be changed
+ field_blob->ptr+= ptrdiff;
field_blob->set_ptr(len, buf);
+ field_blob->ptr-= ptrdiff;
}
offset+= blob_size;
}
@@ -870,6 +874,7 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
if (ndb_blob != NULL)
{
// Set callback
+ m_blobs_offset= buf - (byte*) table->record[0];
void *arg= (void *)this;
DBUG_RETURN(ndb_blob->setActiveHook(g_get_ndb_blobs_value, arg) != 0);
}
@@ -1174,12 +1179,23 @@ void ha_ndbcluster::release_metadata()
int ha_ndbcluster::get_ndb_lock_type(enum thr_lock_type type)
{
+ DBUG_ENTER("ha_ndbcluster::get_ndb_lock_type");
if (type >= TL_WRITE_ALLOW_WRITE)
- return NdbOperation::LM_Exclusive;
- else if (uses_blob_value(m_retrieve_all_fields))
- return NdbOperation::LM_Read;
+ {
+ DBUG_PRINT("info", ("Using exclusive lock"));
+ DBUG_RETURN(NdbOperation::LM_Exclusive);
+ }
+ else if (type == TL_READ_WITH_SHARED_LOCKS ||
+ uses_blob_value(m_retrieve_all_fields))
+ {
+ DBUG_PRINT("info", ("Using read lock"));
+ DBUG_RETURN(NdbOperation::LM_Read);
+ }
else
- return NdbOperation::LM_CommittedRead;
+ {
+ DBUG_PRINT("info", ("Using committed read"));
+ DBUG_RETURN(NdbOperation::LM_CommittedRead);
+ }
}
static const ulong index_type_flags[]=
@@ -1679,7 +1695,30 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
int check;
NdbTransaction *trans= m_active_trans;
- bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE;
+ if (m_lock_tuple)
+ {
+ /*
+ Lock level m_lock.type either TL_WRITE_ALLOW_WRITE
+ (SELECT FOR UPDATE) or TL_READ_WITH_SHARED_LOCKS (SELECT
+ LOCK WITH SHARE MODE) and row was not explictly unlocked
+ with unlock_row() call
+ */
+ NdbConnection *trans= m_active_trans;
+ NdbOperation *op;
+ // Lock row
+ DBUG_PRINT("info", ("Keeping lock on scanned row"));
+
+ if (!(op= m_active_cursor->lockCurrentTuple()))
+ {
+ m_lock_tuple= false;
+ ERR_RETURN(trans->getNdbError());
+ }
+ m_ops_pending++;
+ }
+ m_lock_tuple= false;
+
+ bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE &&
+ m_lock.type != TL_READ_WITH_SHARED_LOCKS;
do {
DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
/*
@@ -1695,6 +1734,13 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
if ((check= cursor->nextResult(contact_ndb, m_force_send)) == 0)
{
+ /*
+ Explicitly lock tuple if "select for update" or
+ "select lock in share mode"
+ */
+ m_lock_tuple= (m_lock.type == TL_WRITE_ALLOW_WRITE
+ ||
+ m_lock.type == TL_READ_WITH_SHARED_LOCKS);
DBUG_RETURN(0);
}
else if (check == 1 || check == 2)
@@ -1983,10 +2029,11 @@ 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);
+ bool need_pk = (lm == NdbOperation::LM_Read);
if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
m_index[active_index].index,
(const NDBTAB *) m_table)) ||
- op->readTuples(lm, 0, parallelism, sorted, descending))
+ op->readTuples(lm, 0, parallelism, sorted, descending, false, need_pk))
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
} else {
@@ -2036,8 +2083,11 @@ int ha_ndbcluster::full_table_scan(byte *buf)
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
+ bool need_pk = (lm == NdbOperation::LM_Read);
if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
- op->readTuples(lm, 0, parallelism))
+ op->readTuples(lm,
+ (need_pk)?NdbScanOperation::SF_KeyInfo:0,
+ parallelism))
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
if (generate_scan_filter(m_cond_stack, op))
@@ -2088,6 +2138,11 @@ int ha_ndbcluster::write_row(byte *record)
*/
if (!m_use_write && m_ignore_dup_key)
{
+ /*
+ compare if expression with that in start_bulk_insert()
+ start_bulk_insert will set parameters to ensure that each
+ write_row is committed individually
+ */
int peek_res= peek_indexed_rows(record);
if (!peek_res)
@@ -2327,6 +2382,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
DBUG_PRINT("info", ("Calling updateTuple on cursor"));
if (!(op= cursor->updateCurrentTuple()))
ERR_RETURN(trans->getNdbError());
+ m_lock_tuple= false;
m_ops_pending++;
if (uses_blob_value(FALSE))
m_blobs_pending= TRUE;
@@ -2406,6 +2462,7 @@ int ha_ndbcluster::delete_row(const byte *record)
DBUG_PRINT("info", ("Calling deleteTuple on cursor"));
if (cursor->deleteCurrentTuple() != 0)
ERR_RETURN(trans->getNdbError());
+ m_lock_tuple= false;
m_ops_pending++;
no_uncommitted_rows_update(-1);
@@ -2529,9 +2586,9 @@ void ha_ndbcluster::unpack_record(byte* buf)
const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec);
DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no,
- hidden_col->getName(), rec->u_64_value()));
+ hidden_col->getName(), rec->u_64_value()));
}
- //print_results();
+ print_results();
#endif
DBUG_VOID_RETURN;
}
@@ -2605,6 +2662,12 @@ int ha_ndbcluster::index_init(uint index)
{
DBUG_ENTER("ha_ndbcluster::index_init");
DBUG_PRINT("enter", ("index: %u", index));
+ /*
+ Locks are are explicitly released in scan
+ unless m_lock.type == TL_READ_HIGH_PRIORITY
+ and no sub-sequent call to unlock_row()
+ */
+ m_lock_tuple= false;
DBUG_RETURN(handler::index_init(index));
}
@@ -3217,6 +3280,19 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
DBUG_PRINT("enter", ("rows: %d", (int)rows));
m_rows_inserted= (ha_rows) 0;
+ if (!m_use_write && m_ignore_dup_key)
+ {
+ /*
+ compare if expression with that in write_row
+ we have a situation where peek_indexed_rows() will be called
+ so we cannot batch
+ */
+ DBUG_PRINT("info", ("Batching turned off as duplicate key is "
+ "ignored by using peek_row"));
+ m_rows_to_insert= 1;
+ m_bulk_insert_rows= 1;
+ DBUG_VOID_RETURN;
+ }
if (rows == (ha_rows) 0)
{
/* We don't know how many will be inserted, guess */
@@ -3614,6 +3690,22 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
}
/*
+ Unlock the last row read in an open scan.
+ Rows are unlocked by default in ndb, but
+ for SELECT FOR UPDATE and SELECT LOCK WIT SHARE MODE
+ locks are kept if unlock_row() is not called.
+*/
+
+void ha_ndbcluster::unlock_row()
+{
+ DBUG_ENTER("unlock_row");
+
+ DBUG_PRINT("info", ("Unlocking row"));
+ m_lock_tuple= false;
+ DBUG_VOID_RETURN;
+}
+
+/*
Start a transaction for running a statement if one is not
already running in a transaction. This will be the case in
a BEGIN; COMMIT; block
@@ -4085,6 +4177,12 @@ int ha_ndbcluster::create(const char *name,
set_dbname(name2);
set_tabname(name2);
+ if (current_thd->lex->sql_command == SQLCOM_TRUNCATE)
+ {
+ DBUG_PRINT("info", ("Dropping and re-creating table for TRUNCATE"));
+ if ((my_errno= delete_table(name)))
+ DBUG_RETURN(my_errno);
+ }
if (create_from_engine)
{
/*
@@ -4392,15 +4490,29 @@ int ha_ndbcluster::delete_table(const char *name)
int ha_ndbcluster::drop_table()
{
+ THD *thd= current_thd;
Ndb *ndb= get_ndb();
NdbDictionary::Dictionary *dict= ndb->getDictionary();
DBUG_ENTER("drop_table");
DBUG_PRINT("enter", ("Deleting %s", m_tabname));
-
+
release_metadata();
- if (dict->dropTable(m_tabname))
+ while (dict->dropTable(m_tabname))
+ {
+ const NdbError err= dict->getNdbError();
+ switch (err.status)
+ {
+ case NdbError::TemporaryError:
+ if (!thd->killed)
+ continue; // retry indefinitly
+ break;
+ default:
+ break;
+ }
ERR_RETURN(dict->getNdbError());
+ }
+
DBUG_RETURN(0);
}
@@ -4477,6 +4589,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_ops_pending(0),
m_skip_auto_increment(TRUE),
m_blobs_pending(0),
+ m_blobs_offset(0),
m_blobs_buffer(0),
m_blobs_buffer_size(0),
m_dupkey((uint) -1),
@@ -4809,14 +4922,24 @@ int ndbcluster_drop_database(const char *path)
List_iterator_fast<char> it(drop_list);
while ((tabname=it++))
{
- if (dict->dropTable(tabname))
+ while (dict->dropTable(tabname))
{
const NdbError err= dict->getNdbError();
- if (err.code != 709)
+ switch (err.status)
+ {
+ case NdbError::TemporaryError:
+ if (!thd->killed)
+ continue; // retry indefinitly
+ break;
+ default:
+ break;
+ }
+ if (err.code != 709) // 709: No such table existed
{
ERR_PRINT(err);
ret= ndb_to_mysql_error(&err);
}
+ break;
}
}
DBUG_RETURN(ret);
@@ -5891,6 +6014,7 @@ 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);
+ bool need_pk = (lm == NdbOperation::LM_Read);
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;
@@ -5957,7 +6081,8 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
end_of_buffer -= reclength;
}
else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab))
- &&!scanOp->readTuples(lm, 0, parallelism, sorted, FALSE, TRUE)
+ &&!scanOp->readTuples(lm, 0, parallelism, sorted,
+ FALSE, TRUE, need_pk)
&&!generate_scan_filter(m_cond_stack, scanOp)
&&!define_read_attrs(end_of_buffer-reclength, scanOp))
{
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index d75d7acefd9..01950c2b00f 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -503,6 +503,7 @@ class ha_ndbcluster: public handler
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
int external_lock(THD *thd, int lock_type);
+ void unlock_row();
int start_stmt(THD *thd, thr_lock_type lock_type);
const char * table_type() const;
const char ** bas_ext() const;
@@ -628,7 +629,7 @@ private:
int set_ndb_value(NdbOperation*, Field *field, uint fieldnr, bool *set_blob_value= 0);
int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, byte*);
friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg);
- int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
+ int get_ndb_blobs_value(NdbBlob *last_ndb_blob, my_ptrdiff_t ptrdiff);
int set_primary_key(NdbOperation *op, const byte *key);
int set_primary_key_from_record(NdbOperation *op, const byte *record);
int set_index_key_from_record(NdbOperation *op, const byte *record,
@@ -684,6 +685,7 @@ private:
char m_tabname[FN_HEADLEN];
ulong m_table_flags;
THR_LOCK_DATA m_lock;
+ bool m_lock_tuple;
NDB_SHARE *m_share;
NDB_INDEX_DATA m_index[MAX_KEY];
// NdbRecAttr has no reference to blob
@@ -704,6 +706,7 @@ private:
ha_rows m_ops_pending;
bool m_skip_auto_increment;
bool m_blobs_pending;
+ my_ptrdiff_t m_blobs_offset;
// memory for blobs in one tuple
char *m_blobs_buffer;
uint32 m_blobs_buffer_size;
diff --git a/sql/item.h b/sql/item.h
index 2311133b86b..2cadfda6895 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -794,6 +794,14 @@ public:
{
return 0;
}
+ /*
+ result_as_longlong() must return TRUE for Items representing DATE/TIME
+ functions and DATE/TIME table fields.
+ Those Items have result_type()==STRING_RESULT (and not INT_RESULT), but
+ their values should be compared as integers (because the integer
+ representation is more precise than the string one).
+ */
+ virtual bool result_as_longlong() { return FALSE; }
};
@@ -1219,6 +1227,10 @@ public:
return 0;
}
void cleanup();
+ bool result_as_longlong()
+ {
+ return field->can_be_compared_as_longlong();
+ }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item *equal_fields_propagator(byte *arg);
Item *set_no_const_sub(byte *arg);
@@ -1827,6 +1839,10 @@ public:
bool walk(Item_processor processor, byte *arg)
{ return (*ref)->walk(processor, arg); }
void print(String *str);
+ bool result_as_longlong()
+ {
+ return (*ref)->result_as_longlong();
+ }
void cleanup();
Item_field *filed_for_view_update()
{ return (*ref)->filed_for_view_update(); }
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 9db2f465080..1661f04a4ae 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -132,7 +132,7 @@ bool Cached_item_decimal::cmp()
{
my_decimal tmp;
my_decimal *ptmp= item->val_decimal(&tmp);
- if (null_value != item->null_value || my_decimal_cmp(&value, ptmp) == 0)
+ if (null_value != item->null_value || my_decimal_cmp(&value, ptmp))
{
null_value= item->null_value;
my_decimal2decimal(ptmp, &value);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 725be547a8a..80cf756d852 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -63,25 +63,137 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
}
+/*
+ Aggregates result types from the array of items.
+
+ SYNOPSIS:
+ agg_cmp_type()
+ thd thread handle
+ type [out] the aggregated type
+ items array of items to aggregate the type from
+ nitems number of items in the array
+
+ DESCRIPTION
+ This function aggregates result types from the array of items. Found type
+ supposed to be used later for comparison of values of these items.
+ Aggregation itself is performed by the item_cmp_type() function.
+
+ NOTES
+ Aggregation rules:
+ If there are DATE/TIME fields/functions in the list and no string
+ fields/functions in the list then:
+ The INT_RESULT type will be used for aggregation instead of original
+ result type of any DATE/TIME field/function in the list
+ All constant items in the list will be converted to a DATE/TIME using
+ found field or result field of found function.
+
+ Implementation notes:
+ The code is equivalent to:
+ 1. Check the list for presence of a STRING field/function.
+ Collect the is_const flag.
+ 2. Get a Field* object to use for type coercion
+ 3. Perform type conversion.
+ 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME
+ field/function and checks presence of a STRING field/function.
+ The second loop works only if a DATE/TIME field/function is found.
+ It checks presence of a STRING field/function in the rest of the list.
+
+ TODO
+ 1) The current implementation can produce false comparison results for
+ expressions like:
+ date_time_field BETWEEN string_field_with_dates AND string_constant
+ if the string_constant will omit some of leading zeroes.
+ In order to fully implement correct comparison of DATE/TIME the new
+ DATETIME_RESULT result type should be introduced and agg_cmp_type()
+ should return the DATE/TIME field used for the conversion. Later
+ this field can be used by comparison functions like Item_func_between to
+ convert string values to ints on the fly and thus return correct results.
+ This modification will affect functions BETWEEN, IN and CASE.
+
+ 2) If in the list a DATE field/function and a DATETIME field/function
+ are present in the list then the first found field/function will be
+ used for conversion. This may lead to wrong results and probably should
+ be fixed.
+*/
+
static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
{
uint i;
+ Item::Type res= (Item::Type)0;
+ /* Used only for date/time fields, max_length = 19 */
+ char buff[20];
+ uchar null_byte;
Field *field= NULL;
- /* If the first argument is a FIELD_ITEM, pull out the field. */
- if (items[0]->real_item()->type() == Item::FIELD_ITEM)
- field=((Item_field *)(items[0]->real_item()))->field;
- /* But if it can't be compared as a longlong, we don't really care. */
- if (field && !field->can_be_compared_as_longlong())
- field= NULL;
+ /* Search for date/time fields/functions */
+ for (i= 0; i < nitems; i++)
+ {
+ if (!items[i]->result_as_longlong())
+ {
+ /* Do not convert anything if a string field/function is present */
+ if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT)
+ {
+ i= nitems;
+ break;
+ }
+ continue;
+ }
+ if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM &&
+ items[i]->result_type() != INT_RESULT)
+ {
+ field= ((Item_field *)items[i]->real_item())->field;
+ break;
+ }
+ else if (res == Item::FUNC_ITEM)
+ {
+ field= items[i]->tmp_table_field_from_field_type(0);
+ if (field)
+ field->move_field(buff, &null_byte, 0);
+ break;
+ }
+ }
+ if (field)
+ {
+ /* Check the rest of the list for presence of a string field/function. */
+ for (i++ ; i < nitems; i++)
+ {
+ if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT &&
+ !items[i]->result_as_longlong())
+ {
+ if (res == Item::FUNC_ITEM)
+ delete field;
+ field= 0;
+ break;
+ }
+ }
+ }
+ /*
+ If the first item is a date/time function then its result should be
+ compared as int
+ */
+ if (field)
+ /* Suppose we are comparing dates */
+ type[0]= INT_RESULT;
+ else
+ type[0]= items[0]->result_type();
- type[0]= items[0]->result_type();
- for (i= 1; i < nitems; i++)
+ for (i= 0; i < nitems ; i++)
{
- type[0]= item_cmp_type(type[0], items[i]->result_type());
- if (field && convert_constant_item(thd, field, &items[i]))
- type[0]= INT_RESULT;
+ Item_result result= items[i]->result_type();
+ /*
+ Use INT_RESULT as result type for DATE/TIME fields/functions and
+ for constants successfully converted to DATE/TIME
+ */
+ if (field &&
+ ((!items[i]->const_item() && items[i]->result_as_longlong()) ||
+ (items[i]->const_item() && convert_constant_item(thd, field,
+ &items[i]))))
+ result= INT_RESULT;
+ type[0]= item_cmp_type(type[0], result);
}
+
+ if (res == Item::FUNC_ITEM && field)
+ delete field;
}
@@ -237,18 +349,18 @@ static bool convert_constant_item(THD *thd, Field *field, Item **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;
- field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES;
+ ulong orig_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode|= MODE_INVALID_DATES;
if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
{
Item *tmp=new Item_int_with_ref(field->val_int(), *item,
test(field->flags & UNSIGNED_FLAG));
- field->table->in_use->variables.sql_mode= orig_sql_mode;
+ thd->variables.sql_mode= orig_sql_mode;
if (tmp)
thd->change_item_tree(item, tmp);
return 1; // Item was replaced
}
- field->table->in_use->variables.sql_mode= orig_sql_mode;
+ thd->variables.sql_mode= orig_sql_mode;
}
return 0;
}
@@ -1098,9 +1210,8 @@ void Item_func_between::fix_length_and_dec()
return;
agg_cmp_type(thd, &cmp_type, args, 3);
- if (cmp_type == STRING_RESULT &&
- agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV))
- return;
+ if (cmp_type == STRING_RESULT)
+ agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 1cfdcef02d0..a2b10eacc79 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -46,7 +46,7 @@ public:
inline int set_compare_func(Item_bool_func2 *owner_arg)
{
return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
- (*b)->result_type()));
+ (*b)->result_type()));
}
inline int set_cmp_func(Item_bool_func2 *owner_arg,
Item **a1, Item **a2,
@@ -59,8 +59,9 @@ public:
inline int set_cmp_func(Item_bool_func2 *owner_arg,
Item **a1, Item **a2)
{
- return set_cmp_func(owner_arg, a1, a2, item_cmp_type((*a1)->result_type(),
- (*a2)->result_type()));
+ return set_cmp_func(owner_arg, a1, a2,
+ item_cmp_type((*a1)->result_type(),
+ (*a2)->result_type()));
}
inline int compare() { return (this->*func)(); }
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 2c770bec1ad..194d62b1183 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3296,7 +3296,7 @@ longlong Item_func_last_insert_id::val_int()
return value; // Avoid side effect of insert_id()
}
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- return thd->insert_id();
+ return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id();
}
/* This function is just used to test speed of different functions */
@@ -4512,7 +4512,7 @@ double Item_func_match::val_real()
if (ft_handler == NULL)
DBUG_RETURN(-1.0);
- if (table->null_row) /* NULL row from an outer join */
+ if (key != NO_SUCH_KEY && table->null_row) /* NULL row from an outer join */
return 0.0;
if (join_key)
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 3f728958df1..7a35dedc08a 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -154,7 +154,15 @@ String *Item_func_md5::val_str(String *str)
void Item_func_md5::fix_length_and_dec()
{
- max_length=32;
+ max_length=32;
+ /*
+ The MD5() function treats its parameter as being a case sensitive. Thus
+ we set binary collation on it so different instances of MD5() will be
+ compared properly.
+ */
+ args[0]->collation.set(
+ get_charset_by_csname(args[0]->collation.collation->csname,
+ MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
}
@@ -195,7 +203,15 @@ String *Item_func_sha::val_str(String *str)
void Item_func_sha::fix_length_and_dec()
{
- max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
+ max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
+ /*
+ The SHA() function treats its parameter as being a case sensitive. Thus
+ we set binary collation on it so different instances of MD5() will be
+ compared properly.
+ */
+ args[0]->collation.set(
+ get_charset_by_csname(args[0]->collation.collation->csname,
+ MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
}
@@ -288,11 +304,14 @@ String *Item_func_concat::val_str(String *str)
DBUG_ASSERT(fixed == 1);
String *res,*res2,*use_as_buff;
uint i;
+ bool is_const= 0;
null_value=0;
if (!(res=args[0]->val_str(str)))
goto null;
use_as_buff= &tmp_value;
+ /* Item_subselect in --ps-protocol mode will state it as a non-const */
+ is_const= args[0]->const_item() || !args[0]->used_tables();
for (i=1 ; i < arg_count ; i++)
{
if (res->length() == 0)
@@ -315,7 +334,7 @@ String *Item_func_concat::val_str(String *str)
current_thd->variables.max_allowed_packet);
goto null;
}
- if (res->alloced_length() >= res->length()+res2->length())
+ if (!is_const && res->alloced_length() >= res->length()+res2->length())
{ // Use old buffer
res->append(*res2);
}
@@ -370,6 +389,7 @@ String *Item_func_concat::val_str(String *str)
res= &tmp_value;
use_as_buff=str;
}
+ is_const= 0;
}
}
res->set_charset(collation.collation);
@@ -389,7 +409,14 @@ void Item_func_concat::fix_length_and_dec()
return;
for (uint i=0 ; i < arg_count ; i++)
- max_result_length+= args[i]->max_length;
+ {
+ if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
+ max_result_length+= (args[i]->max_length /
+ args[i]->collation.collation->mbmaxlen) *
+ collation.collation->mbmaxlen;
+ else
+ max_result_length+= args[i]->max_length;
+ }
if (max_result_length >= MAX_BLOB_WIDTH)
{
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 90d421a2c68..af59b8d740b 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -674,6 +674,7 @@ public:
str->charset(), conv_charset, &errors))
null_value= 1;
use_cached_value= 1;
+ str_value.mark_as_const();
safe= (errors == 0);
}
else
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index ca7028dae1e..d8b309978d5 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1391,7 +1391,7 @@ void Item_func_curtime::fix_length_and_dec()
{
TIME ltime;
- decimals=0;
+ decimals= DATETIME_DEC;
collation.set(&my_charset_bin);
store_now_in_TIME(&ltime);
value= TIME_to_ulonglong_time(&ltime);
@@ -1438,7 +1438,7 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
- decimals=0;
+ decimals= DATETIME_DEC;
collation.set(&my_charset_bin);
store_now_in_TIME(&ltime);
@@ -1785,7 +1785,7 @@ void Item_func_from_unixtime::fix_length_and_dec()
{
thd= current_thd;
collation.set(&my_charset_bin);
- decimals=0;
+ decimals= DATETIME_DEC;
max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null= 1;
thd->time_zone_used= 1;
@@ -2464,6 +2464,20 @@ String *Item_datetime_typecast::val_str(String *str)
}
+longlong Item_datetime_typecast::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ TIME ltime;
+ if (get_arg0_date(&ltime,1))
+ {
+ null_value= 1;
+ return 0;
+ }
+
+ return TIME_to_ulonglong_datetime(&ltime);
+}
+
+
bool Item_time_typecast::get_time(TIME *ltime)
{
bool res= get_arg0_time(ltime);
@@ -2478,6 +2492,17 @@ bool Item_time_typecast::get_time(TIME *ltime)
}
+longlong Item_time_typecast::val_int()
+{
+ TIME ltime;
+ if (get_time(&ltime))
+ {
+ null_value= 1;
+ return 0;
+ }
+ return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
+}
+
String *Item_time_typecast::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -2517,6 +2542,14 @@ String *Item_date_typecast::val_str(String *str)
return 0;
}
+longlong Item_date_typecast::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ TIME ltime;
+ if (args[0]->get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
+ return (longlong) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
+}
/*
MAKEDATE(a,b) is a date function that creates a date value
@@ -2553,6 +2586,33 @@ err:
}
+longlong Item_func_makedate::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ TIME l_time;
+ long daynr= (long) args[1]->val_int();
+ long yearnr= (long) args[0]->val_int();
+ long days;
+
+ if (args[0]->null_value || args[1]->null_value ||
+ yearnr < 0 || daynr <= 0)
+ goto err;
+
+ days= calc_daynr(yearnr,1,1) + daynr - 1;
+ /* Day number from year 0 to 9999-12-31 */
+ if (days >= 0 && days < MAX_DAY_NUMBER)
+ {
+ null_value=0;
+ get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
+ return (longlong) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
+ }
+
+err:
+ null_value= 1;
+ return 0;
+}
+
+
void Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index b2f0dab0837..d5d3efeeab4 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -344,6 +344,7 @@ public:
{
return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
};
@@ -359,6 +360,7 @@ public:
{
return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
};
@@ -388,6 +390,7 @@ public:
TIME representation using UTC-SYSTEM or per-thread time zone.
*/
virtual void store_now_in_TIME(TIME *now_time)=0;
+ bool result_as_longlong() { return TRUE; }
};
@@ -614,6 +617,7 @@ public:
{
collation.set(&my_charset_bin);
maybe_null=1;
+ decimals= DATETIME_DEC;
max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
@@ -622,6 +626,7 @@ public:
{
return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
};
/*
@@ -752,6 +757,8 @@ public:
max_length= 10;
maybe_null= 1;
}
+ bool result_as_longlong() { return TRUE; }
+ longlong val_int();
};
@@ -768,6 +775,8 @@ public:
{
return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
+ longlong val_int();
};
@@ -783,6 +792,8 @@ public:
{
return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
+ longlong val_int();
};
class Item_func_makedate :public Item_str_func
@@ -801,6 +812,8 @@ public:
{
return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
}
+ bool result_as_longlong() { return TRUE; }
+ longlong val_int();
};
diff --git a/sql/log.cc b/sql/log.cc
index ba02c9ba082..cfb90d398e6 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -36,6 +36,8 @@
MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log;
ulong sync_binlog_counter= 0;
+static Muted_query_log_event invisible_commit;
+
static bool test_if_number(const char *str,
long *res, bool allow_wildcards);
static bool binlog_init();
@@ -94,7 +96,9 @@ static int binlog_end_trans(THD *thd, IO_CACHE *trans_log, Log_event *end_ev)
{
int error=0;
DBUG_ENTER("binlog_end_trans");
- if (end_ev)
+
+ /* NULL denotes ROLLBACK with nothing to replicate */
+ if (end_ev != NULL)
error= mysql_bin_log.write(thd, trans_log, end_ev);
statistic_increment(binlog_cache_use, &LOCK_status);
@@ -126,14 +130,19 @@ static int binlog_commit(THD *thd, bool all)
DBUG_ASSERT(mysql_bin_log.is_open() &&
(all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))));
- if (!my_b_tell(trans_log))
+ if (my_b_tell(trans_log) == 0)
{
// we're here because trans_log was flushed in MYSQL_LOG::log()
DBUG_RETURN(0);
}
- Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
- qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
- DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
+ if (all)
+ {
+ Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
+ qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
+ DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
+ }
+ else
+ DBUG_RETURN(binlog_end_trans(thd, trans_log, &invisible_commit));
}
static int binlog_rollback(THD *thd, bool all)
@@ -1813,6 +1822,9 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)");
VOID(pthread_mutex_lock(&LOCK_log));
+ /* NULL would represent nothing to replicate after ROLLBACK */
+ DBUG_ASSERT(commit_event != NULL);
+
if (likely(is_open())) // Should always be true
{
uint length;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 9d6b223f2d7..e93c2855199 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1229,6 +1229,18 @@ bool Query_log_event::write(IO_CACHE* file)
my_b_safe_write(file, (byte*) query, q_len)) ? 1 : 0;
}
+/*
+ Query_log_event::Query_log_event()
+
+ The simplest constructor that could possibly work. This is used for
+ creating static objects that have a special meaning and are invisible
+ to the log.
+*/
+Query_log_event::Query_log_event()
+ :Log_event(), data_buf(0)
+{
+}
+
/*
Query_log_event::Query_log_event()
@@ -1877,6 +1889,21 @@ end:
/**************************************************************************
+ Muted_query_log_event methods
+**************************************************************************/
+
+#ifndef MYSQL_CLIENT
+/*
+ Muted_query_log_event::Muted_query_log_event()
+*/
+Muted_query_log_event::Muted_query_log_event()
+ :Query_log_event()
+{
+}
+#endif
+
+
+/**************************************************************************
Start_log_event_v3 methods
**************************************************************************/
diff --git a/sql/log_event.h b/sql/log_event.h
index 0e1eb7cd13c..f1b441dedb1 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -783,6 +783,7 @@ public:
void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0);
#endif
+ Query_log_event();
Query_log_event(const char* buf, uint event_len,
const Format_description_log_event *description_event,
Log_event_type event_type);
@@ -806,6 +807,26 @@ public:
/* Writes derived event-specific part of post header. */
};
+
+/*****************************************************************************
+
+ Muted Query Log Event class
+
+ Pretends to Log SQL queries, but doesn't actually do so.
+
+ ****************************************************************************/
+class Muted_query_log_event: public Query_log_event
+{
+public:
+#ifndef MYSQL_CLIENT
+ Muted_query_log_event();
+
+ bool write(IO_CACHE* file) { return(false); };
+ virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
+#endif
+};
+
+
#ifdef HAVE_REPLICATION
/*****************************************************************************
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 6d39f2f7440..3bb371b6004 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -513,6 +513,8 @@ class THD;
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
+bool check_single_table_access(THD *thd, ulong privilege,
+ TABLE_LIST *tables);
bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
bool is_proc, bool no_errors);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ae5e85ca15f..b73cd350012 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -120,16 +120,7 @@ extern "C" { // Because of SCO 3.2V4.2
#include <sys/utsname.h>
#endif /* __WIN__ */
-#ifdef HAVE_LIBWRAP
-#include <tcpd.h>
-#include <syslog.h>
-#ifdef NEED_SYS_SYSLOG_H
-#include <sys/syslog.h>
-#endif /* NEED_SYS_SYSLOG_H */
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_WARNING;
-
-#endif /* HAVE_LIBWRAP */
+#include <my_libwrap.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
@@ -591,6 +582,8 @@ static const char* default_dbug_option;
#endif
#ifdef HAVE_LIBWRAP
const char *libwrapName= NULL;
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
#endif
#ifdef HAVE_QUERY_CACHE
static ulong query_cache_limit= 0;
@@ -4072,8 +4065,8 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
struct request_info req;
signal(SIGCHLD, SIG_DFL);
request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
- fromhost(&req);
- if (!hosts_access(&req))
+ my_fromhost(&req);
+ if (!my_hosts_access(&req))
{
/*
This may be stupid but refuse() includes an exit(0)
@@ -4081,7 +4074,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
clean_exit() - same stupid thing ...
*/
syslog(deny_severity, "refused connect from %s",
- eval_client(&req));
+ my_eval_client(&req));
/*
C++ sucks (the gibberish in front just translates the supplied
@@ -5872,7 +5865,8 @@ The minimum value for this variable is 4096.",
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
(gptr*) &global_system_variables.read_buff_size,
(gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
- 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE,
+ 0},
{"read_only", OPT_READONLY,
"Make all non-temporary tables read-only, with the exception for replication (slave) threads and users with the SUPER privilege",
(gptr*) &opt_readonly,
@@ -5883,12 +5877,12 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.read_rnd_buff_size,
(gptr*) &max_system_variables.read_rnd_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
- ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0},
{"record_buffer", OPT_RECORD_BUFFER,
"Alias for read_buffer_size",
(gptr*) &global_system_variables.read_buff_size,
(gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
- 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0},
#ifdef HAVE_REPLICATION
{"relay_log_purge", OPT_RELAY_LOG_PURGE,
"0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.",
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index c80bb8bad9a..cf9dc6e3f60 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -52,6 +52,10 @@
#include <signal.h>
#include <errno.h>
+#ifdef __NETWARE__
+#include <sys/select.h>
+#endif
+
#ifdef EMBEDDED_LIBRARY
#undef MYSQL_SERVER
#undef MYSQL_CLIENT
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e36932cbc0c..cb0f35a425e 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -81,7 +81,7 @@ public:
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
SEL_ARG(enum Type type_arg)
:elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
- type(type_arg)
+ type(type_arg),min_flag(0)
{}
inline bool is_same(SEL_ARG *arg)
{
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 373753a7b80..1f6190241a3 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -608,7 +608,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
}
else
{
- store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
+ store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
+ CHECK_FIELD_IGNORE);
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW);
@@ -663,6 +664,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
field BETWEEN const1 AND const2
3. all references to the columns from the same table as column field
occur only in conjucts mentioned above.
+ 4. each of k first components the index is not partial, i.e. is not
+ defined on a fixed length proper prefix of the field.
If such an index exists the function through the ref parameter
returns the key value to find max/min for the field using the index,
@@ -672,8 +675,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
of the whole search key)
NOTE
- This function may set table->key_read to 1, which must be reset after
- index is used! (This can only happen when function returns 1)
+ This function may set table->key_read to 1, which must be reset after
+ index is used! (This can only happen when function returns 1)
RETURN
0 Index can not be used to optimize MIN(field)/MAX(field)
@@ -698,6 +701,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
{
KEY_PART_INFO *part,*part_end;
key_part_map key_part_to_use= 0;
+ /*
+ Perform a check if index is not disabled by ALTER TABLE
+ or IGNORE INDEX.
+ */
+ if (!table->keys_in_use_for_query.is_set(idx))
+ continue;
uint jdx= 0;
*prefix_len= 0;
for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ;
@@ -707,6 +716,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
return 0;
+ /* Check whether the index component is partial */
+ Field *part_field= table->field[part->fieldnr-1];
+ if ((part_field->flags & BLOB_FLAG) ||
+ part->length < part_field->key_length())
+ break;
+
if (field->eq(part->field))
{
ref->key= idx;
diff --git a/sql/slave.cc b/sql/slave.cc
index d884e54d60d..aed2a41a1e6 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1652,6 +1652,15 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
if (connect_to_master(thd, mysql, mi))
{
my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
+ /*
+ We need to clear the active VIO since, theoretically, somebody
+ might issue an awake() on this thread. If we are then in the
+ middle of closing and destroying the VIO inside the
+ mysql_close(), we will have a problem.
+ */
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ thd->clear_active_vio();
+#endif
mysql_close(mysql);
DBUG_RETURN(1);
}
@@ -3709,6 +3718,17 @@ err:
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql)
{
+ /*
+ Here we need to clear the active VIO before closing the
+ connection with the master. The reason is that THD::awake()
+ might be called from terminate_slave_thread() because somebody
+ issued a STOP SLAVE. If that happends, the close_active_vio()
+ can be called in the middle of closing the VIO associated with
+ the 'mysql' object, causing a crash.
+ */
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ thd->clear_active_vio();
+#endif
mysql_close(mysql);
mi->mysql=0;
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 02eed207f55..b3b99557b63 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -540,7 +540,7 @@ create_typelib(MEM_ROOT *mem_root, create_field *field_def, List<String> *src)
result->name= "";
if (!(result->type_names=(const char **)
alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1))))
- return 0;
+ DBUG_RETURN(0);
result->type_lengths= (unsigned int *)(result->type_names + result->count+1);
List_iterator<String> it(*src);
String conv;
@@ -574,7 +574,7 @@ create_typelib(MEM_ROOT *mem_root, create_field *field_def, List<String> *src)
result->type_names[result->count]= 0;
result->type_lengths[result->count]= 0;
}
- return result;
+ DBUG_RETURN(result);
}
@@ -1049,7 +1049,6 @@ sp_head::execute(THD *thd)
thd->net.no_send_error= 0;
if (i->free_list)
cleanup_items(i->free_list);
- i->state= Query_arena::EXECUTED;
/*
If we've set thd->user_var_events_alloc to mem_root of this SP
@@ -2180,6 +2179,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
m_lex->mark_as_requiring_prelocking(NULL);
}
thd->rollback_item_tree_changes();
+ /* Update the state of the active arena. */
+ thd->stmt_arena->state= Query_arena::EXECUTED;
+
/*
Unlike for PS we should not call Item's destructors for newly created
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1e715bff249..7d14e99fb77 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4184,10 +4184,6 @@ static bool setup_natural_join_row_types(THD *thd,
if (from_clause->elements == 0)
return FALSE; /* We come here in the case of UNIONs. */
- /* For stored procedures do not redo work if already done. */
- if (!context->select_lex->first_execution)
- return FALSE;
-
List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
TABLE_LIST *table_ref; /* Current table reference. */
/* Table reference to the left of the current. */
@@ -4200,14 +4196,18 @@ static bool setup_natural_join_row_types(THD *thd,
{
table_ref= left_neighbor;
left_neighbor= table_ref_it++;
- if (store_top_level_join_columns(thd, table_ref,
- left_neighbor, right_neighbor))
- return TRUE;
- if (left_neighbor)
+ /* For stored procedures do not redo work if already done. */
+ if (context->select_lex->first_execution)
{
- TABLE_LIST *first_leaf_on_the_right;
- first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution();
- left_neighbor->next_name_resolution_table= first_leaf_on_the_right;
+ if (store_top_level_join_columns(thd, table_ref,
+ left_neighbor, right_neighbor))
+ return TRUE;
+ if (left_neighbor)
+ {
+ TABLE_LIST *first_leaf_on_the_right;
+ first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution();
+ left_neighbor->next_name_resolution_table= first_leaf_on_the_right;
+ }
}
right_neighbor= table_ref;
}
@@ -4546,7 +4546,7 @@ bool setup_tables_and_check_access(THD *thd,
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
if (leaves_tmp->belong_to_view &&
- check_one_table_access(thd, want_access, leaves_tmp))
+ check_single_table_access(thd, want_access, leaves_tmp))
{
tables->hide_view_error(thd);
return TRUE;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 65fd4d3ac19..06082a57964 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1853,15 +1853,10 @@ bool select_dumpvar::send_data(List<Item> &items)
Item_func_set_user_var *xx;
Item_splocal *yy;
my_var *zz;
- DBUG_ENTER("send_data");
- if (unit->offset_limit_cnt)
- { // using limit offset,count
- unit->offset_limit_cnt--;
- DBUG_RETURN(0);
- }
+ DBUG_ENTER("select_dumpvar::send_data");
if (unit->offset_limit_cnt)
- { // Using limit offset,count
+ { // using limit offset,count
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
@@ -2050,7 +2045,9 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
backup->enable_slow_log= enable_slow_log;
backup->last_insert_id= last_insert_id;
backup->next_insert_id= next_insert_id;
+ backup->current_insert_id= current_insert_id;
backup->insert_id_used= insert_id_used;
+ backup->last_insert_id_used= last_insert_id_used;
backup->clear_next_insert_id= clear_next_insert_id;
backup->limit_found_rows= limit_found_rows;
backup->examined_row_count= examined_row_count;
@@ -2099,7 +2096,9 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
enable_slow_log= backup->enable_slow_log;
last_insert_id= backup->last_insert_id;
next_insert_id= backup->next_insert_id;
+ current_insert_id= backup->current_insert_id;
insert_id_used= backup->insert_id_used;
+ last_insert_id_used= backup->last_insert_id_used;
clear_next_insert_id= backup->clear_next_insert_id;
limit_found_rows= backup->limit_found_rows;
sent_row_count= backup->sent_row_count;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b63f88d7210..47150912c52 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1051,12 +1051,13 @@ class Sub_statement_state
{
public:
ulonglong options;
- ulonglong last_insert_id, next_insert_id;
+ ulonglong last_insert_id, next_insert_id, current_insert_id;
ulonglong limit_found_rows;
ha_rows cuted_fields, sent_row_count, examined_row_count;
ulong client_capabilities;
uint in_sub_stmt;
bool enable_slow_log, insert_id_used, clear_next_insert_id;
+ bool last_insert_id_used;
my_bool no_send_ok;
SAVEPOINT *savepoints;
};
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 348d43dc702..44947384b32 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -424,16 +424,27 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
DBUG_RETURN(-1);
}
-
- VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
- /* do not create database if another thread is holding read lock */
+ /*
+ Do not create database if another thread is holding read lock.
+ Wait for global read lock before acquiring LOCK_mysql_create_db.
+ After wait_if_global_read_lock() we have protection against another
+ global read lock. If we would acquire LOCK_mysql_create_db first,
+ another thread could step in and get the global read lock before we
+ reach wait_if_global_read_lock(). If this thread tries the same as we
+ (admin a db), it would then go and wait on LOCK_mysql_create_db...
+ Furthermore wait_if_global_read_lock() checks if the current thread
+ has the global read lock and refuses the operation with
+ ER_CANT_UPDATE_WITH_READLOCK if applicable.
+ */
if (wait_if_global_read_lock(thd, 0, 1))
{
error= -1;
goto exit2;
}
+ VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
/* Check directory */
strxmov(path, mysql_data_home, "/", db, NullS);
path_len= unpack_dirname(path,path); // Convert if not unix
@@ -537,9 +548,9 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
}
exit:
+ VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
exit2:
- VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error);
}
@@ -553,12 +564,23 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
int error= 0;
DBUG_ENTER("mysql_alter_db");
- VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
-
- /* do not alter database if another thread is holding read lock */
+ /*
+ Do not alter database if another thread is holding read lock.
+ Wait for global read lock before acquiring LOCK_mysql_create_db.
+ After wait_if_global_read_lock() we have protection against another
+ global read lock. If we would acquire LOCK_mysql_create_db first,
+ another thread could step in and get the global read lock before we
+ reach wait_if_global_read_lock(). If this thread tries the same as we
+ (admin a db), it would then go and wait on LOCK_mysql_create_db...
+ Furthermore wait_if_global_read_lock() checks if the current thread
+ has the global read lock and refuses the operation with
+ ER_CANT_UPDATE_WITH_READLOCK if applicable.
+ */
if ((error=wait_if_global_read_lock(thd,0,1)))
goto exit2;
+ VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
/* Check directory */
strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS);
fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
@@ -596,9 +618,9 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
send_ok(thd, result);
exit:
+ VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
exit2:
- VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error);
}
@@ -630,15 +652,26 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
TABLE_LIST* dropped_tables= 0;
DBUG_ENTER("mysql_rm_db");
- VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
-
- /* do not drop database if another thread is holding read lock */
+ /*
+ Do not drop database if another thread is holding read lock.
+ Wait for global read lock before acquiring LOCK_mysql_create_db.
+ After wait_if_global_read_lock() we have protection against another
+ global read lock. If we would acquire LOCK_mysql_create_db first,
+ another thread could step in and get the global read lock before we
+ reach wait_if_global_read_lock(). If this thread tries the same as we
+ (admin a db), it would then go and wait on LOCK_mysql_create_db...
+ Furthermore wait_if_global_read_lock() checks if the current thread
+ has the global read lock and refuses the operation with
+ ER_CANT_UPDATE_WITH_READLOCK if applicable.
+ */
if (wait_if_global_read_lock(thd, 0, 1))
{
error= -1;
goto exit2;
}
+ VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
(void) sprintf(path,"%s/%s",mysql_data_home,db);
length= unpack_dirname(path,path); // Convert if not unix
strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
@@ -747,7 +780,6 @@ 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 */
- start_waiting_global_read_lock(thd);
/*
If this database was the client's selected database, we silently change the
client's selected database to nothing (to have an empty SELECT DATABASE()
@@ -775,9 +807,9 @@ exit:
x_free(thd->db);
thd->reset_db(NULL, 0);
}
-exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
-
+ start_waiting_global_read_lock(thd);
+exit2:
DBUG_RETURN(error);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 9979b484292..4075478cbc7 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1056,16 +1056,19 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
to convert the latter operation internally to an UPDATE.
We also should not perform this conversion if we have
timestamp field with ON UPDATE which is different from DEFAULT.
+ Another case when conversion should not be performed is when
+ we have ON DELETE trigger on table so user may notice that
+ we cheat here. Note that it is ok to do such conversion for
+ tables which have ON UPDATE but have no ON DELETE triggers,
+ we just should not expose this fact to users by invoking
+ ON UPDATE triggers.
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
- table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
+ table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
{
- if (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
- TRG_ACTION_BEFORE, TRUE))
- goto before_trg_err;
if (thd->clear_next_insert_id)
{
/* Reset auto-increment cacheing if we do an update */
@@ -1076,13 +1079,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->record[0])))
goto err;
info->deleted++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
- TRG_ACTION_AFTER,
- TRUE));
- /* Update logfile and count */
- info->copied++;
- goto ok_or_after_trg_err;
+ /*
+ Since we pretend that we have done insert we should call
+ its after triggers.
+ */
+ goto after_trg_n_copied_inc;
}
else
{
@@ -1106,10 +1107,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
}
}
- info->copied++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
- TRG_ACTION_AFTER, TRUE));
}
else if ((error=table->file->write_row(table->record[0])))
{
@@ -1117,14 +1114,14 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))
goto err;
table->file->restore_auto_increment();
+ goto ok_or_after_trg_err;
}
- else
- {
- info->copied++;
- trg_error= (table->triggers &&
- table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
- TRG_ACTION_AFTER, TRUE));
- }
+
+after_trg_n_copied_inc:
+ info->copied++;
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
+ TRG_ACTION_AFTER, TRUE));
ok_or_after_trg_err:
if (key)
@@ -1937,6 +1934,14 @@ bool delayed_insert::handle_inserts(void)
if (!using_bin_log)
table->file->extra(HA_EXTRA_WRITE_CACHE);
pthread_mutex_lock(&mutex);
+
+ /* Reset auto-increment cacheing */
+ if (thd.clear_next_insert_id)
+ {
+ thd.next_insert_id= 0;
+ thd.clear_next_insert_id= 0;
+ }
+
while ((row=rows.get()))
{
stacked_inserts--;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d2699b88aa4..0bbfc64e272 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -304,18 +304,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)
{
@@ -344,9 +333,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
@@ -360,8 +346,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) {
@@ -388,20 +373,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);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e736aa13fa2..d63c6ef9f20 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1056,6 +1056,8 @@ typedef struct st_lex : public Query_tables_list
case SQLCOM_UPDATE_MULTI:
case SQLCOM_INSERT:
case SQLCOM_INSERT_SELECT:
+ case SQLCOM_REPLACE:
+ case SQLCOM_REPLACE_SELECT:
case SQLCOM_LOAD:
return TRUE;
default:
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fcdd5d91c44..439d7100637 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3338,15 +3338,6 @@ end_with_restore_list:
&lex->value_list,
lex->duplicates, lex->ignore)))
{
- /*
- Skip first table, which is the table we are inserting in.
- Below we set context.table_list again because the call above to
- mysql_insert_select_prepare() calls resolve_in_table_list_only(),
- which in turn resets context.table_list and
- context.first_name_resolution_table.
- */
- select_lex->context.table_list=
- select_lex->context.first_name_resolution_table= second_table;
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
/*
Invalidate the table in the query cache if something changed
@@ -4958,11 +4949,10 @@ error:
/*
- Check grants for commands which work only with one table and all other
- tables belonging to subselects or implicitly opened tables.
+ Check grants for commands which work only with one table.
SYNOPSIS
- check_one_table_access()
+ check_single_table_access()
thd Thread handler
privilege requested privilege
all_tables global table list of query
@@ -4972,7 +4962,8 @@ error:
1 - access denied, error is sent to client
*/
-bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
+bool check_single_table_access(THD *thd, ulong privilege,
+ TABLE_LIST *all_tables)
{
Security_context * backup_ctx= thd->security_ctx;
@@ -4980,7 +4971,14 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
if (all_tables->security_ctx)
thd->security_ctx= all_tables->security_ctx;
- if (check_access(thd, privilege, all_tables->db,
+ const char *db_name;
+ if ((all_tables->view || all_tables->field_translation) &&
+ !all_tables->schema_table)
+ db_name= all_tables->view_db.str;
+ else
+ db_name= all_tables->db;
+
+ if (check_access(thd, privilege, db_name,
&all_tables->grant.privilege, 0, 0,
test(all_tables->schema_table)))
goto deny;
@@ -4990,19 +4988,41 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
goto deny;
thd->security_ctx= backup_ctx;
+ return 0;
+
+deny:
+ thd->security_ctx= backup_ctx;
+ return 1;
+}
+
+/*
+ Check grants for commands which work only with one table and all other
+ tables belonging to subselects or implicitly opened tables.
+
+ SYNOPSIS
+ check_one_table_access()
+ thd Thread handler
+ privilege requested privilege
+ all_tables global table list of query
+
+ RETURN
+ 0 - OK
+ 1 - access denied, error is sent to client
+*/
+
+bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
+{
+ if (check_single_table_access (thd,privilege,all_tables))
+ return 1;
/* Check rights on tables of subselects and implictly opened tables */
TABLE_LIST *subselects_tables;
if ((subselects_tables= all_tables->next_global))
{
if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
- goto deny;
+ return 1;
}
return 0;
-
-deny:
- thd->security_ctx= backup_ctx;
- return 1;
}
@@ -5171,8 +5191,26 @@ bool check_global_access(THD *thd, ulong want_access)
/*
- Check the privilege for all used tables. Table privileges are cached
- in the table list for GRANT checking
+ Check the privilege for all used tables.
+
+ SYNOPSYS
+ check_table_access()
+ thd Thread context
+ want_access Privileges requested
+ tables List of tables to be checked
+ no_errors FALSE/TRUE - report/don't report error to
+ the client (using my_error() call).
+
+ NOTES
+ Table privileges are cached in the table list for GRANT checking.
+ This functions assumes that table list used and
+ thd->lex->query_tables_own_last value correspond to each other
+ (the latter should be either 0 or point to next_global member
+ of one of elements of this table list).
+
+ RETURN VALUE
+ FALSE - OK
+ TRUE - Access denied
*/
bool
@@ -7029,14 +7067,28 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
+ TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
DBUG_ENTER("multi_delete_precheck");
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
- check_table_access(thd,SELECT_ACL, tables,0) ||
- check_table_access(thd,DELETE_ACL, aux_tables,0))
+ check_table_access(thd, SELECT_ACL, tables, 0))
+ DBUG_RETURN(TRUE);
+
+ /*
+ Since aux_tables list is not part of LEX::query_tables list we
+ have to juggle with LEX::query_tables_own_last value to be able
+ call check_table_access() safely.
+ */
+ thd->lex->query_tables_own_last= 0;
+ if (check_table_access(thd, DELETE_ACL, aux_tables, 0))
+ {
+ thd->lex->query_tables_own_last= save_query_tables_own_last;
DBUG_RETURN(TRUE);
+ }
+ thd->lex->query_tables_own_last= save_query_tables_own_last;
+
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 505beedac3e..9f317842d98 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1068,8 +1068,9 @@ JOIN::optimize()
group_list ? 0 : select_distinct,
group_list && simple_group,
select_options,
- (order == 0 || skip_sort_order) ? select_limit :
- HA_POS_ERROR,
+ (order == 0 || skip_sort_order ||
+ test(select_options & OPTION_BUFFER_RESULT)) ?
+ select_limit : HA_POS_ERROR,
(char *) "")))
DBUG_RETURN(1);
@@ -4788,7 +4789,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
*/
bool
-store_val_in_field(Field *field,Item *item)
+store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
{
bool error;
THD *thd= field->table->in_use;
@@ -4799,7 +4800,7 @@ store_val_in_field(Field *field,Item *item)
with select_insert, which make count_cuted_fields= 1
*/
enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
- thd->count_cuted_fields= CHECK_FIELD_WARN;
+ thd->count_cuted_fields= check_flag;
error= item->save_in_field(field, 1);
thd->count_cuted_fields= old_count_cuted_fields;
return error || cuted_fields != thd->cuted_fields;
@@ -8814,6 +8815,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_length+= key_part_info->length;
}
}
+ else
+ {
+ set_if_smaller(table->s->max_rows, rows_limit);
+ param->end_write_records= rows_limit;
+ }
if (distinct && field_count != param->hidden_field_count)
{
@@ -10928,7 +10934,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
field->real_type() != MYSQL_TYPE_VARCHAR &&
(field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
{
- return !store_val_in_field(field,right_item);
+ return !store_val_in_field(field, right_item, CHECK_FIELD_WARN);
}
}
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 01ed8048e4a..d5a1bf82bc8 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -404,7 +404,7 @@ extern const char *join_type_str[];
void TEST_join(JOIN *join);
/* Extern functions in sql_select.cc */
-bool store_val_in_field(Field *field,Item *val);
+bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 246da4dfeec..ca6a8ddfb6b 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2070,7 +2070,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
SELECT_LEX sel;
INDEX_FIELD_VALUES idx_field_vals;
- char path[FN_REFLEN], *end, *base_name, *file_name;
+ char path[FN_REFLEN], *end, *base_name, *orig_base_name, *file_name;
uint len;
bool with_i_schema;
enum enum_schema_tables schema_table_idx;
@@ -2150,7 +2150,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
partial_cond= make_cond_for_info_schema(cond, tables);
it.rewind(); /* To get access to new elements in basis list */
- while ((base_name= it++) ||
+ while ((orig_base_name= base_name= it++) ||
/*
generate error for non existing database.
(to save old behaviour for SHOW TABLES FROM db)
@@ -2181,6 +2181,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (mysql_find_files(thd, &files, base_name,
path, idx_field_vals.table_value, 0))
goto err;
+ if (lower_case_table_names)
+ orig_base_name= thd->strdup(base_name);
}
List_iterator_fast<char> it_files(files);
@@ -2249,7 +2251,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
in this case.
*/
res= schema_table->process_table(thd, show_table_list, table,
- res, base_name,
+ res, orig_base_name,
show_table_list->alias);
close_tables_for_reopen(thd, &show_table_list);
DBUG_ASSERT(!lex->query_tables_own_last);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index fbceea84ce5..d476d4e0b62 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1656,8 +1656,23 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
my_casedn_str(files_charset_info, path);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
- else
+ else
+ {
+ #ifdef FN_DEVCHAR
+ /* check if the table name contains FN_DEVCHAR when defined */
+ const char *start= alias;
+ while (*start != '\0')
+ {
+ if (*start == FN_DEVCHAR)
+ {
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
+ DBUG_RETURN(TRUE);
+ }
+ start++;
+ }
+ #endif
build_table_path(path, sizeof(path), db, alias, reg_ext);
+ }
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -3615,12 +3630,21 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
their layout. See Field_string::type() for details.
Thus, if the table is too old we may have to rebuild the data to
update the layout.
+
+ There was a bug prior to mysql-4.0.25. Number of null fields was
+ calculated incorrectly. As a result frm and data files gets out of
+ sync after fast alter table. There is no way to determine by which
+ mysql version (in 4.0 and 4.1 branches) table was created, thus we
+ disable fast alter table for all tables created by mysql versions
+ prior to 5.0 branch.
+ See BUG#6236.
*/
need_copy_table= (alter_info->flags &
~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
(create_info->used_fields &
~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) ||
table->s->tmp_table ||
+ !table->s->mysql_version ||
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar));
create_info->frm_only= !need_copy_table;
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index d588572a762..d0729deecaa 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -70,6 +70,7 @@ class udf_handler :public Sql_alloc
void cleanup();
double val(my_bool *null_value)
{
+ is_null= 0;
if (get_arguments())
{
*null_value=1;
@@ -88,6 +89,7 @@ class udf_handler :public Sql_alloc
}
longlong val_int(my_bool *null_value)
{
+ is_null= 0;
if (get_arguments())
{
*null_value=1;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b4ae779f9e2..c2b7624c9e7 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -859,7 +859,12 @@ reopen_tables:
}
}
}
-
+ /*
+ Set exclude_from_table_unique_test value back to FALSE. It is needed for
+ further check in multi_update::prepare whether to use record cache.
+ */
+ lex->select_lex.exclude_from_table_unique_test= FALSE;
+
if (thd->fill_derived_tables() &&
mysql_handle_derived(lex, &mysql_derived_filling))
DBUG_RETURN(TRUE);
@@ -1038,7 +1043,7 @@ int multi_update::prepare(List<Item> &not_used_values,
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
TABLE *table=table_ref->table;
- if (!(tables_to_update & table->map) &&
+ if ((tables_to_update & table->map) &&
unique_table(thd, table_ref, update_tables))
table->no_cache= 1; // Disable row cache
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 954024df500..e45be1ef148 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -8789,6 +8789,8 @@ union_list:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
+ /* This counter shouldn't be incremented for UNION parts */
+ Lex->nest_level--;
if (mysql_new_select(lex, 0))
YYABORT;
mysql_init_select(lex);
diff --git a/sql/structs.h b/sql/structs.h
index 9421ebdc2af..41b5f3b39c5 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -70,7 +70,13 @@ typedef struct st_key_part_info { /* Info about a key part */
Field *field;
uint offset; /* offset in record (from 0) */
uint null_offset; /* Offset to null_bit in record */
- uint16 length; /* Length of key_part */
+ uint16 length; /* Length of keypart value in bytes */
+ /*
+ Number of bytes required to store the keypart value. This may be
+ different from the "length" field as it also counts
+ - possible NULL-flag byte (see HA_KEY_NULL_LENGTH)
+ - possible HA_KEY_BLOB_LENGTH bytes needed to store actual value length.
+ */
uint16 store_length;
uint16 key_type;
uint16 fieldnr; /* Fieldnum in UNIREG */
diff --git a/sql/table.cc b/sql/table.cc
index cfdb9bd93aa..9ec9463c33c 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -678,27 +678,6 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (outparam->key_info[key].flags & HA_FULLTEXT)
outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
- if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
- {
- /*
- If the UNIQUE key doesn't have NULL columns and is not a part key
- declare this as a primary key.
- */
- primary_key=key;
- for (i=0 ; i < keyinfo->key_parts ;i++)
- {
- uint fieldnr= key_part[i].fieldnr;
- if (!fieldnr ||
- outparam->field[fieldnr-1]->null_ptr ||
- outparam->field[fieldnr-1]->key_length() !=
- key_part[i].length)
- {
- primary_key=MAX_KEY; // Can't be used
- break;
- }
- }
- }
-
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
{
if (new_field_pack_flag <= 1)
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index a3e10ba7650..0d73c7d1e51 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -24,12 +24,12 @@
void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */
register uchar *map=cs->to_upper;
while (*str)
{
- if ((l=my_ismbchar(cs, str,end)))
+ /* Pointing after the '\0' is safe here. */
+ if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
str+=l;
else
{
@@ -42,12 +42,12 @@ void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register char *end=str+strlen(str);
register uchar *map=cs->to_lower;
while (*str)
{
- if ((l=my_ismbchar(cs, str,end)))
+ /* Pointing after the '\0' is safe here. */
+ if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
str+=l;
else
{
@@ -101,15 +101,18 @@ uint my_casedn_mb(CHARSET_INFO * cs, char *src, uint srclen,
return srclen;
}
+/*
+ my_strcasecmp_mb() returns 0 if strings are equal, non-zero otherwise.
+ */
int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
{
register uint32 l;
- register const char *end=s+strlen(s);
register uchar *map=cs->to_upper;
- while (s<end)
+ while (*s && *t)
{
- if ((l=my_ismbchar(cs, s,end)))
+ /* Pointing after the '\0' is safe here. */
+ if ((l=my_ismbchar(cs, s, s + cs->mbmaxlen)))
{
while (l--)
if (*s++ != *t++)
@@ -120,7 +123,8 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
else if (map[(uchar) *s++] != map[(uchar) *t++])
return 1;
}
- return *t;
+ /* At least one of '*s' and '*t' is zero here. */
+ return (*t != *s);
}
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index bf17375c0eb..d5041f30c0a 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -17,6 +17,7 @@
### BEGIN INIT INFO
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
+# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
@@ -97,6 +98,11 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin
export PATH
mode=$1 # start or stop
+shift
+other_args="$*" # uncommon, but needed when called from an RPM upgrade action
+ # Expected: "--skip-networking --skip-grant-tables"
+ # They are not checked here, intentionally, as it is the resposibility
+ # of the "spec" file author to give correct arguments only.
case `echo "testing\c"`,`echo -n testing` in
*c*,-n*) echo_n= echo_c= ;;
@@ -263,6 +269,11 @@ case "$mode" in
echo $echo_n "Starting MySQL"
if test -x $manager -a "$use_mysqld_safe" = "0"
then
+ if test -n "$other_args"
+ then
+ log_failure_msg "MySQL manager does not support options '$other_args'"
+ exit 1
+ fi
# 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 &
@@ -278,7 +289,7 @@ case "$mode" in
# Give extra arguments to mysqld with the my.cnf file. This script
# may be overwritten at next upgrade.
pid_file=$server_pid_file
- $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file >/dev/null 2>&1 &
+ $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file $other_args >/dev/null 2>&1 &
wait_for_pid created
# Make lock for RedHat / SuSE
@@ -326,8 +337,8 @@ case "$mode" in
'restart')
# Stop the service and regardless of whether it was
# running or not, start it again.
- $0 stop
- $0 start
+ $0 stop $other_args
+ $0 start $other_args
;;
'reload')
@@ -342,7 +353,7 @@ case "$mode" in
*)
# usage
- echo "Usage: $0 start|stop|restart|reload"
+ echo "Usage: $0 {start|stop|restart|reload} [ MySQL server options ]"
exit 1
;;
esac
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 202910f44e4..92d0708200b 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -155,6 +155,7 @@ Summary: MySQL - Benchmarks and test system
Group: Applications/Databases
Provides: mysql-bench
Obsoletes: mysql-bench
+AutoReqProv: no
%description bench
This package contains MySQL benchmark scripts and data.
@@ -485,7 +486,16 @@ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
# Upgrade databases if needed
-%{_bindir}/mysql_upgrade --user=%{mysqld_user}
+# This must be done as database user "root", who should be password-protected,
+# but this password is not available here.
+# So ensure the server is isolated as much as possible, and start it so that
+# passwords are not checked.
+# See the related change in the start script "/etc/init.d/mysql".
+chmod 700 $mysql_datadir
+%{_sysconfdir}/init.d/mysql start --skip-networking --skip-grant-tables
+%{_bindir}/mysql_upgrade
+%{_sysconfdir}/init.d/mysql stop --skip-networking --skip-grant-tables
+chmod 755 $mysql_datadir
# Change permissions again to fix any new files.
chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
@@ -723,6 +733,11 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Tue Jun 20 2006 Joerg Bruehe <joerg@mysql.com>
+
+- To run "mysql_upgrade", we need a running server;
+ start it in isolation and skip password checks.
+
* Sat May 20 2006 Kent Boortz <kent@mysql.com>
- Always compile for PIC, position independent code.
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index b0971980168..3876de58b0e 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
}