summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzr-mysql/default.conf8
-rw-r--r--client/mysqlbinlog.cc38
-rw-r--r--client/mysqldump.c58
-rw-r--r--client/mysqltest.cc6
-rw-r--r--configure.in2
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp4
-rw-r--r--include/my_getopt.h4
-rw-r--r--include/sql_common.h8
-rw-r--r--libmysql/libmysql.c8
-rw-r--r--libmysqld/examples/CMakeLists.txt3
-rw-r--r--libmysqld/examples/Makefile.am3
-rw-r--r--libmysqld/lib_sql.cc6
-rw-r--r--mysql-test/include/mysqlbinlog_have_debug.inc34
-rw-r--r--mysql-test/lib/My/Find.pm7
-rw-r--r--mysql-test/lib/mtr_cases.pm7
-rw-r--r--mysql-test/r/func_group.result2
-rw-r--r--mysql-test/r/func_group_innodb.result40
-rw-r--r--mysql-test/r/mysqldump.result42
-rw-r--r--mysql-test/r/ps.result103
-rw-r--r--mysql-test/r/sp.result38
-rw-r--r--mysql-test/r/type_blob.result4
-rw-r--r--mysql-test/r/type_year.result15
-rw-r--r--mysql-test/suite/binlog/r/binlog_grant.result4
-rw-r--r--mysql-test/suite/binlog/t/binlog_grant.test19
-rw-r--r--mysql-test/suite/engines/iuds/r/delete_year.result6
-rw-r--r--mysql-test/suite/engines/iuds/r/insert_year.result12
-rw-r--r--mysql-test/suite/engines/iuds/r/update_year.result6
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_views.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_innodb.result6
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_memory.result6
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_myisam.result6
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result6
-rw-r--r--mysql-test/suite/funcs_1/r/memory_views.result4
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_views-big.result4
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_views.result4
-rw-r--r--mysql-test/suite/funcs_1/r/storedproc.result4
-rw-r--r--mysql-test/suite/innodb/r/innodb_bug14007649.result56
-rw-r--r--mysql-test/suite/innodb/t/disabled.def3
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug14007649.test58
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result56
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb_bug52745.result1
-rw-r--r--mysql-test/suite/innodb_plugin/t/disabled.def1
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test58
-rw-r--r--mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result36
-rw-r--r--mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result20
-rw-r--r--mysql-test/suite/rpl/r/rpl_log_pos.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_packet.result11
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel_show_binlog_events_purge_logs.result13
-rw-r--r--mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test62
-rw-r--r--mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test61
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet-slave.opt2
-rw-r--r--mysql-test/suite/rpl/t/rpl_packet.test11
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test35
-rw-r--r--mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result139
-rw-r--r--mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test177
-rw-r--r--mysql-test/t/func_group_innodb.test44
-rw-r--r--mysql-test/t/mysqldump.test29
-rw-r--r--mysql-test/t/ps.test90
-rw-r--r--mysql-test/t/sp.test37
-rw-r--r--mysql-test/t/type_year.test8
-rw-r--r--mysys/mf_iocache2.c6
-rw-r--r--mysys/my_access.c3
-rw-r--r--mysys/my_write.c12
-rw-r--r--sql-common/client.c15
-rw-r--r--sql/Makefile.am1
-rwxr-xr-xsql/event_scheduler.cc4
-rw-r--r--sql/field.cc11
-rw-r--r--sql/handler.cc13
-rw-r--r--sql/item.cc2
-rw-r--r--sql/log.cc5
-rw-r--r--sql/log.h11
-rw-r--r--sql/log_event.cc139
-rw-r--r--sql/log_event.h28
-rw-r--r--sql/mem_root_array.h175
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc38
-rw-r--r--sql/protocol.cc6
-rw-r--r--sql/rpl_rli.cc4
-rw-r--r--sql/rpl_rli.h35
-rw-r--r--sql/rpl_utility.cc61
-rw-r--r--sql/rpl_utility.h18
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/slave.cc25
-rw-r--r--sql/sql_base.cc36
-rw-r--r--sql/sql_class.cc21
-rw-r--r--sql/sql_class.h21
-rw-r--r--sql/sql_lex.cc22
-rw-r--r--sql/sql_lex.h16
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_prepare.cc8
-rw-r--r--sql/sql_profile.cc8
-rw-r--r--sql/sql_repl.cc11
-rw-r--r--sql/sql_select.cc11
-rw-r--r--sql/sql_show.cc64
-rw-r--r--sql/sql_yacc.yy18
-rw-r--r--storage/innobase/btr/btr0cur.c2
-rw-r--r--storage/innobase/dict/dict0load.c4
-rw-r--r--storage/innobase/handler/ha_innodb.cc33
-rw-r--r--storage/innobase/handler/ha_innodb.h1
-rw-r--r--storage/innobase/include/srv0srv.h1
-rw-r--r--storage/innobase/row/row0mysql.c4
-rw-r--r--storage/innobase/sync/sync0arr.c5
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c2
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c22
-rw-r--r--storage/innodb_plugin/dict/dict0load.c4
-rw-r--r--storage/innodb_plugin/fil/fil0fil.c2
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc41
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h1
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc4
-rw-r--r--storage/innodb_plugin/include/srv0srv.h1
-rw-r--r--storage/innodb_plugin/row/row0ins.c6
-rw-r--r--storage/innodb_plugin/row/row0vers.c12
-rw-r--r--storage/innodb_plugin/sync/sync0arr.c5
-rw-r--r--storage/myisam/ft_boolean_search.c16
-rw-r--r--storage/myisam/ft_nlq_search.c18
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/mysql_client_fw.c1378
-rw-r--r--tests/mysql_client_test.c1367
-rw-r--r--vio/viosslfactories.c12
119 files changed, 3764 insertions, 1583 deletions
diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf
index 84dab2dc819..f044f8e62da 100644
--- a/.bzr-mysql/default.conf
+++ b/.bzr-mysql/default.conf
@@ -1,6 +1,4 @@
[MYSQL]
-tree_location = lp:maria
-post_commit_to = commits@mariadb.org
-post_commit_url = lp:maria
-tree_name = maria
-project_name = "MariaDB 5.1, with Maria 1.5"
+post_commit_to = "commits@lists.mysql.com"
+post_push_to = "commits@lists.mysql.com"
+tree_name = "mysql-5.1"
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 2a77578401a..6ec67766a94 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -689,6 +689,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
DBUG_ENTER("process_event");
print_event_info->short_form= short_form;
Exit_status retval= OK_CONTINUE;
+ IO_CACHE *const head= &print_event_info->head_cache;
/*
Format events are not concerned by --offset and such, we always need to
@@ -752,6 +753,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
else
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
break;
case CREATE_FILE_EVENT:
@@ -780,8 +783,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto end;
}
else
+ {
ce->print(result_file, print_event_info, TRUE);
-
+ if (head->error == -1)
+ goto err;
+ }
// If this binlog is not 3.23 ; why this test??
if (glob_description_event->binlog_version >= 3)
{
@@ -803,6 +809,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
output of Append_block_log_event::print is only a comment.
*/
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
OK_CONTINUE)
goto end;
@@ -811,6 +819,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case EXEC_LOAD_EVENT:
{
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
Execute_load_log_event *exv= (Execute_load_log_event*)ev;
Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
/*
@@ -828,6 +838,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
ce->print(result_file, print_event_info, TRUE);
my_free((char*)ce->fname,MYF(MY_WME));
delete ce;
+ if (head->error == -1)
+ goto err;
}
else
warning("Ignoring Execute_load_log_event as there is no "
@@ -840,6 +852,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
print_event_info->common_header_len=
glob_description_event->common_header_len;
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
if (!remote_opt)
ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
else
@@ -863,6 +877,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
break;
case BEGIN_LOAD_QUERY_EVENT:
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
OK_CONTINUE)
goto end;
@@ -878,6 +894,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
{
convert_path_to_forward_slashes(fname);
exlq->print(result_file, print_event_info, fname);
+ if (head->error == -1)
+ {
+ if (fname)
+ my_free(fname, MYF(MY_WME));
+ goto err;
+ }
}
else
warning("Ignoring Execute_load_query since there is no "
@@ -973,6 +995,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
default:
ev->print(result_file, print_event_info);
+ if (head->error == -1)
+ goto err;
}
}
@@ -1135,7 +1159,7 @@ static struct my_option my_long_options[] =
"Stop reading the binlog at position N. Applies to the last binlog "
"passed on the command line.",
&stop_position, &stop_position, 0, GET_ULL,
- REQUIRED_ARG, (ulonglong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
+ REQUIRED_ARG, (longlong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
(ulonglong)(~(my_off_t)0), 0, 0, 0},
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
requested binlog but rather continue printing until the end of the last \
@@ -2018,7 +2042,13 @@ err:
end:
if (fd >= 0)
my_close(fd, MYF(MY_WME));
- end_io_cache(file);
+ /*
+ Since the end_io_cache() writes to the
+ file errors may happen.
+ */
+ if (end_io_cache(file))
+ retval= ERROR_STOP;
+
return retval;
}
diff --git a/client/mysqldump.c b/client/mysqldump.c
index db954304ad8..38c0fb0d0bc 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -82,6 +82,15 @@
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
+/* general_log or slow_log tables under mysql database */
+static inline my_bool general_log_or_slow_log_tables(const char *db,
+ const char *table)
+{
+ return (strcmp(db, "mysql") == 0) &&
+ ((strcmp(table, "general_log") == 0) ||
+ (strcmp(table, "slow_log") == 0));
+}
+
static void add_load_option(DYNAMIC_STRING *str, const char *option,
const char *option_value);
static ulong find_set(TYPELIB *lib, const char *x, uint length,
@@ -2458,6 +2467,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
"TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'";
FILE *sql_file= md_result_file;
int len;
+ my_bool is_log_table;
MYSQL_RES *result;
MYSQL_ROW row;
DBUG_ENTER("get_table_structure");
@@ -2542,9 +2552,12 @@ static uint get_table_structure(char *table, char *db, char *table_type,
/*
Even if the "table" is a view, we do a DROP TABLE here. The
view-specific code below fills in the DROP VIEW.
+ We will skip the DROP TABLE for general_log and slow_log, since
+ those stmts will fail, in case we apply dump by enabling logging.
*/
- fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
- opt_quoted_table);
+ if (!general_log_or_slow_log_tables(db, table))
+ fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
+ opt_quoted_table);
check_io(sql_file);
}
@@ -2656,12 +2669,25 @@ static uint get_table_structure(char *table, char *db, char *table_type,
row= mysql_fetch_row(result);
- fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
- "/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
- "/*!40101 SET character_set_client = utf8 */;\n"
- "%s;\n"
- "/*!40101 SET character_set_client = @saved_cs_client */;\n",
- row[1]);
+ is_log_table= general_log_or_slow_log_tables(db, table);
+ if (is_log_table)
+ row[1]+= 13; /* strlen("CREATE TABLE ")= 13 */
+ if (opt_compatible_mode & 3)
+ {
+ fprintf(sql_file,
+ is_log_table ? "CREATE TABLE IF NOT EXISTS %s;\n" : "%s;\n",
+ row[1]);
+ }
+ else
+ {
+ fprintf(sql_file,
+ "/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
+ "/*!40101 SET character_set_client = utf8 */;\n"
+ "%s%s;\n"
+ "/*!40101 SET character_set_client = @saved_cs_client */;\n",
+ is_log_table ? "CREATE TABLE IF NOT EXISTS " : "",
+ row[1]);
+ }
check_io(sql_file);
mysql_free_result(result);
@@ -4261,6 +4287,22 @@ static int dump_all_tables_in_db(char *database)
if (opt_xml)
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
+ if (strcmp(database, "mysql") == 0)
+ {
+ char table_type[NAME_LEN];
+ char ignore_flag;
+ uint num_fields;
+ num_fields= get_table_structure((char *) "general_log",
+ database, table_type, &ignore_flag);
+ if (num_fields == 0)
+ verbose_msg("-- Warning: get_table_structure() failed with some internal "
+ "error for 'general_log' table\n");
+ num_fields= get_table_structure((char *) "slow_log",
+ database, table_type, &ignore_flag);
+ if (num_fields == 0)
+ verbose_msg("-- Warning: get_table_structure() failed with some internal "
+ "error for 'slow_log' table\n");
+ }
if (lock_tables)
{
DYNAMIC_STRING query;
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 8f955ff586b..7720a128270 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2009-2011 Monty Program Ab.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012 Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -6971,6 +6971,8 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
*/
if ((counter==0) && mysql_read_query_result(mysql))
{
+ /* we've failed to collect the result set */
+ cn->pending= TRUE;
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
diff --git a/configure.in b/configure.in
index 10eaaecbc21..71b0d095ac3 100644
--- a/configure.in
+++ b/configure.in
@@ -12,7 +12,7 @@ dnl
dnl When changing the major version number please also check the switch
dnl statement in mysqlbinlog::check_master_version(). You may also need
dnl to update version.c in ndb.
-AC_INIT([MariaDB Server], [5.1.63-MariaDB], [], [mysql])
+AC_INIT([MariaDB Server], [5.1.65-MariaDB], [], [mysql])
AC_CONFIG_SRCDIR([sql/mysqld.cc])
AC_CANONICAL_SYSTEM
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index a502666d15b..5ec4cac1c44 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -758,6 +758,10 @@ void CertDecoder::GetName(NameType nt)
while (source_.get_index() < length) {
GetSet();
+ if (source_.GetError().What() == SET_E) {
+ source_.SetError(NO_ERROR_E); // extensions may only have sequence
+ source_.prev();
+ }
GetSequence();
byte b = source_.next();
diff --git a/include/my_getopt.h b/include/my_getopt.h
index aeed8fa1586..a8d14c9aba5 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2002, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2002, 2012, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@ struct my_option
enum get_opt_arg_type arg_type;
longlong def_value; /* Default value */
longlong min_value; /* Min allowed value */
- longlong max_value; /* Max allowed value */
+ ulonglong max_value; /* Max allowed value */
longlong sub_size; /* Subtract this from given value */
long block_size; /* Value should be a mult. of this */
void *app_type; /* To be used by an application */
diff --git a/include/sql_common.h b/include/sql_common.h
index 9e43d076ba9..b64277ce7e1 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003-2004, 2006 MySQL AB
+/*
+ Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,8 +24,9 @@ extern "C" {
#endif
extern CHARSET_INFO *default_client_charset_info;
-MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
- my_bool default_value, uint server_capabilities);
+MYSQL_FIELD *unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,
+ uint fields, my_bool default_value,
+ uint server_capabilities);
void free_rows(MYSQL_DATA *cur);
void free_old_query(MYSQL *mysql);
void end_server(MYSQL *mysql);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 6c2f34e55a3..f21edbec578 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1265,7 +1265,7 @@ MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
return NULL;
mysql->field_count= (uint) query->rows;
- return unpack_fields(query,&mysql->field_alloc,
+ return unpack_fields(mysql, query,&mysql->field_alloc,
mysql->field_count, 1, mysql->server_capabilities);
}
@@ -1325,7 +1325,7 @@ mysql_list_processes(MYSQL *mysql)
if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0,
protocol_41(mysql) ? 7 : 5)))
DBUG_RETURN(NULL);
- if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
+ if (!(mysql->fields=unpack_fields(mysql, fields,&mysql->field_alloc,field_count,0,
mysql->server_capabilities)))
DBUG_RETURN(0);
mysql->status=MYSQL_STATUS_GET_RESULT;
@@ -1915,7 +1915,7 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
DBUG_RETURN(1);
- if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root,
+ if (!(stmt->fields= unpack_fields(mysql, fields_data,&stmt->mem_root,
field_count,0,
mysql->server_capabilities)))
DBUG_RETURN(1);
diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt
index 2b900a1fa8f..d7f994d9b9f 100644
--- a/libmysqld/examples/CMakeLists.txt
+++ b/libmysqld/examples/CMakeLists.txt
@@ -17,7 +17,8 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/libmysqld/include
${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/zlib
+ ${CMAKE_SOURCE_DIR}/zlib
+ ${CMAKE_SOURCE_DIR}/tests
${CMAKE_SOURCE_DIR}/extra/yassl/include)
# Currently does not work with DBUG, there are missing symbols reported.
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
index 6f0111f8bbc..1dc7cc3204f 100644
--- a/libmysqld/examples/Makefile.am
+++ b/libmysqld/examples/Makefile.am
@@ -35,7 +35,7 @@ link_sources:
DEFS = -DEMBEDDED_LIBRARY
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \
-I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \
- $(openssl_includes)
+ -I$(top_srcdir)/tests $(openssl_includes)
LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ $(yassl_libs)
LDADD = @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysqld/libmysqld.la @LIBDL@ $(CXXLDFLAGS) \
@@ -52,3 +52,4 @@ mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD)
mysql_client_test_embedded_LINK = $(CXXLINK)
nodist_mysql_client_test_embedded_SOURCES = mysql_client_test.c
+mysql_client_test.o: $(top_srcdir)/tests/mysql_client_fw.c
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index fda059a37f0..7e320e714bd 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -758,12 +758,6 @@ void THD::clear_data_list()
cur_data= 0;
}
-void THD::clear_error()
-{
- if (main_da.is_error())
- main_da.reset_diagnostics_area();
-}
-
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
diff --git a/mysql-test/include/mysqlbinlog_have_debug.inc b/mysql-test/include/mysqlbinlog_have_debug.inc
new file mode 100644
index 00000000000..14da1379ecd
--- /dev/null
+++ b/mysql-test/include/mysqlbinlog_have_debug.inc
@@ -0,0 +1,34 @@
+#############################################
+# checks if mysqlbinlog is debug compiled
+# this "cannot" be done simply by using
+# have_debug.inc
+#############################################
+
+--disable_query_log
+--let $temp_out_help_file=$MYSQL_TMP_DIR/mysqlbinlog_help.tmp
+--exec $MYSQL_BINLOG --help>$temp_out_help_file
+let log_tmp=$temp_out_help_file;
+--let $temp_inc=$MYSQL_TMP_DIR/temp.inc
+let inc_tmp=$temp_inc;
+
+--perl
+use strict;
+my $tmp_file= $ENV{'log_tmp'} or die "log_tmp not set";
+open(FILE, "$tmp_file") or die("Unable to open $tmp_file: $!\n");
+my $count = () = grep(/Output debug log/g,<FILE>);
+close FILE;
+
+my $temp_inc= $ENV{'inc_tmp'} or die "temp_inc not set";
+open(FILE_INC,">", "$temp_inc") or die("can't open file \"$temp_inc\": $!");
+print FILE_INC '--let $is_debug= '.$count;
+close FILE_INC;
+EOF
+--source $temp_inc
+
+if (!$is_debug)
+{
+ --skip mysqlbinlog needs to be debug compiled
+}
+--remove_file $temp_out_help_file
+--remove_file $temp_inc
+--enable_query_log
diff --git a/mysql-test/lib/My/Find.pm b/mysql-test/lib/My/Find.pm
index 5dea0537bc6..a636b0e88f7 100644
--- a/mysql-test/lib/My/Find.pm
+++ b/mysql-test/lib/My/Find.pm
@@ -126,9 +126,9 @@ sub my_find_file {
#
#
sub my_find_dir {
- my ($base, $paths, $dirs, $required)= @_;
- croak "usage: my_find_dir(<base>, <paths>[, <dirs>])"
- unless (@_ == 3 or @_ == 2);
+ my ($base, $paths, $dirs, $optional)= @_;
+ croak "usage: my_find_dir(<base>, <paths>[, <dirs>[, <optional>]])"
+ unless (@_ == 3 or @_ == 2 or @_ == 4);
# -------------------------------------------------------
# Find and return the first directory
@@ -136,6 +136,7 @@ sub my_find_dir {
foreach my $path (my_find_paths($base, $paths, $dirs)) {
return $path if ( -d $path );
}
+ return "" if $optional;
find_error($base, $paths, $dirs);
}
diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index 169e9a10d38..a09f8048324 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -127,6 +127,7 @@ sub collect_test_cases ($$$) {
{
push(@$cases, collect_one_suite($suite, $opt_cases));
last if $some_test_found;
+ push(@$cases, collect_one_suite("i_".$suite, $opt_cases));
}
}
@@ -280,10 +281,10 @@ sub collect_one_suite
$suitedir= my_find_dir($suitedir,
["suite",
".",
- # Look in storage engine specific suite dirs
- "../storage/*/mysql-test-suites"
+ "../internal/mysql-test/suite"
],
- [$suite]);
+ [$suite], ($suite =~ /^i_/));
+ return unless $suitedir;
}
mtr_verbose("suitedir: $suitedir");
}
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index b90eb2a4c0f..74899a22636 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1524,6 +1524,8 @@ DROP TABLE t1;
# Bug#43668: Wrong comparison and MIN/MAX for YEAR(2)
#
create table t1 (f1 year(2), f2 year(4), f3 date, f4 datetime);
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
insert into t1 values
(98,1998,19980101,"1998-01-01 00:00:00"),
(00,2000,20000101,"2000-01-01 00:00:01"),
diff --git a/mysql-test/r/func_group_innodb.result b/mysql-test/r/func_group_innodb.result
index 908e85c1652..e68242a8191 100644
--- a/mysql-test/r/func_group_innodb.result
+++ b/mysql-test/r/func_group_innodb.result
@@ -145,3 +145,43 @@ select count(*), min(7), max(7) from t2m, t1i;
count(*) min(7) max(7)
0 NULL NULL
drop table t1m, t1i, t2m, t2i;
+#
+# Bug#12713907: STRANGE OPTIMIZE & WRONG RESULT UNDER ORDER BY
+# COUNT(*) LIMIT.
+#
+CREATE TABLE t1 (
+id BIGINT(20) ,
+member_id_to INT(11) ,
+r_date DATE ,
+PRIMARY KEY (id,r_date),
+KEY r_date_idx (r_date),
+KEY t1_idx01 (member_id_to)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(107924526,518491,'2011-05-01'),
+(107924527,518491,'2011-05-01'),
+(107924528,518491,'2011-05-01'),
+(107924529,518491,'2011-05-01'),
+(107924530,518491,'2011-05-01'),
+(107924531,518491,'2011-05-01'),
+(107924532,518491,'2011-05-01'),
+(107924534,518491,'2011-06-21'),
+(107924535,518491,'2011-06-21'),
+(107924536,518491,'2011-06-21'),
+(107924537,518491,'2011-06-21'),
+(107924538,518491,'2011-06-21'),
+(107924542,1601319,'2011-06-21'),
+(107924543,1601319,'2011-06-21'),
+(107924544,1601319,'2011-06-21'),
+(107924545,1601319,'2011-06-21'),
+(107924546,1601319,'2011-06-21'),
+(107924547,1601319,'2011-06-21'),
+(107924548,1601319,'2011-06-21'),
+(107924549,1601319,'2011-06-21'),
+(107924550,1601319,'2011-06-21');
+SELECT member_id_to, COUNT(*) FROM t1 WHERE r_date =
+'2011-06-21' GROUP BY member_id_to ORDER BY 2 LIMIT 1;
+member_id_to COUNT(*)
+518491 5
+DROP TABLE t1;
+# End of test BUG#12713907
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index caf1acd6dc2..8412b87ea9a 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -5068,5 +5068,47 @@ RETURN CONCAT(']]]]><![CDATA[>, ', s, '!')
DROP DATABASE BUG52792;
USE test;
#
+# Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
+#
+SET @old_log_output_state= @@global.log_output;
+SET @old_general_log_state= @@global.general_log;
+SET @old_slow_query_log_state= @@global.slow_query_log;
+call mtr.add_suppression("Failed to write to mysql.general_log");
+SET @@global.log_output="TABLE";
+SET @@global.general_log='ON';
+SET @@global.slow_query_log='ON';
+DROP DATABASE mysql;
+Warnings:
+Error 1146 Table 'mysql.proc' doesn't exist
+Error 1146 Table 'mysql.event' doesn't exist
+SHOW CREATE TABLE mysql.general_log;
+Table Create Table
+general_log CREATE TABLE `general_log` (
+ `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `user_host` mediumtext NOT NULL,
+ `thread_id` int(11) NOT NULL,
+ `server_id` int(10) unsigned NOT NULL,
+ `command_type` varchar(64) NOT NULL,
+ `argument` mediumtext NOT NULL
+) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
+SHOW CREATE TABLE mysql.slow_log;
+Table Create Table
+slow_log CREATE TABLE `slow_log` (
+ `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `user_host` mediumtext NOT NULL,
+ `query_time` time NOT NULL,
+ `lock_time` time NOT NULL,
+ `rows_sent` int(11) NOT NULL,
+ `rows_examined` int(11) NOT NULL,
+ `db` varchar(512) NOT NULL,
+ `last_insert_id` int(11) NOT NULL,
+ `insert_id` int(11) NOT NULL,
+ `server_id` int(10) unsigned NOT NULL,
+ `sql_text` mediumtext NOT NULL
+) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
+SET @@global.log_output= @old_log_output_state;
+SET @@global.slow_query_log= @old_slow_query_log_state;
+SET @@global.general_log= @old_general_log_state;
+#
# End of 5.1 tests
#
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 84c64a3905a..60370e4b708 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -3040,3 +3040,106 @@ id select_type table type possible_keys key key_len ref rows Extra
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
End of 5.1 tests.
+
+# Bug#13805127: Stored program cache produces wrong result in same THD
+
+PREPARE s1 FROM
+"
+SELECT c1, t2.c2, count(c3)
+FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE @x = 1
+ UNION
+ SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2
+";
+
+SET @x = 1;
+SELECT c1, t2.c2, count(c3)
+FROM
+(
+SELECT 3 as c2 FROM dual WHERE @x = 1
+UNION
+SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+) AS t1,
+(
+SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+UNION
+SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+UNION
+SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+
+EXECUTE s1;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+
+SET @x = 2;
+SELECT c1, t2.c2, count(c3)
+FROM
+(
+SELECT 3 as c2 FROM dual WHERE @x = 1
+UNION
+SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+) AS t1,
+(
+SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+UNION
+SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+UNION
+SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+
+EXECUTE s1;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+
+SET @x = 1;
+SELECT c1, t2.c2, count(c3)
+FROM
+(
+SELECT 3 as c2 FROM dual WHERE @x = 1
+UNION
+SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+) AS t1,
+(
+SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+UNION
+SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+UNION
+SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+
+EXECUTE s1;
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+DEALLOCATE PREPARE s1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 11d6ff02756..0d0d76e609b 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -7110,3 +7110,41 @@ DROP FUNCTION f1;
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+
+# Bug#13805127: Stored program cache produces wrong result in same THD
+
+CREATE PROCEDURE p1(x INT UNSIGNED)
+BEGIN
+SELECT c1, t2.c2, count(c3)
+FROM
+(
+SELECT 3 as c2 FROM dual WHERE x = 1
+UNION
+SELECT 2 FROM dual WHERE x = 1 OR x = 2
+) AS t1,
+(
+SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+UNION
+SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+UNION
+SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2
+;
+END|
+
+CALL p1(1);
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+CALL p1(2);
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+CALL p1(1);
+c1 c2 count(c3)
+2012-03-01 01:00:00 2 1
+2012-03-01 01:00:00 3 1
+2012-03-01 02:00:00 3 1
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index e6fd49b4247..8b4b6438842 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -878,6 +878,8 @@ ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT
CREATE TABLE b15776 (a char(4294967296));
ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
CREATE TABLE b15776 (a year(4294967295));
+Warnings:
+Note 1287 'YEAR(4294967295)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO b15776 VALUES (42);
SELECT * FROM b15776;
a
@@ -886,6 +888,8 @@ DROP TABLE b15776;
CREATE TABLE b15776 (a year(4294967296));
ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
CREATE TABLE b15776 (a year(0));
+Warnings:
+Note 1287 'YEAR(0)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
DROP TABLE b15776;
CREATE TABLE b15776 (a year(-2));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2))' at line 1
diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result
index 2dc491c6166..e00569c93c1 100644
--- a/mysql-test/r/type_year.result
+++ b/mysql-test/r/type_year.result
@@ -1,5 +1,7 @@
drop table if exists t1;
create table t1 (y year,y2 year(2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
insert into t1 values (0,0),(1999,1999),(2000,2000),(2001,2001),(70,70),(69,69);
select * from t1;
y y2
@@ -50,6 +52,8 @@ End of 5.0 tests
# Bug #49480: WHERE using YEAR columns returns unexpected results
#
CREATE TABLE t2(yy YEAR(2), c2 CHAR(4));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4));
INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069);
INSERT INTO t4 (c4) SELECT c2 FROM t2;
@@ -355,4 +359,15 @@ total_rows min_value MAX(c1)
3 0 2155
DROP TABLE t1;
#
+# WL#6219: Deprecate and remove YEAR(2) type
+#
+CREATE TABLE t1 (c1 YEAR(2), c2 YEAR(4));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+ALTER TABLE t1 MODIFY COLUMN c2 YEAR(2);
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+DROP TABLE t1;
+#
End of 5.1 tests
diff --git a/mysql-test/suite/binlog/r/binlog_grant.result b/mysql-test/suite/binlog/r/binlog_grant.result
index 21ebb891103..38442349d3b 100644
--- a/mysql-test/suite/binlog/r/binlog_grant.result
+++ b/mysql-test/suite/binlog/r/binlog_grant.result
@@ -26,3 +26,7 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation
**** Clean up ****
set global binlog_format = @saved_binlog_format;
drop user mysqltest_1@localhost;
+GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost';
+SHOW MASTER LOGS;
+SHOW BINARY LOGS;
+DROP USER 'mysqltest_1'@'localhost';
diff --git a/mysql-test/suite/binlog/t/binlog_grant.test b/mysql-test/suite/binlog/t/binlog_grant.test
index d36dcce4cc3..bbf57b075af 100644
--- a/mysql-test/suite/binlog/t/binlog_grant.test
+++ b/mysql-test/suite/binlog/t/binlog_grant.test
@@ -58,3 +58,22 @@ disconnect root;
connection default;
set global binlog_format = @saved_binlog_format;
drop user mysqltest_1@localhost;
+
+
+# Testing if REPLICATION CLIENT privilege is enough to execute
+# SHOW MASTER LOGS and SHOW BINARY.
+GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost';
+--connect(rpl,localhost,mysqltest_1,,)
+
+--connection rpl
+# We are only interested if the following commands succeed and not on
+# their output.
+--disable_result_log
+SHOW MASTER LOGS;
+SHOW BINARY LOGS;
+--enable_result_log
+
+# clean up
+--disconnect rpl
+connection default;
+DROP USER 'mysqltest_1'@'localhost';
diff --git a/mysql-test/suite/engines/iuds/r/delete_year.result b/mysql-test/suite/engines/iuds/r/delete_year.result
index 02cbe24ecc9..c82f0dae7d9 100644
--- a/mysql-test/suite/engines/iuds/r/delete_year.result
+++ b/mysql-test/suite/engines/iuds/r/delete_year.result
@@ -2,7 +2,13 @@ DROP TABLE IF EXISTS t1,t2,t3,t4;
CREATE TABLE t1(c1 YEAR NOT NULL,c2 YEAR, PRIMARY KEY(c1));
CREATE TABLE t2(c1 YEAR NOT NULL, c2 YEAR, UNIQUE INDEX idx(c1,c2));
CREATE TABLE t3(c1 YEAR(2) NOT NULL,c2 YEAR(2), PRIMARY KEY(c1));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t4(c1 YEAR(2), c2 YEAR(2), UNIQUE INDEX idx(c1,c2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO t1 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
INSERT INTO t2 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
INSERT INTO t3 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
diff --git a/mysql-test/suite/engines/iuds/r/insert_year.result b/mysql-test/suite/engines/iuds/r/insert_year.result
index 386c8090434..b9618ba4e2d 100644
--- a/mysql-test/suite/engines/iuds/r/insert_year.result
+++ b/mysql-test/suite/engines/iuds/r/insert_year.result
@@ -3235,9 +3235,21 @@ c1 c2 c3 c4
1999 1999 1998-12-30 1998-12-30 11:30:45
DROP TABLE t1,t2,t3,t4;
CREATE TABLE t1(c1 YEAR(2) NOT NULL, c2 YEAR(2) NULL, c3 DATE, c4 DATETIME, PRIMARY KEY(c1), UNIQUE INDEX(c2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t2(c1 YEAR(2) NOT NULL, c2 YEAR(2) NULL, c3 DATE, c4 DATETIME, PRIMARY KEY(c1,c2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t3(c1 YEAR(2) NOT NULL, c2 YEAR(2) NULL, c3 DATE, c4 DATETIME, UNIQUE INDEX idx(c1,c2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t4(c1 YEAR(2) NOT NULL, c2 YEAR(2) NULL, c3 DATE, c4 DATETIME);
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO t1 VALUES('1901','1901','98-12-31','98.12.31 11:30:45'),('1999','1999','98-12-30','98.12.30 11:30:45'),('2000','2000','98-12-29','98.12.29 11:30:45'),('2001','2001','98-12-28','98.12.28 11:30:45'),('2099','2099','98-12-27','98.12.27 11:30:45'),('2100','2100','98-12-26','98.12.26 11:30:45'),('2155','2155','98-12-26','98.12.26 11:30:45');
INSERT INTO t2 VALUES('1901','1901','98-12-31','98.12.31 11:30:45'),('1999','1999','98-12-30','98.12.30 11:30:45'),('2000','2000','98-12-29','98.12.29 11:30:45'),('2001','2001','98-12-28','98.12.28 11:30:45'),('2099','2099','98-12-27','98.12.27 11:30:45'),('2100','2100','98-12-26','98.12.26 11:30:45'),('2155','2155','98-12-26','98.12.26 11:30:45');
INSERT INTO t3 VALUES('1901','1901','98-12-31','98.12.31 11:30:45'),('1999','1999','98-12-30','98.12.30 11:30:45'),('2000','2000','98-12-29','98.12.29 11:30:45'),('2001','2001','98-12-28','98.12.28 11:30:45'),('2099','2099','98-12-27','98.12.27 11:30:45'),('2100','2100','98-12-26','98.12.26 11:30:45'),('2155','2155','98-12-26','98.12.26 11:30:45');
diff --git a/mysql-test/suite/engines/iuds/r/update_year.result b/mysql-test/suite/engines/iuds/r/update_year.result
index 1b0ead45314..c762d70a276 100644
--- a/mysql-test/suite/engines/iuds/r/update_year.result
+++ b/mysql-test/suite/engines/iuds/r/update_year.result
@@ -2,7 +2,13 @@ DROP TABLE IF EXISTS t1,t2,t3,t4;
CREATE TABLE t1(c1 YEAR NOT NULL,c2 YEAR, PRIMARY KEY(c1));
CREATE TABLE t2(c1 YEAR NOT NULL, c2 YEAR, UNIQUE INDEX idx(c1,c2));
CREATE TABLE t3(c1 YEAR(2) NOT NULL,c2 YEAR(2), PRIMARY KEY(c1));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CREATE TABLE t4(c1 YEAR(2), c2 YEAR(2), UNIQUE INDEX idx(c1,c2));
+Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO t1 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
INSERT INTO t2 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
INSERT INTO t3 VALUES (1901,1901),(1970,1970),(1999,1999),(2000,2000),(2155,2155);
diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result
index a335e135a4f..951068e3300 100644
--- a/mysql-test/suite/funcs_1/r/innodb_views.result
+++ b/mysql-test/suite/funcs_1/r/innodb_views.result
@@ -53,6 +53,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = innodb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/innodb_tb2.txt'
into table tb2;
DROP DATABASE IF EXISTS test1;
@@ -112,6 +114,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = innodb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/innodb_tb2.txt'
into table tb2;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_innodb.result b/mysql-test/suite/funcs_1/r/is_columns_innodb.result
index 61079b06666..0abe8e11cf3 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_innodb.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_innodb.result
@@ -132,6 +132,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = innodb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/innodb_tb2.txt'
into table tb2;
drop table if exists tb3 ;
@@ -262,6 +264,8 @@ f239 varchar(20000) binary,
f240 varchar(2000),
f241 char(100)
) engine = innodb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/innodb_tb4.txt'
into table tb4;
USE test1;
@@ -319,6 +323,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = innodb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/innodb_tb2.txt'
into table tb2;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_memory.result b/mysql-test/suite/funcs_1/r/is_columns_memory.result
index 60dea25e0e3..c476b930f60 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_memory.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_memory.result
@@ -128,6 +128,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = memory;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/memory_tb2.txt'
into table tb2 ;
drop table if exists tb3;
@@ -251,6 +253,8 @@ f238 varchar(25000) binary,
f239 varbinary(0),
f240 varchar(1200)
) engine = memory;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/memory_tb4.txt'
into table tb4;
USE test1;
@@ -308,6 +312,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = memory;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/memory_tb2.txt'
into table tb2 ;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_myisam.result b/mysql-test/suite/funcs_1/r/is_columns_myisam.result
index 6d0a44d2223..0e464d0fbc1 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_myisam.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_myisam.result
@@ -144,6 +144,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
drop table if exists tb3 ;
@@ -283,6 +285,8 @@ f240 varchar(120),
f241 char(100),
f242 bit(30)
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb4.txt'
into table tb4;
USE test1;
@@ -348,6 +352,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result
index 739f62e371a..7424ba8573d 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result
@@ -144,6 +144,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
drop table if exists tb3 ;
@@ -283,6 +285,8 @@ f240 varchar(120),
f241 char(100),
f242 bit(30)
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb4.txt'
into table tb4;
USE test1;
@@ -348,6 +352,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result
index ccbd086b71f..0bb03e62192 100644
--- a/mysql-test/suite/funcs_1/r/memory_views.result
+++ b/mysql-test/suite/funcs_1/r/memory_views.result
@@ -54,6 +54,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = memory;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/memory_tb2.txt'
into table tb2 ;
DROP DATABASE IF EXISTS test1;
@@ -113,6 +115,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = memory;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/memory_tb2.txt'
into table tb2 ;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/myisam_views-big.result b/mysql-test/suite/funcs_1/r/myisam_views-big.result
index 9b07a0ae45b..0afb1d7d6c8 100644
--- a/mysql-test/suite/funcs_1/r/myisam_views-big.result
+++ b/mysql-test/suite/funcs_1/r/myisam_views-big.result
@@ -62,6 +62,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
DROP DATABASE IF EXISTS test1;
@@ -129,6 +131,8 @@ f115 VARBINARY(27) null ,
f116 VARBINARY(64) null,
f117 VARBINARY(192) null
) engine = myisam;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/myisam_tb2.txt'
into table tb2;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/ndb_views.result b/mysql-test/suite/funcs_1/r/ndb_views.result
index b75f4955986..17eaedce56b 100644
--- a/mysql-test/suite/funcs_1/r/ndb_views.result
+++ b/mysql-test/suite/funcs_1/r/ndb_views.result
@@ -53,6 +53,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = ndb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/ndb_tb2.txt'
into table tb2 ;
DROP DATABASE IF EXISTS test1;
@@ -112,6 +114,8 @@ f107 year(4) not null default 2000,
f108 enum("1enum","2enum") not null default "1enum",
f109 set("1set","2set") not null default "1set"
) engine = ndb;
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
load data infile '<MYSQLTEST_VARDIR>/std_data/funcs_1/ndb_tb2.txt'
into table tb2 ;
USE test;
diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result
index 8da7213bded..7647579820a 100644
--- a/mysql-test/suite/funcs_1/r/storedproc.result
+++ b/mysql-test/suite/funcs_1/r/storedproc.result
@@ -7526,9 +7526,13 @@ BEGIN
declare x, y, z year(3) default 2005;
SELECT x, y, z;
END//
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
CALL sp1();
x y z
2005 2005 2005
+Warnings:
+Note 1287 'YEAR(3)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
BEGIN
diff --git a/mysql-test/suite/innodb/r/innodb_bug14007649.result b/mysql-test/suite/innodb/r/innodb_bug14007649.result
new file mode 100644
index 00000000000..1f802dcd146
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_bug14007649.result
@@ -0,0 +1,56 @@
+create table t1 (
+rowid int,
+f1 int,
+f2 int,
+key i1 (f1, f2),
+key i2 (f2)) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `rowid` int(11) DEFAULT NULL,
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL,
+ KEY `i1` (`f1`,`f2`),
+ KEY `i2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
+start transaction with consistent snapshot;
+start transaction;
+update t1 set f2 = 4 where f1 = 1 and f2 is null;
+(b) Number of rows updated:
+select row_count();
+row_count()
+1
+insert into t1 values (3, 1, null);
+(b) After update and insert query.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 4
+3 1 NULL
+commit;
+(a) Before the update statement is executed.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 NULL
+SET SESSION debug="+d,bug14007649";
+update t1 set f2 = 6 where f1 = 1 and f2 is null;
+(a) Number of rows updated:
+select row_count();
+row_count()
+1
+(a) After the update statement is executed.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 NULL
+3 1 6
+commit;
+"The trx with consistent snapshot ended."
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 4
+3 1 6
+drop table t1;
diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def
index 46309c92bbe..1d25fbf14c0 100644
--- a/mysql-test/suite/innodb/t/disabled.def
+++ b/mysql-test/suite/innodb/t/disabled.def
@@ -14,3 +14,6 @@ innodb_bug13635833: Disabled until merging with XtraDB 5.1.63
innodb-lock: Disabled until merging with XtraDB 5.1.60
innodb_replace: Disabled until merging with XtraDB 5.1.60
+
+innodb_bug14007649: Disabled until merging with XtraDB 5.1.65
+
diff --git a/mysql-test/suite/innodb/t/innodb_bug14007649.test b/mysql-test/suite/innodb/t/innodb_bug14007649.test
new file mode 100644
index 00000000000..2832bd41f3c
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_bug14007649.test
@@ -0,0 +1,58 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+
+create table t1 (
+ rowid int,
+ f1 int,
+ f2 int,
+ key i1 (f1, f2),
+ key i2 (f2)) engine=innodb;
+
+show create table t1;
+insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+
+connection a;
+start transaction with consistent snapshot;
+
+connection b;
+start transaction;
+update t1 set f2 = 4 where f1 = 1 and f2 is null;
+
+-- echo (b) Number of rows updated:
+select row_count();
+
+insert into t1 values (3, 1, null);
+
+-- echo (b) After update and insert query.
+select rowid, f1, f2 from t1;
+
+commit;
+
+connection a;
+
+-- echo (a) Before the update statement is executed.
+select rowid, f1, f2 from t1;
+
+SET SESSION debug="+d,bug14007649";
+update t1 set f2 = 6 where f1 = 1 and f2 is null;
+
+-- echo (a) Number of rows updated:
+select row_count();
+
+-- echo (a) After the update statement is executed.
+select rowid, f1, f2 from t1;
+
+commit;
+
+--echo "The trx with consistent snapshot ended."
+
+select rowid, f1, f2 from t1;
+
+connection default;
+disconnect a;
+disconnect b;
+
+drop table t1;
diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result b/mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result
new file mode 100644
index 00000000000..1f802dcd146
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result
@@ -0,0 +1,56 @@
+create table t1 (
+rowid int,
+f1 int,
+f2 int,
+key i1 (f1, f2),
+key i2 (f2)) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `rowid` int(11) DEFAULT NULL,
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL,
+ KEY `i1` (`f1`,`f2`),
+ KEY `i2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
+start transaction with consistent snapshot;
+start transaction;
+update t1 set f2 = 4 where f1 = 1 and f2 is null;
+(b) Number of rows updated:
+select row_count();
+row_count()
+1
+insert into t1 values (3, 1, null);
+(b) After update and insert query.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 4
+3 1 NULL
+commit;
+(a) Before the update statement is executed.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 NULL
+SET SESSION debug="+d,bug14007649";
+update t1 set f2 = 6 where f1 = 1 and f2 is null;
+(a) Number of rows updated:
+select row_count();
+row_count()
+1
+(a) After the update statement is executed.
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 NULL
+3 1 6
+commit;
+"The trx with consistent snapshot ended."
+select rowid, f1, f2 from t1;
+rowid f1 f2
+1 1 10
+2 1 4
+3 1 6
+drop table t1;
diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
index 74db8b0c20a..927ba0e0e53 100644
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
@@ -58,6 +58,7 @@ col89 float unsigned zerofill DEFAULT NULL,
col90 tinyblob
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
Warnings:
+Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
Note 1291 Column 'col82' has duplicated value '' in ENUM
Note 1291 Column 'col82' has duplicated value '' in ENUM
INSERT INTO bug52745 SET
diff --git a/mysql-test/suite/innodb_plugin/t/disabled.def b/mysql-test/suite/innodb_plugin/t/disabled.def
index a8f74a04a53..a849d589fb2 100644
--- a/mysql-test/suite/innodb_plugin/t/disabled.def
+++ b/mysql-test/suite/innodb_plugin/t/disabled.def
@@ -17,3 +17,4 @@ innodb-index: Disabled until merging with XtraDB 5.1.60
innodb-lock: Disabled until merging with XtraDB 5.1.60
innodb_replace: Disabled until merging with XtraDB 5.1.60
innodb-blob: Disabled until merging with XtraDB 5.1.63
+innodb_bug14007649: Disabled until merging with XtraDB 5.1.65
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test b/mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test
new file mode 100644
index 00000000000..e1d27ecd742
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test
@@ -0,0 +1,58 @@
+--source include/have_innodb_plugin.inc
+--source include/have_debug.inc
+
+create table t1 (
+ rowid int,
+ f1 int,
+ f2 int,
+ key i1 (f1, f2),
+ key i2 (f2)) engine=innodb;
+
+show create table t1;
+insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+
+connection a;
+start transaction with consistent snapshot;
+
+connection b;
+start transaction;
+update t1 set f2 = 4 where f1 = 1 and f2 is null;
+
+-- echo (b) Number of rows updated:
+select row_count();
+
+insert into t1 values (3, 1, null);
+
+-- echo (b) After update and insert query.
+select rowid, f1, f2 from t1;
+
+commit;
+
+connection a;
+
+-- echo (a) Before the update statement is executed.
+select rowid, f1, f2 from t1;
+
+SET SESSION debug="+d,bug14007649";
+update t1 set f2 = 6 where f1 = 1 and f2 is null;
+
+-- echo (a) Number of rows updated:
+select row_count();
+
+-- echo (a) After the update statement is executed.
+select rowid, f1, f2 from t1;
+
+commit;
+
+--echo "The trx with consistent snapshot ended."
+
+select rowid, f1, f2 from t1;
+
+connection default;
+disconnect a;
+disconnect b;
+
+drop table t1;
diff --git a/mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result b/mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result
new file mode 100644
index 00000000000..e2b3206eb02
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result
@@ -0,0 +1,36 @@
+include/master-slave.inc
+[connection master]
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam;
+create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb;
+ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
+create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb;
+set @@binlog_format=statement;
+*** autoincrement field is not the first in PK warning must be there: ***
+insert into tm set b=null, a=1;
+Warnings:
+Note 1592 Statement may not be safe to log in statement format.
+show warnings;
+Level Code Message
+Note 1592 Statement may not be safe to log in statement format.
+*** no warning when autoincrement is the first in PK
+insert into ti set b=null, a=1;
+show warnings;
+Level Code Message
+create function multi_part_pk_with_autoinc (arg int)
+returns int
+begin
+insert into tm set b=null, a=arg;
+return arg;
+end//
+select multi_part_pk_with_autoinc (3);
+multi_part_pk_with_autoinc (3)
+3
+*** No warnings in 5.1 because of Bug11749859-39934 ***
+show warnings;
+Level Code Message
+set @@binlog_format=mixed;
+insert into tm set b=null, a=2;
+drop table tm, ti;
+drop function multi_part_pk_with_autoinc;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result b/mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
index c88dcee9dbc..baf0cf81cec 100644
--- a/mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
+++ b/mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
@@ -114,4 +114,24 @@ id c
3 3
[on master]
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT);
+CREATE TABLE test.t1 (a INT);
+INSERT INTO test.t1 VALUES(1);
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT);
+CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW
+INSERT INTO test.t_slave VALUES(NULL, RAND(), @c);
+SET INSERT_ID=2;
+SET @c=2;
+SET @@rand_seed1=10000000, @@rand_seed2=1000000;
+INSERT INTO t5 VALUES (NULL, RAND(), @c);
+SELECT b into @b FROM test.t5;
+UPDATE test.t1 SET a=2;
+SELECT a AS 'ONE' into @a FROM test.t_slave;
+SELECT c AS 'NULL' into @c FROM test.t_slave;
+SELECT b into @b FROM test.t_slave;
+include/assert.inc [Random values from master and slave must be different]
+drop table test.t5;
+drop table test.t1;
+drop table test.t_slave;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_log_pos.result b/mysql-test/suite/rpl/r/rpl_log_pos.result
index 58d0e202110..f07eaac94e9 100644
--- a/mysql-test/suite/rpl/r/rpl_log_pos.result
+++ b/mysql-test/suite/rpl/r/rpl_log_pos.result
@@ -11,7 +11,7 @@ include/stop_slave.inc
change master to master_log_pos=MASTER_LOG_POS;
start slave;
include/wait_for_slave_io_error.inc [errno=1236]
-Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master''
+Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event''
include/stop_slave_sql.inc
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result
index 7a7f8141ac8..6d68a094594 100644
--- a/mysql-test/suite/rpl/r/rpl_packet.result
+++ b/mysql-test/suite/rpl/r/rpl_packet.result
@@ -1,7 +1,7 @@
include/master-slave.inc
[connection master]
-call mtr.add_suppression("Slave I/O: Got a packet bigger than 'max_allowed_packet' bytes, Error_code: 1153");
-call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log:");
+call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, Error_code: 1153");
+call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet");
drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
SET @@global.max_allowed_packet=1024;
@@ -30,14 +30,14 @@ include/start_slave.inc
CREATE TABLE `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
include/wait_for_slave_io_error.inc [errno=1153]
-Last_IO_Error = 'Got a packet bigger than 'max_allowed_packet' bytes'
+Last_IO_Error = 'Got a packet bigger than 'slave_max_allowed_packet' bytes'
include/stop_slave_sql.inc
include/rpl_reset.inc
DROP TABLE t1;
CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM;
INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet));
-include/wait_for_slave_io_error.inc [errno=1236]
-Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master''
+include/wait_for_slave_io_error.inc [errno=1153]
+Last_IO_Error = 'Got a packet bigger than 'slave_max_allowed_packet' bytes'
STOP SLAVE;
RESET SLAVE;
RESET MASTER;
@@ -52,6 +52,7 @@ SET @@global.max_allowed_packet= 1024;
Warnings:
Warning 1105 The value of 'max_allowed_packet' should be no less than the value of 'net_buffer_length'
SET @@global.net_buffer_length= 1024;
+SET @@global.slave_max_allowed_packet= 1073741824;
DROP TABLE t1;
RESET SLAVE;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_show_binlog_events_purge_logs.result b/mysql-test/suite/rpl/r/rpl_parallel_show_binlog_events_purge_logs.result
new file mode 100644
index 00000000000..b69deb17c4c
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_show_binlog_events_purge_logs.result
@@ -0,0 +1,13 @@
+include/master-slave.inc
+[connection master]
+[connection slave]
+SET DEBUG_SYNC= 'after_show_binlog_events SIGNAL on_show_binlog_events WAIT_FOR end';
+SHOW BINLOG EVENTS;
+[connection slave1]
+SET DEBUG_SYNC= 'now WAIT_FOR on_show_binlog_events';
+FLUSH LOGS;
+SET DEBUG_SYNC= 'now SIGNAL end';
+SET DEBUG_SYNC= 'RESET';
+[connection slave]
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
new file mode 100644
index 00000000000..0df086ddbfa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
@@ -0,0 +1,62 @@
+# Test of auto-increment.
+#
+# BUG#11754117-45670
+# Multipart primary key with the autoincrement part not first in it
+# is replication unsafe.
+#
+
+source include/master-slave.inc;
+source include/have_binlog_format_mixed.inc;
+source include/have_innodb.inc;
+
+call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
+
+--connection master
+create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam;
+--error ER_WRONG_AUTO_KEY
+create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb;
+create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb;
+
+set @@binlog_format=statement;
+--echo *** autoincrement field is not the first in PK warning must be there: ***
+insert into tm set b=null, a=1;
+show warnings;
+--echo *** no warning when autoincrement is the first in PK
+insert into ti set b=null, a=1;
+show warnings;
+
+delimiter //;
+create function multi_part_pk_with_autoinc (arg int)
+returns int
+begin
+ insert into tm set b=null, a=arg;
+ return arg;
+end//
+delimiter ;//
+
+select multi_part_pk_with_autoinc (3);
+--echo *** No warnings in 5.1 because of Bug11749859-39934 ***
+show warnings;
+
+set @@binlog_format=mixed;
+insert into tm set b=null, a=2;
+
+sync_slave_with_master;
+
+if (`select count(*) <> 3 from tm`)
+{
+ --echo Wrong result from SELECT on the slave side.
+ select * from tm;
+ --die
+}
+
+# cleanup
+
+--connection master
+
+drop table tm, ti;
+drop function multi_part_pk_with_autoinc;
+
+sync_slave_with_master;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
index 13c66f9f64b..3572dd53ea7 100644
--- a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
+++ b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
@@ -206,4 +206,65 @@ SELECT * FROM t3;
connection master;
echo [on master];
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+--sync_slave_with_master
+
+#
+# BUG#11754117 - 45670: INTVAR_EVENTS FOR FILTERED-OUT QUERY_LOG_EVENTS ARE EXECUTED
+# Int-, Rand- and User- var events accompaning a filtered out Query-log-event should
+# be filtered as well.
+#
+connection master;
+# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D.
+CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT); # ignored on slave
+CREATE TABLE test.t1 (a INT); # accepted on slave
+INSERT INTO test.t1 VALUES(1);
+
+--sync_slave_with_master
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D.
+CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT);
+CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW
+ INSERT INTO test.t_slave VALUES(NULL, RAND(), @c);
+
+connection master;
+SET INSERT_ID=2;
+SET @c=2;
+SET @@rand_seed1=10000000, @@rand_seed2=1000000;
+INSERT INTO t5 VALUES (NULL, RAND(), @c); # to be ignored
+SELECT b into @b FROM test.t5;
+--let $b_master=`select @b`
+UPDATE test.t1 SET a=2; # to run trigger on slave
+
+--sync_slave_with_master
+
+# The proof:
+SELECT a AS 'ONE' into @a FROM test.t_slave;
+SELECT c AS 'NULL' into @c FROM test.t_slave;
+
+let $count= 1;
+let $table= test.t_slave;
+source include/wait_until_rows_count.inc;
+
+if (`SELECT @a != 2 and @c != NULL`)
+{
+ SELECT * FROM test.t_slave;
+ --die Intvar or user var from replication events unexpetedly escaped out to screw a following query applying context.
+}
+
+SELECT b into @b FROM test.t_slave;
+--let $b_slave=`select @b`
+
+--let $assert_text= Random values from master and slave must be different
+--let $assert_cond= $b_master != $b_slave
+--source include/assert.inc
+
+# cleanup BUG#11754117
+connection master;
+drop table test.t5;
+drop table test.t1;
+
+--sync_slave_with_master
+drop table test.t_slave;
+
--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_packet-slave.opt b/mysql-test/suite/rpl/t/rpl_packet-slave.opt
index 42d4f94c999..e0a7a203f99 100644
--- a/mysql-test/suite/rpl/t/rpl_packet-slave.opt
+++ b/mysql-test/suite/rpl/t/rpl_packet-slave.opt
@@ -1 +1 @@
--O max_allowed_packet=1024 -O net_buffer_length=1024
+-O max_allowed_packet=1024 -O net_buffer_length=1024 -O slave_max_allowed_packet=1024
diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test
index 3197b6160cd..7fbea87f71e 100644
--- a/mysql-test/suite/rpl/t/rpl_packet.test
+++ b/mysql-test/suite/rpl/t/rpl_packet.test
@@ -11,9 +11,8 @@
# max-out size db name
source include/master-slave.inc;
source include/have_binlog_format_row.inc;
-call mtr.add_suppression("Slave I/O: Got a packet bigger than 'max_allowed_packet' bytes, Error_code: 1153");
-call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log:");
-
+call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, Error_code: 1153");
+call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet");
let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
disable_warnings;
eval drop database if exists $db;
@@ -23,6 +22,7 @@ eval create database $db;
connection master;
let $old_max_allowed_packet= `SELECT @@global.max_allowed_packet`;
let $old_net_buffer_length= `SELECT @@global.net_buffer_length`;
+let $old_slave_max_allowed_packet= `SELECT @@global.slave_max_allowed_packet`;
SET @@global.max_allowed_packet=1024;
SET @@global.net_buffer_length=1024;
@@ -124,8 +124,8 @@ INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), R
connection slave;
# The slave I/O thread must stop after receiving
-# 1236=ER_MASTER_FATAL_ERROR_READING_BINLOG error message from master.
---let $slave_io_errno= 1236
+# 1153 = ER_NET_PACKET_TOO_LARGE
+--let $slave_io_errno= 1153
--let $show_slave_io_error= 1
--source include/wait_for_slave_io_error.inc
@@ -166,6 +166,7 @@ connection master;
DROP TABLE t1;
eval SET @@global.max_allowed_packet= $old_max_allowed_packet;
eval SET @@global.net_buffer_length= $old_net_buffer_length;
+eval SET @@global.slave_max_allowed_packet= $old_slave_max_allowed_packet;
# slave is stopped
connection slave;
DROP TABLE t1;
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test
new file mode 100644
index 00000000000..16d986268c9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test
@@ -0,0 +1,35 @@
+# BUG#13979418: SHOW BINLOG EVENTS MAY CRASH THE SERVER
+#
+# The function mysql_show_binlog_events has a local stack variable
+# 'LOG_INFO linfo;', which is assigned to thd->current_linfo, however
+# this variable goes out of scope and is destroyed before clean
+# thd->current_linfo.
+#
+# This test case runs SHOW BINLOG EVENTS and FLUSH LOGS to make sure
+# that with the fix local variable linfo is valid along all
+# mysql_show_binlog_events function scope.
+#
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--echo [connection slave]
+--connection slave
+SET DEBUG_SYNC= 'after_show_binlog_events SIGNAL on_show_binlog_events WAIT_FOR end';
+--send SHOW BINLOG EVENTS
+
+--connection slave1
+--echo [connection slave1]
+SET DEBUG_SYNC= 'now WAIT_FOR on_show_binlog_events';
+FLUSH LOGS;
+SET DEBUG_SYNC= 'now SIGNAL end';
+SET DEBUG_SYNC= 'RESET';
+
+--echo [connection slave]
+--connection slave
+--disable_result_log
+--reap
+--enable_result_log
+SET DEBUG_SYNC= 'RESET';
+
+--connection master
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result b/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result
new file mode 100644
index 00000000000..4a7849c0337
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result
@@ -0,0 +1,139 @@
+SET @start_value = @@global.slave_max_allowed_packet;
+SELECT @start_value;
+@start_value
+1073741824
+'#--------------------FN_DYNVARS_072_01------------------------#'
+SET @@global.slave_max_allowed_packet = 5000;
+SET @@global.slave_max_allowed_packet = DEFAULT;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+'#---------------------FN_DYNVARS_072_02-------------------------#'
+SET @@global.slave_max_allowed_packet = @start_value;
+SELECT @@global.slave_max_allowed_packet = 1073741824;
+@@global.slave_max_allowed_packet = 1073741824
+1
+'Bug# 34876: Incorrect Default Value is assigned to variable';
+'#--------------------FN_DYNVARS_072_03------------------------#'
+SET @@global.slave_max_allowed_packet = 1024;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = 1073741824;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+SET @@global.slave_max_allowed_packet = 1073741824;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+SET @@global.slave_max_allowed_packet = 1025;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = 65535;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+64512
+'Bug# 34877: Invalid Values are coming in variable on assigning valid values';
+'#--------------------FN_DYNVARS_072_04-------------------------#'
+SET @@global.slave_max_allowed_packet = -1;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '-1'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = 100000000000;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '100000000000'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+SET @@global.slave_max_allowed_packet = 10000.01;
+ERROR 42000: Incorrect argument type to variable 'slave_max_allowed_packet'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+SET @@global.slave_max_allowed_packet = -1024;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '-1024'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = 4294967296;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '4294967296'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
+SET @@global.slave_max_allowed_packet = 1023;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '1023'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+'Bug # 34837: Errors are not coming on assigning invalid values to variable';
+SET @@global.slave_max_allowed_packet = ON;
+ERROR 42000: Incorrect argument type to variable 'slave_max_allowed_packet'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = 'test';
+ERROR 42000: Incorrect argument type to variable 'slave_max_allowed_packet'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+'#-------------------FN_DYNVARS_072_05----------------------------#'
+SET @@session.slave_max_allowed_packet = 4096;
+ERROR HY000: Variable 'slave_max_allowed_packet' is a GLOBAL variable and should be set with SET GLOBAL
+SELECT @@session.slave_max_allowed_packet;
+ERROR HY000: Variable 'slave_max_allowed_packet' is a GLOBAL variable
+'#----------------------FN_DYNVARS_072_06------------------------#'
+SELECT @@global.slave_max_allowed_packet = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='slave_max_allowed_packet';
+@@global.slave_max_allowed_packet = VARIABLE_VALUE
+1
+SELECT @@slave_max_allowed_packet = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.SESSION_VARIABLES
+WHERE VARIABLE_NAME='slave_max_allowed_packet';
+@@slave_max_allowed_packet = VARIABLE_VALUE
+1
+'#---------------------FN_DYNVARS_072_07----------------------#'
+SET @@global.slave_max_allowed_packet = TRUE;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '1'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+SET @@global.slave_max_allowed_packet = FALSE;
+Warnings:
+Warning 1292 Truncated incorrect slave_max_allowed_packet value: '0'
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1024
+'#---------------------FN_DYNVARS_072_08----------------------#'
+SET @@global.slave_max_allowed_packet = 5000;
+SELECT @@slave_max_allowed_packet = @@global.slave_max_allowed_packet;
+@@slave_max_allowed_packet = @@global.slave_max_allowed_packet
+1
+'#---------------------FN_DYNVARS_072_09----------------------#'
+SET slave_max_allowed_packet = 6000;
+ERROR HY000: Variable 'slave_max_allowed_packet' is a GLOBAL variable and should be set with SET GLOBAL
+SELECT @@slave_max_allowed_packet;
+@@slave_max_allowed_packet
+4096
+SET local.slave_max_allowed_packet = 7000;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'slave_max_allowed_packet = 7000' at line 1
+SELECT local.slave_max_allowed_packet;
+ERROR 42S02: Unknown table 'local' in field list
+SET global.slave_max_allowed_packet = 8000;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'slave_max_allowed_packet = 8000' at line 1
+SELECT global.slave_max_allowed_packet;
+ERROR 42S02: Unknown table 'global' in field list
+SELECT slave_max_allowed_packet = @@session.slave_max_allowed_packet;
+ERROR 42S22: Unknown column 'slave_max_allowed_packet' in 'field list'
+SET @@global.slave_max_allowed_packet = @start_value;
+SELECT @@global.slave_max_allowed_packet;
+@@global.slave_max_allowed_packet
+1073741824
diff --git a/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test b/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test
new file mode 100644
index 00000000000..4caaae84906
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test
@@ -0,0 +1,177 @@
+############## mysql-test\t\slave_max_allowed_packet_basic.test ##################
+# #
+# Variable Name: slave_max_allowed_packet #
+# Scope: GLOBAL #
+# Access Type: Dynamic #
+# Data Type: numeric #
+# Default Value:1073741824 #
+# Range: 1024 - 1073741824 #
+# #
+# #
+# #
+# Description: Test Cases of Dynamic System Variable slave_max_allowed_packet #
+# that checks the behavior of this variable in the following ways#
+# * Default Value #
+# * Valid & Invalid values #
+# * Scope & Access method #
+# * Data Integrity #
+# #
+###############################################################################
+
+--source include/load_sysvars.inc
+
+########################################################################
+# START OF slave_max_allowed_packet TESTS #
+########################################################################
+
+
+###########################################################################
+# Saving initial value of slave_max_allowed_packet in a temporary variable#
+###########################################################################
+
+SET @start_value = @@global.slave_max_allowed_packet;
+SELECT @start_value;
+
+
+--echo '#--------------------FN_DYNVARS_072_01------------------------#'
+########################################################################
+# Display the DEFAULT value of slave_max_allowed_packet #
+########################################################################
+
+SET @@global.slave_max_allowed_packet = 5000;
+SET @@global.slave_max_allowed_packet = DEFAULT;
+SELECT @@global.slave_max_allowed_packet;
+
+
+--echo '#---------------------FN_DYNVARS_072_02-------------------------#'
+###############################################
+# Verify default value of variable #
+###############################################
+
+SET @@global.slave_max_allowed_packet = @start_value;
+SELECT @@global.slave_max_allowed_packet = 1073741824;
+--echo 'Bug# 34876: Incorrect Default Value is assigned to variable';
+
+--echo '#--------------------FN_DYNVARS_072_03------------------------#'
+########################################################################
+# Change the value of slave_max_allowed_packet to a valid value #
+########################################################################
+
+SET @@global.slave_max_allowed_packet = 1024;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 1073741824;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 1073741824;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 1025;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 65535;
+SELECT @@global.slave_max_allowed_packet;
+--echo 'Bug# 34877: Invalid Values are coming in variable on assigning valid values';
+
+
+--echo '#--------------------FN_DYNVARS_072_04-------------------------#'
+###########################################################################
+# Change the value of slave_max_allowed_packet to invalid value #
+###########################################################################
+
+SET @@global.slave_max_allowed_packet = -1;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 100000000000;
+SELECT @@global.slave_max_allowed_packet;
+--Error ER_WRONG_TYPE_FOR_VAR
+SET @@global.slave_max_allowed_packet = 10000.01;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = -1024;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 4294967296;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = 1023;
+SELECT @@global.slave_max_allowed_packet;
+
+--echo 'Bug # 34837: Errors are not coming on assigning invalid values to variable';
+
+--Error ER_WRONG_TYPE_FOR_VAR
+SET @@global.slave_max_allowed_packet = ON;
+SELECT @@global.slave_max_allowed_packet;
+--Error ER_WRONG_TYPE_FOR_VAR
+SET @@global.slave_max_allowed_packet = 'test';
+SELECT @@global.slave_max_allowed_packet;
+
+
+--echo '#-------------------FN_DYNVARS_072_05----------------------------#'
+###########################################################################
+# Test if accessing session slave_max_allowed_packet gives error #
+###########################################################################
+
+--Error ER_GLOBAL_VARIABLE
+SET @@session.slave_max_allowed_packet = 4096;
+--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@session.slave_max_allowed_packet;
+
+
+--echo '#----------------------FN_DYNVARS_072_06------------------------#'
+##############################################################################
+# Check if the value in GLOBAL & SESSION Tables matches values in variable #
+##############################################################################
+
+SELECT @@global.slave_max_allowed_packet = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='slave_max_allowed_packet';
+
+SELECT @@slave_max_allowed_packet = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.SESSION_VARIABLES
+WHERE VARIABLE_NAME='slave_max_allowed_packet';
+
+
+--echo '#---------------------FN_DYNVARS_072_07----------------------#'
+###################################################################
+# Check if TRUE and FALSE values can be used on variable #
+###################################################################
+
+SET @@global.slave_max_allowed_packet = TRUE;
+SELECT @@global.slave_max_allowed_packet;
+SET @@global.slave_max_allowed_packet = FALSE;
+SELECT @@global.slave_max_allowed_packet;
+
+
+--echo '#---------------------FN_DYNVARS_072_08----------------------#'
+########################################################################################################
+# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable #
+########################################################################################################
+
+SET @@global.slave_max_allowed_packet = 5000;
+SELECT @@slave_max_allowed_packet = @@global.slave_max_allowed_packet;
+
+
+--echo '#---------------------FN_DYNVARS_072_09----------------------#'
+################################################################################
+# Check if slave_max_allowed_packet can be accessed with and without @@ sign #
+################################################################################
+
+--Error ER_GLOBAL_VARIABLE
+SET slave_max_allowed_packet = 6000;
+SELECT @@slave_max_allowed_packet;
+--Error ER_PARSE_ERROR
+SET local.slave_max_allowed_packet = 7000;
+--Error ER_UNKNOWN_TABLE
+SELECT local.slave_max_allowed_packet;
+--Error ER_PARSE_ERROR
+SET global.slave_max_allowed_packet = 8000;
+--Error ER_UNKNOWN_TABLE
+SELECT global.slave_max_allowed_packet;
+--Error ER_BAD_FIELD_ERROR
+SELECT slave_max_allowed_packet = @@session.slave_max_allowed_packet;
+
+
+##############################
+# Restore initial value #
+##############################
+
+SET @@global.slave_max_allowed_packet = @start_value;
+SELECT @@global.slave_max_allowed_packet;
+
+
+########################################################################
+# END OF slave_max_allowed_packet TESTS #
+########################################################################
diff --git a/mysql-test/t/func_group_innodb.test b/mysql-test/t/func_group_innodb.test
index 1bdfd8f54bb..58f365bb244 100644
--- a/mysql-test/t/func_group_innodb.test
+++ b/mysql-test/t/func_group_innodb.test
@@ -83,3 +83,47 @@ explain select count(*), min(7), max(7) from t2m, t1i;
select count(*), min(7), max(7) from t2m, t1i;
drop table t1m, t1i, t2m, t2i;
+
+--echo #
+--echo # Bug#12713907: STRANGE OPTIMIZE & WRONG RESULT UNDER ORDER BY
+--echo # COUNT(*) LIMIT.
+--echo #
+
+CREATE TABLE t1 (
+id BIGINT(20) ,
+member_id_to INT(11) ,
+r_date DATE ,
+PRIMARY KEY (id,r_date),
+KEY r_date_idx (r_date),
+KEY t1_idx01 (member_id_to)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES
+(107924526,518491,'2011-05-01'),
+(107924527,518491,'2011-05-01'),
+(107924528,518491,'2011-05-01'),
+(107924529,518491,'2011-05-01'),
+(107924530,518491,'2011-05-01'),
+(107924531,518491,'2011-05-01'),
+(107924532,518491,'2011-05-01'),
+(107924534,518491,'2011-06-21'),
+(107924535,518491,'2011-06-21'),
+(107924536,518491,'2011-06-21'),
+(107924537,518491,'2011-06-21'),
+(107924538,518491,'2011-06-21'),
+(107924542,1601319,'2011-06-21'),
+(107924543,1601319,'2011-06-21'),
+(107924544,1601319,'2011-06-21'),
+(107924545,1601319,'2011-06-21'),
+(107924546,1601319,'2011-06-21'),
+(107924547,1601319,'2011-06-21'),
+(107924548,1601319,'2011-06-21'),
+(107924549,1601319,'2011-06-21'),
+(107924550,1601319,'2011-06-21');
+
+SELECT member_id_to, COUNT(*) FROM t1 WHERE r_date =
+ '2011-06-21' GROUP BY member_id_to ORDER BY 2 LIMIT 1;
+
+DROP TABLE t1;
+
+--echo # End of test BUG#12713907
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index bfbb18b7aed..39d0c294a39 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -2315,9 +2315,32 @@ DROP DATABASE BUG52792;
USE test;
+# Wait till we reached the initial number of concurrent sessions
+--source include/wait_until_count_sessions.inc
+
--echo #
---echo # End of 5.1 tests
+--echo # Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
--echo #
+SET @old_log_output_state= @@global.log_output;
+SET @old_general_log_state= @@global.general_log;
+SET @old_slow_query_log_state= @@global.slow_query_log;
-# Wait till we reached the initial number of concurrent sessions
---source include/wait_until_count_sessions.inc
+call mtr.add_suppression("Failed to write to mysql.general_log");
+--exec $MYSQL_DUMP -uroot --all-databases > $MYSQLTEST_VARDIR/tmp/bug45740.sql
+# Make log_output as table and enable general_log and slow_log
+SET @@global.log_output="TABLE";
+SET @@global.general_log='ON';
+SET @@global.slow_query_log='ON';
+DROP DATABASE mysql;
+--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug45740.sql
+SHOW CREATE TABLE mysql.general_log;
+SHOW CREATE TABLE mysql.slow_log;
+--remove_file $MYSQLTEST_VARDIR/tmp/bug45740.sql
+
+SET @@global.log_output= @old_log_output_state;
+SET @@global.slow_query_log= @old_slow_query_log_state;
+SET @@global.general_log= @old_general_log_state;
+
+--echo #
+--echo # End of 5.1 tests
+--echo #
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 9b3f3e750e1..88bfe1dd2be 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -3102,3 +3102,93 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo End of 5.1 tests.
+
+--echo
+--echo # Bug#13805127: Stored program cache produces wrong result in same THD
+--echo
+
+PREPARE s1 FROM
+"
+SELECT c1, t2.c2, count(c3)
+FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE @x = 1
+ UNION
+ SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2
+";
+
+--echo
+SET @x = 1;
+SELECT c1, t2.c2, count(c3)
+FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE @x = 1
+ UNION
+ SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+--echo
+EXECUTE s1;
+
+--echo
+SET @x = 2;
+SELECT c1, t2.c2, count(c3)
+FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE @x = 1
+ UNION
+ SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+--echo
+EXECUTE s1;
+
+--echo
+SET @x = 1;
+SELECT c1, t2.c2, count(c3)
+FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE @x = 1
+ UNION
+ SELECT 2 FROM dual WHERE @x = 1 OR @x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+WHERE t2.c2 = t1.c2
+GROUP BY c1, c2;
+--echo
+EXECUTE s1;
+
+DEALLOCATE PREPARE s1;
+
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index ae4e1dd588e..75d290f7c8b 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -8429,3 +8429,40 @@ DROP FUNCTION f1;
--echo # ------------------------------------------------------------------
--echo # -- End of 5.1 tests
--echo # ------------------------------------------------------------------
+
+--echo
+--echo # Bug#13805127: Stored program cache produces wrong result in same THD
+--echo
+
+delimiter |;
+
+CREATE PROCEDURE p1(x INT UNSIGNED)
+BEGIN
+ SELECT c1, t2.c2, count(c3)
+ FROM
+ (
+ SELECT 3 as c2 FROM dual WHERE x = 1
+ UNION
+ SELECT 2 FROM dual WHERE x = 1 OR x = 2
+ ) AS t1,
+ (
+ SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual
+ UNION
+ SELECT '2012-03-01 02:00:00', 3, 2 FROM dual
+ UNION
+ SELECT '2012-03-01 01:00:00', 2, 1 FROM dual
+ ) AS t2
+ WHERE t2.c2 = t1.c2
+ GROUP BY c1, c2
+ ;
+END|
+
+delimiter ;|
+
+--echo
+CALL p1(1);
+CALL p1(2);
+CALL p1(1);
+
+DROP PROCEDURE p1;
+
diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test
index 1a9e66478e1..8ba8260cfc4 100644
--- a/mysql-test/t/type_year.test
+++ b/mysql-test/t/type_year.test
@@ -160,5 +160,13 @@ SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1;
DROP TABLE t1;
--echo #
+--echo # WL#6219: Deprecate and remove YEAR(2) type
+--echo #
+
+CREATE TABLE t1 (c1 YEAR(2), c2 YEAR(4));
+ALTER TABLE t1 MODIFY COLUMN c2 YEAR(2);
+DROP TABLE t1;
+
+--echo #
--echo End of 5.1 tests
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 16358b0056e..2316c2594ab 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -430,7 +430,11 @@ process_flags:
memset(buffz, '0', minimum_width - length2);
else
memset(buffz, ' ', minimum_width - length2);
- my_b_write(info, buffz, minimum_width - length2);
+ if (my_b_write(info, buffz, minimum_width - length2))
+ {
+ my_afree(buffz);
+ goto err;
+ }
my_afree(buffz);
}
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 210946d50a8..43917da7f98 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -148,7 +148,8 @@ static char reserved_map[256]=
int check_if_legal_tablename(const char *name)
{
DBUG_ENTER("check_if_legal_tablename");
- DBUG_RETURN((reserved_map[(uchar) name[0]] & 1) &&
+ DBUG_RETURN(name[0] != 0 && name[1] != 0 &&
+ (reserved_map[(uchar) name[0]] & 1) &&
(reserved_map[(uchar) name[1]] & 2) &&
(reserved_map[(uchar) name[2]] & 4) &&
str_list_find(&reserved_names[1], name));
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 5d28e066814..11708d8f10e 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -38,7 +38,17 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
for (;;)
{
- if ((writenbytes= write(Filedes, Buffer, Count)) == Count)
+ writenbytes= write(Filedes, Buffer, Count);
+ /**
+ To simulate the write error set the errno = error code
+ and the number pf written bytes to -1.
+ */
+ DBUG_EXECUTE_IF ("simulate_file_write_error",
+ {
+ errno= ENOSPC;
+ writenbytes= (size_t) -1;
+ });
+ if (writenbytes == Count)
break;
if (writenbytes != (size_t) -1)
{ /* Safeguard */
diff --git a/sql-common/client.c b/sql-common/client.c
index cdb272e076e..53642b65be7 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2003, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2003, 2012, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1268,7 +1268,7 @@ static void cli_fetch_lengths(ulong *to, MYSQL_ROW column,
***************************************************************************/
MYSQL_FIELD *
-unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
+unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
my_bool default_value, uint server_capabilities)
{
MYSQL_ROWS *row;
@@ -1281,6 +1281,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
if (!result)
{
free_rows(data); /* Free old data */
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields);
@@ -1308,6 +1309,14 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->org_name_length= lengths[5];
/* Unpack fixed length parts */
+ if (lengths[6] != 12)
+ {
+ /* malformed packet. signal an error. */
+ free_rows(data); /* Free old data */
+ set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+ DBUG_RETURN(0);
+ }
+
pos= (uchar*) row->data[6];
field->charsetnr= uint2korr(pos);
field->length= (uint) uint4korr(pos+2);
@@ -2896,7 +2905,7 @@ get_info:
if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
DBUG_RETURN(1);
- if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
+ if (!(mysql->fields=unpack_fields(mysql, fields,&mysql->field_alloc,
(uint) field_count,0,
mysql->server_capabilities)))
DBUG_RETURN(1);
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 5b125be2eb5..92fcc4cdb6b 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -73,6 +73,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
tztime.h my_decimal.h\
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h sql_view.h sql_trigger.h \
+ mem_root_array.h \
sql_array.h sql_cursor.h events.h scheduler.h \
event_db_repository.h event_queue.h \
sql_plugin.h authors.h event_parse_data.h \
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index fb66a50ee7f..9f3bba3e896 100755
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -640,13 +640,13 @@ Event_scheduler::stop()
DBUG_PRINT("info", ("Scheduler thread has id %lu",
scheduler_thd->thread_id));
/* Lock from delete */
- pthread_mutex_lock(&scheduler_thd->LOCK_thd_data);
+ pthread_mutex_lock(&scheduler_thd->LOCK_thd_kill);
/* This will wake up the thread if it waits on Queue's conditional */
sql_print_information("Event Scheduler: Killing the scheduler thread, "
"thread id %lu",
scheduler_thd->thread_id);
scheduler_thd->awake(THD::KILL_CONNECTION);
- pthread_mutex_unlock(&scheduler_thd->LOCK_thd_data);
+ pthread_mutex_unlock(&scheduler_thd->LOCK_thd_kill);
/* thd could be 0x0, when shutting down */
sql_print_information("Event Scheduler: "
diff --git a/sql/field.cc b/sql/field.cc
index a8bb59ca417..278ba83cc81 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -10236,6 +10236,17 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
geom_type= ((Field_geom*)old_field)->geom_type;
break;
#endif
+ case MYSQL_TYPE_YEAR:
+ if (length != 4)
+ {
+ char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
+ my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER(ER_WARN_DEPRECATED_SYNTAX),
+ buff, "YEAR(4)");
+ }
+ break;
default:
break;
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 234420b64a8..e56bb93caab 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2416,8 +2416,19 @@ int handler::update_auto_increment()
reservation means potentially losing unused values).
Note that in prelocked mode no estimation is given.
*/
+
if ((auto_inc_intervals_count == 0) && (estimation_rows_to_insert > 0))
nb_desired_values= estimation_rows_to_insert;
+ else if ((auto_inc_intervals_count == 0) &&
+ (thd->lex->many_values.elements > 0))
+ {
+ /*
+ For multi-row inserts, if the bulk inserts cannot be started, the
+ handler::estimation_rows_to_insert will not be set. But we still
+ want to reserve the autoinc values.
+ */
+ nb_desired_values= thd->lex->many_values.elements;
+ }
else /* go with the increasing defaults */
{
/* avoid overflow in formula, with this if() */
@@ -4757,6 +4768,8 @@ int handler::ha_write_row(uchar *buf)
DBUG_RETURN(error);
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
DBUG_RETURN(error); /* purecov: inspected */
+
+ DEBUG_SYNC_C("ha_write_row_end");
DBUG_RETURN(0);
}
diff --git a/sql/item.cc b/sql/item.cc
index c2e208fe10f..7ca51157e9c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6010,7 +6010,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (from_field != not_found_field)
{
Item_field* fld;
- if (!(fld= new Item_field(from_field)))
+ if (!(fld= new Item_field(thd, last_checked_context, from_field)))
goto error;
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex,
diff --git a/sql/log.cc b/sql/log.cc
index c74e8bc9233..732ce6326fc 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2423,7 +2423,10 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
{
end= strxmov(buff, "# administrator command: ", NullS);
buff_len= (ulong) (end - buff);
- my_b_write(&log_file, (uchar*) buff, buff_len);
+ DBUG_EXECUTE_IF("simulate_slow_log_write_error",
+ {DBUG_SET("+d,simulate_file_write_error");});
+ if(my_b_write(&log_file, (uchar*) buff, buff_len))
+ tmp_errno= errno;
}
if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len) ||
my_b_write(&log_file, (uchar*) ";\n",2) ||
diff --git a/sql/log.h b/sql/log.h
index 361ad0f2a91..f42ef514307 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2005, 2012, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -130,6 +130,11 @@ extern TC_LOG_DUMMY tc_log_dummy;
class Relay_log_info;
+/*
+ Note that we destroy the lock mutex in the desctructor here.
+ This means that object instances cannot be destroyed/go out of scope,
+ until we have reset thd->current_linfo to NULL;
+ */
typedef struct st_log_info
{
char log_file_name[FN_REFLEN];
@@ -289,8 +294,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
int new_file_impl(bool need_lock);
public:
- MYSQL_LOG::generate_name;
- MYSQL_LOG::is_open;
+ using MYSQL_LOG::generate_name;
+ using MYSQL_LOG::is_open;
/* This is relay log */
bool is_relay_log;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 2ca1721a7ab..06722bdbeca 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1121,7 +1121,7 @@ failed my_b_read"));
Log_event *res= 0;
#ifndef max_allowed_packet
THD *thd=current_thd;
- uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0;
+ uint max_allowed_packet= thd ? slave_max_allowed_packet:~(ulong)0;
#endif
if (data_len > max_allowed_packet)
@@ -2834,23 +2834,40 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
pos= (const uchar*) end; // Break loop
}
}
-
+
+ /**
+ Layout for the data buffer is as follows
+ +--------+-----------+------+------+---------+----+-------+
+ | catlog | time_zone | user | host | db name | \0 | Query |
+ +--------+-----------+------+------+---------+----+-------+
+
+ To support the query cache we append the following buffer to the above
+ +-------+----------------------------------------+-------+
+ |db len | uninitiatlized space of size of db len | FLAGS |
+ +-------+----------------------------------------+-------+
+
+ The area of buffer starting from Query field all the way to the end belongs
+ to the Query buffer and its structure is described in alloc_query() in
+ sql_parse.cc
+ */
+
#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
- if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 +
- time_zone_len + 1 +
- data_len + 1 +
- QUERY_CACHE_FLAGS_SIZE +
- user.length + 1 +
- host.length + 1 +
- db_len + 1,
- MYF(MY_WME))))
+ if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
+ + time_zone_len + 1
+ + user.length + 1
+ + host.length + 1
+ + data_len + 1
+ + sizeof(size_t)//for db_len
+ + db_len + 1
+ + QUERY_CACHE_FLAGS_SIZE,
+ MYF(MY_WME))))
#else
- if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 +
- time_zone_len + 1 +
- data_len + 1 +
- user.length + 1 +
- host.length + 1,
- MYF(MY_WME))))
+ if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
+ + time_zone_len + 1
+ + user.length + 1
+ + host.length + 1
+ + data_len + 1,
+ MYF(MY_WME))))
#endif
DBUG_VOID_RETURN;
if (catalog_len) // If catalog is given
@@ -2890,6 +2907,14 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
db= (char *)start;
query= (char *)(start + db_len + 1);
q_len= data_len - db_len -1;
+ /**
+ Append the db length at the end of the buffer. This will be used by
+ Query_cache::send_result_to_client() in case the query cache is On.
+ */
+#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
+ size_t db_length= (size_t)db_len;
+ memcpy(start + data_len + 1, &db_length, sizeof(size_t));
+#endif
DBUG_VOID_RETURN;
}
@@ -3071,6 +3096,12 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
{
Write_on_release_cache cache(&print_event_info->head_cache, file);
+ /**
+ reduce the size of io cache so that the write function is called
+ for every call to my_b_write().
+ */
+ DBUG_EXECUTE_IF ("simulate_file_write_error",
+ {(&cache)->write_pos= (&cache)->write_end- 500;});
print_query_header(&cache, print_event_info);
my_b_write(&cache, (uchar*) query, q_len);
my_b_printf(&cache, "\n%s\n", print_event_info->delimiter);
@@ -5269,11 +5300,12 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
#endif
+#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
+
/*
Intvar_log_event::do_apply_event()
*/
-#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
{
/*
@@ -5282,6 +5314,9 @@ int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
*/
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
+ if (rli->deferred_events_collecting)
+ return rli->deferred_events->add(this);
+
switch (type) {
case LAST_INSERT_ID_EVENT:
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
@@ -5387,6 +5422,9 @@ int Rand_log_event::do_apply_event(Relay_log_info const *rli)
*/
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
+ if (rli->deferred_events_collecting)
+ return rli->deferred_events->add(this);
+
thd->rand.seed1= (ulong) seed1;
thd->rand.seed2= (ulong) seed2;
return 0;
@@ -5413,6 +5451,29 @@ Rand_log_event::do_shall_skip(Relay_log_info *rli)
return continue_group(rli);
}
+/**
+ Exec deferred Int-, Rand- and User- var events prefixing
+ a Query-log-event event.
+
+ @param thd THD handle
+
+ @return false on success, true if a failure in an event applying occurred.
+*/
+bool slave_execute_deferred_events(THD *thd)
+{
+ bool res= false;
+ Relay_log_info *rli= thd->rli_slave;
+
+ DBUG_ASSERT(rli && (!rli->deferred_events_collecting || rli->deferred_events));
+
+ if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
+ return res;
+
+ res= rli->deferred_events->execute(rli);
+
+ return res;
+}
+
#endif /* !MYSQL_CLIENT */
@@ -5593,6 +5654,9 @@ User_var_log_event::
User_var_log_event(const char* buf,
const Format_description_log_event* description_event)
:Log_event(buf, description_event)
+#ifndef MYSQL_CLIENT
+ , deferred(false)
+#endif
{
/* The Post-Header is empty. The Variable Data part begins immediately. */
buf+= description_event->common_header_len +
@@ -5800,6 +5864,13 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
{
Item *it= 0;
CHARSET_INFO *charset;
+
+ if (rli->deferred_events_collecting)
+ {
+ set_deferred();
+ return rli->deferred_events->add(this);
+ }
+
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
return 1;
LEX_STRING user_var_name;
@@ -5851,7 +5922,8 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
return 0;
}
}
- Item_func_set_user_var e(user_var_name, it);
+
+ Item_func_set_user_var *e= new Item_func_set_user_var(user_var_name, it);
/*
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
@@ -5860,7 +5932,7 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
crash the server, so if fix fields fails, we just return with an
error.
*/
- if (e.fix_fields(thd, 0))
+ if (e->fix_fields(thd, 0))
return 1;
/*
@@ -5868,8 +5940,9 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
a single record and with a single column. Thus, like
a column value, it could always have IMPLICIT derivation.
*/
- e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
- free_root(thd->mem_root,0);
+ e->update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
+ if (!is_deferred())
+ free_root(thd->mem_root,0);
return 0;
}
@@ -6263,11 +6336,18 @@ void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info
{
Load_log_event::print(file, print_event_info,
!check_fname_outside_temp_buf());
- /*
- That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
- SHOW BINLOG EVENTS we don't.
- */
- my_b_printf(&cache, "#");
+ /**
+ reduce the size of io cache so that the write function is called
+ for every call to my_b_printf().
+ */
+ DBUG_EXECUTE_IF ("simulate_create_event_write_error",
+ {(&cache)->write_pos= (&cache)->write_end;
+ DBUG_SET("+d,simulate_file_write_error");});
+ /*
+ That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
+ SHOW BINLOG EVENTS we don't.
+ */
+ my_b_printf(&cache, "#");
}
my_b_printf(&cache, " file_id: %d block_len: %d\n", file_id, block_len);
@@ -6944,6 +7024,13 @@ void Execute_load_query_log_event::print(FILE* file,
Write_on_release_cache cache(&print_event_info->head_cache, file);
print_query_header(&cache, print_event_info);
+ /**
+ reduce the size of io cache so that the write function is called
+ for every call to my_b_printf().
+ */
+ DBUG_EXECUTE_IF ("simulate_execute_event_write_error",
+ {(&cache)->write_pos= (&cache)->write_end;
+ DBUG_SET("+d,simulate_file_write_error");});
if (local_fname)
{
diff --git a/sql/log_event.h b/sql/log_event.h
index 645585c8ccb..a3c0eccd85a 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -275,6 +275,13 @@ struct sql_ex_info
MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
NAME_LEN + 1)
+/*
+ The new option is added to handle large packets that are sent from the master
+ to the slave. It is used to increase the thd(max_allowed) for both the
+ DUMP thread on the master and the SQL/IO thread on the slave.
+*/
+#define MAX_MAX_ALLOWED_PACKET 1024*1024*1024
+
/*
Event header offsets;
these point to places inside the fixed header.
@@ -2476,11 +2483,13 @@ public:
uint charset_number;
bool is_null;
#ifndef MYSQL_CLIENT
+ bool deferred;
User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
char *val_arg, ulong val_len_arg, Item_result type_arg,
uint charset_number_arg)
:Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
- val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
+ val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
+ deferred(false)
{ is_null= !val; }
void pack_info(Protocol* protocol);
#else
@@ -2493,6 +2502,13 @@ public:
Log_event_type get_type_code() { return USER_VAR_EVENT;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+ /*
+ Getter and setter for deferred User-event.
+ Returns true if the event is not applied directly
+ and which case the applier adjusts execution path.
+ */
+ bool is_deferred() { return deferred; }
+ void set_deferred() { deferred= val; }
#endif
bool is_valid() const { return 1; }
@@ -3965,6 +3981,16 @@ bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos,
const char **group_relay_log_name,
ulonglong *relay_log_pos);
+#ifndef MYSQL_CLIENT
+/**
+ The function is called by slave applier in case there are
+ active table filtering rules to force gathering events associated
+ with Query-log-event into an array to execute
+ them once the fate of the Query is determined for execution.
+*/
+bool slave_execute_deferred_events(THD *thd);
+#endif
+
/**
@} (end of group Replication)
*/
diff --git a/sql/mem_root_array.h b/sql/mem_root_array.h
new file mode 100644
index 00000000000..5ce4dcb584d
--- /dev/null
+++ b/sql/mem_root_array.h
@@ -0,0 +1,175 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 MEM_ROOT_ARRAY_INCLUDED
+#define MEM_ROOT_ARRAY_INCLUDED
+
+#include <my_alloc.h>
+
+/**
+ A typesafe replacement for DYNAMIC_ARRAY.
+ We use MEM_ROOT for allocating storage, rather than the C++ heap.
+ The interface is chosen to be similar to std::vector.
+
+ @remark
+ Unlike DYNAMIC_ARRAY, elements are properly copied
+ (rather than memcpy()d) if the underlying array needs to be expanded.
+
+ @remark
+ Depending on has_trivial_destructor, we destroy objects which are
+ removed from the array (including when the array object itself is destroyed).
+
+ @remark
+ Note that MEM_ROOT has no facility for reusing free space,
+ so don't use this if multiple re-expansions are likely to happen.
+
+ @param Element_type The type of the elements of the container.
+ Elements must be copyable.
+ @param has_trivial_destructor If true, we don't destroy elements.
+ We could have used type traits to determine this.
+ __has_trivial_destructor is supported by some (but not all)
+ compilers we use.
+*/
+template<typename Element_type, bool has_trivial_destructor>
+class Mem_root_array
+{
+public:
+ Mem_root_array(MEM_ROOT *root)
+ : m_root(root), m_array(NULL), m_size(0), m_capacity(0)
+ {
+ DBUG_ASSERT(m_root != NULL);
+ }
+
+ ~Mem_root_array()
+ {
+ clear();
+ }
+
+ Element_type &at(size_t n)
+ {
+ DBUG_ASSERT(n < size());
+ return m_array[n];
+ }
+
+ const Element_type &at(size_t n) const
+ {
+ DBUG_ASSERT(n < size());
+ return m_array[n];
+ }
+
+ // Returns a pointer to the first element in the array.
+ Element_type *begin() { return &m_array[0]; }
+
+ // Returns a pointer to the past-the-end element in the array.
+ Element_type *end() { return &m_array[size()]; }
+
+ // Erases all of the elements.
+ void clear()
+ {
+ if (!empty())
+ chop(0);
+ }
+
+ /*
+ Chops the tail off the array, erasing all tail elements.
+ @param pos Index of first element to erase.
+ */
+ void chop(const size_t pos)
+ {
+ DBUG_ASSERT(pos < m_size);
+ if (!has_trivial_destructor)
+ {
+ for (size_t ix= pos; ix < m_size; ++ix)
+ {
+ Element_type *p= &m_array[ix];
+ p->~Element_type(); // Destroy discarded element.
+ }
+ }
+ m_size= pos;
+ }
+
+ /*
+ Reserves space for array elements.
+ Copies over existing elements, in case we are re-expanding the array.
+
+ @param n number of elements.
+ @retval true if out-of-memory, false otherwise.
+ */
+ bool reserve(size_t n)
+ {
+ if (n <= m_capacity)
+ return false;
+
+ void *mem= alloc_root(m_root, n * element_size());
+ if (!mem)
+ return true;
+ Element_type *array= static_cast<Element_type*>(mem);
+
+ // Copy all the existing elements into the new array.
+ for (size_t ix= 0; ix < m_size; ++ix)
+ {
+ Element_type *new_p= &array[ix];
+ Element_type *old_p= &m_array[ix];
+ new (new_p) Element_type(*old_p); // Copy into new location.
+ if (!has_trivial_destructor)
+ old_p->~Element_type(); // Destroy the old element.
+ }
+
+ // Forget the old array.
+ m_array= array;
+ m_capacity= n;
+ return false;
+ }
+
+ /*
+ Adds a new element at the end of the array, after its current last
+ element. The content of this new element is initialized to a copy of
+ the input argument.
+
+ @param element Object to copy.
+ @retval true if out-of-memory, false otherwise.
+ */
+ bool push_back(const Element_type &element)
+ {
+ const size_t min_capacity= 20;
+ const size_t expansion_factor= 2;
+ if (0 == m_capacity && reserve(min_capacity))
+ return true;
+ if (m_size == m_capacity && reserve(m_capacity * expansion_factor))
+ return true;
+ Element_type *p= &m_array[m_size++];
+ new (p) Element_type(element);
+ return false;
+ }
+
+ size_t capacity() const { return m_capacity; }
+ size_t element_size() const { return sizeof(Element_type); }
+ bool empty() const { return size() == 0; }
+ size_t size() const { return m_size; }
+
+private:
+ MEM_ROOT *const m_root;
+ Element_type *m_array;
+ size_t m_size;
+ size_t m_capacity;
+
+ // Not (yet) implemented.
+ Mem_root_array(const Mem_root_array&);
+ Mem_root_array &operator=(const Mem_root_array&);
+};
+
+
+#endif // MEM_ROOT_ARRAY_INCLUDED
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 60abf5a2361..16fdaef2eae 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1971,6 +1971,7 @@ extern ulong slave_net_timeout, slave_trans_retries;
extern uint max_user_connections;
extern ulong what_to_log,flush_time;
extern ulong query_buff_size;
+extern ulong slave_max_allowed_packet;
extern ulong max_prepared_stmt_count, prepared_stmt_count;
extern ulong binlog_cache_size, open_files_limit;
extern ulonglong max_binlog_cache_size;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3a7519991b2..629ffe26f2c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
#include "events.h"
#include <waiting_threads.h>
#include "debug_sync.h"
+#include "log_event.h"
#include "../storage/myisam/ha_myisam.h"
@@ -581,6 +582,7 @@ static const char *slave_exec_mode_str= "STRICT";
ulong thread_cache_size=0, thread_pool_size= 0;
ulong binlog_cache_size=0;
ulonglong max_binlog_cache_size=0;
+ulong slave_max_allowed_packet= 0;
ulong query_cache_size=0;
ulong refresh_version; /* Increments on each reload */
query_id_t global_query_id;
@@ -5731,6 +5733,7 @@ enum options_mysqld
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
+ OPT_SLAVE_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
@@ -6951,10 +6954,14 @@ thread is in the relay logs.",
&global_system_variables.max_allowed_packet,
&max_system_variables.max_allowed_packet, 0, GET_ULONG,
REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
+ {"slave_max_allowed_packet", OPT_SLAVE_MAX_ALLOWED_PACKET,
+ "The maximum packet length to sent successfully from the master to slave.",
+ &slave_max_allowed_packet, &slave_max_allowed_packet, 0, GET_ULONG,
+ REQUIRED_ARG, MAX_MAX_ALLOWED_PACKET, 1024, MAX_MAX_ALLOWED_PACKET, MALLOC_OVERHEAD, 1024, 0},
{"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE,
"Can be used to restrict the total size used to cache a multi-transaction query.",
&max_binlog_cache_size, &max_binlog_cache_size, 0,
- GET_ULL, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONGLONG_MAX, 0, IO_SIZE, 0},
+ GET_ULL, REQUIRED_ARG, (longlong) ULONG_MAX, IO_SIZE, ULONGLONG_MAX, 0, IO_SIZE, 0},
{"max_binlog_size", OPT_MAX_BINLOG_SIZE,
"Binary log will be rotated automatically when the size exceeds this "
"value. Will also apply to relay logs if max_relay_log_size is 0. "
@@ -6992,7 +6999,7 @@ thread is in the relay logs.",
"Joins that are probably going to read more than max_join_size records return an error.",
&global_system_variables.max_join_size,
&max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
- HA_POS_ERROR, 1, HA_POS_ERROR, 0, 1, 0},
+ (longlong) HA_POS_ERROR, 1, HA_POS_ERROR, 0, 1, 0},
{"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
"Max number of bytes in sorted records.",
&global_system_variables.max_length_for_sort_data,
@@ -7018,7 +7025,7 @@ thread is in the relay logs.",
"Limit assumed max number of seeks when looking up rows based on a key.",
&global_system_variables.max_seeks_for_key,
&max_system_variables.max_seeks_for_key, 0, GET_ULONG,
- REQUIRED_ARG, (longlong) ULONG_MAX, 1, (longlong) ULONG_MAX, 0, 1, 0 },
+ REQUIRED_ARG, (longlong) ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 },
{"max_sort_length", OPT_MAX_SORT_LENGTH,
"The number of bytes to use when sorting BLOB or TEXT values (only the "
"first max_sort_length bytes of each value are used; the rest are ignored).",
@@ -7042,7 +7049,7 @@ thread is in the relay logs.",
{"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
"After this many write locks, allow some read locks to run in between.",
&max_write_lock_count, &max_write_lock_count, 0, GET_ULONG,
- REQUIRED_ARG, (longlong) ULONG_MAX, 1, (longlong) ULONG_MAX, 0, 1, 0},
+ REQUIRED_ARG, (longlong) ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
{"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
"Don't log queries which examine less than min_examined_row_limit rows to file.",
&global_system_variables.min_examined_row_limit,
@@ -7069,18 +7076,19 @@ thread is in the relay logs.",
&global_system_variables.myisam_max_extra_sort_file_size,
&max_system_variables.myisam_max_extra_sort_file_size,
0, GET_ULL, REQUIRED_ARG, (ulonglong) INT_MAX32,
- 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0},
+ 0, MAX_FILE_SIZE, 0, 1, 0},
{"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
"Don't use the fast sort index method to created index if the temporary "
"file would get bigger than this.",
&global_system_variables.myisam_max_sort_file_size,
&max_system_variables.myisam_max_sort_file_size, 0,
- GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE,
+ GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, MAX_FILE_SIZE,
0, 1024*1024, 0},
{"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE,
"Can be used to restrict the total memory used for memory mmaping of myisam files",
&myisam_mmap_size, &myisam_mmap_size, 0,
- GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0},
+ GET_ULL, REQUIRED_ARG, (longlong) SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX,
+ 0, 1, 0},
{"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS,
"Specifies whether several threads should be used when repairing MyISAM "
"tables. For values > 1, one thread is used per index. The value of 1 "
@@ -7093,7 +7101,7 @@ thread is in the relay logs.",
"or when creating indexes with CREATE INDEX or ALTER TABLE.",
&global_system_variables.myisam_sort_buff_size,
&max_system_variables.myisam_sort_buff_size, 0,
- GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, (longlong) ULONG_MAX, 0, 1, 0},
+ GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, ~0ULL, 0, 1, 0},
{"myisam_use_mmap", OPT_MYISAM_USE_MMAP,
"Use memory mapping for reading and writing MyISAM tables.",
&opt_myisam_use_mmap, &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG,
@@ -7201,7 +7209,7 @@ thread is in the relay logs.",
{"query_cache_size", OPT_QUERY_CACHE_SIZE,
"The memory allocated to store results from old queries.",
&query_cache_size, &query_cache_size, 0, GET_ULONG,
- REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0},
+ REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1024, 0},
#ifdef HAVE_QUERY_CACHE
{"query_cache_type", OPT_QUERY_CACHE_TYPE,
"0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results "
@@ -7263,7 +7271,7 @@ thread is in the relay logs.",
"Maximum space to use for all relay logs.",
&relay_log_space_limit,
&relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
- (longlong) ULONG_MAX, 0, 1, 0},
+ ULONG_MAX, 0, 1, 0},
{"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL,
"Use compression on master/slave protocol.",
&opt_slave_compressed_protocol,
@@ -7278,7 +7286,7 @@ thread is in the relay logs.",
"it failed with a deadlock or elapsed lock wait timeout, "
"before giving up and stopping.",
&slave_trans_retries, &slave_trans_retries, 0,
- GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
+ GET_ULONG, REQUIRED_ARG, 10L, 0L, ULONG_MAX, 0, 1, 0},
#endif /* HAVE_REPLICATION */
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), "
@@ -7289,8 +7297,8 @@ thread is in the relay logs.",
"Each thread that needs to do a sort allocates a buffer of this size.",
&global_system_variables.sortbuff_size,
&max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
- MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, (longlong) ULONG_MAX,
- MALLOC_OVERHEAD, 1, 0},
+ MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0ULL, MALLOC_OVERHEAD,
+ 1, 0},
{"sync-binlog", OPT_SYNC_BINLOG,
"Synchronously flush binary log to disk after every #th event. "
"Use 0 (default) to disable synchronous flushing.",
diff --git a/sql/protocol.cc b/sql/protocol.cc
index b3ae09a5755..c0e30f8d7ee 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008, 2011, Monty Program Ab
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -683,6 +683,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
/* Store fixed length fields */
pos= (char*) local_packet->ptr()+local_packet->length();
*pos++= 12; // Length of packed fields
+ /* inject a NULL to test the client */
+ DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= 0xfb;);
if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
{
/* No conversion */
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index b56cef3913f..e2d008975ec 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -40,7 +40,9 @@ Relay_log_info::Relay_log_info()
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
until_log_pos(0), retried_trans(0),
tables_to_lock(0), tables_to_lock_count(0),
- last_event_start_time(0), m_flags(0)
+ last_event_start_time(0),
+ deferred_events(NULL),
+ m_flags(0)
{
DBUG_ENTER("Relay_log_info::Relay_log_info");
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index f82d0901d79..4d0b6c39d19 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -369,6 +369,41 @@ public:
*/
time_t last_event_start_time;
+ /*
+ A container to hold on Intvar-, Rand-, Uservar- log-events in case
+ the slave is configured with table filtering rules.
+ The withhold events are executed when their parent Query destiny is
+ determined for execution as well.
+ */
+ Deferred_log_events *deferred_events;
+
+ /*
+ State of the container: true stands for IRU events gathering,
+ false does for execution, either deferred or direct.
+ */
+ bool deferred_events_collecting;
+
+ /*
+ Returns true if the argument event resides in the containter;
+ more specifically, the checking is done against the last added event.
+ */
+ bool is_deferred_event(Log_event * ev)
+ {
+ return deferred_events_collecting ? deferred_events->is_last(ev) : false;
+ };
+ /* The general cleanup that slave applier may need at the end of query. */
+ inline void cleanup_after_query()
+ {
+ if (deferred_events)
+ deferred_events->rewind();
+ };
+ /* The general cleanup that slave applier may need at the end of session. */
+ void cleanup_after_session()
+ {
+ if (deferred_events)
+ delete deferred_events;
+ };
+
/**
Helper function to do after statement completion.
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index d304d5fbd6a..dad2309981f 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -226,3 +226,64 @@ table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table)
return error;
}
+
+#ifndef MYSQL_CLIENT
+Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL)
+{
+ my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16);
+}
+
+Deferred_log_events::~Deferred_log_events()
+{
+ delete_dynamic(&array);
+}
+
+int Deferred_log_events::add(Log_event *ev)
+{
+ last_added= ev;
+ insert_dynamic(&array, (uchar*) &ev);
+ return 0;
+}
+
+bool Deferred_log_events::is_empty()
+{
+ return array.elements == 0;
+}
+
+bool Deferred_log_events::execute(Relay_log_info *rli)
+{
+ bool res= false;
+
+ DBUG_ASSERT(rli->deferred_events_collecting);
+
+ rli->deferred_events_collecting= false;
+ for (uint i= 0; !res && i < array.elements; i++)
+ {
+ Log_event *ev= (* (Log_event **)
+ dynamic_array_ptr(&array, i));
+ res= ev->apply_event(rli);
+ }
+ rli->deferred_events_collecting= true;
+ return res;
+}
+
+void Deferred_log_events::rewind()
+{
+ /*
+ Reset preceeding Query log event events which execution was
+ deferred because of slave side filtering.
+ */
+ if (!is_empty())
+ {
+ for (uint i= 0; i < array.elements; i++)
+ {
+ Log_event *ev= *(Log_event **) dynamic_array_ptr(&array, i);
+ delete ev;
+ }
+ if (array.elements > array.max_element)
+ freeze_size(&array);
+ reset_dynamic(&array);
+ }
+}
+
+#endif
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
index 701b9f3c5de..afe54f1dd28 100644
--- a/sql/rpl_utility.h
+++ b/sql/rpl_utility.h
@@ -290,6 +290,24 @@ namespace {
};
}
+
+class Deferred_log_events
+{
+private:
+ DYNAMIC_ARRAY array;
+ Log_event *last_added;
+
+public:
+ Deferred_log_events(Relay_log_info *rli);
+ ~Deferred_log_events();
+ /* queue for exection at Query-log-event time prior the Query */
+ int add(Log_event *ev);
+ bool is_empty();
+ bool execute(Relay_log_info *rli);
+ void rewind();
+ bool is_last(Log_event *ev) { return ev == last_added; };
+};
+
#endif
// NB. number of printed bit values is limited to sizeof(buf) - 1
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 40e26ea4930..6d12c45fc3c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -396,6 +396,8 @@ static sys_var_const sys_lower_case_table_names(&vars,
static sys_var_thd_ulong_session_readonly sys_max_allowed_packet(&vars, "max_allowed_packet",
&SV::max_allowed_packet,
check_max_allowed_packet);
+static sys_var_long_ptr sys_slave_max_allowed_packet(&vars, "slave_max_allowed_packet",
+ &slave_max_allowed_packet);
static sys_var_ulonglong_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size",
&max_binlog_cache_size);
static sys_var_long_ptr sys_max_binlog_size(&vars, "max_binlog_size",
diff --git a/sql/slave.cc b/sql/slave.cc
index 41068ffa211..1a5dd9c4395 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -516,7 +516,7 @@ terminate_slave_thread(THD *thd,
int error __attribute__((unused));
DBUG_PRINT("loop", ("killing slave thread"));
- pthread_mutex_lock(&thd->LOCK_thd_data);
+ pthread_mutex_lock(&thd->LOCK_thd_kill);
#ifndef DONT_USE_THR_ALARM
/*
Error codes from pthread_kill are:
@@ -527,7 +527,7 @@ terminate_slave_thread(THD *thd,
DBUG_ASSERT(err != EINVAL);
#endif
thd->awake(THD::NOT_KILLED);
- pthread_mutex_unlock(&thd->LOCK_thd_data);
+ pthread_mutex_unlock(&thd->LOCK_thd_kill);
/*
There is a small chance that slave thread might miss the first
@@ -1846,8 +1846,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
slave threads, since a replication event can become this much larger
than the corresponding packet (query) sent from client to master.
*/
- thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
- + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
+ thd->variables.max_allowed_packet= slave_max_allowed_packet;
thd->slave_thread = 1;
thd->enable_slow_log= opt_log_slow_slave_statements;
thd->variables.log_slow_filter= global_system_variables.log_slow_filter;
@@ -2323,7 +2322,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
used to read info about the relay log's format; it will be deleted when
the SQL thread does not need it, i.e. when this thread terminates.
*/
- if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
+ if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT &&
+ !rli->is_deferred_event(ev))
{
DBUG_PRINT("info", ("Deleting the event after it has been executed"));
delete ev;
@@ -2593,6 +2593,7 @@ pthread_handler_t handle_slave_io(void *arg)
thread, since a replication event can become this much larger than
the corresponding packet (query) sent from client to master.
*/
+ thd->net.max_packet_size= slave_max_allowed_packet;
mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
}
else
@@ -2724,12 +2725,12 @@ reading event"))
switch (mysql_error_number) {
case CR_NET_PACKET_TOO_LARGE:
sql_print_error("\
-Log entry on master is longer than max_allowed_packet (%ld) on \
+Log entry on master is longer than slave_max_allowed_packet (%lu) on \
slave. If the entry is correct, restart the server with a higher value of \
-max_allowed_packet",
- thd->variables.max_allowed_packet);
+slave_max_allowed_packet",
+ slave_max_allowed_packet);
mi->report(ERROR_LEVEL, ER_NET_PACKET_TOO_LARGE,
- "%s", ER(ER_NET_PACKET_TOO_LARGE));
+ "%s", "Got a packet bigger than 'slave_max_allowed_packet' bytes");
goto err;
case ER_MASTER_FATAL_ERROR_READING_BINLOG:
mi->report(ERROR_LEVEL, ER_MASTER_FATAL_ERROR_READING_BINLOG,
@@ -2955,6 +2956,12 @@ pthread_handler_t handle_slave_sql(void *arg)
goto err;
}
thd->init_for_queries();
+ thd->rli_slave= rli;
+ if ((rli->deferred_events_collecting= rpl_filter->is_on()))
+ {
+ rli->deferred_events= new Deferred_log_events(rli);
+ }
+
thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables
pthread_mutex_lock(&LOCK_thread_count);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e895793f3c8..77ba3c5099c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -116,6 +116,8 @@ static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
bool send_refresh);
static bool
has_write_table_with_auto_increment(TABLE_LIST *tables);
+static bool
+has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables);
extern "C" uchar *table_cache_key(const uchar *record, size_t *length,
@@ -2210,6 +2212,8 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond)
*/
pthread_mutex_unlock(mutex);
+ DEBUG_SYNC(thd, "waiting_for_table_unlock");
+ DBUG_EXECUTE_IF("sleep_after_waiting_for_table", my_sleep(1000000););
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
@@ -5516,6 +5520,12 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
*(ptr++)= table->table;
}
+ if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables)
+ {
+ if (has_write_table_auto_increment_not_first_in_pk(tables))
+ thd->lex->set_stmt_unsafe();
+ }
+
/* We have to emulate LOCK TABLES if we are statement needs prelocking. */
if (thd->lex->requires_prelocking())
{
@@ -9130,6 +9140,32 @@ has_write_table_with_auto_increment(TABLE_LIST *tables)
return 0;
}
+/*
+ Tells if there is a table whose auto_increment column is a part
+ of a compound primary key while is not the first column in
+ the table definition.
+
+ @param tables Table list
+
+ @return true if the table exists, fais if does not.
+*/
+
+static bool
+has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables)
+{
+ for (TABLE_LIST *table= tables; table; table= table->next_global)
+ {
+ /* we must do preliminary checks as table->table may be NULL */
+ if (!table->placeholder() &&
+ table->table->found_next_number_field &&
+ (table->lock_type >= TL_WRITE_ALLOW_WRITE)
+ && table->table->s->next_number_keypart != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
/*
Open and lock system tables for read.
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5d81c57d302..318875c6318 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -369,6 +369,7 @@ extern "C"
char *thd_security_context(THD *thd, char *buffer, unsigned int length,
unsigned int max_query_len)
{
+ DEBUG_SYNC(thd, "thd_security_context");
String str(buffer, length, &my_charset_latin1);
const Security_context *sctx= &thd->main_security_ctx;
char header[64];
@@ -607,7 +608,7 @@ Diagnostics_area::disable_status()
THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
- Open_tables_state(refresh_version), rli_fake(0),
+ Open_tables_state(refresh_version), rli_fake(NULL), rli_slave(NULL),
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0),
sql_log_bin_toplevel(false),
@@ -707,6 +708,7 @@ THD::THD()
active_vio = 0;
#endif
pthread_mutex_init(&LOCK_thd_data, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_thd_kill, MY_MUTEX_INIT_FAST);
/* Variables with default values */
proc_info="login";
@@ -1011,6 +1013,8 @@ THD::~THD()
/* Ensure that no one is using THD */
pthread_mutex_lock(&LOCK_thd_data);
pthread_mutex_unlock(&LOCK_thd_data);
+ pthread_mutex_lock(&LOCK_thd_kill);
+ pthread_mutex_unlock(&LOCK_thd_kill);
add_to_status(&global_status_var, &status_var);
/* Close connection */
@@ -1039,6 +1043,7 @@ THD::~THD()
#endif
mysys_var=0; // Safety (shouldn't be needed)
pthread_mutex_destroy(&LOCK_thd_data);
+ pthread_mutex_destroy(&LOCK_thd_kill);
#ifndef DBUG_OFF
dbug_sentry= THD_SENTRY_GONE;
#endif
@@ -1048,6 +1053,8 @@ THD::~THD()
delete rli_fake;
rli_fake= NULL;
}
+ if (rli_slave)
+ rli_slave->cleanup_after_session();
#endif
free_root(&main_mem_root, MYF(0));
@@ -1123,9 +1130,11 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
void THD::awake(THD::killed_state state_to_set)
{
DBUG_ENTER("THD::awake");
- DBUG_PRINT("enter", ("this: 0x%lx", (long) this));
+ DBUG_PRINT("enter", ("this: 0x%lx thread_id=%lu killed_state=%d",
+ (long) this, thread_id, state_to_set));
THD_CHECK_SENTRY(this);
- safe_mutex_assert_owner(&LOCK_thd_data);
+ safe_mutex_assert_not_owner(&LOCK_thd_data);
+ safe_mutex_assert_owner(&LOCK_thd_kill);
killed= state_to_set;
if (state_to_set != THD::KILL_QUERY)
@@ -1146,7 +1155,9 @@ void THD::awake(THD::killed_state state_to_set)
hack is not used.
*/
+ pthread_mutex_lock(&LOCK_thd_data);
close_active_vio();
+ pthread_mutex_unlock(&LOCK_thd_data);
}
#endif
}
@@ -1335,6 +1346,10 @@ void THD::cleanup_after_query()
/* reset table map for multi-table update */
table_map_for_update= 0;
m_binlog_invoker= FALSE;
+#ifndef EMBEDDED_LIBRARY
+ if (rli_slave)
+ rli_slave->cleanup_after_query();
+#endif
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 40a5d61e433..fb4e13ad9c6 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1312,6 +1312,8 @@ class THD :public Statement,
public:
/* Used to execute base64 coded binlog events in MySQL server */
Relay_log_info* rli_fake;
+ /* Slave applier execution context */
+ Relay_log_info* rli_slave;
/*
Constant for THD::where initialization in the beginning of every query.
@@ -1362,11 +1364,23 @@ public:
Protects THD data accessed from other threads:
- thd->query and thd->query_length (used by SHOW ENGINE
INNODB STATUS and SHOW PROCESSLIST
- - thd->mysys_var (used by KILL statement and shutdown).
- Is locked when THD is deleted.
*/
pthread_mutex_t LOCK_thd_data;
+ /**
+ - Protects thd->mysys_var (used during KILL statement and shutdown).
+ - Is Locked when THD is deleted.
+
+ Note: This responsibility was earlier handled by LOCK_thd_data.
+ This lock is introduced to solve a deadlock issue waiting for
+ LOCK_thd_data. As this lock reduces responsibility of LOCK_thd_data
+ the deadlock issues is solved.
+ Caution: LOCK_thd_kill should not be taken while holding LOCK_thd_data.
+ THD::awake() currently takes LOCK_thd_data after holding
+ LOCK_thd_kill.
+ */
+ pthread_mutex_t LOCK_thd_kill;
+
/* all prepared statements and cursors of this connection */
Statement_map stmt_map;
/*
@@ -2103,7 +2117,6 @@ public:
void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
int send_explain_fields(select_result *result);
-#ifndef EMBEDDED_LIBRARY
/**
Clear the current error, if any.
We do not clear is_fatal_error or is_fatal_sub_stmt_error since we
@@ -2119,9 +2132,9 @@ public:
is_slave_error= 0;
DBUG_VOID_RETURN;
}
+#ifndef EMBEDDED_LIBRARY
inline bool vio_ok() const { return net.vio != 0; }
#else
- void clear_error();
inline bool vio_ok() const { return true; }
#endif
/**
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index cbb3782114a..b95c3981310 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -305,6 +305,8 @@ void lex_start(THD *thd)
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();
lex->select_lex.group_list.empty();
+ if (lex->select_lex.group_list_ptrs)
+ lex->select_lex.group_list_ptrs->clear();
lex->describe= 0;
lex->subqueries= FALSE;
lex->context_analysis_only= 0;
@@ -1642,6 +1644,8 @@ void st_select_lex::init_select()
{
st_select_lex_node::init_select();
group_list.empty();
+ if (group_list_ptrs)
+ group_list_ptrs->clear();
type= db= 0;
having= 0;
table_join_options= 0;
@@ -2920,6 +2924,8 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
The passed WHERE and HAVING are to be saved for the future executions.
This function saves it, and returns a copy which can be thrashed during
this execution of the statement. By saving/thrashing here we mean only
+ We also save the chain of ORDER::next in group_list, in case
+ the list is modified by remove_const().
AND/OR trees.
The function also calls fix_prepare_info_in_table_list that saves all
ON expressions.
@@ -2931,6 +2937,19 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
if (!thd->stmt_arena->is_conventional() && first_execution)
{
first_execution= 0;
+ if (group_list.first)
+ {
+ if (!group_list_ptrs)
+ {
+ void *mem= thd->stmt_arena->alloc(sizeof(Group_list_ptrs));
+ group_list_ptrs= new (mem) Group_list_ptrs(thd->stmt_arena->mem_root);
+ }
+ group_list_ptrs->reserve(group_list.elements);
+ for (ORDER *order= group_list.first; order; order= order->next)
+ {
+ group_list_ptrs->push_back(order);
+ }
+ }
if (*conds)
{
thd->check_and_register_item_tree(&prep_where, conds);
@@ -3035,3 +3054,6 @@ bool st_lex::is_partition_management() const
alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+template class Mem_root_array<ORDER*, true>;
+#endif
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3706d4c30ae..819cf41ec21 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -40,6 +40,7 @@ class Event_parse_data;
*/
#include "set_var.h"
+#include "mem_root_array.h"
#ifdef MYSQL_YACC
#define LEX_YYSTYPE void *
@@ -183,6 +184,7 @@ enum enum_drop_mode
};
typedef List<Item> List_item;
+typedef Mem_root_array<ORDER*, true> Group_list_ptrs;
/* SERVERS CACHE CHANGES */
typedef struct st_lex_server_options
@@ -590,7 +592,16 @@ public:
enum olap_type olap;
/* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
SQL_I_List<TABLE_LIST> table_list;
- SQL_I_List<ORDER> group_list; /* GROUP BY clause. */
+
+ /*
+ GROUP BY clause.
+ This list may be mutated during optimization (by remove_const()),
+ so for prepared statements, we keep a copy of the ORDER.next pointers in
+ group_list_ptrs, and re-establish the original list before each execution.
+ */
+ SQL_I_List<ORDER> group_list;
+ Group_list_ptrs *group_list_ptrs;
+
List<Item> item_list; /* list of fields & expressions */
List<String> interval_list;
bool is_item_list_lookup;
@@ -778,7 +789,8 @@ public:
bool test_limit();
friend void lex_start(THD *thd);
- st_select_lex() : n_sum_items(0), n_child_sum_items(0) {}
+ st_select_lex() : group_list_ptrs(NULL), n_sum_items(0), n_child_sum_items(0)
+ {}
void make_empty_select()
{
init_query();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 64eb7645d03..e0e6a4a57d6 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2307,6 +2307,11 @@ mysql_execute_command(THD *thd)
}
DBUG_RETURN(0);
}
+ /*
+ Execute deferred events first
+ */
+ if (slave_execute_deferred_events(thd))
+ DBUG_RETURN(-1);
}
else
{
@@ -3083,7 +3088,7 @@ end_with_restore_list:
goto error;
#else
{
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_binlogs(thd);
break;
@@ -7298,7 +7303,7 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
continue;
if (tmp->thread_id == id)
{
- pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ pthread_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
break;
}
}
@@ -7326,12 +7331,13 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx))
{
+ DEBUG_SYNC(thd, "kill_one_thread_before_kill");
tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
error=0;
}
else
error=ER_KILL_DENIED_ERROR;
- pthread_mutex_unlock(&tmp->LOCK_thd_data);
+ pthread_mutex_unlock(&tmp->LOCK_thd_kill);
}
DBUG_PRINT("exit", ("%d", error));
DBUG_RETURN(error);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 6aa119f7d71..7f5cbc5e99b 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2366,6 +2366,14 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
+ if (sl->group_list_ptrs && sl->group_list_ptrs->size() > 0)
+ {
+ for (uint ix= 0; ix < sl->group_list_ptrs->size() - 1; ++ix)
+ {
+ order= sl->group_list_ptrs->at(ix);
+ order->next= sl->group_list_ptrs->at(ix+1);
+ }
+ }
for (order= sl->group_list.first; order; order= order->next)
order->item= &order->item_ptr;
/* Fix ORDER list */
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 116cdb91ef3..5bc91eff001 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2007, 2010, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+ Copyright (c) 2007, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -82,8 +82,8 @@ ST_FIELD_INFO query_profile_statistics_info[]=
int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
{
- int profile_options = thd->lex->profile_options;
- int fields_include_condition_truth_values[]= {
+ uint profile_options = thd->lex->profile_options;
+ uint fields_include_condition_truth_values[]= {
FALSE, /* Query_id */
FALSE, /* Seq */
TRUE, /* Status */
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 7a09074f554..d84b8bbcd81 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -470,7 +470,7 @@ impossible position";
this larger than the corresponding packet (query) sent
from client to master.
*/
- thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
+ thd->variables.max_allowed_packet= MAX_MAX_ALLOWED_PACKET;
/*
We can set log_lock now, it does not move (it's a member of
@@ -1139,7 +1139,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
if (tmp->command == COM_BINLOG_DUMP &&
tmp->server_id == slave_server_id)
{
- pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ pthread_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
break;
}
}
@@ -1152,7 +1152,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
again. We just to do kill the thread ourselves.
*/
tmp->awake(THD::KILL_QUERY);
- pthread_mutex_unlock(&tmp->LOCK_thd_data);
+ pthread_mutex_unlock(&tmp->LOCK_thd_kill);
}
}
@@ -1460,6 +1460,8 @@ bool mysql_show_binlog_events(THD* thd)
IO_CACHE log;
File file = -1;
int old_max_allowed_packet= thd->variables.max_allowed_packet;
+ LOG_INFO linfo;
+
DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list);
@@ -1486,7 +1488,6 @@ bool mysql_show_binlog_events(THD* thd)
char search_file_name[FN_REFLEN], *name;
const char *log_file_name = lex_mi->log_file_name;
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
- LOG_INFO linfo;
Log_event* ev;
unit->set_limit(thd->lex->current_select);
@@ -1578,6 +1579,8 @@ bool mysql_show_binlog_events(THD* thd)
pthread_mutex_unlock(log_lock);
}
+ // Check that linfo is still on the function scope.
+ DEBUG_SYNC(thd, "after_show_binlog_events");
ret= FALSE;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 745e02e128a..3dc80bdef3b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -538,6 +538,8 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having)
{
+ Query_arena backup, *arena;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause";
thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
@@ -546,6 +548,10 @@ JOIN::prepare(Item ***rref_pointer_array,
(having->fix_fields(thd, &having) ||
having->check_cols(1)));
select_lex->having_fix_field= 0;
+ select_lex->having= having;
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+
if (having_fix_rc || thd->is_error())
DBUG_RETURN(-1); /* purecov: inspected */
thd->lex->allow_sum_func= save_allow_sum_func;
@@ -12107,7 +12113,8 @@ int report_error(TABLE *table, int error)
Locking reads can legally return also these errors, do not
print them to the .err log
*/
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT
+ && !table->in_use->killed)
sql_print_error("Got error %d when reading table '%s'",
error, table->s->path.str);
table->file->print_error(error,MYF(0));
@@ -14203,8 +14210,6 @@ check_reverse_order:
join_read_first:join_read_last;
tab->type=JT_NEXT; // Read with index_first(), index_next()
- if (table->covering_keys.is_set(best_key) && ! table->key_read)
- table->enable_keyread();
table->file->ha_index_or_rnd_end();
if (tab->join->select_options & SELECT_DESCRIBE)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 02505962347..f3e49b40811 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3232,39 +3232,44 @@ end:
static int fill_schema_table_names(THD *thd, TABLE *table,
LEX_STRING *db_name, LEX_STRING *table_name,
- bool with_i_schema)
+ bool with_i_schema,
+ bool need_table_type)
{
- if (with_i_schema)
+ /* Avoid opening FRM files if table type is not needed. */
+ if (need_table_type)
{
- table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
- system_charset_info);
- }
- else
- {
- enum legacy_db_type not_used;
- char path[FN_REFLEN + 1];
- (void) build_table_filename(path, sizeof(path) - 1, db_name->str,
- table_name->str, reg_ext, 0);
- switch (mysql_frm_type(thd, path, &not_used)) {
- case FRMTYPE_ERROR:
- table->field[3]->store(STRING_WITH_LEN("ERROR"),
- system_charset_info);
- break;
- case FRMTYPE_TABLE:
- table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
- system_charset_info);
- break;
- case FRMTYPE_VIEW:
- table->field[3]->store(STRING_WITH_LEN("VIEW"),
+ if (with_i_schema)
+ {
+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
system_charset_info);
- break;
- default:
- DBUG_ASSERT(0);
}
- if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
+ else
{
- thd->clear_error();
- return 0;
+ enum legacy_db_type not_used;
+ char path[FN_REFLEN + 1];
+ (void) build_table_filename(path, sizeof(path) - 1, db_name->str,
+ table_name->str, reg_ext, 0);
+ switch (mysql_frm_type(thd, path, &not_used)) {
+ case FRMTYPE_ERROR:
+ table->field[3]->store(STRING_WITH_LEN("ERROR"),
+ system_charset_info);
+ break;
+ case FRMTYPE_TABLE:
+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
+ system_charset_info);
+ break;
+ case FRMTYPE_VIEW:
+ table->field[3]->store(STRING_WITH_LEN("VIEW"),
+ system_charset_info);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ thd->clear_error();
+ return 0;
+ }
}
}
if (schema_table_store_record(thd, table))
@@ -3585,7 +3590,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (schema_table_idx == SCH_TABLE_NAMES)
{
if (fill_schema_table_names(thd, tables->table, db_name,
- table_name, with_i_schema))
+ table_name, with_i_schema,
+ lex->verbose))
continue;
}
else
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 37a963b4dfb..0dd36592539 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5060,7 +5060,23 @@ type:
$$= MYSQL_TYPE_VARCHAR;
}
| YEAR_SYM opt_field_length field_options
- { $$=MYSQL_TYPE_YEAR; }
+ {
+ if (Lex->length)
+ {
+ errno= 0;
+ ulong length= strtoul(Lex->length, NULL, 10);
+ if (errno == 0 && length <= MAX_FIELD_BLOBLENGTH && length != 4)
+ {
+ char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
+ my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
+ push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER(ER_WARN_DEPRECATED_SYNTAX),
+ buff, "YEAR(4)");
+ }
+ }
+ $$=MYSQL_TYPE_YEAR;
+ }
| DATE_SYM
{ $$=MYSQL_TYPE_DATE; }
| TIME_SYM
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index c09d6408fa0..4678ea8cd22 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -2792,6 +2792,8 @@ btr_estimate_n_rows_in_range(
n_rows = n_rows * 2;
}
+ DBUG_EXECUTE_IF("bug14007649", return(n_rows););
+
/* Do not estimate the number of rows in the range
to over 1 / 2 of the estimated rows in the whole
table */
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 7e820cfb08d..3c3c0d10c7c 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -150,7 +150,7 @@ dict_print(void)
monitor printout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
mutex_enter(&(dict_sys->mutex));
@@ -178,7 +178,7 @@ loop:
/* Restore the fatal semaphore wait timeout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
return;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 6576016501f..796f51d737b 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3180,6 +3180,30 @@ table_opened:
DBUG_RETURN(0);
}
+handler*
+ha_innobase::clone(
+/*===============*/
+ const char* name, /*!< in: table name */
+ MEM_ROOT* mem_root) /*!< in: memory context */
+{
+ ha_innobase* new_handler;
+
+ DBUG_ENTER("ha_innobase::clone");
+
+ new_handler = static_cast<ha_innobase*>(handler::clone(name,
+ mem_root));
+ if (new_handler) {
+ DBUG_ASSERT(new_handler->prebuilt != NULL);
+ DBUG_ASSERT(new_handler->user_thd == user_thd);
+ DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
+
+ new_handler->prebuilt->select_lock_type
+ = prebuilt->select_lock_type;
+ }
+
+ DBUG_RETURN(new_handler);
+}
+
uint
ha_innobase::max_supported_key_part_length() const
{
@@ -4869,6 +4893,7 @@ ha_innobase::index_read(
ulint ret;
DBUG_ENTER("index_read");
+ DEBUG_SYNC_C("ha_innobase_index_read_begin");
ut_a(prebuilt->trx == thd_to_trx(user_thd));
ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
@@ -9103,7 +9128,7 @@ static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
PLUGIN_VAR_RQCMDARG,
"Desired maximum length of the purge queue (0 = no limit)",
- NULL, NULL, 0, 0, ~0L, 0);
+ NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@@ -9157,7 +9182,7 @@ static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
PLUGIN_VAR_RQCMDARG,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
- NULL, NULL, 500L, 1L, ~0L, 0);
+ NULL, NULL, 500L, 1L, ~0UL, 0);
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
@@ -9202,7 +9227,7 @@ static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
PLUGIN_VAR_RQCMDARG,
"Count of spin-loop rounds in InnoDB mutexes",
- NULL, NULL, 20L, 0L, ~0L, 0);
+ NULL, NULL, 20L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG,
@@ -9212,7 +9237,7 @@ static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
PLUGIN_VAR_RQCMDARG,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
- NULL, NULL, 10000L, 0L, ~0L, 0);
+ NULL, NULL, 10000L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 8b91f7d4c51..93229ad9185 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -117,6 +117,7 @@ class ha_innobase: public handler
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
int open(const char *name, int mode, uint test_if_locked);
+ handler* clone(const char *name, MEM_ROOT *mem_root);
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 811074b2be8..aa6c88e0538 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -173,6 +173,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
+#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
extern ulint srv_dml_needed_delay;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index e8b3c485b0e..6c2f910eec7 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -4189,7 +4189,7 @@ row_check_table_for_mysql(
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
index = dict_table_get_first_index(table);
@@ -4247,7 +4247,7 @@ row_check_table_for_mysql(
/* Restore the fatal lock wait timeout after CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
prebuilt->trx->op_info = "";
diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c
index 93a7398f252..60a96fe4388 100644
--- a/storage/innobase/sync/sync0arr.c
+++ b/storage/innobase/sync/sync0arr.c
@@ -931,6 +931,11 @@ sync_array_print_long_waits(
ibool fatal = FALSE;
double longest_diff = 0;
+ /* For huge tables, skip the check during CHECK TABLE etc... */
+ if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
+ return(FALSE);
+ }
+
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff;
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index b67da53ec8a..223b976dea7 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -3194,6 +3194,8 @@ btr_estimate_n_rows_in_range(
n_rows = n_rows * 2;
}
+ DBUG_EXECUTE_IF("bug14007649", return(n_rows););
+
/* Do not estimate the number of rows in the range
to over 1 / 2 of the estimated rows in the whole
table */
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index df7ac85681c..cfeba015723 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -4872,6 +4872,28 @@ dict_table_replace_index_in_foreign_list(
foreign->foreign_index = new_index;
}
}
+
+
+ for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ foreign;
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+
+ dict_index_t* new_index;
+
+ if (foreign->referenced_index == index) {
+ ut_ad(foreign->referenced_table == index->table);
+
+ new_index = dict_foreign_find_index(
+ foreign->referenced_table,
+ foreign->referenced_col_names,
+ foreign->n_fields, index,
+ /*check_charsets=*/TRUE, /*check_null=*/FALSE);
+ ut_ad(new_index || !trx->check_foreigns);
+ ut_ad(!new_index || new_index->table == index->table);
+
+ foreign->referenced_index = new_index;
+ }
+ }
}
/**********************************************************************//**
diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
index 7a0b6edcb08..7231fadabe1 100644
--- a/storage/innodb_plugin/dict/dict0load.c
+++ b/storage/innodb_plugin/dict/dict0load.c
@@ -164,7 +164,7 @@ dict_print(void)
monitor printout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
mutex_enter(&(dict_sys->mutex));
@@ -192,7 +192,7 @@ loop:
/* Restore the fatal semaphore wait timeout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
return;
diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
index eebfbd9ccad..6f2ab938042 100644
--- a/storage/innodb_plugin/fil/fil0fil.c
+++ b/storage/innodb_plugin/fil/fil0fil.c
@@ -1853,7 +1853,7 @@ fil_inc_pending_ops(
if (space == NULL) {
fprintf(stderr,
- "InnoDB: Error: trying to do ibuf merge to a"
+ "InnoDB: Error: trying to do an operation on a"
" dropped tablespace %lu\n",
(ulong) id);
}
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index 41224dcf470..ea3d6ae010f 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -3890,6 +3890,31 @@ table_opened:
}
UNIV_INTERN
+handler*
+ha_innobase::clone(
+/*===============*/
+ const char* name, /*!< in: table name */
+ MEM_ROOT* mem_root) /*!< in: memory context */
+{
+ ha_innobase* new_handler;
+
+ DBUG_ENTER("ha_innobase::clone");
+
+ new_handler = static_cast<ha_innobase*>(handler::clone(name,
+ mem_root));
+ if (new_handler) {
+ DBUG_ASSERT(new_handler->prebuilt != NULL);
+ DBUG_ASSERT(new_handler->user_thd == user_thd);
+ DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
+
+ new_handler->prebuilt->select_lock_type
+ = prebuilt->select_lock_type;
+ }
+
+ DBUG_RETURN(new_handler);
+}
+
+UNIV_INTERN
uint
ha_innobase::max_supported_key_part_length() const
{
@@ -8153,7 +8178,7 @@ ha_innobase::check(
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
for (index = dict_table_get_first_index(prebuilt->table);
@@ -8249,7 +8274,7 @@ ha_innobase::check(
/* Restore the fatal lock wait timeout after CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
prebuilt->trx->op_info = "";
@@ -10950,7 +10975,7 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
PLUGIN_VAR_RQCMDARG,
"Number of IOPs the server can do. Tunes the background IO rate",
- NULL, NULL, 200, 100, ~0L, 0);
+ NULL, NULL, 200, 100, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
PLUGIN_VAR_OPCMDARG,
@@ -11028,7 +11053,7 @@ static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
PLUGIN_VAR_RQCMDARG,
"Desired maximum length of the purge queue (0 = no limit)",
- NULL, NULL, 0, 0, ~0L, 0);
+ NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@@ -11085,7 +11110,7 @@ static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
PLUGIN_VAR_RQCMDARG,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
- NULL, NULL, 500L, 1L, ~0L, 0);
+ NULL, NULL, 500L, 1L, ~0UL, 0);
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
@@ -11147,12 +11172,12 @@ static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
PLUGIN_VAR_RQCMDARG,
"Count of spin-loop rounds in InnoDB mutexes (30 by default)",
- NULL, NULL, 30L, 0L, ~0L, 0);
+ NULL, NULL, 30L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
PLUGIN_VAR_OPCMDARG,
"Maximum delay between polling for a spin lock (6 by default)",
- NULL, NULL, 6L, 0L, ~0L, 0);
+ NULL, NULL, 6L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG,
@@ -11162,7 +11187,7 @@ static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
PLUGIN_VAR_RQCMDARG,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
- NULL, NULL, 10000L, 0L, ~0L, 0);
+ NULL, NULL, 10000L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h
index f7a5456b1a7..15cc4a77b6f 100644
--- a/storage/innodb_plugin/handler/ha_innodb.h
+++ b/storage/innodb_plugin/handler/ha_innodb.h
@@ -132,6 +132,7 @@ class ha_innobase: public handler
const key_map* keys_to_use_for_scanning();
int open(const char *name, int mode, uint test_if_locked);
+ handler* clone(const char *name, MEM_ROOT *mem_root);
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index e2702b157af..6f02b500d96 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -665,6 +665,10 @@ ha_innobase::add_index(
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
+ if (innodb_table->tablespace_discarded) {
+ DBUG_RETURN(-1);
+ }
+
/* Check that index keys are sensible */
error = innobase_check_index_keys(key_info, num_of_keys, innodb_table);
diff --git a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
index 7c63a5f0d45..1a9f54882c5 100644
--- a/storage/innodb_plugin/include/srv0srv.h
+++ b/storage/innodb_plugin/include/srv0srv.h
@@ -244,6 +244,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
+#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
extern ulint srv_dml_needed_delay;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 2d4afa6c5ed..4994a91dd23 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -1296,7 +1296,8 @@ run_again:
check_index = foreign->foreign_index;
}
- if (check_table == NULL || check_table->ibd_file_missing) {
+ if (check_table == NULL || check_table->ibd_file_missing
+ || check_index == NULL) {
if (check_ref) {
FILE* ef = dict_foreign_err_file;
@@ -1331,9 +1332,6 @@ run_again:
goto exit_func;
}
- ut_a(check_table);
- ut_a(check_index);
-
if (check_table != table) {
/* We already have a LOCK_IX on table, but not necessarily
on check_table */
diff --git a/storage/innodb_plugin/row/row0vers.c b/storage/innodb_plugin/row/row0vers.c
index 8a7bb842293..9aeaa2db6c0 100644
--- a/storage/innodb_plugin/row/row0vers.c
+++ b/storage/innodb_plugin/row/row0vers.c
@@ -208,18 +208,6 @@ row_vers_impl_x_locked_off_kernel(
vers_del = rec_get_deleted_flag(prev_version, comp);
prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
clust_offsets);
-
- /* If the trx_id and prev_trx_id are different and if
- the prev_version is marked deleted then the
- prev_trx_id must have already committed for the trx_id
- to be able to modify the row. Therefore, prev_trx_id
- cannot hold any implicit lock. */
- if (vers_del && 0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
-
- mutex_enter(&kernel_mutex);
- break;
- }
-
/* The stack of versions is locked by mtr. Thus, it
is safe to fetch the prefixes for externally stored
columns. */
diff --git a/storage/innodb_plugin/sync/sync0arr.c b/storage/innodb_plugin/sync/sync0arr.c
index 13970023573..90ea50b641b 100644
--- a/storage/innodb_plugin/sync/sync0arr.c
+++ b/storage/innodb_plugin/sync/sync0arr.c
@@ -927,6 +927,11 @@ sync_array_print_long_waits(
ibool fatal = FALSE;
double longest_diff = 0;
+ /* For huge tables, skip the check during CHECK TABLE etc... */
+ if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
+ return(FALSE);
+ }
+
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff;
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 01bff11fb3d..71ec55fc798 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -354,7 +354,7 @@ static int _ftb_no_dupes_cmp(void* not_used __attribute__((unused)),
returns 1 if the search was finished (must-word wasn't found)
*/
-static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
+static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
int r;
int subkeys=1;
@@ -454,7 +454,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
ftbw->off=0;
- return _ft2_search(ftb, ftbw, 0);
+ return _ft2_search_no_lock(ftb, ftbw, 0);
}
/* matching key found */
@@ -482,6 +482,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
return 0;
}
+static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
+{
+ int r;
+ MYISAM_SHARE *share= ftb->info->s;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[ftb->keynr]);
+ r= _ft2_search_no_lock(ftb, ftbw, init_search);
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[ftb->keynr]);
+ return r;
+}
+
static void _ftb_init_index_search(FT_INFO *ftb)
{
int i;
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index 85557b5e6c4..9ebdef582c9 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -72,9 +72,10 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
TREE_ELEMENT *selem;
double gweight=1;
MI_INFO *info=aio->info;
+ MYISAM_SHARE *share= info->s;
uchar *keybuff=aio->keybuff;
MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
- my_off_t key_root=info->s->state.key_root[aio->keynr];
+ my_off_t key_root;
uint extra= HA_FT_WLEN + info->s->rec_reflength;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
@@ -89,6 +90,11 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
keylen-=HA_FT_WLEN;
doc_cnt=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
+
+ key_root= share->state.key_root[aio->keynr];
+
/* Skip rows inserted by current inserted */
for (r=_mi_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ;
!r &&
@@ -98,6 +104,9 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
info->lastkey_length, SEARCH_BIGGER, key_root))
;
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[aio->keynr]);
+
info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
/* The following should be safe, even if we compare doubles */
@@ -121,6 +130,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
keyinfo=& info->s->ft2_keyinfo;
key_root=info->lastpos;
keylen=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
r=_mi_search_first(info, keyinfo, key_root);
goto do_skip;
}
@@ -156,6 +167,9 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
if (gweight < 0 || doc_cnt > 2000000)
gweight=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
+
if (_mi_test_if_changed(info) == 0)
r=_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
SEARCH_BIGGER, key_root);
@@ -168,6 +182,8 @@ do_skip:
r= _mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
SEARCH_BIGGER, key_root);
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[aio->keynr]);
}
word->weight=gweight;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 204c5457f13..48ac873fcd0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -33,6 +33,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
grant.pl grant.res test_delayed_insert.pl \
pmail.pl mail_to_db.pl table_types.pl \
myisam-big-rows.tst \
+ mysql_client_fw.c \
CMakeLists.txt
bin_PROGRAMS = mysql_client_test
@@ -47,6 +48,7 @@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \
mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
mysql_client_test_SOURCES= mysql_client_test.c\
$(top_srcdir)/mysys/my_memmem.c
+mysql_client_test.o: mysql_client_fw.c
insert_test_SOURCES= insert_test.c
select_test_SOURCES= select_test.c
diff --git a/tests/mysql_client_fw.c b/tests/mysql_client_fw.c
new file mode 100644
index 00000000000..ec909c91079
--- /dev/null
+++ b/tests/mysql_client_fw.c
@@ -0,0 +1,1378 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <errmsg.h>
+#include <my_getopt.h>
+#include <m_string.h>
+#include <mysqld_error.h>
+#include <my_handler.h>
+
+#define VER "2.1"
+#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
+#define MAX_KEY MAX_INDEXES
+#define MAX_SERVER_ARGS 64
+
+/* set default options */
+static int opt_testcase __attribute__((unused)) = 0;
+static char *opt_db= 0;
+static char *opt_user= 0;
+static char *opt_password= 0;
+static char *opt_host= 0;
+static char *opt_unix_socket= 0;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name= 0;
+#endif
+static unsigned int opt_port;
+static my_bool tty_password= 0, opt_silent= 0;
+
+static MYSQL *mysql= 0;
+static char current_db[]= "client_test_db";
+static unsigned int test_count= 0;
+static unsigned int opt_count= 0;
+static unsigned int iter_count= 0;
+static my_bool have_innodb= FALSE;
+
+static const char *opt_basedir= "./";
+static const char *opt_vardir= "mysql-test/var";
+
+static longlong opt_getopt_ll_test= 0;
+
+static int embedded_server_arg_count= 0;
+static char *embedded_server_args[MAX_SERVER_ARGS];
+
+static const char *embedded_server_groups[]= {
+"server",
+"embedded",
+"mysql_client_test_SERVER",
+NullS
+};
+
+static time_t start_time, end_time;
+static double total_time;
+
+const char *default_dbug_option= "d:t:o,/tmp/mysql_client_test.trace";
+
+struct my_tests_st
+{
+const char *name;
+void (*function)();
+};
+
+#define myheader(str) \
+DBUG_PRINT("test", ("name: %s", str)); \
+ if (opt_silent < 2) \
+ { \
+ fprintf(stdout, "\n\n#####################################\n"); \
+ fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \
+ opt_count, str); \
+ fprintf(stdout, " \n#####################################\n"); \
+ }
+
+#define myheader_r(str) \
+DBUG_PRINT("test", ("name: %s", str)); \
+ if (!opt_silent) \
+ { \
+ fprintf(stdout, "\n\n#####################################\n"); \
+ fprintf(stdout, "%s", str); \
+ fprintf(stdout, " \n#####################################\n"); \
+ }
+
+static void print_error(const char *msg);
+static void print_st_error(MYSQL_STMT *stmt, const char *msg);
+static void client_disconnect(MYSQL* mysql, my_bool drop_db);
+
+
+/*
+Abort unless given experssion is non-zero.
+
+SYNOPSIS
+DIE_UNLESS(expr)
+
+DESCRIPTION
+We can't use any kind of system assert as we need to
+preserve tested invariants in release builds as well.
+*/
+
+#define DIE_UNLESS(expr) \
+((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
+#define DIE_IF(expr) \
+((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
+#define DIE(expr) \
+die(__FILE__, __LINE__, #expr)
+
+static void die(const char *file, int line, const char *expr)
+{
+ fflush(stdout);
+ fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr);
+ fflush(stderr);
+ exit(1);
+}
+
+
+#define myerror(msg) print_error(msg)
+#define mysterror(stmt, msg) print_st_error(stmt, msg)
+
+#define myquery(RES) \
+{ \
+ int r= (RES); \
+ if (r) \
+ myerror(NULL); \
+ DIE_UNLESS(r == 0); \
+}
+
+#define myquery_r(r) \
+{ \
+ if (r) \
+ myerror(NULL); \
+ DIE_UNLESS(r != 0); \
+}
+
+#define check_execute(stmt, r) \
+{ \
+ if (r) \
+ mysterror(stmt, NULL); \
+ DIE_UNLESS(r == 0); \
+}
+
+#define check_execute_r(stmt, r) \
+{ \
+ if (r) \
+ mysterror(stmt, NULL); \
+ DIE_UNLESS(r != 0); \
+}
+
+#define check_stmt(stmt) \
+{ \
+ if ( stmt == 0) \
+ myerror(NULL); \
+ DIE_UNLESS(stmt != 0); \
+}
+
+#define check_stmt_r(stmt) \
+{ \
+ if (stmt == 0) \
+ myerror(NULL); \
+ DIE_UNLESS(stmt == 0); \
+}
+
+#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);}
+#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);}
+
+
+/* A workaround for Sun Forte 5.6 on Solaris x86 */
+
+static int cmp_double(double *a, double *b)
+{
+ return *a == *b;
+}
+
+
+/* Print the error message */
+
+static void print_error(const char *msg)
+{
+ if (!opt_silent)
+ {
+ if (mysql && mysql_errno(mysql))
+ {
+ if (mysql->server_version)
+ fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
+ else
+ fprintf(stdout, "\n [MySQL]");
+ fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
+ }
+ else if (msg)
+ fprintf(stderr, " [MySQL] %s\n", msg);
+ }
+}
+
+
+static void print_st_error(MYSQL_STMT *stmt, const char *msg)
+{
+ if (!opt_silent)
+ {
+ if (stmt && mysql_stmt_errno(stmt))
+ {
+ if (stmt->mysql && stmt->mysql->server_version)
+ fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version);
+ else
+ fprintf(stdout, "\n [MySQL]");
+
+ fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt));
+ }
+ else if (msg)
+ fprintf(stderr, " [MySQL] %s\n", msg);
+ }
+}
+
+/*
+Enhanced version of mysql_client_init(), which may also set shared memory
+base on Windows.
+*/
+static MYSQL *mysql_client_init(MYSQL* con)
+{
+ MYSQL* res = mysql_init(con);
+ #ifdef HAVE_SMEM
+ if (res && shared_memory_base_name)
+ mysql_options(res, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name);
+ #endif
+ return res;
+}
+
+/*
+Disable direct calls of mysql_init, as it disregards shared memory base.
+*/
+#define mysql_init(A) Please use mysql_client_init instead of mysql_init
+
+
+/* Check if the connection has InnoDB tables */
+
+static my_bool check_have_innodb(MYSQL *conn)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ my_bool result;
+
+ rc= mysql_query(conn, "show variables like 'have_innodb'");
+ myquery(rc);
+ res= mysql_use_result(conn);
+ DIE_UNLESS(res);
+
+ row= mysql_fetch_row(res);
+ DIE_UNLESS(row);
+
+ result= strcmp(row[1], "YES") == 0;
+ mysql_free_result(res);
+ return result;
+}
+
+
+/*
+This is to be what mysql_query() is for mysql_real_query(), for
+mysql_simple_prepare(): a variant without the 'length' parameter.
+*/
+
+static MYSQL_STMT *STDCALL
+mysql_simple_prepare(MYSQL *mysql_arg, const char *query)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql_arg);
+ if (stmt && mysql_stmt_prepare(stmt, query, (uint) strlen(query)))
+ {
+ mysql_stmt_close(stmt);
+ return 0;
+ }
+ return stmt;
+}
+
+
+/**
+Connect to the server with options given by arguments to this application,
+stored in global variables opt_host, opt_user, opt_password, opt_db,
+opt_port and opt_unix_socket.
+
+@param flag[in] client_flag passed on to mysql_real_connect
+@param protocol[in] MYSQL_PROTOCOL_* to use for this connection
+@param auto_reconnect[in] set to 1 for auto reconnect
+
+@return pointer to initialized and connected MYSQL object
+*/
+static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect)
+{
+ MYSQL* mysql;
+ int rc;
+ static char query[MAX_TEST_QUERY_LENGTH];
+ myheader_r("client_connect");
+
+ if (!opt_silent)
+ fprintf(stdout, "\n Establishing a connection to '%s' ...",
+ opt_host ? opt_host : "");
+
+ if (!(mysql= mysql_client_init(NULL)))
+ {
+ opt_silent= 0;
+ myerror("mysql_client_init() failed");
+ exit(1);
+ }
+ /* enable local infile, in non-binary builds often disabled by default */
+ mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
+ mysql_options(mysql, MYSQL_OPT_PROTOCOL, &protocol);
+
+ if (!(mysql_real_connect(mysql, opt_host, opt_user,
+ opt_password, opt_db ? opt_db:"test", opt_port,
+ opt_unix_socket, flag)))
+ {
+ opt_silent= 0;
+ myerror("connection failed");
+ mysql_close(mysql);
+ fprintf(stdout, "\n Check the connection options using --help or -?\n");
+ exit(1);
+ }
+ mysql->reconnect= auto_reconnect;
+
+ if (!opt_silent)
+ fprintf(stdout, "OK");
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(mysql, TRUE);
+
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\nConnected to MySQL server version: %s (%lu)\n",
+ mysql_get_server_info(mysql),
+ (ulong) mysql_get_server_version(mysql));
+ fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
+ }
+ strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
+
+ rc= mysql_query(mysql, query);
+ myquery(rc);
+
+ strxmov(query, "USE ", current_db, NullS);
+ rc= mysql_query(mysql, query);
+ myquery(rc);
+ have_innodb= check_have_innodb(mysql);
+
+ if (!opt_silent)
+ fprintf(stdout, "OK");
+
+ return mysql;
+}
+
+
+/* Close the connection */
+
+static void client_disconnect(MYSQL* mysql, my_bool drop_db)
+{
+ static char query[MAX_TEST_QUERY_LENGTH];
+
+ myheader_r("client_disconnect");
+
+ if (mysql)
+ {
+ if (drop_db)
+ {
+ if (!opt_silent)
+ fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
+ strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
+
+ mysql_query(mysql, query);
+ if (!opt_silent)
+ fprintf(stdout, "OK");
+ }
+
+ if (!opt_silent)
+ fprintf(stdout, "\n closing the connection ...");
+ mysql_close(mysql);
+ if (!opt_silent)
+ fprintf(stdout, "OK\n");
+ }
+}
+
+
+/* Print dashes */
+
+static void my_print_dashes(MYSQL_RES *result)
+{
+ MYSQL_FIELD *field;
+ unsigned int i, j;
+
+ mysql_field_seek(result, 0);
+ fputc('\t', stdout);
+ fputc('+', stdout);
+
+ for(i= 0; i< mysql_num_fields(result); i++)
+ {
+ field= mysql_fetch_field(result);
+ for(j= 0; j < field->max_length+2; j++)
+ fputc('-', stdout);
+ fputc('+', stdout);
+ }
+ fputc('\n', stdout);
+}
+
+
+/* Print resultset metadata information */
+
+static void my_print_result_metadata(MYSQL_RES *result)
+{
+ MYSQL_FIELD *field;
+ unsigned int i, j;
+ unsigned int field_count;
+
+ mysql_field_seek(result, 0);
+ if (!opt_silent)
+ {
+ fputc('\n', stdout);
+ fputc('\n', stdout);
+ }
+
+ field_count= mysql_num_fields(result);
+ for(i= 0; i< field_count; i++)
+ {
+ field= mysql_fetch_field(result);
+ j= strlen(field->name);
+ if (j < field->max_length)
+ j= field->max_length;
+ if (j < 4 && !IS_NOT_NULL(field->flags))
+ j= 4;
+ field->max_length= j;
+ }
+ if (!opt_silent)
+ {
+ my_print_dashes(result);
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
+
+ mysql_field_seek(result, 0);
+ for(i= 0; i< field_count; i++)
+ {
+ field= mysql_fetch_field(result);
+ if (!opt_silent)
+ fprintf(stdout, " %-*s |", (int) field->max_length, field->name);
+ }
+ if (!opt_silent)
+ {
+ fputc('\n', stdout);
+ my_print_dashes(result);
+ }
+}
+
+
+/* Process the result set */
+
+static int my_process_result_set(MYSQL_RES *result)
+{
+ MYSQL_ROW row;
+ MYSQL_FIELD *field;
+ unsigned int i;
+ unsigned int row_count= 0;
+
+ if (!result)
+ return 0;
+
+ my_print_result_metadata(result);
+
+ while ((row= mysql_fetch_row(result)) != NULL)
+ {
+ mysql_field_seek(result, 0);
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
+
+ for(i= 0; i< mysql_num_fields(result); i++)
+ {
+ field= mysql_fetch_field(result);
+ if (!opt_silent)
+ {
+ if (row[i] == NULL)
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
+ }
+ }
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('\n', stdout);
+ }
+ row_count++;
+ }
+ if (!opt_silent)
+ {
+ if (row_count)
+ my_print_dashes(result);
+
+ if (mysql_errno(mysql) != 0)
+ fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
+ else
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ }
+ return row_count;
+}
+
+
+static int my_process_result(MYSQL *mysql_arg)
+{
+ MYSQL_RES *result;
+ int row_count;
+
+ if (!(result= mysql_store_result(mysql_arg)))
+ return 0;
+
+ row_count= my_process_result_set(result);
+
+ mysql_free_result(result);
+ return row_count;
+}
+
+
+/* Process the statement result set */
+
+#define MAX_RES_FIELDS 50
+#define MAX_FIELD_DATA_SIZE 255
+
+static int my_process_stmt_result(MYSQL_STMT *stmt)
+{
+ int field_count;
+ int row_count= 0;
+ MYSQL_BIND buffer[MAX_RES_FIELDS];
+ MYSQL_FIELD *field;
+ MYSQL_RES *result;
+ char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE];
+ ulong length[MAX_RES_FIELDS];
+ my_bool is_null[MAX_RES_FIELDS];
+ int rc, i;
+
+ if (!(result= mysql_stmt_result_metadata(stmt))) /* No meta info */
+ {
+ while (!mysql_stmt_fetch(stmt))
+ row_count++;
+ return row_count;
+ }
+
+ field_count= min(mysql_num_fields(result), MAX_RES_FIELDS);
+
+ bzero((char*) buffer, sizeof(buffer));
+ bzero((char*) length, sizeof(length));
+ bzero((char*) is_null, sizeof(is_null));
+
+ for(i= 0; i < field_count; i++)
+ {
+ buffer[i].buffer_type= MYSQL_TYPE_STRING;
+ buffer[i].buffer_length= MAX_FIELD_DATA_SIZE;
+ buffer[i].length= &length[i];
+ buffer[i].buffer= (void *) data[i];
+ buffer[i].is_null= &is_null[i];
+ }
+
+ rc= mysql_stmt_bind_result(stmt, buffer);
+ check_execute(stmt, rc);
+
+ rc= 1;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
+ mysql_field_seek(result, 0);
+ for (i= 0; i < field_count; i++)
+ {
+ field= mysql_fetch_field(result);
+ if (!opt_silent)
+ {
+ if (is_null[i])
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (length[i] == 0)
+ {
+ data[i][0]= '\0'; /* unmodified buffer */
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ }
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
+ }
+ }
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('\n', stdout);
+ }
+ row_count++;
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+ if (!opt_silent)
+ {
+ if (row_count)
+ my_print_dashes(result);
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ }
+ mysql_free_result(result);
+ return row_count;
+}
+
+
+/* Prepare statement, execute, and process result set for given query */
+
+int my_stmt_result(const char *buff)
+{
+ MYSQL_STMT *stmt;
+ int row_count;
+ int rc;
+
+ if (!opt_silent)
+ fprintf(stdout, "\n\n %s", buff);
+ stmt= mysql_simple_prepare(mysql, buff);
+ check_stmt(stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ row_count= my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+
+ return row_count;
+}
+
+
+/* Utility function to verify a particular column data */
+
+static void verify_col_data(const char *table, const char *col,
+const char *exp_data)
+{
+ static char query[MAX_TEST_QUERY_LENGTH];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc, field= 1;
+
+ if (table && col)
+ {
+ strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS);
+ if (!opt_silent)
+ fprintf(stdout, "\n %s", query);
+ rc= mysql_query(mysql, query);
+ myquery(rc);
+
+ field= 0;
+ }
+
+ result= mysql_use_result(mysql);
+ mytest(result);
+
+ if (!(row= mysql_fetch_row(result)) || !row[field])
+ {
+ fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ if (strcmp(row[field], exp_data))
+ {
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)",
+ row[field], exp_data);
+ DIE_UNLESS(FALSE);
+ }
+ mysql_free_result(result);
+}
+
+
+/* Utility function to verify the field members */
+
+#define verify_prepare_field(result,no,name,org_name,type,table, \
+org_table,db,length,def) \
+do_verify_prepare_field((result),(no),(name),(org_name),(type), \
+(table),(org_table),(db),(length),(def), \
+__FILE__, __LINE__)
+
+static void do_verify_prepare_field(MYSQL_RES *result,
+unsigned int no, const char *name,
+const char *org_name,
+enum enum_field_types type,
+const char *table,
+const char *org_table, const char *db,
+unsigned long length, const char *def,
+const char *file, int line)
+{
+ MYSQL_FIELD *field;
+ CHARSET_INFO *cs;
+ ulonglong expected_field_length;
+
+ if (!(field= mysql_fetch_field_direct(result, no)))
+ {
+ fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ cs= get_charset(field->charsetnr, 0);
+ DIE_UNLESS(cs);
+ if ((expected_field_length= length * cs->mbmaxlen) > UINT_MAX32)
+ expected_field_length= UINT_MAX32;
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n field[%d]:", no);
+ fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name);
+ fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)",
+ field->org_name, org_name);
+ fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type);
+ if (table)
+ fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
+ field->table, table);
+ if (org_table)
+ fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)",
+ field->org_table, org_table);
+ fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db);
+ fprintf(stdout, "\n length :`%lu`\t(expected: `%llu`)",
+ field->length, expected_field_length);
+ fprintf(stdout, "\n maxlength:`%ld`", field->max_length);
+ fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr);
+ fprintf(stdout, "\n default :`%s`\t(expected: `%s`)",
+ field->def ? field->def : "(null)", def ? def: "(null)");
+ fprintf(stdout, "\n");
+ }
+ DIE_UNLESS(strcmp(field->name, name) == 0);
+ DIE_UNLESS(strcmp(field->org_name, org_name) == 0);
+ /*
+ XXX: silent column specification change works based on number of
+ bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
+ for CHAR(2) column if its character set is multibyte.
+ VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
+ expect.
+ */
+ if (cs->mbmaxlen == 1)
+ {
+ if (field->type != type)
+ {
+ fprintf(stderr,
+ "Expected field type: %d, got type: %d in file %s, line %d\n",
+ (int) type, (int) field->type, file, line);
+ DIE_UNLESS(field->type == type);
+ }
+ }
+ if (table)
+ DIE_UNLESS(strcmp(field->table, table) == 0);
+ if (org_table)
+ DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
+ DIE_UNLESS(strcmp(field->db, db) == 0);
+ /*
+ Character set should be taken into account for multibyte encodings, such
+ as utf8. Field length is calculated as number of characters * maximum
+ number of bytes a character can occupy.
+ */
+ if (length && (field->length != expected_field_length))
+ {
+ fflush(stdout);
+ fprintf(stderr, "Expected field length: %llu, got length: %lu\n",
+ expected_field_length, field->length);
+ fflush(stderr);
+ DIE_UNLESS(field->length == expected_field_length);
+ }
+ if (def)
+ DIE_UNLESS(strcmp(field->def, def) == 0);
+}
+
+
+/* Utility function to verify the parameter count */
+
+static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
+{
+ long param_count= mysql_stmt_param_count(stmt);
+ if (!opt_silent)
+ fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)",
+ param_count, exp_count);
+ DIE_UNLESS(param_count == exp_count);
+}
+
+
+/* Utility function to verify the total affected rows */
+
+static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
+{
+ ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
+ DIE_UNLESS(affected_rows == exp_count);
+}
+
+
+/* Utility function to verify the total affected rows */
+
+static void verify_affected_rows(ulonglong exp_count)
+{
+ ulonglong affected_rows= mysql_affected_rows(mysql);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
+ DIE_UNLESS(affected_rows == exp_count);
+}
+
+
+/* Utility function to verify the total fields count */
+
+static void verify_field_count(MYSQL_RES *result, uint exp_count)
+{
+ uint field_count= mysql_num_fields(result);
+ if (!opt_silent)
+ fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)",
+ field_count, exp_count);
+ DIE_UNLESS(field_count == exp_count);
+}
+
+
+/* Utility function to execute a query using prepare-execute */
+
+#ifndef EMBEDDED_LIBRARY
+static void execute_prepare_query(const char *query, ulonglong exp_count)
+{
+ MYSQL_STMT *stmt;
+ ulonglong affected_rows;
+ int rc;
+
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ myquery(rc);
+
+ affected_rows= mysql_stmt_affected_rows(stmt);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
+
+ DIE_UNLESS(affected_rows == exp_count);
+ mysql_stmt_close(stmt);
+}
+#endif
+
+/*
+Accepts arbitrary number of queries and runs them against the database.
+Used to fill tables for each test.
+*/
+
+void fill_tables(const char **query_list, unsigned query_count)
+{
+ int rc;
+ const char **query;
+ DBUG_ENTER("fill_tables");
+ for (query= query_list; query < query_list + query_count;
+ ++query)
+ {
+ rc= mysql_query(mysql, *query);
+ myquery(rc);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+All state of fetch from one statement: statement handle, out buffers,
+fetch position.
+See fetch_n for for the only use case.
+*/
+
+enum { MAX_COLUMN_LENGTH= 255 };
+
+typedef struct st_stmt_fetch
+{
+const char *query;
+unsigned stmt_no;
+MYSQL_STMT *handle;
+my_bool is_open;
+MYSQL_BIND *bind_array;
+char **out_data;
+unsigned long *out_data_length;
+unsigned column_count;
+unsigned row_count;
+} Stmt_fetch;
+
+
+/*
+Create statement handle, prepare it with statement, execute and allocate
+fetch buffers.
+*/
+
+void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg,
+const char *query_arg)
+{
+ unsigned long type= CURSOR_TYPE_READ_ONLY;
+ int rc;
+ unsigned i;
+ MYSQL_RES *metadata;
+ DBUG_ENTER("stmt_fetch_init");
+
+ /* Save query and statement number for error messages */
+ fetch->stmt_no= stmt_no_arg;
+ fetch->query= query_arg;
+
+ fetch->handle= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(fetch->handle, fetch->query, strlen(fetch->query));
+ check_execute(fetch->handle, rc);
+
+ /*
+ The attribute is sent to server on execute and asks to open read-only
+ for result set
+ */
+ mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE,
+ (const void*) &type);
+
+ rc= mysql_stmt_execute(fetch->handle);
+ check_execute(fetch->handle, rc);
+
+ /* Find out total number of columns in result set */
+ metadata= mysql_stmt_result_metadata(fetch->handle);
+ fetch->column_count= mysql_num_fields(metadata);
+ mysql_free_result(metadata);
+
+ /*
+ Now allocate bind handles and buffers for output data:
+ calloc memory to reduce number of MYSQL_BIND members we need to
+ set up.
+ */
+
+ fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) *
+ fetch->column_count);
+ fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count);
+ fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) *
+ fetch->column_count);
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH);
+ fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING;
+ fetch->bind_array[i].buffer= fetch->out_data[i];
+ fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH;
+ fetch->bind_array[i].length= fetch->out_data_length + i;
+ }
+
+ mysql_stmt_bind_result(fetch->handle, fetch->bind_array);
+
+ fetch->row_count= 0;
+ fetch->is_open= TRUE;
+
+ /* Ready for reading rows */
+ DBUG_VOID_RETURN;
+}
+
+
+/* Fetch and print one row from cursor */
+
+int stmt_fetch_fetch_row(Stmt_fetch *fetch)
+{
+ int rc;
+ unsigned i;
+ DBUG_ENTER("stmt_fetch_fetch_row");
+
+ if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
+ {
+ ++fetch->row_count;
+ if (!opt_silent)
+ printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count);
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i][fetch->out_data_length[i]]= '\0';
+ if (!opt_silent)
+ printf("column %d: %s\n", i+1, fetch->out_data[i]);
+ }
+ }
+ else
+ fetch->is_open= FALSE;
+ DBUG_RETURN(rc);
+}
+
+
+void stmt_fetch_close(Stmt_fetch *fetch)
+{
+ unsigned i;
+ DBUG_ENTER("stmt_fetch_close");
+
+ for (i= 0; i < fetch->column_count; ++i)
+ free(fetch->out_data[i]);
+ free(fetch->out_data);
+ free(fetch->out_data_length);
+ free(fetch->bind_array);
+ mysql_stmt_close(fetch->handle);
+ DBUG_VOID_RETURN;
+}
+
+/*
+For given array of queries, open query_count cursors and fetch
+from them in simultaneous manner.
+In case there was an error in one of the cursors, continue
+reading from the rest.
+*/
+
+enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
+
+my_bool fetch_n(const char **query_list, unsigned query_count,
+enum fetch_type fetch_type)
+{
+ unsigned open_statements= query_count;
+ int rc, error_count= 0;
+ Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
+ query_count);
+ Stmt_fetch *fetch;
+ DBUG_ENTER("fetch_n");
+
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ /* Init will exit(1) in case of error */
+ stmt_fetch_init(fetch, fetch - fetch_array,
+ query_list[fetch - fetch_array]);
+ }
+
+ if (fetch_type == USE_STORE_RESULT)
+ {
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ rc= mysql_stmt_store_result(fetch->handle);
+ check_execute(fetch->handle, rc);
+ }
+ }
+
+ while (open_statements)
+ {
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
+ {
+ open_statements--;
+ /*
+ We try to fetch from the rest of the statements in case of
+ error
+ */
+ if (rc != MYSQL_NO_DATA)
+ {
+ fprintf(stderr,
+ "Got error reading rows from statement %d,\n"
+ "query is: %s,\n"
+ "error message: %s", (int) (fetch - fetch_array),
+ fetch->query,
+ mysql_stmt_error(fetch->handle));
+ error_count++;
+ }
+ }
+ }
+ }
+ if (error_count)
+ fprintf(stderr, "Fetch FAILED");
+ else
+ {
+ unsigned total_row_count= 0;
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ total_row_count+= fetch->row_count;
+ if (!opt_silent)
+ printf("Success, total rows fetched: %d\n", total_row_count);
+ }
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ stmt_fetch_close(fetch);
+ free(fetch_array);
+ DBUG_RETURN(error_count != 0);
+}
+
+/* Separate thread query to test some cases */
+
+static my_bool thread_query(const char *query)
+{
+ MYSQL *l_mysql;
+ my_bool error;
+
+ error= 0;
+ if (!opt_silent)
+ fprintf(stdout, "\n in thread_query(%s)", query);
+ if (!(l_mysql= mysql_client_init(NULL)))
+ {
+ myerror("mysql_client_init() failed");
+ return 1;
+ }
+ if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ error= 1;
+ goto end;
+ }
+ l_mysql->reconnect= 1;
+ if (mysql_query(l_mysql, query))
+ {
+ fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql));
+ error= 1;
+ goto end;
+ }
+ mysql_commit(l_mysql);
+ end:
+ mysql_close(l_mysql);
+ return error;
+}
+
+
+/*
+Read and parse arguments and MySQL options from my.cnf
+*/
+
+static const char *client_test_load_default_groups[]= { "client", 0 };
+static char **defaults_argv;
+
+static struct my_option client_test_long_options[] =
+{
+{"basedir", 'b', "Basedir for tests.", &opt_basedir,
+ &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"count", 't', "Number of times test to be executed", &opt_count,
+ &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
+{"database", 'D', "Database to use", &opt_db, &opt_db,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"debug", '#', "Output debug log", &default_dbug_option,
+ &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
+{"host", 'h', "Connect to host", &opt_host, &opt_host,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"password", 'p',
+ "Password to use when connecting to server. If password is not given it's asked from the tty.",
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+{"port", 'P', "Port number to use for connection or 0 for default to, in "
+ "order of preference, my.cnf, $MYSQL_TCP_PORT, "
+ #if MYSQL_PORT_DEFAULT == 0
+ "/etc/services, "
+ #endif
+ "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
+ &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"server-arg", 'A', "Send embedded server this as a parameter.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+{"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0,
+ 0},
+#ifdef HAVE_SMEM
+{"shared-memory-base-name", 'm', "Base name of shared memory.",
+ &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+{"socket", 'S', "Socket file to use for connection",
+ &opt_unix_socket, &opt_unix_socket, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"testcase", 'c',
+ "May disable some code when runs as mysql-test-run testcase.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifndef DONT_ALLOW_USER_CHANGE
+{"user", 'u', "User for login if not current user", &opt_user,
+ &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+{"vardir", 'v', "Data dir for tests.", &opt_vardir,
+ &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+{"getopt-ll-test", 'g', "Option for testing bug in getopt library",
+ &opt_getopt_ll_test, &opt_getopt_ll_test, 0,
+ GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0},
+{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+static void usage(void)
+{
+/* show the usage string when the user asks for this */
+ putc('\n', stdout);
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",
+ my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+ puts("By Monty, Venu, Kent and others\n");
+ printf("\
+Copyright (C) 2002-2004 MySQL AB\n\
+This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
+and you are welcome to modify and redistribute it under the GPL license\n");
+ printf("Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]\n", my_progname);
+ my_print_help(client_test_long_options);
+ print_defaults("my", client_test_load_default_groups);
+ my_print_variables(client_test_long_options);
+}
+
+
+static struct my_tests_st *get_my_tests(); /* To be defined in main .c file */
+
+static struct my_tests_st *my_testlist= 0;
+
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ break;
+ case 'c':
+ opt_testcase = 1;
+ break;
+ case 'p':
+ if (argument)
+ {
+ char *start=argument;
+ my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ opt_password= my_strdup(argument, MYF(MY_FAE));
+ while (*argument) *argument++= 'x'; /* Destroy argument */
+ if (*start)
+ start[1]=0;
+ }
+ else
+ tty_password= 1;
+ break;
+ case 's':
+ if (argument == disabled_my_option)
+ opt_silent= 0;
+ else
+ opt_silent++;
+ break;
+ case 'A':
+ /*
+ When the embedded server is being tested, the test suite needs to be
+ able to pass command-line arguments to the embedded server so it can
+ locate the language files and data directory. The test suite
+ (mysql-test-run) never uses config files, just command-line options.
+ */
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count= 1;
+ embedded_server_args[0]= (char*) "";
+ }
+ if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
+ !(embedded_server_args[embedded_server_arg_count++]=
+ my_strdup(argument, MYF(MY_FAE))))
+ {
+ DIE("Can't use server argument");
+ }
+ break;
+ case 'T':
+ {
+ struct my_tests_st *fptr;
+
+ printf("All possible test names:\n\n");
+ for (fptr= my_testlist; fptr->name; fptr++)
+ printf("%s\n", fptr->name);
+ exit(0);
+ break;
+ }
+ case '?':
+ case 'I': /* Info */
+ usage();
+ exit(0);
+ break;
+ }
+ return 0;
+}
+
+static void get_options(int *argc, char ***argv)
+{
+ int ho_error;
+
+ if ((ho_error= handle_options(argc, argv, client_test_long_options,
+ get_one_option)))
+ exit(ho_error);
+
+ if (tty_password)
+ opt_password= get_tty_password(NullS);
+ return;
+}
+
+/*
+Print the test output on successful execution before exiting
+*/
+
+static void print_test_output()
+{
+ if (opt_silent < 3)
+ {
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)",
+ test_count-1, opt_count);
+ fprintf(stdout, "\n Total execution time: %g SECS", total_time);
+ if (opt_count > 1)
+ fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count);
+
+ fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
+ }
+}
+
+/***************************************************************************
+main routine
+***************************************************************************/
+
+
+int main(int argc, char **argv)
+{
+ struct my_tests_st *fptr;
+ my_testlist= get_my_tests();
+
+ MY_INIT(argv[0]);
+
+ load_defaults("my", client_test_load_default_groups, &argc, &argv);
+ defaults_argv= argv;
+ get_options(&argc, &argv);
+
+ if (mysql_server_init(embedded_server_arg_count,
+ embedded_server_args,
+ (char**) embedded_server_groups))
+ DIE("Can't initialize MySQL server");
+
+ /* connect to server with no flags, default protocol, auto reconnect true */
+ mysql= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1);
+
+ total_time= 0;
+ for (iter_count= 1; iter_count <= opt_count; iter_count++)
+ {
+ /* Start of tests */
+ test_count= 1;
+ start_time= time((time_t *)0);
+ if (!argc)
+ {
+ for (fptr= my_testlist; fptr->name; fptr++)
+ (*fptr->function)();
+ }
+ else
+ {
+ for ( ; *argv ; argv++)
+ {
+ for (fptr= my_testlist; fptr->name; fptr++)
+ {
+ if (!strcmp(fptr->name, *argv))
+ {
+ (*fptr->function)();
+ break;
+ }
+ }
+ if (!fptr->name)
+ {
+ fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
+ fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
+ my_progname);
+ client_disconnect(mysql, 1);
+ free_defaults(defaults_argv);
+ exit(1);
+ }
+ }
+ }
+
+ end_time= time((time_t *)0);
+ total_time+= difftime(end_time, start_time);
+
+ /* End of tests */
+ }
+
+ client_disconnect(mysql, 1); /* disconnect from server */
+
+ free_defaults(defaults_argv);
+ print_test_output();
+
+ while (embedded_server_arg_count > 1)
+ my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
+
+ mysql_server_end();
+
+ my_end(0);
+
+ exit(0);
+}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index a67b5a80cfb..5f9d7bc76c8 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2002, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+/* Copyright (c) 2002, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,381 +26,12 @@
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
*/
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <mysql.h>
-#include <errmsg.h>
-#include <my_getopt.h>
-#include <m_string.h>
-#include <mysqld_error.h>
-#include <my_handler.h>
-
-#define VER "2.1"
-#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
-#define MAX_KEY MAX_INDEXES
-#define MAX_SERVER_ARGS 64
-
-/* set default options */
-#ifdef NOT_USED
-static int opt_testcase = 0;
-#endif
-static char *opt_db= 0;
-static char *opt_user= 0;
-static char *opt_password= 0;
-static char *opt_host= 0;
-static char *opt_unix_socket= 0;
-#ifdef HAVE_SMEM
-static char *shared_memory_base_name= 0;
-#endif
-static unsigned int opt_port;
-static my_bool tty_password= 0, opt_silent= 0;
-
-static MYSQL *mysql= 0;
-static char current_db[]= "client_test_db";
-static unsigned int test_count= 0;
-static unsigned int opt_count= 0;
-static unsigned int iter_count= 0;
-static my_bool have_innodb= FALSE;
-
-static const char *opt_basedir= "./";
-static const char *opt_vardir= "mysql-test/var";
-
-static longlong opt_getopt_ll_test= 0;
-
-static int embedded_server_arg_count= 0;
-static char *embedded_server_args[MAX_SERVER_ARGS];
-
-static const char *embedded_server_groups[]= {
- "server",
- "embedded",
- "mysql_client_test_SERVER",
- NullS
-};
-
-static time_t start_time, end_time;
-static double total_time;
-
-const char *default_dbug_option= "d:t:o,/tmp/mysql_client_test.trace";
-
-struct my_tests_st
-{
- const char *name;
- void (*function)();
-};
-
-#define myheader(str) \
-DBUG_PRINT("test", ("name: %s", str)); \
-if (opt_silent < 2) \
-{ \
- fprintf(stdout, "\n\n#####################################\n"); \
- fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \
- opt_count, str); \
- fprintf(stdout, " \n#####################################\n"); \
-}
-
-#define myheader_r(str) \
-DBUG_PRINT("test", ("name: %s", str)); \
-if (!opt_silent) \
-{ \
- fprintf(stdout, "\n\n#####################################\n"); \
- fprintf(stdout, "%s", str); \
- fprintf(stdout, " \n#####################################\n"); \
-}
-
-static void print_error(const char *msg);
-static void print_st_error(MYSQL_STMT *stmt, const char *msg);
-static void client_disconnect(MYSQL* mysql, my_bool drop_db);
-
-
/*
- Abort unless given experssion is non-zero.
-
- SYNOPSIS
- DIE_UNLESS(expr)
-
- DESCRIPTION
- We can't use any kind of system assert as we need to
- preserve tested invariants in release builds as well.
+ The fw.c file includes all the mysql_client_test framework; this file
+ contains only the actual tests, plus the list of test functions to call.
*/
-#define DIE_UNLESS(expr) \
- ((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
-#define DIE_IF(expr) \
- ((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
-#define DIE(expr) \
- die(__FILE__, __LINE__, #expr)
-
-static void die(const char *file, int line, const char *expr)
-{
- fflush(stdout);
- fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr);
- fflush(stderr);
- exit(1);
-}
-
-
-#define myerror(msg) print_error(msg)
-#define mysterror(stmt, msg) print_st_error(stmt, msg)
-
-#define myquery(RES) \
-{ \
- int r= (RES); \
- if (r) \
- myerror(NULL); \
- DIE_UNLESS(r == 0); \
-}
-
-#define myquery_r(r) \
-{ \
-if (r) \
- myerror(NULL); \
-DIE_UNLESS(r != 0); \
-}
-
-#define check_execute(stmt, r) \
-{ \
-if (r) \
- mysterror(stmt, NULL); \
-DIE_UNLESS(r == 0);\
-}
-
-#define check_execute_r(stmt, r) \
-{ \
-if (r) \
- mysterror(stmt, NULL); \
-DIE_UNLESS(r != 0);\
-}
-
-#define check_stmt(stmt) \
-{ \
-if ( stmt == 0) \
- myerror(NULL); \
-DIE_UNLESS(stmt != 0); \
-}
-
-#define check_stmt_r(stmt) \
-{ \
-if (stmt == 0) \
- myerror(NULL);\
-DIE_UNLESS(stmt == 0);\
-}
-
-#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);}
-#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);}
-
-
-/* A workaround for Sun Forte 5.6 on Solaris x86 */
-
-static int cmp_double(double *a, double *b)
-{
- return *a == *b;
-}
-
-
-/* Print the error message */
-
-static void print_error(const char *msg)
-{
- if (!opt_silent)
- {
- if (mysql && mysql_errno(mysql))
- {
- if (mysql->server_version)
- fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
- else
- fprintf(stdout, "\n [MySQL]");
- fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
- }
- else if (msg)
- fprintf(stderr, " [MySQL] %s\n", msg);
- }
-}
-
-
-static void print_st_error(MYSQL_STMT *stmt, const char *msg)
-{
- if (!opt_silent)
- {
- if (stmt && mysql_stmt_errno(stmt))
- {
- if (stmt->mysql && stmt->mysql->server_version)
- fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version);
- else
- fprintf(stdout, "\n [MySQL]");
-
- fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt),
- mysql_stmt_error(stmt));
- }
- else if (msg)
- fprintf(stderr, " [MySQL] %s\n", msg);
- }
-}
-
-/*
- Enhanced version of mysql_client_init(), which may also set shared memory
- base on Windows.
-*/
-static MYSQL *mysql_client_init(MYSQL* con)
-{
- MYSQL* res = mysql_init(con);
-#ifdef HAVE_SMEM
- if (res && shared_memory_base_name)
- mysql_options(res, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name);
-#endif
- return res;
-}
-
-/*
- Disable direct calls of mysql_init, as it disregards shared memory base.
-*/
-#define mysql_init(A) Please use mysql_client_init instead of mysql_init
-
-
-/* Check if the connection has InnoDB tables */
-
-static my_bool check_have_innodb(MYSQL *conn)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- int rc;
- my_bool result;
-
- rc= mysql_query(conn, "show variables like 'have_innodb'");
- myquery(rc);
- res= mysql_use_result(conn);
- DIE_UNLESS(res);
-
- row= mysql_fetch_row(res);
- DIE_UNLESS(row);
-
- result= strcmp(row[1], "YES") == 0;
- mysql_free_result(res);
- return result;
-}
-
-
-/*
- This is to be what mysql_query() is for mysql_real_query(), for
- mysql_simple_prepare(): a variant without the 'length' parameter.
-*/
-
-static MYSQL_STMT *STDCALL
-mysql_simple_prepare(MYSQL *mysql_arg, const char *query)
-{
- MYSQL_STMT *stmt= mysql_stmt_init(mysql_arg);
- if (stmt && mysql_stmt_prepare(stmt, query, (uint) strlen(query)))
- {
- mysql_stmt_close(stmt);
- return 0;
- }
- return stmt;
-}
-
-
-/**
- Connect to the server with options given by arguments to this application,
- stored in global variables opt_host, opt_user, opt_password, opt_db,
- opt_port and opt_unix_socket.
-
- @param flag[in] client_flag passed on to mysql_real_connect
- @param protocol[in] MYSQL_PROTOCOL_* to use for this connection
- @param auto_reconnect[in] set to 1 for auto reconnect
-
- @return pointer to initialized and connected MYSQL object
-*/
-static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect)
-{
- MYSQL* mysql;
- int rc;
- static char query[MAX_TEST_QUERY_LENGTH];
- myheader_r("client_connect");
-
- if (!opt_silent)
- fprintf(stdout, "\n Establishing a connection to '%s' ...",
- opt_host ? opt_host : "");
-
- if (!(mysql= mysql_client_init(NULL)))
- {
- opt_silent= 0;
- myerror("mysql_client_init() failed");
- exit(1);
- }
- /* enable local infile, in non-binary builds often disabled by default */
- mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(mysql, MYSQL_OPT_PROTOCOL, &protocol);
-
- if (!(mysql_real_connect(mysql, opt_host, opt_user,
- opt_password, opt_db ? opt_db:"test", opt_port,
- opt_unix_socket, flag)))
- {
- opt_silent= 0;
- myerror("connection failed");
- mysql_close(mysql);
- fprintf(stdout, "\n Check the connection options using --help or -?\n");
- exit(1);
- }
- mysql->reconnect= auto_reconnect;
-
- if (!opt_silent)
- fprintf(stdout, "OK");
-
- /* set AUTOCOMMIT to ON*/
- mysql_autocommit(mysql, TRUE);
-
- if (!opt_silent)
- {
- fprintf(stdout, "\nConnected to MySQL server version: %s (%lu)\n",
- mysql_get_server_info(mysql),
- (ulong) mysql_get_server_version(mysql));
- fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
- }
- strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
-
- rc= mysql_query(mysql, query);
- myquery(rc);
-
- strxmov(query, "USE ", current_db, NullS);
- rc= mysql_query(mysql, query);
- myquery(rc);
- have_innodb= check_have_innodb(mysql);
-
- if (!opt_silent)
- fprintf(stdout, "OK");
-
- return mysql;
-}
-
-
-/* Close the connection */
-
-static void client_disconnect(MYSQL* mysql, my_bool drop_db)
-{
- static char query[MAX_TEST_QUERY_LENGTH];
-
- myheader_r("client_disconnect");
-
- if (mysql)
- {
- if (drop_db)
- {
- if (!opt_silent)
- fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
- strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
-
- mysql_query(mysql, query);
- if (!opt_silent)
- fprintf(stdout, "OK");
- }
-
- if (!opt_silent)
- fprintf(stdout, "\n closing the connection ...");
- mysql_close(mysql);
- if (!opt_silent)
- fprintf(stdout, "OK\n");
- }
-}
-
+#include "mysql_client_fw.c"
/* Query processing */
@@ -447,473 +78,6 @@ static void client_query()
}
-/* Print dashes */
-
-static void my_print_dashes(MYSQL_RES *result)
-{
- MYSQL_FIELD *field;
- unsigned int i, j;
-
- mysql_field_seek(result, 0);
- fputc('\t', stdout);
- fputc('+', stdout);
-
- for(i= 0; i< mysql_num_fields(result); i++)
- {
- field= mysql_fetch_field(result);
- for(j= 0; j < field->max_length+2; j++)
- fputc('-', stdout);
- fputc('+', stdout);
- }
- fputc('\n', stdout);
-}
-
-
-/* Print resultset metadata information */
-
-static void my_print_result_metadata(MYSQL_RES *result)
-{
- MYSQL_FIELD *field;
- unsigned int i, j;
- unsigned int field_count;
-
- mysql_field_seek(result, 0);
- if (!opt_silent)
- {
- fputc('\n', stdout);
- fputc('\n', stdout);
- }
-
- field_count= mysql_num_fields(result);
- for(i= 0; i< field_count; i++)
- {
- field= mysql_fetch_field(result);
- j= strlen(field->name);
- if (j < field->max_length)
- j= field->max_length;
- if (j < 4 && !IS_NOT_NULL(field->flags))
- j= 4;
- field->max_length= j;
- }
- if (!opt_silent)
- {
- my_print_dashes(result);
- fputc('\t', stdout);
- fputc('|', stdout);
- }
-
- mysql_field_seek(result, 0);
- for(i= 0; i< field_count; i++)
- {
- field= mysql_fetch_field(result);
- if (!opt_silent)
- fprintf(stdout, " %-*s |", (int) field->max_length, field->name);
- }
- if (!opt_silent)
- {
- fputc('\n', stdout);
- my_print_dashes(result);
- }
-}
-
-
-/* Process the result set */
-
-static int my_process_result_set(MYSQL_RES *result)
-{
- MYSQL_ROW row;
- MYSQL_FIELD *field;
- unsigned int i;
- unsigned int row_count= 0;
-
- if (!result)
- return 0;
-
- my_print_result_metadata(result);
-
- while ((row= mysql_fetch_row(result)) != NULL)
- {
- mysql_field_seek(result, 0);
- if (!opt_silent)
- {
- fputc('\t', stdout);
- fputc('|', stdout);
- }
-
- for(i= 0; i< mysql_num_fields(result); i++)
- {
- field= mysql_fetch_field(result);
- if (!opt_silent)
- {
- if (row[i] == NULL)
- fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
- else if (IS_NUM(field->type))
- fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
- else
- fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
- }
- }
- if (!opt_silent)
- {
- fputc('\t', stdout);
- fputc('\n', stdout);
- }
- row_count++;
- }
- if (!opt_silent)
- {
- if (row_count)
- my_print_dashes(result);
-
- if (mysql_errno(mysql) != 0)
- fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
- else
- fprintf(stdout, "\n\t%d %s returned\n", row_count,
- row_count == 1 ? "row" : "rows");
- }
- return row_count;
-}
-
-
-static int my_process_result(MYSQL *mysql_arg)
-{
- MYSQL_RES *result;
- int row_count;
-
- if (!(result= mysql_store_result(mysql_arg)))
- return 0;
-
- row_count= my_process_result_set(result);
-
- mysql_free_result(result);
- return row_count;
-}
-
-
-/* Process the statement result set */
-
-#define MAX_RES_FIELDS 50
-#define MAX_FIELD_DATA_SIZE 255
-
-static int my_process_stmt_result(MYSQL_STMT *stmt)
-{
- int field_count;
- int row_count= 0;
- MYSQL_BIND buffer[MAX_RES_FIELDS];
- MYSQL_FIELD *field;
- MYSQL_RES *result;
- char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE];
- ulong length[MAX_RES_FIELDS];
- my_bool is_null[MAX_RES_FIELDS];
- int rc, i;
-
- if (!(result= mysql_stmt_result_metadata(stmt))) /* No meta info */
- {
- while (!mysql_stmt_fetch(stmt))
- row_count++;
- return row_count;
- }
-
- field_count= min(mysql_num_fields(result), MAX_RES_FIELDS);
-
- bzero((char*) buffer, sizeof(buffer));
- bzero((char*) length, sizeof(length));
- bzero((char*) is_null, sizeof(is_null));
-
- for(i= 0; i < field_count; i++)
- {
- buffer[i].buffer_type= MYSQL_TYPE_STRING;
- buffer[i].buffer_length= MAX_FIELD_DATA_SIZE;
- buffer[i].length= &length[i];
- buffer[i].buffer= (void *) data[i];
- buffer[i].is_null= &is_null[i];
- }
-
- rc= mysql_stmt_bind_result(stmt, buffer);
- check_execute(stmt, rc);
-
- rc= 1;
- mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc);
- rc= mysql_stmt_store_result(stmt);
- check_execute(stmt, rc);
- my_print_result_metadata(result);
-
- mysql_field_seek(result, 0);
- while ((rc= mysql_stmt_fetch(stmt)) == 0)
- {
- if (!opt_silent)
- {
- fputc('\t', stdout);
- fputc('|', stdout);
- }
- mysql_field_seek(result, 0);
- for (i= 0; i < field_count; i++)
- {
- field= mysql_fetch_field(result);
- if (!opt_silent)
- {
- if (is_null[i])
- fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
- else if (length[i] == 0)
- {
- data[i][0]= '\0'; /* unmodified buffer */
- fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
- }
- else if (IS_NUM(field->type))
- fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
- else
- fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
- }
- }
- if (!opt_silent)
- {
- fputc('\t', stdout);
- fputc('\n', stdout);
- }
- row_count++;
- }
- DIE_UNLESS(rc == MYSQL_NO_DATA);
- if (!opt_silent)
- {
- if (row_count)
- my_print_dashes(result);
- fprintf(stdout, "\n\t%d %s returned\n", row_count,
- row_count == 1 ? "row" : "rows");
- }
- mysql_free_result(result);
- return row_count;
-}
-
-
-/* Prepare statement, execute, and process result set for given query */
-
-int my_stmt_result(const char *buff)
-{
- MYSQL_STMT *stmt;
- int row_count;
- int rc;
-
- if (!opt_silent)
- fprintf(stdout, "\n\n %s", buff);
- stmt= mysql_simple_prepare(mysql, buff);
- check_stmt(stmt);
-
- rc= mysql_stmt_execute(stmt);
- check_execute(stmt, rc);
-
- row_count= my_process_stmt_result(stmt);
- mysql_stmt_close(stmt);
-
- return row_count;
-}
-
-
-/* Utility function to verify a particular column data */
-
-static void verify_col_data(const char *table, const char *col,
- const char *exp_data)
-{
- static char query[MAX_TEST_QUERY_LENGTH];
- MYSQL_RES *result;
- MYSQL_ROW row;
- int rc, field= 1;
-
- if (table && col)
- {
- strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS);
- if (!opt_silent)
- fprintf(stdout, "\n %s", query);
- rc= mysql_query(mysql, query);
- myquery(rc);
-
- field= 0;
- }
-
- result= mysql_use_result(mysql);
- mytest(result);
-
- if (!(row= mysql_fetch_row(result)) || !row[field])
- {
- fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
- exit(1);
- }
- if (strcmp(row[field], exp_data))
- {
- fprintf(stdout, "\n obtained: `%s` (expected: `%s`)",
- row[field], exp_data);
- DIE_UNLESS(FALSE);
- }
- mysql_free_result(result);
-}
-
-
-/* Utility function to verify the field members */
-
-#define verify_prepare_field(result,no,name,org_name,type,table,\
- org_table,db,length,def) \
- do_verify_prepare_field((result),(no),(name),(org_name),(type), \
- (table),(org_table),(db),(length),(def), \
- __FILE__, __LINE__)
-
-static void do_verify_prepare_field(MYSQL_RES *result,
- unsigned int no, const char *name,
- const char *org_name,
- enum enum_field_types type,
- const char *table,
- const char *org_table, const char *db,
- unsigned long length, const char *def,
- const char *file, int line)
-{
- MYSQL_FIELD *field;
- CHARSET_INFO *cs;
- ulonglong expected_field_length;
-
- if (!(field= mysql_fetch_field_direct(result, no)))
- {
- fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
- exit(1);
- }
- cs= get_charset(field->charsetnr, 0);
- DIE_UNLESS(cs);
- if ((expected_field_length= length * cs->mbmaxlen) > UINT_MAX32)
- expected_field_length= UINT_MAX32;
- if (!opt_silent)
- {
- fprintf(stdout, "\n field[%d]:", no);
- fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name);
- fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)",
- field->org_name, org_name);
- fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type);
- if (table)
- fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
- field->table, table);
- if (org_table)
- fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)",
- field->org_table, org_table);
- fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db);
- fprintf(stdout, "\n length :`%lu`\t(expected: `%llu`)",
- field->length, expected_field_length);
- fprintf(stdout, "\n maxlength:`%ld`", field->max_length);
- fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr);
- fprintf(stdout, "\n default :`%s`\t(expected: `%s`)",
- field->def ? field->def : "(null)", def ? def: "(null)");
- fprintf(stdout, "\n");
- }
- DIE_UNLESS(strcmp(field->name, name) == 0);
- DIE_UNLESS(strcmp(field->org_name, org_name) == 0);
- /*
- XXX: silent column specification change works based on number of
- bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
- for CHAR(2) column if its character set is multibyte.
- VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
- expect.
- */
- if (cs->mbmaxlen == 1)
- {
- if (field->type != type)
- {
- fprintf(stderr,
- "Expected field type: %d, got type: %d in file %s, line %d\n",
- (int) type, (int) field->type, file, line);
- DIE_UNLESS(field->type == type);
- }
- }
- if (table)
- DIE_UNLESS(strcmp(field->table, table) == 0);
- if (org_table)
- DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
- DIE_UNLESS(strcmp(field->db, db) == 0);
- /*
- Character set should be taken into account for multibyte encodings, such
- as utf8. Field length is calculated as number of characters * maximum
- number of bytes a character can occupy.
- */
- if (length && (field->length != expected_field_length))
- {
- fflush(stdout);
- fprintf(stderr, "Expected field length: %llu, got length: %lu\n",
- expected_field_length, field->length);
- fflush(stderr);
- DIE_UNLESS(field->length == expected_field_length);
- }
- if (def)
- DIE_UNLESS(strcmp(field->def, def) == 0);
-}
-
-
-/* Utility function to verify the parameter count */
-
-static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
-{
- long param_count= mysql_stmt_param_count(stmt);
- if (!opt_silent)
- fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)",
- param_count, exp_count);
- DIE_UNLESS(param_count == exp_count);
-}
-
-
-/* Utility function to verify the total affected rows */
-
-static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
-{
- ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
- if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
- (long) affected_rows, (long) exp_count);
- DIE_UNLESS(affected_rows == exp_count);
-}
-
-
-/* Utility function to verify the total affected rows */
-
-static void verify_affected_rows(ulonglong exp_count)
-{
- ulonglong affected_rows= mysql_affected_rows(mysql);
- if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
- (long) affected_rows, (long) exp_count);
- DIE_UNLESS(affected_rows == exp_count);
-}
-
-
-/* Utility function to verify the total fields count */
-
-static void verify_field_count(MYSQL_RES *result, uint exp_count)
-{
- uint field_count= mysql_num_fields(result);
- if (!opt_silent)
- fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)",
- field_count, exp_count);
- DIE_UNLESS(field_count == exp_count);
-}
-
-
-/* Utility function to execute a query using prepare-execute */
-
-#ifndef EMBEDDED_LIBRARY
-static void execute_prepare_query(const char *query, ulonglong exp_count)
-{
- MYSQL_STMT *stmt;
- ulonglong affected_rows;
- int rc;
-
- stmt= mysql_simple_prepare(mysql, query);
- check_stmt(stmt);
-
- rc= mysql_stmt_execute(stmt);
- myquery(rc);
-
- affected_rows= mysql_stmt_affected_rows(stmt);
- if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
- (long) affected_rows, (long) exp_count);
-
- DIE_UNLESS(affected_rows == exp_count);
- mysql_stmt_close(stmt);
-}
-#endif
-
/* Store result processing */
static void client_store_result()
@@ -955,267 +119,6 @@ static void client_use_result()
}
-/*
- Accepts arbitrary number of queries and runs them against the database.
- Used to fill tables for each test.
-*/
-
-void fill_tables(const char **query_list, unsigned query_count)
-{
- int rc;
- const char **query;
- DBUG_ENTER("fill_tables");
- for (query= query_list; query < query_list + query_count;
- ++query)
- {
- rc= mysql_query(mysql, *query);
- myquery(rc);
- }
- DBUG_VOID_RETURN;
-}
-
-/*
- All state of fetch from one statement: statement handle, out buffers,
- fetch position.
- See fetch_n for for the only use case.
-*/
-
-enum { MAX_COLUMN_LENGTH= 255 };
-
-typedef struct st_stmt_fetch
-{
- const char *query;
- unsigned stmt_no;
- MYSQL_STMT *handle;
- my_bool is_open;
- MYSQL_BIND *bind_array;
- char **out_data;
- unsigned long *out_data_length;
- unsigned column_count;
- unsigned row_count;
-} Stmt_fetch;
-
-
-/*
- Create statement handle, prepare it with statement, execute and allocate
- fetch buffers.
-*/
-
-void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg,
- const char *query_arg)
-{
- unsigned long type= CURSOR_TYPE_READ_ONLY;
- int rc;
- unsigned i;
- MYSQL_RES *metadata;
- DBUG_ENTER("stmt_fetch_init");
-
- /* Save query and statement number for error messages */
- fetch->stmt_no= stmt_no_arg;
- fetch->query= query_arg;
-
- fetch->handle= mysql_stmt_init(mysql);
-
- rc= mysql_stmt_prepare(fetch->handle, fetch->query, strlen(fetch->query));
- check_execute(fetch->handle, rc);
-
- /*
- The attribute is sent to server on execute and asks to open read-only
- for result set
- */
- mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE,
- (const void*) &type);
-
- rc= mysql_stmt_execute(fetch->handle);
- check_execute(fetch->handle, rc);
-
- /* Find out total number of columns in result set */
- metadata= mysql_stmt_result_metadata(fetch->handle);
- fetch->column_count= mysql_num_fields(metadata);
- mysql_free_result(metadata);
-
- /*
- Now allocate bind handles and buffers for output data:
- calloc memory to reduce number of MYSQL_BIND members we need to
- set up.
- */
-
- fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) *
- fetch->column_count);
- fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count);
- fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) *
- fetch->column_count);
- for (i= 0; i < fetch->column_count; ++i)
- {
- fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH);
- fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING;
- fetch->bind_array[i].buffer= fetch->out_data[i];
- fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH;
- fetch->bind_array[i].length= fetch->out_data_length + i;
- }
-
- mysql_stmt_bind_result(fetch->handle, fetch->bind_array);
-
- fetch->row_count= 0;
- fetch->is_open= TRUE;
-
- /* Ready for reading rows */
- DBUG_VOID_RETURN;
-}
-
-
-/* Fetch and print one row from cursor */
-
-int stmt_fetch_fetch_row(Stmt_fetch *fetch)
-{
- int rc;
- unsigned i;
- DBUG_ENTER("stmt_fetch_fetch_row");
-
- if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
- {
- ++fetch->row_count;
- if (!opt_silent)
- printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count);
- for (i= 0; i < fetch->column_count; ++i)
- {
- fetch->out_data[i][fetch->out_data_length[i]]= '\0';
- if (!opt_silent)
- printf("column %d: %s\n", i+1, fetch->out_data[i]);
- }
- }
- else
- fetch->is_open= FALSE;
- DBUG_RETURN(rc);
-}
-
-
-void stmt_fetch_close(Stmt_fetch *fetch)
-{
- unsigned i;
- DBUG_ENTER("stmt_fetch_close");
-
- for (i= 0; i < fetch->column_count; ++i)
- free(fetch->out_data[i]);
- free(fetch->out_data);
- free(fetch->out_data_length);
- free(fetch->bind_array);
- mysql_stmt_close(fetch->handle);
- DBUG_VOID_RETURN;
-}
-
-/*
- For given array of queries, open query_count cursors and fetch
- from them in simultaneous manner.
- In case there was an error in one of the cursors, continue
- reading from the rest.
-*/
-
-enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
-
-my_bool fetch_n(const char **query_list, unsigned query_count,
- enum fetch_type fetch_type)
-{
- unsigned open_statements= query_count;
- int rc, error_count= 0;
- Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
- query_count);
- Stmt_fetch *fetch;
- DBUG_ENTER("fetch_n");
-
- for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
- {
- /* Init will exit(1) in case of error */
- stmt_fetch_init(fetch, fetch - fetch_array,
- query_list[fetch - fetch_array]);
- }
-
- if (fetch_type == USE_STORE_RESULT)
- {
- for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
- {
- rc= mysql_stmt_store_result(fetch->handle);
- check_execute(fetch->handle, rc);
- }
- }
-
- while (open_statements)
- {
- for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
- {
- if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
- {
- open_statements--;
- /*
- We try to fetch from the rest of the statements in case of
- error
- */
- if (rc != MYSQL_NO_DATA)
- {
- fprintf(stderr,
- "Got error reading rows from statement %d,\n"
- "query is: %s,\n"
- "error message: %s", (int) (fetch - fetch_array),
- fetch->query,
- mysql_stmt_error(fetch->handle));
- error_count++;
- }
- }
- }
- }
- if (error_count)
- fprintf(stderr, "Fetch FAILED");
- else
- {
- unsigned total_row_count= 0;
- for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
- total_row_count+= fetch->row_count;
- if (!opt_silent)
- printf("Success, total rows fetched: %d\n", total_row_count);
- }
- for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
- stmt_fetch_close(fetch);
- free(fetch_array);
- DBUG_RETURN(error_count != 0);
-}
-
-/* Separate thread query to test some cases */
-
-static my_bool thread_query(const char *query)
-{
- MYSQL *l_mysql;
- my_bool error;
-
- error= 0;
- if (!opt_silent)
- fprintf(stdout, "\n in thread_query(%s)", query);
- if (!(l_mysql= mysql_client_init(NULL)))
- {
- myerror("mysql_client_init() failed");
- return 1;
- }
- if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, 0)))
- {
- myerror("connection failed");
- error= 1;
- goto end;
- }
- l_mysql->reconnect= 1;
- if (mysql_query(l_mysql, query))
- {
- fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql));
- error= 1;
- goto end;
- }
- mysql_commit(l_mysql);
-end:
- mysql_close(l_mysql);
- return error;
-}
-
-
/* Query processing */
static void test_debug_example()
@@ -18638,85 +17541,6 @@ static void test_bug13001491()
}
-/*
- Read and parse arguments and MySQL options from my.cnf
-*/
-
-static const char *client_test_load_default_groups[]= { "client", 0 };
-static char **defaults_argv;
-
-static struct my_option client_test_long_options[] =
-{
- {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
- (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"count", 't', "Number of times test to be executed", &opt_count,
- &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
- {"database", 'D', "Database to use", &opt_db, &opt_db,
- 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"debug", '#', "Output debug log", (char**) &default_dbug_option,
- (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
- 0, 0, 0, 0, 0},
- {"host", 'h', "Connect to host", &opt_host, &opt_host,
- 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"password", 'p',
- "Password to use when connecting to server. If password is not given it's asked from the tty.",
- 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"port", 'P', "Port number to use for connection or 0 for default to, in "
- "order of preference, my.cnf, $MYSQL_TCP_PORT, "
-#if MYSQL_PORT_DEFAULT == 0
- "/etc/services, "
-#endif
- "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
- &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"server-arg", 'A', "Send embedded server this as a parameter.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG,
- 0, 0, 0, 0, 0, 0},
- {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0,
- 0},
-#ifdef HAVE_SMEM
- {"shared-memory-base-name", 'm', "Base name of shared memory.",
- &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"socket", 'S', "Socket file to use for connection",
- &opt_unix_socket, &opt_unix_socket, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"testcase", 'c',
- "May disable some code when runs as mysql-test-run testcase.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifndef DONT_ALLOW_USER_CHANGE
- {"user", 'u', "User for login if not current user", &opt_user,
- &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"vardir", 'v', "Data dir for tests.", (char**) &opt_vardir,
- (char**) &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"getopt-ll-test", 'g', "Option for testing bug in getopt library",
- &opt_getopt_ll_test, &opt_getopt_ll_test, 0,
- GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-
-static void usage(void)
-{
- /* show the usage string when the user asks for this */
- putc('\n', stdout);
- printf("%s Ver %s Distrib %s, for %s (%s)\n",
- my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
- puts("By Monty, Venu, Kent and others\n");
- printf("\
-Copyright (C) 2002-2004 MySQL AB\n\
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL license\n");
- printf("Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]\n", my_progname);
- my_print_help(client_test_long_options);
- print_defaults("my", client_test_load_default_groups);
- my_print_variables(client_test_long_options);
-}
-
-
static struct my_tests_st my_tests[]= {
{ "disable_query_logs", disable_query_logs },
{ "test_view_sp_list_fields", test_view_sp_list_fields },
@@ -18969,183 +17793,4 @@ static struct my_tests_st my_tests[]= {
};
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- switch (optid) {
- case '#':
- DBUG_PUSH(argument ? argument : default_dbug_option);
- break;
- case 'c':
-#ifdef NOT_USED
- opt_testcase = 1;
-#endif
- break;
- case 'p':
- if (argument)
- {
- char *start=argument;
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
- opt_password= my_strdup(argument, MYF(MY_FAE));
- while (*argument) *argument++= 'x'; /* Destroy argument */
- if (*start)
- start[1]=0;
- }
- else
- tty_password= 1;
- break;
- case 's':
- if (argument == disabled_my_option)
- opt_silent= 0;
- else
- opt_silent++;
- break;
- case 'A':
- /*
- When the embedded server is being tested, the test suite needs to be
- able to pass command-line arguments to the embedded server so it can
- locate the language files and data directory. The test suite
- (mysql-test-run) never uses config files, just command-line options.
- */
- if (!embedded_server_arg_count)
- {
- embedded_server_arg_count= 1;
- embedded_server_args[0]= (char*) "";
- }
- if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
- !(embedded_server_args[embedded_server_arg_count++]=
- my_strdup(argument, MYF(MY_FAE))))
- {
- DIE("Can't use server argument");
- }
- break;
- case 'T':
- {
- struct my_tests_st *fptr;
-
- printf("All possible test names:\n\n");
- for (fptr= my_tests; fptr->name; fptr++)
- printf("%s\n", fptr->name);
- exit(0);
- break;
- }
- case '?':
- case 'I': /* Info */
- usage();
- exit(0);
- break;
- }
- return 0;
-}
-
-static void get_options(int *argc, char ***argv)
-{
- int ho_error;
-
- if ((ho_error= handle_options(argc, argv, client_test_long_options,
- get_one_option)))
- exit(ho_error);
-
- if (tty_password)
- opt_password= get_tty_password(NullS);
- return;
-}
-
-/*
- Print the test output on successful execution before exiting
-*/
-
-static void print_test_output()
-{
- if (opt_silent < 3)
- {
- fprintf(stdout, "\n\n");
- fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)",
- test_count-1, opt_count);
- fprintf(stdout, "\n Total execution time: %g SECS", total_time);
- if (opt_count > 1)
- fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count);
-
- fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
- }
-}
-
-/***************************************************************************
- main routine
-***************************************************************************/
-
-
-int main(int argc, char **argv)
-{
- struct my_tests_st *fptr;
-
- MY_INIT(argv[0]);
-
- load_defaults("my", client_test_load_default_groups, &argc, &argv);
- defaults_argv= argv;
- get_options(&argc, &argv);
-
- if (mysql_server_init(embedded_server_arg_count,
- embedded_server_args,
- (char**) embedded_server_groups))
- DIE("Can't initialize MySQL server");
-
- /* connect to server with no flags, default protocol, auto reconnect true */
- mysql= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1);
-
- total_time= 0;
- for (iter_count= 1; iter_count <= opt_count; iter_count++)
- {
- /* Start of tests */
- test_count= 1;
- start_time= time((time_t *)0);
- if (!argc)
- {
- for (fptr= my_tests; fptr->name; fptr++)
- (*fptr->function)();
- }
- else
- {
- for ( ; *argv ; argv++)
- {
- for (fptr= my_tests; fptr->name; fptr++)
- {
- if (!strcmp(fptr->name, *argv))
- {
- (*fptr->function)();
- break;
- }
- }
- if (!fptr->name)
- {
- fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
- fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
- my_progname);
- client_disconnect(mysql, 1);
- free_defaults(defaults_argv);
- exit(1);
- }
- }
- }
-
- end_time= time((time_t *)0);
- total_time+= difftime(end_time, start_time);
-
- /* End of tests */
- }
-
- client_disconnect(mysql, 1); /* disconnect from server */
-
- free_defaults(defaults_argv);
- print_test_output();
-
- while (embedded_server_arg_count > 1)
- my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
-
- mysql_server_end();
-
- my_end(0);
-
- exit(0);
-}
+static struct my_tests_st *get_my_tests() { return my_tests; }
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 31863a0830f..945e288a799 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -201,7 +201,7 @@ static void check_ssl_init()
static struct st_VioSSLFd *
new_VioSSLFd(const char *key_file, const char *cert_file,
const char *ca_file, const char *ca_path,
- const char *cipher, SSL_METHOD *method,
+ const char *cipher, my_bool is_client_method,
enum enum_ssl_init_error* error)
{
DH *dh;
@@ -222,7 +222,9 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
my_malloc(sizeof(struct st_VioSSLFd),MYF(0)))))
DBUG_RETURN(0);
- if (!(ssl_fd->ssl_context= SSL_CTX_new(method)))
+ if (!(ssl_fd->ssl_context= SSL_CTX_new(is_client_method ?
+ TLSv1_client_method() :
+ TLSv1_server_method())))
{
*error= SSL_INITERR_MEMFAIL;
DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
@@ -300,8 +302,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
verify= SSL_VERIFY_NONE;
if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
- ca_path, cipher,
- (SSL_METHOD*) TLSv1_client_method(), &dummy)))
+ ca_path, cipher, TRUE, &dummy)))
{
return 0;
}
@@ -323,8 +324,7 @@ new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
struct st_VioSSLFd *ssl_fd;
int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
- ca_path, cipher,
- (SSL_METHOD*) TLSv1_server_method(), error)))
+ ca_path, cipher, FALSE, error)))
{
return 0;
}