summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore7
-rw-r--r--README65
-rw-r--r--client/mysqlimport.c3
-rw-r--r--client/mysqltest.c135
-rw-r--r--configure.in99
-rw-r--r--include/keycache.h8
-rw-r--r--include/my_global.h3
-rw-r--r--include/my_pthread.h5
-rw-r--r--include/my_sys.h3
-rw-r--r--include/violite.h4
-rw-r--r--man/which.254
-rw-r--r--myisam/mi_check.c6
-rw-r--r--myisam/mi_packrec.c113
-rw-r--r--myisam/mi_static.c2
-rw-r--r--myisam/mi_test2.c12
-rw-r--r--myisam/myisamdef.h5
-rw-r--r--myisam/myisampack.c25
-rw-r--r--mysql-test/include/mysqltest-x.inc2
-rw-r--r--mysql-test/lib/mtr_process.pl10
-rw-r--r--mysql-test/lib/mtr_report.pl12
-rwxr-xr-xmysql-test/mysql-test-run.pl135
-rw-r--r--mysql-test/r/analyse.result6
-rw-r--r--mysql-test/r/connect.result6
-rw-r--r--mysql-test/r/create.result28
-rw-r--r--mysql-test/r/ctype_utf8.result4
-rw-r--r--mysql-test/r/func_gconcat.result38
-rw-r--r--mysql-test/r/func_like.result7
-rw-r--r--mysql-test/r/func_math.result5
-rw-r--r--mysql-test/r/group_by.result9
-rw-r--r--mysql-test/r/innodb.result20
-rw-r--r--mysql-test/r/insert_select.result10
-rw-r--r--mysql-test/r/join_outer.result133
-rw-r--r--mysql-test/r/mysqltest.result2
-rw-r--r--mysql-test/r/ndb_autodiscover.result2
-rw-r--r--mysql-test/r/olap.result25
-rw-r--r--mysql-test/r/ps.result44
-rw-r--r--mysql-test/r/ps_1general.result12
-rw-r--r--mysql-test/r/ps_2myisam.result6
-rw-r--r--mysql-test/r/ps_3innodb.result6
-rw-r--r--mysql-test/r/ps_4heap.result6
-rw-r--r--mysql-test/r/ps_5merge.result12
-rw-r--r--mysql-test/r/ps_6bdb.result6
-rw-r--r--mysql-test/r/ps_7ndb.result6
-rw-r--r--mysql-test/r/rpl_multi_delete2.result29
-rw-r--r--mysql-test/r/rpl_slave_status.result2
-rw-r--r--mysql-test/r/temp_table.result2
-rw-r--r--mysql-test/r/warnings.result4
-rw-r--r--mysql-test/t/analyse.test9
-rw-r--r--mysql-test/t/connect.test18
-rw-r--r--mysql-test/t/create.test13
-rw-r--r--mysql-test/t/ctype_utf8.test6
-rw-r--r--mysql-test/t/func_gconcat.test34
-rw-r--r--mysql-test/t/func_like.test17
-rw-r--r--mysql-test/t/func_math.test9
-rw-r--r--mysql-test/t/group_by.test10
-rw-r--r--mysql-test/t/innodb.test19
-rw-r--r--mysql-test/t/insert_select.test10
-rw-r--r--mysql-test/t/join_outer.test46
-rw-r--r--mysql-test/t/mysqltest.test45
-rw-r--r--mysql-test/t/olap.test22
-rw-r--r--mysql-test/t/openssl_1.test8
-rw-r--r--mysql-test/t/ps.test4
-rw-r--r--mysql-test/t/rpl_multi_delete2-slave.opt2
-rw-r--r--mysql-test/t/rpl_multi_delete2.test45
-rw-r--r--mysql-test/t/rpl_slave_status.test4
-rw-r--r--mysys/mf_keycache.c13
-rw-r--r--ndb/include/kernel/signaldata/BackupImpl.hpp9
-rw-r--r--ndb/include/kernel/signaldata/BackupSignalData.hpp5
-rw-r--r--ndb/include/kernel/signaldata/NFCompleteRep.hpp18
-rw-r--r--ndb/include/kernel/signaldata/NodeFailRep.hpp28
-rw-r--r--ndb/include/kernel/signaldata/SignalData.hpp1
-rw-r--r--ndb/include/kernel/signaldata/StartFragReq.hpp2
-rw-r--r--ndb/include/util/Parser.hpp2
-rw-r--r--ndb/include/util/ndb_opts.h12
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp6
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp1
-rw-r--r--ndb/src/common/debugger/signaldata/StartRec.cpp25
-rw-r--r--ndb/src/common/portlib/NdbThread.c10
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt5
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp104
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp3
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp148
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp329
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp12
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp22
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp140
-rw-r--r--ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp15
-rw-r--r--ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp13
-rw-r--r--ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp25
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp12
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp4
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp8
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp14
-rw-r--r--ndb/src/kernel/error/ErrorReporter.hpp2
-rw-r--r--ndb/src/kernel/main.cpp39
-rw-r--r--ndb/src/kernel/vm/Emulator.cpp72
-rw-r--r--ndb/src/kernel/vm/Emulator.hpp3
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp3
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp16
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp299
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp3
-rw-r--r--ndb/src/mgmsrv/Services.cpp2
-rw-r--r--ndb/src/ndbapi/Makefile.am3
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp26
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp3
-rw-r--r--ndb/src/ndbapi/ObjectMap.hpp33
-rw-r--r--ndb/src/ndbapi/SignalSender.cpp280
-rw-r--r--ndb/src/ndbapi/SignalSender.hpp83
-rw-r--r--ndb/test/include/NDBT_Test.hpp3
-rw-r--r--ndb/test/ndbapi/Makefile.am5
-rw-r--r--ndb/test/ndbapi/bank/Bank.cpp168
-rw-r--r--ndb/test/ndbapi/bank/Bank.hpp2
-rw-r--r--ndb/test/ndbapi/testSRBank.cpp246
-rw-r--r--ndb/test/src/NDBT_Test.cpp9
-rw-r--r--ndb/test/src/NdbBackup.cpp9
-rw-r--r--ndb/test/src/UtilTransactions.cpp22
-rw-r--r--ndb/tools/Makefile.am2
-rw-r--r--ndb/tools/ndb_config.cpp1
-rw-r--r--ndb/tools/restore/consumer_restore.cpp29
-rw-r--r--ndb/tools/restore/restore_main.cpp48
-rw-r--r--scripts/mysqld_multi.sh13
-rw-r--r--sql-common/client.c2
-rw-r--r--sql/examples/ha_archive.cc2
-rw-r--r--sql/examples/ha_tina.cc3
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/hostname.cc10
-rw-r--r--sql/item.cc9
-rw-r--r--sql/item_cmpfunc.cc203
-rw-r--r--sql/item_cmpfunc.h59
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_sum.cc9
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc16
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/opt_range.cc5
-rw-r--r--sql/opt_sum.cc3
-rw-r--r--sql/slave.cc9
-rw-r--r--sql/sql_analyse.cc13
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_cache.cc114
-rw-r--r--sql/sql_cache.h5
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_db.cc6
-rw-r--r--sql/sql_load.cc7
-rw-r--r--sql/sql_parse.cc87
-rw-r--r--sql/sql_select.cc19
-rw-r--r--sql/sql_show.cc38
-rw-r--r--sql/sql_table.cc28
-rw-r--r--sql/sql_test.cc19
-rw-r--r--sql/sql_yacc.yy42
-rw-r--r--sql/structs.h2
-rw-r--r--tests/mysql_client_test.c6
-rw-r--r--vio/vio.c4
-rw-r--r--vio/vio_priv.h2
-rw-r--r--vio/viosocket.c11
-rw-r--r--vio/viossl.c9
157 files changed, 3298 insertions, 1339 deletions
diff --git a/.bzrignore b/.bzrignore
index f9f9c146692..d8be10eacdb 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -800,6 +800,7 @@ ndb/test/ndbapi/testNodeRestart
ndb/test/ndbapi/testOIBasic
ndb/test/ndbapi/testOperations
ndb/test/ndbapi/testRestartGci
+ndb/test/ndbapi/testSRBank
ndb/test/ndbapi/testScan
ndb/test/ndbapi/testScan.dsp
ndb/test/ndbapi/testScanInterpreter
@@ -825,6 +826,7 @@ ndb/test/tools/hugoScanUpdate
ndb/test/tools/ndb_cpcc
ndb/test/tools/restart
ndb/test/tools/verify_index
+ndb/tools/ndb_config
ndb/tools/ndb_delete_all
ndb/tools/ndb_delete_all.dsp
ndb/tools/ndb_desc
@@ -969,7 +971,9 @@ support-files/MacOSX/Description.plist
support-files/MacOSX/Info.plist
support-files/MacOSX/ReadMe.txt
support-files/MacOSX/StartupParameters.plist
+support-files/MacOSX/postflight
support-files/MacOSX/postinstall
+support-files/MacOSX/preflight
support-files/MacOSX/preinstall
support-files/binary-configure
support-files/my-huge.cnf
@@ -1053,6 +1057,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-ndb/tools/ndb_config
-support-files/MacOSX/postflight
-support-files/MacOSX/preflight
diff --git a/README b/README
index 29851358765..88cdaaf67d4 100644
--- a/README
+++ b/README
@@ -1,52 +1,35 @@
-This is a release of MySQL, a GPL (free) SQL database server (more
-licence information in the PUBLIC file and in the reference manual).
+This is a release of MySQL, a dual-license SQL database server.
+MySQL is brought to you by the MySQL team at MySQL AB.
-Please read the "Upgrading from..." section in the manual first, if you are
-migrating from older versions of MySQL!
+License information can be found in these files:
+- For GPL (free) distributions, see the COPYING file.
+- For commercial distributions, see the MySQLEULA.txt file.
-The latest information about MySQL can be found at:
-http://www.mysql.com
-To see what it can do take a look at the features section in the
-manual.
+For further information about MySQL or additional documentation, see:
+- The latest information about MySQL: http://www.mysql.com
+- The current MySQL documentation: http:/dev.mysql.com/doc
-For installation instructions see the Installation chapter in the
-manual.
+Some manual sections of special interest:
-For future plans see the TODO appendix in the manual.
+- If you are migrating from an older version of MySQL, please read the
+ "Upgrading from..." section first!
+- To see what MySQL can do, take a look at the features section.
+- For installation instructions, see the Installation chapter.
+- For future plans, see the TODO appendix.
+- For the new features/bugfix history, see the News appendix.
+- For the currently known bugs/misfeatures (known errors) see the problems
+ appendix.
+- For a list of developers and other contributors, see the Credits
+ appendix.
-New features/bug fixes history is in the news appendix in the manual.
-
-For the currently known bugs/misfeatures (known errors) see the bugs
-appendix in the manual.
-
-For examples of SQL and benchmarking information see the bench
-directory.
-
-The manual mentioned above can be found in the Docs directory. The
-manual is available in the following formats: as plain ASCII text in
-Docs/manual.txt, in HTML format in Docs/manual_toc.html, as GNU Info in
-Docs/mysql.info and as PostScript in Docs/manual.ps.
-
-MySQL is brought to you by the MySQL team at MySQL AB
-
-For a list of developers and other contributors, see the Credits appendix
-in the manual.
+A local copy of the MySQL Reference Manual can be found in the Docs
+directory in GNU Info format. You can also browse the manual online or
+download it in any of several formats at the URL given earlier in this
+file.
************************************************************
IMPORTANT:
-Send bug (error) reports, questions and comments to the mailing list
-at mysql@lists.mysql.com
-
-Please use the 'mysqlbug' script when posting bug reports or questions
-about MySQL. mysqlbug will gather some information about your system
-and start your editor with a form in which you can describe your
-problem. Bug reports might be silently ignored by the MySQL
-maintainers if there is not a good reason included in the report as to
-why mysqlbug has not been used. A report that says 'MySQL does not
-work for me. Why?' is not considered a valid bug report.
-
-The mysqlbug script can be found in the 'scripts' directory of the
-distribution, that is '<where-you-installed-mysql>/scripts'.
+Bug or error reports should be sent to http://bugs.mysql.com.
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 019e3080023..ca4acd82db6 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -37,8 +37,9 @@ static char *add_load_option(char *ptr,const char *object,
const char *statement);
static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
- replace=0,silent=0,ignore=0,opt_compress=0,opt_local_file=0,
+ replace=0,silent=0,ignore=0,opt_compress=0,
opt_low_priority= 0, tty_password= 0;
+static uint opt_local_file=0;
static MYSQL mysql_connection;
static char *opt_password=0, *current_user=0,
*current_host=0, *current_db=0, *fields_terminated=0,
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 33702e9d1d2..f5facccee3a 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -97,6 +97,10 @@
#define DEFAULT_DELIMITER ";"
#define MAX_DELIMITER 16
+#define RESULT_OK 0
+#define RESULT_CONTENT_MISMATCH 1
+#define RESULT_LENGTH_MISMATCH 2
+
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
@@ -456,6 +460,7 @@ my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
+static int handle_no_error(struct st_query *q);
static void do_eval(DYNAMIC_STRING* query_eval, const char *query)
{
@@ -649,7 +654,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
ds->length, stat_info.st_size));
- DBUG_RETURN(2);
+ DBUG_RETURN(RESULT_LENGTH_MISMATCH);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS);
@@ -666,7 +671,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
res_ptr = res_ds.str;
if ((res_len = res_ds.length) != ds->length)
{
- res = 2;
+ res= RESULT_LENGTH_MISMATCH;
goto err;
}
}
@@ -676,7 +681,8 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
res_len = stat_info.st_size;
}
- res = (memcmp(res_ptr, ds->str, res_len)) ? 1 : 0;
+ res= (memcmp(res_ptr, ds->str, res_len)) ?
+ RESULT_CONTENT_MISMATCH : RESULT_OK;
err:
if (res && eval_result)
@@ -693,21 +699,21 @@ err:
static int check_result(DYNAMIC_STRING* ds, const char *fname,
my_bool require_option)
{
- int error = 0;
- int res=dyn_string_cmp(ds, fname);
+ int error= RESULT_OK;
+ int res= dyn_string_cmp(ds, fname);
if (res && require_option)
abort_not_supported_test();
switch (res) {
- case 0:
+ case RESULT_OK:
break; /* ok */
- case 2:
+ case RESULT_LENGTH_MISMATCH:
verbose_msg("Result length mismatch");
- error = 1;
+ error= RESULT_LENGTH_MISMATCH;
break;
- case 1:
+ case RESULT_CONTENT_MISMATCH:
verbose_msg("Result content mismatch");
- error = 1;
+ error= RESULT_CONTENT_MISMATCH;
break;
default: /* impossible */
die("Unknown error code from dyn_string_cmp()");
@@ -812,9 +818,9 @@ int var_set(const char *var_name, const char *var_name_end,
int open_file(const char *name)
{
+ char buff[FN_REFLEN];
DBUG_ENTER("open_file");
DBUG_PRINT("enter", ("name: %s", name));
- char buff[FN_REFLEN];
if (!test_if_hard_path(name))
{
strxmov(buff, opt_basedir, name, NullS);
@@ -843,9 +849,9 @@ int open_file(const char *name)
int check_eol_junk(const char *eol)
{
+ const char *p= eol;
DBUG_ENTER("check_eol_junk");
DBUG_PRINT("enter", ("eol: %s", eol));
- const char *p= eol;
/* Remove all spacing chars except new line */
while (*p && my_isspace(charset_info, *p) && (*p != '\n'))
p++;
@@ -2170,7 +2176,10 @@ int read_line(char *buf, int size)
{
found_eof:
if (cur_file->file != stdin)
+ {
my_fclose(cur_file->file, MYF(0));
+ cur_file->file= 0;
+ }
my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
cur_file->file_name= 0;
lineno--;
@@ -2556,10 +2565,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
argument= buff;
}
fn_format(buff, argument, "", "", 4);
- DBUG_ASSERT(cur_file->file == 0);
+ DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
if (!(cur_file->file=
my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
- die("Could not open %s: errno = %d", argument, errno);
+ die("Could not open %s: errno = %d", buff, errno);
+ cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
break;
}
case 'm':
@@ -2904,22 +2914,9 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
}
- if (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0)
- {
- /* Error code we wanted was != 0, i.e. not an expected success */
- verbose_msg("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0].code.errnum);
- error = 1;
- goto end;
- }
- else if (q->expected_errno[0].type == ERR_SQLSTATE &&
- strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ if (handle_no_error(q))
{
- /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
- verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
- q->query, q->expected_errno[0].code.sqlstate);
- error = 1;
+ error= 1;
goto end;
}
@@ -3099,10 +3096,8 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
{
if (q->abort_on_error)
{
- die("unable to prepare statement '%s': "
- "%s (mysql_stmt_errno=%d returned=%d)",
- query,
- mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
+ die("query '%s' failed: %d: %s", query,
+ mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
else
{
@@ -3183,12 +3178,8 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
}
/* If we got here the statement was both executed and read succeesfully */
-
- if (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0)
+ if (handle_no_error(q))
{
- verbose_msg("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0].code.errnum);
error= 1;
goto end;
}
@@ -3515,8 +3506,14 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q,
dynstr_append_mem(ds,"\n",1);
if (i)
{
- verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
- q->query, mysql_stmt_errno(stmt), q->expected_errno[0]);
+ if (q->expected_errno[0].type == ERR_ERRNO)
+ verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
+ q->query, mysql_stmt_errno(stmt),
+ q->expected_errno[0].code.errnum);
+ else
+ verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
+ q->query, mysql_stmt_sqlstate(stmt),
+ q->expected_errno[0].code.sqlstate);
return 1; /* Error */
}
verbose_msg("query '%s' failed: %d: %s", q->query, mysql_stmt_errno(stmt),
@@ -3531,6 +3528,43 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q,
return 0;
}
+
+/*
+ Handle absence of errors after execution
+
+ SYNOPSIS
+ handle_no_error()
+ q - context of query
+
+ RETURN VALUE
+ 0 - OK
+ 1 - Some error was expected from this query.
+*/
+
+static int handle_no_error(struct st_query *q)
+{
+ DBUG_ENTER("handle_no_error");
+
+ if (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0)
+ {
+ /* Error code we wanted was != 0, i.e. not an expected success */
+ verbose_msg("query '%s' succeeded - should have failed with errno %d...",
+ q->query, q->expected_errno[0].code.errnum);
+ DBUG_RETURN(1);
+ }
+ else if (q->expected_errno[0].type == ERR_SQLSTATE &&
+ strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ {
+ /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
+ verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
+ q->query, q->expected_errno[0].code.sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
/****************************************************************************\
* Functions to match SQL statements that can be prepared
\****************************************************************************/
@@ -3709,8 +3743,9 @@ int main(int argc, char **argv)
{
int error = 0;
struct st_query *q;
- my_bool require_file=0, q_send_flag=0;
+ my_bool require_file=0, q_send_flag=0, query_executed= 0;
char save_file[FN_REFLEN];
+ MY_STAT res_info;
MY_INIT(argv[0]);
{
DBUG_ENTER("main");
@@ -3746,9 +3781,8 @@ int main(int argc, char **argv)
embedded_server_args,
(char**) embedded_server_groups))
die("Can't initialize MySQL server");
- if (cur_file == file_stack)
+ if (cur_file == file_stack && cur_file->file == 0)
{
- DBUG_ASSERT(cur_file->file == 0);
cur_file->file= stdin;
cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
}
@@ -3904,6 +3938,7 @@ int main(int argc, char **argv)
save_file[0]=0;
}
error |= run_query(&cur_con->mysql, q, flags);
+ query_executed= 1;
q->last_argument= q->end;
break;
}
@@ -3924,6 +3959,7 @@ int main(int argc, char **argv)
is given on this connection.
*/
error |= run_query(&cur_con->mysql, q, QUERY_SEND);
+ query_executed= 1;
q->last_argument= q->end;
break;
case Q_RESULT:
@@ -3964,6 +4000,7 @@ int main(int argc, char **argv)
break;
case Q_EXEC:
do_exec(q);
+ query_executed= 1;
break;
case Q_START_TIMER:
/* Overwrite possible earlier start of timer */
@@ -4020,6 +4057,18 @@ int main(int argc, char **argv)
parser.current_line += current_line_inc;
}
+ if (!query_executed && result_file && my_stat(result_file, &res_info, 0))
+ {
+ /*
+ my_stat() successful on result file. Check if we have not run a
+ single query, but we do have a result file that contains data.
+ Note that we don't care, if my_stat() fails. For example for
+ non-existing or non-readable file we assume it's fine to have
+ no query output from the test file, e.g. regarded as no error.
+ */
+ if (res_info.st_size)
+ error|= (RESULT_CONTENT_MISMATCH | RESULT_LENGTH_MISMATCH);
+ }
if (result_file && ds_res.length && !error)
{
if (!record)
diff --git a/configure.in b/configure.in
index f3840e6f1a8..97eb0cb0edf 100644
--- a/configure.in
+++ b/configure.in
@@ -381,19 +381,19 @@ case "$target_os" in
;;
esac
;;
- sysv5UnixWare*)
+ sysv5UnixWare* | sysv5OpenUNIX8*)
if test "$GCC" != "yes"; then
- # We are using built-in inline function
+ # Use the built-in alloca()
CFLAGS="$CFLAGS -Kalloca"
fi
CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
;;
- sysv5OpenUNIX8*)
+ sysv5SCO_SV6.0.0*)
if test "$GCC" != "yes"; then
- # We are using built-in inline function
+ # Use the built-in alloca()
CFLAGS="$CFLAGS -Kalloca"
+ CXXFLAGS="$CFLAGS -Kalloca"
fi
- CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
;;
esac
AC_SUBST(CC)
@@ -1128,6 +1128,15 @@ case $SYSTEM_TYPE in
MAX_C_OPTIMIZE="-O"
fi
;;
+ *darwin9*)
+ if test "$ac_cv_prog_gcc" = "yes"
+ then
+ FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
+ CFLAGS="$CFLAGS $FLAGS"
+ CXXFLAGS="$CXXFLAGS $FLAGS"
+ MAX_C_OPTIMIZE="-O"
+ fi
+ ;;
*freebsd*)
echo "Adding fix for interrupted reads"
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
@@ -1440,8 +1449,6 @@ then
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
fi
AC_MSG_RESULT("yes")
# We must have cc
@@ -1467,87 +1474,41 @@ then
AC_MSG_RESULT("no")
fi
fi
-# Hack for SCO UnixWare7
+
+#
+# Check for SCO threading libraries
#
if test "$with_named_thread" = "no"
then
- AC_MSG_CHECKING("SCO UnixWare7 native threads")
- if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null
+ AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads])
+ if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \
+ expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \
+ expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null
then
if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
then
MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
- if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
- then
- AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
+ if expr "$CC" : ".*gcc.*" > /dev/null
then
+ with_named_thread="-pthread -lsocket -lnsl"
CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
else
+ with_named_thread="-Kthread -lsocket -lnsl"
CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
fi
- AC_MSG_RESULT("yes")
- else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
- fi
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-# Hack for Caldera OpenUNIX8
-#
-if test "$with_named_thread" = "no"
-then
- AC_MSG_CHECKING("OpenUNIX8 native threads")
- if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null
- then
- if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
- AC_DEFINE([HAVE_UNIXWARE7_THREADS], [1],
- [UNIXWARE7 threads are not posix])
- else
- AC_DEFINE([HAVE_UNIXWARE7_POSIX], [1],
- [new UNIXWARE7 threads that are not yet posix])
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
- then
- CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- else
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
+ AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library])
fi
- AC_MSG_RESULT("yes")
+ AC_MSG_RESULT(yes)
else
- { echo "configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ AC_MSG_RESULT(failed)
+ { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
fi
else
- AC_MSG_RESULT("no")
+ AC_MSG_RESULT(no)
fi
fi
@@ -3016,7 +2977,7 @@ then
AC_CONFIG_FILES(bdb/Makefile)
echo "CONFIGURING FOR BERKELEY DB"
- bdb_conf_flags="--disable-shared"
+ bdb_conf_flags="--disable-shared --build=$build_alias"
if test $with_debug = "yes"
then
bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic"
diff --git a/include/keycache.h b/include/keycache.h
index a292a69b0a3..9fe1cce5da5 100644
--- a/include/keycache.h
+++ b/include/keycache.h
@@ -90,10 +90,10 @@ typedef struct st_key_cache
/* Statistics variables. These are reset in reset_key_cache_counters(). */
ulong global_blocks_changed; /* number of currently dirty blocks */
- ulong global_cache_w_requests;/* number of write requests (write hits) */
- ulong global_cache_write; /* number of writes from the cache to files */
- ulong global_cache_r_requests;/* number of read requests (read hits) */
- ulong global_cache_read; /* number of reads from files to the cache */
+ ulonglong global_cache_w_requests;/* number of write requests (write hits) */
+ ulonglong global_cache_write; /* number of writes from cache to files */
+ ulonglong global_cache_r_requests;/* number of read requests (read hits) */
+ ulonglong global_cache_read; /* number of reads from files to cache */
int blocks; /* max number of blocks in the cache */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
diff --git a/include/my_global.h b/include/my_global.h
index f3d42106458..0f99aacd079 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -801,6 +801,7 @@ typedef off_t os_off_t;
#define socket_errno WSAGetLastError()
#define SOCKET_EINTR WSAEINTR
#define SOCKET_EAGAIN WSAEINPROGRESS
+#define SOCKET_ETIMEDOUT WSAETIMEDOUT
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
#define SOCKET_ENFILE ENFILE
#define SOCKET_EMFILE EMFILE
@@ -808,6 +809,7 @@ typedef off_t os_off_t;
#define socket_errno sock_errno()
#define SOCKET_EINTR SOCEINTR
#define SOCKET_EAGAIN SOCEINPROGRESS
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
#define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK
#define SOCKET_ENFILE SOCENFILE
#define SOCKET_EMFILE SOCEMFILE
@@ -817,6 +819,7 @@ typedef off_t os_off_t;
#define closesocket(A) close(A)
#define SOCKET_EINTR EINTR
#define SOCKET_EAGAIN EAGAIN
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
#define SOCKET_EWOULDBLOCK EWOULDBLOCK
#define SOCKET_ENFILE ENFILE
#define SOCKET_EMFILE EMFILE
diff --git a/include/my_pthread.h b/include/my_pthread.h
index fde62655c5f..d83ddf62a80 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -298,11 +298,6 @@ extern int my_pthread_create_detached;
int sigwait(sigset_t *set, int *sig);
#endif
-#if defined(HAVE_UNIXWARE7_POSIX)
-#undef HAVE_NONPOSIX_SIGWAIT
-#define HAVE_NONPOSIX_SIGWAIT /* sigwait takes only 1 argument */
-#endif
-
#ifndef HAVE_NONPOSIX_SIGWAIT
#define my_sigwait(A,B) sigwait((A),(B))
#else
diff --git a/include/my_sys.h b/include/my_sys.h
index ab0efe247ef..02ea188a18e 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -216,9 +216,6 @@ extern CHARSET_INFO *all_charsets[256];
extern CHARSET_INFO compiled_charsets[];
/* statistics */
-extern ulong my_cache_w_requests, my_cache_write, my_cache_r_requests,
- my_cache_read;
-extern ulong my_blocks_used, my_blocks_changed;
extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
extern uint mysys_usage_id;
extern my_bool my_init_done;
diff --git a/include/violite.h b/include/violite.h
index 4b644051dd2..fbc6a546cc5 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -68,6 +68,8 @@ int vio_fastsend(Vio *vio);
int vio_keepalive(Vio *vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_should_retry(Vio *vio);
+/* Check that operation was timed out */
+my_bool vio_was_interrupted(Vio *vio);
/* Short text description of the socket for those, who are curious.. */
const char* vio_description(Vio *vio);
/* Return the type of the connection */
@@ -146,6 +148,7 @@ int vio_close_shared_memory(Vio * vio);
#define vio_fastsend(vio) (vio)->fastsend(vio)
#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
#define vio_should_retry(vio) (vio)->should_retry(vio)
+#define vio_was_interrupted(vio) (vio)->was_interrupted(vio)
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
@@ -188,6 +191,7 @@ struct st_vio
my_bool (*peer_addr)(Vio*, char *, uint16*);
void (*in_addr)(Vio*, struct in_addr*);
my_bool (*should_retry)(Vio*);
+ my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
void *ssl_arg;
diff --git a/man/which.2 b/man/which.2
deleted file mode 100644
index 30d5557ed01..00000000000
--- a/man/which.2
+++ /dev/null
@@ -1,54 +0,0 @@
-.TH WHICH 1 "20 December 2000"
-.SH NAME
-which - Jani please supply one.
-.SH USAGE
-which [options] [--] programname [...]
-.SH SYNOPSIS
-.B which
-.RB [ \-\-version | \-[vV] ]
-.RB [ \-\-skip\-dot ]
-.RB [ \-\-skip\-tilde ]
-.RB [ \-\-show\-dot ]
-.RB [ \-\-show\-tilde ]
-.RB [ \-\-tty\-only ]
-.RB [ \-\-all | \-a ]
-.RB [ \-\-read\-alias | \-i ]
-.RB [ \-\-skip\-alias ]
-.SH DESCRIPTION
-.TP
-.BR which
-supports by executing
-.TP
-.BR \-\-version | \-[vV]
-Print version and exit successfully.
-.TP
-.BR \-\-skip\-dot
-Skip directories in PATH that start with a dot.
-.TP
-.BR \-\-skip\-tilde
-Skip directories in PATH that start with a tilde.
-.TP
-.BR \-\-show\-dot
-Don\'t expand a dot to current directory in output.
-.TP
-.BR \-\-show\-tilde
-Output a tilde for HOME directory for non-root.
-.TP
-.BR \-\-tty\-only
-Stop processing options on the right if not on tty.
-.TP
-.BR \-\-all | \-a
-Print all matches in PATH, not just the first
-.TP
-.BR \-\-read\-alias | \-i
-Read list of aliases from stdin.
-.TP
-.BR \-\-skip\-alias
-Ignore option
-.BR --read-alias;
-don\'t read stdin.
-.SH "SEE ALSO"
-isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), mysqld_safe (1), which1 (1), zap (1),
-.SH AUTHOR
-Ver 1.0, distribution 3.23.29a Michael (Monty) Widenius (monty@tcx.se), TCX Datakonsult AB (http://www.tcx.se). This software comes with no warranty. Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com)
-.\" end of man page \ No newline at end of file
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 246d2c58dde..038ce8d953f 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -3193,9 +3193,11 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
break;
case COMPRESSED_RECORD:
reclength=info->packed_length;
- length=save_pack_length(block_buff,reclength);
+ length= save_pack_length((uint) share->pack.version, block_buff,
+ reclength);
if (info->s->base.blobs)
- length+=save_pack_length(block_buff+length,info->blob_length);
+ length+= save_pack_length((uint) share->pack.version,
+ block_buff + length, info->blob_length);
if (my_b_write(&info->rec_cache,block_buff,length) ||
my_b_write(&info->rec_cache,(byte*) sort_param->rec_buff,reclength))
{
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 1a71d43a7f1..322420b71db 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -149,11 +149,12 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
my_errno=HA_ERR_END_OF_FILE;
goto err0;
}
- if (memcmp((byte*) header,(byte*) myisam_pack_file_magic,4))
+ if (memcmp((byte*) header, (byte*) myisam_pack_file_magic, 3))
{
my_errno=HA_ERR_WRONG_IN_RECORD;
goto err0;
}
+ share->pack.version= header[3];
share->pack.header_length= uint4korr(header+4);
share->min_pack_length=(uint) uint4korr(header+8);
share->max_pack_length=(uint) uint4korr(header+12);
@@ -1040,38 +1041,12 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file,
return BLOCK_FATAL_ERROR;
DBUG_DUMP("header",(byte*) header,ref_length);
}
- if (header[0] < 254)
- {
- info->rec_len=header[0];
- head_length=1;
- }
- else if (header[0] == 254)
- {
- info->rec_len=uint2korr(header+1);
- head_length=3;
- }
- else
- {
- info->rec_len=uint3korr(header+1);
- head_length=4;
- }
+ head_length= read_pack_length((uint) myisam->s->pack.version, header,
+ &info->rec_len);
if (myisam->s->base.blobs)
{
- if (header[head_length] < 254)
- {
- info->blob_len=header[head_length];
- head_length++;
- }
- else if (header[head_length] == 254)
- {
- info->blob_len=uint2korr(header+head_length+1);
- head_length+=3;
- }
- else
- {
- info->blob_len=uint3korr(header+head_length+1);
- head_length+=4;
- }
+ head_length+= read_pack_length((uint) myisam->s->pack.version,
+ header + head_length, &info->blob_len);
if (!(mi_alloc_rec_buff(myisam,info->rec_len + info->blob_len,
&myisam->rec_buff)))
return BLOCK_FATAL_ERROR; /* not enough memory */
@@ -1220,34 +1195,12 @@ void _mi_unmap_file(MI_INFO *info)
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
uchar *header)
{
- if (header[0] < 254)
- info->rec_len= *header++;
- else if (header[0] == 254)
- {
- info->rec_len=uint2korr(header+1);
- header+=3;
- }
- else
- {
- info->rec_len=uint3korr(header+1);
- header+=4;
- }
+ header+= read_pack_length((uint) myisam->s->pack.version, header,
+ &info->rec_len);
if (myisam->s->base.blobs)
{
- if (header[0] < 254)
- {
- info->blob_len= *header++;
- }
- else if (header[0] == 254)
- {
- info->blob_len=uint2korr(header+1);
- header+=3;
- }
- else
- {
- info->blob_len=uint3korr(header+1);
- header+=4;
- }
+ header+= read_pack_length((uint) myisam->s->pack.version, header,
+ &info->blob_len);
/* mi_alloc_rec_buff sets my_errno on error */
if (!(mi_alloc_rec_buff(myisam, info->blob_len,
&myisam->rec_buff)))
@@ -1319,7 +1272,7 @@ static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf,
/* Save length of row */
-uint save_pack_length(byte *block_buff,ulong length)
+uint save_pack_length(uint version, byte *block_buff, ulong length)
{
if (length < 254)
{
@@ -1333,6 +1286,46 @@ uint save_pack_length(byte *block_buff,ulong length)
return 3;
}
*(uchar*) block_buff=255;
- int3store(block_buff+1,(ulong) length);
- return 4;
+ if (version == 1) /* old format */
+ {
+ DBUG_ASSERT(length <= 0xFFFFFF);
+ int3store(block_buff + 1, (ulong) length);
+ return 4;
+ }
+ else
+ {
+ int4store(block_buff + 1, (ulong) length);
+ return 5;
+ }
+}
+
+
+uint read_pack_length(uint version, const uchar *buf, ulong *length)
+{
+ if (buf[0] < 254)
+ {
+ *length= buf[0];
+ return 1;
+ }
+ else if (buf[0] == 254)
+ {
+ *length= uint2korr(buf + 1);
+ return 3;
+ }
+ if (version == 1) /* old format */
+ {
+ *length= uint3korr(buf + 1);
+ return 4;
+ }
+ else
+ {
+ *length= uint4korr(buf + 1);
+ return 5;
+ }
+}
+
+
+uint calc_pack_length(uint version, ulong length)
+{
+ return (length < 254) ? 1 : (length < 65536) ? 3 : (version == 1) ? 4 : 5;
}
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index f41aeff8453..9725c120f44 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -27,7 +27,7 @@ LIST *myisam_open_list=0;
uchar NEAR myisam_file_magic[]=
{ (uchar) 254, (uchar) 254,'\007', '\001', };
uchar NEAR myisam_pack_file_magic[]=
-{ (uchar) 254, (uchar) 254,'\010', '\001', };
+{ (uchar) 254, (uchar) 254,'\010', '\002', };
my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1;
uint myisam_quick_table_bits=9;
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 95c8ce56a13..6a6dcb971a2 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -831,17 +831,19 @@ end:
puts("Locking used");
if (use_blob)
puts("blobs used");
-#if 0
printf("key cache status: \n\
blocks used:%10lu\n\
+not flushed:%10lu\n\
w_requests: %10lu\n\
writes: %10lu\n\
r_requests: %10lu\n\
reads: %10lu\n",
- my_blocks_used,
- my_cache_w_requests, my_cache_write,
- my_cache_r_requests, my_cache_read);
-#endif
+ dflt_key_cache->blocks_used,
+ dflt_key_cache->global_blocks_changed,
+ (ulong) dflt_key_cache->global_cache_w_requests,
+ (ulong) dflt_key_cache->global_cache_write,
+ (ulong) dflt_key_cache->global_cache_r_requests,
+ (ulong) dflt_key_cache->global_cache_read);
}
end_key_cache(dflt_key_cache,1);
if (blob_buffer)
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index a41bcf5449b..15b310e907e 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -149,6 +149,7 @@ typedef struct st_mi_blob /* Info of record */
typedef struct st_mi_isam_pack {
ulong header_length;
uint ref_length;
+ uchar version;
} MI_PACK;
@@ -669,7 +670,9 @@ extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info,
int result);
extern my_bool _mi_memmap_file(MI_INFO *info);
extern void _mi_unmap_file(MI_INFO *info);
-extern uint save_pack_length(byte *block_buff,ulong length);
+extern uint save_pack_length(uint version, byte *block_buff, ulong length);
+extern uint read_pack_length(uint version, const uchar *buf, ulong *length);
+extern uint calc_pack_length(uint version, ulong length);
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite);
char *mi_state_info_read(char *ptr, MI_STATE_INFO *state);
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index c5db66ef209..f017e4d23ab 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -1675,6 +1675,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
HUFF_COUNTS *count,*end_count;
HUFF_TREE *tree;
MI_INFO *isam_file=mrg->file[0];
+ uint pack_version= (uint) isam_file->s->pack.version;
DBUG_ENTER("compress_isam_file");
if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
@@ -1702,23 +1703,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
huff_counts[i].tree->height+huff_counts[i].length_bits;
}
max_calc_length/=8;
- if (max_calc_length < 254)
- pack_ref_length=1;
- else if (max_calc_length <= 65535)
- pack_ref_length=3;
- else
- pack_ref_length=4;
+ pack_ref_length= calc_pack_length(pack_version, max_calc_length);
record_count=0;
- pack_blob_length=0;
- if (isam_file->s->base.blobs)
- {
- if (mrg->max_blob_length < 254)
- pack_blob_length=1;
- else if (mrg->max_blob_length <= 65535)
- pack_blob_length=3;
- else
- pack_blob_length=4;
- }
+ pack_blob_length= isam_file->s->base.blobs ?
+ calc_pack_length(pack_version, mrg->max_blob_length) : 0;
max_pack_length=pack_ref_length+pack_blob_length;
mrg_reset(mrg);
@@ -1874,9 +1862,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
flush_bits();
length=(ulong) (file_buffer.pos-record_pos)-max_pack_length;
- pack_length=save_pack_length(record_pos,length);
+ pack_length= save_pack_length(pack_version, record_pos, length);
if (pack_blob_length)
- pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length);
+ pack_length+= save_pack_length(pack_version, record_pos + pack_length,
+ tot_blob_length);
/* Correct file buffer if the header was smaller */
if (pack_length != max_pack_length)
diff --git a/mysql-test/include/mysqltest-x.inc b/mysql-test/include/mysqltest-x.inc
new file mode 100644
index 00000000000..dd1468aed07
--- /dev/null
+++ b/mysql-test/include/mysqltest-x.inc
@@ -0,0 +1,2 @@
+echo Output from mysqltest-x.inc;
+
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index bae66353825..9176a246835 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -166,7 +166,7 @@ sub spawn_impl ($$$$$$$$) {
{
if ( ! open(STDOUT,$log_file_open_mode,$output) )
{
- mtr_error("can't redirect STDOUT to \"$output\": $!");
+ mtr_child_error("can't redirect STDOUT to \"$output\": $!");
}
}
@@ -176,14 +176,14 @@ sub spawn_impl ($$$$$$$$) {
{
if ( ! open(STDERR,">&STDOUT") )
{
- mtr_error("can't dup STDOUT: $!");
+ mtr_child_error("can't dup STDOUT: $!");
}
}
else
{
if ( ! open(STDERR,$log_file_open_mode,$error) )
{
- mtr_error("can't redirect STDERR to \"$error\": $!");
+ mtr_child_error("can't redirect STDERR to \"$error\": $!");
}
}
}
@@ -192,13 +192,13 @@ sub spawn_impl ($$$$$$$$) {
{
if ( ! open(STDIN,"<",$input) )
{
- mtr_error("can't redirect STDIN to \"$input\": $!");
+ mtr_child_error("can't redirect STDIN to \"$input\": $!");
}
}
if ( ! exec($path,@$arg_list_t) )
{
- mtr_error("failed to execute \"$path\": $!");
+ mtr_child_error("failed to execute \"$path\": $!");
}
}
}
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 868653afaa4..9002f204602 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -19,6 +19,7 @@ sub mtr_print_header ();
sub mtr_report (@);
sub mtr_warning (@);
sub mtr_error (@);
+sub mtr_child_error (@);
sub mtr_debug (@);
@@ -74,7 +75,7 @@ sub mtr_show_failed_diff ($) {
sub mtr_report_test_name ($) {
my $tinfo= shift;
- printf "%-31s ", $tinfo->{'name'};
+ printf "%-30s ", $tinfo->{'name'};
}
sub mtr_report_test_skipped ($) {
@@ -122,13 +123,13 @@ sub mtr_report_test_failed ($) {
# we should write out into $::path_timefile when the error occurs.
if ( -f $::path_timefile )
{
- print "Errors are (from $::path_timefile) :\n";
+ print "\nErrors are (from $::path_timefile) :\n";
print mtr_fromfile($::path_timefile); # FIXME print_file() instead
print "\n(the last lines may be the most important ones)\n";
}
else
{
- print "Unexpected termination, probably when starting mysqld\n";
+ print "\nUnexpected termination, probably when starting mysqld\n";
}
}
@@ -286,6 +287,11 @@ sub mtr_error (@) {
mtr_exit(1);
}
+sub mtr_child_error (@) {
+ print STDERR "mysql-test-run: *** ERROR(child): ",join(" ", @_),"\n";
+ exit(1);
+}
+
sub mtr_debug (@) {
if ( $::opt_script_debug )
{
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 013b8d49967..cd182e8fc73 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -237,8 +237,10 @@ our $opt_ps_protocol;
our $opt_sleep_time_after_restart= 1;
our $opt_sleep_time_for_delete= 10;
-our $opt_testcase_timeout= 5; # 5 min max
-our $opt_suite_timeout= 120; # 2 hours max
+our $opt_testcase_timeout;
+our $opt_suite_timeout;
+my $default_testcase_timeout= 10; # 10 min max
+my $default_suite_timeout= 120; # 2 hours max
our $opt_socket;
@@ -256,6 +258,7 @@ our $opt_user;
our $opt_user_test;
our $opt_valgrind;
+our $opt_valgrind_mysqltest;
our $opt_valgrind_all;
our $opt_valgrind_options;
@@ -509,8 +512,9 @@ sub command_line_setup () {
# Coverage, profiling etc
'gcov' => \$opt_gcov,
'gprof' => \$opt_gprof,
- 'valgrind' => \$opt_valgrind,
- 'valgrind-all' => \$opt_valgrind_all,
+ 'valgrind:s' => \$opt_valgrind,
+ 'valgrind-mysqltest:s' => \$opt_valgrind_mysqltest,
+ 'valgrind-all:s' => \$opt_valgrind_all,
'valgrind-options=s' => \$opt_valgrind_options,
# Misc
@@ -688,29 +692,42 @@ sub command_line_setup () {
$opt_with_ndbcluster= 0;
}
- # FIXME
+ # The ":s" in the argument spec, means we have three different cases
+ #
+ # undefined option not set
+ # "" option set with no argument
+ # "somestring" option is name/path of valgrind executable
+
+ # Take executable path from any of them, if any
+ $opt_valgrind= $opt_valgrind_mysqltest if $opt_valgrind_mysqltest;
+ $opt_valgrind= $opt_valgrind_all if $opt_valgrind_all;
+
+ # If valgrind flag not defined, define if other valgrind flags are
+ unless ( defined $opt_valgrind )
+ {
+ $opt_valgrind= ""
+ if defined $opt_valgrind_mysqltest or defined $opt_valgrind_all;
+ }
- #if ( $opt_valgrind or $opt_valgrind_all )
- #{
- # VALGRIND=`which valgrind` # this will print an error if not found FIXME
- # Give good warning to the user and stop
- # if ( ! $VALGRIND )
- # {
- # print "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://valgrind.kde.org.\n"
- # exit 1
- # }
+ if ( ! $opt_testcase_timeout )
+ {
+ $opt_testcase_timeout= $default_testcase_timeout;
+ $opt_testcase_timeout*= 10 if defined $opt_valgrind;
+ }
+
+ if ( ! $opt_suite_timeout )
+ {
+ $opt_suite_timeout= $default_suite_timeout;
+ $opt_suite_timeout*= 4 if defined $opt_valgrind;
+ }
+
+ if ( defined $opt_valgrind )
+ {
+ $opt_sleep_time_after_restart= 10;
+ $opt_sleep_time_for_delete= 60;
# >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr
- # valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck"
- # VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16"
- # $opt_extra_mysqld_opt.= " --skip-safemalloc --skip-bdb";
- # SLEEP_TIME_AFTER_RESTART=10
- # $opt_sleep_time_for_delete= 60
- # $glob_use_running_server= ""
- # if ( "$1"= "--valgrind-all" )
- # {
- # VALGRIND="$VALGRIND -v --show-reachable=yes"
- # }
- #}
+ # valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck"
+ }
if ( ! $opt_user )
{
@@ -1703,7 +1720,7 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
- if ( $opt_valgrind )
+ if ( defined $opt_valgrind )
{
mtr_add_arg($args, "%s--skip-safemalloc", $prefix);
mtr_add_arg($args, "%s--skip-bdb", $prefix);
@@ -1928,29 +1945,9 @@ sub mysqld_start ($$$$) {
mtr_init_args(\$args);
- if ( $opt_valgrind )
+ if ( defined $opt_valgrind )
{
-
- mtr_add_arg($args, "--tool=memcheck");
- mtr_add_arg($args, "--alignment=8");
- mtr_add_arg($args, "--leak-check=yes");
- mtr_add_arg($args, "--num-callers=16");
-
- if ( $opt_valgrind_all )
- {
- mtr_add_arg($args, "-v");
- mtr_add_arg($args, "--show-reachable=yes");
- }
-
- if ( $opt_valgrind_options )
- {
- # FIXME split earlier and put into @glob_valgrind_*
- mtr_add_arg($args, split(' ', $opt_valgrind_options));
- }
-
- mtr_add_arg($args, $exe);
-
- $exe= $opt_valgrind;
+ valgrind_arguments($args, \$exe);
}
mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info);
@@ -2121,6 +2118,11 @@ sub run_mysqltest ($) {
mtr_init_args(\$args);
+ if ( defined $opt_valgrind_mysqltest )
+ {
+ valgrind_arguments($args, \$exe);
+ }
+
mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
mtr_add_arg($args, "--database=test");
@@ -2205,6 +2207,36 @@ sub run_mysqltest ($) {
return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,"");
}
+
+sub valgrind_arguments {
+ my $args= shift;
+ my $exe= shift;
+
+ mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
+ mtr_add_arg($args, "--alignment=8");
+ mtr_add_arg($args, "--leak-check=yes");
+ mtr_add_arg($args, "--num-callers=16");
+ mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
+ if -f "$glob_mysql_test_dir/valgrind.supp";
+
+ if ( defined $opt_valgrind_all )
+ {
+ mtr_add_arg($args, "-v");
+ mtr_add_arg($args, "--show-reachable=yes");
+ }
+
+ if ( $opt_valgrind_options )
+ {
+ # FIXME split earlier and put into @glob_valgrind_*
+ mtr_add_arg($args, split(' ', $opt_valgrind_options));
+ }
+
+ mtr_add_arg($args, $$exe);
+
+ $$exe= $opt_valgrind || "valgrind";
+}
+
+
##############################################################################
#
# Usage
@@ -2271,8 +2303,11 @@ Options for coverage, profiling etc
gcov FIXME
gprof FIXME
- valgrind FIXME
- valgrind-all FIXME
+ valgrind[=EXE] Run the "mysqltest" executable as well as the "mysqld"
+ server using valgrind, optionally specifying the
+ executable path/name
+ valgrind-mysqltest[=EXE] In addition, run the "mysqltest" executable with valgrind
+ valgrind-all[=EXE] Adds verbose flag, and --show-reachable to valgrind
valgrind-options=ARGS Extra options to give valgrind
Misc options
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index 09c606b5a04..0ebd4a3e409 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -102,3 +102,9 @@ select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.v " \\ 1 19 0 0 3.7619 NULL ENUM('"','""','"c','\'\0\\"','\'','\'\'','\'b','a\0\0\0b','a\0','a""""b','a\'\'\'\'b','abc','abc\'def\\hij"klm\0opq','a\\\\\\\\b','b\'','c"','d\\','The\ZEnd','\\','\\d','\\\\') NOT NULL
drop table t1;
+create table t1 (d double);
+insert into t1 values (100000);
+select * from t1 procedure analyse (1,1);
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+test.t1.d 100000 100000 6 6 0 0 100000 0 MEDIUMINT(6) UNSIGNED NOT NULL
+drop table t1;
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index edf30e7f6e4..68c86b80e60 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t2;
show tables;
Tables_in_mysql
columns_priv
@@ -65,3 +66,8 @@ show tables;
Tables_in_test
delete from mysql.user where user=_binary"test";
flush privileges;
+create table t1 (id integer not null auto_increment primary key);
+create temporary table t2(id integer not null auto_increment primary key);
+set @id := 1;
+delete from t1 where id like @id;
+drop table t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 95757fbd7dc..6edd4cbc48f 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -9,6 +9,8 @@ NULL
drop table if exists t1;
create table t1 (b char(0) not null);
create table if not exists t1 (b char(0) not null);
+Warnings:
+Note 1050 Table 't1' already exists
insert into t1 values (""),(null);
Warnings:
Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
@@ -232,9 +234,13 @@ create table t1 select x'4132';
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 1,2,3,4;
ERROR 21S01: Column count doesn't match value count at row 1
create table if not exists t1 select 1;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
1 2 3
1 2 3
@@ -243,9 +249,13 @@ select * from t1;
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 1,2,3,4;
ERROR 21S01: Column count doesn't match value count at row 1
create table if not exists t1 select 1;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
1 2 3
1 2 3
@@ -255,11 +265,15 @@ drop table t1;
create table t1 (a int not null, b int, primary key (a));
insert into t1 values (1,1);
create table if not exists t1 select 2;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
a b
1 1
0 2
create table if not exists t1 select 3 as 'a',4 as 'b';
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 3 as 'a',3 as 'b';
ERROR 23000: Duplicate entry '3' for key 1
select * from t1;
@@ -593,3 +607,17 @@ drop database mysqltest;
create table test.t1 like x;
ERROR 42000: Incorrect database name 'NULL'
drop table if exists test.t1;
+create database mysqltest;
+create database if not exists mysqltest character set latin2;
+Warnings:
+Note 1007 Can't create database 'mysqltest'; database exists
+show create database mysqltest;
+Database Create Database
+mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET latin1 */
+drop database mysqltest;
+use test;
+create table t1 (a int);
+create table if not exists t1 (a int);
+Warnings:
+Note 1050 Table 't1' already exists
+drop table t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 748361d3178..9f2d7eac700 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -955,6 +955,10 @@ char_length(a) length(a) a
2 4 ан
drop table t1;
set names utf8;
+select 'andre%' like 'andreñ%' escape 'ñ';
+'andre%' like 'andreñ%' escape 'ñ'
+1
+set names utf8;
select 'a\\' like 'a\\';
'a\\' like 'a\\'
1
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index a6c25fcd26c..d7a741827d5 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -469,6 +469,15 @@ select collation(group_concat(a,b)) from t1;
ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,IMPLICIT) for operation 'group_concat'
drop table t1;
drop table t2;
+CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp850);
+INSERT INTO t1 VALUES ('À');
+SELECT a FROM t1;
+a
+SELECT GROUP_CONCAT(a) FROM t1;
+GROUP_CONCAT(a)
+DROP TABLE t1;
CREATE TABLE t1 (id int);
SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL;
gc
@@ -551,3 +560,32 @@ DROP TABLE t1,t2;
select * from (select group_concat('c') from DUAL) t;
group_concat('c')
NULL
+create table t1 ( a int not null default 0);
+select * from (select group_concat(a) from t1) t2;
+group_concat(a)
+NULL
+select group_concat('x') UNION ALL select 1;
+group_concat('x')
+NULL
+1
+drop table t1;
+CREATE TABLE t1 (id int, a varchar(9));
+INSERT INTO t1 VALUES
+(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
+SELECT GROUP_CONCAT(a) FROM t1;
+GROUP_CONCAT(a)
+,,x,y,z,
+SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
+GROUP_CONCAT(a ORDER BY a)
+,,,x,y,z
+SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
+GROUP_CONCAT(a)
+,y
+,x
+z,
+SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
+GROUP_CONCAT(a ORDER BY a)
+,y
+,x
+,z
+DROP TABLE t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index a58432cb06e..bc658f9f7de 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -158,3 +158,10 @@ DROP TABLE t1;
select _cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin;
_cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin
1
+set names koi8r;
+select 'andre%' like 'andreÊ%' escape 'Ê';
+'andre%' like 'andreÊ%' escape 'Ê'
+1
+select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê';
+_cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'
+1
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index 80b15d1d3c8..b36902d7872 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -140,3 +140,8 @@ drop table t1;
select abs(-2) * -2;
abs(-2) * -2
-4
+create table t1 (i int);
+insert into t1 values (1);
+select rand(i) from t1;
+ERROR HY000: Incorrect arguments to RAND
+drop table t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 8287a042d60..4ad28091164 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -764,3 +764,12 @@ select date(left(f1+0,8)) from t1 group by 1;
date(left(f1+0,8))
2005-06-06
drop table t1;
+create table t1(f1 varchar(5) key);
+insert into t1 values (1),(2);
+select sql_buffer_result max(f1) is null from t1;
+max(f1) is null
+0
+select sql_buffer_result max(f1)+1 from t1;
+max(f1)+1
+3
+drop table t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 858daacffe9..c7aef8ed792 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1674,3 +1674,23 @@ select * from t1;
a
42
drop table t1;
+create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb;
+insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3);
+select * from t1 order by a,b,c,d;
+a b c d e
+1 1 a 1 1
+2 2 b 2 2
+3 3 ab 3 3
+explain select * from t1 order by a,b,c,d;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort
+drop table t1;
+create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
+insert into t1 values ('8', '6'), ('4', '7');
+select min(a) from t1;
+min(a)
+4
+select min(b) from t1 where a='8';
+min(b)
+6
+drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 2ac73fe7662..d4eb4e8b788 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -668,3 +668,13 @@ ERROR 42S02: Unknown table 't2' in field list
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
ERROR 42S02: Unknown table 't2' in field list
drop table t1,t2,t3;
+create table t1(f1 varchar(5) key);
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+select * from t1;
+f1
+2000
+2001
+2002
+drop table t1;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index b6265aac4a3..d5ae1a58e83 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -883,3 +883,136 @@ Warnings:
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
drop table t1, t2;
set group_concat_max_len=default;
+CREATE TABLE t1 (a int PRIMARY KEY, b int);
+CREATE TABLE t2 (a int PRIMARY KEY, b int);
+INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
+INSERT INTO t2 VALUES (3,0), (4,1), (6,4), (7,5);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b <= t1.a AND t1.a <= t1.b;
+a b a b
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a BETWEEN t2.b AND t1.b;
+a b a b
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT BETWEEN t2.b AND t1.b);
+a b a b
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b > t1.a OR t1.a > t1.b;
+a b a b
+2 1 NULL NULL
+3 2 3 0
+4 3 4 1
+6 5 6 4
+8 7 NULL NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT BETWEEN t2.b AND t1.b;
+a b a b
+2 1 NULL NULL
+3 2 3 0
+4 3 4 1
+6 5 6 4
+8 7 NULL NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a BETWEEN t2.b AND t1.b);
+a b a b
+2 1 NULL NULL
+3 2 3 0
+4 3 4 1
+6 5 6 4
+8 7 NULL NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t2.b > t1.a OR t1.a > t1.b;
+a b a b
+2 1 NULL NULL
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+8 7 NULL NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a AND t1.a BETWEEN t2.b AND t1.b);
+a b a b
+2 1 NULL NULL
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+8 7 NULL NULL
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a AND (t2.b > t1.a OR t1.a > t1.b);
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a OR t1.a BETWEEN t2.b AND t1.b);
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT IN(t2.a, t2.b));
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a != t1.b AND t1.a != t2.b;
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT IN(t1.b, t2.b);
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a IN(t1.b, t2.b));
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b OR (t1.a != t2.a AND t1.a != t2.b);
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b AND t1.a IN(t2.a, t2.b));
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b AND t1.a != t1.b AND t1.a != t2.b;
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b OR t1.a IN(t1.b, t2.b));
+a b a b
+3 2 3 0
+4 3 4 1
+6 5 6 4
+7 8 7 5
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 9175bdc7250..ae44233aab6 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -179,7 +179,6 @@ source database
echo message echo message
mysqltest: At line 1: Empty variable
-mysqltest: At line 1: command "';' 2> /dev/null" failed
mysqltest: At line 1: Missing argument in exec
MySQL
"MySQL"
@@ -301,7 +300,6 @@ mysqltest: At line 1: First argument to dec must be a variable (start with $)
mysqltest: At line 1: End of line junk detected: "1000"
mysqltest: At line 1: Missing arguments to system, nothing to do!
mysqltest: At line 1: Missing arguments to system, nothing to do!
-mysqltest: At line 1: system command 'NonExistsinfComamdn 2> /dev/null' failed
test
test2
test3
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
index 5a1a82832fa..c61270c02a8 100644
--- a/mysql-test/r/ndb_autodiscover.result
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -99,6 +99,8 @@ id int not null primary key,
id2 int not null,
name char(20)
) engine=ndb;
+Warnings:
+Note 1050 Table 't3' already exists
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 7178895cf80..fef990297d9 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -516,3 +516,28 @@ a b c count
1 NULL NULL 2
NULL NULL NULL 2
DROP TABLE t1;
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+a a + 1 COUNT(*)
+1 2 1
+2 3 1
+NULL NULL 2
+SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+a LENGTH(a) COUNT(*)
+1 1 1
+2 1 1
+NULL NULL 2
+DROP TABLE t1;
+create table t1 ( a varchar(9), b int );
+insert into t1 values('a',1),(null,2);
+select a, max(b) from t1 group by a with rollup;
+a max(b)
+NULL 2
+a 1
+NULL 2
+select distinct a, max(b) from t1 group by a with rollup;
+a max(b)
+NULL 2
+a 1
+drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index c17015df757..f5bf3ffa96d 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -334,39 +334,37 @@ create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4);
set @precision=10000000000;
select rand(),
-cast(rand(10)*@precision as unsigned integer),
-cast(rand(a)*@precision as unsigned integer) from t1;
-rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer)
-- 6570515219 -
-- 1282061302 -
-- 6698761160 -
-- 9647622201 -
+cast(rand(10)*@precision as unsigned integer) from t1;
+rand() cast(rand(10)*@precision as unsigned integer)
+- 6570515219
+- 1282061302
+- 6698761160
+- 9647622201
prepare stmt from
"select rand(),
cast(rand(10)*@precision as unsigned integer),
- cast(rand(a)*@precision as unsigned integer),
cast(rand(?)*@precision as unsigned integer) from t1";
set @var=1;
execute stmt using @var;
-rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
-- 6570515219 - 4054035371
-- 1282061302 - 8716141803
-- 6698761160 - 1418603212
-- 9647622201 - 944590960
+rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
+- 6570515219 -
+- 1282061302 -
+- 6698761160 -
+- 9647622201 -
set @var=2;
execute stmt using @var;
-rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
-- 6570515219 1559528654 6555866465
-- 1282061302 6238114970 1223466192
-- 6698761160 6511989195 6449731873
-- 9647622201 3845601374 8578261098
+rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
+- 6570515219 6555866465
+- 1282061302 1223466192
+- 6698761160 6449731873
+- 9647622201 8578261098
set @var=3;
execute stmt using @var;
-rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
-- 6570515219 1559528654 9057697559
-- 1282061302 6238114970 3730790581
-- 6698761160 6511989195 1480860534
-- 9647622201 3845601374 6211931236
+rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
+- 6570515219 9057697559
+- 1282061302 3730790581
+- 6698761160 1480860534
+- 9647622201 6211931236
drop table t1;
deallocate prepare stmt;
create database mysqltest1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index c4ccdf9eb34..49e858eca56 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -470,12 +470,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 14 N 1 31 8
+def Extra 253 255 14 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
SET @arg00=1 ;
@@ -486,12 +486,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 5 Y 0 31 8
-def possible_keys 252 4096 7 Y 0 31 8
+def possible_keys 253 4096 7 Y 0 31 8
def key 253 64 7 Y 0 31 8
def key_len 8 3 1 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 27 N 1 31 8
+def Extra 253 255 27 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort
drop table if exists t2;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 6ef61b05577..4b655cfb854 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
drop table if exists t2 ;
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 96047ac3182..4d2a62887d6 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index bff4b6a5ad8..a4919b664c4 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1154,12 +1154,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 5ed6c10a47c..f98cc1b3cdf 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1196,12 +1196,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
@@ -4210,12 +4210,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index ef74e13a41d..acd7f45de95 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 3
test_sequence
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index e7ffbb7c6ef..27a1ea0925d 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/rpl_multi_delete2.result b/mysql-test/r/rpl_multi_delete2.result
index c6c088111fc..73db9f62eb4 100644
--- a/mysql-test/r/rpl_multi_delete2.result
+++ b/mysql-test/r/rpl_multi_delete2.result
@@ -4,6 +4,26 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+set sql_log_bin=0;
+create database mysqltest_from;
+set sql_log_bin=1;
+create database mysqltest_to;
+use mysqltest_from;
+drop table if exists a;
+CREATE TABLE a (i INT);
+INSERT INTO a VALUES(1);
+DELETE alias FROM a alias WHERE alias.i=1;
+SELECT * FROM a;
+i
+insert into a values(2),(3);
+delete a alias FROM a alias where alias.i=2;
+select * from a;
+i
+3
+use mysqltest_to;
+select * from a;
+i
+3
create table t1 (a int);
create table t2 (a int);
insert into t1 values (1);
@@ -15,7 +35,10 @@ select * from t2;
a
1
select * from t1;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'mysqltest_to.t1' doesn't exist
select * from t2;
-ERROR 42S02: Table 'test.t2' doesn't exist
-drop table t1,t2;
+ERROR 42S02: Table 'mysqltest_to.t2' doesn't exist
+set sql_log_bin=0;
+drop database mysqltest_from;
+set sql_log_bin=1;
+drop database mysqltest_to;
diff --git a/mysql-test/r/rpl_slave_status.result b/mysql-test/r/rpl_slave_status.result
index 8badbab85ff..2146132aeb0 100644
--- a/mysql-test/r/rpl_slave_status.result
+++ b/mysql-test/r/rpl_slave_status.result
@@ -19,7 +19,7 @@ flush privileges;
stop slave;
start slave;
show slave status;
-Slave_IO_State Connecting to master
+Slave_IO_State #
Master_Host 127.0.0.1
Master_User rpl
Master_Port MASTER_MYPORT
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index f08fe6ddd0f..0b6bc48c350 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -23,6 +23,8 @@ a b
6 g
create TEMPORARY TABLE t2 engine=heap select * from t1;
create TEMPORARY TABLE IF NOT EXISTS t2 (a int) engine=heap;
+Warnings:
+Note 1050 Table 't2' already exists
CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
ERROR 42S01: Table 't1' already exists
ALTER TABLE t1 RENAME t2;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index e97b309547a..b9c05bc388c 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -63,9 +63,11 @@ show count(*) warnings;
1
create table t1(id int);
create table if not exists t1(id int);
+Warnings:
+Note 1050 Table 't1' already exists
select @@warning_count;
@@warning_count
-0
+1
drop table t1;
create table t1(a tinyint, b int not null, c date, d char(5));
load data infile '../../std_data/warnings_loaddata.dat' into table t1 fields terminated by ',';
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index e7fbf09c19a..e38e43381bc 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -48,4 +48,13 @@ insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),(
select * from t1 procedure analyse();
drop table t1;
+#
+# Bug#10716 - Procedure Analyse results in wrong values for optimal field type
+#
+
+create table t1 (d double);
+insert into t1 values (100000);
+select * from t1 procedure analyse (1,1);
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index 1a6dca5b69e..ff15d74e5ac 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -6,6 +6,10 @@
# This test makes no sense with the embedded server
--source include/not_embedded.inc
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
#connect (con1,localhost,root,,"");
#show tables;
connect (con1,localhost,root,,mysql);
@@ -77,4 +81,18 @@ show tables;
delete from mysql.user where user=_binary"test";
flush privileges;
+#
+# Bug#12517: Clear user variables and replication events before
+# closing temp tables in thread cleanup.
+connect (con2,localhost,root,,test);
+connection con2;
+create table t1 (id integer not null auto_increment primary key);
+create temporary table t2(id integer not null auto_increment primary key);
+set @id := 1;
+delete from t1 where id like @id;
+disconnect con2;
+--sleep 5
+connection default;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 9ea810aaf7d..73184853d1a 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -513,4 +513,17 @@ create table test.t1 like x;
drop table if exists test.t1;
--enable_warnings
+#
+# Bug #6008 MySQL does not create warnings when
+# creating database and using IF NOT EXISTS
+#
+create database mysqltest;
+create database if not exists mysqltest character set latin2;
+show create database mysqltest;
+drop database mysqltest;
+use test;
+create table t1 (a int);
+create table if not exists t1 (a int);
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index e6342777839..0cdda648899 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -810,6 +810,12 @@ alter table t1 modify a char(2) character set utf8;
select char_length(a), length(a), a from t1 order by a;
drop table t1;
+#
+# Bugs#12611
+# ESCAPE + LIKE do not work when the escape char is a multibyte one
+#
+set names utf8;
+select 'andre%' like 'andreñ%' escape 'ñ';
#
# Bugs#11754: SET NAMES utf8 followed by SELECT "A\\" LIKE "A\\" returns 0
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index 827a2813718..eb1cbc3d667 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -282,6 +282,16 @@ drop table t1;
drop table t2;
#
+# Bug #12829
+# Cannot convert the charset of a GROUP_CONCAT result
+#
+CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp850);
+INSERT INTO t1 VALUES ('À');
+SELECT a FROM t1;
+SELECT GROUP_CONCAT(a) FROM t1;
+DROP TABLE t1;
+
+#
# bug #7769: group_concat returning null is checked in having
#
CREATE TABLE t1 (id int);
@@ -348,4 +358,28 @@ DROP TABLE t1,t2;
#
select * from (select group_concat('c') from DUAL) t;
+#
+# Bug #12859 group_concat in subquery cause incorrect not null
+#
+create table t1 ( a int not null default 0);
+select * from (select group_concat(a) from t1) t2;
+select group_concat('x') UNION ALL select 1;
+drop table t1;
+
+#
+# Bug #12863 : missing separators after first empty cancatanated elements
+#
+
+CREATE TABLE t1 (id int, a varchar(9));
+INSERT INTO t1 VALUES
+ (2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
+
+SELECT GROUP_CONCAT(a) FROM t1;
+SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
+
+SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
+SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
+
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index 684d7032038..4e1183afeff 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -96,4 +96,21 @@ DROP TABLE t1;
#
select _cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin;
+#
+# Check 8bit escape character
+#
+set names koi8r;
+select 'andre%' like 'andreÊ%' escape 'Ê';
+
+# Check 8bit escape character with charset conversion:
+# For "a LIKE b ESCAPE c" expressions,
+# escape character is converted into the operation character set,
+# which is result of aggregation of character sets of "a" and "b".
+# "c" itself doesn't take part in aggregation, because its collation
+# doesn't matter, escape character is always compared binary.
+# In the example below, escape character is converted from koi8r into cp1251:
+#
+select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê';
+
+#
# End of 4.1 tests
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index ebbc594952c..c75454a96d4 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -77,4 +77,13 @@ drop table t1;
#
select abs(-2) * -2;
+#
+# Bug #6172 RAND(a) should only accept constant values as arguments
+#
+create table t1 (i int);
+insert into t1 values (1);
+--error 1210
+select rand(i) from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 815da66c717..f14fab2d30e 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -600,4 +600,14 @@ insert into t1 values('2005-06-06');
select date(left(f1+0,8)) from t1 group by 1;
drop table t1;
+#
+# BUG#12695: Item_func_isnull::update_used_tables
+# did not update const_item_cache
+#
+create table t1(f1 varchar(5) key);
+insert into t1 values (1),(2);
+select sql_buffer_result max(f1) is null from t1;
+select sql_buffer_result max(f1)+1 from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 33432209e65..b966ea5b281 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1220,4 +1220,23 @@ insert into t1 values (42);
select * from t1;
drop table t1;
+#
+# Bug #13025 Server crash during filesort
+#
+
+create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb;
+insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3);
+select * from t1 order by a,b,c,d;
+explain select * from t1 order by a,b,c,d;
+drop table t1;
+
+#
+# BUG#11039,#13218 Wrong key length in min()
+#
+
+create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
+insert into t1 values ('8', '6'), ('4', '7');
+select min(a) from t1;
+select min(b) from t1 where a='8';
+drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 14853b38db2..6fcdef6ab03 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -204,4 +204,14 @@ insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b;
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
drop table t1,t2,t3;
+#
+# Bug #12695 Item_func_isnull::update_used_tables() did not update
+# const_item_cache
+create table t1(f1 varchar(5) key);
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+select * from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index fa2dd93c9ba..05cd2fb152e 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -625,4 +625,50 @@ select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
drop table t1, t2;
set group_concat_max_len=default;
+#
+# Test for bugs
+# #12101: erroneously applied outer join elimination in case of WHERE NOT BETWEEN
+# #12102: erroneously missing outer join elimination in case of WHERE IN/IF
+#
+
+CREATE TABLE t1 (a int PRIMARY KEY, b int);
+CREATE TABLE t2 (a int PRIMARY KEY, b int);
+
+INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
+INSERT INTO t2 VALUES (3,0), (4,1), (6,4), (7,5);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b <= t1.a AND t1.a <= t1.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a BETWEEN t2.b AND t1.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT BETWEEN t2.b AND t1.b);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b > t1.a OR t1.a > t1.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT BETWEEN t2.b AND t1.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a BETWEEN t2.b AND t1.b);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t2.b > t1.a OR t1.a > t1.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a AND t1.a BETWEEN t2.b AND t1.b);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a AND (t2.b > t1.a OR t1.a > t1.b);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a OR t1.a BETWEEN t2.b AND t1.b);
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT IN(t2.a, t2.b));
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a != t1.b AND t1.a != t2.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT IN(t1.b, t2.b);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a IN(t1.b, t2.b));
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b OR (t1.a != t2.a AND t1.a != t2.b);
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b AND t1.a IN(t2.a, t2.b));
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b AND t1.a != t1.b AND t1.a != t2.b;
+SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b OR t1.a IN(t1.b, t2.b));
+
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
+
+DROP TABLE t1,t2;
+
# End of 4.1 tests
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index bfb1919e75c..4d3bcc037d1 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -358,8 +358,11 @@ select 3 from t1 ;
# Missing delimiter
# The comment will be "sucked into" the sleep command since
# delimiter is missing until after "show status"
+--system echo "sleep 4" > var/log/mysqltest.sql
+--system echo "# A comment" >> var/log/mysqltest.sql
+--system echo "show status;" >> var/log/mysqltest.sql
--error 1
---exec echo -e "sleep 4\n # A comment\nshow status;" | $MYSQL_TEST 2>&1
+--exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1
#
# Extra delimiter
@@ -423,8 +426,9 @@ echo ;
# ----------------------------------------------------------------------------
# Illegal use of exec
---error 1
---exec echo "--exec ';' 2> /dev/null" | $MYSQL_TEST 2>&1
+# Disabled, some shells prints the failed command regardless of pipes
+#--error 1
+#--exec echo "--exec ';' 2> /dev/null" | $MYSQL_TEST 2>&1
--error 1
--exec echo "--exec " | $MYSQL_TEST 2>&1
@@ -588,7 +592,7 @@ while ($num)
--source var/tmp/sourced1.sql
dec $num;
}
---enable_abort_on_error;
+--enable_abort_on_error
--enable_query_log
# ----------------------------------------------------------------------------
@@ -671,8 +675,9 @@ system echo "hej" > /dev/null;
--exec echo "system;" | $MYSQL_TEST 2>&1
--error 1
--exec echo "system $NONEXISTSINFVAREABLI;" | $MYSQL_TEST 2>&1
---error 1
---exec echo "system NonExistsinfComamdn 2> /dev/null;" | $MYSQL_TEST 2>&1
+# Disabled, some shells prints the failed command regardless of pipes
+#--error 1
+#--exec echo "system NonExistsinfComamdn 2> /dev/null;" | $MYSQL_TEST 2>&1
--disable_abort_on_error
system NonExistsinfComamdn;
@@ -722,12 +727,21 @@ while ($i)
--exec echo "end;" | $MYSQL_TEST 2>&1
--error 1
--exec echo "{;" | $MYSQL_TEST 2>&1
+
+--system echo "while (0)" > var/log/mysqltest.sql
+--system echo "echo hej;" >> var/log/mysqltest.sql
--error 1
---exec echo -e "while (0)\necho hej;" | $MYSQL_TEST 2>&1
+--exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1
+
+--system echo "while (0)" > var/log/mysqltest.sql
+--system echo "{echo hej;" >> var/log/mysqltest.sql
--error 1
---exec echo -e "while (0)\n{echo hej;" | $MYSQL_TEST 2>&1
+--exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1
+
+--system echo "while (0){" > var/log/mysqltest.sql
+--system echo "echo hej;" >> var/log/mysqltest.sql
--error 1
---exec echo -e "while (0){\n echo hej;" | $MYSQL_TEST 2>&1
+--exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1
# ----------------------------------------------------------------------------
# Test error messages returned from comments starting with a command
@@ -792,6 +806,19 @@ select "a" as col1, "c" as col2;
--error 1
--exec echo "save_master_pos; sync_with_master a;" | $MYSQL_TEST 2>&1
+
+# ----------------------------------------------------------------------------
+# Test mysqltest arguments
+# ----------------------------------------------------------------------------
+
+# -x <file_name>, use the file specified after -x as the test file
+#--exec $MYSQL_TEST < $MYSQL_TEST_DIR/include/mysqltest-x.inc 2>&1
+#--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/include/mysqltest-x.inc 2>&1
+#--exec $MYSQL_TEST --result_file=$MYSQL_TEST_DIR/include/mysqltest-x.inc 2>&1
+#--error 1
+#--exec $MYSQL_TEST -x non_existing_file.inc 2>&1
+
+
# ----------------------------------------------------------------------------
# TODO Test queries, especially their errormessages... so it's easy to debug
# new scripts and diagnose errors
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index c9a16b897c6..4f9790b0de6 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -250,4 +250,26 @@ SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
DROP TABLE t1;
+#
+# Bug #11885: derived table specified by a subquery with
+# ROLLUP over expressions on not nullable group by attributes
+#
+
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+
+SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+
+DROP TABLE t1;
+
+#
+# Bug #12887 Distinct is not always applied after rollup
+#
+create table t1 ( a varchar(9), b int );
+insert into t1 values('a',1),(null,2);
+select a, max(b) from t1 group by a with rollup;
+select distinct a, max(b) from t1 group by a with rollup;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 3698ab54ec1..3f398a91834 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -20,22 +20,22 @@ connect (con4,localhost,ssl_user4,,);
connection con1;
select * from t1;
---error 1044;
+--error 1044
delete from t1;
connection con2;
select * from t1;
---error 1044;
+--error 1044
delete from t1;
connection con3;
select * from t1;
---error 1044;
+--error 1044
delete from t1;
connection con4;
select * from t1;
---error 1044;
+--error 1044
delete from t1;
connection default;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 5a2e469fbc4..c4cb0056763 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -368,12 +368,10 @@ insert into t1 (a) values (1), (2), (3), (4);
set @precision=10000000000;
--replace_column 1 - 3 -
select rand(),
- cast(rand(10)*@precision as unsigned integer),
- cast(rand(a)*@precision as unsigned integer) from t1;
+ cast(rand(10)*@precision as unsigned integer) from t1;
prepare stmt from
"select rand(),
cast(rand(10)*@precision as unsigned integer),
- cast(rand(a)*@precision as unsigned integer),
cast(rand(?)*@precision as unsigned integer) from t1";
set @var=1;
--replace_column 1 - 3 -
diff --git a/mysql-test/t/rpl_multi_delete2-slave.opt b/mysql-test/t/rpl_multi_delete2-slave.opt
index b828d03fafb..0febb2891b1 100644
--- a/mysql-test/t/rpl_multi_delete2-slave.opt
+++ b/mysql-test/t/rpl_multi_delete2-slave.opt
@@ -1 +1 @@
---replicate-wild-ignore-table=test.%
+"--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a
diff --git a/mysql-test/t/rpl_multi_delete2.test b/mysql-test/t/rpl_multi_delete2.test
index 62d95a3a90f..c50311de363 100644
--- a/mysql-test/t/rpl_multi_delete2.test
+++ b/mysql-test/t/rpl_multi_delete2.test
@@ -1,4 +1,41 @@
+#multi delete replication bugs
+
+
source include/master-slave.inc;
+
+#BUG#11139 - improper wild-table and table rules
+#checking for multi deletes with an alias
+
+connection master;
+set sql_log_bin=0;
+create database mysqltest_from;
+set sql_log_bin=1;
+
+connection slave;
+create database mysqltest_to;
+
+
+connection master;
+use mysqltest_from;
+--disable_warnings
+drop table if exists a;
+--enable_warnings
+CREATE TABLE a (i INT);
+INSERT INTO a VALUES(1);
+DELETE alias FROM a alias WHERE alias.i=1;
+SELECT * FROM a;
+insert into a values(2),(3);
+delete a alias FROM a alias where alias.i=2;
+select * from a;
+save_master_pos;
+connection slave;
+
+use mysqltest_to;
+sync_with_master;
+select * from a;
+
+# BUG#3461
+connection master;
create table t1 (a int);
create table t2 (a int);
@@ -19,7 +56,13 @@ select * from t1;
error 1146;
select * from t2;
+# cleanup
connection master;
-drop table t1,t2;
+set sql_log_bin=0;
+drop database mysqltest_from;
+set sql_log_bin=1;
+connection slave;
+drop database mysqltest_to;
# End of 4.1 tests
+
diff --git a/mysql-test/t/rpl_slave_status.test b/mysql-test/t/rpl_slave_status.test
index 2c5bd2bffb0..67d3816f443 100644
--- a/mysql-test/t/rpl_slave_status.test
+++ b/mysql-test/t/rpl_slave_status.test
@@ -23,7 +23,9 @@ connection slave;
stop slave;
start slave;
--replace_result $MASTER_MYPORT MASTER_MYPORT
---replace_column 7 # 8 # 9 # 22 # 23 #
+# Column 1 is replaced, since the output can be either
+# "Connecting to master" or "Waiting for master update"
+--replace_column 1 # 7 # 8 # 9 # 22 # 23 #
--vertical_results
show slave status;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index f14af44dbb9..ca683f16415 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -632,12 +632,13 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
keycache->blocks_changed= 0;
}
- DBUG_PRINT("status",
- ("used: %d changed: %d w_requests: %ld \
-writes: %ld r_requests: %ld reads: %ld",
- keycache->blocks_used, keycache->global_blocks_changed,
- keycache->global_cache_w_requests, keycache->global_cache_write,
- keycache->global_cache_r_requests, keycache->global_cache_read));
+ DBUG_PRINT("status", ("used: %d changed: %d w_requests: %lu "
+ "writes: %lu r_requests: %lu reads: %lu",
+ keycache->blocks_used, keycache->global_blocks_changed,
+ (ulong) keycache->global_cache_w_requests,
+ (ulong) keycache->global_cache_write,
+ (ulong) keycache->global_cache_r_requests,
+ (ulong) keycache->global_cache_read));
if (cleanup)
{
diff --git a/ndb/include/kernel/signaldata/BackupImpl.hpp b/ndb/include/kernel/signaldata/BackupImpl.hpp
index 2032e2347b5..298440ad377 100644
--- a/ndb/include/kernel/signaldata/BackupImpl.hpp
+++ b/ndb/include/kernel/signaldata/BackupImpl.hpp
@@ -33,7 +33,7 @@ class DefineBackupReq {
friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size);
+ STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
private:
/**
@@ -60,6 +60,13 @@ private:
* Length of backup data
*/
Uint32 backupDataLen;
+
+ /**
+ * Backup flags
+ */
+ /* & 0x3 - waitCompleted
+ */
+ Uint32 flags;
};
class DefineBackupRef {
diff --git a/ndb/include/kernel/signaldata/BackupSignalData.hpp b/ndb/include/kernel/signaldata/BackupSignalData.hpp
index b38dd8d14b2..e1b8c6203a1 100644
--- a/ndb/include/kernel/signaldata/BackupSignalData.hpp
+++ b/ndb/include/kernel/signaldata/BackupSignalData.hpp
@@ -36,11 +36,14 @@ class BackupReq {
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 2 );
+ STATIC_CONST( SignalLength = 3 );
private:
Uint32 senderData;
Uint32 backupDataLen;
+ /* & 0x3 - waitCompleted
+ */
+ Uint32 flags;
};
class BackupData {
diff --git a/ndb/include/kernel/signaldata/NFCompleteRep.hpp b/ndb/include/kernel/signaldata/NFCompleteRep.hpp
index c8bde705a86..764da85b163 100644
--- a/ndb/include/kernel/signaldata/NFCompleteRep.hpp
+++ b/ndb/include/kernel/signaldata/NFCompleteRep.hpp
@@ -30,28 +30,12 @@
* from the failed NDB node
*
*/
-class NFCompleteRep {
- /**
- * Sender(s)
- */
- friend class Dbdict;
- friend class Dblqh;
- friend class Dbtc;
- friend class Qmgr;
-
- /**
- * Sender/Reciver
- */
- friend class Dbdih;
- friend class ClusterMgr;
+struct NFCompleteRep {
friend bool printNF_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16);
-public:
STATIC_CONST( SignalLength = 5 );
-private:
-
/**
* Which block has completed...
*
diff --git a/ndb/include/kernel/signaldata/NodeFailRep.hpp b/ndb/include/kernel/signaldata/NodeFailRep.hpp
index 060acd6a3e2..fe57ba1a712 100644
--- a/ndb/include/kernel/signaldata/NodeFailRep.hpp
+++ b/ndb/include/kernel/signaldata/NodeFailRep.hpp
@@ -24,34 +24,8 @@
* This signals is sent by Qmgr to NdbCntr
* and then from NdbCntr sent to: dih, dict, lqh, tc & API
*/
-class NodeFailRep {
- /**
- * Sender(s)
- */
- friend class Qmgr;
-
- /**
- * Sender(s) / Reciver(s)
- */
- friend class Ndbcntr;
- friend class Dbdict;
-
- /**
- * Reciver(s)
- */
- friend class Dbdih;
- friend class Dblqh;
- friend class Dbtc;
- friend class ClusterMgr;
- friend class Trix;
- friend class Backup;
- friend class Suma;
- friend class Grep;
- friend class SafeCounterManager;
-
-public:
+struct NodeFailRep {
STATIC_CONST( SignalLength = 3 + NodeBitmask::Size );
-private:
Uint32 failNo;
diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp
index f9d3a6faa64..b0cfbc1540c 100644
--- a/ndb/include/kernel/signaldata/SignalData.hpp
+++ b/ndb/include/kernel/signaldata/SignalData.hpp
@@ -215,5 +215,6 @@ GSN_PRINT_SIGNATURE(printSCAN_FRAGREQ);
GSN_PRINT_SIGNATURE(printCONTINUEB_NDBFS);
GSN_PRINT_SIGNATURE(printCONTINUEB_DBDIH);
+GSN_PRINT_SIGNATURE(printSTART_FRAG_REQ);
#endif
diff --git a/ndb/include/kernel/signaldata/StartFragReq.hpp b/ndb/include/kernel/signaldata/StartFragReq.hpp
index ec05c1ee366..ab17a147195 100644
--- a/ndb/include/kernel/signaldata/StartFragReq.hpp
+++ b/ndb/include/kernel/signaldata/StartFragReq.hpp
@@ -32,6 +32,8 @@ class StartFragReq {
public:
STATIC_CONST( SignalLength = 19 );
+ friend bool printSTART_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16);
+
private:
Uint32 userPtr;
Uint32 userRef;
diff --git a/ndb/include/util/Parser.hpp b/ndb/include/util/Parser.hpp
index c117498e1ba..3baf7601a6c 100644
--- a/ndb/include/util/Parser.hpp
+++ b/ndb/include/util/Parser.hpp
@@ -285,7 +285,7 @@ template<class T>
inline
void
Parser<T>::setBreakOnInvalidArg(bool v){
- impl->m_breakOnInvalidArg;
+ impl->m_breakOnInvalidArg = v;
}
#endif
diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h
index ca4ca5eac83..462d9996582 100644
--- a/ndb/include/util/ndb_opts.h
+++ b/ndb/include/util/ndb_opts.h
@@ -30,8 +30,14 @@ my_bool opt_ndb_optimized_node_selection
bool opt_endinfo= 0;
my_bool opt_ndb_shm;
+my_bool opt_core;
#define OPT_NDB_CONNECTSTRING 'c'
+#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
+#define OPT_WANT_CORE_DEFAULT 1
+#else
+#define OPT_WANT_CORE_DEFAULT 0
+#endif
#define NDB_STD_OPTS_COMMON \
{ "usage", '?', "Display this help and exit.", \
@@ -57,7 +63,10 @@ my_bool opt_ndb_shm;
GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},\
{ "connect-string", OPT_NDB_CONNECTSTRING, "same as --ndb-connectstring",\
(gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0,\
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ { "core-file", OPT_WANT_CORE, "Write core on errors.",\
+ (gptr*) &opt_core, (gptr*) &opt_core, 0,\
+ GET_BOOL, NO_ARG, OPT_WANT_CORE_DEFAULT, 0, 0, 0, 0, 0}
#ifndef DBUG_OFF
#define NDB_STD_OPTS(prog_name) \
@@ -80,6 +89,7 @@ enum ndb_std_options {
OPT_NDB_SHM= 256,
OPT_NDB_SHM_SIGNUM,
OPT_NDB_OPTIMIZED_NODE_SELECTION,
+ OPT_WANT_CORE,
NDB_STD_OPTIONS_LAST /* should always be last in this enum */
};
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index 97945394690..f7cef644c64 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -585,11 +585,13 @@ EventLogger::getText(char * m_text, size_t m_text_len,
BaseString::snprintf(m_text,
m_text_len,
"%sTable ID = %u, fragment ID = %u has completed LCP "
- "on Node %u",
+ "on Node %u maxGciStarted: %d maxGciCompleted: %d",
theNodeId,
theData[2],
theData[3],
- theData[1]);
+ theData[1],
+ theData[4],
+ theData[5]);
break;
case EventReport::TransReportCounters:
// -------------------------------------------------------------------
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index a4cee38e06f..bd1dff074f9 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -195,6 +195,7 @@ SignalDataPrintFunctions[] = {
,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ }
,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF }
,{ GSN_SCAN_FRAGREQ, printSCAN_FRAGREQ }
+ ,{ GSN_START_FRAGREQ, printSTART_FRAG_REQ }
,{ 0, 0 }
};
diff --git a/ndb/src/common/debugger/signaldata/StartRec.cpp b/ndb/src/common/debugger/signaldata/StartRec.cpp
index 482e3cb0728..54830e533c5 100644
--- a/ndb/src/common/debugger/signaldata/StartRec.cpp
+++ b/ndb/src/common/debugger/signaldata/StartRec.cpp
@@ -17,6 +17,7 @@
#include <RefConvert.hpp>
#include <signaldata/StartRec.hpp>
+#include <signaldata/StartFragReq.hpp>
bool
printSTART_REC_REQ(FILE * output,
@@ -50,3 +51,27 @@ printSTART_REC_CONF(FILE * output,
return true;
}
+
+bool
+printSTART_FRAG_REQ(FILE * output,
+ const Uint32 * theData,
+ Uint32 len,
+ Uint16 recBlockNo)
+{
+ StartFragReq* sig = (StartFragReq*)theData;
+
+ fprintf(output, " table: %d frag: %d lcpId: %d lcpNo: %d #nodes: %d \n",
+ sig->tableId, sig->fragId, sig->lcpId, sig->lcpNo,
+ sig->noOfLogNodes);
+
+ for(Uint32 i = 0; i<sig->noOfLogNodes; i++)
+ {
+ fprintf(output, " (node: %d startGci: %d lastGci: %d)",
+ sig->lqhLogNode[i],
+ sig->startGci[i],
+ sig->lastGci[i]);
+ }
+
+ fprintf(output, "\n");
+ return true;
+}
diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c
index 55ebc4c8111..48d00956ec2 100644
--- a/ndb/src/common/portlib/NdbThread.c
+++ b/ndb/src/common/portlib/NdbThread.c
@@ -53,6 +53,16 @@ ndb_thread_wrapper(void* _ss){
}
#endif
{
+ /**
+ * Block all signals to thread by default
+ * let them go to main process instead
+ */
+ sigset_t mask;
+ sigfillset(&mask);
+ pthread_sigmask(SIG_BLOCK, &mask, 0);
+ }
+
+ {
void *ret;
struct NdbThread * ss = (struct NdbThread *)_ss;
ret= (* ss->func)(ss->object);
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 5193d3eae9d..791df915d66 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -6,7 +6,7 @@ Next DBTUP 4013
Next DBLQH 5042
Next DBDICT 6006
Next DBDIH 7174
-Next DBTC 8035
+Next DBTC 8037
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
@@ -406,8 +406,11 @@ Drop Table/Index:
4001: Crash on REL_TABMEMREQ in TUP
4002: Crash on DROP_TABFILEREQ in TUP
4003: Fail next trigger create in TUP
+4004: Fail next trigger drop in TUP
8033: Fail next trigger create in TC
8034: Fail next index create in TC
+8035: Fail next trigger drop in TC
+8036: Fail next index drop in TC
System Restart:
---------------
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index 3334d69ae89..ec5c7a5d588 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -69,6 +69,9 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
+#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
+#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
+
void
Backup::execSTTOR(Signal* signal)
{
@@ -852,23 +855,24 @@ Backup::execBACKUP_REQ(Signal* signal)
const Uint32 senderData = req->senderData;
const BlockReference senderRef = signal->senderBlockRef();
const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
-
+ const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
+
if(getOwnNodeId() != getMasterNodeId()) {
jam();
- sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
+ sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
return;
}//if
if (m_diskless)
{
- sendBackupRef(senderRef, signal, senderData,
+ sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::CannotBackupDiskless);
return;
}
if(dataLen32 != 0) {
jam();
- sendBackupRef(senderRef, signal, senderData,
+ sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::BackupDefinitionNotImplemented);
return;
}//if
@@ -883,7 +887,7 @@ Backup::execBACKUP_REQ(Signal* signal)
c_backups.seize(ptr);
if(ptr.i == RNIL) {
jam();
- sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord);
+ sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
return;
}//if
@@ -894,6 +898,7 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0;
ptr.p->clientRef = senderRef;
ptr.p->clientData = senderData;
+ ptr.p->flags = flags;
ptr.p->masterRef = reference();
ptr.p->nodes = c_aliveNodes;
ptr.p->backupId = 0;
@@ -931,20 +936,23 @@ void
Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
{
jam();
- sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode);
+ sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
cleanup(signal, ptr);
}
void
-Backup::sendBackupRef(BlockReference senderRef, Signal *signal,
+Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode)
{
jam();
- BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->errorCode = errorCode;
- ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
- sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+ if (SEND_BACKUP_STARTED_FLAG(flags))
+ {
+ BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
+ ref->senderData = senderData;
+ ref->errorCode = errorCode;
+ ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
+ sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+ }
if(errorCode != BackupRef::IAmNotMaster){
signal->theData[0] = EventReport::BackupFailedToStart;
@@ -1098,6 +1106,7 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
req->backupKey[1] = ptr.p->backupKey[1];
req->nodes = ptr.p->nodes;
req->backupDataLen = ptr.p->backupDataLen;
+ req->flags = ptr.p->flags;
ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
ptr.p->masterData.sendCounter = ptr.p->nodes;
@@ -1193,13 +1202,18 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
/**
* Reply to client
*/
- BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->senderData = ptr.p->clientData;
- conf->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
- BackupConf::SignalLength, JBB);
-
+ CRASH_INSERTION((10034));
+
+ if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
+ {
+ BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
+ conf->backupId = ptr.p->backupId;
+ conf->senderData = ptr.p->clientData;
+ conf->nodes = ptr.p->nodes;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
+ BackupConf::SignalLength, JBB);
+ }
+
signal->theData[0] = EventReport::BackupStarted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2080,19 +2094,22 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
if(!ptr.p->checkError())
{
- BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->startGCP = ptr.p->startGCP;
- rep->stopGCP = ptr.p->stopGCP;
- rep->noOfBytes = ptr.p->noOfBytes;
- rep->noOfRecords = ptr.p->noOfRecords;
- rep->noOfLogBytes = ptr.p->noOfLogBytes;
- rep->noOfLogRecords = ptr.p->noOfLogRecords;
- rep->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
- BackupCompleteRep::SignalLength, JBB);
-
+ if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+ {
+ BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
+ rep->backupId = ptr.p->backupId;
+ rep->senderData = ptr.p->clientData;
+ rep->startGCP = ptr.p->startGCP;
+ rep->stopGCP = ptr.p->stopGCP;
+ rep->noOfBytes = ptr.p->noOfBytes;
+ rep->noOfRecords = ptr.p->noOfRecords;
+ rep->noOfLogBytes = ptr.p->noOfLogBytes;
+ rep->noOfLogRecords = ptr.p->noOfLogRecords;
+ rep->nodes = ptr.p->nodes;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
+ BackupCompleteRep::SignalLength, JBB);
+ }
+
signal->theData[0] = EventReport::BackupCompleted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2129,13 +2146,15 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
return;
}
- BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->reason = ptr.p->errorCode;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
- BackupAbortRep::SignalLength, JBB);
-
+ if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+ {
+ BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
+ rep->backupId = ptr.p->backupId;
+ rep->senderData = ptr.p->clientData;
+ rep->reason = ptr.p->errorCode;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
+ BackupAbortRep::SignalLength, JBB);
+ }
signal->theData[0] = EventReport::BackupAborted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2267,6 +2286,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0;
ptr.p->clientRef = req->clientRef;
ptr.p->clientData = req->clientData;
+ if(senderRef == reference())
+ ptr.p->flags = req->flags;
+ else
+ ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
+ * as non master should never
+ * reply
+ */
ptr.p->masterRef = senderRef;
ptr.p->nodes = req->nodes;
ptr.p->backupId = backupId;
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index 7bcea5655b4..f3d180b9467 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -413,6 +413,7 @@ public:
Uint32 clientRef;
Uint32 clientData;
+ Uint32 flags;
Uint32 backupId;
Uint32 backupKey[2];
Uint32 masterRef;
@@ -595,7 +596,7 @@ public:
bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);
- void sendBackupRef(BlockReference ref, Signal *signal,
+ void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode);
void dumpUsedResources();
void cleanup(Signal*, BackupRecordPtr ptr);
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 3d5eb0c52aa..90f4ac73411 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -6740,14 +6740,16 @@ Dbdict::createIndex_sendReply(Signal* signal, OpCreateIndexPtr opPtr,
CreateIndxRef* rep = (CreateIndxRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_CREATE_INDX_CONF;
Uint32 length = CreateIndxConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == CreateIndxReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -6816,11 +6818,8 @@ Dbdict::execDROP_INDX_REQ(Signal* signal)
goto error;
}
- if (tmp.p->indexState == TableRecord::IS_DROPPING){
- jam();
- err = DropIndxRef::IndexNotFound;
- goto error;
- }
+ if (tmp.p->indexState != TableRecord::IS_ONLINE)
+ req->addRequestFlag(RequestFlag::RF_FORCE);
tmp.p->indexState = TableRecord::IS_DROPPING;
@@ -7083,14 +7082,16 @@ Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr,
DropIndxRef* rep = (DropIndxRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_DROP_INDX_CONF;
Uint32 length = DropIndxConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == DropIndxReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -9607,7 +9608,7 @@ Dbdict::alterIndex_fromCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
{
jam();
// mark created in local TC
- if (! opPtr.p->hasError()) {
+ if (! opPtr.p->hasLastError()) {
TableRecordPtr indexPtr;
c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
indexPtr.p->indexLocal |= TableRecord::IL_CREATED_TC;
@@ -9623,9 +9624,10 @@ Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
jam();
TableRecordPtr indexPtr;
c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // broken index
+ // broken index allowed if force
if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
jam();
+ ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterIndex_sendReply(signal, opPtr, false);
return;
}
@@ -9647,8 +9649,8 @@ Dbdict::alterIndex_fromDropTc(Signal* signal, OpAlterIndexPtr opPtr)
{
jam();
ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
- if (! opPtr.p->hasError()) {
- // mark dropped in local TC
+ // mark dropped locally
+ if (! opPtr.p->hasLastError()) {
TableRecordPtr indexPtr;
c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
indexPtr.p->indexLocal &= ~TableRecord::IL_CREATED_TC;
@@ -9786,51 +9788,46 @@ Dbdict::alterIndex_toDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
req->setUserRef(reference());
req->setConnectionPtr(opPtr.p->key);
req->setRequestType(DropTrigReq::RT_ALTER_INDEX);
+ req->addRequestFlag(opPtr.p->m_requestFlag);
req->setTableId(opPtr.p->m_request.getTableId());
req->setIndexId(opPtr.p->m_request.getIndexId());
req->setTriggerInfo(0); // not used
opPtr.p->m_triggerCounter = 0;
- // insert
- if (indexPtr.p->insertTriggerId != RNIL) {
+ if (indexPtr.p->isHashIndex()) {
+ // insert
req->setTriggerId(indexPtr.p->insertTriggerId);
sendSignal(reference(), GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB);
opPtr.p->m_triggerCounter++;
- }
- // update
- if (indexPtr.p->updateTriggerId != RNIL) {
+ // update
req->setTriggerId(indexPtr.p->updateTriggerId);
sendSignal(reference(), GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB);
opPtr.p->m_triggerCounter++;
- }
- // delete
- if (indexPtr.p->deleteTriggerId != RNIL) {
+ // delete
req->setTriggerId(indexPtr.p->deleteTriggerId);
sendSignal(reference(), GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB);
opPtr.p->m_triggerCounter++;
+ // build
+ if (indexPtr.p->buildTriggerId != RNIL) {
+ req->setTriggerId(indexPtr.p->buildTriggerId);
+ sendSignal(reference(), GSN_DROP_TRIG_REQ,
+ signal, DropTrigReq::SignalLength, JBB);
+ opPtr.p->m_triggerCounter++;
+ }
+ return;
}
- // custom
- if (indexPtr.p->customTriggerId != RNIL) {
+ if (indexPtr.p->isOrderedIndex()) {
+ // custom
+ req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
req->setTriggerId(indexPtr.p->customTriggerId);
sendSignal(reference(), GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB);
opPtr.p->m_triggerCounter++;
+ return;
}
- // build
- if (indexPtr.p->buildTriggerId != RNIL) {
- req->setTriggerId(indexPtr.p->buildTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- }
- if (opPtr.p->m_triggerCounter == 0) {
- // drop in each TC
- jam();
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
- alterIndex_sendSlaveReq(signal, opPtr);
- }
+ ndbrequire(false);
}
void
@@ -9948,14 +9945,16 @@ Dbdict::alterIndex_sendReply(Signal* signal, OpAlterIndexPtr opPtr,
AlterIndxRef* rep = (AlterIndxRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_ALTER_INDX_CONF;
Uint32 length = AlterIndxConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == AlterIndxReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -10368,8 +10367,10 @@ Dbdict::buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr)
req->setUserRef(reference());
req->setConnectionPtr(opPtr.p->key);
if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
+ jam();
req->setRequestType(AlterIndxReq::RT_TC);
} else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
+ jam();
req->setRequestType(AlterIndxReq::RT_TUX);
} else {
ndbrequire(false);
@@ -10380,8 +10381,10 @@ Dbdict::buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr)
req->setOnline(true);
BlockReference blockRef = 0;
if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
+ jam();
blockRef = calcTcBlockRef(getOwnNodeId());
} else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
+ jam();
blockRef = calcTuxBlockRef(getOwnNodeId());
} else {
ndbrequire(false);
@@ -10408,15 +10411,14 @@ Dbdict::buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr)
req->setConnectionPtr(opPtr.p->key);
req->setRequestType(opPtr.p->m_requestType);
req->addRequestFlag(opPtr.p->m_requestFlag);
- if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
- {
+ if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
+ jam();
opPtr.p->m_signalCounter.clearWaitingFor();
opPtr.p->m_signalCounter.setWaitingFor(getOwnNodeId());
sendSignal(reference(), GSN_BUILDINDXREQ,
signal, BuildIndxReq::SignalLength, JBB);
- }
- else
- {
+ } else {
+ jam();
opPtr.p->m_signalCounter = c_aliveNodes;
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
sendSignal(rg, GSN_BUILDINDXREQ,
@@ -10431,14 +10433,16 @@ Dbdict::buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr,
BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_BUILDINDXCONF;
Uint32 length = BuildIndxConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -10925,14 +10929,16 @@ Dbdict::createTrigger_sendReply(Signal* signal, OpCreateTriggerPtr opPtr,
CreateTrigRef* rep = (CreateTrigRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_CREATE_TRIG_CONF;
Uint32 length = CreateTrigConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == CreateTrigReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -11020,8 +11026,10 @@ Dbdict::execDROP_TRIG_REQ(Signal* signal)
OpDropTrigger opBad;
opPtr.p = &opBad;
opPtr.p->save(req);
- opPtr.p->m_errorCode = DropTrigRef::TriggerNotFound;
- opPtr.p->m_errorLine = __LINE__;
+ if (! (req->getRequestFlag() & RequestFlag::RF_FORCE)) {
+ opPtr.p->m_errorCode = DropTrigRef::TriggerNotFound;
+ opPtr.p->m_errorLine = __LINE__;
+ }
dropTrigger_sendReply(signal, opPtr, true);
return;
}
@@ -11188,6 +11196,7 @@ Dbdict::dropTrigger_toAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
req->setUserRef(reference());
req->setConnectionPtr(opPtr.p->key);
req->setRequestType(AlterTrigReq::RT_DROP_TRIGGER);
+ req->addRequestFlag(opPtr.p->m_requestFlag);
req->setTableId(opPtr.p->m_request.getTableId());
req->setTriggerId(opPtr.p->m_request.getTriggerId());
req->setTriggerInfo(0); // not used
@@ -11283,14 +11292,16 @@ Dbdict::dropTrigger_sendReply(Signal* signal, OpDropTriggerPtr opPtr,
DropTrigRef* rep = (DropTrigRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_DROP_TRIG_CONF;
Uint32 length = DropTrigConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
if (opPtr.p->m_requestType == DropTrigReq::RT_DICT_ABORT)
sendRef = false;
} else {
+ sendRef = opPtr.p->hasError();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
rep->setRequestType(opPtr.p->m_request.getRequestType());
@@ -11514,28 +11525,37 @@ Dbdict::alterTrigger_recvReply(Signal* signal, const AlterTrigConf* conf,
if (! (opPtr.p->m_request.getRequestFlag() & RequestFlag::RF_NOTCTRIGGER)) {
if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
jam();
- if (opPtr.p->m_request.getOnline())
+ if (opPtr.p->m_request.getOnline()) {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
- else
+ } else {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
+ }
alterTrigger_sendSlaveReq(signal, opPtr);
return;
}
if (requestType == AlterTrigReq::RT_DICT_TC) {
jam();
- if (opPtr.p->m_request.getOnline())
+ if (opPtr.p->m_request.getOnline()) {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
- else
+ } else {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
+ }
alterTrigger_sendSlaveReq(signal, opPtr);
return;
}
if (requestType == AlterTrigReq::RT_DICT_LQH) {
jam();
- if (opPtr.p->m_request.getOnline())
+ if (opPtr.p->m_request.getOnline()) {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
- else
+ } else {
+ jam();
opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
+ }
alterTrigger_sendSlaveReq(signal, opPtr);
return;
}
@@ -11595,8 +11615,10 @@ Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
req->setUserRef(reference());
req->setConnectionPtr(opPtr.p->key);
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
+ jam();
req->setRequestType(CreateTrigReq::RT_TC);
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
+ jam();
req->setRequestType(CreateTrigReq::RT_LQH);
} else {
ndbassert(false);
@@ -11613,8 +11635,10 @@ Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
BlockReference blockRef = 0;
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
+ jam();
blockRef = calcTcBlockRef(getOwnNodeId());
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
+ jam();
blockRef = calcLqhBlockRef(getOwnNodeId());
} else {
ndbassert(false);
@@ -11628,13 +11652,15 @@ void
Dbdict::alterTrigger_fromCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
{
jam();
- if (! opPtr.p->hasError()) {
+ if (! opPtr.p->hasLastError()) {
// mark created locally
TriggerRecordPtr triggerPtr;
c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
+ jam();
triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_TC;
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
+ jam();
triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_LQH;
} else {
ndbrequire(false);
@@ -11654,17 +11680,21 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
req->setUserRef(reference());
req->setConnectionPtr(opPtr.p->key);
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- // broken trigger
+ jam();
+ // broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
jam();
+ ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
req->setRequestType(DropTrigReq::RT_TC);
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- // broken trigger
+ jam();
+ // broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) {
jam();
+ ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
@@ -11682,8 +11712,10 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
BlockReference blockRef = 0;
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
+ jam();
blockRef = calcTcBlockRef(getOwnNodeId());
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
+ jam();
blockRef = calcLqhBlockRef(getOwnNodeId());
} else {
ndbassert(false);
@@ -11696,13 +11728,15 @@ void
Dbdict::alterTrigger_fromDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
{
jam();
- if (! opPtr.p->hasError()) {
+ if (! opPtr.p->hasLastError()) {
// mark dropped locally
TriggerRecordPtr triggerPtr;
c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
+ jam();
triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_TC;
} else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
+ jam();
triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_LQH;
} else {
ndbrequire(false);
@@ -11759,8 +11793,9 @@ Dbdict::alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr,
AlterTrigRef* rep = (AlterTrigRef*)signal->getDataPtrSend();
Uint32 gsn = GSN_ALTER_TRIG_CONF;
Uint32 length = AlterTrigConf::InternalLength;
- bool sendRef = opPtr.p->hasError();
+ bool sendRef;
if (! toUser) {
+ sendRef = opPtr.p->hasLastError();
rep->setUserRef(opPtr.p->m_coordinatorRef);
rep->setConnectionPtr(opPtr.p->key);
rep->setRequestType(opPtr.p->m_requestType);
@@ -11771,6 +11806,7 @@ Dbdict::alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr,
jam();
}
} else {
+ sendRef = opPtr.p->hasError();
jam();
rep->setUserRef(opPtr.p->m_request.getUserRef());
rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index abe253bcaa7..bcee4a52b6a 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -924,7 +924,8 @@ private:
enum {
RF_LOCAL = 1 << 0, // create on local node only
RF_NOBUILD = 1 << 1, // no need to build index
- RF_NOTCTRIGGER = 1 << 2 // alter trigger: no trigger in TC
+ RF_NOTCTRIGGER = 1 << 2, // alter trigger: no trigger in TC
+ RF_FORCE = 1 << 4 // force drop
};
};
@@ -944,6 +945,7 @@ private:
CreateIndxReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ CreateIndxRef::ErrorCode m_lastError;
CreateIndxRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -955,6 +957,7 @@ private:
m_coordinatorRef = 0;
m_requestType = CreateIndxReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = CreateIndxRef::NoError;
m_errorCode = CreateIndxRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -964,34 +967,49 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != CreateIndxRef::NoError;
+ }
bool hasError() {
return m_errorCode != CreateIndxRef::NoError;
}
void setError(const CreateIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = CreateIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const CreateTableRef* ref) {
- if (ref != 0 && ! hasError()) {
+ m_lastError = CreateIndxRef::NoError;
+ if (ref != 0) {
switch (ref->getErrorCode()) {
case CreateTableRef::TableAlreadyExist:
- m_errorCode = CreateIndxRef::IndexExists;
+ m_lastError = CreateIndxRef::IndexExists;
break;
default:
- m_errorCode = (CreateIndxRef::ErrorCode)ref->getErrorCode();
+ m_lastError = (CreateIndxRef::ErrorCode)ref->getErrorCode();
break;
}
- m_errorLine = ref->getErrorLine();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ }
}
}
void setError(const AlterIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (CreateIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = CreateIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (CreateIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
@@ -1010,6 +1028,7 @@ private:
DropIndxReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ DropIndxRef::ErrorCode m_lastError;
DropIndxRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1021,6 +1040,7 @@ private:
m_coordinatorRef = 0;
m_requestType = DropIndxReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = DropIndxRef::NoError;
m_errorCode = DropIndxRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1030,44 +1050,59 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != DropIndxRef::NoError;
+ }
bool hasError() {
return m_errorCode != DropIndxRef::NoError;
}
void setError(const DropIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = DropIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = ref->getErrorCode();
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const AlterIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (DropIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = DropIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (DropIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const DropTableRef* ref) {
- if (ref != 0 && ! hasError()) {
- switch(ref->errorCode) {
- case(DropTableRef::Busy):
- m_errorCode = DropIndxRef::Busy;
+ m_lastError = DropIndxRef::NoError;
+ if (ref != 0) {
+ switch (ref->errorCode) {
+ case DropTableRef::Busy:
+ m_lastError = DropIndxRef::Busy;
break;
- case(DropTableRef::NoSuchTable):
- m_errorCode = DropIndxRef::IndexNotFound;
+ case DropTableRef::NoSuchTable:
+ m_lastError = DropIndxRef::IndexNotFound;
break;
- case(DropTableRef::DropInProgress):
- m_errorCode = DropIndxRef::Busy;
+ case DropTableRef::DropInProgress:
+ m_lastError = DropIndxRef::Busy;
break;
- case(DropTableRef::NoDropTableRecordAvailable):
- m_errorCode = DropIndxRef::Busy;
+ case DropTableRef::NoDropTableRecordAvailable:
+ m_lastError = DropIndxRef::Busy;
break;
default:
- m_errorCode = (DropIndxRef::ErrorCode)ref->errorCode;
+ m_lastError = (DropIndxRef::ErrorCode)ref->errorCode;
break;
}
- //m_errorLine = ref->getErrorLine();
- //m_errorNode = ref->getErrorNode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = 0;
+ m_errorNode = 0;
+ }
}
}
};
@@ -1088,6 +1123,7 @@ private:
AlterIndxReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ AlterIndxRef::ErrorCode m_lastError;
AlterIndxRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1100,6 +1136,7 @@ private:
m_coordinatorRef = 0;
m_requestType = AlterIndxReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = AlterIndxRef::NoError;
m_errorCode = AlterIndxRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1110,47 +1147,76 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != AlterIndxRef::NoError;
+ }
bool hasError() {
return m_errorCode != AlterIndxRef::NoError;
}
void setError(const AlterIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const CreateIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const DropIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const BuildIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = 0;
+ m_errorNode = 0;
+ }
}
}
void setError(const CreateTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const DropTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
@@ -1172,6 +1238,7 @@ private:
Uint32 m_requestFlag;
Uint32 m_constrTriggerId;
// error info
+ BuildIndxRef::ErrorCode m_lastError;
BuildIndxRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1183,7 +1250,7 @@ private:
m_coordinatorRef = 0;
m_requestType = BuildIndxReq::RT_UNDEFINED;
m_requestFlag = 0;
-// Uint32 m_constrTriggerId = RNIL;
+ m_lastError = BuildIndxRef::NoError;
m_errorCode = BuildIndxRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1193,33 +1260,54 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != BuildIndxRef::NoError;
+ }
bool hasError() {
return m_errorCode != BuildIndxRef::NoError;
}
void setError(const BuildIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
+ m_lastError = BuildIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = 0;
+ m_errorNode = 0;
+ }
}
}
void setError(const AlterIndxRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = BuildIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const CreateTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = BuildIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const DropTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = BuildIndxRef::NoError;
+ if (ref != 0) {
+ m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
@@ -1352,6 +1440,7 @@ private:
CreateTrigReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ CreateTrigRef::ErrorCode m_lastError;
CreateTrigRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1363,6 +1452,7 @@ private:
m_coordinatorRef = 0;
m_requestType = CreateTrigReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = CreateTrigRef::NoError;
m_errorCode = CreateTrigRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1372,21 +1462,32 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != CreateTrigRef::NoError;
+ }
bool hasError() {
return m_errorCode != CreateTrigRef::NoError;
}
void setError(const CreateTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = CreateTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const AlterTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (CreateTrigRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = CreateTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = (CreateTrigRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
@@ -1405,6 +1506,7 @@ private:
DropTrigReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ DropTrigRef::ErrorCode m_lastError;
DropTrigRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1416,6 +1518,7 @@ private:
m_coordinatorRef = 0;
m_requestType = DropTrigReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = DropTrigRef::NoError;
m_errorCode = DropTrigRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1425,21 +1528,32 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != DropTrigRef::NoError;
+ }
bool hasError() {
return m_errorCode != DropTrigRef::NoError;
}
void setError(const DropTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = DropTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const AlterTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (DropTrigRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = DropTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = (DropTrigRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
@@ -1460,6 +1574,7 @@ private:
AlterTrigReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
+ AlterTrigRef::ErrorCode m_lastError;
AlterTrigRef::ErrorCode m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
@@ -1471,6 +1586,7 @@ private:
m_coordinatorRef = 0;
m_requestType = AlterTrigReq::RT_UNDEFINED;
m_requestFlag = 0;
+ m_lastError = AlterTrigRef::NoError;
m_errorCode = AlterTrigRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@@ -1480,28 +1596,43 @@ private:
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
+ bool hasLastError() {
+ return m_lastError != AlterTrigRef::NoError;
+ }
bool hasError() {
return m_errorCode != AlterTrigRef::NoError;
}
void setError(const AlterTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const CreateTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
void setError(const DropTrigRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
+ m_lastError = AlterTrigRef::NoError;
+ if (ref != 0) {
+ m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
+ if (! hasError()) {
+ m_errorCode = m_lastError;
+ m_errorLine = ref->getErrorLine();
+ m_errorNode = ref->getErrorNode();
+ }
}
}
};
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 669be2b48f0..ca066b588e7 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -9640,6 +9640,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
}
bool tableDone = reportLcpCompletion(lcpReport);
+
+ Uint32 started = lcpReport->maxGciStarted;
+ Uint32 completed = lcpReport->maxGciCompleted;
if(tableDone){
jam();
@@ -9673,7 +9676,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
signal->theData[1] = nodeId;
signal->theData[2] = tableId;
signal->theData[3] = fragId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
+ signal->theData[4] = started;
+ signal->theData[5] = completed;
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
#endif
bool ok = false;
@@ -10790,7 +10795,9 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr,
lcpNo = fmgReplicaPtr.p->nextLcp;
do {
ndbrequire(lcpNo < MAX_LCP_STORED);
- if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID) {
+ if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID &&
+ fmgReplicaPtr.p->maxGciStarted[lcpNo] <= coldgcp)
+ {
jam();
keepGci = fmgReplicaPtr.p->maxGciCompleted[lcpNo];
oldestRestorableGci = fmgReplicaPtr.p->maxGciStarted[lcpNo];
@@ -10798,7 +10805,6 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr,
return;
} else {
jam();
- ndbrequire(fmgReplicaPtr.p->lcpStatus[lcpNo] == ZINVALID);
if (fmgReplicaPtr.p->createGci[0] == fmgReplicaPtr.p->initialGci) {
jam();
/*-------------------------------------------------------------------
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 836fc9398e5..951d1e90251 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -86,6 +86,17 @@
#define ZCURR_PAGE_INDEX 8
#define ZLAST_LOG_PREP_REF 10
#define ZPOS_DIRTY 11
+/* A number of debug items written in the page header of all log files */
+#define ZPOS_LOG_TIMER 12
+#define ZPOS_PAGE_I 13
+#define ZPOS_PLACE_WRITTEN_FROM 14
+#define ZPOS_PAGE_NO 15
+#define ZPOS_PAGE_FILE_NO 16
+#define ZPOS_WORD_WRITTEN 17
+#define ZPOS_IN_WRITING 18
+#define ZPOS_PREV_PAGE_NO 19
+#define ZPOS_IN_FREE_LIST 20
+
/* ------------------------------------------------------------------------- */
/* CONSTANTS FOR THE VARIOUS REPLICA AND NODE TYPES. */
/* ------------------------------------------------------------------------- */
@@ -2278,7 +2289,7 @@ private:
const LogPartRecordPtr &sltLogPartPtr);
void checkGcpCompleted(Signal* signal, Uint32 pageWritten, Uint32 wordWritten);
void initFsopenconf(Signal* signal);
- void initFsrwconf(Signal* signal);
+ void initFsrwconf(Signal* signal, bool write);
void initLfo(Signal* signal);
void initLogfile(Signal* signal, Uint32 fileNo);
void initLogpage(Signal* signal);
@@ -2294,7 +2305,8 @@ private:
void writeFileDescriptor(Signal* signal);
void writeFileHeaderOpen(Signal* signal, Uint32 type);
void writeInitMbyte(Signal* signal);
- void writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten);
+ void writeSinglePage(Signal* signal, Uint32 pageNo,
+ Uint32 wordWritten, Uint32 place);
void buildLinkedLogPageList(Signal* signal);
void changeMbyte(Signal* signal);
Uint32 checkIfExecLog(Signal* signal);
@@ -2303,7 +2315,7 @@ private:
void checkScanTcCompleted(Signal* signal);
void checkSrCompleted(Signal* signal);
void closeFile(Signal* signal, LogFileRecordPtr logFilePtr);
- void completedLogPage(Signal* signal, Uint32 clpType);
+ void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place);
void deleteFragrec(Uint32 fragId);
void deleteTransidHash(Signal* signal);
void findLogfile(Signal* signal,
@@ -2399,7 +2411,9 @@ private:
void writeAbortLog(Signal* signal);
void writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
void writeCompletedGciLog(Signal* signal);
- void writeDirty(Signal* signal);
+ void writeDbgInfoPageHeader(LogPageRecordPtr logPagePtr, Uint32 place,
+ Uint32 pageNo, Uint32 wordWritten);
+ void writeDirty(Signal* signal, Uint32 place);
void writeKey(Signal* signal);
void writeLogHeader(Signal* signal);
void writeLogWord(Signal* signal, Uint32 data);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 5e2e6dc392c..b6178227d31 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -11749,42 +11749,34 @@ void Dblqh::execFSCLOSECONF(Signal* signal)
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
exitFromInvalidate(signal);
return;
- break;
case LogFileRecord::CLOSING_INIT:
jam();
closingInitLab(signal);
return;
- break;
case LogFileRecord::CLOSING_SR:
jam();
closingSrLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_SR:
jam();
closeExecSrLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
jam();
closeExecSrCompletedLab(signal);
return;
- break;
case LogFileRecord::CLOSING_WRITE_LOG:
jam();
closeWriteLogLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_LOG:
jam();
closeExecLogLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSCLOSECONF()
@@ -11802,77 +11794,64 @@ void Dblqh::execFSOPENCONF(Signal* signal)
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
readFileInInvalidate(signal);
return;
- break;
case LogFileRecord::OPENING_INIT:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openFileInitLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FRONTPAGE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFrontpageLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_LAST_FILE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrLastFileLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_NEXT_FILE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrNextFileLab(signal);
return;
- break;
case LogFileRecord::OPEN_EXEC_SR_START:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecSrStartLab(signal);
return;
- break;
case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecSrNewMbyteLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_PHASE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthPhaseLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_NEXT:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthNextLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_ZERO:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthZeroLab(signal);
return;
- break;
case LogFileRecord::OPENING_WRITE_LOG:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
return;
- break;
case LogFileRecord::OPEN_EXEC_LOG:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecLogLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSOPENCONF()
@@ -11883,7 +11862,7 @@ void Dblqh::execFSOPENCONF(Signal* signal)
void Dblqh::execFSREADCONF(Signal* signal)
{
jamEntry();
- initFsrwconf(signal);
+ initFsrwconf(signal, false);
switch (lfoPtr.p->lfoState) {
case LogFileOperationRecord::READ_SR_LAST_MBYTE:
@@ -11891,57 +11870,47 @@ void Dblqh::execFSREADCONF(Signal* signal)
releaseLfo(signal);
readSrLastMbyteLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FRONTPAGE:
jam();
releaseLfo(signal);
readSrFrontpageLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_LAST_FILE:
jam();
releaseLfo(signal);
readSrLastFileLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_NEXT_FILE:
jam();
releaseLfo(signal);
readSrNextFileLab(signal);
return;
- break;
case LogFileOperationRecord::READ_EXEC_SR:
jam();
readExecSrLab(signal);
return;
- break;
case LogFileOperationRecord::READ_EXEC_LOG:
jam();
readExecLogLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
jam();
invalidateLogAfterLastGCI(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
jam();
releaseLfo(signal);
readSrFourthPhaseLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
jam();
releaseLfo(signal);
readSrFourthZeroLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSREADCONF()
@@ -11998,63 +11967,52 @@ void Dblqh::execFSREADREF(Signal* signal)
void Dblqh::execFSWRITECONF(Signal* signal)
{
jamEntry();
- initFsrwconf(signal);
+ initFsrwconf(signal, true);
switch (lfoPtr.p->lfoState) {
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
jam();
invalidateLogAfterLastGCI(signal);
return;
- break;
case LogFileOperationRecord::WRITE_PAGE_ZERO:
jam();
writePageZeroLab(signal);
return;
- break;
case LogFileOperationRecord::LAST_WRITE_IN_FILE:
jam();
lastWriteInFileLab(signal);
return;
- break;
case LogFileOperationRecord::INIT_WRITE_AT_END:
jam();
initWriteEndLab(signal);
return;
- break;
case LogFileOperationRecord::INIT_FIRST_PAGE:
jam();
initFirstPageLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_GCI_ZERO:
jam();
writeGciZeroLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_DIRTY:
jam();
writeDirtyLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_INIT_MBYTE:
jam();
writeInitMbyteLab(signal);
return;
- break;
case LogFileOperationRecord::ACTIVE_WRITE_LOG:
jam();
writeLogfileLab(signal);
return;
- break;
case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
jam();
firstPageWriteLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSWRITECONF()
@@ -12130,16 +12088,35 @@ void Dblqh::initFsopenconf(Signal* signal)
/* ======= INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF ======= */
/* */
/* ========================================================================= */
-void Dblqh::initFsrwconf(Signal* signal)
+void Dblqh::initFsrwconf(Signal* signal, bool write)
{
+ LogPageRecordPtr logP;
+ Uint32 noPages, totPages;
lfoPtr.i = signal->theData[0];
ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
+ totPages= lfoPtr.p->noPagesRw;
logFilePtr.i = lfoPtr.p->logFileRec;
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
logPartPtr.i = logFilePtr.p->logPartRec;
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
logPagePtr.i = lfoPtr.p->firstLfoPage;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
+ logP= logPagePtr;
+ noPages= 1;
+ ndbassert(totPages > 0);
+ for (;;)
+ {
+ logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
+ logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
+ if (noPages == totPages)
+ return;
+ if (write)
+ logP.i= logP.p->logPageWord[ZNEXT_PAGE];
+ else
+ logP.i= lfoPtr.p->logPageArray[noPages];
+ ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
+ noPages++;
+ }
}//Dblqh::initFsrwconf()
/* ######################################################################### */
@@ -12227,7 +12204,7 @@ void Dblqh::timeSup(Signal* signal)
ndbrequire(wordWritten < ZPAGE_SIZE);
if (logFilePtr.p->noLogpagesInBuffer > 0) {
jam();
- completedLogPage(signal, ZENFORCE_WRITE);
+ completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
/*---------------------------------------------------------------------------*/
/*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
/*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE */
@@ -12249,7 +12226,8 @@ void Dblqh::timeSup(Signal* signal)
releaseLogpage(signal);
} else {
jam();
- writeSinglePage(signal, logFilePtr.p->currentFilepage, wordWritten);
+ writeSinglePage(signal, logFilePtr.p->currentFilepage,
+ wordWritten, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
}//if
}//if
@@ -12385,7 +12363,7 @@ void Dblqh::firstPageWriteLab(Signal* signal)
logPagePtr.i = logFilePtr.p->logPageZero;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->logFileRec = currLogFile;
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
return;
@@ -12474,7 +12452,7 @@ void Dblqh::lastWriteInFileLab(Signal* signal)
logPagePtr.i = logFilePtr.p->logPageZero;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->logFileRec = currLogFile;
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
return;
@@ -12509,7 +12487,8 @@ void Dblqh::openFileInitLab(Signal* signal)
{
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
seizeLogpage(signal);
- writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
return;
}//Dblqh::openFileInitLab()
@@ -12550,7 +12529,7 @@ void Dblqh::initFirstPageLab(Signal* signal)
logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
- writeSinglePage(signal, 1, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
return;
}//if
@@ -12852,17 +12831,13 @@ void Dblqh::releaseLogpage(Signal* signal)
{
#ifdef VM_TRACE
// Check that log page isn't already in free list
- LogPageRecordPtr TlogPagePtr;
- TlogPagePtr.i = cfirstfreeLogPage;
- while (TlogPagePtr.i != RNIL){
- ptrCheckGuard(TlogPagePtr, clogPageFileSize, logPageRecord);
- ndbrequire(TlogPagePtr.i != logPagePtr.i);
- TlogPagePtr.i = TlogPagePtr.p->logPageWord[ZNEXT_PAGE];
- }
+ ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
#endif
cnoOfLogPages++;
logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
+ logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
cfirstfreeLogPage = logPagePtr.i;
}//Dblqh::releaseLogpage()
@@ -12908,6 +12883,7 @@ void Dblqh::seizeLogpage(Signal* signal)
/* ------------------------------------------------------------------------- */
cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
}//Dblqh::seizeLogpage()
/* ------------------------------------------------------------------------- */
@@ -13015,7 +12991,7 @@ WMO_LOOP:
/* LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND */
/* THE END OF THE LOG AT SYSTEM RESTART. */
/* ------------------------------------------------------- */
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
if (wmoType == ZINIT) {
jam();
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
@@ -13049,7 +13025,8 @@ WMO_LOOP:
void Dblqh::writeInitMbyte(Signal* signal)
{
initLogpage(signal);
- writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
}//Dblqh::writeInitMbyte()
@@ -13059,13 +13036,15 @@ void Dblqh::writeInitMbyte(Signal* signal)
/* INPUT: TWSP_PAGE_NO THE PAGE NUMBER WRITTEN */
/* SUBROUTINE SHORT NAME: WSP */
/* ------------------------------------------------------------------------- */
-void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten)
+void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
+ Uint32 wordWritten, Uint32 place)
{
seizeLfo(signal);
initLfo(signal);
lfoPtr.p->firstLfoPage = logPagePtr.i;
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
+ writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
// Calculate checksum for page
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
@@ -14534,7 +14513,7 @@ void Dblqh::execSr(Signal* signal)
* IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
* AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
* ----------------------------------------------------------------- */
- writeDirty(signal);
+ writeDirty(signal, __LINE__);
return;
break;
case LogPartRecord::LES_EXEC_LOG:
@@ -14545,7 +14524,7 @@ void Dblqh::execSr(Signal* signal)
* ------------------------------------------------------------------- */
if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
jam();
- writeDirty(signal);
+ writeDirty(signal, __LINE__);
return;
}//if
break;
@@ -14989,7 +14968,8 @@ void Dblqh::invalidateLogAfterLastGCI(Signal* signal) {
// This page must be invalidated.
logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 0;
// Contact NDBFS. Real time break.
- writeSinglePage(signal, logPartPtr.p->invalidatePageNo, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
} else {
// We are done with invalidating. Finish start phase 3.4.
@@ -15937,7 +15917,7 @@ void Dblqh::closeFile(Signal* signal, LogFileRecordPtr clfLogFilePtr)
// logPartPtr
// Defines lfoPtr
/* ---------------------------------------------------------------- */
-void Dblqh::completedLogPage(Signal* signal, Uint32 clpType)
+void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
{
LogPageRecordPtr clpLogPagePtr;
LogPageRecordPtr wlpLogPagePtr;
@@ -15980,6 +15960,9 @@ void Dblqh::completedLogPage(Signal* signal, Uint32 clpType)
twlpNoPages++;
ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
+ writeDbgInfoPageHeader(wlpLogPagePtr, place,
+ logFilePtr.p->filePosition + twlpNoPages - 1,
+ ZPAGE_SIZE);
// Calculate checksum for page
wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
@@ -16382,6 +16365,8 @@ void Dblqh::initialiseLogPage(Signal* signal)
refresh_watch_dog();
ptrAss(logPagePtr, logPageRecord);
logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
+ logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
}//for
logPagePtr.i = clogPageFileSize - 1;
ptrAss(logPagePtr, logPageRecord);
@@ -18038,10 +18023,14 @@ void Dblqh::writeCompletedGciLog(Signal* signal)
*
* SUBROUTINE SHORT NAME: WD
* ------------------------------------------------------------------------- */
-void Dblqh::writeDirty(Signal* signal)
+void Dblqh::writeDirty(Signal* signal, Uint32 place)
{
logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
+ ndbassert(logPartPtr.p->prevFilepage ==
+ logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
+ writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
+ ZPAGE_SIZE);
// Calculate checksum for page
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
@@ -18075,7 +18064,7 @@ void Dblqh::writeLogWord(Signal* signal, Uint32 data)
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
if ((logPos + 1) == ZPAGE_SIZE) {
jam();
- completedLogPage(signal, ZNORMAL);
+ completedLogPage(signal, ZNORMAL, __LINE__);
seizeLogpage(signal);
initLogpage(signal);
logFilePtr.p->currentLogpage = logPagePtr.i;
@@ -18133,7 +18122,7 @@ void Dblqh::writeNextLog(Signal* signal)
/* -------------------------------------------------- */
/* WE HAVE TO CHANGE LOG FILE */
/* -------------------------------------------------- */
- completedLogPage(signal, ZLAST_WRITE_IN_FILE);
+ completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
if (wnlNextLogFilePtr.p->fileNo == 0) {
jam();
/* -------------------------------------------------- */
@@ -18152,7 +18141,7 @@ void Dblqh::writeNextLog(Signal* signal)
/* INCREMENT THE CURRENT MBYTE */
/* SET PAGE INDEX TO PAGE HEADER SIZE */
/* -------------------------------------------------- */
- completedLogPage(signal, ZENFORCE_WRITE);
+ completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
}//if
/* -------------------------------------------------- */
@@ -18520,3 +18509,16 @@ Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
return checkSum;
}
+void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
+ Uint32 pageNo, Uint32 wordWritten)
+{
+ logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
+ logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
+ logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
+ logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
+ logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
+ logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
+ logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
+ logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
+}
+
diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
index ba6d65ca838..6eadefe5df5 100644
--- a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
+++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
@@ -134,7 +134,9 @@ bool PrepareOperationRecord::check() {
return true;
}
-Uint32 PrepareOperationRecord::getLogRecordSize() {
+Uint32 PrepareOperationRecord::getLogRecordSize(Uint32 wordsRead) {
+ if (wordsRead < 2)
+ return 2; // make sure we read more
return m_logRecordSize;
}
@@ -264,7 +266,16 @@ NdbOut& operator<<(NdbOut& no, const PageHeader& ph) {
printOut("Current page index:", ph.m_current_page_index);
printOut("Oldest prepare op. file No.:", ph.m_old_prepare_file_number);
printOut("Oldest prepare op. page ref.:", ph.m_old_prepare_page_reference);
- printOut("Dirty flag:", ph.m_dirty_flag);
+ printOut("Dirty flag:", ph.m_dirty_flag);
+ printOut("Write Timer:", ph.m_log_timer);
+ printOut("Page i-val:", ph.m_page_i_value);
+ printOut("Place written:", ph.m_place_written_from);
+ printOut("Page No in File:", ph.m_page_no);
+ printOut("File No:", ph.m_file_no);
+ printOut("Word Written:", ph.m_word_written);
+ printOut("In Writing (should be 1)", ph.m_in_writing_flag);
+ printOut("Prev Page No (can be garbage)", ph.m_prev_page_no);
+ printOut("In Free List (should be 0):", ph.m_in_free_list);
no << endl;
return no;
}
diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
index 11b8dc4a6fa..06bf7a85d53 100644
--- a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
+++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
@@ -83,7 +83,7 @@ class PrepareOperationRecord {
friend NdbOut& operator<<(NdbOut&, const PrepareOperationRecord&);
public:
bool check();
- Uint32 getLogRecordSize();
+ Uint32 getLogRecordSize(Uint32 wordsRead);
protected:
Uint32 m_recordType;
@@ -147,6 +147,17 @@ protected:
Uint32 m_old_prepare_file_number;
Uint32 m_old_prepare_page_reference;
Uint32 m_dirty_flag;
+/* Debug info Start */
+ Uint32 m_log_timer;
+ Uint32 m_page_i_value;
+ Uint32 m_place_written_from;
+ Uint32 m_page_no;
+ Uint32 m_file_no;
+ Uint32 m_word_written;
+ Uint32 m_in_writing_flag;
+ Uint32 m_prev_page_no;
+ Uint32 m_in_free_list;
+/* Debug info End */
};
//----------------------------------------------------------------
diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
index aa8b1d25e4e..751d27db74e 100644
--- a/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
+++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp
@@ -41,6 +41,7 @@ void doExit();
FILE * f= 0;
char fileName[256];
+bool theDumpFlag = false;
bool thePrintFlag = true;
bool theCheckFlag = true;
bool onlyPageHeaders = false;
@@ -208,7 +209,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
case ZPREP_OP_TYPE:
poRecord = (PrepareOperationRecord *) redoLogPagePos;
- wordIndex += poRecord->getLogRecordSize();
+ wordIndex += poRecord->getLogRecordSize(PAGESIZE-wordIndex);
if (wordIndex <= PAGESIZE) {
if (thePrintFlag) ndbout << (*poRecord);
if (theCheckFlag) {
@@ -277,10 +278,9 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
// Print out remaining data in this page
- for (int j = wordIndex; j < PAGESIZE; j++){
- Uint32 unknown = redoLogPage[i*PAGESIZE + j];
-
- ndbout_c("%-30d%-12u%-12x", j, unknown, unknown);
+ for (int k = wordIndex; k < PAGESIZE; k++){
+ Uint32 unknown = redoLogPage[i*PAGESIZE + k];
+ ndbout_c("%-30d%-12u%-12x", k, unknown, unknown);
}
doExit();
@@ -289,8 +289,19 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
if (lastPage)
+ {
+ if (theDumpFlag)
+ {
+ ndbout << " ------PAGE END: DUMPING REST OF PAGE------" << endl;
+ for (int k = wordIndex > PAGESIZE ? oldWordIndex : wordIndex;
+ k < PAGESIZE; k++)
+ {
+ Uint32 word = redoLogPage[i*PAGESIZE + k];
+ ndbout_c("%-30d%-12u%-12x", k, word, word);
+ }
+ }
break;
-
+ }
if (wordIndex > PAGESIZE) {
words_from_previous_page = PAGESIZE - oldWordIndex;
ndbout << " ----------- Record continues on next page -----------" << endl;
@@ -353,6 +364,8 @@ void readArguments(int argc, const char** argv)
{
if (strcmp(argv[i], "-noprint") == 0) {
thePrintFlag = false;
+ } else if (strcmp(argv[i], "-dump") == 0) {
+ theDumpFlag = true;
} else if (strcmp(argv[i], "-nocheck") == 0) {
theCheckFlag = false;
} else if (strcmp(argv[i], "-mbyteheaders") == 0) {
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 93b122b9a99..04b40dafcb5 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -4404,7 +4404,7 @@ Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
*------------------------------------------------------------------------*/
tabortInd = ZFALSE;
setupFailData(signal);
- if (tabortInd == ZFALSE) {
+ if (false && tabortInd == ZFALSE) {
jam();
commitGciHandling(signal, Tgci);
toCommitHandlingLab(signal);
@@ -10833,6 +10833,7 @@ void Dbtc::execCREATE_TRIG_REQ(Signal* signal)
if (ERROR_INSERTED(8033) ||
!c_theDefinedTriggers.seizeId(triggerPtr,
createTrigReq->getTriggerId())) {
+ jam();
CLEAR_ERROR_INSERT_VALUE;
// Failed to allocate trigger record
CreateTrigRef * const createTrigRef =
@@ -10867,8 +10868,10 @@ void Dbtc::execDROP_TRIG_REQ(Signal* signal)
DropTrigReq * const dropTrigReq = (DropTrigReq *)&signal->theData[0];
BlockReference sender = signal->senderBlockRef();
- if ((c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
+ if (ERROR_INSERTED(8035) ||
+ (c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
jam();
+ CLEAR_ERROR_INSERT_VALUE;
// Failed to find find trigger record
DropTrigRef * const dropTrigRef = (DropTrigRef *)&signal->theData[0];
@@ -10900,6 +10903,7 @@ void Dbtc::execCREATE_INDX_REQ(Signal* signal)
if (ERROR_INSERTED(8034) ||
!c_theIndexes.seizeId(indexPtr, createIndxReq->getIndexId())) {
+ jam();
CLEAR_ERROR_INSERT_VALUE;
// Failed to allocate index record
CreateIndxRef * const createIndxRef =
@@ -11111,8 +11115,10 @@ void Dbtc::execDROP_INDX_REQ(Signal* signal)
TcIndexData* indexData;
BlockReference sender = signal->senderBlockRef();
- if ((indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
+ if (ERROR_INSERTED(8036) ||
+ (indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
jam();
+ CLEAR_ERROR_INSERT_VALUE;
// Failed to find index record
DropIndxRef * const dropIndxRef =
(DropIndxRef *)signal->getDataPtrSend();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 575d08efffc..0acfd390360 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -305,6 +305,10 @@ Dbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId)
Uint32
Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req)
{
+ if (ERROR_INSERTED(4004)) {
+ CLEAR_ERROR_INSERT_VALUE;
+ return 9999;
+ }
Uint32 triggerId = req->getTriggerId();
TriggerType::Value ttype = req->getTriggerType();
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 2e2c834ad9c..071a85c96da 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -2493,6 +2493,14 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
const Uint32 start = currentBlockIndex;
+ if (currentStartPhase == ZSTART_PHASE_6)
+ {
+ // Ndbd has passed the critical startphases.
+ // Change error handler from "startup" state
+ // to normal state.
+ ErrorReporter::setErrorHandlerShutdownType();
+ }
+
for(; currentBlockIndex < ALL_BLOCKS_SZ; currentBlockIndex++){
jam();
if(ALL_BLOCKS[currentBlockIndex].NextSP == currentStartPhase){
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index e4ead4ce34d..25409db48a8 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -152,6 +152,14 @@ ErrorReporter::formatMessage(ErrorCategory type,
return;
}
+NdbShutdownType ErrorReporter::s_errorHandlerShutdownType = NST_ErrorHandler;
+
+void
+ErrorReporter::setErrorHandlerShutdownType(NdbShutdownType nst)
+{
+ s_errorHandlerShutdownType = nst;
+}
+
void
ErrorReporter::handleAssert(const char* message, const char* file, int line)
{
@@ -170,7 +178,7 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line)
WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage,
theEmulatedJamIndex, theEmulatedJam);
- NdbShutdown(NST_ErrorHandler);
+ NdbShutdown(s_errorHandlerShutdownType);
}
void
@@ -182,7 +190,7 @@ ErrorReporter::handleThreadAssert(const char* message,
BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d - %s",
file, line, message);
- NdbShutdown(NST_ErrorHandler);
+ NdbShutdown(s_errorHandlerShutdownType);
}//ErrorReporter::handleThreadAssert()
@@ -201,6 +209,8 @@ ErrorReporter::handleError(ErrorCategory type, int messageID,
if(messageID == ERR_ERROR_INSERT){
NdbShutdown(NST_ErrorInsert);
} else {
+ if (nst == NST_ErrorHandler)
+ nst = s_errorHandlerShutdownType;
NdbShutdown(nst);
}
}
diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp
index 2c79f242eea..c5533df46f4 100644
--- a/ndb/src/kernel/error/ErrorReporter.hpp
+++ b/ndb/src/kernel/error/ErrorReporter.hpp
@@ -26,6 +26,7 @@
class ErrorReporter
{
public:
+ static void setErrorHandlerShutdownType(NdbShutdownType nst = NST_ErrorHandler);
static void handleAssert(const char* message,
const char* file,
int line);
@@ -57,6 +58,7 @@ public:
static const char* formatTimeStampString();
private:
+ static enum NdbShutdownType s_errorHandlerShutdownType;
};
#endif
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index 1e5cd5270e4..d9953b920d2 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -45,8 +45,14 @@ extern NdbMutex * theShutdownMutex;
void catchsigs(bool ignore); // for process signal handling
+#define MAX_FAILED_STARTUPS 3
+// Flag set by child through SIGUSR1 to signal a failed startup
+static bool failed_startup_flag = false;
+// Counter for consecutive failed startups
+static Uint32 failed_startups = 0;
extern "C" void handler_shutdown(int signum); // for process signal handling
extern "C" void handler_error(int signum); // for process signal handling
+extern "C" void handler_sigusr1(int signum); // child signalling failed restart
// Shows system information
void systemInfo(const Configuration & conf,
@@ -57,7 +63,7 @@ int main(int argc, char** argv)
NDB_INIT(argv[0]);
// Print to stdout/console
g_eventLogger.createConsoleHandler();
- g_eventLogger.setCategory("NDB");
+ g_eventLogger.setCategory("ndbd");
g_eventLogger.enable(Logger::LL_ON, Logger::LL_CRITICAL);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_ERROR);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_WARNING);
@@ -92,6 +98,8 @@ int main(int argc, char** argv)
}
#ifndef NDB_WIN32
+ signal(SIGUSR1, handler_sigusr1);
+
for(pid_t child = fork(); child != 0; child = fork()){
/**
* Parent
@@ -137,6 +145,20 @@ int main(int argc, char** argv)
*/
exit(0);
}
+ if (!failed_startup_flag)
+ {
+ // Reset the counter for consecutive failed startups
+ failed_startups = 0;
+ }
+ else if (failed_startups >= MAX_FAILED_STARTUPS && !theConfig->stopOnError())
+ {
+ /**
+ * Error shutdown && stopOnError()
+ */
+ g_eventLogger.alert("Ndbd has failed %u consecutive startups. Not restarting", failed_startups);
+ exit(0);
+ }
+ failed_startup_flag = false;
g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
theConfig->fetch_configuration();
}
@@ -170,6 +192,9 @@ int main(int argc, char** argv)
/**
* Do startup
*/
+
+ ErrorReporter::setErrorHandlerShutdownType(NST_ErrorHandlerStartup);
+
switch(globalData.theRestartFlag){
case initial_state:
globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
@@ -359,3 +384,15 @@ handler_error(int signum){
BaseString::snprintf(errorData, 40, "Signal %d received", signum);
ERROR_SET_SIGNAL(fatal, 0, errorData, __FILE__);
}
+
+extern "C"
+void
+handler_sigusr1(int signum)
+{
+ if (!failed_startup_flag)
+ {
+ failed_startups++;
+ failed_startup_flag = true;
+ }
+ g_eventLogger.info("Angel received ndbd startup failure count %u.", failed_startups);
+}
diff --git a/ndb/src/kernel/vm/Emulator.cpp b/ndb/src/kernel/vm/Emulator.cpp
index d6ed6c0dafd..058829e05e2 100644
--- a/ndb/src/kernel/vm/Emulator.cpp
+++ b/ndb/src/kernel/vm/Emulator.cpp
@@ -30,13 +30,16 @@
#include <NodeState.hpp>
#include <NdbMem.h>
-#include <NdbOut.hpp>
#include <NdbMutex.h>
#include <NdbSleep.h>
+#include <EventLogger.hpp>
+
extern "C" {
extern void (* ndb_new_handler)();
}
+extern EventLogger g_eventLogger;
+extern my_bool opt_core;
/**
* Declare the global variables
@@ -141,45 +144,50 @@ NdbShutdown(NdbShutdownType type,
switch(type){
case NST_Normal:
- ndbout << "Shutdown initiated" << endl;
+ g_eventLogger.info("Shutdown initiated");
break;
case NST_Watchdog:
- ndbout << "Watchdog " << shutting << " system" << endl;
+ g_eventLogger.info("Watchdog %s system", shutting);
break;
case NST_ErrorHandler:
- ndbout << "Error handler " << shutting << " system" << endl;
+ g_eventLogger.info("Error handler %s system", shutting);
break;
case NST_ErrorHandlerSignal:
- ndbout << "Error handler signal " << shutting << " system" << endl;
+ g_eventLogger.info("Error handler signal %s system", shutting);
+ break;
+ case NST_ErrorHandlerStartup:
+ g_eventLogger.info("Error handler startup %s system", shutting);
break;
case NST_Restart:
- ndbout << "Restarting system" << endl;
+ g_eventLogger.info("Restarting system");
break;
default:
- ndbout << "Error handler " << shutting << " system"
- << " (unknown type: " << (unsigned)type << ")" << endl;
+ g_eventLogger.info("Error handler %s system (unknown type: %u)",
+ shutting, (unsigned)type);
type = NST_ErrorHandler;
break;
}
const char * exitAbort = 0;
-#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
- exitAbort = "aborting";
-#else
- exitAbort = "exiting";
-#endif
+ if (opt_core)
+ exitAbort = "aborting";
+ else
+ exitAbort = "exiting";
if(type == NST_Watchdog){
/**
* Very serious, don't attempt to free, just die!!
*/
- ndbout << "Watchdog shutdown completed - " << exitAbort << endl;
-#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
- signal(6, SIG_DFL);
- abort();
-#else
- exit(-1);
-#endif
+ g_eventLogger.info("Watchdog shutdown completed - %s", exitAbort);
+ if (opt_core)
+ {
+ signal(6, SIG_DFL);
+ abort();
+ }
+ else
+ {
+ exit(-1);
+ }
}
#ifndef NDB_WIN32
@@ -227,13 +235,19 @@ NdbShutdown(NdbShutdownType type,
}
if(type != NST_Normal && type != NST_Restart){
- ndbout << "Error handler shutdown completed - " << exitAbort << endl;
-#if ( defined VM_TRACE || defined ERROR_INSERT ) && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
- signal(6, SIG_DFL);
- abort();
-#else
- exit(-1);
-#endif
+ // Signal parent that error occured during startup
+ if (type == NST_ErrorHandlerStartup)
+ kill(getppid(), SIGUSR1);
+ g_eventLogger.info("Error handler shutdown completed - %s", exitAbort);
+ if (opt_core)
+ {
+ signal(6, SIG_DFL);
+ abort();
+ }
+ else
+ {
+ exit(-1);
+ }
}
/**
@@ -243,7 +257,7 @@ NdbShutdown(NdbShutdownType type,
exit(restartType);
}
- ndbout << "Shutdown completed - exiting" << endl;
+ g_eventLogger.info("Shutdown completed - exiting");
} else {
/**
* Shutdown is already in progress
@@ -253,7 +267,7 @@ NdbShutdown(NdbShutdownType type,
* If this is the watchdog, kill system the hard way
*/
if (type== NST_Watchdog){
- ndbout << "Watchdog is killing system the hard way" << endl;
+ g_eventLogger.info("Watchdog is killing system the hard way");
#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
signal(6, SIG_DFL);
abort();
diff --git a/ndb/src/kernel/vm/Emulator.hpp b/ndb/src/kernel/vm/Emulator.hpp
index dba8cb3ab9b..cd194202d85 100644
--- a/ndb/src/kernel/vm/Emulator.hpp
+++ b/ndb/src/kernel/vm/Emulator.hpp
@@ -83,7 +83,8 @@ enum NdbShutdownType {
NST_ErrorHandler,
NST_ErrorHandlerSignal,
NST_Restart,
- NST_ErrorInsert
+ NST_ErrorInsert,
+ NST_ErrorHandlerStartup
};
enum NdbRestartType {
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index bf78adec970..06b534ac0ca 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -638,12 +638,10 @@ ndb_mgm_get_status(NdbMgmHandle handle)
Vector<BaseString> split;
tmp.split(split, ":");
if(split.size() != 2){
- abort();
return NULL;
}
if(!(split[0].trim() == "nodes")){
- abort();
return NULL;
}
@@ -692,7 +690,6 @@ ndb_mgm_get_status(NdbMgmHandle handle)
if(i+1 != noOfNodes){
free(state);
- abort();
return NULL;
}
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index cface035174..36a72dcb975 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -25,6 +25,7 @@
#include <m_string.h>
extern my_bool opt_ndb_shm;
+extern my_bool opt_core;
#define MAX_LINE_LENGTH 255
#define KEY_INTERNAL 0
@@ -2140,11 +2141,10 @@ static void require(bool v)
{
if(!v)
{
-#ifndef DBUG_OFF
- abort();
-#else
- exit(-1);
-#endif
+ if (opt_core)
+ abort();
+ else
+ exit(-1);
}
}
@@ -2214,7 +2214,7 @@ ConfigInfo::ConfigInfo()
ndbout << "Error: Parameter " << param._fname
<< " defined twice in section " << param._section
<< "." << endl;
- exit(-1);
+ require(false);
}
// Add new pinfo to section
@@ -2264,7 +2264,7 @@ ConfigInfo::ConfigInfo()
ndbout << "Check that each entry has a section failed." << endl;
ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl;
ndbout << "Edit file " << __FILE__ << "." << endl;
- exit(-1);
+ require(false);
}
if(m_ParamInfo[i]._type == ConfigInfo::CI_SECTION)
@@ -2277,7 +2277,7 @@ ConfigInfo::ConfigInfo()
<< "\" does not exist in section \""
<< m_ParamInfo[i]._section << "\"." << endl;
ndbout << "Edit file " << __FILE__ << "." << endl;
- exit(-1);
+ require(false);
}
}
}
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 452dabc50e0..56c24e5f862 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -39,6 +39,8 @@
#include <signaldata/BackupSignalData.hpp>
#include <signaldata/GrepImpl.hpp>
#include <signaldata/ManagementServer.hpp>
+#include <signaldata/NFCompleteRep.hpp>
+#include <signaldata/NodeFailRep.hpp>
#include <NdbSleep.h>
#include <EventLogger.hpp>
#include <DebuggerNames.hpp>
@@ -56,6 +58,8 @@
#include <mgmapi_config_parameters.h>
#include <m_string.h>
+#include <SignalSender.hpp>
+
//#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0)
@@ -65,6 +69,18 @@
extern int global_flag_send_heartbeat_now;
extern int g_no_nodeid_checks;
+extern my_bool opt_core;
+
+static void require(bool v)
+{
+ if(!v)
+ {
+ if (opt_core)
+ abort();
+ else
+ exit(-1);
+ }
+}
void *
MgmtSrvr::logLevelThread_C(void* m)
@@ -436,14 +452,14 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
if (tmp_nodeid == 0)
{
ndbout_c(m_config_retriever->getErrorString());
- exit(-1);
+ require(false);
}
// read config from other managent server
_config= fetchConfig();
if (_config == 0)
{
ndbout << m_config_retriever->getErrorString() << endl;
- exit(-1);
+ require(false);
}
_ownNodeId= tmp_nodeid;
}
@@ -454,7 +470,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
_config= readConfig();
if (_config == 0) {
ndbout << "Unable to read config file" << endl;
- exit(-1);
+ require(false);
}
}
@@ -511,7 +527,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
if ((m_node_id_mutex = NdbMutex_Create()) == 0)
{
ndbout << "mutex creation failed line = " << __LINE__ << endl;
- exit(-1);
+ require(false);
}
if (_ownNodeId == 0) // we did not get node id from other server
@@ -522,7 +538,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
0, 0, error_string)){
ndbout << "Unable to obtain requested nodeid: "
<< error_string.c_str() << endl;
- exit(-1);
+ require(false);
}
_ownNodeId = tmp;
}
@@ -533,7 +549,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
_ownNodeId))
{
ndbout << m_config_retriever->getErrorString() << endl;
- exit(-1);
+ require(false);
}
}
@@ -697,6 +713,15 @@ int MgmtSrvr::okToSendTo(NodeId processId, bool unCond)
}
}
+void report_unknown_signal(SimpleSignal *signal)
+{
+ g_eventLogger.error("Unknown signal received. SignalNumber: "
+ "%i from (%d, %x)",
+ signal->readSignalNumber(),
+ refToNode(signal->header.theSendersBlockRef),
+ refToBlock(signal->header.theSendersBlockRef));
+}
+
/*****************************************************************************
* Starting and stopping database nodes
****************************************************************************/
@@ -1899,81 +1924,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
}
break;
- case GSN_BACKUP_CONF:{
- const BackupConf * const conf =
- CAST_CONSTPTR(BackupConf, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupStarted;
- event.Started.BackupId = conf->backupId;
- event.Nodes = conf->nodes;
-#ifdef VM_TRACE
- ndbout_c("Backup master is %d", refToNode(signal->theSendersBlockRef));
-#endif
- backupCallback(event);
- }
- break;
-
- case GSN_BACKUP_REF:{
- const BackupRef * const ref =
- CAST_CONSTPTR(BackupRef, signal->getDataPtr());
- Uint32 errCode = ref->errorCode;
- if(ref->errorCode == BackupRef::IAmNotMaster){
- const Uint32 aNodeId = refToNode(ref->masterRef);
-#ifdef VM_TRACE
- ndbout_c("I'm not master resending to %d", aNodeId);
-#endif
- theWaitNode= aNodeId;
- NdbApiSignal aSignal(_ownReference);
- BackupReq* req = CAST_PTR(BackupReq, aSignal.getDataPtrSend());
- aSignal.set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength);
- req->senderData = 19;
- req->backupDataLen = 0;
-
- int i = theFacade->sendSignalUnCond(&aSignal, aNodeId);
- if(i == 0){
- return;
- }
- errCode = 5030;
- }
- BackupEvent event;
- event.Event = BackupEvent::BackupFailedToStart;
- event.FailedToStart.ErrorCode = errCode;
- backupCallback(event);
- break;
- }
-
- case GSN_BACKUP_ABORT_REP:{
- const BackupAbortRep * const rep =
- CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupAborted;
- event.Aborted.Reason = rep->reason;
- event.Aborted.BackupId = rep->backupId;
- event.Aborted.ErrorCode = rep->reason;
- backupCallback(event);
- }
- break;
-
- case GSN_BACKUP_COMPLETE_REP:{
- const BackupCompleteRep * const rep =
- CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupCompleted;
- event.Completed.BackupId = rep->backupId;
-
- event.Completed.NoOfBytes = rep->noOfBytes;
- event.Completed.NoOfLogBytes = rep->noOfLogBytes;
- event.Completed.NoOfRecords = rep->noOfRecords;
- event.Completed.NoOfLogRecords = rep->noOfLogRecords;
- event.Completed.stopGCP = rep->stopGCP;
- event.Completed.startGCP = rep->startGCP;
- event.Nodes = rep->nodes;
-
- backupCallback(event);
- }
- break;
-
case GSN_MGM_LOCK_CONFIG_REP:
case GSN_MGM_LOCK_CONFIG_REQ:
case GSN_MGM_UNLOCK_CONFIG_REP:
@@ -2203,18 +2153,18 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
iter(*(ndb_mgm_configuration *)_config->m_configValues, CFG_SECTION_NODE);
for(iter.first(); iter.valid(); iter.next()) {
unsigned tmp= 0;
- if(iter.get(CFG_NODE_ID, &tmp)) abort();
+ if(iter.get(CFG_NODE_ID, &tmp)) require(false);
if (*nodeId && *nodeId != tmp)
continue;
found_matching_id= true;
- if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) abort();
+ if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) require(false);
if(type_c != (unsigned)type)
continue;
found_matching_type= true;
if (connected_nodes.get(tmp))
continue;
found_free_node= true;
- if(iter.get(CFG_NODE_HOST, &config_hostname)) abort();
+ if(iter.get(CFG_NODE_HOST, &config_hostname)) require(false);
if (config_hostname && config_hostname[0] == 0)
config_hostname= 0;
else if (client_addr) {
@@ -2434,6 +2384,9 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
int
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
{
+ SignalSender ss(theFacade);
+ ss.lock(); // lock will be released on exit
+
bool next;
NodeId nodeId = 0;
while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
@@ -2441,50 +2394,124 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
if(!next) return NO_CONTACT_WITH_DB_NODES;
- NdbApiSignal* signal = getSignal();
- if (signal == NULL) {
- return COULD_NOT_ALLOCATE_MEMORY;
- }
+ SimpleSignal ssig;
- BackupReq* req = CAST_PTR(BackupReq, signal->getDataPtrSend());
- signal->set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength);
+ BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
+ ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
+ BackupReq::SignalLength);
req->senderData = 19;
req->backupDataLen = 0;
+ assert(waitCompleted < 3);
+ req->flags = waitCompleted & 0x3;
- int result;
- if (waitCompleted == 2) {
- result = sendRecSignal(nodeId, WAIT_BACKUP_COMPLETED,
- signal, true, 48*60*60*1000 /* 48 hours */);
- }
- else if (waitCompleted == 1) {
- result = sendRecSignal(nodeId, WAIT_BACKUP_STARTED,
- signal, true, 5*60*1000 /*5 mins*/);
- }
- else {
- result = sendRecSignal(nodeId, NO_WAIT, signal, true);
- }
- if (result == -1) {
- return SEND_OR_RECEIVE_FAILED;
- }
-
- if (waitCompleted){
- switch(m_lastBackupEvent.Event){
- case BackupEvent::BackupCompleted:
- backupId = m_lastBackupEvent.Completed.BackupId;
+ BackupEvent event;
+ int do_send = 1;
+ while (1) {
+ if (do_send)
+ {
+ SendStatus result = ss.sendSignal(nodeId, &ssig);
+ if (result != SEND_OK) {
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ if (waitCompleted == 0)
+ return 0;
+ do_send = 0;
+ }
+ SimpleSignal *signal = ss.waitFor();
+
+ int gsn = signal->readSignalNumber();
+ switch (gsn) {
+ case GSN_BACKUP_CONF:{
+ const BackupConf * const conf =
+ CAST_CONSTPTR(BackupConf, signal->getDataPtr());
+ event.Event = BackupEvent::BackupStarted;
+ event.Started.BackupId = conf->backupId;
+ event.Nodes = conf->nodes;
+#ifdef VM_TRACE
+ ndbout_c("Backup(%d) master is %d", conf->backupId,
+ refToNode(signal->header.theSendersBlockRef));
+#endif
+ backupId = conf->backupId;
+ if (waitCompleted == 1)
+ return 0;
+ // wait for next signal
break;
- case BackupEvent::BackupStarted:
- backupId = m_lastBackupEvent.Started.BackupId;
+ }
+ case GSN_BACKUP_COMPLETE_REP:{
+ const BackupCompleteRep * const rep =
+ CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
+#ifdef VM_TRACE
+ ndbout_c("Backup(%d) completed %d", rep->backupId);
+#endif
+ event.Event = BackupEvent::BackupCompleted;
+ event.Completed.BackupId = rep->backupId;
+
+ event.Completed.NoOfBytes = rep->noOfBytes;
+ event.Completed.NoOfLogBytes = rep->noOfLogBytes;
+ event.Completed.NoOfRecords = rep->noOfRecords;
+ event.Completed.NoOfLogRecords = rep->noOfLogRecords;
+ event.Completed.stopGCP = rep->stopGCP;
+ event.Completed.startGCP = rep->startGCP;
+ event.Nodes = rep->nodes;
+
+ backupId = rep->backupId;
+ return 0;
+ }
+ case GSN_BACKUP_REF:{
+ const BackupRef * const ref =
+ CAST_CONSTPTR(BackupRef, signal->getDataPtr());
+ if(ref->errorCode == BackupRef::IAmNotMaster){
+ nodeId = refToNode(ref->masterRef);
+#ifdef VM_TRACE
+ ndbout_c("I'm not master resending to %d", nodeId);
+#endif
+ do_send = 1; // try again
+ continue;
+ }
+ event.Event = BackupEvent::BackupFailedToStart;
+ event.FailedToStart.ErrorCode = ref->errorCode;
+ return ref->errorCode;
+ }
+ case GSN_BACKUP_ABORT_REP:{
+ const BackupAbortRep * const rep =
+ CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
+ event.Event = BackupEvent::BackupAborted;
+ event.Aborted.Reason = rep->reason;
+ event.Aborted.BackupId = rep->backupId;
+ event.Aborted.ErrorCode = rep->reason;
+#ifdef VM_TRACE
+ ndbout_c("Backup %d aborted", rep->backupId);
+#endif
+ return rep->reason;
+ }
+ case GSN_NF_COMPLETEREP:{
+ const NFCompleteRep * const rep =
+ CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
+#ifdef VM_TRACE
+ ndbout_c("Node %d fail completed", rep->failedNodeId);
+#endif
+ if (rep->failedNodeId == nodeId ||
+ waitCompleted == 1)
+ return 1326;
+ // wait for next signal
+ // master node will report aborted backup
break;
- case BackupEvent::BackupFailedToStart:
- return m_lastBackupEvent.FailedToStart.ErrorCode;
- case BackupEvent::BackupAborted:
- return m_lastBackupEvent.Aborted.ErrorCode;
- default:
- return -1;
+ }
+ case GSN_NODE_FAILREP:{
+ const NodeFailRep * const rep =
+ CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
+ if (NodeBitmask::get(rep->theNodes,nodeId) ||
+ waitCompleted == 1)
+ return 1326;
+ // wait for next signal
+ // master node will report aborted backup
break;
}
+ default:
+ report_unknown_signal(signal);
+ return SEND_OR_RECEIVE_FAILED;
+ }
}
return 0;
@@ -2523,36 +2550,6 @@ MgmtSrvr::abortBackup(Uint32 backupId)
return 0;
}
-void
-MgmtSrvr::backupCallback(BackupEvent & event)
-{
- DBUG_ENTER("MgmtSrvr::backupCallback");
- m_lastBackupEvent = event;
- switch(event.Event){
- case BackupEvent::BackupFailedToStart:
- DBUG_PRINT("info",("BackupEvent::BackupFailedToStart"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupAborted:
- DBUG_PRINT("info",("BackupEvent::BackupAborted"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupCompleted:
- DBUG_PRINT("info",("BackupEvent::BackupCompleted"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupStarted:
- if(theWaitState == WAIT_BACKUP_STARTED)
- {
- DBUG_PRINT("info",("BackupEvent::BackupStarted NO_WAIT"));
- theWaitState = NO_WAIT;
- } else {
- DBUG_PRINT("info",("BackupEvent::BackupStarted"));
- }
- }
- DBUG_VOID_RETURN;
-}
-
/*****************************************************************************
* Global Replication
@@ -2561,7 +2558,7 @@ MgmtSrvr::backupCallback(BackupEvent & event)
int
MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted)
{
- abort();
+ require(false);
return 0;
}
@@ -2715,7 +2712,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
ndbout_c("Updating node %d param: %d to %s", node, param, val_char);
break;
default:
- abort();
+ require(false);
}
assert(res);
} while(node == 0 && iter.next() == 0);
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index c132852338b..f8c244a1bf1 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -757,9 +757,6 @@ private:
static void *signalRecvThread_C(void *);
void signalRecvThreadRun();
- void backupCallback(BackupEvent &);
- BackupEvent m_lastBackupEvent;
-
Config *_props;
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 00cf6390c73..46bfb531b61 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -343,8 +343,6 @@ MgmApiSession::getConfig_old(Parser_t::Context &ctx) {
}
#endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
-inline void require(bool b){ if(!b) abort(); }
-
void
MgmApiSession::getConfig(Parser_t::Context &ctx,
const class Properties &args) {
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
index 9f8a851b995..1ba80ef7d85 100644
--- a/ndb/src/ndbapi/Makefile.am
+++ b/ndb/src/ndbapi/Makefile.am
@@ -35,7 +35,8 @@ libndbapi_la_SOURCES = \
NdbDictionaryImpl.cpp \
DictCache.cpp \
ndb_cluster_connection.cpp \
- NdbBlob.cpp
+ NdbBlob.cpp \
+ SignalSender.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index e1f70160fb7..c9e26f8ccaf 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -280,6 +280,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
+ NdbError savedError= theError;
DBUG_ENTER("NdbConnection::execute");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -309,7 +310,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tPrepOp->theBlobList;
while (tBlob != NULL) {
if (tBlob->preExecute(tExecType, batch) == -1)
+ {
ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
if (batch) {
@@ -338,7 +343,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tOp->theBlobList;
while (tBlob != NULL) {
if (tBlob->preCommit() == -1)
- ret = -1;
+ {
+ ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
}
@@ -360,7 +369,12 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
- ret = -1;
+ {
+ ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
+
#ifdef ndb_api_crash_on_complex_blob_abort
assert(theFirstOpInList == NULL && theLastOpInList == NULL);
#else
@@ -375,7 +389,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
while (tBlob != NULL) {
// may add new operations if batch
if (tBlob->postExecute(tExecType) == -1)
+ {
ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
}
@@ -406,6 +424,10 @@ NdbConnection::execute(ExecType aTypeOfExec,
ndbout << "completed ops: " << n << endl;
}
#endif
+
+ if(savedError.code!=0 && theError.code==4350) // Trans already aborted
+ theError= savedError;
+
DBUG_RETURN(ret);
}
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index a11dd842495..cbb344d3680 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -296,7 +296,8 @@ NdbImpl::NdbImpl(Ndb_cluster_connection *ndb_cluster_connection,
: m_ndb_cluster_connection(ndb_cluster_connection->m_impl),
m_dictionary(ndb),
theCurrentConnectIndex(0),
- theNdbObjectIdMap(1024,1024),
+ theNdbObjectIdMap(ndb_cluster_connection->m_impl.m_transporter_facade->theMutexPtr,
+ 1024,1024),
theNoOfDBnodes(0)
{
int i;
diff --git a/ndb/src/ndbapi/ObjectMap.hpp b/ndb/src/ndbapi/ObjectMap.hpp
index 21407279f0b..c730d1ce6b1 100644
--- a/ndb/src/ndbapi/ObjectMap.hpp
+++ b/ndb/src/ndbapi/ObjectMap.hpp
@@ -30,7 +30,7 @@ class NdbObjectIdMap //: NdbLockable
{
public:
STATIC_CONST( InvalidId = ~(Uint32)0 );
- NdbObjectIdMap(Uint32 initalSize = 128, Uint32 expandSize = 10);
+ NdbObjectIdMap(NdbMutex*, Uint32 initalSize = 128, Uint32 expandSize = 10);
~NdbObjectIdMap();
Uint32 map(void * object);
@@ -46,14 +46,16 @@ private:
void * m_obj;
} * m_map;
+ NdbMutex * m_mutex;
void expand(Uint32 newSize);
};
inline
-NdbObjectIdMap::NdbObjectIdMap(Uint32 sz, Uint32 eSz) {
+NdbObjectIdMap::NdbObjectIdMap(NdbMutex* mutex, Uint32 sz, Uint32 eSz) {
m_size = 0;
m_firstFree = InvalidId;
m_map = 0;
+ m_mutex = mutex;
m_expandSize = eSz;
expand(sz);
#ifdef DEBUG_OBJECTMAP
@@ -131,21 +133,26 @@ NdbObjectIdMap::getObject(Uint32 id){
inline void
NdbObjectIdMap::expand(Uint32 incSize){
+ NdbMutex_Lock(m_mutex);
Uint32 newSize = m_size + incSize;
- MapEntry * tmp = (MapEntry*)malloc(newSize * sizeof(MapEntry));
+ MapEntry * tmp = (MapEntry*)realloc(m_map, newSize * sizeof(MapEntry));
- if (m_map) {
- memcpy(tmp, m_map, m_size * sizeof(MapEntry));
- free((void*)m_map);
+ if (likely(tmp != 0))
+ {
+ m_map = tmp;
+
+ for(Uint32 i = m_size; i<newSize; i++){
+ m_map[i].m_next = i + 1;
+ }
+ m_firstFree = m_size;
+ m_map[newSize-1].m_next = InvalidId;
+ m_size = newSize;
}
- m_map = tmp;
-
- for(Uint32 i = m_size; i<newSize; i++){
- m_map[i].m_next = i + 1;
+ else
+ {
+ ndbout_c("NdbObjectIdMap::expand unable to expand!!");
}
- m_firstFree = m_size;
- m_map[newSize-1].m_next = InvalidId;
- m_size = newSize;
+ NdbMutex_Unlock(m_mutex);
}
#endif
diff --git a/ndb/src/ndbapi/SignalSender.cpp b/ndb/src/ndbapi/SignalSender.cpp
new file mode 100644
index 00000000000..a29fe68937b
--- /dev/null
+++ b/ndb/src/ndbapi/SignalSender.cpp
@@ -0,0 +1,280 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "SignalSender.hpp"
+#include <NdbSleep.h>
+#include <SignalLoggerManager.hpp>
+#include <signaldata/NFCompleteRep.hpp>
+#include <signaldata/NodeFailRep.hpp>
+
+SimpleSignal::SimpleSignal(bool dealloc){
+ memset(this, 0, sizeof(* this));
+ deallocSections = dealloc;
+}
+
+SimpleSignal::~SimpleSignal(){
+ if(!deallocSections)
+ return;
+ if(ptr[0].p != 0) delete []ptr[0].p;
+ if(ptr[1].p != 0) delete []ptr[1].p;
+ if(ptr[2].p != 0) delete []ptr[2].p;
+}
+
+void
+SimpleSignal::set(class SignalSender& ss,
+ Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len){
+
+ header.theTrace = trace;
+ header.theReceiversBlockNumber = recBlock;
+ header.theVerId_signalNumber = gsn;
+ header.theLength = len;
+ header.theSendersBlockRef = refToBlock(ss.getOwnRef());
+}
+
+void
+SimpleSignal::print(FILE * out){
+ fprintf(out, "---- Signal ----------------\n");
+ SignalLoggerManager::printSignalHeader(out, header, 0, 0, false);
+ SignalLoggerManager::printSignalData(out, header, theData);
+ for(Uint32 i = 0; i<header.m_noOfSections; i++){
+ Uint32 len = ptr[i].sz;
+ fprintf(out, " --- Section %d size=%d ---\n", i, len);
+ Uint32 * signalData = ptr[i].p;
+ while(len >= 7){
+ fprintf(out,
+ " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
+ signalData[0], signalData[1], signalData[2], signalData[3],
+ signalData[4], signalData[5], signalData[6]);
+ len -= 7;
+ signalData += 7;
+ }
+ if(len > 0){
+ fprintf(out, " H\'%.8x", signalData[0]);
+ for(Uint32 i = 1; i<len; i++)
+ fprintf(out, " H\'%.8x", signalData[i]);
+ fprintf(out, "\n");
+ }
+ }
+}
+
+SignalSender::SignalSender(TransporterFacade *facade)
+ : m_lock(0)
+{
+ m_cond = NdbCondition_Create();
+ theFacade = facade;
+ m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
+ assert(m_blockNo > 0);
+}
+
+SignalSender::~SignalSender(){
+ int i;
+ if (m_lock)
+ unlock();
+ theFacade->close(m_blockNo,0);
+ // free these _after_ closing theFacade to ensure that
+ // we delete all signals
+ for (i= m_jobBuffer.size()-1; i>= 0; i--)
+ delete m_jobBuffer[i];
+ for (i= m_usedBuffer.size()-1; i>= 0; i--)
+ delete m_usedBuffer[i];
+ NdbCondition_Destroy(m_cond);
+}
+
+int SignalSender::lock()
+{
+ if (NdbMutex_Lock(theFacade->theMutexPtr))
+ return -1;
+ m_lock= 1;
+ return 0;
+}
+
+int SignalSender::unlock()
+{
+ if (NdbMutex_Unlock(theFacade->theMutexPtr))
+ return -1;
+ m_lock= 0;
+ return 0;
+}
+
+Uint32
+SignalSender::getOwnRef() const {
+ return numberToRef(m_blockNo, theFacade->ownId());
+}
+
+Uint32
+SignalSender::getAliveNode() const{
+ return theFacade->get_an_alive_node();
+}
+
+const ClusterMgr::Node &
+SignalSender::getNodeInfo(Uint16 nodeId) const {
+ return theFacade->theClusterMgr->getNodeInfo(nodeId);
+}
+
+Uint32
+SignalSender::getNoOfConnectedNodes() const {
+ return theFacade->theClusterMgr->getNoOfConnectedNodes();
+}
+
+SendStatus
+SignalSender::sendSignal(Uint16 nodeId, const SimpleSignal * s){
+ return theFacade->theTransporterRegistry->prepareSend(&s->header,
+ 1, // JBB
+ &s->theData[0],
+ nodeId,
+ &s->ptr[0]);
+}
+
+template<class T>
+SimpleSignal *
+SignalSender::waitFor(Uint32 timeOutMillis, T & t)
+{
+ SimpleSignal * s = t.check(m_jobBuffer);
+ if(s != 0){
+ return s;
+ }
+
+ NDB_TICKS now = NdbTick_CurrentMillisecond();
+ NDB_TICKS stop = now + timeOutMillis;
+ Uint32 wait = (timeOutMillis == 0 ? 10 : timeOutMillis);
+ do {
+ NdbCondition_WaitTimeout(m_cond,
+ theFacade->theMutexPtr,
+ wait);
+
+
+ SimpleSignal * s = t.check(m_jobBuffer);
+ if(s != 0){
+ m_usedBuffer.push_back(s);
+ return s;
+ }
+
+ now = NdbTick_CurrentMillisecond();
+ wait = (timeOutMillis == 0 ? 10 : stop - now);
+ } while(stop > now || timeOutMillis == 0);
+
+ return 0;
+}
+
+class WaitForAny {
+public:
+ SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
+ if(m_jobBuffer.size() > 0){
+ SimpleSignal * s = m_jobBuffer[0];
+ m_jobBuffer.erase(0);
+ return s;
+ }
+ return 0;
+ }
+};
+
+SimpleSignal *
+SignalSender::waitFor(Uint32 timeOutMillis){
+
+ WaitForAny w;
+ return waitFor(timeOutMillis, w);
+}
+
+class WaitForNode {
+public:
+ Uint32 m_nodeId;
+ SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
+ Uint32 len = m_jobBuffer.size();
+ for(Uint32 i = 0; i<len; i++){
+ if(refToNode(m_jobBuffer[i]->header.theSendersBlockRef) == m_nodeId){
+ SimpleSignal * s = m_jobBuffer[i];
+ m_jobBuffer.erase(i);
+ return s;
+ }
+ }
+ return 0;
+ }
+};
+
+SimpleSignal *
+SignalSender::waitFor(Uint16 nodeId, Uint32 timeOutMillis){
+
+ WaitForNode w;
+ w.m_nodeId = nodeId;
+ return waitFor(timeOutMillis, w);
+}
+
+#include <NdbApiSignal.hpp>
+
+void
+SignalSender::execSignal(void* signalSender,
+ NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]){
+ SimpleSignal * s = new SimpleSignal(true);
+ s->header = * signal;
+ memcpy(&s->theData[0], signal->getDataPtr(), 4 * s->header.theLength);
+ for(Uint32 i = 0; i<s->header.m_noOfSections; i++){
+ s->ptr[i].p = new Uint32[ptr[i].sz];
+ s->ptr[i].sz = ptr[i].sz;
+ memcpy(s->ptr[i].p, ptr[i].p, 4 * ptr[i].sz);
+ }
+ SignalSender * ss = (SignalSender*)signalSender;
+ ss->m_jobBuffer.push_back(s);
+ NdbCondition_Signal(ss->m_cond);
+}
+
+void
+SignalSender::execNodeStatus(void* signalSender,
+ Uint32 nodeId,
+ bool alive,
+ bool nfCompleted){
+ if (alive) {
+ // node connected
+ return;
+ }
+
+ SimpleSignal * s = new SimpleSignal(true);
+ SignalSender * ss = (SignalSender*)signalSender;
+
+ // node disconnected
+ if(nfCompleted)
+ {
+ // node shutdown complete
+ s->header.theVerId_signalNumber = GSN_NF_COMPLETEREP;
+ NFCompleteRep *rep = (NFCompleteRep *)s->getDataPtrSend();
+ rep->blockNo = 0;
+ rep->nodeId = 0;
+ rep->failedNodeId = nodeId;
+ rep->unused = 0;
+ rep->from = 0;
+ }
+ else
+ {
+ // node failure
+ s->header.theVerId_signalNumber = GSN_NODE_FAILREP;
+ NodeFailRep *rep = (NodeFailRep *)s->getDataPtrSend();
+ rep->failNo = 0;
+ rep->masterNodeId = 0;
+ rep->noOfNodes = 1;
+ NodeBitmask::clear(rep->theNodes);
+ NodeBitmask::set(rep->theNodes,nodeId);
+ }
+
+ ss->m_jobBuffer.push_back(s);
+ NdbCondition_Signal(ss->m_cond);
+}
+
+#if __SUNPRO_CC != 0x560
+template SimpleSignal* SignalSender::waitFor<WaitForNode>(unsigned, WaitForNode&);
+template SimpleSignal* SignalSender::waitFor<WaitForAny>(unsigned, WaitForAny&);
+#endif
+template class Vector<SimpleSignal*>;
+
diff --git a/ndb/src/ndbapi/SignalSender.hpp b/ndb/src/ndbapi/SignalSender.hpp
new file mode 100644
index 00000000000..4b991460034
--- /dev/null
+++ b/ndb/src/ndbapi/SignalSender.hpp
@@ -0,0 +1,83 @@
+/* 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 SIGNAL_SENDER_HPP
+#define SIGNAL_SENDER_HPP
+
+#include <ndb_global.h>
+#include "TransporterFacade.hpp"
+#include <Vector.hpp>
+
+struct SimpleSignal {
+public:
+ SimpleSignal(bool dealloc = false);
+ ~SimpleSignal();
+
+ void set(class SignalSender&,
+ Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len);
+
+ struct SignalHeader header;
+ Uint32 theData[25];
+ LinearSectionPtr ptr[3];
+
+ int readSignalNumber() {return header.theVerId_signalNumber; }
+ Uint32 *getDataPtrSend() { return theData; }
+ const Uint32 *getDataPtr() const { return theData; }
+
+ void print(FILE * out = stdout);
+private:
+ bool deallocSections;
+};
+
+class SignalSender {
+public:
+ SignalSender(TransporterFacade *facade);
+ virtual ~SignalSender();
+
+ int lock();
+ int unlock();
+
+ Uint32 getOwnRef() const;
+ Uint32 getAliveNode() const;
+ const ClusterMgr::Node &getNodeInfo(Uint16 nodeId) const;
+ Uint32 getNoOfConnectedNodes() const;
+
+ SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
+
+ SimpleSignal * waitFor(Uint32 timeOutMillis = 0);
+ SimpleSignal * waitFor(Uint16 nodeId, Uint32 timeOutMillis = 0);
+ SimpleSignal * waitFor(Uint16 nodeId, Uint16 gsn, Uint32 timeOutMillis = 0);
+private:
+ int m_blockNo;
+ TransporterFacade * theFacade;
+
+ static void execSignal(void* signalSender,
+ NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]);
+
+ static void execNodeStatus(void* signalSender, Uint32 nodeId,
+ bool alive, bool nfCompleted);
+
+ int m_lock;
+ struct NdbCondition * m_cond;
+ Vector<SimpleSignal *> m_jobBuffer;
+ Vector<SimpleSignal *> m_usedBuffer;
+
+ template<class T>
+ SimpleSignal * waitFor(Uint32 timeOutMillis, T & t);
+};
+
+#endif
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index a60228c1a5d..bcaa0bf4d40 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -64,7 +64,8 @@ public:
const char* getPropertyWait(const char*, const char* );
void decProperty(const char *);
-
+ void incProperty(const char *);
+
// Communicate with other tests
void stopTest();
bool isTestStopped();
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 6f04ac3fce2..7b4a96f5890 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -31,7 +31,8 @@ testTimeout \
testTransactions \
testDeadlock \
test_event ndbapi_slow_select testReadPerf testLcp \
-DbCreate DbAsyncGenerator
+DbCreate DbAsyncGenerator \
+testSRBank
#flexTimedAsynch
#testBlobs
@@ -72,6 +73,7 @@ testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp
DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
+testSRBank_SOURCES = testSRBank.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
@@ -83,6 +85,7 @@ include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testTransactions_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
testBackup_LDADD = $(LDADD) bank/libbank.a
+testSRBank_LDADD = bank/libbank.a $(LDADD)
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/test/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp
index c6029259357..346442367fc 100644
--- a/ndb/test/ndbapi/bank/Bank.cpp
+++ b/ndb/test/ndbapi/bank/Bank.cpp
@@ -19,12 +19,13 @@
#include <NdbSleep.h>
#include <UtilTransactions.hpp>
-Bank::Bank():
+Bank::Bank(bool _init):
m_ndb("BANK"),
m_maxAccount(-1),
m_initialized(false)
{
-
+ if(_init)
+ init();
}
int Bank::init(){
@@ -34,40 +35,39 @@ int Bank::init(){
myRandom48Init(NdbTick_CurrentMillisecond());
m_ndb.init();
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
+ if (m_ndb.waitUntilReady(30) != 0)
+ {
+ ndbout << "Ndb not ready" << endl;
+ return NDBT_FAILED;
+ }
+
if (getNumAccounts() != NDBT_OK)
return NDBT_FAILED;
+
+ m_initialized = true;
return NDBT_OK;
}
int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int transactions = 0;
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(performTransaction() != NDBT_FAILED){
- transactions++;
-
- if (maxSleepBetweenTrans > 0){
- int val = myRandom48(maxSleepBetweenTrans);
- NdbSleep_MilliSleep(val);
- }
-
- if((transactions % 100) == 0)
- g_info << transactions << endl;
-
- if (yield != 0 && transactions >= yield)
- return NDBT_OK;
+ while(performTransaction() == NDBT_OK)
+ {
+ transactions++;
+
+ if (maxSleepBetweenTrans > 0){
+ int val = myRandom48(maxSleepBetweenTrans);
+ NdbSleep_MilliSleep(val);
}
+
+ if((transactions % 100) == 0)
+ g_info << transactions << endl;
+
+ if (yield != 0 && transactions >= yield)
+ return NDBT_OK;
}
+
return NDBT_FAILED;
}
@@ -92,7 +92,7 @@ int Bank::performTransaction(){
int amount = myRandom48(maxAmount);
- retry_transaction:
+retry_transaction:
int res = performTransaction(fromAccount, toAccount, amount);
if (res != 0){
switch (res){
@@ -158,8 +158,9 @@ int Bank::performTransactionImpl1(int fromAccountId,
// Ok, all clear to do the transaction
Uint64 transId;
- if (getNextTransactionId(transId) != NDBT_OK){
- return NDBT_FAILED;
+ int result = NDBT_OK;
+ if ((result= getNextTransactionId(transId)) != NDBT_OK){
+ return result;
}
NdbConnection* pTrans = m_ndb.startTransaction();
@@ -500,8 +501,6 @@ int Bank::performTransactionImpl1(int fromAccountId,
int Bank::performMakeGLs(int yield){
int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int counter, maxCounter;
int yieldCounter = 0;
@@ -512,9 +511,6 @@ int Bank::performMakeGLs(int yield){
counter = 0;
maxCounter = 50 + myRandom48(100);
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
/**
* Validate GLs and Transactions for previous days
*
@@ -526,6 +522,7 @@ int Bank::performMakeGLs(int yield){
return NDBT_FAILED;
}
g_info << "performValidateGLs failed" << endl;
+ return NDBT_FAILED;
continue;
}
@@ -536,7 +533,7 @@ int Bank::performMakeGLs(int yield){
return NDBT_FAILED;
}
g_info << "performValidatePurged failed" << endl;
- continue;
+ return NDBT_FAILED;
}
while (1){
@@ -607,14 +604,9 @@ int Bank::performMakeGLs(int yield){
int Bank::performValidateAllGLs(){
int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
while (1){
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
/**
* Validate GLs and Transactions for previous days
* Set age so that ALL GL's are validated
@@ -1937,39 +1929,29 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
}
- int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
+int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield)
+{
int yieldCounter = 0;
-
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(1){
-
- Uint64 currTime;
- if (incCurrTime(currTime) != NDBT_OK)
- break;
-
- g_info << "Current time is " << currTime << endl;
- if (maxSleepBetweenDays > 0){
- int val = myRandom48(maxSleepBetweenDays);
- NdbSleep_SecSleep(val);
- }
-
- yieldCounter++;
- if (yield != 0 && yieldCounter >= yield)
- return NDBT_OK;
-
- }
- }
- return NDBT_FAILED;
- }
-
-
+
+ while(1){
+
+ Uint64 currTime;
+ if (incCurrTime(currTime) != NDBT_OK)
+ break;
+
+ g_info << "Current time is " << currTime << endl;
+ if (maxSleepBetweenDays > 0){
+ int val = myRandom48(maxSleepBetweenDays);
+ NdbSleep_SecSleep(val);
+ }
+
+ yieldCounter++;
+ if (yield != 0 && yieldCounter >= yield)
+ return NDBT_OK;
+
+ }
+ return NDBT_FAILED;
+}
int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
@@ -1978,22 +1960,30 @@ int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if(m_ndb.getNdbError().status == NdbError::TemporaryError)
+ return NDBT_TEMPORARY;
return NDBT_FAILED;
}
- if (prepareReadSystemValueOp(pTrans, sysValId, value) != NDBT_OK) {
+ int result;
+ if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK) {
ERR(pTrans->getNdbError());
m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
+ return result;
}
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if(pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_TEMPORARY;
+ }
m_ndb.closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
m_ndb.closeTransaction(pTrans);
return NDBT_OK;
@@ -2099,6 +2089,8 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if (m_ndb.getNdbError().status == NdbError::TemporaryError)
+ DBUG_RETURN(NDBT_TEMPORARY);
DBUG_RETURN(NDBT_FAILED);
}
@@ -2134,6 +2126,11 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if (pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ DBUG_RETURN(NDBT_TEMPORARY);
+ }
m_ndb.closeTransaction(pTrans);
DBUG_RETURN(NDBT_FAILED);
}
@@ -2208,16 +2205,21 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if (pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ DBUG_RETURN(NDBT_TEMPORARY);
+ }
m_ndb.closeTransaction(pTrans);
DBUG_RETURN(NDBT_FAILED);
}
// Check that value updated equals the value we read after the update
if (valueNewRec->u_64_value() != value){
-
+
printf("value actual=%lld\n", valueNewRec->u_64_value());
printf("value expected=%lld actual=%lld\n", value, valueNewRec->u_64_value());
-
+
DBUG_PRINT("info", ("value expected=%ld actual=%ld", value, valueNewRec->u_64_value()));
g_err << "getNextTransactionId: value was not updated" << endl;
m_ndb.closeTransaction(pTrans);
@@ -2225,7 +2227,7 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
}
m_ndb.closeTransaction(pTrans);
-
+
DBUG_RETURN(0);
}
@@ -2242,6 +2244,8 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if(m_ndb.getNdbError().status == NdbError::TemporaryError)
+ return NDBT_TEMPORARY;
return NDBT_FAILED;
}
@@ -2284,6 +2288,11 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if(pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_TEMPORARY;
+ }
m_ndb.closeTransaction(pTrans);
return NDBT_FAILED;
}
@@ -2308,16 +2317,11 @@ int Bank::prepareGetCurrTimeOp(NdbConnection *pTrans, Uint64 &time){
int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int yieldCounter = 0;
while (1){
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
Uint32 sumAccounts = 0;
Uint32 numAccounts = 0;
if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
diff --git a/ndb/test/ndbapi/bank/Bank.hpp b/ndb/test/ndbapi/bank/Bank.hpp
index 34c5ff51cc2..14e01df29d5 100644
--- a/ndb/test/ndbapi/bank/Bank.hpp
+++ b/ndb/test/ndbapi/bank/Bank.hpp
@@ -27,7 +27,7 @@
class Bank {
public:
- Bank();
+ Bank(bool init = true);
int createAndLoadBank(bool overWrite, int num_accounts=10);
int dropBank();
diff --git a/ndb/test/ndbapi/testSRBank.cpp b/ndb/test/ndbapi/testSRBank.cpp
new file mode 100644
index 00000000000..5677f551da6
--- /dev/null
+++ b/ndb/test/ndbapi/testSRBank.cpp
@@ -0,0 +1,246 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbBackup.hpp>
+
+#include "bank/Bank.hpp"
+
+int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int overWriteExisting = true;
+ if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+/**
+ *
+ * SR 0 - normal
+ * SR 1 - shutdown in progress
+ * SR 2 - restart in progress
+ */
+int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
+ int wait = 5; // Max seconds between each "day"
+ int yield = 1; // Loops before bank returns
+
+ ctx->incProperty("ThreadCount");
+ while (!ctx->isTestStopped())
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if(bank.performIncreaseTime(wait, yield) == NDBT_FAILED)
+ break;
+
+ ndbout_c("runBankTimer is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
+ int wait = 0; // Max ms between each transaction
+ int yield = 1; // Loops before bank returns
+
+ ctx->incProperty("ThreadCount");
+ while (!ctx->isTestStopped())
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if(bank.performTransactions(0, 1) == NDBT_FAILED)
+ break;
+
+ ndbout_c("runBankTransactions is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ ctx->incProperty("ThreadCount");
+ while (ctx->isTestStopped() == false)
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if (bank.performMakeGLs(yield) != NDBT_OK)
+ {
+ if(ctx->getProperty("SR") != 0)
+ break;
+ ndbout << "bank.performMakeGLs FAILED" << endl;
+ return NDBT_FAILED;
+ }
+
+ ndbout_c("runBankGL is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 2000; // Max ms between each sum of accounts
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performSumAccounts(wait, yield) != NDBT_OK){
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return result ;
+}
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+int runSR(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int result = NDBT_OK;
+ int runtime = ctx->getNumLoops();
+ int sleeptime = ctx->getNumRecords();
+ NdbRestarter restarter;
+ bool abort = true;
+ int timeout = 180;
+
+ Uint32 now;
+ const Uint32 stop = time(0)+ runtime;
+ while(!ctx->isTestStopped() && ((now= time(0)) < stop) && result == NDBT_OK)
+ {
+ ndbout << " -- Sleep " << sleeptime << "s " << endl;
+ NdbSleep_SecSleep(sleeptime);
+ ndbout << " -- Shutting down " << endl;
+ ctx->setProperty("SR", 1);
+ CHECK(restarter.restartAll(false, true, abort) == 0);
+ ctx->setProperty("SR", 2);
+ CHECK(restarter.waitClusterNoStart(timeout) == 0);
+
+ Uint32 cnt = ctx->getProperty("ThreadCount");
+ Uint32 curr= ctx->getProperty("ThreadStopped");
+ while(curr != cnt)
+ {
+ ndbout_c("%d %d", curr, cnt);
+ NdbSleep_MilliSleep(100);
+ curr= ctx->getProperty("ThreadStopped");
+ }
+
+ ctx->setProperty("ThreadStopped", (Uint32)0);
+ CHECK(restarter.startAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+
+ ndbout << " -- Validating starts " << endl;
+ {
+ int wait = 0;
+ int yield = 1;
+ Bank bank;
+ if (bank.performSumAccounts(wait, yield) != 0)
+ {
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ return NDBT_FAILED;
+ }
+
+ if (bank.performValidateAllGLs() != 0)
+ {
+ ndbout << "bank.performValidateAllGLs FAILED" << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ ndbout << " -- Validating complete " << endl;
+ ctx->setProperty("SR", (Uint32)0);
+ ctx->broadcast();
+ }
+ ctx->stopTest();
+ return NDBT_OK;
+}
+
+int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ if (bank.dropBank() != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+
+NDBT_TESTSUITE(testSRBank);
+TESTCASE("Graceful",
+ " Test that a consistent bank is restored after graceful shutdown\n"
+ "1. Create bank\n"
+ "2. Start bank and let it run\n"
+ "3. Restart ndb and verify consistency\n"
+ "4. Drop bank\n")
+{
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ STEP(runSR);
+}
+TESTCASE("Abort",
+ " Test that a consistent bank is restored after graceful shutdown\n"
+ "1. Create bank\n"
+ "2. Start bank and let it run\n"
+ "3. Restart ndb and verify consistency\n"
+ "4. Drop bank\n")
+{
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ STEP(runSR);
+ FINALIZER(runDropBank);
+}
+NDBT_TESTSUITE_END(testSRBank);
+
+int main(int argc, const char** argv){
+ ndb_init();
+ return testSRBank.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 600a5443f40..6355c21c997 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -145,6 +145,15 @@ NDBT_Context::decProperty(const char * name){
NdbCondition_Broadcast(propertyCondPtr);
NdbMutex_Unlock(propertyMutexPtr);
}
+void
+NDBT_Context::incProperty(const char * name){
+ NdbMutex_Lock(propertyMutexPtr);
+ Uint32 val = 0;
+ props.get(name, &val);
+ props.put(name, (val + 1), true);
+ NdbCondition_Broadcast(propertyCondPtr);
+ NdbMutex_Unlock(propertyMutexPtr);
+}
void NDBT_Context::setProperty(const char* _name, const char* _val){
NdbMutex_Lock(propertyMutexPtr);
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 28724323bd7..1e56db83c11 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -50,14 +50,17 @@ NdbBackup::start(unsigned int & _backup_id){
2, // wait until completed
&_backup_id,
&reply) == -1) {
- g_err << "Could not start backup " << endl;
- g_err << "Error: " << reply.message << endl;
+ g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
+ g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
+ g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return -1;
}
if(reply.return_code != 0){
g_err << "PLEASE CHECK CODE NdbBackup.cpp line=" << __LINE__ << endl;
- g_err << "Error: " << reply.message << endl;
+ g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
+ g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
+ g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return reply.return_code;
}
return 0;
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 869f7fc76cb..92073143d34 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -766,19 +766,29 @@ UtilTransactions::selectCount(Ndb* pNdb,
int check;
NdbScanOperation *pOp;
- if(!pTrans)
- pTrans = pNdb->startTransaction();
while (true){
-
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
+ if(!pTrans)
+ pTrans = pNdb->startTransaction();
+
+ if(!pTrans)
+ {
+ const NdbError err = pNdb->getNdbError();
+
+ if (err.status == NdbError::TemporaryError)
+ continue;
+ return NDBT_FAILED;
+ }
+
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -786,6 +796,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( rs == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -799,6 +810,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
}
@@ -808,6 +820,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -823,16 +836,19 @@ UtilTransactions::selectCount(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
if (count_rows != NULL){
*count_rows = rows;
diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am
index 89830129576..795441380a8 100644
--- a/ndb/tools/Makefile.am
+++ b/ndb/tools/Makefile.am
@@ -30,7 +30,7 @@ ndb_restore_SOURCES = restore/restore_main.cpp \
restore/consumer.cpp \
restore/consumer_restore.cpp \
restore/consumer_printer.cpp \
- restore/Restore.cpp
+ restore/Restore.cpp $(tools_common_sources)
ndb_config_SOURCES = ndb_config.cpp \
../src/mgmsrv/Config.cpp \
diff --git a/ndb/tools/ndb_config.cpp b/ndb/tools/ndb_config.cpp
index d188aec1337..725249a5af5 100644
--- a/ndb/tools/ndb_config.cpp
+++ b/ndb/tools/ndb_config.cpp
@@ -42,6 +42,7 @@ static const char * g_field_delimiter=",";
static const char * g_row_delimiter=" ";
int g_print_full_config, opt_ndb_shm;
+my_bool opt_core;
typedef ndb_mgm_configuration_iterator Iter;
diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp
index d782a561e6a..70ea7460d78 100644
--- a/ndb/tools/restore/consumer_restore.cpp
+++ b/ndb/tools/restore/consumer_restore.cpp
@@ -14,9 +14,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <NDBT_ReturnCodes.h>
#include "consumer_restore.hpp"
#include <NdbSleep.h>
+extern my_bool opt_core;
+
extern FilteredNdbOut err;
extern FilteredNdbOut info;
extern FilteredNdbOut debug;
@@ -458,7 +461,11 @@ bool BackupRestore::errorHandler(restore_callback_t *cb)
void BackupRestore::exitHandler()
{
release();
- exit(-1);
+ NDBT_ProgramExit(NDBT_FAILED);
+ if (opt_core)
+ abort();
+ else
+ exit(NDBT_FAILED);
}
@@ -492,7 +499,7 @@ BackupRestore::logEntry(const LogEntry & tup)
{
// Deep shit, TODO: handle the error
err << "Cannot start transaction" << endl;
- exit(-1);
+ exitHandler();
} // if
const NdbDictionary::Table * table = get_table(tup.m_table->m_dictTable);
@@ -500,7 +507,7 @@ BackupRestore::logEntry(const LogEntry & tup)
if (op == NULL)
{
err << "Cannot get operation: " << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
} // if
int check = 0;
@@ -518,13 +525,13 @@ BackupRestore::logEntry(const LogEntry & tup)
default:
err << "Log entry has wrong operation type."
<< " Exiting...";
- exit(-1);
+ exitHandler();
}
if (check != 0)
{
err << "Error defining op: " << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
} // if
Bitmask<4096> keys;
@@ -553,7 +560,7 @@ BackupRestore::logEntry(const LogEntry & tup)
if (check != 0)
{
err << "Error defining op: " << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
} // if
}
@@ -582,7 +589,7 @@ BackupRestore::logEntry(const LogEntry & tup)
if (!ok)
{
err << "execute failed: " << errobj << endl;
- exit(-1);
+ exitHandler();
}
}
@@ -629,7 +636,7 @@ BackupRestore::tuple(const TupleS & tup)
{
// Deep shit, TODO: handle the error
ndbout << "Cannot start transaction" << endl;
- exit(-1);
+ exitHandler();
} // if
const TableS * table = tup.getTable();
@@ -638,7 +645,7 @@ BackupRestore::tuple(const TupleS & tup)
{
ndbout << "Cannot get operation: ";
ndbout << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
} // if
// TODO: check return value and handle error
@@ -646,7 +653,7 @@ BackupRestore::tuple(const TupleS & tup)
{
ndbout << "writeTuple call failed: ";
ndbout << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
} // if
for (int i = 0; i < tup.getNoOfAttributes(); i++)
@@ -680,7 +687,7 @@ BackupRestore::tuple(const TupleS & tup)
{
ndbout << "execute failed: ";
ndbout << trans->getNdbError() << endl;
- exit(-1);
+ exitHandler();
}
m_ndb->closeTransaction(trans);
if (ret == 0)
diff --git a/ndb/tools/restore/restore_main.cpp b/ndb/tools/restore/restore_main.cpp
index 0c4419bb072..d786dffe89e 100644
--- a/ndb/tools/restore/restore_main.cpp
+++ b/ndb/tools/restore/restore_main.cpp
@@ -20,6 +20,7 @@
#include <ndb_limits.h>
#include <NdbTCP.h>
#include <NdbOut.hpp>
+#include <NDBT_ReturnCodes.h>
#include "consumer_restore.hpp"
#include "consumer_printer.hpp"
@@ -116,14 +117,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (ga_nodeId == 0)
{
printf("Error in --nodeid,-n setting, see --help\n");
- exit(1);
+ exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
break;
case 'b':
if (ga_backupId == 0)
{
printf("Error in --backupid,-b setting, see --help\n");
- exit(1);
+ exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
break;
}
@@ -136,7 +137,7 @@ readArguments(int *pargc, char*** pargv)
load_defaults("my",load_default_groups,pargc,pargv);
if (handle_options(pargc, pargv, my_long_options, get_one_option))
{
- exit(1);
+ exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
BackupPrinter* printer = new BackupPrinter();
@@ -226,6 +227,15 @@ free_data_callback()
g_consumers[i]->tuple_free();
}
+static void exitHandler(int code)
+{
+ NDBT_ProgramExit(code);
+ if (opt_core)
+ abort();
+ else
+ exit(code);
+}
+
int
main(int argc, char** argv)
{
@@ -233,7 +243,7 @@ main(int argc, char** argv)
if (!readArguments(&argc, &argv))
{
- return -1;
+ exitHandler(NDBT_FAILED);
}
Ndb::setConnectString(opt_connect_str);
@@ -245,7 +255,7 @@ main(int argc, char** argv)
if (!metaData.readHeader())
{
ndbout << "Failed to read " << metaData.getFilename() << endl << endl;
- return -1;
+ exitHandler(NDBT_FAILED);
}
const BackupFormat::FileHeader & tmp = metaData.getFileHeader();
@@ -263,20 +273,20 @@ main(int argc, char** argv)
if (res == 0)
{
ndbout_c("Restore: Failed to load content");
- return -1;
+ exitHandler(NDBT_FAILED);
}
if (metaData.getNoOfTables() == 0)
{
ndbout_c("Restore: The backup contains no tables ");
- return -1;
+ exitHandler(NDBT_FAILED);
}
if (!metaData.validateFooter())
{
ndbout_c("Restore: Failed to validate footer.");
- return -1;
+ exitHandler(NDBT_FAILED);
}
Uint32 i;
@@ -285,7 +295,7 @@ main(int argc, char** argv)
if (!g_consumers[i]->init())
{
clearConsumers();
- return -11;
+ exitHandler(NDBT_FAILED);
}
}
@@ -300,7 +310,7 @@ main(int argc, char** argv)
ndbout_c("Restore: Failed to restore table: %s. "
"Exiting...",
metaData[i]->getTableName());
- return -11;
+ exitHandler(NDBT_FAILED);
}
}
}
@@ -309,7 +319,7 @@ main(int argc, char** argv)
if (!g_consumers[i]->endOfTables())
{
ndbout_c("Restore: Failed while closing tables");
- return -11;
+ exitHandler(NDBT_FAILED);
}
if (ga_restore || ga_print)
@@ -322,7 +332,7 @@ main(int argc, char** argv)
if (!dataIter.readHeader())
{
ndbout << "Failed to read header of data file. Exiting..." ;
- return -11;
+ exitHandler(NDBT_FAILED);
}
@@ -340,12 +350,12 @@ main(int argc, char** argv)
{
ndbout_c("Restore: An error occured while restoring data. "
"Exiting...");
- return -1;
+ exitHandler(NDBT_FAILED);
}
if (!dataIter.validateFragmentFooter()) {
ndbout_c("Restore: Error validating fragment footer. "
"Exiting...");
- return -1;
+ exitHandler(NDBT_FAILED);
}
} // while (dataIter.readFragmentHeader(res))
@@ -353,7 +363,7 @@ main(int argc, char** argv)
{
err << "Restore: An error occured while restoring data. Exiting... "
<< "res=" << res << endl;
- return -1;
+ exitHandler(NDBT_FAILED);
}
@@ -366,7 +376,7 @@ main(int argc, char** argv)
if (!logIter.readHeader())
{
err << "Failed to read header of data file. Exiting..." << endl;
- return -1;
+ exitHandler(NDBT_FAILED);
}
const LogEntry * logEntry = 0;
@@ -380,7 +390,7 @@ main(int argc, char** argv)
{
err << "Restore: An restoring the data log. Exiting... res="
<< res << endl;
- return -1;
+ exitHandler(NDBT_FAILED);
}
logIter.validateFooter(); //not implemented
for (i= 0; i < g_consumers.size(); i++)
@@ -395,14 +405,14 @@ main(int argc, char** argv)
ndbout_c("Restore: Failed to finalize restore table: %s. "
"Exiting...",
metaData[i]->getTableName());
- return -11;
+ exitHandler(NDBT_FAILED);
}
}
}
}
}
clearConsumers();
- return 0;
+ return NDBT_ProgramExit(NDBT_OK);
} // main
template class Vector<BackupConsumer*>;
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index ba46fd6fa29..7fff4cbb731 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -289,8 +289,10 @@ sub start_mysqlds()
}
else
{
- $options[$j]=~ s/;/\\;/g;
- $tmp.= " $options[$j]";
+ # we single-quote the argument, but first convert single-quotes to
+ # '"'"' so they are passed through correctly
+ $options[$j]=~ s/'/'"'"'/g;
+ $tmp.= " '$options[$j]'";
}
}
if ($opt_verbose && $com =~ m/\/safe_mysqld$/ && !$info_sent)
@@ -374,7 +376,12 @@ sub get_mysqladmin_options
$mysqladmin_found= 0 if (!length($mysqladmin));
$com = "$mysqladmin";
$tmp = " -u $opt_user";
- $tmp.= defined($opt_password) ? " -p$opt_password" : "";
+ if (defined($opt_password)) {
+ my $pw= $opt_password;
+ # Protect single quotes in password
+ $pw =~ s/'/'"'"'/g;
+ $tmp.= " -p'$pw'";
+ }
$tmp.= $opt_tcp_ip ? " -h 127.0.0.1" : "";
for ($j = 0; defined($options[$j]); $j++)
{
diff --git a/sql-common/client.c b/sql-common/client.c
index 73e136f7366..3979b9304f7 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -602,7 +602,7 @@ net_safe_read(MYSQL *mysql)
DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
vio_description(net->vio),len));
#ifdef MYSQL_SERVER
- if (vio_errno(net->vio) == SOCKET_EINTR)
+ if (vio_was_interrupted(net->vio))
return (packet_error);
#endif /*MYSQL_SERVER*/
end_server(mysql);
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index 577ead8a86d..ee4cad25460 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -520,7 +520,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
error= my_errno;
goto error;
}
- if ((archive= gzdopen(create_file, "ab")) == NULL)
+ if ((archive= gzdopen(create_file, "wb")) == NULL)
{
error= errno;
goto error2;
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index bbcdfb0dafb..8a9aa91c680 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -609,7 +609,8 @@ int ha_tina::rnd_init(bool scan)
records= 0;
chain_ptr= chain;
#ifdef HAVE_MADVISE
- (void)madvise(share->mapped_file,share->file_stat.st_size,MADV_SEQUENTIAL);
+ if (scan)
+ (void)madvise(share->mapped_file,share->file_stat.st_size,MADV_SEQUENTIAL);
#endif
DBUG_RETURN(0);
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 75b114fc140..63a8515020b 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -443,7 +443,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
ha_store_ptr(ref_pos,ref_length,record); // Position to row
record+=sort_form->db_record_offset;
}
- else
+ else if (!error)
file->position(sort_form->record[0]);
}
if (error && error != HA_ERR_RECORD_DELETED)
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 39223556024..32e1d84fac3 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -130,15 +130,23 @@ void reset_host_errors(struct in_addr *in)
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
+/* Deal with systems that don't defined INADDR_LOOPBACK */
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
my_string ip_to_hostname(struct in_addr *in, uint *errors)
{
uint i;
host_entry *entry;
DBUG_ENTER("ip_to_hostname");
+ *errors= 0;
+
+ /* We always treat the loopback address as "localhost". */
+ if (in->s_addr == htonl(INADDR_LOOPBACK))
+ DBUG_RETURN((char *)my_localhost);
/* Check first if we have name in cache */
- *errors=0;
if (!(specialflag & SPECIAL_NO_HOST_CACHE))
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
diff --git a/sql/item.cc b/sql/item.cc
index 7aaa678ddb0..010189c321c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1973,14 +1973,7 @@ void Item::make_field(Send_field *tmp_field)
void Item_empty_string::make_field(Send_field *tmp_field)
{
- enum_field_types type = FIELD_TYPE_VAR_STRING;
- if (max_length >= 16777216)
- type = FIELD_TYPE_LONG_BLOB;
- else if (max_length >= 65536)
- type = FIELD_TYPE_MEDIUM_BLOB;
- else if (max_length >= 256)
- type = FIELD_TYPE_BLOB;
- init_make_field(tmp_field, type);
+ init_make_field(tmp_field,FIELD_TYPE_VAR_STRING);
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 9146b3c3b9e..74eed7fa41a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -51,7 +51,8 @@ static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
type[0]= item_cmp_type(type[0], items[i]->result_type());
}
-static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
+static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
+ const char *fname)
{
my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
c1.collation->name,c1.derivation_name(),
@@ -820,6 +821,55 @@ longlong Item_func_interval::val_int()
return i-1;
}
+
+/*
+ Perform context analysis of a BETWEEN item tree
+
+ SYNOPSIS:
+ fix_fields()
+ thd reference to the global context of the query thread
+ tables list of all open tables involved in the query
+ ref pointer to Item* variable where pointer to resulting "fixed"
+ item is to be assigned
+
+ DESCRIPTION
+ This function performs context analysis (name resolution) and calculates
+ various attributes of the item tree with Item_func_between as its root.
+ The function saves in ref the pointer to the item or to a newly created
+ item that is considered as a replacement for the original one.
+
+ NOTES
+ Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
+ a predicate/function level. Then it's easy to show that:
+ T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2))
+ T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
+ T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
+ T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
+
+ RETURN
+ 0 ok
+ 1 got error
+*/
+
+bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables,
+ Item **ref)
+{
+ if (Item_func_opt_neg::fix_fields(thd, tables, ref))
+ return 1;
+
+ /* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
+ if (pred_level && !negated)
+ return 0;
+
+ /* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
+ not_null_tables_cache= (args[0]->not_null_tables() |
+ (args[1]->not_null_tables() &
+ args[2]->not_null_tables()));
+
+ return 0;
+}
+
+
void Item_func_between::fix_length_and_dec()
{
max_length= 1;
@@ -871,8 +921,9 @@ longlong Item_func_between::val_int()
a=args[1]->val_str(&value1);
b=args[2]->val_str(&value2);
if (!args[1]->null_value && !args[2]->null_value)
- return (sortcmp(value,a,cmp_collation.collation) >= 0 &&
- sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0;
+ return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
+ sortcmp(value,b,cmp_collation.collation) <= 0) !=
+ negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
@@ -894,7 +945,7 @@ longlong Item_func_between::val_int()
a=args[1]->val_int();
b=args[2]->val_int();
if (!args[1]->null_value && !args[2]->null_value)
- return (value >= a && value <= b) ? 1 : 0;
+ return (longlong) ((value >= a && value <= b) != negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
@@ -914,7 +965,7 @@ longlong Item_func_between::val_int()
a=args[1]->val();
b=args[2]->val();
if (!args[1]->null_value && !args[2]->null_value)
- return (value >= a && value <= b) ? 1 : 0;
+ return (longlong) ((value >= a && value <= b) != negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
@@ -926,7 +977,7 @@ longlong Item_func_between::val_int()
null_value= value >= a;
}
}
- return 0;
+ return (longlong) (!null_value && negated);
}
@@ -934,6 +985,8 @@ void Item_func_between::print(String *str)
{
str->append('(');
args[0]->print(str);
+ if (negated)
+ str->append(" not", 4);
str->append(" between ", 9);
args[1]->print(str);
str->append(" and ", 5);
@@ -1019,6 +1072,49 @@ Item_func_ifnull::val_str(String *str)
}
+/*
+ Perform context analysis of an IF item tree
+
+ SYNOPSIS:
+ fix_fields()
+ thd reference to the global context of the query thread
+ tables list of all open tables involved in the query
+ ref pointer to Item* variable where pointer to resulting "fixed"
+ item is to be assigned
+
+ DESCRIPTION
+ This function performs context analysis (name resolution) and calculates
+ various attributes of the item tree with Item_func_if as its root.
+ The function saves in ref the pointer to the item or to a newly created
+ item that is considered as a replacement for the original one.
+
+ NOTES
+ Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
+ a predicate/function level. Then it's easy to show that:
+ T0(IF(e,e1,e2) = T1(IF(e,e1,e2))
+ T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2))
+
+ RETURN
+ 0 ok
+ 1 got error
+*/
+
+bool
+Item_func_if::fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
+{
+ DBUG_ASSERT(fixed == 0);
+ args[0]->top_level_item();
+
+ if (Item_func::fix_fields(thd, tlist, ref))
+ return 1;
+
+ not_null_tables_cache= (args[1]->not_null_tables() &
+ args[2]->not_null_tables());
+
+ return 0;
+}
+
+
void
Item_func_if::fix_length_and_dec()
{
@@ -1750,6 +1846,56 @@ bool Item_func_in::nulls_in_row()
}
+/*
+ Perform context analysis of an IN item tree
+
+ SYNOPSIS:
+ fix_fields()
+ thd reference to the global context of the query thread
+ tables list of all open tables involved in the query
+ ref pointer to Item* variable where pointer to resulting "fixed"
+ item is to be assigned
+
+ DESCRIPTION
+ This function performs context analysis (name resolution) and calculates
+ various attributes of the item tree with Item_func_in as its root.
+ The function saves in ref the pointer to the item or to a newly created
+ item that is considered as a replacement for the original one.
+
+ NOTES
+ Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
+ a predicate/function level. Then it's easy to show that:
+ T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
+ T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
+ T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei)))
+ T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
+
+ RETURN
+ 0 ok
+ 1 got error
+*/
+
+bool
+Item_func_in::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+{
+ Item **arg, **arg_end;
+
+ if (Item_func_opt_neg::fix_fields(thd, tables, ref))
+ return 1;
+
+ /* not_null_tables_cache == union(T1(e),union(T1(ei))) */
+ if (pred_level && negated)
+ return 0;
+
+ /* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
+ not_null_tables_cache= ~(table_map) 0;
+ for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++)
+ not_null_tables_cache&= (*arg)->not_null_tables();
+ not_null_tables_cache|= (*args)->not_null_tables();
+ return 0;
+}
+
+
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
return cs->coll->strnncollsp(cs,
@@ -1827,6 +1973,8 @@ void Item_func_in::print(String *str)
{
str->append('(');
args[0]->print(str);
+ if (negated)
+ str->append(" not", 4);
str->append(" in (", 5);
print_args(str, 1);
str->append("))", 2);
@@ -1840,7 +1988,7 @@ longlong Item_func_in::val_int()
{
int tmp=array->find(args[0]);
null_value=args[0]->null_value || (!tmp && have_null);
- return tmp;
+ return (longlong) (!null_value && tmp != negated);
}
in_item->store_value(args[0]);
if ((null_value=args[0]->null_value))
@@ -1849,11 +1997,11 @@ longlong Item_func_in::val_int()
for (uint i=1 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
- return 1; // Would maybe be nice with i ?
+ return (longlong) (!negated);
have_null|= args[i]->null_value;
}
null_value= have_null;
- return 0;
+ return (longlong) (!null_value && negated);
}
@@ -2293,7 +2441,42 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
/* If we are on execution stage */
String *escape_str= escape_item->val_str(&tmp_value1);
- escape= escape_str ? *(escape_str->ptr()) : '\\';
+ if (escape_str)
+ {
+ CHARSET_INFO *cs= cmp.cmp_collation.collation;
+ if (use_mb(cs))
+ {
+ my_wc_t wc;
+ int rc= cs->cset->mb_wc(cs, &wc,
+ (const uchar*) escape_str->ptr(),
+ (const uchar*) escape_str->ptr() +
+ escape_str->length());
+ escape= (int) (rc > 0 ? wc : '\\');
+ }
+ else
+ {
+ /*
+ In the case of 8bit character set, we pass native
+ code instead of Unicode code as "escape" argument.
+ Convert to "cs" if charset of escape differs.
+ */
+ uint32 unused;
+ if (escape_str->needs_conversion(escape_str->length(),
+ escape_str->charset(), cs, &unused))
+ {
+ char ch;
+ uint errors;
+ uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(),
+ escape_str->length(),
+ escape_str->charset(), &errors);
+ escape= cnvlen ? ch : '\\';
+ }
+ else
+ escape= *(escape_str->ptr());
+ }
+ }
+ else
+ escape= '\\';
/*
We could also do boyer-more for non-const items, but as we would have to
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 47884f6064e..741ae90108a 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -358,17 +358,49 @@ public:
};
-class Item_func_between :public Item_int_func
+/*
+ The class Item_func_opt_neg is defined to factor out the functionality
+ common for the classes Item_func_between and Item_func_in. The objects
+ of these classes can express predicates or there negations.
+ The alternative approach would be to create pairs Item_func_between,
+ Item_func_notbetween and Item_func_in, Item_func_notin.
+
+*/
+
+class Item_func_opt_neg :public Item_int_func
+{
+public:
+ bool negated; /* <=> the item represents NOT <func> */
+ bool pred_level; /* <=> [NOT] <func> is used on a predicate level */
+public:
+ Item_func_opt_neg(Item *a, Item *b, Item *c)
+ :Item_int_func(a, b, c), negated(0), pred_level(0) {}
+ Item_func_opt_neg(List<Item> &list)
+ :Item_int_func(list), negated(0), pred_level(0) {}
+public:
+ inline void negate() { negated= !negated; }
+ inline void top_level_item() { pred_level= 1; }
+ Item *neg_transformer(THD *thd)
+ {
+ negated= !negated;
+ return this;
+ }
+};
+
+
+class Item_func_between :public Item_func_opt_neg
{
DTCollation cmp_collation;
public:
Item_result cmp_type;
String value0,value1,value2;
- Item_func_between(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
+ Item_func_between(Item *a, Item *b, Item *c)
+ :Item_func_opt_neg(a, b, c) {}
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
enum Functype functype() const { return BETWEEN; }
const char *func_name() const { return "between"; }
+ bool fix_fields(THD *, struct st_table_list *, Item **);
void fix_length_and_dec();
void print(String *str);
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
@@ -433,15 +465,9 @@ public:
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
- bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
- {
- DBUG_ASSERT(fixed == 0);
- args[0]->top_level_item();
- return Item_func::fix_fields(thd, tlist, ref);
- }
+ bool fix_fields(THD *, struct st_table_list *, Item **);
void fix_length_and_dec();
const char *func_name() const { return "if"; }
- table_map not_null_tables() const { return 0; }
};
@@ -736,7 +762,7 @@ public:
}
};
-class Item_func_in :public Item_int_func
+class Item_func_in :public Item_func_opt_neg
{
Item_result cmp_type;
in_vector *array;
@@ -745,11 +771,12 @@ class Item_func_in :public Item_int_func
DTCollation cmp_collation;
public:
Item_func_in(List<Item> &list)
- :Item_int_func(list), array(0), in_item(0), have_null(0)
+ :Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int();
+ bool fix_fields(THD *, struct st_table_list *, Item **);
void fix_length_and_dec();
void cleanup()
{
@@ -769,12 +796,6 @@ class Item_func_in :public Item_int_func
bool nulls_in_row();
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
- /*
- IN() protect from NULL only first argument, if construction like
- "expression IN ()" will be allowed, we will need to check number of
- argument here, because "NOT(NULL IN ())" is TRUE.
- */
- table_map not_null_tables() const { return args[0]->not_null_tables(); }
};
/* Functions used by where clause */
@@ -805,7 +826,7 @@ public:
else
{
args[0]->update_used_tables();
- if (!(used_tables_cache=args[0]->used_tables()))
+ if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())))
{
/* Remember if the value is always NULL or never NULL */
cached_value= (longlong) args[0]->is_null();
@@ -879,7 +900,7 @@ class Item_func_like :public Item_bool_func2
Item *escape_item;
public:
- char escape;
+ int escape;
Item_func_like(Item *a,Item *b, Item *escape_arg)
:Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 41573406949..ebb200ec4da 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1038,6 +1038,11 @@ bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
used_tables_cache|= RAND_TABLE_BIT;
if (arg_count)
{ // Only use argument once in query
+ if (!args[0]->const_during_execution())
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "RAND");
+ return TRUE;
+ }
/*
Allocate rand structure once: we must use thd->current_arena
to create rand in proper mem_root if it's a prepared statement or
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 000dcdb4997..6ae782db557 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1664,7 +1664,9 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
char buff[MAX_FIELD_WIDTH];
String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
- if (item->result.length())
+ if (item->no_appended)
+ item->no_appended= FALSE;
+ else
item->result.append(*item->separator);
tmp.length(0);
@@ -1856,6 +1858,7 @@ void Item_func_group_concat::clear()
result.copy();
null_value= TRUE;
warning_for_row= FALSE;
+ no_appended= TRUE;
if (tree_mode)
reset_tree(tree);
}
@@ -1898,8 +1901,7 @@ bool Item_func_group_concat::add()
void Item_func_group_concat::reset_field()
{
- if (tree_mode)
- reset_tree(tree);
+ DBUG_ASSERT(0);
}
@@ -1935,6 +1937,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
args, arg_count, MY_COLL_ALLOW_CONV))
return 1;
+ result.set_charset(collation.collation);
result_field= 0;
null_value= 1;
max_length= group_concat_max_len;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index a3b422565d1..d53d8d861ae 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -709,6 +709,7 @@ class Item_func_group_concat : public Item_sum
uint arg_count_field;
uint field_list_offset;
uint count_cut_values;
+ bool no_appended;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 0af3ea3af63..32c5861028e 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -59,6 +59,7 @@ void kill_one_thread(THD *thd, ulong id);
bool net_request_file(NET* net, const char* fname);
char* query_table_status(THD *thd,const char *db,const char *table_name);
+
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
#define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } }
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
@@ -412,6 +413,7 @@ struct Query_cache_query_flags
#define query_cache_store_query(A, B) query_cache.store_query(A, B)
#define query_cache_destroy() query_cache.destroy()
#define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
+#define query_cache_init() query_cache.init()
#define query_cache_resize(A) query_cache.resize(A)
#define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A)
#define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C)
@@ -425,6 +427,7 @@ struct Query_cache_query_flags
#define query_cache_store_query(A, B)
#define query_cache_destroy()
#define query_cache_result_size_limit(A)
+#define query_cache_init()
#define query_cache_resize(A)
#define query_cache_set_min_res_unit(A)
#define query_cache_invalidate3(A, B, C)
@@ -462,6 +465,7 @@ void mysql_reset_thd_for_next_command(THD *thd);
bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex);
+void fix_multi_delete_lex(LEX* lex);
void init_max_user_conn(void);
void init_update_queries(void);
void free_max_user_conn(void);
@@ -931,6 +935,7 @@ extern bool opt_using_transactions, mysqld_embedded;
extern bool using_update_log, opt_large_files, server_id_supplied;
extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log, opt_error_log;
extern bool opt_disable_networking, opt_skip_show_db;
+extern bool opt_character_set_client_handshake;
extern bool volatile abort_loop, shutdown_in_progress, grant_option;
extern uint volatile thread_count, thread_running, global_read_lock;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 8894ed39b08..86ba437596d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -271,6 +271,7 @@ arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
bool opt_error_log= IF_WIN(1,0);
bool opt_disable_networking=0, opt_skip_show_db=0;
+bool opt_character_set_client_handshake= 1;
bool lower_case_table_names_used= 0;
bool server_id_supplied = 0;
bool opt_endinfo,using_udf_functions, locked_in_memory;
@@ -2704,6 +2705,7 @@ static int init_server_components()
query_cache_result_size_limit(query_cache_limit);
query_cache_set_min_res_unit(query_cache_min_res_unit);
+ query_cache_init();
query_cache_resize(query_cache_size);
randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
reset_floating_point_exceptions();
@@ -4216,6 +4218,7 @@ enum options_mysqld
OPT_EXPIRE_LOGS_DAYS,
OPT_GROUP_CONCAT_MAX_LEN,
OPT_DEFAULT_COLLATION,
+ OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
OPT_INIT_CONNECT,
OPT_INIT_SLAVE,
OPT_SECURE_AUTH,
@@ -4295,6 +4298,11 @@ Disable with --skip-bdb (will save memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
+ "Don't use client side character set value sent during handshake.",
+ (gptr*) &opt_character_set_client_handshake,
+ (gptr*) &opt_character_set_client_handshake,
+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"character-set-server", 'C', "Set the default character set.",
(gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
@@ -5536,13 +5544,13 @@ struct show_var_st status_vars[]= {
{"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used,
SHOW_KEY_CACHE_CONST_LONG},
{"Key_read_requests", (char*) &dflt_key_cache_var.global_cache_r_requests,
- SHOW_KEY_CACHE_LONG},
+ SHOW_KEY_CACHE_LONGLONG},
{"Key_reads", (char*) &dflt_key_cache_var.global_cache_read,
- SHOW_KEY_CACHE_LONG},
+ SHOW_KEY_CACHE_LONGLONG},
{"Key_write_requests", (char*) &dflt_key_cache_var.global_cache_w_requests,
- SHOW_KEY_CACHE_LONG},
+ SHOW_KEY_CACHE_LONGLONG},
{"Key_writes", (char*) &dflt_key_cache_var.global_cache_write,
- SHOW_KEY_CACHE_LONG},
+ SHOW_KEY_CACHE_LONGLONG},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 9d84d0b2427..93fa7ac938c 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -759,7 +759,7 @@ my_real_read(NET *net, ulong *complen)
net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER
- net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
+ net->last_errno= (vio_was_interrupted(net->vio) ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
#endif
goto end;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 2dd097cbaab..5cb330100f8 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -849,7 +849,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if (cond_func->functype() == Item_func::BETWEEN)
{
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
+ if (!((Item_func_between *)(cond_func))->negated &&
+ cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
{
Field *field=((Item_field*) (cond_func->arguments()[0]))->field;
Item_result cmp_type=field->cmp_type();
@@ -866,7 +867,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if (cond_func->functype() == Item_func::IN_FUNC)
{ // COND OR
Item_func_in *func=(Item_func_in*) cond_func;
- if (func->key_item()->type() == Item::FIELD_ITEM)
+ if (!func->negated && func->key_item()->type() == Item::FIELD_ITEM)
{
Field *field=((Item_field*) (func->key_item()))->field;
Item_result cmp_type=field->cmp_type();
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 4ab506cc4e1..cb8e3c2d273 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -661,7 +661,8 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
If key_part2 may be NULL, then we want to find the first row
that is not null
*/
- ref->key_buff[ref->key_length++]= 1;
+ ref->key_buff[ref->key_length]= 1;
+ ref->key_length+= part->store_length;
*range_fl&= ~NO_MIN_RANGE;
*range_fl|= NEAR_MIN; // > NULL
}
diff --git a/sql/slave.cc b/sql/slave.cc
index 9ff7a432b89..1be3e3b4a17 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -746,14 +746,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
rules (see code below). For that reason, users should not set conflicting
rules because they may get unpredicted results (precedence order is
explained in the manual).
- If no table of the list is marked "updating" (so far this can only happen
- if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
- is the tables in the FROM): then we always return 0, because there is no
- reason we play this statement on this slave if it updates nothing. In the
- case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
- with tables having "updating==TRUE" (those after the DELETE), so this
- second call will make the decision (because
- all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
+
RETURN VALUES
0 should not be logged/replicated
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index fb5d0eb0a3f..d2237c24139 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -788,19 +788,22 @@ void field_real::get_opt_type(String *answer,
if (!max_notzero_dec_len)
{
+ int len= (int) max_length - ((item->decimals == NOT_FIXED_DEC) ?
+ 0 : (item->decimals + 1));
+
if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
- sprintf(buff, "TINYINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "TINYINT(%d)", len);
else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
UINT_MAX16 : INT_MAX16))
- sprintf(buff, "SMALLINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "SMALLINT(%d)", len);
else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
UINT_MAX24 : INT_MAX24))
- sprintf(buff, "MEDIUMINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "MEDIUMINT(%d)", len);
else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
UINT_MAX32 : INT_MAX32))
- sprintf(buff, "INT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "INT(%d)", len);
else
- sprintf(buff, "BIGINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "BIGINT(%d)", len);
answer->append(buff, (uint) strlen(buff));
if (min_arg >= 0)
answer->append(" UNSIGNED");
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1cedc89ef97..b48f2537069 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -868,6 +868,13 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
{
if (table->version != refresh_version)
{
+ if (! refresh)
+ {
+ /* Ignore flush for now, but force close after usage. */
+ thd->version= table->version;
+ continue;
+ }
+
/*
** There is a refresh in progress for this table
** Wait until the table is freed or the thread is killed.
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 2dd88f40005..4214c9a7c07 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -574,13 +574,18 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
{
DBUG_ENTER("query_cache_insert");
-#ifndef DBUG_OFF
- // Check if we have called query_cache.wreck() (which disables the cache)
- if (query_cache.query_cache_size == 0)
+ STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after guard
+ mutex lock
+ */
+ if (unlikely(query_cache.query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
DBUG_VOID_RETURN;
-#endif
+ }
- STRUCT_LOCK(&query_cache.structure_guard_mutex);
Query_cache_block *query_block = ((Query_cache_block*)
net->query_cache_query);
if (query_block)
@@ -623,14 +628,20 @@ void query_cache_abort(NET *net)
{
DBUG_ENTER("query_cache_abort");
-#ifndef DBUG_OFF
- // Check if we have called query_cache.wreck() (which disables the cache)
- if (query_cache.query_cache_size == 0)
- DBUG_VOID_RETURN;
-#endif
if (net->query_cache_query != 0) // Quick check on unlocked structure
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after guard
+ mutex lock
+ */
+ if (unlikely(query_cache.query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ DBUG_VOID_RETURN;
+ }
+
Query_cache_block *query_block = ((Query_cache_block*)
net->query_cache_query);
if (query_block) // Test if changed by other thread
@@ -652,11 +663,6 @@ void query_cache_end_of_result(THD *thd)
{
DBUG_ENTER("query_cache_end_of_result");
-#ifndef DBUG_OFF
- // Check if we have called query_cache.wreck() (which disables the cache)
- if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN;
-#endif
-
if (thd->net.query_cache_query != 0) // Quick check on unlocked structure
{
#ifdef EMBEDDED_LIBRARY
@@ -664,6 +670,17 @@ void query_cache_end_of_result(THD *thd)
emb_count_querycache_size(thd));
#endif
STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after guard
+ mutex lock
+ */
+ if (unlikely(query_cache.query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ DBUG_VOID_RETURN;
+ }
+
Query_cache_block *query_block = ((Query_cache_block*)
thd->net.query_cache_query);
if (query_block)
@@ -743,9 +760,14 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
DBUG_ENTER("Query_cache::resize");
DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size,
query_cache_size_arg));
- free_cache(0);
+ DBUG_ASSERT(initialized);
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ free_cache();
query_cache_size= query_cache_size_arg;
- DBUG_RETURN(::query_cache_size= init_cache());
+ ::query_cache_size= init_cache();
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(::query_cache_size);
}
@@ -1388,7 +1410,7 @@ void Query_cache::destroy()
}
else
{
- free_cache(1);
+ free_cache();
pthread_mutex_destroy(&structure_guard_mutex);
initialized = 0;
}
@@ -1417,8 +1439,6 @@ ulong Query_cache::init_cache()
int align;
DBUG_ENTER("Query_cache::init_cache");
- if (!initialized)
- init();
approx_additional_data_size = (sizeof(Query_cache) +
sizeof(gptr)*(def_query_hash_size+
def_table_hash_size));
@@ -1476,14 +1496,9 @@ ulong Query_cache::init_cache()
goto err;
query_cache_size -= additional_data_size;
- STRUCT_LOCK(&structure_guard_mutex);
-
- if (!(cache = (byte *)
- my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
- {
- STRUCT_UNLOCK(&structure_guard_mutex);
+ if (!(cache= (byte *)
+ my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
goto err;
- }
DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
query_cache_size, min_allocation_unit, mem_bin_num));
@@ -1579,7 +1594,6 @@ ulong Query_cache::init_cache()
queries_in_cache = 0;
queries_blocks = 0;
- STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(query_cache_size +
additional_data_size + approx_additional_data_size);
@@ -1595,6 +1609,7 @@ void Query_cache::make_disabled()
{
DBUG_ENTER("Query_cache::make_disabled");
query_cache_size= 0;
+ queries_blocks= 0;
free_memory= 0;
bins= 0;
steps= 0;
@@ -1606,14 +1621,11 @@ void Query_cache::make_disabled()
}
-void Query_cache::free_cache(my_bool destruction)
+void Query_cache::free_cache()
{
DBUG_ENTER("Query_cache::free_cache");
if (query_cache_size > 0)
{
- if (!destruction)
- STRUCT_LOCK(&structure_guard_mutex);
-
flush_cache();
#ifndef DBUG_OFF
if (bins[0].free_blocks == 0)
@@ -1635,8 +1647,6 @@ void Query_cache::free_cache(my_bool destruction)
make_disabled();
hash_free(&queries);
hash_free(&tables);
- if (!destruction)
- STRUCT_UNLOCK(&structure_guard_mutex);
}
DBUG_VOID_RETURN;
}
@@ -2266,7 +2276,19 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
}
if (!under_guard)
+ {
STRUCT_LOCK(&structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after
+ guard mutex lock
+ */
+ if (unlikely(query_cache.query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(0);
+ }
+ }
/* Free old queries until we have enough memory to store this block */
Query_cache_block *block;
@@ -2764,6 +2786,17 @@ void Query_cache::pack_cache()
{
DBUG_ENTER("Query_cache::pack_cache");
STRUCT_LOCK(&structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after
+ guard mutex lock
+ */
+ if (unlikely(query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_VOID_RETURN;
+ }
+
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
byte *border = 0;
@@ -3073,6 +3106,7 @@ my_bool Query_cache::join_results(ulong join_limit)
STRUCT_LOCK(&structure_guard_mutex);
if (queries_blocks != 0)
{
+ DBUG_ASSERT(query_cache_size > 0);
Query_cache_block *block = queries_blocks;
do
{
@@ -3369,7 +3403,19 @@ my_bool Query_cache::check_integrity(bool not_locked)
DBUG_RETURN(0);
}
if (!not_locked)
+ {
STRUCT_LOCK(&structure_guard_mutex);
+ /*
+ It is very unlikely that following condition is TRUE (it is possible
+ only if other thread is resizing cache), so we check it only after
+ guard mutex lock
+ */
+ if (unlikely(query_cache_size == 0))
+ {
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ DBUG_RETURN(0);
+ }
+ }
if (hash_check(&queries))
{
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index c933a2349af..b0a045a8aad 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -312,10 +312,9 @@ protected:
Following function control structure_guard_mutex
by themself or don't need structure_guard_mutex
*/
- void init();
ulong init_cache();
void make_disabled();
- void free_cache(my_bool destruction);
+ void free_cache();
Query_cache_block *write_block_data(ulong data_len, gptr data,
ulong header_len,
Query_cache_block::block_type type,
@@ -351,6 +350,8 @@ protected:
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
+ /* initialize cache (mutex) */
+ void init();
/* resize query cache (return real query size, 0 if disabled) */
ulong resize(ulong query_cache_size);
/* set limit on result size */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e845769d7ad..11b45b848c8 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -353,12 +353,12 @@ void THD::cleanup(void)
mysql_ha_flush(this, (TABLE_LIST*) 0,
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
hash_free(&handler_tables_hash);
+ delete_dynamic(&user_var_events);
+ hash_free(&user_vars);
close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
- delete_dynamic(&user_var_events);
- hash_free(&user_vars);
if (global_read_lock)
unlock_global_read_lock(this);
if (ull)
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7635774e3ac..7c834c91183 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -427,7 +427,11 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
error= -1;
goto exit;
}
- result= 0;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
+ error= 0;
+ send_ok(thd);
+ goto exit;
}
else
{
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index c4f5b1427af..7b963c7ea31 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -114,6 +114,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
MYF(0));
DBUG_RETURN(-1);
}
+ /*
+ This needs to be done before external_lock
+ */
+ ha_enable_transaction(thd, FALSE);
if (!(table = open_ltable(thd,table_list,lock_type)))
DBUG_RETURN(-1);
transactional_table= table->file->has_transactions();
@@ -273,7 +277,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (ignore ||
handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- ha_enable_transaction(thd, FALSE);
table->file->start_bulk_insert((ha_rows) 0);
table->copy_blobs=1;
if (!field_term->length() && !enclosed->length())
@@ -284,10 +287,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
skip_lines);
if (table->file->end_bulk_insert())
error=1; /* purecov: inspected */
- ha_enable_transaction(thd, TRUE);
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->next_number_field=0;
}
+ ha_enable_transaction(thd, TRUE);
if (file >= 0)
my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 297ea8fbd67..a2df59e56c7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -59,6 +59,9 @@ static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
+
+static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
+ const char* alias);
const char *any_db="*any*"; // Special symbol for check_access
@@ -125,10 +128,7 @@ static bool end_active_trans(THD *thd)
*/
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
{
- return (table_rules_on && tables && !tables_ok(thd,tables) &&
- ((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
- !tables_ok(thd,
- (TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
+ return (table_rules_on && tables && !tables_ok(thd,tables));
}
#endif
@@ -696,29 +696,19 @@ static int check_connection(THD *thd)
return (ER_OUT_OF_RESOURCES);
thd->host_or_ip= thd->ip;
vio_in_addr(net->vio,&thd->remote.sin_addr);
-#if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread)
- /* Fast local hostname resolve for Win32 */
- if (!strcmp(thd->ip,"127.0.0.1"))
+ if (!(specialflag & SPECIAL_NO_RESOLVE))
{
- thd->host= (char*) my_localhost;
- thd->host_or_ip= my_localhost;
- }
- else
-#endif
- {
- if (!(specialflag & SPECIAL_NO_RESOLVE))
+ vio_in_addr(net->vio,&thd->remote.sin_addr);
+ thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
+ /* Cut very long hostnames to avoid possible overflows */
+ if (thd->host)
{
- vio_in_addr(net->vio,&thd->remote.sin_addr);
- thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
- /* Cut very long hostnames to avoid possible overflows */
- if (thd->host)
- {
- thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
- thd->host_or_ip= thd->host;
- }
- if (connect_errors > max_connect_errors)
- return(ER_HOST_IS_BLOCKED);
+ if (thd->host != my_localhost)
+ thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
+ thd->host_or_ip= thd->host;
}
+ if (connect_errors > max_connect_errors)
+ return(ER_HOST_IS_BLOCKED);
}
DBUG_PRINT("info",("Host: %s ip: %s",
thd->host ? thd->host : "unknown host",
@@ -814,11 +804,13 @@ static int check_connection(THD *thd)
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
/*
Use server character set and collation if
+ - opt_character_set_client_handshake is not set
- client has not specified a character set
- client character set is the same as the servers
- client character set doesn't exists in server
*/
- if (!(thd->variables.character_set_client=
+ if (!opt_character_set_client_handshake ||
+ !(thd->variables.character_set_client=
get_charset((uint) net->read_pos[8], MYF(0))) ||
!my_strcasecmp(&my_charset_latin1,
global_system_variables.character_set_client->name,
@@ -3335,7 +3327,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(lex->name)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
@@ -3371,7 +3362,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(lex->name)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
@@ -3412,7 +3402,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(db)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
@@ -4256,6 +4245,40 @@ void create_select_for_variable(const char *var_name)
DBUG_VOID_RETURN;
}
+static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
+ const char* alias)
+{
+ for (;tl;tl= tl->next)
+ {
+ if (!strcmp(db,tl->db) &&
+ tl->alias && !my_strcasecmp(table_alias_charset,tl->alias,alias))
+ return tl;
+ }
+
+ return 0;
+}
+
+/* Sets up lex->auxilliary_table_list */
+void fix_multi_delete_lex(LEX* lex)
+{
+ TABLE_LIST *tl;
+ TABLE_LIST *good_list= (TABLE_LIST*)lex->select_lex.table_list.first;
+
+ for (tl= (TABLE_LIST*)lex->auxilliary_table_list.first; tl; tl= tl->next)
+ {
+ TABLE_LIST* good_table= get_table_by_alias(good_list,tl->db,tl->alias);
+ if (good_table && !good_table->derived)
+ {
+ /*
+ real_name points to a member of Table_ident which is
+ allocated via thd->strmake() from THD memroot
+ */
+ tl->real_name= good_table->real_name;
+ tl->real_name_length= good_table->real_name_length;
+ good_table->updating= tl->updating;
+ }
+ }
+}
void mysql_init_multi_delete(LEX *lex)
{
@@ -5578,13 +5601,7 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
(*table_count)++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
- for (walk= delete_tables; walk; walk= walk->next)
- {
- if (!my_strcasecmp(table_alias_charset,
- target_tbl->alias, walk->alias) &&
- !strcmp(walk->db, target_tbl->db))
- break;
- }
+ walk= get_table_by_alias(delete_tables,target_tbl->db,target_tbl->alias);
if (!walk)
{
my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e7af2a1aa75..59b82b53b32 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -618,7 +618,7 @@ JOIN::optimize()
}
if (group_list || tmp_table_param.sum_func_count)
{
- if (! hidden_group_fields)
+ if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
select_distinct=0;
}
else if (select_distinct && tables - const_tables == 1)
@@ -9277,6 +9277,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate
functions.
+ The function also corrects value of the the maybe_null attribute
+ for the items of all subexpressions containing group by fields.
IMPLEMENTATION
The function recursively traverses the tree of the expr expression,
@@ -9287,6 +9289,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
This substitution is needed GROUP BY queries with ROLLUP if
SELECT list contains expressions over group by attributes.
+ TODO: Some functions are not null-preserving. For those functions
+ updating of the maybe_null attribute is an overkill.
+
EXAMPLES
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
@@ -9302,6 +9307,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if (expr->arg_count)
{
Item **arg,**arg_end;
+ bool arg_changed= FALSE;
for (arg= expr->arguments(),
arg_end= expr->arguments()+expr->arg_count;
arg != arg_end; arg++)
@@ -9318,16 +9324,21 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
return 1; // fatal_error is set
thd->change_item_tree(arg, new_item);
- *changed= TRUE;
+ arg_changed= TRUE;
}
}
}
else if (item->type() == Item::FUNC_ITEM)
{
- if (change_group_ref(thd, (Item_func *) item, group_list, changed))
+ if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
return 1;
}
}
+ if (arg_changed)
+ {
+ expr->maybe_null= 1;
+ *changed= TRUE;
+ }
}
return 0;
}
@@ -9389,7 +9400,7 @@ bool JOIN::rollup_init()
}
if (item->type() == Item::FUNC_ITEM)
{
- bool changed= 0;
+ bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1;
/*
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 647dfe2ac4d..c3c28535954 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -638,33 +638,6 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
DBUG_RETURN(0);
}
-/*
- returns the length of the longest type on the given table.
-
- This is used so that show fields will return the data using the proper
- lengths instead of forcing columns such as type to always return with a
- given length.
-*/
-
-uint get_longest_type_in_table(TABLE *table, const char *wild)
-{
- Field **ptr,*field;
- char tmp[MAX_FIELD_WIDTH];
- uint max_len= 0;
-
- for (ptr=table->field; (field= *ptr); ptr++)
- {
- if (!wild || !wild[0] ||
- !wild_case_compare(system_charset_info, field->field_name,wild))
- {
- String type(tmp,sizeof(tmp), system_charset_info);
- field->sql_type(type);
- max_len= max(max_len, type.length());
- }
- }
- return max_len;
-}
-
/***************************************************************************
** List all columns in a table_list->real_name
@@ -694,14 +667,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) get_table_grant(thd, table_list);
#endif
-
- /* we scan for the longest since long enum types can exceed 40 */
- uint max_len = get_longest_type_in_table(table, wild);
-
List<Item> field_list;
field_list.push_back(new Item_empty_string("Field",NAME_LEN));
- field_list.push_back(new Item_empty_string("Type",
- max_len > 40 ? max_len : 40));
+ field_list.push_back(new Item_empty_string("Type", 40));
if (verbose)
field_list.push_back(new Item_empty_string("Collation",40));
field_list.push_back(new Item_empty_string("Null",1));
@@ -2123,6 +2091,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
end= int10_to_str(*(long*) value, buff, 10);
break;
+ case SHOW_KEY_CACHE_LONGLONG:
+ value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
case SHOW_UNDEF: // Show never happen
case SHOW_SYS:
break; // Return empty string
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 92db0143980..01126043764 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1360,6 +1360,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
create_info->table_existed= 1; // Mark that table existed
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ alias);
DBUG_RETURN(0);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -1373,12 +1376,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!access(path,F_OK))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- create_info->table_existed= 1; // Mark that table existed
- error= 0;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
}
@@ -1401,12 +1400,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_PRINT("info", ("Table with same name already existed in handler"));
if (create_if_not_exists)
- {
- create_info->table_existed= 1; // Mark that table existed
- error= 0;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
}
@@ -1447,6 +1442,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
}
error=0;
+ goto end;
+
+warn:
+ error= 0;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ alias);
+ create_info->table_existed= 1; // Mark that table existed
+
end:
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 8af7903a910..d6afc888be2 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -309,6 +309,11 @@ end:
static int print_key_cache_status(const char *name, KEY_CACHE *key_cache)
{
+ char llbuff1[22];
+ char llbuff2[22];
+ char llbuff3[22];
+ char llbuff4[22];
+
if (!key_cache->key_cache_inited)
{
printf("%s: Not in use\n", name);
@@ -322,16 +327,18 @@ Division_limit: %10lu\n\
Age_limit: %10lu\n\
blocks used: %10lu\n\
not flushed: %10lu\n\
-w_requests: %10lu\n\
-writes: %10lu\n\
-r_requests: %10lu\n\
-reads: %10lu\n\n",
+w_requests: %10s\n\
+writes: %10s\n\
+r_requests: %10s\n\
+reads: %10s\n\n",
name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold,
key_cache->blocks_used,key_cache->global_blocks_changed,
- key_cache->global_cache_w_requests,key_cache->global_cache_write,
- key_cache->global_cache_r_requests,key_cache->global_cache_read);
+ llstr(key_cache->global_cache_w_requests,llbuff1),
+ llstr(key_cache->global_cache_write,llbuff2),
+ llstr(key_cache->global_cache_r_requests,llbuff3),
+ llstr(key_cache->global_cache_read,llbuff4));
}
return 0;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index be8ead8e157..e29aaac8f94 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2598,7 +2598,12 @@ expr_expr:
expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| expr NOT IN_SYM '(' expr_list ')'
- { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
+ {
+ $5->push_front($1);
+ Item_func_in *item= new Item_func_in(*$5);
+ item->negate();
+ $$= item;
+ }
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
| expr NOT IN_SYM in_subselect
@@ -2608,7 +2613,11 @@ expr_expr:
| expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
+ {
+ Item_func_between *item= new Item_func_between($1,$4,$6);
+ item->negate();
+ $$= item;
+ }
| expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
@@ -2656,7 +2665,11 @@ no_in_expr:
no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
+ {
+ Item_func_between *item= new Item_func_between($1,$4,$6);
+ item->negate();
+ $$= item;
+ }
| no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
@@ -2704,7 +2717,12 @@ no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
- { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
+ {
+ $5->push_front($1);
+ Item_func_in *item= new Item_func_in(*$5);
+ item->negate();
+ $$= item;
+ }
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
| no_and_expr NOT IN_SYM in_subselect
@@ -2714,7 +2732,11 @@ no_and_expr:
| no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
+ {
+ Item_func_between *item= new Item_func_between($1,$4,$6);
+ item->negate();
+ $$= item;
+ }
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
@@ -4273,12 +4295,10 @@ single_multi:
}
where_clause opt_order_clause
delete_limit_clause {}
- | table_wild_list
- { mysql_init_multi_delete(Lex); }
- FROM join_table_list where_clause
- | FROM table_wild_list
- { mysql_init_multi_delete(Lex); }
- USING join_table_list where_clause
+ | table_wild_list {mysql_init_multi_delete(Lex);}
+ FROM join_table_list {fix_multi_delete_lex(Lex);} where_clause
+ | FROM table_wild_list { mysql_init_multi_delete(Lex);}
+ USING join_table_list {fix_multi_delete_lex(Lex);} where_clause
{}
;
diff --git a/sql/structs.h b/sql/structs.h
index ba081b570c1..081ada88bf7 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -181,7 +181,7 @@ enum SHOW_TYPE
SHOW_SSL_GET_CIPHER_LIST,
#endif /* HAVE_OPENSSL */
SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS,
- SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG
+ SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index ffcf5b6f34d..eadbd37f8f6 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -7182,7 +7182,7 @@ static void test_explain_bug()
verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING,
"", "", "", 10, 0);
- verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*64, 0);
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
@@ -7195,13 +7195,13 @@ static void test_explain_bug()
(mysql_get_server_version(mysql) <= 50000 ? 3 : 4096),
0);
- verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0);
verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_LONGLONG,
"", "", "", 10, 0);
- verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING,
"", "", "", 255, 0);
mysql_free_result(result);
diff --git a/vio/vio.c b/vio/vio.c
index 4660efe3048..45572b93ed6 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -50,6 +50,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close_pipe;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
@@ -69,6 +70,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close_shared_memory;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
@@ -88,6 +90,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_ssl_fastsend;
vio->viokeepalive =vio_ssl_keepalive;
vio->should_retry =vio_ssl_should_retry;
+ vio->was_interrupted=vio_ssl_was_interrupted;
vio->vioclose =vio_ssl_close;
vio->peer_addr =vio_ssl_peer_addr;
vio->in_addr =vio_ssl_in_addr;
@@ -105,6 +108,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index 3a75a08021d..c1c78cc6efa 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -39,6 +39,8 @@ int vio_ssl_fastsend(Vio *vio);
int vio_ssl_keepalive(Vio *vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_ssl_should_retry(Vio *vio);
+/* Check that operation was timed out */
+my_bool vio_ssl_was_interrupted(Vio *vio);
/* When the workday is over... */
int vio_ssl_close(Vio *vio);
/* Return last error number */
diff --git a/vio/viosocket.c b/vio/viosocket.c
index c7561890ead..5213390e2e6 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -99,7 +99,7 @@ int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
#endif /* !defined(NO_FCNTL_NONBLOCK) */
#else /* !defined(__WIN__) && !defined(__EMX__) */
#ifndef __EMX__
- if (vio->type != VIO_TYPE_NAMEDPIPE)
+ if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
#endif
{
ulong arg;
@@ -196,6 +196,15 @@ vio_should_retry(Vio * vio __attribute__((unused)))
}
+my_bool
+vio_was_interrupted(Vio *vio __attribute__((unused)))
+{
+ int en= socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+}
+
+
int vio_close(Vio * vio)
{
int r=0;
diff --git a/vio/viossl.c b/vio/viossl.c
index 2f608209a53..a3a2e7190bd 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -184,6 +184,15 @@ vio_ssl_should_retry(Vio * vio __attribute__((unused)))
}
+my_bool
+vio_ssl_was_interrupted(Vio *vio __attribute__((unused)))
+{
+ int en= socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+}
+
+
int vio_ssl_close(Vio * vio)
{
int r;