[Pkg-mysql-commits] [mariadb-5.5] 01/03: Imported Upstream version 5.5.49

Otto Kekäläinen otto at moszumanska.debian.org
Fri Apr 22 19:20:37 UTC 2016


This is an automated email from the git hooks/post-receive script.

otto pushed a commit to branch ubuntu-14.04
in repository mariadb-5.5.

commit d97fe3f6f998b1c2fb8167ccf580c10802045923
Author: Otto Kekäläinen <otto at seravo.fi>
Date:   Fri Apr 22 22:10:27 2016 +0300

    Imported Upstream version 5.5.49
---
 .gitignore                                         |   3 +
 Docs/INFO_SRC                                      |  10 +-
 VERSION                                            |   2 +-
 client/client_priv.h                               |   1 +
 client/mysql.cc                                    |  34 +-
 client/mysql_upgrade.c                             |  20 +-
 client/mysqladmin.cc                               |   2 +-
 client/mysqlcheck.c                                |   3 +-
 client/mysqldump.c                                 |   2 +-
 client/mysqlimport.c                               |   2 +-
 client/mysqlshow.c                                 |   2 +-
 client/mysqlslap.c                                 |   2 +-
 client/mysqltest.cc                                |   4 +-
 cmake/dtrace.cmake                                 |   3 +
 cmake/libutils.cmake                               |   5 +
 cmake/os/Windows.cmake                             |  11 +-
 cmake/os/WindowsCache.cmake                        |   4 -
 cmake/ssl.cmake                                    |   5 +
 config.h.cmake                                     |  10 +-
 configure.cmake                                    |  31 +-
 debian/mariadb-test-5.5.dirs                       |   2 -
 extra/yassl/README                                 |  17 +
 extra/yassl/include/crypto_wrapper.hpp             |   1 +
 extra/yassl/include/openssl/ssl.h                  |   2 +-
 extra/yassl/include/yassl_int.hpp                  |   8 +-
 extra/yassl/src/cert_wrapper.cpp                   |   9 +-
 extra/yassl/src/crypto_wrapper.cpp                 |  11 +-
 extra/yassl/src/ssl.cpp                            |  14 +-
 extra/yassl/src/yassl_imp.cpp                      |  15 +-
 extra/yassl/src/yassl_int.cpp                      |  46 +-
 extra/yassl/taocrypt/include/asn.hpp               |   8 +
 extra/yassl/taocrypt/src/asn.cpp                   |  12 +-
 extra/yassl/testsuite/test.hpp                     |  22 +-
 include/my_context.h                               |   2 +-
 include/my_global.h                                |  16 +-
 include/my_pthread.h                               |   2 +
 ...mysql_nodtrace.h => probes_mysql_nodtrace.h.in} |   0
 include/violite.h                                  |   4 +
 include/welcome_copyright_notice.h                 |   6 +-
 libmysql/CMakeLists.txt                            |  46 +-
 libmysql/errmsg.c                                  |   2 +-
 libmysql/libmysql_versions.ld.in                   |  16 +-
 mysql-test/include/ctype_numconv.inc               |   6 +
 mysql-test/lib/My/SafeProcess/safe_process_win.cc  |  10 +-
 mysql-test/r/cache_temporal_4265.result            |  13 +
 mysql-test/r/case.result                           |  13 +
 mysql-test/r/create.result                         |  16 +
 mysql-test/r/ctype_binary.result                   |   9 +
 mysql-test/r/ctype_cp1251.result                   |   9 +
 mysql-test/r/ctype_cp850.result                    |  14 +
 mysql-test/r/ctype_latin1.result                   |   9 +
 mysql-test/r/ctype_ucs.result                      |   9 +
 mysql-test/r/ctype_utf8.result                     |  32 +-
 mysql-test/r/ctype_utf8mb4.result                  |  18 +-
 mysql-test/r/ctype_utf8mb4_heap.result             |   2 +-
 mysql-test/r/ctype_utf8mb4_innodb.result           |   2 +-
 mysql-test/r/ctype_utf8mb4_myisam.result           |   2 +-
 mysql-test/r/derived.result                        | 344 ++++++++
 mysql-test/r/events_2.result                       |   4 +-
 mysql-test/r/func_math.result                      |   9 +-
 mysql-test/r/func_str.result                       |   6 +-
 mysql-test/r/func_time.result                      |  35 +
 mysql-test/r/insert_innodb.result                  |  30 +
 mysql-test/r/kill_processlist-6619.result          |   4 -
 mysql-test/r/locale.result                         |  11 +
 mysql-test/r/mdev6830.result                       |   3 +-
 mysql-test/r/merge_innodb.result                   |  33 +
 mysql-test/r/myisam-blob.result                    |   4 +-
 mysql-test/r/mysql_upgrade.result                  |   2 +-
 mysql-test/r/mysql_upgrade_view.result             |  15 +
 mysql-test/r/mysqld--help.result                   |   2 +-
 mysql-test/r/second_frac-9175.result               |  13 +
 mysql-test/r/select_debug.result                   |   2 +-
 mysql-test/r/set_password_plugin-9835.result       | 158 ++++
 mysql-test/r/sp.result                             |  18 +-
 mysql-test/r/ssl_cert_verify.result                |   5 +
 mysql-test/r/ssl_timeout-9836.result               |   7 +
 mysql-test/r/subselect.result                      |  13 +
 mysql-test/r/subselect_extra_no_semijoin.result    |   8 +-
 mysql-test/r/subselect_no_mat.result               |  13 +
 mysql-test/r/subselect_no_opts.result              |  13 +
 mysql-test/r/subselect_no_scache.result            |  13 +
 mysql-test/r/subselect_no_semijoin.result          |  13 +
 mysql-test/r/subselect_sj.result                   |  65 ++
 mysql-test/r/subselect_sj_jcl6.result              |  65 ++
 mysql-test/r/type_blob.result                      |  33 +
 mysql-test/r/type_date.result                      |  35 +
 mysql-test/r/type_timestamp.result                 |   9 +
 mysql-test/r/view.result                           |  20 +-
 mysql-test/std_data/ca-cert-verify.pem             |  20 +
 mysql-test/std_data/server-cert-verify-fail.pem    |  19 +
 mysql-test/std_data/server-cert-verify-pass.pem    |  19 +
 mysql-test/std_data/server-key-verify-fail.pem     |  27 +
 mysql-test/std_data/server-key-verify-pass.pem     |  27 +
 mysql-test/suite.pm                                |   2 +-
 mysql-test/suite/binlog/r/binlog_row_binlog.result |   2 +-
 mysql-test/suite/innodb/r/innodb-dict.result       |  40 +
 mysql-test/suite/innodb/t/innodb-dict.test         |  31 +
 .../suite/plugins/r/feedback_plugin_install.result |   1 +
 .../suite/plugins/r/feedback_plugin_load.result    |   1 +
 .../suite/plugins/r/feedback_plugin_send.result    |   1 +
 mysql-test/suite/plugins/r/server_audit.result     |   9 +-
 .../plugins/r/thread_pool_server_audit.result      |   9 +-
 .../rpl/r/rpl_autogen_query_multi_byte_char.result |  29 +
 mysql-test/suite/rpl/r/rpl_killed_ddl.result       |  10 +
 mysql-test/suite/rpl/r/rpl_row_merge_engine.result |   5 +-
 .../rpl/r/rpl_tmp_table_and_DDL_innodb.result      |  13 +
 .../suite/rpl/r/rpl_unsafe_statements.result       |  53 ++
 .../rpl/t/rpl_autogen_query_multi_byte_char.test   |  87 ++
 mysql-test/suite/rpl/t/rpl_killed_ddl.test         |  40 +-
 mysql-test/suite/rpl/t/rpl_row_merge_engine.test   |   6 +-
 .../suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test  |  55 ++
 mysql-test/suite/rpl/t/rpl_unsafe_statements.test  | 176 +++++
 mysql-test/suite/sys_vars/t/secure_file_priv.test  |  40 +-
 mysql-test/suite/vcol/inc/vcol_ins_upd.inc         |  27 +
 mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result |  26 +
 mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result |  26 +
 mysql-test/suite/vcol/r/vcol_misc.result           |   8 +
 mysql-test/suite/vcol/t/vcol_misc.test             |   7 +
 mysql-test/t/cache_temporal_4265.test              |  11 +
 mysql-test/t/case.test                             |   9 +
 mysql-test/t/create.test                           |  21 +
 mysql-test/t/ctype_cp850.test                      |  16 +
 mysql-test/t/ctype_utf8.test                       |  14 +-
 mysql-test/t/ctype_utf8mb4.test                    |  12 +
 mysql-test/t/derived.test                          | 290 +++++++
 mysql-test/t/events_2.test                         |   6 +-
 mysql-test/t/func_math.test                        |   8 +
 mysql-test/t/func_time.test                        |  18 +
 mysql-test/t/insert_innodb.test                    |  43 +
 mysql-test/t/kill_processlist-6619.test            |   2 -
 mysql-test/t/locale.test                           |   9 +
 mysql-test/t/mdev6830-master.opt                   |   1 -
 mysql-test/t/mdev6830.test                         |  10 +-
 mysql-test/t/merge_innodb.test                     |  31 +
 mysql-test/t/mysql_upgrade_view.test               |  27 +-
 mysql-test/t/mysqldump.test                        |   7 +-
 mysql-test/t/second_frac-9175.test                 |   9 +
 mysql-test/t/select_debug.test                     |   2 +-
 mysql-test/t/set_password_plugin-9835.test         | 128 +++
 mysql-test/t/ssl_cert_verify.test                  |  43 +
 mysql-test/t/ssl_timeout-9836.opt                  |   1 +
 mysql-test/t/ssl_timeout-9836.test                 |  11 +
 mysql-test/t/subselect.test                        |  10 +
 mysql-test/t/subselect_sj.test                     |  69 ++
 mysql-test/t/type_blob.test                        |  25 +
 mysql-test/t/type_date.test                        |  29 +
 mysql-test/t/type_timestamp.test                   |   8 +
 mysql-test/t/view.test                             |  10 +
 mysql-test/valgrind.supp                           |  10 +-
 mysys/default.c                                    |   1 +
 mysys/file_logger.c                                |   2 +
 mysys/lf_alloc-pin.c                               |   9 +-
 mysys/lf_hash.c                                    |  43 +-
 mysys/my_copy.c                                    |   1 -
 mysys/my_gethwaddr.c                               |   2 +-
 mysys/my_wincond.c                                 |   3 +-
 mysys/string.c                                     |  17 +-
 plugin/feedback/feedback.cc                        |  12 +-
 plugin/feedback/feedback.h                         |   6 +
 plugin/feedback/url_base.cc                        |  45 ++
 plugin/feedback/url_http.cc                        |  49 +-
 plugin/semisync/semisync_master.cc                 |   4 +-
 plugin/server_audit/CMakeLists.txt                 |   5 +-
 plugin/server_audit/plugin_audit_v4.h              | 561 +++++++++++++
 plugin/server_audit/server_audit.c                 | 880 ++++++++++++++-------
 plugin/server_audit/test_audit_v4.c                | 162 ++++
 sql-common/client.c                                |  90 ++-
 sql/field.cc                                       |  29 +
 sql/field.h                                        |   1 +
 sql/field_conv.cc                                  |  21 +-
 sql/gcalc_slicescan.cc                             | 266 +++----
 sql/gcalc_slicescan.h                              |  22 +-
 sql/gcalc_tools.cc                                 |   6 +-
 sql/handler.cc                                     |   4 +-
 sql/handler.h                                      |  14 +-
 sql/item.cc                                        |  14 +-
 sql/item.h                                         |   4 +-
 sql/item_cmpfunc.cc                                |  67 +-
 sql/item_cmpfunc.h                                 |   4 +-
 sql/item_func.cc                                   |  22 +-
 sql/item_func.h                                    |  21 +-
 sql/item_geofunc.cc                                |  22 +-
 sql/item_geofunc.h                                 |   6 +-
 sql/item_strfunc.cc                                |   2 +-
 sql/item_subselect.cc                              |  24 -
 sql/item_timefunc.cc                               |   4 +-
 sql/log.cc                                         |   2 +-
 sql/log_event.cc                                   |  10 +-
 sql/mysqld.cc                                      |  26 +-
 sql/mysqld.h                                       |  12 +-
 sql/opt_subselect.cc                               |  14 +-
 sql/rpl_reporting.cc                               |   1 +
 sql/sql_acl.cc                                     |  35 +-
 sql/sql_admin.cc                                   |  14 +-
 sql/sql_base.cc                                    | 166 +---
 sql/sql_class.cc                                   | 135 +++-
 sql/sql_class.h                                    |  16 +-
 sql/sql_insert.cc                                  |  15 +-
 sql/sql_lex.cc                                     |  15 +-
 sql/sql_lex.h                                      |  16 +-
 sql/sql_load.cc                                    |   5 +-
 sql/sql_locale.cc                                  |   2 +-
 sql/sql_select.cc                                  | 107 ++-
 sql/sql_select.h                                   |  13 +
 sql/sql_show.cc                                    |  27 +-
 sql/sql_show.h                                     |   3 +-
 sql/sql_table.cc                                   |  47 +-
 sql/sql_time.h                                     |   3 +-
 sql/sql_update.cc                                  |  20 +-
 sql/sql_view.cc                                    |   3 +-
 sql/sql_yacc.cc                                    |  18 +-
 sql/sql_yacc.yy                                    |  18 +-
 storage/innobase/buf/buf0flu.c                     |   9 +-
 storage/innobase/dict/dict0crea.c                  |   4 +-
 storage/innobase/dict/dict0dict.c                  |   2 +-
 storage/innobase/handler/ha_innodb.cc              |   2 +-
 storage/innobase/include/ha_prototypes.h           |  14 +
 storage/innobase/include/os0sync.h                 |  46 +-
 storage/innobase/log/log0recv.c                    |   4 +-
 storage/innobase/row/row0mysql.c                   |  49 ++
 storage/innobase/srv/srv0srv.c                     |  33 +-
 storage/myisam/ft_boolean_search.c                 |   5 +-
 storage/myisammrg/ha_myisammrg.cc                  |   1 +
 storage/sphinx/ha_sphinx.cc                        |   2 +
 storage/tokudb/ft-index/buildheader/make_tdb.cc    |   4 +-
 .../ft-index/cmake_modules/TokuSetupCompiler.cmake |  18 +-
 storage/tokudb/ft-index/ft/txn/rollback.cc         |   4 +-
 storage/tokudb/ft-index/tools/tokudb_dump.cc       |  70 --
 storage/tokudb/ft-index/util/dmt.h                 |   8 +-
 storage/tokudb/ha_tokudb.cc                        |   2 +-
 storage/xtradb/buf/buf0flu.c                       |   9 +-
 storage/xtradb/dict/dict0dict.c                    |   2 +-
 storage/xtradb/handler/ha_innodb.cc                |  16 +-
 storage/xtradb/handler/ha_innodb.h                 |  23 +
 storage/xtradb/handler/handler0alter.cc            |  16 +
 storage/xtradb/include/ha_prototypes.h             |  14 +
 storage/xtradb/include/univ.i                      |   4 +-
 storage/xtradb/log/log0recv.c                      |   6 +-
 storage/xtradb/row/row0mysql.c                     |  49 ++
 storage/xtradb/srv/srv0srv.c                       |  33 +-
 strings/decimal.c                                  |   3 +-
 unittest/my_decimal/CMakeLists.txt                 |   2 +-
 unittest/my_decimal/my_decimal-t.cc                |  34 +-
 unittest/mysys/CMakeLists.txt                      |   4 +-
 unittest/mysys/dynstring-t.c                       |  74 ++
 unittest/strings/CMakeLists.txt                    |   2 +-
 vio/viosslfactories.c                              |   4 +
 win/packaging/CMakeLists.txt                       |  61 +-
 win/packaging/ca/CMakeLists.txt                    |  41 +-
 250 files changed, 5730 insertions(+), 1424 deletions(-)

diff --git a/.gitignore b/.gitignore
index c3d50ee..b780ca8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,9 @@ include/mysql_version.h
 include/mysqld_ername.h
 include/mysqld_error.h
 include/sql_state.h
+include/probes_mysql.d
+include/probes_mysql_dtrace.h
+include/probes_mysql_nodtrace.h
 info_macros.cmake
 libmysql*/libmysql*_exports_file.cc
 libmysql*/merge_archives_mysql*.cmake
diff --git a/Docs/INFO_SRC b/Docs/INFO_SRC
index 7092fb8..74c32cd 100644
--- a/Docs/INFO_SRC
+++ b/Docs/INFO_SRC
@@ -1,8 +1,8 @@
-commit: d67aacb4fbb449ffa8db4e3d70fe8756d62b5222
-date: 2015-12-09 17:11:55 +0100
-build-date: 2015-12-09 18:22:49 +0100 
-short: d67aacb
+commit: 0991e19e9d38f7475390276c0557c2390e4d93c9
+date: 2016-04-20 20:25:46 +0200
+build-date: 2016-04-20 22:44:41 +0200 
+short: 0991e19e
 branch: HEAD
 
 
-MySQL source 5.5.47
+MySQL source 5.5.49
diff --git a/VERSION b/VERSION
index b85da23..ba54e70 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
 MYSQL_VERSION_MAJOR=5
 MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=47
+MYSQL_VERSION_PATCH=49
 MYSQL_VERSION_EXTRA=
diff --git a/client/client_priv.h b/client/client_priv.h
index e206804..d89ca89 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,5 +1,6 @@
 /*
    Copyright (c) 2001, 2012, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
diff --git a/client/mysql.cc b/client/mysql.cc
index 8e40cf0..43c09ca 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, Monty Program Ab.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -95,9 +95,16 @@ extern "C" {
 #endif
 }
 
-#if !defined(HAVE_VIDATTR)
-#undef vidattr
-#define vidattr(A) {}			// Can't get this to work
+#ifdef HAVE_VIDATTR
+static int have_curses= 0;
+static void my_vidattr(chtype attrs)
+{
+  if (have_curses)
+    vidattr(attrs);
+}
+#else
+#undef HAVE_SETUPTERM
+#define my_vidattr(A) {}              // Can't get this to work
 #endif
 
 #ifdef FN_NO_CASE_SENSE
@@ -1107,7 +1114,7 @@ inline int get_command_index(char cmd_char)
     All client-specific commands are in the first part of commands array
     and have a function to implement it.
   */
-  for (uint i= 0; *commands[i].func; i++)
+  for (uint i= 0; commands[i].func; i++)
     if (commands[i].cmd_char == cmd_char)
       return i;
   return -1;
@@ -4726,9 +4733,9 @@ com_status(String *buffer __attribute__((unused)),
 
   if (skip_updates)
   {
-    vidattr(A_BOLD);
+    my_vidattr(A_BOLD);
     tee_fprintf(stdout, "\nAll updates ignored to this database\n");
-    vidattr(A_NORMAL);
+    my_vidattr(A_NORMAL);
   }
 #ifdef USE_POPEN
   tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
@@ -4796,9 +4803,9 @@ com_status(String *buffer __attribute__((unused)),
   }
   if (safe_updates)
   {
-    vidattr(A_BOLD);
+    my_vidattr(A_BOLD);
     tee_fprintf(stdout, "\nNote that you are running in safe_update_mode:\n");
-    vidattr(A_NORMAL);
+    my_vidattr(A_NORMAL);
     tee_fprintf(stdout, "\
 UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
 (One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n\
@@ -4891,9 +4898,10 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
   {
     if (!inited)
     {
+      int errret;
       inited=1;
 #ifdef HAVE_SETUPTERM
-      (void) setupterm((char *)0, 1, (int *) 0);
+      have_curses= setupterm((char *)0, 1, &errret) != ERR;
 #endif
     }
     if (info_type == INFO_ERROR)
@@ -4906,7 +4914,7 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
         putchar('\a');		      	/* This should make a bell */
 #endif
       }
-      vidattr(A_STANDOUT);
+      my_vidattr(A_STANDOUT);
       if (error)
       {
 	if (sqlstate)
@@ -4925,9 +4933,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
       tee_fputs(": ", file);
     }
     else
-      vidattr(A_BOLD);
+      my_vidattr(A_BOLD);
     (void) tee_puts(str, file);
-    vidattr(A_NORMAL);
+    my_vidattr(A_NORMAL);
   }
   if (unbuffered)
     fflush(file);
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 0be8f91..eaa1024 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2006, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -182,7 +182,8 @@ static const char *load_default_groups[]=
 static void free_used_memory(void)
 {
   /* Free memory allocated by 'load_defaults' */
-  free_defaults(defaults_argv);
+  if (defaults_argv)
+    free_defaults(defaults_argv);
 
   dynstr_free(&ds_args);
   dynstr_free(&conn_args);
@@ -1051,16 +1052,11 @@ int main(int argc, char **argv)
   /* Find mysql */
   find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name);
 
-  if (!opt_systables_only)
-  {
-    /* Find mysqlcheck */
-    find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
-  }
-  else
-  {
-    if (!opt_silent)
-      printf("The --upgrade-system-tables option was used, databases won't be touched.\n");
-  }
+  /* Find mysqlcheck */
+  find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
+
+  if (opt_systables_only && !opt_silent)
+    printf("The --upgrade-system-tables option was used, user tables won't be touched.\n");
 
   /*
     Read the mysql_upgrade_info file to check if mysql_upgrade
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 10026cf..9fd8a9b 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2014, Monty Program Ab.
+   Copyright (c) 2010, 2016, 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
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 267d847..f249ca4 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2001, 2011, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -512,7 +512,6 @@ static int is_view(const char *table)
   {
     fprintf(stderr, "Failed to %s\n", query);
     fprintf(stderr, "Error: %s\n", mysql_error(sock));
-    my_free(query);
     DBUG_RETURN(-1);
   }
   res= mysql_store_result(sock);
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 74fd4f6..ecb4ed0 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, Monty Program Ab.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index a22774b..8fab3f2 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2011, 2015, MariaDB
+   Copyright (c) 2011, 2016, MariaDB
 
    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
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index b4514f5..64a6a65 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2010, 2016, MariaDB
 
    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
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 03301b0..4f6fc7d 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2005, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2010, 2016, MariaDB
 
    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
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 9b925d6..9a1dfaa 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2013, Monty Program Ab.
+   Copyright (c) 2009, 2016, 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
@@ -5211,7 +5211,7 @@ static st_error global_error_names[] =
 #include <my_base.h>
 static st_error handler_error_names[] =
 {
-  { "<No error>", -1U, "" },
+  { "<No error>", UINT_MAX, "" },
 #include <handler_ername.h>
   { 0, 0, 0 }
 };
diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake
index 5d0bb7f..3edcdc4 100644
--- a/cmake/dtrace.cmake
+++ b/cmake/dtrace.cmake
@@ -86,6 +86,9 @@ IF(ENABLE_DTRACE)
   ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h
   ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h
   ) 
+ELSE()
+ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql_nodtrace.h.in
+   ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h COPYONLY)
 ENDIF()
 
 FUNCTION(DTRACE_INSTRUMENT target)
diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake
index cca0032..41b7d9d 100644
--- a/cmake/libutils.cmake
+++ b/cmake/libutils.cmake
@@ -87,6 +87,11 @@ MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS)
     ENDFOREACH()
     SET(CONTENT "${CONTENT} (void *)0\n}\;")
     CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
+    # Avoid "function redeclared as variable" error
+    # when using gcc/clang option -flto(link time optimization)
+    IF(" ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS} " MATCHES " -flto")
+      SET_SOURCE_FILES_PROPERTIES(${EXPORTS} PROPERTIES COMPILE_FLAGS "-fno-lto")
+    ENDIF()
     SET(${VAR} ${EXPORTS})
   ENDIF()
 ENDMACRO()
diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake
index 5999ae6..e1055ab 100644
--- a/cmake/os/Windows.cmake
+++ b/cmake/os/Windows.cmake
@@ -100,8 +100,11 @@ IF(MSVC)
    STRING(REGEX REPLACE "/STACK:([^ ]+)" "" CMAKE_${type}_LINKER_FLAGS "${CMAKE_${type}_LINKER_FLAGS}")
    STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}")
    STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}")
+   STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_DEBUG "${CMAKE_${type}_LINKER_FLAGS_DEBUG}")
+   STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_DEBUG "${CMAKE_${type}_LINKER_FLAGS_DEBUG}")
    SET(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /release")
   ENDFOREACH()
+
   
   # Mark 32 bit executables large address aware so they can 
   # use > 2GB address space
@@ -117,7 +120,7 @@ IF(MSVC)
   
   #TODO: update the code and remove the disabled warnings
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805 /wd4996")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /we4099")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /we4099")
 
   IF(CMAKE_SIZEOF_VOID_P MATCHES 8)
     # _WIN64 is defined by the compiler itself. 
@@ -185,14 +188,14 @@ CHECK_SYMBOL_REPLACEMENT(S_IROTH _S_IREAD sys/stat.h)
 CHECK_SYMBOL_REPLACEMENT(S_IFIFO _S_IFIFO sys/stat.h)
 CHECK_SYMBOL_REPLACEMENT(SIGQUIT SIGTERM signal.h)
 CHECK_SYMBOL_REPLACEMENT(SIGPIPE SIGINT signal.h)
-CHECK_SYMBOL_REPLACEMENT(isnan _isnan float.h)
-CHECK_SYMBOL_REPLACEMENT(finite _finite float.h)
+CHECK_SYMBOL_REPLACEMENT(isnan _isnan "math.h;float.h")
+CHECK_SYMBOL_REPLACEMENT(finite _finite "math;float.h")
 CHECK_FUNCTION_REPLACEMENT(popen _popen)
 CHECK_FUNCTION_REPLACEMENT(pclose _pclose)
 CHECK_FUNCTION_REPLACEMENT(access _access)
 CHECK_FUNCTION_REPLACEMENT(strcasecmp _stricmp)
 CHECK_FUNCTION_REPLACEMENT(strncasecmp _strnicmp)
-CHECK_FUNCTION_REPLACEMENT(snprintf _snprintf)
+CHECK_SYMBOL_REPLACEMENT(snprintf _snprintf stdio.h)
 CHECK_FUNCTION_REPLACEMENT(strtok_r strtok_s)
 CHECK_FUNCTION_REPLACEMENT(strtoll _strtoi64)
 CHECK_FUNCTION_REPLACEMENT(strtoull _strtoui64)
diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake
index c75f2e4..1694b23 100644
--- a/cmake/os/WindowsCache.cmake
+++ b/cmake/os/WindowsCache.cmake
@@ -101,7 +101,6 @@ SET(HAVE_IPPROTO_IPV6 CACHE  INTERNAL "")
 SET(HAVE_IPV6 TRUE CACHE  INTERNAL "")
 SET(HAVE_IPV6_V6ONLY 1 CACHE  INTERNAL "")
 SET(HAVE_ISINF CACHE  INTERNAL "")
-SET(HAVE_ISNAN CACHE  INTERNAL "")
 SET(HAVE_ISSETUGID CACHE  INTERNAL "")
 SET(HAVE_GETUID CACHE  INTERNAL "")
 SET(HAVE_GETEUID CACHE  INTERNAL "")
@@ -231,7 +230,6 @@ SET(HAVE_SIZEOF_ULONG FALSE CACHE  INTERNAL "")
 SET(HAVE_SIZEOF_U_INT32_T FALSE CACHE  INTERNAL "")
 SET(HAVE_SIZE_OF_SSIZE_T FALSE CACHE  INTERNAL "")
 SET(HAVE_SLEEP CACHE  INTERNAL "")
-SET(HAVE_SNPRINTF CACHE  INTERNAL "")
 SET(HAVE_SOCKADDR_STORAGE_SS_FAMILY 1 CACHE  INTERNAL "")
 SET(HAVE_SOLARIS_STYLE_GETHOST CACHE  INTERNAL "")
 SET(STACK_DIRECTION -1 CACHE INTERNAL "")
@@ -324,10 +322,8 @@ SET(WORDS_BIGENDIAN CACHE  INTERNAL "")
 SET(HAVE__S_IFIFO 1 CACHE  INTERNAL "")
 SET(HAVE__S_IREAD 1 CACHE  INTERNAL "")
 SET(HAVE__finite 1 CACHE  INTERNAL "")
-SET(HAVE__isnan 1 CACHE  INTERNAL "")
 SET(HAVE__pclose 1 CACHE  INTERNAL "")
 SET(HAVE__popen 1 CACHE  INTERNAL "")
-SET(HAVE__snprintf 1 CACHE  INTERNAL "")
 SET(HAVE__stricmp 1 CACHE  INTERNAL "")
 SET(HAVE__strnicmp 1 CACHE  INTERNAL "")
 SET(HAVE__strtoi64 1 CACHE  INTERNAL "")
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index ca95022..43665d0 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -26,6 +26,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL)
   SET(SSL_INCLUDE_DIRS ${INC_DIRS})
   SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL)
   SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED")
+  SET(HAVE_ERR_remove_thread_state OFF CACHE INTERNAL "yassl doesn't have ERR_remove_thread_state")
   CHANGE_SSL_SETTINGS("bundled")
   #Remove -fno-implicit-templates 
   #(yassl sources cannot  be compiled with  it)
@@ -70,9 +71,13 @@ MACRO (MYSQL_CHECK_SSL)
     MARK_AS_ADVANCED(CRYPTO_LIBRARY)
     INCLUDE(CheckSymbolExists)
     SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+    SET(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
     CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h" 
                         HAVE_SHA512_DIGEST_LENGTH)
+    CHECK_SYMBOL_EXISTS(ERR_remove_thread_state "openssl/err.h"
+                        HAVE_ERR_remove_thread_state)
     SET(CMAKE_REQUIRED_INCLUDES)
+    SET(CMAKE_REQUIRED_LIBRARIES)
     IF(OPENSSL_FOUND AND CRYPTO_LIBRARY AND HAVE_SHA512_DIGEST_LENGTH)
       SET(SSL_SOURCES "")
       SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY})
diff --git a/config.h.cmake b/config.h.cmake
index 73dc918..225d489 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -95,6 +95,7 @@
 #cmakedefine HAVE_SYS_TYPES_H 1
 #cmakedefine HAVE_SYS_UN_H 1
 #cmakedefine HAVE_SYS_VADVISE_H 1
+#cmakedefine HAVE_UCONTEXT_H 1
 #cmakedefine HAVE_TERM_H 1
 #cmakedefine HAVE_TERMBITS_H 1
 #cmakedefine HAVE_TERMIOS_H 1
@@ -291,7 +292,6 @@
 #cmakedefine HAVE_THR_YIELD 1
 #cmakedefine HAVE_TIME 1
 #cmakedefine HAVE_TIMES 1
-#cmakedefine HAVE_UCONTEXT 1
 #cmakedefine HAVE_VALLOC 1
 #cmakedefine HAVE_VIDATTR 1
 #define HAVE_VIO_READ_BUFF 1
@@ -319,6 +319,8 @@
 #cmakedefine HAVE_TIMESPEC_TS_SEC 1
 #cmakedefine STRUCT_DIRENT_HAS_D_INO 1
 #cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1
+#cmakedefine STRUCT_TIMESPEC_HAS_TV_SEC 1
+#cmakedefine STRUCT_TIMESPEC_HAS_TV_NSEC 1
 #cmakedefine SPRINTF_RETURNS_INT 1
 
 #define USE_MB 1
@@ -465,7 +467,7 @@
 #cmakedefine HAVE_BSD_SIGNALS 1
 #cmakedefine HAVE_SVR3_SIGNALS 1
 #cmakedefine HAVE_V7_SIGNALS 1
-
+#cmakedefine HAVE_ERR_remove_thread_state 1
 
 #cmakedefine HAVE_SOLARIS_STYLE_GETHOST 1
 
@@ -515,6 +517,10 @@
 #cmakedefine strtoll @strtoll@
 #cmakedefine strtoull @strtoull@
 #cmakedefine vsnprintf @vsnprintf@
+#if (_MSC_VER > 1800)
+#define tzname _tzname
+#define P_tmpdir "C:\\TEMP"
+#endif
 #if (_MSC_VER > 1310)
 # define HAVE_SETENV
 #define setenv(a,b,c) _putenv_s(a,b)
diff --git a/configure.cmake b/configure.cmake
index 1e64e05..f0517bf 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -798,16 +798,36 @@ ENDIF()
 #
 # Test for how the C compiler does inline, if at all
 #
+# SunPro is weird, apparently it only supports inline at -xO3 or -xO4.
+# And if CMAKE_C_FLAGS has -xO4 but CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE} has -xO2
+# then CHECK_C_SOURCE_COMPILES will succeed but the built will fail.
+# We must test all flags here.
+# XXX actually, we can do this for all compilers, not only SunPro
+IF (CMAKE_CXX_COMPILER_ID MATCHES "SunPro" AND
+    CMAKE_GENERATOR MATCHES "Makefiles")
+  STRING(TOUPPER "CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}" flags)
+  SET(CMAKE_REQUIRED_FLAGS "${${flags}}")
+ENDIF()
 CHECK_C_SOURCE_COMPILES("
-static inline int foo(){return 0;}
+extern int bar(int x);
+static inline int foo(){return bar(1);}
 int main(int argc, char *argv[]){return 0;}"
                             C_HAS_inline)
 IF(NOT C_HAS_inline)
   CHECK_C_SOURCE_COMPILES("
-  static __inline int foo(){return 0;}
+  extern int bar(int x);
+  static __inline int foo(){return bar(1);}
   int main(int argc, char *argv[]){return 0;}"
                             C_HAS___inline)
-  SET(C_INLINE __inline)
+  IF(C_HAS___inline)
+    SET(C_INLINE __inline)
+  ElSE()
+    SET(C_INLINE)
+    MESSAGE(WARNING "C compiler does not support funcion inlining")
+    IF(NOT NOINLINE)
+      MESSAGE(FATAL_ERROR "Use -DNOINLINE=TRUE to allow compilation without inlining")
+    ENDIF()
+  ENDIF()
 ENDIF()
 
 IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC)
@@ -1098,3 +1118,8 @@ CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h"  STRUCT_DIRENT_HAS_D_IN
 CHECK_STRUCT_HAS_MEMBER("struct dirent" d_namlen "dirent.h"  STRUCT_DIRENT_HAS_D_NAMLEN)
 SET(SPRINTF_RETURNS_INT 1)
 CHECK_INCLUDE_FILE(ucontext.h HAVE_UCONTEXT_H)
+IF(NOT HAVE_UCONTEXT_H)
+  CHECK_INCLUDE_FILE(sys/ucontext.h HAVE_UCONTEXT_H)
+ENDIF()
+CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_sec "time.h" STRUCT_TIMESPEC_HAS_TV_SEC)
+CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_nsec "time.h" STRUCT_TIMESPEC_HAS_TV_NSEC)
diff --git a/debian/mariadb-test-5.5.dirs b/debian/mariadb-test-5.5.dirs
index f45bf43..65dbbc8 100644
--- a/debian/mariadb-test-5.5.dirs
+++ b/debian/mariadb-test-5.5.dirs
@@ -50,8 +50,6 @@ usr/share/mysql/mysql-test/suite/ndb
 usr/share/mysql/mysql-test/suite/ndb/t
 usr/share/mysql/mysql-test/suite/ndb/r
 usr/share/mysql/mysql-test/suite/maria
-usr/share/mysql/mysql-test/suite/maria/t
-usr/share/mysql/mysql-test/suite/maria/r
 usr/share/mysql/mysql-test/suite/funcs_2
 usr/share/mysql/mysql-test/suite/funcs_2/lib
 usr/share/mysql/mysql-test/suite/funcs_2/t
diff --git a/extra/yassl/README b/extra/yassl/README
index bf0e1c9..b5eb888 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -12,6 +12,23 @@ before calling SSL_new();
 
 *** end Note ***
 
+yaSSL Release notes, version 2.3.9b (2/03/2016)
+    This release of yaSSL fixes the OpenSSL compatibility function
+    X509_NAME_get_index_by_NID() to use the actual index of the common name
+    instead of searching on the format prefix.  Thanks for the report from
+    yashwant.sahu at oracle.com  .  Anyone using this function should update.
+
+yaSSL Release notes, version 2.3.9 (12/01/2015)
+    This release of yaSSL fixes two client side Diffie-Hellman problems.
+    yaSSL was only handling the cases of zero or one leading zeros for the key
+    agreement instead of potentially any number.  This caused about 1 in 50,000
+    connections to fail when using DHE cipher suites.  The second problem was
+    the case where a server would send a public value shorter than the prime
+    value, causing about 1 in 128 client connections to fail, and also
+    caused the yaSSL client to read off the end of memory.  All client side
+    DHE cipher suite users should update.
+    Thanks to Adam Langely (agl at imperialviolet.org) for the detailed report!
+
 yaSSL Release notes, version 2.3.8 (9/17/2015)
     This release of yaSSL fixes a high security vulnerability.  All users
     SHOULD update.  If using yaSSL for TLS on the server side with private
diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp
index b09b662..0472b30 100644
--- a/extra/yassl/include/crypto_wrapper.hpp
+++ b/extra/yassl/include/crypto_wrapper.hpp
@@ -378,6 +378,7 @@ public:
 
     uint        get_agreedKeyLength() const;
     const byte* get_agreedKey()       const;
+    uint        get_publicKeyLength() const;
     const byte* get_publicKey()       const;
     void        makeAgreement(const byte*, unsigned int);
 
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
index b0a7592..83daf3c 100644
--- a/extra/yassl/include/openssl/ssl.h
+++ b/extra/yassl/include/openssl/ssl.h
@@ -35,7 +35,7 @@
 #include "rsa.h"
 
 
-#define YASSL_VERSION "2.3.8"
+#define YASSL_VERSION "2.3.9b"
 
 
 #if defined(__cplusplus)
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index 9f28cbe..d046d4f 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -191,14 +191,18 @@ private:
 class X509_NAME {
     char*       name_;
     size_t      sz_;
+    int         cnPosition_;   // start of common name, -1 is none
+    int         cnLen_;        // length of above
     ASN1_STRING entry_;
 public:
-    X509_NAME(const char*, size_t sz);
+    X509_NAME(const char*, size_t sz, int pos, int len);
     ~X509_NAME();
 
     const char*  GetName() const;
     ASN1_STRING* GetEntry(int i);
     size_t       GetLength() const;
+    int          GetCnPosition() const { return cnPosition_; }
+    int          GetCnLength()   const { return cnLen_; }
 private:
     X509_NAME(const X509_NAME&);                // hide copy
     X509_NAME& operator=(const X509_NAME&);     // and assign
@@ -226,7 +230,7 @@ class X509 {
     StringHolder afterDate_;    // not valid after
 public:
     X509(const char* i, size_t, const char* s, size_t,
-         const char* b, int, const char* a, int);
+         const char* b, int, const char* a, int, int, int, int, int);
     ~X509() {}
 
     X509_NAME* GetIssuer();
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
index ff359c6..f620f5e 100644
--- a/extra/yassl/src/cert_wrapper.cpp
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -293,7 +293,10 @@ int CertManager::Validate()
         int aSz = (int)strlen(cert.GetAfterDate()) + 1;
         peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
                                 sSz, cert.GetBeforeDate(), bSz,
-                                cert.GetAfterDate(), aSz);
+                             cert.GetAfterDate(), aSz,
+                             cert.GetIssuerCnStart(), cert.GetIssuerCnLength(),
+                             cert.GetSubjectCnStart(), cert.GetSubjectCnLength()
+                            );
 
         if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) {
             X509_STORE_CTX store;
@@ -345,7 +348,9 @@ void CertManager::setPeerX509(X509* x)
 
     peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
         subject->GetName(), subject->GetLength(), (const char*) before->data,
-        before->length, (const char*) after->data, after->length);
+        before->length, (const char*) after->data, after->length,
+        issuer->GetCnPosition(), issuer->GetCnLength(),
+        subject->GetCnPosition(), subject->GetCnLength());
 }
 
 
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
index cc74690..c405998 100644
--- a/extra/yassl/src/crypto_wrapper.cpp
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -751,9 +751,10 @@ struct DiffieHellman::DHImpl {
     byte* publicKey_;
     byte* privateKey_;
     byte* agreedKey_;
+    uint  pubKeyLength_;
 
     DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0),
-                                               privateKey_(0), agreedKey_(0) {}
+                              privateKey_(0), agreedKey_(0), pubKeyLength_(0) {}
     ~DHImpl() 
     {   
         ysArrayDelete(agreedKey_); 
@@ -762,7 +763,7 @@ struct DiffieHellman::DHImpl {
     }
 
     DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_),
-                                 publicKey_(0), privateKey_(0), agreedKey_(0)
+                  publicKey_(0), privateKey_(0), agreedKey_(0), pubKeyLength_(0)
     {
         uint length = dh_.GetByteLength();
         AllocKeys(length, length, length);
@@ -810,7 +811,7 @@ DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g,
     using TaoCrypt::Integer;
 
     pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref());
-    pimpl_->publicKey_ = NEW_YS opaque[pubSz];
+    pimpl_->publicKey_ = NEW_YS opaque[pimpl_->pubKeyLength_ = pubSz];
     memcpy(pimpl_->publicKey_, pub, pubSz);
 }
 
@@ -869,6 +870,10 @@ const byte* DiffieHellman::get_agreedKey() const
     return pimpl_->agreedKey_;
 }
 
+uint DiffieHellman::get_publicKeyLength() const
+{
+    return pimpl_->pubKeyLength_;
+}
 
 const byte* DiffieHellman::get_publicKey() const
 {
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index 9516e8b..778c6a8 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -1351,15 +1351,13 @@ int ASN1_STRING_type(ASN1_STRING *x)
 int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos)
 {
     int idx = -1;  // not found
-    const char* start = &name->GetName()[lastpos + 1];
+    int cnPos = -1;
 
     switch (nid) {
     case NID_commonName:
-        const char* found = strstr(start, "/CN=");
-        if (found) {
-            found += 4;  // advance to str
-            idx = found - start + lastpos + 1;
-        }
+        cnPos = name->GetCnPosition();
+        if (lastpos < cnPos)
+            idx = cnPos;
         break;
     }
 
@@ -1471,10 +1469,6 @@ int SSL_peek(SSL* ssl, void* buffer, int sz)
 
 int SSL_pending(SSL* ssl)
 {
-    // Just in case there's pending data that hasn't been processed yet...
-    char c;
-    SSL_peek(ssl, &c, 1);
-    
     return ssl->bufferedData();
 }
 
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
index e1a4100..5158bd2 100644
--- a/extra/yassl/src/yassl_imp.cpp
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -109,15 +109,12 @@ void ClientDiffieHellmanPublic::build(SSL& ssl)
     uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same
 
     alloc(keyLength, true);
-    dhClient.makeAgreement(dhServer.get_publicKey(), keyLength);
+    dhClient.makeAgreement(dhServer.get_publicKey(),
+                           dhServer.get_publicKeyLength());
     c16toa(keyLength, Yc_);
     memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
 
-    // because of encoding first byte might be zero, don't use it for preMaster
-    if (*dhClient.get_agreedKey() == 0) 
-        ssl.set_preMaster(dhClient.get_agreedKey() + 1, keyLength - 1);
-    else
-        ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
+    ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
 }
 
 
@@ -321,11 +318,7 @@ void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
     }
     dh.makeAgreement(Yc_, keyLength); 
 
-    // because of encoding, first byte might be 0, don't use for preMaster 
-    if (*dh.get_agreedKey() == 0) 
-        ssl.set_preMaster(dh.get_agreedKey() + 1, dh.get_agreedKeyLength() - 1);
-    else
-        ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength());
+    ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength());
     ssl.makeMasterSecret();
 }
 
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index a98b4f3..215628c 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -807,6 +807,19 @@ void SSL::set_random(const opaque* random, ConnectionEnd sender)
 // store client pre master secret
 void SSL::set_preMaster(const opaque* pre, uint sz)
 {
+    uint i(0);  // trim leading zeros
+    uint fullSz(sz);
+
+    while (i++ < fullSz && *pre == 0) {
+        sz--;
+        pre++;
+    }
+
+    if (sz == 0) {
+        SetError(bad_input);
+        return;
+    }
+
     secure_.use_connection().AllocPreSecret(sz);
     memcpy(secure_.use_connection().pre_master_secret_, pre, sz);
 }
@@ -924,6 +937,8 @@ void SSL::order_error()
 // Create and store the master secret see page 32, 6.1
 void SSL::makeMasterSecret()
 {
+    if (GetError()) return;
+
     if (isTLS())
         makeTLSMasterSecret();
     else {
@@ -1540,7 +1555,9 @@ void SSL_SESSION::CopyX509(X509* x)
 
     peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
         subject->GetName(), subject->GetLength(), (const char*) before->data,
-        before->length, (const char*) after->data, after->length);
+        before->length, (const char*) after->data, after->length,
+        issuer->GetCnPosition(), issuer->GetCnLength(),
+        subject->GetCnPosition(), subject->GetCnLength());
 }
 
 
@@ -2457,8 +2474,8 @@ void Security::set_resuming(bool b)
 }
 
 
-X509_NAME::X509_NAME(const char* n, size_t sz)
-    : name_(0), sz_(sz)
+X509_NAME::X509_NAME(const char* n, size_t sz, int pos, int len)
+    : name_(0), sz_(sz), cnPosition_(pos), cnLen_(len)
 {
     if (sz) {
         name_ = NEW_YS char[sz];
@@ -2488,8 +2505,9 @@ size_t X509_NAME::GetLength() const
 
 
 X509::X509(const char* i, size_t iSz, const char* s, size_t sSz,
-           const char* b, int bSz, const char* a, int aSz)
-    : issuer_(i, iSz), subject_(s, sSz),
+           const char* b, int bSz, const char* a, int aSz, int issPos,
+           int issLen, int subPos, int subLen)
+    : issuer_(i, iSz, issPos, issLen), subject_(s, sSz, subPos, subLen),
       beforeDate_(b, bSz), afterDate_(a, aSz)
 {}
 
@@ -2523,17 +2541,19 @@ ASN1_STRING* X509_NAME::GetEntry(int i)
     if (i < 0 || i >= int(sz_))
         return 0;
 
+    if (i != cnPosition_ || cnLen_ <= 0)   // only entry currently supported
+        return 0;
+
+    if (cnLen_ > int(sz_-i))   // make sure there's room in read buffer
+        return 0;
+
     if (entry_.data)
         ysArrayDelete(entry_.data);
-    entry_.data = NEW_YS byte[sz_];       // max size;
+    entry_.data = NEW_YS byte[cnLen_+1];       // max size;
 
-    memcpy(entry_.data, &name_[i], sz_ - i);
-    if (entry_.data[sz_ -i - 1]) {
-        entry_.data[sz_ - i] = 0;
-        entry_.length = int(sz_) - i;
-    }
-    else
-        entry_.length = int(sz_) - i - 1;
+    memcpy(entry_.data, &name_[i], cnLen_);
+    entry_.data[cnLen_] = 0;
+    entry_.length = cnLen_;
     entry_.type = 0;
 
     return &entry_;
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
index c7d01d0..9a10064 100644
--- a/extra/yassl/taocrypt/include/asn.hpp
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -283,6 +283,10 @@ public:
     const byte*      GetHash()       const { return subjectHash_; }
     const char*      GetBeforeDate() const { return beforeDate_; }
     const char*      GetAfterDate()  const { return afterDate_; }
+    int              GetSubjectCnStart()  const { return subCnPos_; }
+    int              GetIssuerCnStart()   const { return issCnPos_; }
+    int              GetSubjectCnLength() const { return subCnLen_; }
+    int              GetIssuerCnLength()  const { return issCnLen_; }
 
     void DecodeToKey();
 private:
@@ -292,6 +296,10 @@ private:
     word32    sigLength_;               // length of signature
     word32    signatureOID_;            // sum of algorithm object id
     word32    keyOID_;                  // sum of key algo  object id
+    int       subCnPos_;                // subject common name start, -1 is none
+    int       subCnLen_;                // length of above
+    int       issCnPos_;                // issuer common name start, -1 is none
+    int       issCnLen_;                // length of above
     byte      subjectHash_[SHA_SIZE];   // hash of all Names
     byte      issuerHash_[SHA_SIZE];    // hash of all Names
     byte*     signature_;
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index c419ec0..a210d80 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -474,8 +474,9 @@ void DH_Decoder::Decode(DH& key)
 
 CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers,
                          bool noVerify, CertType ct)
-    : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
-      signature_(0), verify_(!noVerify)
+    : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), subCnPos_(-1),
+      subCnLen_(0), issCnPos_(-1), issCnLen_(0), signature_(0),
+      verify_(!noVerify)
 {
     issuer_[0] = 0;
     subject_[0] = 0;
@@ -796,6 +797,13 @@ void CertDecoder::GetName(NameType nt)
             case COMMON_NAME:
                 if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen)))
                     return;
+                if (nt == ISSUER) {
+                    issCnPos_ = (int)(ptr - strLen - issuer_);
+                    issCnLen_ = (int)strLen;
+                } else {
+                    subCnPos_ = (int)(ptr - strLen - subject_);
+                    subCnLen_ = (int)strLen;
+                }
                 break;
             case SUR_NAME:
                 if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen)))
diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp
index 52f6ed7..5374edd 100644
--- a/extra/yassl/testsuite/test.hpp
+++ b/extra/yassl/testsuite/test.hpp
@@ -470,10 +470,28 @@ inline void showPeer(SSL* ssl)
         char* issuer  = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0);
         char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0);
 
-        printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer,
-                                                                  subject);
+        X509_NAME_ENTRY* se = NULL;
+        ASN1_STRING*     sd = NULL;
+        char*            subCN = NULL;
+
+        X509_NAME* sub = X509_get_subject_name(peer);
+        int lastpos = -1;
+        if (sub)
+            lastpos = X509_NAME_get_index_by_NID(sub, NID_commonName, lastpos);
+        if (lastpos >= 0) {
+            se = X509_NAME_get_entry(sub, lastpos);
+            if (se)
+                sd = X509_NAME_ENTRY_get_data(se);
+            if (sd)
+                subCN = (char*)ASN1_STRING_data(sd);
+        }
+
+        printf("peer's cert info:\n issuer : %s\n subject: %s\n"
+               " subject cn: %s\n", issuer, subject, subCN);
+
         free(subject);
         free(issuer);
+
     }
     else
         printf("peer has no cert!\n");
diff --git a/include/my_context.h b/include/my_context.h
index b5daca2..dd44103 100644
--- a/include/my_context.h
+++ b/include/my_context.h
@@ -31,7 +31,7 @@
 #define MY_CONTEXT_USE_X86_64_GCC_ASM
 #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
 #define MY_CONTEXT_USE_I386_GCC_ASM
-#elif defined(HAVE_UCONTEXT)
+#elif defined(HAVE_UCONTEXT_H)
 #define MY_CONTEXT_USE_UCONTEXT
 #else
 #define MY_CONTEXT_DISABLE
diff --git a/include/my_global.h b/include/my_global.h
index 09adc99..dce38a1 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -207,20 +207,6 @@
 #define likely(x)	__builtin_expect(((x) != 0),1)
 #define unlikely(x)	__builtin_expect(((x) != 0),0)
 
-/*
-  now let's figure out if inline functions are supported
-  autoconf defines 'inline' to be empty, if not
-*/
-#define inline_test_1(X)        X ## 1
-#define inline_test_2(X)        inline_test_1(X)
-#if inline_test_2(inline) != 1
-#define HAVE_INLINE
-#else
-#error Compiler does not support inline!
-#endif
-#undef inline_test_2
-#undef inline_test_1
-
 /* Fix problem with S_ISLNK() on Linux */
 #if defined(TARGET_OS_LINUX) || defined(__GLIBC__)
 #undef  _GNU_SOURCE
@@ -436,7 +422,7 @@ extern "C" int madvise(void *addr, size_t len, int behav);
 #endif
 
 #ifndef STDERR_FILENO
-#define STDERR_FILENO 2
+#define STDERR_FILENO fileno(stderr)
 #endif
 
 /*
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 17c971c..9b5703d 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -86,10 +86,12 @@ typedef volatile LONG my_pthread_once_t;
 #define MY_PTHREAD_ONCE_INPROGRESS 1
 #define MY_PTHREAD_ONCE_DONE 2
 
+#if !STRUCT_TIMESPEC_HAS_TV_SEC  || !STRUCT_TIMESPEC_HAS_TV_NSEC
 struct timespec {
   time_t tv_sec;
   long tv_nsec;
 };
+#endif
 
 int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
 int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *);
diff --git a/include/probes_mysql_nodtrace.h b/include/probes_mysql_nodtrace.h.in
similarity index 100%
rename from include/probes_mysql_nodtrace.h
rename to include/probes_mysql_nodtrace.h.in
diff --git a/include/violite.h b/include/violite.h
index 14c99e8..ea7e3d7 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -123,6 +123,10 @@ typedef my_socket YASSL_SOCKET_T;
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
+#ifdef HAVE_ERR_remove_thread_state
+#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
+#endif
+
 enum enum_ssl_init_error
 {
   SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY, 
diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h
index 096d424..e989185 100644
--- a/include/welcome_copyright_notice.h
+++ b/include/welcome_copyright_notice.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2011, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2011, 2015, MariaDB
+/* Copyright (c) 2011, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
 #ifndef _welcome_copyright_notice_h_
 #define _welcome_copyright_notice_h_
 
-#define COPYRIGHT_NOTICE_CURRENT_YEAR "2015"
+#define COPYRIGHT_NOTICE_CURRENT_YEAR "2016"
 
 /*
   This define specifies copyright notice which is displayed by every MySQL
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index e611efa..7615630 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -251,6 +251,25 @@ SET(CLIENT_API_FUNCTIONS
 )
 
 IF(CMAKE_SYSTEM_NAME MATCHES "Linux") 
+  IF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+
+    INCLUDE (CheckCSourceCompiles)
+    FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.ld"
+      "VERSION {\nlibmysqlclient_18 {\nglobal: *;\n};\n}\n")
+    SET(CMAKE_REQUIRED_LIBRARIES "-Wl,src.ld")
+    CHECK_C_SOURCE_COMPILES("int main() { return 0; }"
+      SUPPORTS_VERSION_IN_LINK_SCRIPT)
+    SET(CMAKE_REQUIRED_LIBRARIES)
+
+    IF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT)
+      # https://sourceware.org/bugzilla/show_bug.cgi?id=16895
+      MESSAGE(SEND_ERROR "Your current linker does not support VERSION "
+        "command in linker scripts like a GNU ld or any compatible linker "
+        "should. Perhaps you're using gold? Either switch to GNU ld compatible "
+        "linker or run cmake with -DDISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING=TRUE "
+        "to be able to complete the build")
+    ENDIF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT)
+
   # When building RPM, or DEB package on Debian, use ELF symbol versioning
   # for compatibility with distribution packages, so client shared library can 
   # painlessly replace the one supplied by the distribution.
@@ -335,14 +354,26 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
     make_scrambled_password_323
   )
 
-  # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529
-  SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in)
-
   # Generate version script.  
   # Create semicolon separated lists of functions to export from 
   # Since RPM packages use separate versioning for 5.1 API
   # and 5.5 API (libmysqlclient_16 vs libmysqlclient_18), 
   # we need 2 lists.
+  SET (VERSION_HEADER
+"VERSION {
+  libmysqlclient_18 {
+    global:")
+  SET (VERSION_FOOTER
+"    local:
+      *;
+  };
+
+  libmysqlclient_16 {
+    /* empty here. aliases are added above */
+  };
+}
+")
+
   SET (CLIENT_API_5_1_LIST)
   SET (CLIENT_API_5_1_ALIASES)
   FOREACH (f ${CLIENT_API_FUNCTIONS_5_1} ${CLIENT_API_5_1_EXTRA})
@@ -355,6 +386,13 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
     SET(CLIENT_API_5_5_LIST "${CLIENT_API_5_5_LIST}\t${f};\n")
   ENDFOREACH()
 
+  ELSE (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+    SET (CLIENT_API_5_1_ALIASES "/* Versioning disabled per user request. MDEV-5982 */")
+  ENDIF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+
+  # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529
+  SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in)
+
   CONFIGURE_FILE(
     ${VERSION_SCRIPT_TEMPLATE}
     ${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld
@@ -363,7 +401,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
   SET(VERSION_SCRIPT_LINK_FLAGS 
     "-Wl,${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld")
 
-ENDIF()
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
 
 
 SET(CLIENT_SOURCES
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 23c8e99..9c241c2 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -88,7 +88,7 @@ const char *client_errors[]=
   ""
 };
 
-const char** get_client_errmsgs()
+const char** get_client_errmsgs(void)
 {
   return client_errors;
 }
diff --git a/libmysql/libmysql_versions.ld.in b/libmysql/libmysql_versions.ld.in
index 8d97da5..0cf5b45 100644
--- a/libmysql/libmysql_versions.ld.in
+++ b/libmysql/libmysql_versions.ld.in
@@ -27,19 +27,7 @@ mysql_get_charset_by_csname = get_charset_by_csname;
 mysql_net_realloc = net_realloc;
 mysql_client_errors = client_errors;
 
-VERSION {
-
-libmysqlclient_18 {
-  global:
+ at VERSION_HEADER@
 @CLIENT_API_5_1_LIST@
 @CLIENT_API_5_5_LIST@
-
-  local:
-	*;
-};
-
-libmysqlclient_16 {
-  /* empty here. aliases are added above */
-};
-
-}
+ at VERSION_FOOTER@
diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc
index 25314d5..9b21e7f 100644
--- a/mysql-test/include/ctype_numconv.inc
+++ b/mysql-test/include/ctype_numconv.inc
@@ -1795,6 +1795,12 @@ DROP FUNCTION f1;
 DROP TABLE t1;
 
 --echo #
+--echo # MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+--echo #
+SELECT @@collation_connection;
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+
+--echo #
 --echo # MDEV-5702 Incorrect results are returned with NULLIF()
 --echo #
 CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc
index 87a1448..dca2fad 100644
--- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc
+++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc
@@ -357,14 +357,14 @@ int main(int argc, const char** argv )
   CloseHandle(job_handle);
   message("Job terminated and closed");
 
-  if (!jobobject_assigned)
-  {
-    GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, process_info.dwProcessId);
-    TerminateProcess(process_info.hProcess, 202);
-  }
+
 
   if (wait_res != WAIT_OBJECT_0 + CHILD)
   {
+    if (!jobobject_assigned)
+    {
+      TerminateProcess(process_info.hProcess, 202);
+    }
     /* The child has not yet returned, wait for it */
     message("waiting for child to exit");
     if ((wait_res= WaitForSingleObject(wait_handles[CHILD], INFINITE))
diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result
index 1b4b3c2..7f215de 100644
--- a/mysql-test/r/cache_temporal_4265.result
+++ b/mysql-test/r/cache_temporal_4265.result
@@ -7,4 +7,17 @@ a
 2002-03-04
 Warnings:
 Note	1003	2000-01-01
+set debug_dbug='';
+drop table t1;
+create table t1 (id int not null, ut timestamp(6) not null);
+insert into t1 values(1, '2001-01-01 00:00:00.2');
+insert into t1 values(1, '2001-01-01 00:00:00.1');
+select * from t1;
+id	ut
+1	2001-01-01 00:00:00.200000
+1	2001-01-01 00:00:00.100000
+select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1;
+(select max(m2.ut) from t1 m2 where m1.id <> 0)
+2001-01-01 00:00:00.200000
+2001-01-01 00:00:00.200000
 drop table t1;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 3852da5..274d5da 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -231,3 +231,16 @@ case t1.f1 when '00:00:00' then 1 end
 1
 NULL
 drop table t1;
+#
+# MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END
+#
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a;
+DESCRIBE t1;
+Field	Type	Null	Key	Default	Extra
+a	decimal(1,0)	YES		NULL	
+DROP TABLE t1;
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a;
+DESCRIBE t1;
+Field	Type	Null	Key	Default	Extra
+a	decimal(2,0)	YES		NULL	
+DROP TABLE t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 327b53c..0164aa4 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -2483,3 +2483,19 @@ Warnings:
 Note	1291	Column 'a' has duplicated value '' in ENUM
 drop table t1;
 set @@session.collation_server=default;
+#
+# MDEV-7765: Crash (Assertion `!table || (!table->write_set ||
+# bitmap_is_set(table->write_set, field_index) ||
+# bitmap_is_set(table->vcol_set, field_index))' fails)
+# on using function over not created table
+#
+CREATE function f1() returns int
+BEGIN
+declare n int;
+set n:= (select count(*) from t1);
+return n;
+end|
+create table t1 as select f1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop function f1;
+End of 5.5 tests
diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result
index 73c81c4..e7bf123 100644
--- a/mysql-test/r/ctype_binary.result
+++ b/mysql-test/r/ctype_binary.result
@@ -2849,6 +2849,15 @@ f1()
 DROP FUNCTION f1;
 DROP TABLE t1;
 #
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+binary
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
 # MDEV-5702 Incorrect results are returned with NULLIF()
 #
 CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result
index 313f60e..2a7d4ed 100644
--- a/mysql-test/r/ctype_cp1251.result
+++ b/mysql-test/r/ctype_cp1251.result
@@ -3241,6 +3241,15 @@ f1()
 DROP FUNCTION f1;
 DROP TABLE t1;
 #
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+cp1251_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
 # MDEV-5702 Incorrect results are returned with NULLIF()
 #
 CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_cp850.result b/mysql-test/r/ctype_cp850.result
new file mode 100644
index 0000000..c028f72
--- /dev/null
+++ b/mysql-test/r/ctype_cp850.result
@@ -0,0 +1,14 @@
+#
+# Start of 5.5 tests
+#
+#
+# MDEV-9862 Illegal mix of collation, when comparing column with CASE expression
+#
+SET NAMES cp850;
+CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1);
+SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a;
+a
+DROP TABLE t1;
+#
+# End of 5.5 tests
+#
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index 11a9479..dc96495 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -3423,6 +3423,15 @@ f1()
 DROP FUNCTION f1;
 DROP TABLE t1;
 #
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+latin1_swedish_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
 # MDEV-5702 Incorrect results are returned with NULLIF()
 #
 CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index f9e9a69..96e0970 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -4239,6 +4239,15 @@ f1()
 DROP FUNCTION f1;
 DROP TABLE t1;
 #
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+ucs2_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
 # MDEV-5702 Incorrect results are returned with NULLIF()
 #
 CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 91dbe85..217d3ca 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -116,7 +116,7 @@ hex(a)	STRCMP(a,'a')	STRCMP(a,'a ')
 DROP TABLE t1;
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
@@ -5060,6 +5060,15 @@ f1()
 DROP FUNCTION f1;
 DROP TABLE t1;
 #
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+utf8_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
 # MDEV-5702 Incorrect results are returned with NULLIF()
 #
 CREATE TABLE t1 (d DATE);
@@ -5092,9 +5101,10 @@ SET sql_mode=default;
 SET NAMES utf8;
 CREATE TABLE t1 (a INT);
 INSERT INTO t1 VALUES (0), (0), (1), (0), (0);
-SELECT COUNT(*) FROM t1, t1 t2 
+SELECT COUNT(*) FROM t1, t1 t2
 GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
-ERROR 23000: Duplicate entry '107374182410737418241' for key 'group_key'
+COUNT(*)
+25
 DROP TABLE t1;
 #
 # Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
@@ -5804,5 +5814,21 @@ c0	c1	c2	c3	c4
 2012-06-11 15:18:24	2012-06-11 15:18:24	2012-06-11 15:18:24	2012-06-11 15:18:24	2012-06-11 15:18:24
 DROP TABLE t2, t1;
 #
+# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a TEXT CHARACTER SET utf8);
+INSERT INTO t1 VALUES (REPEAT('A',100));
+SELECT OCTET_LENGTH(a) FROM t1;
+OCTET_LENGTH(a)
+300
+ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT OCTET_LENGTH(a),a FROM t1;
+OCTET_LENGTH(a)	a
+255	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+DROP TABLE t1;
+#
 # End of 5.5 tests
 #
diff --git a/mysql-test/r/ctype_utf8mb4.result b/mysql-test/r/ctype_utf8mb4.result
index 6455630..448645e 100644
--- a/mysql-test/r/ctype_utf8mb4.result
+++ b/mysql-test/r/ctype_utf8mb4.result
@@ -116,7 +116,7 @@ hex(a)	STRCMP(a,'a')	STRCMP(a,'a ')
 DROP TABLE t1;
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
@@ -2606,6 +2606,22 @@ Warning	1292	Truncated incorrect INTEGER value: 'a'
 DROP TABLE t1;
 # End of test for Bug#13581962,Bug#14096619
 #
+# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+#
+SET NAMES utf8mb4;
+CREATE TABLE t1 (a TEXT CHARACTER SET utf8mb4);
+INSERT INTO t1 VALUES (REPEAT('😎',100));
+SELECT OCTET_LENGTH(a) FROM t1;
+OCTET_LENGTH(a)
+400
+ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8mb4;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT OCTET_LENGTH(a),a FROM t1;
+OCTET_LENGTH(a)	a
+252	😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎
+DROP TABLE t1;
+#
 # End of 5.5 tests
 #
 #
diff --git a/mysql-test/r/ctype_utf8mb4_heap.result b/mysql-test/r/ctype_utf8mb4_heap.result
index 5959205..a9a8482 100644
--- a/mysql-test/r/ctype_utf8mb4_heap.result
+++ b/mysql-test/r/ctype_utf8mb4_heap.result
@@ -116,7 +116,7 @@ hex(a)	STRCMP(a,'a')	STRCMP(a,'a ')
 DROP TABLE t1;
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
diff --git a/mysql-test/r/ctype_utf8mb4_innodb.result b/mysql-test/r/ctype_utf8mb4_innodb.result
index 4dcac1d..d8649d3 100644
--- a/mysql-test/r/ctype_utf8mb4_innodb.result
+++ b/mysql-test/r/ctype_utf8mb4_innodb.result
@@ -116,7 +116,7 @@ hex(a)	STRCMP(a,'a')	STRCMP(a,'a ')
 DROP TABLE t1;
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
diff --git a/mysql-test/r/ctype_utf8mb4_myisam.result b/mysql-test/r/ctype_utf8mb4_myisam.result
index e07e347..b0c673f 100644
--- a/mysql-test/r/ctype_utf8mb4_myisam.result
+++ b/mysql-test/r/ctype_utf8mb4_myisam.result
@@ -116,7 +116,7 @@ hex(a)	STRCMP(a,'a')	STRCMP(a,'a ')
 DROP TABLE t1;
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 7c44466..2c316a8 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -580,3 +580,347 @@ select x.id, message from (select id from t1) x left join
 where coalesce(message,0) <> 0;
 id	message
 drop table t1,t2;
+#
+# MDEV-7827: Assertion `!table || (!table->read_set ||
+# bitmap_is_set(table->read_set, field_index))' failed
+# in Field_long::val_str on EXPLAIN EXTENDED
+#
+CREATE TABLE t1 (f1 INT, f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (6,9);
+CREATE TABLE t2 (f3 INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (2),(0);
+EXPLAIN EXTENDED
+SELECT f1 FROM ( SELECT * FROM t1 ) AS sq
+WHERE f1 IN (
+SELECT f3 FROM t2 WHERE f2 IN (
+SELECT f3 FROM t2 HAVING f3 >= 8
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	1	100.00	
+1	PRIMARY	<subquery4>	eq_ref	distinct_key	distinct_key	4	test.t1.f2	1	100.00	
+1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; FirstMatch(<subquery4>); Using join buffer (flat, BNL join)
+4	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	
+Warnings:
+Note	1276	Field or reference 'f2' of SELECT #3 was resolved in SELECT #1
+Note	1003	select 6 AS `f1` from  <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and (9 = `<subquery4>`.`f3`))
+DROP TABLE t2,t1;
+#
+# MDEV-9462: Out of memory using explain on 2 empty tables 
+#
+CREATE TABLE `t1` (
+`REC_GROUP` char(2) DEFAULT NULL,
+`CLIENT_INFO` text CHARACTER SET utf8,
+`NAME` text,
+`PHONE_NUMBER` text,
+`ATTENTION_NAME` text,
+`PAYMENT_TERM` text CHARACTER SET utf8,
+`CREDIT_LIMIT` decimal(12,2) DEFAULT NULL,
+`LAST_PAY_DATE` text CHARACTER SET utf8,
+`TOTAL` double DEFAULT NULL,
+`TOTAL_MCL` double DEFAULT NULL,
+`TOTAL_MFS` double DEFAULT NULL,
+`TOTAL_MIS` double DEFAULT NULL,
+`BEFORE_DUE_7_MCL` double DEFAULT NULL,
+`BEFORE_DUE_7_MFS` double DEFAULT NULL,
+`BEFORE_DUE_7_MIS` double DEFAULT NULL,
+`PER1_MCL` double DEFAULT NULL,
+`PER1_MFS` double DEFAULT NULL,
+`PER1_MIS` double DEFAULT NULL,
+`PER2_MCL` double DEFAULT NULL,
+`PER2_MFS` double DEFAULT NULL,
+`PER2_MIS` double DEFAULT NULL,
+`PER3_MCL` double DEFAULT NULL,
+`PER3_MFS` double DEFAULT NULL,
+`PER3_MIS` double DEFAULT NULL,
+`PER4_MCL` double DEFAULT NULL,
+`PER4_MFS` double DEFAULT NULL,
+`PER4_MIS` double DEFAULT NULL,
+`PER5_MCL` double DEFAULT NULL,
+`PER5_MFS` double DEFAULT NULL,
+`PER5_MIS` double DEFAULT NULL,
+`PER6_MCL` double DEFAULT NULL,
+`PER6_MFS` double DEFAULT NULL,
+`PER6_MIS` double DEFAULT NULL,
+`PER7_MCL` double DEFAULT NULL,
+`PER7_MFS` double DEFAULT NULL,
+`PER7_MIS` double DEFAULT NULL,
+`BEFORE_DUE_7` double DEFAULT NULL,
+`PER1` double DEFAULT NULL,
+`PER2` double DEFAULT NULL,
+`PER3` double DEFAULT NULL,
+`PER4` double DEFAULT NULL,
+`PER5` double DEFAULT NULL,
+`PER6` double DEFAULT NULL,
+`PER7` double DEFAULT NULL,
+`REF` varchar(30) DEFAULT NULL,
+`TYPE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
+);
+CREATE TABLE `t2` (
+`RECEIVABLE_GROUP` char(2) DEFAULT NULL,
+`CLIENT_NUMBER` varchar(35) DEFAULT NULL,
+`CLIENT_NAME` varchar(73) DEFAULT NULL,
+`PHONE_NUMBER` char(12) DEFAULT NULL,
+`ATTENTION_NAME` char(26) DEFAULT NULL,
+`PAYMENT_TERM` varchar(26) CHARACTER SET utf8 DEFAULT NULL,
+`CREDIT_LIMIT` decimal(12,2) DEFAULT NULL,
+`LAST_PAY_DATE` varchar(42) CHARACTER SET utf8 DEFAULT NULL,
+`TOTAL` decimal(12,2) DEFAULT NULL,
+`BEFORE_DUE_7` decimal(12,2) DEFAULT NULL,
+`PER1` decimal(12,2) DEFAULT NULL,
+`PER2` decimal(12,2) DEFAULT NULL,
+`PER3` decimal(12,2) DEFAULT NULL,
+`PER4` decimal(12,2) DEFAULT NULL,
+`PER5` decimal(12,2) DEFAULT NULL,
+`PER6` decimal(12,2) DEFAULT NULL,
+`PER7` decimal(12,2) DEFAULT NULL,
+`DIVISION` varchar(3) CHARACTER SET utf8 NOT NULL,
+`CLIENT_INFO` varchar(294) CHARACTER SET utf8 DEFAULT NULL,
+`EXCHANGE_RATE` double NOT NULL,
+`REF` varchar(30) DEFAULT NULL
+);
+explain
+SELECT A.RECEIVABLE_GROUP,A.CLIENT_INFO,A.CLIENT_NAME,A.PHONE_NUMBER,A.ATTENTION_NAME,A.PAYMENT_TERM,A.CREDIT_LIMIT,A.LAST_PAY_DATE,A.TOTAL,
+COALESCE(B.TOTAL_MCL,0) AS TOTAL_MCL,
+COALESCE(C.TOTAL_MFS,0) AS TOTAL_MFS,
+COALESCE(D.TOTAL_MIS,0) AS TOTAL_MIS,
+COALESCE(F.BEFORE_DUE_7_MCL,0) AS BEFORE_DUE_7_MCL,
+COALESCE(G.BEFORE_DUE_7_MFS,0) AS BEFORE_DUE_7_MFS,
+COALESCE(H.BEFORE_DUE_7_MIS,0) AS BEFORE_DUE_7_MIS,
+COALESCE(I.PER1_MCL,0) AS PER1_MCL,
+COALESCE(J.PER1_MFS,0) AS PER1_MFS,
+COALESCE(K.PER1_MIS,0) AS PER1_MIS,
+COALESCE(L.PER2_MCL,0) AS PER2_MCL,
+COALESCE(M.PER2_MFS,0) AS PER2_MFS,
+COALESCE(N.PER2_MIS,0) AS PER2_MIS,
+COALESCE(O.PER3_MCL,0) AS PER3_MCL,
+COALESCE(P.PER3_MFS,0) AS PER3_MFS,
+COALESCE(R.PER3_MIS,0) AS PER3_MIS,
+COALESCE(S.PER4_MCL,0) AS PER4_MCL,
+COALESCE(T.PER4_MFS,0) AS PER4_MFS,
+COALESCE(U.PER4_MIS,0) AS PER4_MIS,
+COALESCE(V.PER5_MCL,0) AS PER5_MCL,
+COALESCE(X.PER5_MFS,0) AS PER5_MFS,
+COALESCE(Z.PER5_MIS,0) AS PER5_MIS,
+COALESCE(Q.PER6_MCL,0) AS PER6_MCL,
+COALESCE(Y.PER6_MFS,0) AS PER6_MFS,
+COALESCE(W.PER6_MIS,0) AS PER6_MIS,
+COALESCE(A1.PER7_MCL,0) AS PER7_MCL,
+COALESCE(B1.PER7_MFS,0) AS PER7_MFS,
+COALESCE(C1.PER7_MIS,0) AS PER7_MIS,
+A.BEFORE_DUE_7,A.PER1,A.PER2,A.PER3,A.PER4,A.PER5,A.PER6,A.PER7,
+CONCAT(A.DIVISION,'-',A.CLIENT_NUMBER) AS REF,"2" AS TYPE FROM
+(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,
+GROUP_CONCAT(DISTINCT CLIENT_INFO SEPARATOR '<br>') AS CLIENT_INFO,
+GROUP_CONCAT(DISTINCT CLIENT_NAME SEPARATOR '<br>') AS CLIENT_NAME, 
+GROUP_CONCAT( DISTINCT `PHONE_NUMBER` SEPARATOR '<br>' ) AS PHONE_NUMBER , 
+GROUP_CONCAT( DISTINCT `ATTENTION_NAME` SEPARATOR '<br>' )  AS ATTENTION_NAME, 
+GROUP_CONCAT( DISTINCT `PAYMENT_TERM` SEPARATOR '<br>' ) AS PAYMENT_TERM, 
+CREDIT_LIMIT , 
+GROUP_CONCAT( `LAST_PAY_DATE` SEPARATOR '<br>' ) AS LAST_PAY_DATE, 
+SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL, 
+SUM( `BEFORE_DUE_7`*EXCHANGE_RATE ) AS BEFORE_DUE_7, 
+SUM( `PER1`*EXCHANGE_RATE ) AS PER1, 
+SUM( `PER2`*EXCHANGE_RATE ) AS PER2, 
+SUM( `PER3`*EXCHANGE_RATE ) AS PER3, 
+SUM( `PER4`*EXCHANGE_RATE ) AS PER4, 
+SUM( `PER5`*EXCHANGE_RATE ) AS PER5, 
+SUM( `PER6`*EXCHANGE_RATE ) AS PER6, 
+SUM( `PER7`*EXCHANGE_RATE ) AS PER7
+FROM `t2`
+WHERE REF IS NULL GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A 
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B ON A.CLIENT_NUMBER=B.CLIENT_NUMBER AND 
+A.DIVISION=B.DIVISION AND A.RECEIVABLE_GROUP=B.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C ON A.CLIENT_NUMBER=C.CLIENT_NUMBER 
+AND 
+A.DIVISION=C.DIVISION AND A.RECEIVABLE_GROUP=C.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS D ON A.CLIENT_NUMBER=D.CLIENT_NUMBER AND 
+A.DIVISION=D.DIVISION AND A.RECEIVABLE_GROUP=D.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=D.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS F ON A.CLIENT_NUMBER=F.CLIENT_NUMBER AND 
+A.DIVISION=F.DIVISION AND A.RECEIVABLE_GROUP=F.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=F.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS G ON A.CLIENT_NUMBER=G.CLIENT_NUMBER AND 
+A.DIVISION=G.DIVISION AND A.RECEIVABLE_GROUP=G.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=G.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS H ON A.CLIENT_NUMBER=H.CLIENT_NUMBER AND 
+A.DIVISION=H.DIVISION AND A.RECEIVABLE_GROUP=H.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=H.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS I ON A.CLIENT_NUMBER=I.CLIENT_NUMBER  AND 
+A.DIVISION=I.DIVISION AND A.RECEIVABLE_GROUP=I.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=I.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS J ON A.CLIENT_NUMBER=J.CLIENT_NUMBER AND 
+A.DIVISION=J.DIVISION AND A.RECEIVABLE_GROUP=J.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=J.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS K ON A.CLIENT_NUMBER=K.CLIENT_NUMBER AND 
+A.DIVISION=K.DIVISION AND A.RECEIVABLE_GROUP=K.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=K.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS L ON A.CLIENT_NUMBER=L.CLIENT_NUMBER AND 
+A.DIVISION=L.DIVISION AND A.RECEIVABLE_GROUP=L.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=L.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS M ON A.CLIENT_NUMBER=M.CLIENT_NUMBER AND 
+A.DIVISION=M.DIVISION AND A.RECEIVABLE_GROUP=M.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=M.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS N ON A.CLIENT_NUMBER=N.CLIENT_NUMBER AND 
+A.DIVISION=N.DIVISION AND A.RECEIVABLE_GROUP=N.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=N.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS O ON A.CLIENT_NUMBER=O.CLIENT_NUMBER AND 
+A.DIVISION=O.DIVISION AND A.RECEIVABLE_GROUP=O.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=O.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS P ON A.CLIENT_NUMBER=P.CLIENT_NUMBER AND 
+A.DIVISION=P.DIVISION AND A.RECEIVABLE_GROUP=P.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=P.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS R ON A.CLIENT_NUMBER=R.CLIENT_NUMBER AND 
+A.DIVISION=R.DIVISION AND A.RECEIVABLE_GROUP=R.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=R.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS S ON A.CLIENT_NUMBER=S.CLIENT_NUMBER AND 
+A.DIVISION=S.DIVISION AND A.RECEIVABLE_GROUP=S.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=S.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS T ON A.CLIENT_NUMBER=T.CLIENT_NUMBER AND 
+A.DIVISION=T.DIVISION AND A.RECEIVABLE_GROUP=T.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=T.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS U ON A.CLIENT_NUMBER=U.CLIENT_NUMBER AND 
+A.DIVISION=U.DIVISION AND A.RECEIVABLE_GROUP=U.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=U.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS V ON A.CLIENT_NUMBER=V.CLIENT_NUMBER AND 
+A.DIVISION=V.DIVISION AND A.RECEIVABLE_GROUP=V.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=V.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS X ON A.CLIENT_NUMBER=X.CLIENT_NUMBER AND 
+A.DIVISION=X.DIVISION AND A.RECEIVABLE_GROUP=X.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=X.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Z ON A.CLIENT_NUMBER=Z.CLIENT_NUMBER AND 
+A.DIVISION=Z.DIVISION AND A.RECEIVABLE_GROUP=Z.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Z.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Q ON A.CLIENT_NUMBER=Q.CLIENT_NUMBER AND 
+A.DIVISION=Q.DIVISION AND A.RECEIVABLE_GROUP=Q.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Q.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Y ON A.CLIENT_NUMBER=Y.CLIENT_NUMBER AND 
+A.DIVISION=Y.DIVISION AND A.RECEIVABLE_GROUP=Y.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Y.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS W ON A.CLIENT_NUMBER=W.CLIENT_NUMBER AND 
+A.DIVISION=W.DIVISION AND A.RECEIVABLE_GROUP=W.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=W.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A1 ON A.CLIENT_NUMBER=A1.CLIENT_NUMBER AND 
+A.DIVISION=A1.DIVISION AND A.RECEIVABLE_GROUP=A1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=A1.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B1 ON A.CLIENT_NUMBER=B1.CLIENT_NUMBER AND 
+A.DIVISION=B1.DIVISION AND A.RECEIVABLE_GROUP=B1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B1.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C1 ON A.CLIENT_NUMBER=C1.CLIENT_NUMBER AND 
+A.DIVISION=C1.DIVISION AND A.RECEIVABLE_GROUP=C1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C1.CREDIT_LIMIT
+ORDER BY TOTAL DESC;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived3>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived4>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived5>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived6>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived7>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived8>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived9>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived10>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived11>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived12>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived13>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived14>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived15>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived16>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived17>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived18>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived19>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived20>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived21>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived22>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived23>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived24>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived25>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived26>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived27>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived28>	system	NULL	NULL	NULL	NULL	0	const row not found
+1	PRIMARY	<derived29>	system	NULL	NULL	NULL	NULL	0	const row not found
+29	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+28	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+27	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+26	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+25	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+24	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+23	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+22	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+21	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+20	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+19	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+18	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+17	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+16	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+15	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+14	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+13	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+12	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+11	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+10	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+9	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+8	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+7	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+6	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+5	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+4	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+3	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
+DROP TABLES t1,t2;
diff --git a/mysql-test/r/events_2.result b/mysql-test/r/events_2.result
index 66ec00d..17eee91 100644
--- a/mysql-test/r/events_2.result
+++ b/mysql-test/r/events_2.result
@@ -1,10 +1,10 @@
 drop database if exists events_test;
 create database events_test;
 use events_test;
-create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
+create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5;
 select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
 db	name	body	definer	convert_tz(execute_at, 'UTC', 'SYSTEM')	on_completion
-events_test	e_26	set @a = 5	root at localhost	2017-01-01 00:00:00	DROP
+events_test	e_26	set @a = 5	root at localhost	2027-01-01 00:00:00	DROP
 drop event e_26;
 create event e_26 on schedule at NULL disable do set @a = 5;
 ERROR HY000: Incorrect AT value: 'NULL'
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index 04e71a7..d122d43 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -660,9 +660,14 @@ ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 DIV
 CREATE TABLE t1(a BIGINT, b BIGINT UNSIGNED);
 INSERT INTO t1 VALUES(-9223372036854775808, 9223372036854775809);
 SELECT -a FROM t1;
-ERROR 22003: BIGINT value is out of range in '-(-9223372036854775808)'
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)'
 SELECT -b FROM t1;
-ERROR 22003: BIGINT value is out of range in '-(9223372036854775809)'
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)'
+INSERT INTO t1 VALUES(0,0);
+SELECT -a FROM t1;
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)'
+SELECT -b FROM t1;
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)'
 DROP TABLE t1;
 SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999;
 SELECT @a + @a;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 05d975b..5a7a13b 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -203,7 +203,7 @@ CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('
 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
-this	is a	test
+this	is 	test
 select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
 replace('aaaa','a','b')	replace('aaaa','aa','b')	replace('aaaa','a','bb')	replace('aaaa','','b')	replace('bbbb','a','c')
 bbbb	bb	bbbbbbbb	aaaa	bbbb
@@ -2335,7 +2335,7 @@ INSERT('abc', 3, 3, '1234')
 ab1234
 SELECT INSERT('abc', 4, 3, '1234');
 INSERT('abc', 4, 3, '1234')
-abc1234
+abc
 SELECT INSERT('abc', 5, 3, '1234');
 INSERT('abc', 5, 3, '1234')
 abc
@@ -2625,7 +2625,7 @@ CREATE TABLE t1 ( a TEXT );
 SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug58165.txt';;
 SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' );
 insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' )
-x
+
 Warnings:
 Warning	1292	Truncated incorrect INTEGER value: 'b'
 LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug58165.txt' INTO TABLE t1;;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 08d46ab..ef5e348 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1720,6 +1720,41 @@ insert into t1 values ('00:00:00'),('00:01:00');
 select 1 from t1 where 1 < some (select cast(a as datetime) from t1);
 1
 drop table t1;
+#
+# Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6
+#                UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M"
+#
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"));
+UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"))
+NULL
+Warnings:
+Warning	1411	Incorrect datetime value: '201506' for function str_to_date
+SELECT UNIX_TIMESTAMP('2015-06-00');
+UNIX_TIMESTAMP('2015-06-00')
+NULL
+Warnings:
+Warning	1292	Incorrect datetime value: '2015-06-00'
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'));
+UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'))
+NULL
+set sql_mode= 'TRADITIONAL';
+SELECT @@sql_mode;
+@@sql_mode
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"));
+UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"))
+NULL
+Warnings:
+Warning	1411	Incorrect datetime value: '201506' for function str_to_date
+SELECT UNIX_TIMESTAMP('2015-06-00');
+UNIX_TIMESTAMP('2015-06-00')
+NULL
+Warnings:
+Warning	1292	Incorrect datetime value: '2015-06-00'
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'));
+UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'))
+NULL
+set sql_mode= default;
 select time('10:10:10') > 10;
 time('10:10:10') > 10
 1
diff --git a/mysql-test/r/insert_innodb.result b/mysql-test/r/insert_innodb.result
new file mode 100644
index 0000000..ffba938
--- /dev/null
+++ b/mysql-test/r/insert_innodb.result
@@ -0,0 +1,30 @@
+#
+# BUG#22037930: INSERT IGNORE FAILS TO IGNORE
+#               FOREIGN KEY CONSTRAINT
+# Setup.
+CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1))
+ENGINE=INNODB;
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(0);
+# Without fix, an error is reported.
+INSERT IGNORE INTO t2 VALUES(1);
+Warnings:
+Warning	1452	Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0;
+UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0;
+# Test for multi update.
+UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3;
+UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3;
+# Reports an error since IGNORE is not used.
+INSERT INTO t2 VALUES(1);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t2 SET fld2=20 WHERE fld2=0;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1 SET fld1=20 WHERE fld1=0;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+DROP TABLE t2, t1;
diff --git a/mysql-test/r/kill_processlist-6619.result b/mysql-test/r/kill_processlist-6619.result
index 588c8e6..a3d971e 100644
--- a/mysql-test/r/kill_processlist-6619.result
+++ b/mysql-test/r/kill_processlist-6619.result
@@ -1,8 +1,4 @@
 connect  con1,localhost,root,,;
-SHOW PROCESSLIST;
-Id	User	Host	db	Command	Time	State	Info	Progress
-#	root	#	test	Sleep	#	#	NULL	0.000
-#	root	#	test	Query	#	#	SHOW PROCESSLIST	0.000
 connection default;
 KILL QUERY con_id;
 connection con1;
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
index aa61d8c..195468c 100644
--- a/mysql-test/r/locale.result
+++ b/mysql-test/r/locale.result
@@ -90,3 +90,14 @@ SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
 DATE_FORMAT('2001-01-07', '%w %a %W')
 0 Du Duminică
 End of 5.4 tests
+SET NAMES utf8;
+SET lc_time_names=de_AT;
+SELECT monthname('2001-01-01');
+monthname('2001-01-01')
+Jänner
+SELECT monthname('2001-02-01');
+monthname('2001-02-01')
+Februar
+SELECT monthname('2001-03-01');
+monthname('2001-03-01')
+März
diff --git a/mysql-test/r/mdev6830.result b/mysql-test/r/mdev6830.result
index 0570659..d1cf8c9 100644
--- a/mysql-test/r/mdev6830.result
+++ b/mysql-test/r/mdev6830.result
@@ -1,5 +1,4 @@
-drop table if exists t1,t2,t3;
-drop view if exists v2,v3;
+set @@debug_dbug= 'd,opt';
 CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM;
 CREATE TABLE t2 (
 f1 DATE,
diff --git a/mysql-test/r/merge_innodb.result b/mysql-test/r/merge_innodb.result
index f6057d2..5aa344a 100644
--- a/mysql-test/r/merge_innodb.result
+++ b/mysql-test/r/merge_innodb.result
@@ -35,3 +35,36 @@ c1
 Ann
 Alice
 DROP TABLE t1, t2, t3, t4, t5;
+create table t1 (c1 varchar(100));
+create table t2 (c1 varchar(100));
+create view t3 as select * from t1;
+insert into t1 values ('ann'), ('alice');
+insert into t2 values ('bob'), ('brian');
+create temporary table t4 (c1 varchar(100)) engine=MERGE union=(t2, t1);
+create temporary table t5 (c1 varchar(100)) engine=MERGE union=(t3, t1);
+select * from t5;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+lock tables t1 read, t2 read, t3 read, t4 read;
+select * from t5;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+select * from t4;
+c1
+bob
+brian
+ann
+alice
+unlock tables;
+drop table t2;
+create view t2 as select * from t1;
+select * from t4;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+lock tables t1 read, t2 read, t3 read;
+select * from t4;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+select * from t4;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+select * from t4;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+unlock tables;
+drop view t2, t3;
+drop table t1;
diff --git a/mysql-test/r/myisam-blob.result b/mysql-test/r/myisam-blob.result
index 43db7c8..6b41a24 100644
--- a/mysql-test/r/myisam-blob.result
+++ b/mysql-test/r/myisam-blob.result
@@ -29,9 +29,11 @@ select length(data) from t1;
 length(data)
 18874368
 alter table t1 modify data blob;
+Warnings:
+Warning	1265	Data truncated for column 'data' at row 1
 select length(data) from t1;
 length(data)
-0
+65535
 drop table t1;
 CREATE TABLE t1 (data BLOB) ENGINE=myisam;
 INSERT INTO t1 (data) VALUES (NULL);
diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result
index 5f81ee5..49adac3 100644
--- a/mysql-test/r/mysql_upgrade.result
+++ b/mysql-test/r/mysql_upgrade.result
@@ -250,7 +250,7 @@ GRANT USAGE ON *.* TO 'user3'@'%'
 GRANT ALL PRIVILEGES ON `roelt`.`test2` TO 'user3'@'%'
 DROP USER 'user3'@'%';
 End of 5.1 tests
-The --upgrade-system-tables option was used, databases won't be touched.
+The --upgrade-system-tables option was used, user tables won't be touched.
 Phase 1/4: Fixing views... Skipped
 Phase 2/4: Fixing table and database names ... Skipped
 Phase 3/4: Checking and upgrading tables... Skipped
diff --git a/mysql-test/r/mysql_upgrade_view.result b/mysql-test/r/mysql_upgrade_view.result
index fa0ea5e..fc174e9 100644
--- a/mysql-test/r/mysql_upgrade_view.result
+++ b/mysql-test/r/mysql_upgrade_view.result
@@ -266,4 +266,19 @@ master-bin.000001	#	Query	#	#	use `test`; REPAIR VIEW `v3`  FROM MYSQL
 master-bin.000001	#	Query	#	#	use `test`; REPAIR VIEW `v4`  FROM MYSQL
 drop table if exists kv;
 drop view v1,v2,v3,v4;
+rename table mysql.event to mysql.ev_bk;
+flush tables;
+The --upgrade-system-tables option was used, user tables won't be touched.
+MySQL upgrade detected
+Phase 1/4: Fixing views from mysql
+test.v1                                            OK
+test.v2                                            OK
+test.v3                                            OK
+Phase 2/4: Fixing table and database names ... Skipped
+Phase 3/4: Checking and upgrading tables... Skipped
+Phase 4/4: Running 'mysql_fix_privilege_tables'
+OK
+drop table mysql.event;
+rename table mysql.ev_bk to mysql.event;
+drop view v1,v2,v3;
 drop table t1;
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 8bcad2a..ef68c06 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1091,7 +1091,7 @@ sysdate-is-now FALSE
 table-cache 400
 table-definition-cache 400
 table-open-cache 400
-tc-heuristic-recover COMMIT
+tc-heuristic-recover OFF
 thread-cache-size 0
 thread-stack 294912
 time-format %H:%i:%s
diff --git a/mysql-test/r/second_frac-9175.result b/mysql-test/r/second_frac-9175.result
new file mode 100644
index 0000000..dbf268b
--- /dev/null
+++ b/mysql-test/r/second_frac-9175.result
@@ -0,0 +1,13 @@
+select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456')
+31622400123456
+explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+Warnings:
+Note	1003	select timestampdiff(MICROSECOND,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') AS `timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456')`
+create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+select * from v1;
+Name_exp_1
+31622400123456
+drop view v1;
diff --git a/mysql-test/r/select_debug.result b/mysql-test/r/select_debug.result
index a056aff..55882ad 100644
--- a/mysql-test/r/select_debug.result
+++ b/mysql-test/r/select_debug.result
@@ -6,7 +6,7 @@ insert into t1 values (2,2), (1,1);
 create table t2 (a int);
 insert into t2 values (2), (3);
 set session join_cache_level=3;
-set @@debug_dbug= 'd:t:O,/tmp/trace.out';
+set @@debug_dbug= 'd,opt';
 explain select t1.b from t1,t2 where t1.b=t2.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
diff --git a/mysql-test/r/set_password_plugin-9835.result b/mysql-test/r/set_password_plugin-9835.result
new file mode 100644
index 0000000..e9ee09f
--- /dev/null
+++ b/mysql-test/r/set_password_plugin-9835.result
@@ -0,0 +1,158 @@
+create user natauth at localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user newpass at localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user newpassnat at localhost identified via 'mysql_native_password';
+set password for newpassnat at localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user oldauth at localhost identified with 'mysql_old_password' using '378b243e220ca493';
+create user oldpass at localhost identified by password '378b243e220ca493';
+create user oldpassold at localhost identified with 'mysql_old_password';
+set password for oldpassold at localhost = '378b243e220ca493';
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+user	host	password	plugin	authentication_string
+natauth	localhost		mysql_native_password	*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
+newpass	localhost	*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29		
+newpassnat	localhost	*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29		
+oldauth	localhost		mysql_old_password	378b243e220ca493
+oldpass	localhost	378b243e220ca493		
+oldpassold	localhost	378b243e220ca493		
+connect con,localhost,natauth,test,;
+select current_user();
+current_user()
+natauth at localhost
+disconnect con;
+connect con,localhost,newpass,test,;
+select current_user();
+current_user()
+newpass at localhost
+disconnect con;
+connect con,localhost,newpassnat,test,;
+select current_user();
+current_user()
+newpassnat at localhost
+disconnect con;
+connect con,localhost,oldauth,test,;
+select current_user();
+current_user()
+oldauth at localhost
+disconnect con;
+connect con,localhost,oldpass,test,;
+select current_user();
+current_user()
+oldpass at localhost
+disconnect con;
+connect con,localhost,oldpassold,test,;
+select current_user();
+current_user()
+oldpassold at localhost
+disconnect con;
+connection default;
+flush privileges;
+connect con,localhost,natauth,test,;
+select current_user();
+current_user()
+natauth at localhost
+disconnect con;
+connect con,localhost,newpass,test,;
+select current_user();
+current_user()
+newpass at localhost
+disconnect con;
+connect con,localhost,newpassnat,test,;
+select current_user();
+current_user()
+newpassnat at localhost
+disconnect con;
+connect con,localhost,oldauth,test,;
+select current_user();
+current_user()
+oldauth at localhost
+disconnect con;
+connect con,localhost,oldpass,test,;
+select current_user();
+current_user()
+oldpass at localhost
+disconnect con;
+connect con,localhost,oldpassold,test,;
+select current_user();
+current_user()
+oldpassold at localhost
+disconnect con;
+connection default;
+set password for natauth at localhost = PASSWORD('test2');
+set password for newpass at localhost = PASSWORD('test2');
+set password for newpassnat at localhost = PASSWORD('test2');
+set password for oldauth at localhost = PASSWORD('test2');
+set password for oldpass at localhost = PASSWORD('test2');
+set password for oldpassold at localhost = PASSWORD('test2');
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+user	host	password	plugin	authentication_string
+natauth	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+newpass	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+newpassnat	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+oldauth	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+oldpass	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+oldpassold	localhost	*7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E		
+connect con,localhost,natauth,test2,;
+select current_user();
+current_user()
+natauth at localhost
+disconnect con;
+connect con,localhost,newpass,test2,;
+select current_user();
+current_user()
+newpass at localhost
+disconnect con;
+connect con,localhost,newpassnat,test2,;
+select current_user();
+current_user()
+newpassnat at localhost
+disconnect con;
+connect con,localhost,oldauth,test2,;
+select current_user();
+current_user()
+oldauth at localhost
+disconnect con;
+connect con,localhost,oldpass,test2,;
+select current_user();
+current_user()
+oldpass at localhost
+disconnect con;
+connect con,localhost,oldpassold,test2,;
+select current_user();
+current_user()
+oldpassold at localhost
+disconnect con;
+connection default;
+flush privileges;
+connect con,localhost,natauth,test2,;
+select current_user();
+current_user()
+natauth at localhost
+disconnect con;
+connect con,localhost,newpass,test2,;
+select current_user();
+current_user()
+newpass at localhost
+disconnect con;
+connect con,localhost,newpassnat,test2,;
+select current_user();
+current_user()
+newpassnat at localhost
+disconnect con;
+connect con,localhost,oldauth,test2,;
+select current_user();
+current_user()
+oldauth at localhost
+disconnect con;
+connect con,localhost,oldpass,test2,;
+select current_user();
+current_user()
+oldpass at localhost
+disconnect con;
+connect con,localhost,oldpassold,test2,;
+select current_user();
+current_user()
+oldpassold at localhost
+disconnect con;
+connection default;
+drop user natauth at localhost, newpass at localhost, newpassnat at localhost;
+drop user oldauth at localhost, oldpass at localhost, oldpassold at localhost;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 962b834..6214fbc 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4413,57 +4413,57 @@ test.t1	repair	status	OK
 test.t2	repair	status	OK
 test.t3	repair	status	OK
 test.v1	repair	Error	'test.v1' is not BASE TABLE
-test.v1	repair	error	Corrupt
+test.v1	repair	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	status	OK
 test.t2	optimize	status	OK
 test.t3	optimize	status	OK
 test.v1	optimize	Error	'test.v1' is not BASE TABLE
-test.v1	optimize	error	Corrupt
+test.v1	optimize	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	analyze	status	Table is already up to date
 test.t2	analyze	status	Table is already up to date
 test.t3	analyze	status	Table is already up to date
 test.v1	analyze	Error	'test.v1' is not BASE TABLE
-test.v1	analyze	error	Corrupt
+test.v1	analyze	status	Operation failed
 call bug13012()|
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
 test.t2	repair	status	OK
 test.t3	repair	status	OK
 test.v1	repair	Error	'test.v1' is not BASE TABLE
-test.v1	repair	error	Corrupt
+test.v1	repair	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	status	OK
 test.t2	optimize	status	OK
 test.t3	optimize	status	OK
 test.v1	optimize	Error	'test.v1' is not BASE TABLE
-test.v1	optimize	error	Corrupt
+test.v1	optimize	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	analyze	status	Table is already up to date
 test.t2	analyze	status	Table is already up to date
 test.t3	analyze	status	Table is already up to date
 test.v1	analyze	Error	'test.v1' is not BASE TABLE
-test.v1	analyze	error	Corrupt
+test.v1	analyze	status	Operation failed
 call bug13012()|
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
 test.t2	repair	status	OK
 test.t3	repair	status	OK
 test.v1	repair	Error	'test.v1' is not BASE TABLE
-test.v1	repair	error	Corrupt
+test.v1	repair	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	status	OK
 test.t2	optimize	status	OK
 test.t3	optimize	status	OK
 test.v1	optimize	Error	'test.v1' is not BASE TABLE
-test.v1	optimize	error	Corrupt
+test.v1	optimize	status	Operation failed
 Table	Op	Msg_type	Msg_text
 test.t1	analyze	status	Table is already up to date
 test.t2	analyze	status	Table is already up to date
 test.t3	analyze	status	Table is already up to date
 test.v1	analyze	Error	'test.v1' is not BASE TABLE
-test.v1	analyze	error	Corrupt
+test.v1	analyze	status	Operation failed
 drop procedure bug13012|
 drop view v1|
 select * from t1 order by data|
diff --git a/mysql-test/r/ssl_cert_verify.result b/mysql-test/r/ssl_cert_verify.result
new file mode 100644
index 0000000..1da7732
--- /dev/null
+++ b/mysql-test/r/ssl_cert_verify.result
@@ -0,0 +1,5 @@
+#T1: Host name (/CN=localhost/) as OU name in the server certificate, server certificate verification should fail.
+#T2: Host name (localhost) as common name in the server certificate, server certificate verification should pass.
+Variable_name	Value
+Ssl_version	TLS_VERSION
+# restart server using restart
diff --git a/mysql-test/r/ssl_timeout-9836.result b/mysql-test/r/ssl_timeout-9836.result
new file mode 100644
index 0000000..bc2e19e
--- /dev/null
+++ b/mysql-test/r/ssl_timeout-9836.result
@@ -0,0 +1,7 @@
+SET @@net_read_timeout=1;
+SELECT 1;
+1
+1
+SELECT 1;
+1
+1
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ba52fd9..16ab4cf 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -7081,3 +7081,16 @@ sq
 NULL
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+# MDEV-7122
+# Assertion `0' failed in subselect_hash_sj_engine::init
+#
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+a
+0
+0
+0
+DROP TABLE t1;
+SET SESSION big_tables=0;
diff --git a/mysql-test/r/subselect_extra_no_semijoin.result b/mysql-test/r/subselect_extra_no_semijoin.result
index 525b80e..b8f1ba7 100644
--- a/mysql-test/r/subselect_extra_no_semijoin.result
+++ b/mysql-test/r/subselect_extra_no_semijoin.result
@@ -349,9 +349,9 @@ WHERE t.a IN (SELECT b FROM t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	1	100.00	
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
-3	MATERIALIZED	t1	system	NULL	NULL	NULL	NULL	1	100.00	
+3	DEPENDENT SUBQUERY	t1	system	NULL	NULL	NULL	NULL	1	100.00	
 Warnings:
-Note	1003	select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery3>`.`b`))))))
+Note	1003	select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0))))
 SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0
 WHERE t.a IN (SELECT b FROM t1);
 a	a	b
@@ -362,9 +362,9 @@ WHERE t.a IN (SELECT b FROM t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	1	100.00	
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
-2	MATERIALIZED	t1	system	NULL	NULL	NULL	NULL	1	100.00	
+2	DEPENDENT SUBQUERY	t1	system	NULL	NULL	NULL	NULL	1	100.00	
 Warnings:
-Note	1003	select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery2>`.`b`))))))
+Note	1003	select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0))))
 DROP VIEW v1;
 DROP TABLE t1,t2;
 #
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index d8d5c4e..aed4fb3 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -7078,6 +7078,19 @@ sq
 NULL
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+# MDEV-7122
+# Assertion `0' failed in subselect_hash_sj_engine::init
+#
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+a
+0
+0
+0
+DROP TABLE t1;
+SET SESSION big_tables=0;
 set optimizer_switch=default;
 select @@optimizer_switch like '%materialization=on%';
 @@optimizer_switch like '%materialization=on%'
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 78908bc..e1f0853 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -7076,4 +7076,17 @@ sq
 NULL
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+# MDEV-7122
+# Assertion `0' failed in subselect_hash_sj_engine::init
+#
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+a
+0
+0
+0
+DROP TABLE t1;
+SET SESSION big_tables=0;
 set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index d1de4b8..b5fa7b1 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -7087,6 +7087,19 @@ sq
 NULL
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+# MDEV-7122
+# Assertion `0' failed in subselect_hash_sj_engine::init
+#
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+a
+0
+0
+0
+DROP TABLE t1;
+SET SESSION big_tables=0;
 set optimizer_switch=default;
 select @@optimizer_switch like '%subquery_cache=on%';
 @@optimizer_switch like '%subquery_cache=on%'
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index 524a5dd..b815559 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -7076,5 +7076,18 @@ sq
 NULL
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+# MDEV-7122
+# Assertion `0' failed in subselect_hash_sj_engine::init
+#
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+a
+0
+0
+0
+DROP TABLE t1;
+SET SESSION big_tables=0;
 set @optimizer_switch_for_subselect_test=null;
 set @join_cache_level_for_subselect_test=NULL;
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index 21acd46..1662d4e 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -2995,4 +2995,69 @@ explain
 select 1 from t1 where _cp932 "1" in (select '1' from t1);
 ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '='
 drop table t1;
+#
+# MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside
+#
+set @tmp_mdev7823=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f2 INT, KEY(f2));
+INSERT INTO t2 VALUES (8),(0);
+CREATE TABLE t3 (f3 INT);
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t4 (f4 INT);
+INSERT INTO t4 VALUES (0),(5);
+explain 
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	t2	ref	f2	f2	5	const	0	Using where; Using index
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	2	Using join buffer (flat, BNL join)
+2	DEPENDENT SUBQUERY	t4	ALL	NULL	NULL	NULL	NULL	2	Using where
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+f1	f2	f3
+1	0	1
+1	0	2
+drop table t1,t2,t3,t4;
+set optimizer_switch= @tmp_mdev7823;
+#
+# MDEV-6859: scalar subqueries in a comparison produced unexpected result
+#
+set @tmp_mdev6859=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (
+project_number varchar(50) NOT NULL,
+PRIMARY KEY (project_number)
+) ENGINE=MyISAM;
+INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb');
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL AUTO_INCREMENT,
+project_number varchar(50) NOT NULL,
+history_date date NOT NULL,
+country varchar(50) NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=MyISAM;
+INSERT INTO t2 (id, project_number, history_date, country) VALUES
+(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore');
+CREATE TABLE t3 (
+region varchar(50) NOT NULL,
+country varchar(50) NOT NULL
+) ENGINE=MyISAM;
+INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france');
+SELECT SQL_NO_CACHE a.project_number 
+FROM t1 a 
+WHERE ( SELECT z.country 
+FROM t2 z 
+WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' 
+ORDER BY z.id DESC LIMIT 1 
+) IN ( 
+SELECT r.country 
+FROM t3 r 
+WHERE r.region = 'eame'
+      );
+project_number
+aaa
+drop table t1, t2, t3;
+set optimizer_switch= @tmp_mdev6859;
 set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index d9aa187..96bae67 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -3009,6 +3009,71 @@ explain
 select 1 from t1 where _cp932 "1" in (select '1' from t1);
 ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '='
 drop table t1;
+#
+# MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside
+#
+set @tmp_mdev7823=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f2 INT, KEY(f2));
+INSERT INTO t2 VALUES (8),(0);
+CREATE TABLE t3 (f3 INT);
+INSERT INTO t3 VALUES (1),(2);
+CREATE TABLE t4 (f4 INT);
+INSERT INTO t4 VALUES (0),(5);
+explain 
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	t2	ref	f2	f2	5	const	0	Using where; Using index
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	2	Using join buffer (flat, BNL join)
+2	DEPENDENT SUBQUERY	t4	ALL	NULL	NULL	NULL	NULL	2	Using where
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+f1	f2	f3
+1	0	1
+1	0	2
+drop table t1,t2,t3,t4;
+set optimizer_switch= @tmp_mdev7823;
+#
+# MDEV-6859: scalar subqueries in a comparison produced unexpected result
+#
+set @tmp_mdev6859=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (
+project_number varchar(50) NOT NULL,
+PRIMARY KEY (project_number)
+) ENGINE=MyISAM;
+INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb');
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL AUTO_INCREMENT,
+project_number varchar(50) NOT NULL,
+history_date date NOT NULL,
+country varchar(50) NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=MyISAM;
+INSERT INTO t2 (id, project_number, history_date, country) VALUES
+(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore');
+CREATE TABLE t3 (
+region varchar(50) NOT NULL,
+country varchar(50) NOT NULL
+) ENGINE=MyISAM;
+INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france');
+SELECT SQL_NO_CACHE a.project_number 
+FROM t1 a 
+WHERE ( SELECT z.country 
+FROM t2 z 
+WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' 
+ORDER BY z.id DESC LIMIT 1 
+) IN ( 
+SELECT r.country 
+FROM t3 r 
+WHERE r.region = 'eame'
+      );
+project_number
+aaa
+drop table t1, t2, t3;
+set optimizer_switch= @tmp_mdev6859;
 set optimizer_switch=@subselect_sj_tmp;
 #
 # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 723efbd..f49b2a7 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -1000,9 +1000,42 @@ COUNT(*)
 DROP FUNCTION f1;
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Start of 5.5 tests
+#
 CREATE TABLE t1 ( f1 blob, f2 blob );
 INSERT INTO t1 VALUES ('','');
 SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ;
 f1	f2	found row
 		found row
 DROP TABLE t1;
+#
+# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+#
+CREATE TABLE t1 (a MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT(0x61,128000));
+SELECT LENGTH(a) FROM t1;
+LENGTH(a)
+128000
+ALTER TABLE t1 MODIFY a BLOB;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT LENGTH(a) FROM t1;
+LENGTH(a)
+65535
+DROP TABLE t1;
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (REPEAT(0x61,65000));
+SELECT LENGTH(a) FROM t1;
+LENGTH(a)
+65000
+ALTER TABLE t1 MODIFY a TINYBLOB;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT LENGTH(a) FROM t1;
+LENGTH(a)
+255
+DROP TABLE t1;
+#
+# End of 5.5 tests
+#
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 4e299ec..7678f03 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -440,3 +440,38 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
 1
 drop table t1;
+#
+# MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
+#
+CREATE TABLE t1 (
+id BIGINT NOT NULL,
+date_debut DATE NOT NULL,
+date_fin DATE DEFAULT NULL);
+CREATE TABLE t2(
+id BIGINT NOT NULL,
+date_debut DATE NOT NULL,
+date_fin DATE DEFAULT NULL);
+INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t1 VALUES (2,'2016-02-01',null);
+INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31');
+INSERT INTO t1 VALUES (4,'2016-04-01',null);
+INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28');
+INSERT INTO t2 VALUES (3,'2016-03-01',null);
+INSERT INTO t2 VALUES (4,'2016-04-01',null);
+SELECT t1.id,
+GREATEST(t2.date_debut, t1.date_debut) AS date_debut,
+LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)),
+IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin
+FROM t1 LEFT JOIN t2 ON (t1.id=t2.id);
+id	date_debut	date_fin
+1	2016-01-01	2016-01-31 00:00:00
+2	2016-02-01	2016-01-28 00:00:00
+3	2016-03-01	2016-03-31 00:00:00
+4	2016-04-01	NULL
+DROP TABLE t1,t2;
+SELECT
+LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0,
+LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1;
+d0	d1
+NULL	NULL
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 52c7f05..1f17247 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -644,4 +644,13 @@ SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1;
 MAX(dt) = '2011-01-06 12:34:30'
 1
 DROP TABLE t1;
+#
+# MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL
+#
+CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1;
+c1	'2016-06-13 20:00:00.000003' >= COALESCE( c1 )
+NULL	NULL
+DROP TABLE t1;
 End of 5.5 tests
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index b008e62..dbfdf3f 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -2422,28 +2422,28 @@ CREATE VIEW v1 AS SELECT id FROM t1;
 OPTIMIZE TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	optimize	Error	'test.v1' is not BASE TABLE
-test.v1	optimize	error	Corrupt
+test.v1	optimize	status	Operation failed
 ANALYZE TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	analyze	Error	'test.v1' is not BASE TABLE
-test.v1	analyze	error	Corrupt
+test.v1	analyze	status	Operation failed
 REPAIR TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	repair	Error	'test.v1' is not BASE TABLE
-test.v1	repair	error	Corrupt
+test.v1	repair	status	Operation failed
 DROP TABLE t1;
 OPTIMIZE TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	optimize	Error	'test.v1' is not BASE TABLE
-test.v1	optimize	error	Corrupt
+test.v1	optimize	status	Operation failed
 ANALYZE TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	analyze	Error	'test.v1' is not BASE TABLE
-test.v1	analyze	error	Corrupt
+test.v1	analyze	status	Operation failed
 REPAIR TABLE v1;
 Table	Op	Msg_type	Msg_text
 test.v1	repair	Error	'test.v1' is not BASE TABLE
-test.v1	repair	error	Corrupt
+test.v1	repair	status	Operation failed
 DROP VIEW v1;
 create definer = current_user() sql security invoker view v1 as select 1;
 show create view v1;
@@ -5512,6 +5512,14 @@ execute stmt;
 deallocate prepare stmt;
 drop view v1,v2;
 drop table `t1`;
+create table t1 (a int, b int);
+create view v1 as select a+b from t1;
+alter table v1 check partition p1;
+Table	Op	Msg_type	Msg_text
+test.v1	check	Error	'test.v1' is not BASE TABLE
+test.v1	check	status	Operation failed
+drop view v1;
+drop table t1;
 # -----------------------------------------------------------------
 # -- End of 5.5 tests.
 # -----------------------------------------------------------------
diff --git a/mysql-test/std_data/ca-cert-verify.pem b/mysql-test/std_data/ca-cert-verify.pem
new file mode 100644
index 0000000..21d6264
--- /dev/null
+++ b/mysql-test/std_data/ca-cert-verify.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDWzCCAkOgAwIBAgIJAO/QdKLEDQdXMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNV
+BAYTAklOMREwDwYDVQQIDAhLYXJuYXRrYTESMBAGA1UEBwwJQmFuZ2Fsb3JlMQ4w
+DAYDVQQKDAVNeVNRTDAeFw0xNjAxMDUxMDA1MDhaFw0yNTExMTMxMDA1MDhaMEQx
+CzAJBgNVBAYTAklOMREwDwYDVQQIDAhLYXJuYXRrYTESMBAGA1UEBwwJQmFuZ2Fs
+b3JlMQ4wDAYDVQQKDAVNeVNRTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKdOCuS2CzfBTJ2x8SAzY0J7cYJfNJvMDF1cvANnhkIhtnkWt/HZ5DJ9NxeX
+q5h7FJLAi4gddqdk/tvQJw0V6gZepJr/mKVnMPivF5+oHPc9ZJQMX6B3FBNwWylm
+ACd5GKx8I/H/MXyuhQTcoV//Ab+2pI8RHeYbBsm3lHH+tX7bRU6mUFjneqMpiCkb
+JHt6BWZiWR10O6pMuGQ9+dDdsLhEV1fj3CctEPwW6rs4IZzD8xl5n+8cy7qu6eYH
+Wt/snwsTzkrufeMRqTtqelxON9eoQwYOR1oH3vNEVlcbuoJAvaWOqBROUBdf12SP
+TYSdP9nlRh7lTKQOywN4kYt6LqUCAwEAAaNQME4wHQYDVR0OBBYEFJ4c9tKaUU0P
+EjBq5G207jjXI7RAMB8GA1UdIwQYMBaAFJ4c9tKaUU0PEjBq5G207jjXI7RAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABRnUyj21oFi0SGJg/K5+8Lc
+4n6OwVU/NgLOysIB0baIP/Rqeaze59xG/v9FPQgBlWcJK3RabOywx5bxAxdcus+1
+yp5j4h37Qq1/qkgqmevvdSAPa0OBQbLb+58/naV+ywUpCYZ6flLdCMH3fXuDSlSq
+qrCznextjojtWbnzrBmCmJmXWGd2gSaJDvb90ZZp/Elt3vN1sgjW0M/JEkb4MJ1r
+6nfD/FHr2lUwBHm2yk7Blovx7x4d/Ip3pglk63cNO/Rn0SBTdoVDS2LB9du3Phq2
+TZiL3NrRMGUNwmdaavyrJxaPq5D+Sfa4LYP3MMYD4KhLogNzIl299n5joyizlJw=
+-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-cert-verify-fail.pem b/mysql-test/std_data/server-cert-verify-fail.pem
new file mode 100644
index 0000000..4203425
--- /dev/null
+++ b/mysql-test/std_data/server-cert-verify-fail.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDJzCCAg8CAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCSU4xETAPBgNV
+BAgMCEthcm5hdGthMRIwEAYDVQQHDAlCYW5nYWxvcmUxDjAMBgNVBAoMBU15U1FM
+MB4XDTE2MDEwNTEwMDgyN1oXDTI1MTExMzEwMDgyN1owbzELMAkGA1UEBhMCSU4x
+EjAQBgNVBAgMCTpLYXJuYXRrYTETMBEGA1UEBwwKOkJhbmdhbG9yZTEPMA0GA1UE
+CgwGOk15U1FMMRcwFQYDVQQLDA4vQ049bG9jYWxob3N0LzENMAsGA1UEAwwEZmFp
+bDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3wnWuJodzZYq9TAJRm
+HU7995FA3TEWdUinYTgGP79aTVQ4M9aeINlB6whWXOI8seh9Ja7C6kMzqOgYbgCl
+WlDPAVJWktFYeWXOLxbpzh1KWkS6jBkWT02t7H7JcYbil7xjlJUxLz4UOOUDUDIP
+6yqdA9VE3osESttjzj57Zm2xPqzbIHVJfORn7EexH4pryS7439p6i4XtfL31NJ8V
+07M3j3a8GqbcEqXYvcUCrLnywDQ1igP817b6ta52nbgYWiqdn0mJs535UJ/p/rSl
+D4Ae/6G3BSEY7whir6xY6vsd4KJ6w+wRCHnY0ky6OdDJVJLH1iqh7si7P3RBGkxw
+Y7MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAggbw1jj2b7H5KDdeGJGIoOGkQAcs
+GNSJussCfdk7qnzYXKmjyNppC86jjaOrXona5f+SNCuujdu86Tv8V69EH57k4lUc
+DW7J4AD3vUb/tBzB0tsI/76Z4gm1XoCsnCGGpWd8GQAg/QNn/ZfJB2Vb/9ObN6rH
+0HV7ouB6OGZSsb71+grKiN6mDyB1lZynCGvqBxOCKFISfcRbCNFHo/pONlHaNGPE
+vjDH1bPZbEHj8owYgkdcQe0a8EbJYeQfm6fH8V8bmUcG7N60DrCnq4l1qwwVkh1S
+7RpIDgrWkU+esIIdYZIIbtDxQP1Sm7kUh++7b+bcHnyw3KtDVSCw7MIedA==
+-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-cert-verify-pass.pem b/mysql-test/std_data/server-cert-verify-pass.pem
new file mode 100644
index 0000000..f8780f1
--- /dev/null
+++ b/mysql-test/std_data/server-cert-verify-pass.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAfsCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCSU4xETAPBgNV
+BAgMCEthcm5hdGthMRIwEAYDVQQHDAlCYW5nYWxvcmUxDjAMBgNVBAoMBU15U1FM
+MB4XDTE2MDEwNTEwMDU1OVoXDTI1MTExMzEwMDU1OVowWzELMAkGA1UEBhMCSU4x
+EjAQBgNVBAgMCTpLYXJuYXRrYTETMBEGA1UEBwwKOkJhbmdhbG9yZTEPMA0GA1UE
+CgwGOk15U1FMMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDAmkbUwDe+nrqL8A8uwlIZk74HHCDjUAWrskKF9leEIQsB
+5exFZ8JEo1u6mdR4laQWsxizGdTPqIEidkDyyEMh4+joHgyQEPD/G3rFVW8yEFHb
+42O04O96BEPFXNPDRuX3MxI+lGbYDjxTS/WhVub4/3SqLjC28FJmEUXIHA0/A+c5
+hlYXK0u+aPAqXxHIjBgB4BxxHXZKqecmvR3LhXoVmhJmndsVfKajB27nDKc8/OTI
+H2SXb6h3nRPDXRfwB/C5i+004tEsVeIgkYshcCgLSyDdeVieUP2pm3EAmDSjmtLF
+6CgY/EBSfH+JCKFUk75bA4k8CCGzBfIeOcsKHwgFAgMBAAEwDQYJKoZIhvcNAQEL
+BQADggEBAInDuHtDkeT6dkWmRJCP56c4xiQqib2QuYUuMSrAhf07xlLHc6iHnD2X
+hCWCrja6uwF90DnPjeouKMAUe5txq/uKA8/Y/NfXN6nPiAeHLI0qnTv7Mr9TQ8zU
+DNDwRz6onlI2cS4GhrwAnlpiaxu7AjMUWHtfBFGFrgn3PawjDQpsBZNcxw1QsLc0
+E0hFrWLOd0vDETEhoRge88N7a0jqK0Rd9cvRWnvjI+IsjQMLZzKufivIHPzI9K+9
+Wtp8iRHcaBr5DpsBjgsO7dqVRbsNyaWsdHdLt+CQSGXpv7P6fq3K6nJFTBeIgSfS
+gflrHVKYZRkKDDDpX4yHNdnIqrvy4RU=
+-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-key-verify-fail.pem b/mysql-test/std_data/server-key-verify-fail.pem
new file mode 100644
index 0000000..af1ae1e
--- /dev/null
+++ b/mysql-test/std_data/server-key-verify-fail.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAvfCda4mh3Nlir1MAlGYdTv33kUDdMRZ1SKdhOAY/v1pNVDgz
+1p4g2UHrCFZc4jyx6H0lrsLqQzOo6BhuAKVaUM8BUlaS0Vh5Zc4vFunOHUpaRLqM
+GRZPTa3sfslxhuKXvGOUlTEvPhQ45QNQMg/rKp0D1UTeiwRK22POPntmbbE+rNsg
+dUl85GfsR7EfimvJLvjf2nqLhe18vfU0nxXTszePdrwaptwSpdi9xQKsufLANDWK
+A/zXtvq1rnaduBhaKp2fSYmznflQn+n+tKUPgB7/obcFIRjvCGKvrFjq+x3gonrD
+7BEIedjSTLo50MlUksfWKqHuyLs/dEEaTHBjswIDAQABAoIBAQCSUyNzDPydXvsf
+hhoUOParPAvU4tuETYDdD9Vdi7Lgf3jDQOjulbNIq/ec3KuBvrBwIrk9APvn+YxO
+AUP9S2Vgi5jBDeDdVgNv4n90b3pSJk2UVQJI8V72wN5Ibnf/KeErSKvWo6V5daq/
+AuZtKsZIdd3WFtA62HuyuBjTGc23Alj1C0EKnN0Rx1uBwDvx/OVQ266Us/x8jJqW
+ZxIOfcvfNzBQEa5hAzbQCReVaC+rBLRAcMM2yGP7aDa+8cRkwuVlSqpX8CXBdLoU
+PqmU49etcW72Rb1AFt9WgEu1Oh9UYbHFSB+FEbO8IGcGBsuYHf9zkxQyjpy/iKyT
+H5dTu7YBAoGBAOWqEGepZVrfB+P6X18n3vbJhgYmF0sa0mCmwkFYgk36yNqsZ8at
+lQjm5mbn4wjEKHIcQ/T1taq73W471M+PxMnn0WTwoG5jsyarZGgy6/95YXiyZtQe
+qgA4P3aKkCteRP22DjG7uxmm9Hoqx8Z31vfRTLAHN1IEHPHHkg/J3gPTAoGBANO4
+aqKeY4vcDvVkvxVbADrw++tZGwA+RuxfO4HKKru59VdA2PsAxhXwb3Dfejwj7hYW
+yE9edHjGpMr1+dpf8YJYs7qjajHe1HxBOYqQGHycIdw+Gv56R4HpaS9eW3x8l/Pi
+b4xnAodv2qIriACOe7br+rll4wKX46Wt64zdvpShAoGAT0r3HQM0Vjp4u/J+qRjX
+9za+yjKuiiS5i9snaG5JlujGHhG2Rrc5pHgsBk17alRnbnZp1BJdZZQ1MFEB+aO2
+mssp1YLqsRJFEU3NfdhO+MaMq6JUtFnd8fN5ndDbU83ZXgtUPUGGqKWm9OL+VHyd
+wLQHmSL0q6F16Ngxirf0qjcCgYEAtSmiJVA+gdhk/FmeoBlkEwtNpM50Kjsf2PaM
+Jrzk4Al5A5Y7lFvPI8q+sOio4XklKsWH1VJPe2EOdZUQnGlocE6SS+u03MN9Mm1l
+XUl7inTXDGwgEQx0z5b4KE4nHlhGdauWI5+pLFbrz8RL9Z32AkneGnIyU2/AnW46
+lijQAMECgYEAmgp/88ndIw49RCtMhYhtXQ87AsEAP6kzXQyKppDkn0os+xI5igIL
+i/UDxB33hx3yjrUZwoGDV9MwlMhZNX5Tf5bwjPmmh1NR6KdEpPt5AkklX4s6uil2
+Bxl1P5l1jl/PbEYtv5LDZKIPANWRzViMSIWqjUWlbdqE7/vjx+Oo+cc=
+-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/std_data/server-key-verify-pass.pem b/mysql-test/std_data/server-key-verify-pass.pem
new file mode 100644
index 0000000..7ecc44f
--- /dev/null
+++ b/mysql-test/std_data/server-key-verify-pass.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAwJpG1MA3vp66i/APLsJSGZO+Bxwg41AFq7JChfZXhCELAeXs
+RWfCRKNbupnUeJWkFrMYsxnUz6iBInZA8shDIePo6B4MkBDw/xt6xVVvMhBR2+Nj
+tODvegRDxVzTw0bl9zMSPpRm2A48U0v1oVbm+P90qi4wtvBSZhFFyBwNPwPnOYZW
+FytLvmjwKl8RyIwYAeAccR12SqnnJr0dy4V6FZoSZp3bFXymowdu5wynPPzkyB9k
+l2+od50Tw10X8AfwuYvtNOLRLFXiIJGLIXAoC0sg3XlYnlD9qZtxAJg0o5rSxego
+GPxAUnx/iQihVJO+WwOJPAghswXyHjnLCh8IBQIDAQABAoIBAHPQUSc9LkgBSks7
+XuXPE28t1+aOk3gcdkx4NGg5aQaal/PcPea+LaL4WAAs4AZidPjxWLjZn43+1SfT
+09opcbS/Rx3Mc+FtTn0YGQrwBJ0mExMV+K6bU2Ubi2TyHKQfzciHfUEEG5Nve/ba
+hikuCFVRxuVOQRzABcw6NqvNsmlg892lfw6/+RDwMBcz7ocwzmiOUoIxgjyFo9G4
+aJvRmHLij5892H6qveik+A/Xr+8leGQHiQET2wW/F9MFP5ypIT7aeE6remeZH7fG
+f4/Zfei/TE4xK2ElNR/91byzeKIVY4vjtTndAiBuqpfYuICb40MC02LNW5Oe6VN2
+3mQ6EgECgYEA7O4ndBnbs/00gyTGyNg6I+3wRTibhNH4R8RZFJiLfKRKOlUiLhUo
++bQeO4bCQ6YY++TYDvMEXTlA3jow9R9Mj2AWc6bNmQmJd/065QyFHftywT66I+V4
+rz1ohSJyHXcv4DxqNk3o3Vb4N8GFjZKcodSgTv2Lk+9ipDYFcQiZop0CgYEA0BrF
+SIyLTnjoVht/7RbIGEqhMQUiz5mx7qQ1TPB+YTG77G2xXJNg5d6S7WT4LN+cqbxN
+YdndIbW4NdV7bH7FlG9q7jfkuZ+AY2BPU047tcDeyO0HYYEhVY+EyZqHci/26mvt
+JrawdqS5HQS1y/rKfytm7YBGTvqoNZHvOHc6aokCgYEAxcjlbJkte+pyzMuFmiJP
+HrFBczeXM+BoJ9j0GCpjvvAS+vEYsGl/pDvFRSHwx7I/hv/5kTkzOnNSAHGJbwbq
+zYGEHJVxakC43k6pvI2gDnBa0pD/qHmmLnvP5dvkcU6Oy90DOUP+kc9JNJo7V/y8
+/qdWD7q+qwcaTETAdCSexE0CgYA/DN1Y7bwHOnqqHArWOmDFe1b7EyNI4rgWJYpA
+lVy09eyJ5XInKj/hZV3+rujCL723b2XCj89/tx7osJWEeaRDJL6xDh4uXzT25uch
+xkIw/w6Asc/aqtT+p00EB92hqwaUX76qTA+K4r1zHUo3UvSnMu8sZgDnTOpJ0L05
+zmXUgQKBgDT+IFrAzOty4B0mJncTCC/TulpW704bEZwNJfQSdtiBQr/vqoXygBQc
+bHfpncpSfhzHB5lhRUv02TqXgl53D70nM7JD5nx98WYTTBxsbvxPlt4gBRZkfgq5
+tHKclAArc1SbfW5Z8oYyl7h33LQJK116QSyiIIGieH5VXNPwnqUs
+-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm
index d328518..15615c4 100644
--- a/mysql-test/suite.pm
+++ b/mysql-test/suite.pm
@@ -35,7 +35,7 @@ sub skip_combinations {
     return 0 unless socket my $sock, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
     # eval{}, if there's no Socket::sockaddr_in6 at all, old Perl installation
     eval { connect $sock, sockaddr_in6(7, Socket::IN6ADDR_LOOPBACK) };
-    return $! != 101;
+    return $@ eq "";
   }
   $skip{'include/check_ipv6.inc'} = 'No IPv6' unless ipv6_ok();
 
diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result
index ba160aa..109328d 100644
--- a/mysql-test/suite/binlog/r/binlog_row_binlog.result
+++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result
@@ -662,7 +662,7 @@ master-bin.000001	#	Query	#	#	use `test`; CREATE TABLE IF NOT EXISTS `t2` (
 master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; CREATE TABLE IF NOT EXISTS `t3` (
   `a` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
 master-bin.000001	#	Query	#	#	BEGIN
 master-bin.000001	#	Table_map	#	#	table_id: # (mysql.user)
 master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
diff --git a/mysql-test/suite/innodb/r/innodb-dict.result b/mysql-test/suite/innodb/r/innodb-dict.result
new file mode 100644
index 0000000..e3b2f0d
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-dict.result
@@ -0,0 +1,40 @@
+CREATE TABLE t1 (D INT) ENGINE=innodb;
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 MODIFY COLUMN d INT;
+ALTER TABLE t1 ADD INDEX my_d (d);
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `d` int(11) DEFAULT NULL,
+  KEY `my_d` (`d`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+EXPLAIN SELECT d FROM t1 WHERE d = 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	my_d	my_d	5	const	128	Using index
+EXPLAIN SELECT D FROM t1 WHERE D = 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	my_d	my_d	5	const	128	Using index
+ALTER TABLE t1 DROP INDEX my_d;
+ALTER TABLE t1 MODIFY COLUMN D INT;
+ALTER TABLE t1 ADD INDEX my_d (D);
+EXPLAIN SELECT d FROM t1 WHERE d = 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	my_d	my_d	5	const	128	Using index
+EXPLAIN SELECT D FROM t1 WHERE D = 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	my_d	my_d	5	const	128	Using index
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `D` int(11) DEFAULT NULL,
+  KEY `my_d` (`D`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/innodb-dict.test b/mysql-test/suite/innodb/t/innodb-dict.test
new file mode 100644
index 0000000..25a2845
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-dict.test
@@ -0,0 +1,31 @@
+--source include/have_innodb.inc
+
+#
+# Fix MySQL Bug#20755615: InnoDB compares column names case sensitively,
+# while according to Storage Engine API column names should be compared
+# case insensitively. This can cause FRM and InnoDB data dictionary to
+# go out of sync:
+#
+
+CREATE TABLE t1 (D INT) ENGINE=innodb;
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 MODIFY COLUMN d INT;
+ALTER TABLE t1 ADD INDEX my_d (d);
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+EXPLAIN SELECT d FROM t1 WHERE d = 5;
+EXPLAIN SELECT D FROM t1 WHERE D = 5;
+ALTER TABLE t1 DROP INDEX my_d;
+ALTER TABLE t1 MODIFY COLUMN D INT;
+ALTER TABLE t1 ADD INDEX my_d (D);
+EXPLAIN SELECT d FROM t1 WHERE d = 5;
+EXPLAIN SELECT D FROM t1 WHERE D = 5;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_install.result b/mysql-test/suite/plugins/r/feedback_plugin_install.result
index c52fdb8..ee74435 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_install.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_install.result
@@ -8,6 +8,7 @@ select * from information_schema.feedback where variable_name like 'feed%'
 VARIABLE_NAME	VARIABLE_VALUE
 FEEDBACK used	1
 FEEDBACK version	1.1
+FEEDBACK_HTTP_PROXY	
 FEEDBACK_SEND_RETRY_WAIT	60
 FEEDBACK_SEND_TIMEOUT	60
 FEEDBACK_URL	http://mariadb.org/feedback_plugin/post
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result
index e2cf324..ee433fe 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_load.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result
@@ -10,6 +10,7 @@ select * from information_schema.feedback where variable_name like 'feed%'
        and variable_name not like '%debug%';
 VARIABLE_NAME	VARIABLE_VALUE
 FEEDBACK version	1.1
+FEEDBACK_HTTP_PROXY	
 FEEDBACK_SEND_RETRY_WAIT	60
 FEEDBACK_SEND_TIMEOUT	60
 FEEDBACK_URL	http://mariadb.org/feedback_plugin/post
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result
index 1037867..881a5aa 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_send.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result
@@ -10,6 +10,7 @@ select * from information_schema.feedback where variable_name like 'feed%'
        and variable_name not like '%debug%';
 VARIABLE_NAME	VARIABLE_VALUE
 FEEDBACK version	1.1
+FEEDBACK_HTTP_PROXY	
 FEEDBACK_SEND_RETRY_WAIT	60
 FEEDBACK_SEND_TIMEOUT	60
 FEEDBACK_URL	http://mariadb.org/feedback_plugin/post
diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result
index 69c9bc3..6733850 100644
--- a/mysql-test/suite/plugins/r/server_audit.result
+++ b/mysql-test/suite/plugins/r/server_audit.result
@@ -8,6 +8,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	
+server_audit_loc_info	
 server_audit_logging	OFF
 server_audit_mode	0
 server_audit_output_type	file
@@ -71,6 +72,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	odin, root, dva, tri
+server_audit_loc_info	
 server_audit_logging	ON
 server_audit_mode	0
 server_audit_output_type	file
@@ -216,6 +218,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	odin, root, dva, tri
+server_audit_loc_info	
 server_audit_logging	ON
 server_audit_mode	1
 server_audit_output_type	file
@@ -229,9 +232,9 @@ Warnings:
 Warning	1620	Plugin is busy and will be uninstalled on shutdown
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0
 TIME,HOSTNAME,root,localhost,ID,0,CONNECT,mysql,,0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,mysql,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,no_such_user,localhost,ID,0,FAILED_CONNECT,,,ID
-TIME,HOSTNAME,no_such_user,localhost,ID,0,DISCONNECT,,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0
 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t2,
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t2 (id int)',0
@@ -281,7 +284,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result
index 69c9bc3..6733850 100644
--- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result
+++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result
@@ -8,6 +8,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	
+server_audit_loc_info	
 server_audit_logging	OFF
 server_audit_mode	0
 server_audit_output_type	file
@@ -71,6 +72,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	odin, root, dva, tri
+server_audit_loc_info	
 server_audit_logging	ON
 server_audit_mode	0
 server_audit_output_type	file
@@ -216,6 +218,7 @@ server_audit_file_rotate_now	OFF
 server_audit_file_rotate_size	1000000
 server_audit_file_rotations	9
 server_audit_incl_users	odin, root, dva, tri
+server_audit_loc_info	
 server_audit_logging	ON
 server_audit_mode	1
 server_audit_output_type	file
@@ -229,9 +232,9 @@ Warnings:
 Warning	1620	Plugin is busy and will be uninstalled on shutdown
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0
 TIME,HOSTNAME,root,localhost,ID,0,CONNECT,mysql,,0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,mysql,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,no_such_user,localhost,ID,0,FAILED_CONNECT,,,ID
-TIME,HOSTNAME,no_such_user,localhost,ID,0,DISCONNECT,,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0
 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t2,
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t2 (id int)',0
@@ -281,7 +284,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
+TIME,HOSTNAME,,,ID,0,DISCONNECT,,,0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
diff --git a/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result b/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result
new file mode 100644
index 0000000..b03c005
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result
@@ -0,0 +1,29 @@
+include/master-slave.inc
+[connection master]
+Test case 1:- table name with one character latin name.
+SET @s:=CONCAT("CREATE TABLE `",REPEAT(CHAR(131),1),"` (a INT)");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("INSERT INTO `",REPEAT(CHAR(131),1),"` VALUES (1)");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("DROP TABLE `",REPEAT(CHAR(131),1), "`");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+Test case 2:- table name and database names with one character latin name.
+SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("CREATE TABLE `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1),"` (a INT)");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("INSERT INTO `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1),"` VALUES (1)");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("DROP TABLE `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1), "`");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`");
+PREPARE STMT FROM @s;
+EXECUTE stmt;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_killed_ddl.result b/mysql-test/suite/rpl/r/rpl_killed_ddl.result
index a02c9b5..ed8745c 100644
--- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result
+++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result
@@ -56,6 +56,10 @@ CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100;
 CREATE DATABASE d2;
 source include/kill_query.inc;
 include/rpl_diff.inc
+ALTER DATABASE d1
+DEFAULT CHARACTER SET = 'utf8';
+source include/kill_query.inc;
+include/rpl_diff.inc
 DROP DATABASE d1;
 source include/kill_query.inc;
 include/rpl_diff.inc
@@ -83,6 +87,9 @@ include/rpl_diff.inc
 DROP FUNCTION f1;
 source include/kill_query.inc;
 include/rpl_diff.inc
+DROP FUNCTION IF EXISTS f2;
+source include/kill_query.inc;
+include/rpl_diff.inc
 CREATE PROCEDURE p2 (OUT rows INT)
 BEGIN
 SELECT COUNT(*) INTO rows FROM t2;
@@ -96,6 +103,9 @@ include/rpl_diff.inc
 DROP PROCEDURE p1;
 source include/kill_query.inc;
 include/rpl_diff.inc
+DROP PROCEDURE IF EXISTS p2;
+source include/kill_query.inc;
+include/rpl_diff.inc
 CREATE TABLE t2 (b int);
 source include/kill_query.inc;
 include/rpl_diff.inc
diff --git a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
index c61167e..3b2e02b 100644
--- a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
+++ b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
@@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
 CREATE TABLE t2 (a int) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (1), (2), (3);
 INSERT INTO t2 VALUES (4), (5), (6);
-CREATE TABLE IF NOT EXISTS t1_merge LIKE t1;
-ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
+ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TABLE t1_merge LIKE tt1_merge;
 include/diff_tables.inc [master:test.t1, slave:test.t1]
 include/diff_tables.inc [master:test.t2, slave:test.t2]
 UPDATE t1_merge SET a=10 WHERE a=1;
diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result
new file mode 100644
index 0000000..4a5bc3b
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result
@@ -0,0 +1,13 @@
+include/master-slave.inc
+[connection master]
+CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE t1 LIKE temp_t1;
+CREATE TABLE t2 LIKE temp_t2;
+include/assert.inc ["t1 on master and temp_t1 have the same storage engine"]
+include/assert.inc ["t2 on master and temp_t2 have the same storage engine"]
+include/assert.inc ["t1 on slave and temp_t1 have the same storage engine"]
+include/assert.inc ["t2 on slave and temp_t2 have the same storage engine"]
+DROP TEMPORARY TABLE temp_t1, temp_t2;
+DROP TABLE t1, t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_unsafe_statements.result b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result
new file mode 100644
index 0000000..2efb3eb
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result
@@ -0,0 +1,53 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TRIGGER trig1 AFTER INSERT ON t1
+FOR EACH ROW
+INSERT INTO t2(i) VALUES(new.i);
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+INSERT INTO t1(i) VALUES(2);
+START TRANSACTION;
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t1(i) VALUES(3);
+UNLOCK TABLES;
+COMMIT;
+include/diff_tables.inc [master:t1, slave:t1]
+include/diff_tables.inc [master:t2, slave:t2]
+DROP TABLE t1,t2;
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+INSERT INTO t1 values (1), (2), (3);
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+INSERT INTO t2(i) SELECT i FROM t1;
+START TRANSACTION;
+LOCK TABLES t2 WRITE, t1 READ;
+INSERT INTO t2(i) SELECT i FROM t1;
+UNLOCK TABLES;
+COMMIT;
+include/diff_tables.inc [master:t1, slave:t1]
+include/diff_tables.inc [master:t2, slave:t2]
+DROP TABLE t1,t2;
+CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM;
+INSERT INTO t1 (i) values (1);
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i) values (2);
+UNLOCK TABLES;
+COMMIT;
+include/diff_tables.inc [master:t1, slave:t1]
+DROP TABLE t1;
+CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB;
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+UNLOCK TABLES;
+COMMIT;
+include/diff_tables.inc [master:t1, slave:t1]
+DROP TABLE t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test
new file mode 100644
index 0000000..a93fcba
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test
@@ -0,0 +1,87 @@
+###############################################################################
+# Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK
+#
+# Problem:
+# ========
+# 1) Drop table queries are re-generated by server
+#    before writing the events(queries) into binlog
+#    for various reasons. If table name/db name contains
+#    a non regular characters (like latin characters),
+#    the generated query is wrong. Hence it breaks the
+#    replication.
+# 2) In the edge case, when table name contains
+#    64 latin characters (latin takes 2 bytes), server is
+#    throwing an assert (M_TBLLEN < 128)
+#
+# 3) In the edge case, when db name contains 64 latin
+#    characters, binlog contents are interpreted wrongly
+#    which is leading to replication issues.
+#
+###############################################################################
+
+--source include/not_windows.inc
+--source include/master-slave.inc
+
+--let iter=1
+# Change iteration to 4 after fixing Bug #22280214
+while ($iter <= 2)
+{
+  --connection master
+  if ($iter == 1)
+  {
+    --echo Test case 1:- table name with one character latin name.
+    --let $tblname= REPEAT(CHAR(131),1)
+  }
+  if ($iter == 2)
+  {
+    --echo Test case 2:- table name and database names with one character latin name.
+    --let $tblname= REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1)
+    --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`")
+    PREPARE STMT FROM @s; EXECUTE stmt;
+  }
+  # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING
+  # IDENTIFIER MAX LENGTH,  the following two tests (iter 3 and 4) can be
+  # uncommented.
+  #if ($iter == 3)
+  #{
+    # --echo Test case 3:- table name and database names with 64 latin characters name.
+    # --let $tblname= REPEAT(CHAR(131),64),"`.`", REPEAT(CHAR(131),64)
+    # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),64),"`")
+    # PREPARE STMT FROM @s; EXECUTE stmt;
+  #}
+  #if ($iter == 4)
+  #{
+    # --echo Test case 4:- table name and database names with 64 Euro(€) characters.
+    # --let $tblname= REPEAT(CHAR(226,130,172),64),"`.`", REPEAT(CHAR(226,130,172),64)
+    # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(226,130,172),64),"`")
+    # PREPARE STMT FROM @s; EXECUTE stmt;
+  #}
+  --eval SET @s:=CONCAT("CREATE TABLE `",$tblname,"` (a INT)")
+  PREPARE STMT FROM @s; EXECUTE stmt;
+  --eval SET @s:=CONCAT("INSERT INTO `",$tblname,"` VALUES (1)")
+  PREPARE STMT FROM @s; EXECUTE stmt;
+  --eval SET @s:=CONCAT("DROP TABLE `",$tblname, "`")
+  PREPARE STMT FROM @s; EXECUTE stmt;
+  if ($iter == 2)
+  {
+    --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`")
+    PREPARE STMT FROM @s; EXECUTE stmt;
+  }
+  # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING
+  # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be
+  # uncommented.
+  #if ($iter == 3)
+  #{
+     # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),64),"`")
+     # PREPARE STMT FROM @s; EXECUTE stmt;
+  #}
+  #if ($iter == 4)
+  #{
+     # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(226,130,172),64),"`")
+     # PREPARE STMT FROM @s; EXECUTE stmt;
+  #}
+  --sync_slave_with_master
+  --inc $iter
+}
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
index eff0392..a910ab4 100644
--- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test
+++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
@@ -26,10 +26,8 @@
 #
 # There are some part of the test are temporarily disabled because of
 # the following bugs, please enable then once they get fixed:
-#  - BUG#44041
-#  - BUG#43353
-#  - BUG#25705
-#  - BUG#44171
+#  - BUG#22473427
+#  - Bug#22587377
 
 # Temporarily disabled on Windows due to bug #47638 
 --source include/not_windows.inc
@@ -148,11 +146,9 @@ let $rpl_diff_statement= SELECT schema_name FROM information_schema.schemata
 send CREATE DATABASE d2;
 source include/kill_query_and_diff_master_slave.inc;
 
-# Temporarily disabled, see BUG#44041, the ALTER DATABASE can affect the
-# collation of other database on slave
-#send ALTER DATABASE d1
-#       DEFAULT CHARACTER SET = 'utf8';
-#source include/kill_query_and_diff_master_slave.inc;
+send ALTER DATABASE d1
+       DEFAULT CHARACTER SET = 'utf8';
+source include/kill_query_and_diff_master_slave.inc;
 
 send DROP DATABASE d1;
 source include/kill_query_and_diff_master_slave.inc;
@@ -171,8 +167,8 @@ send CREATE EVENT e2
   DO INSERT INTO test.t1 VALUES (2);
 source include/kill_query_and_diff_master_slave.inc;
 
-# Temporarily disabled because of BUG#44171, killing ALTER EVENT can
-# crash the server
+# Temporarily disabled,see Bug#22587377-RPL.RPL_KILLED_DDL
+# FAILS SPORADICALLY ON PB2 IN 5.5 AND 5.6
 #send ALTER EVENT e1
 #  ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY;
 #source include/kill_query_and_diff_master_slave.inc;
@@ -201,16 +197,8 @@ source include/kill_query_and_diff_master_slave.inc;
 
 # function f2 probably does not exist because the CREATE query was
 # killed
-#
-# Temporarily disabled. Because of BUG#43353, KILL the query may
-# result in function not found, and for 5.1, DROP statements will be
-# logged if the function is not found on master, so the following DROP
-# FUNCTION statement may be interrupted and not drop the function on
-# master, but still get logged and executed on slave and cause
-# inconsistence. Also disable the following DROP PROCEDURE IF EXITS
-# below.
-#send DROP FUNCTION IF EXISTS f2;
-#source include/kill_query_and_diff_master_slave.inc;
+send DROP FUNCTION IF EXISTS f2;
+source include/kill_query_and_diff_master_slave.inc;
 
 ######## PROCEDURE ########
 
@@ -231,9 +219,8 @@ source include/kill_query_and_diff_master_slave.inc;
 send DROP PROCEDURE p1;
 source include/kill_query_and_diff_master_slave.inc;
 
-# Temporarily disabled because of bug#43353, see comment above for DROP FUNCTION IF EXISTS
-#send DROP PROCEDURE IF EXISTS p2;
-#source include/kill_query_and_diff_master_slave.inc;
+send DROP PROCEDURE IF EXISTS p2;
+source include/kill_query_and_diff_master_slave.inc;
 
 ######## TABLE ########
 
@@ -261,9 +248,10 @@ source include/kill_query_and_diff_master_slave.inc;
 
 ######## SERVER ########
 
-# Tempoarily disabled, see bug#25705
+# Temporarily disabled, see Bug #22473427 - DROP SERVER FAILS
+# AFTER ALTER SERVER+KILL QUERY
 
-# --let $rpl_diff_statement= SELECT * FROM mysql.server WHERE name like \'s%\'
+# --let $rpl_diff_statement= SELECT * FROM mysql.servers WHERE Server_name like \'s%\'
 
 # send CREATE SERVER s2
 #     FOREIGN DATA WRAPPER mysql
diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
index 5add8dc..dcbb8b8 100644
--- a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
+++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
@@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
 CREATE TABLE t2 (a int) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (1), (2), (3);
 INSERT INTO t2 VALUES (4), (5), (6);
-CREATE TABLE IF NOT EXISTS t1_merge LIKE t1;
-ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1);
+# Changed a little to check also an issue reported on BUG#20574550
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
+ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TABLE t1_merge LIKE tt1_merge;
 
 --sync_slave_with_master
 
diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
new file mode 100644
index 0000000..1a09b68
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
@@ -0,0 +1,55 @@
+source include/have_innodb.inc;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+#
+# BUG#20574550
+# CREATE TABLE LIKE <TEMP_TABLE> does not preserve original table storage
+# engine when using row based replication
+#
+--connection master
+
+# Define temp_t1 and temp_t2 storage engines
+--let $engine_temp_t1= InnoDB
+--let $engine_temp_t2= MyISAM
+
+# Create the two temporary tables
+--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1
+--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2
+
+# Create t1 and t2 based on temporary tables
+CREATE TABLE t1 LIKE temp_t1;
+CREATE TABLE t2 LIKE temp_t2;
+--sync_slave_with_master
+
+# On master
+--connection master
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on master and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on master and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# On slave
+--connection slave
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on slave and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on slave and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# Cleanup
+--connection master
+DROP TEMPORARY TABLE temp_t1, temp_t2;
+DROP TABLE t1, t2;
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test
new file mode 100644
index 0000000..cbb4b54
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test
@@ -0,0 +1,176 @@
+################################################################################
+# Bug#17047208 REPLICATION DIFFERENCE FOR MULTIPLE TRIGGERS
+# Problem: If DML invokes a trigger or a stored function that inserts into an
+# AUTO_INCREMENT column, that DML has to be marked as 'unsafe' statement. If the
+# tables are locked in the transaction prior to DML statement (using LOCK
+# TABLES), then the DML statement is not marked as 'unsafe' statement.
+
+# Steps to reproduce the reported test case (BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS)
+# Case-1:
+#  > Create a trigger on a table and do a insert in the trigger that updates
+#     auto increment column
+#  > A DML that executes the trigger in step.1 and check that DML is marked
+#     as unsafe and DML is written into binlog using row format (in MBR)
+#  > Execute the step 2 by locking the required tables prior to DML and check
+#     that DML is marked as unsafe and DML is written into binlog using row
+#     format (in MBR)
+#
+#  This test script also adds test cases to cover few other unsafe statements.
+#    Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT
+#    Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST
+#    Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS
+################################################################################
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS
+#  Statement is unsafe because it invokes a trigger or a
+#  stored function that inserts into an AUTO_INCREMENT column.
+
+# Step-1.1: Create two tables, one with AUTO_INCREMENT column.
+CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+
+# Step-1.2: Create a trigger that inserts into an AUTO_INCREMENT column.
+CREATE TRIGGER trig1 AFTER INSERT ON t1
+FOR EACH ROW
+  INSERT INTO t2(i) VALUES(new.i);
+
+# Step-1.3: Create some gap in auto increment value on master's t2 table
+# but not on slave (by doing rollback). Just in case if the unsafe statements
+# are written in statement format, diff tables will fail.
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+
+# Step-1.4: Insert a tuple into table t1 that triggers trig1 which inserts
+# into an AUTO_INCREMENT column.
+INSERT INTO t1(i) VALUES(2);
+
+# Step-1.5: Repeat step 1.4 but using 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t1(i) VALUES(3);
+UNLOCK TABLES;
+COMMIT;
+
+# Step-1.6: Sync slave with master
+--sync_slave_with_master
+
+# Step-1.7: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+--let $diff_tables=master:t2, slave:t2
+--source include/diff_tables.inc
+
+# Step-1.8: Cleanup
+--connection master
+DROP TABLE t1,t2;
+
+# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT
+#  Statements writing to a table with an auto-increment column after selecting
+#  from another table are unsafe because the order in which rows are retrieved
+#  determines what (if any) rows will be written. This order cannot be
+#  predicted and may differ on master and the slave.
+
+# Step-2.1: Create two tables,  one with AUTO_INCREMENT column.
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
+
+# Step-2.2: Create some tuples in table t1.
+INSERT INTO t1 values (1), (2), (3);
+
+# Step-2.3: Create some gap in auto increment value on master's t2 table
+# but not on slave (by doing rollback). Just in case if the unsafe statements
+# are written in statement format, diff tables will fail.
+START TRANSACTION;
+INSERT INTO t2(i) VALUES (1);
+ROLLBACK;
+
+# Step-2.4: Insert into t2 (table with an auto-increment) by selecting tuples
+# from table t1.
+INSERT INTO t2(i) SELECT i FROM t1;
+
+# Step-2.5: Repeat step 2.4 but now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t2 WRITE, t1 READ;
+INSERT INTO t2(i) SELECT i FROM t1;
+UNLOCK TABLES;
+COMMIT;
+
+# Step-2.6: Sync slave with master
+--sync_slave_with_master
+
+# Step-2.7: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+--let $diff_tables=master:t2, slave:t2
+--source include/diff_tables.inc
+
+# Step-2.8: Cleanup
+--connection master
+DROP TABLE t1,t2;
+
+# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST
+#  INSERT into autoincrement field which is not the first part in the
+#  composed primary key is unsafe
+#
+# Step-3.1: Create a table with auto increment column and a composed primary key
+# (second column is auto increment column). Such a definition is allowed only
+# with 'myisam' engine.
+CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM;
+
+# Step-3.2: Inserting into such a table is unsafe.
+INSERT INTO t1 (i) values (1);
+
+# Step-3.3: Repeat step 3.2, now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i) values (2);
+UNLOCK TABLES;
+COMMIT;
+
+# Step-3.4: Sync slave with master
+--sync_slave_with_master
+
+# Step-3.5: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Step-3.6: Cleanup
+--connection master
+DROP TABLE t1;
+
+# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS
+#  INSERT... ON DUPLICATE KEY UPDATE  on a table with more than one UNIQUE KEY
+#  is unsafe Statement
+
+# Step-4.1: Create a table with two unique keys
+CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB;
+
+# Step-4.2: Inserting into such a table is unsafe.
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+
+# Step-4.3: Repeat step 3.2, now with 'LOCK TABLES' logic.
+START TRANSACTION;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
+UNLOCK TABLES;
+COMMIT;
+
+# Step-4.4: Sync slave with master
+--sync_slave_with_master
+
+# Step-4.5: Diff master-slave tables to make sure everything is in sync.
+--let $diff_tables=master:t1, slave:t1
+--source include/diff_tables.inc
+
+# Step-4.6: Cleanup
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv.test b/mysql-test/suite/sys_vars/t/secure_file_priv.test
index 3e2a4fa..5c53da5 100644
--- a/mysql-test/suite/sys_vars/t/secure_file_priv.test
+++ b/mysql-test/suite/sys_vars/t/secure_file_priv.test
@@ -5,17 +5,39 @@ CREATE TABLE t1 (c1 VARCHAR(50));
 INSERT INTO t1 VALUES ("one"),("two"),("three"),("four"),("five");
 SHOW VARIABLES LIKE 'secure_file_priv';
 --disable_query_log
+
 # Atempt to create a file where we normally aren't allowed to create one.
+#
 # Doing this in a portable manner is difficult but we should be able to
-# count on the depth of the directory hierarchy used. Three steps up from
-# the datadir is the 'mysql_test' directory.
---let $PROTECTED_FILE=`SELECT concat(@@datadir,'/../../../bug50373.txt')`
---eval SELECT * FROM t1 INTO OUTFILE '$PROTECTED_FILE';
-DELETE FROM t1;
---eval LOAD DATA INFILE '$PROTECTED_FILE' INTO TABLE t1;
-SELECT * FROM t1;
---eval SELECT load_file('$PROTECTED_FILE') AS loaded_file;
+# count on the directory hierarchy used. A step up from MYSQLTEST_VARDIR
+# should definitely lead us to a "protected" directory, 
+# but at the same time should still be writable since MTR was able
+# to create the vardir itself there. 
+# If we run tests normally, it will be mysql-test directory.
+# If we run tests with --mem, it will be /dev/shm.
+# If we run tests with --parallel, it will be mysql-test/var
+# (because MYSQLTEST_VARDIR in this case is mysql-test/var/N).
+
+--perl
+use File::Basename;
+my $protected_file= dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt';
+open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/bug50373.inc") or die;
+print FILE "SELECT * FROM t1 INTO OUTFILE '".$protected_file."';\n";
+print FILE "DELETE FROM t1;\n";
+print FILE "LOAD DATA INFILE '".$protected_file."' INTO TABLE t1;\n";
+print FILE "SELECT * FROM t1;\n";
+print FILE "SELECT load_file('",$protected_file,"') AS loaded_file;\n";
+close(FILE);
+EOF
+
+--source $MYSQL_TMP_DIR/bug50373.inc
+--remove_file $MYSQL_TMP_DIR/bug50373.inc
 --enable_query_log
-remove_file $PROTECTED_FILE;
+
 DROP TABLE t1;
 
+--perl
+use File::Basename;
+unlink dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt';
+EOF
+
diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
index 8d0a51f..d9a1e06 100644
--- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
+++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
@@ -287,3 +287,30 @@ select * from t1;
 
 set sql_warnings = 0;
 drop table t1;
+
+--echo #
+--echo # MDEV-9093: Persistent computed column is not updated when
+--echo # update query contains join
+--echo #
+
+CREATE TABLE `t1` (
+  `id` bigint(20) NOT NULL,
+  `name` varchar(254) DEFAULT NULL,
+  `name_hash` varchar(64) AS (sha1(name)) PERSISTENT,
+  PRIMARY KEY (`id`)
+);
+
+insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3');
+
+create table t2 (id bigint);
+insert into t2 values (2050),(2051),(2041);
+
+select * from t1;
+
+update t1 join t2 using(id) set name = concat(name,
+'+1') where t1.id in (2051,2041);
+
+select * from t1;
+
+drop table t1,t2;
+
diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
index 44fcae7..af03cc4 100644
--- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
@@ -425,3 +425,29 @@ select * from t1;
 a	b	c	d
 set sql_warnings = 0;
 drop table t1;
+#
+# MDEV-9093: Persistent computed column is not updated when
+# update query contains join
+#
+CREATE TABLE `t1` (
+`id` bigint(20) NOT NULL,
+`name` varchar(254) DEFAULT NULL,
+`name_hash` varchar(64) AS (sha1(name)) PERSISTENT,
+PRIMARY KEY (`id`)
+);
+insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3');
+create table t2 (id bigint);
+insert into t2 values (2050),(2051),(2041);
+select * from t1;
+id	name	name_hash
+2041	name3	1aefcd1b0f39da45fa1fd7236f683c907c15ef82
+2050	name1	9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da
+2051	name2	39ea84acf1fef629fef18a9c6f5799bba32ecc25
+update t1 join t2 using(id) set name = concat(name,
+'+1') where t1.id in (2051,2041);
+select * from t1;
+id	name	name_hash
+2041	name3+1	93c9096df48221428de46e146abc9f4f94bf7d2e
+2050	name1	9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da
+2051	name2+1	fd4f236320db3956a5ec073c5ec39707d7f05708
+drop table t1,t2;
diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
index 6674586..351dfd2 100644
--- a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
@@ -363,3 +363,29 @@ select * from t1;
 a	b	c	d
 set sql_warnings = 0;
 drop table t1;
+#
+# MDEV-9093: Persistent computed column is not updated when
+# update query contains join
+#
+CREATE TABLE `t1` (
+`id` bigint(20) NOT NULL,
+`name` varchar(254) DEFAULT NULL,
+`name_hash` varchar(64) AS (sha1(name)) PERSISTENT,
+PRIMARY KEY (`id`)
+);
+insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3');
+create table t2 (id bigint);
+insert into t2 values (2050),(2051),(2041);
+select * from t1;
+id	name	name_hash
+2050	name1	9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da
+2051	name2	39ea84acf1fef629fef18a9c6f5799bba32ecc25
+2041	name3	1aefcd1b0f39da45fa1fd7236f683c907c15ef82
+update t1 join t2 using(id) set name = concat(name,
+'+1') where t1.id in (2051,2041);
+select * from t1;
+id	name	name_hash
+2050	name1	9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da
+2051	name2+1	fd4f236320db3956a5ec073c5ec39707d7f05708
+2041	name3+1	93c9096df48221428de46e146abc9f4f94bf7d2e
+drop table t1,t2;
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result
index 8631789..0aaed59 100644
--- a/mysql-test/suite/vcol/r/vcol_misc.result
+++ b/mysql-test/suite/vcol/r/vcol_misc.result
@@ -322,3 +322,11 @@ drop table t1;
 create table t1 (a int, b int as (b is null) virtual);
 ERROR HY000: A computed column cannot be based on a computed column
 # end of 5.3 tests
+create table t1 (v1 varchar(255) as (c1) persistent, c1 varchar(50)) collate=latin1_general_ci;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v1` varchar(255) AS (c1) PERSISTENT,
+  `c1` varchar(50) COLLATE latin1_general_ci DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
+drop table t1;
diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test
index a4c1fc0..12f46e9 100644
--- a/mysql-test/suite/vcol/t/vcol_misc.test
+++ b/mysql-test/suite/vcol/t/vcol_misc.test
@@ -283,3 +283,10 @@ drop table t1;
 create table t1 (a int, b int as (b is null) virtual);
 
 --echo # end of 5.3 tests
+
+#
+# MDEV-7655 SHOW CREATE TABLE returns invalid DDL when using virtual columns along with a table collation
+#
+create table t1 (v1 varchar(255) as (c1) persistent, c1 varchar(50)) collate=latin1_general_ci;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/cache_temporal_4265.test b/mysql-test/t/cache_temporal_4265.test
index 6135438..c62f3c3 100644
--- a/mysql-test/t/cache_temporal_4265.test
+++ b/mysql-test/t/cache_temporal_4265.test
@@ -7,5 +7,16 @@ create table t1 (a date);
 insert t1 values ('2000-01-02'), ('2001-02-03'), ('2002-03-04');
 set debug_dbug='d,str_to_datetime_warn';
 select * from t1 where a > date_add('2000-01-01', interval 5 day);
+set debug_dbug='';
+drop table t1;
+
+#
+# MDEV-9707 MAX(timestamp(6) column) in correlated sub-query returns non-existent row data in original table
+#
+create table t1 (id int not null, ut timestamp(6) not null);
+insert into t1 values(1, '2001-01-01 00:00:00.2');
+insert into t1 values(1, '2001-01-01 00:00:00.1');
+select * from t1;
+select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1;
 drop table t1;
 
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index f536f55..c127836 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -193,3 +193,12 @@ insert t1 values ('00:00:00'),('00:01:00');
 select case t1.f1 when '00:00:00' then 1 end from t1;
 drop table t1;
 
+--echo #
+--echo # MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END
+--echo #
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a;
+DESCRIBE t1;
+DROP TABLE t1;
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a;
+DESCRIBE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index e066dc6..5c90c3e 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -2061,3 +2061,24 @@ set @@session.collation_server=filename;
 create table t1(a enum('',''));
 drop table t1;
 set @@session.collation_server=default;
+
+--echo #
+--echo # MDEV-7765: Crash (Assertion `!table || (!table->write_set ||
+--echo # bitmap_is_set(table->write_set, field_index) ||
+--echo # bitmap_is_set(table->vcol_set, field_index))' fails)
+--echo # on using function over not created table
+--echo #
+
+DELIMITER |;
+CREATE function f1() returns int
+BEGIN
+  declare n int;
+  set n:= (select count(*) from t1);
+  return n;
+end|
+DELIMITER ;|
+-- error ER_NO_SUCH_TABLE
+create table t1 as select f1();
+drop function f1;
+
+--echo End of 5.5 tests
diff --git a/mysql-test/t/ctype_cp850.test b/mysql-test/t/ctype_cp850.test
new file mode 100644
index 0000000..358829e
--- /dev/null
+++ b/mysql-test/t/ctype_cp850.test
@@ -0,0 +1,16 @@
+--echo #
+--echo # Start of 5.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-9862 Illegal mix of collation, when comparing column with CASE expression
+--echo #
+SET NAMES cp850;
+CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1);
+SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 8cd70e9..a9b5cee 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1563,8 +1563,7 @@ SET NAMES utf8;
 SET NAMES utf8;
 CREATE TABLE t1 (a INT);
 INSERT INTO t1 VALUES (0), (0), (1), (0), (0);
---error ER_DUP_ENTRY
-SELECT COUNT(*) FROM t1, t1 t2 
+SELECT COUNT(*) FROM t1, t1 t2
 GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
 DROP TABLE t1;
 
@@ -1649,5 +1648,16 @@ SELECT * FROM t2;
 DROP TABLE t2, t1;
 
 --echo #
+--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+--echo #
+SET NAMES utf8;
+CREATE TABLE t1 (a TEXT CHARACTER SET utf8);
+INSERT INTO t1 VALUES (REPEAT('A',100));
+SELECT OCTET_LENGTH(a) FROM t1;
+ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8;
+SELECT OCTET_LENGTH(a),a FROM t1;
+DROP TABLE t1;
+
+--echo #
 --echo # End of 5.5 tests
 --echo #
diff --git a/mysql-test/t/ctype_utf8mb4.test b/mysql-test/t/ctype_utf8mb4.test
index fda20ca..66f5a3b 100644
--- a/mysql-test/t/ctype_utf8mb4.test
+++ b/mysql-test/t/ctype_utf8mb4.test
@@ -1827,6 +1827,18 @@ DROP TABLE t1;
 --echo # End of test for Bug#13581962,Bug#14096619
 
 --echo #
+--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+--echo #
+SET NAMES utf8mb4;
+CREATE TABLE t1 (a TEXT CHARACTER SET utf8mb4);
+INSERT INTO t1 VALUES (REPEAT('😎',100));
+SELECT OCTET_LENGTH(a) FROM t1;
+ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8mb4;
+SELECT OCTET_LENGTH(a),a FROM t1;
+DROP TABLE t1;
+
+
+--echo #
 --echo # End of 5.5 tests
 --echo #
 
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index ddce7f5..e10349b 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -506,3 +506,293 @@ select x.id, message from (select id from t1) x left join
 (select id, 1 as message from t2) y on x.id=y.id
 where coalesce(message,0) <> 0;
 drop table t1,t2;
+
+--echo #
+--echo # MDEV-7827: Assertion `!table || (!table->read_set ||
+--echo # bitmap_is_set(table->read_set, field_index))' failed
+--echo # in Field_long::val_str on EXPLAIN EXTENDED
+--echo #
+
+CREATE TABLE t1 (f1 INT, f2 INT, KEY(f2)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (6,9);
+
+CREATE TABLE t2 (f3 INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (2),(0);
+
+EXPLAIN EXTENDED
+SELECT f1 FROM ( SELECT * FROM t1 ) AS sq
+WHERE f1 IN (
+  SELECT f3 FROM t2 WHERE f2 IN (
+    SELECT f3 FROM t2 HAVING f3 >= 8
+  )
+);
+
+DROP TABLE t2,t1;
+
+--echo #
+--echo # MDEV-9462: Out of memory using explain on 2 empty tables 
+--echo #
+
+CREATE TABLE `t1` (
+ `REC_GROUP` char(2) DEFAULT NULL,
+ `CLIENT_INFO` text CHARACTER SET utf8,
+ `NAME` text,
+ `PHONE_NUMBER` text,
+ `ATTENTION_NAME` text,
+ `PAYMENT_TERM` text CHARACTER SET utf8,
+ `CREDIT_LIMIT` decimal(12,2) DEFAULT NULL,
+ `LAST_PAY_DATE` text CHARACTER SET utf8,
+ `TOTAL` double DEFAULT NULL,
+ `TOTAL_MCL` double DEFAULT NULL,
+ `TOTAL_MFS` double DEFAULT NULL,
+ `TOTAL_MIS` double DEFAULT NULL,
+ `BEFORE_DUE_7_MCL` double DEFAULT NULL,
+ `BEFORE_DUE_7_MFS` double DEFAULT NULL,
+ `BEFORE_DUE_7_MIS` double DEFAULT NULL,
+ `PER1_MCL` double DEFAULT NULL,
+ `PER1_MFS` double DEFAULT NULL,
+ `PER1_MIS` double DEFAULT NULL,
+ `PER2_MCL` double DEFAULT NULL,
+ `PER2_MFS` double DEFAULT NULL,
+ `PER2_MIS` double DEFAULT NULL,
+ `PER3_MCL` double DEFAULT NULL,
+ `PER3_MFS` double DEFAULT NULL,
+ `PER3_MIS` double DEFAULT NULL,
+ `PER4_MCL` double DEFAULT NULL,
+ `PER4_MFS` double DEFAULT NULL,
+ `PER4_MIS` double DEFAULT NULL,
+ `PER5_MCL` double DEFAULT NULL,
+ `PER5_MFS` double DEFAULT NULL,
+ `PER5_MIS` double DEFAULT NULL,
+ `PER6_MCL` double DEFAULT NULL,
+ `PER6_MFS` double DEFAULT NULL,
+ `PER6_MIS` double DEFAULT NULL,
+ `PER7_MCL` double DEFAULT NULL,
+ `PER7_MFS` double DEFAULT NULL,
+ `PER7_MIS` double DEFAULT NULL,
+ `BEFORE_DUE_7` double DEFAULT NULL,
+ `PER1` double DEFAULT NULL,
+ `PER2` double DEFAULT NULL,
+ `PER3` double DEFAULT NULL,
+ `PER4` double DEFAULT NULL,
+ `PER5` double DEFAULT NULL,
+ `PER6` double DEFAULT NULL,
+ `PER7` double DEFAULT NULL,
+ `REF` varchar(30) DEFAULT NULL,
+ `TYPE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
+);
+
+
+CREATE TABLE `t2` (
+ `RECEIVABLE_GROUP` char(2) DEFAULT NULL,
+ `CLIENT_NUMBER` varchar(35) DEFAULT NULL,
+ `CLIENT_NAME` varchar(73) DEFAULT NULL,
+ `PHONE_NUMBER` char(12) DEFAULT NULL,
+ `ATTENTION_NAME` char(26) DEFAULT NULL,
+ `PAYMENT_TERM` varchar(26) CHARACTER SET utf8 DEFAULT NULL,
+ `CREDIT_LIMIT` decimal(12,2) DEFAULT NULL,
+ `LAST_PAY_DATE` varchar(42) CHARACTER SET utf8 DEFAULT NULL,
+ `TOTAL` decimal(12,2) DEFAULT NULL,
+ `BEFORE_DUE_7` decimal(12,2) DEFAULT NULL,
+ `PER1` decimal(12,2) DEFAULT NULL,
+ `PER2` decimal(12,2) DEFAULT NULL,
+ `PER3` decimal(12,2) DEFAULT NULL,
+ `PER4` decimal(12,2) DEFAULT NULL,
+ `PER5` decimal(12,2) DEFAULT NULL,
+ `PER6` decimal(12,2) DEFAULT NULL,
+ `PER7` decimal(12,2) DEFAULT NULL,
+ `DIVISION` varchar(3) CHARACTER SET utf8 NOT NULL,
+ `CLIENT_INFO` varchar(294) CHARACTER SET utf8 DEFAULT NULL,
+ `EXCHANGE_RATE` double NOT NULL,
+ `REF` varchar(30) DEFAULT NULL
+);
+
+explain
+SELECT A.RECEIVABLE_GROUP,A.CLIENT_INFO,A.CLIENT_NAME,A.PHONE_NUMBER,A.ATTENTION_NAME,A.PAYMENT_TERM,A.CREDIT_LIMIT,A.LAST_PAY_DATE,A.TOTAL,
+COALESCE(B.TOTAL_MCL,0) AS TOTAL_MCL,
+COALESCE(C.TOTAL_MFS,0) AS TOTAL_MFS,
+COALESCE(D.TOTAL_MIS,0) AS TOTAL_MIS,
+COALESCE(F.BEFORE_DUE_7_MCL,0) AS BEFORE_DUE_7_MCL,
+COALESCE(G.BEFORE_DUE_7_MFS,0) AS BEFORE_DUE_7_MFS,
+COALESCE(H.BEFORE_DUE_7_MIS,0) AS BEFORE_DUE_7_MIS,
+COALESCE(I.PER1_MCL,0) AS PER1_MCL,
+COALESCE(J.PER1_MFS,0) AS PER1_MFS,
+COALESCE(K.PER1_MIS,0) AS PER1_MIS,
+COALESCE(L.PER2_MCL,0) AS PER2_MCL,
+COALESCE(M.PER2_MFS,0) AS PER2_MFS,
+COALESCE(N.PER2_MIS,0) AS PER2_MIS,
+COALESCE(O.PER3_MCL,0) AS PER3_MCL,
+COALESCE(P.PER3_MFS,0) AS PER3_MFS,
+COALESCE(R.PER3_MIS,0) AS PER3_MIS,
+COALESCE(S.PER4_MCL,0) AS PER4_MCL,
+COALESCE(T.PER4_MFS,0) AS PER4_MFS,
+COALESCE(U.PER4_MIS,0) AS PER4_MIS,
+COALESCE(V.PER5_MCL,0) AS PER5_MCL,
+COALESCE(X.PER5_MFS,0) AS PER5_MFS,
+COALESCE(Z.PER5_MIS,0) AS PER5_MIS,
+COALESCE(Q.PER6_MCL,0) AS PER6_MCL,
+COALESCE(Y.PER6_MFS,0) AS PER6_MFS,
+COALESCE(W.PER6_MIS,0) AS PER6_MIS,
+COALESCE(A1.PER7_MCL,0) AS PER7_MCL,
+COALESCE(B1.PER7_MFS,0) AS PER7_MFS,
+COALESCE(C1.PER7_MIS,0) AS PER7_MIS,
+A.BEFORE_DUE_7,A.PER1,A.PER2,A.PER3,A.PER4,A.PER5,A.PER6,A.PER7,
+CONCAT(A.DIVISION,'-',A.CLIENT_NUMBER) AS REF,"2" AS TYPE FROM
+(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,
+GROUP_CONCAT(DISTINCT CLIENT_INFO SEPARATOR '<br>') AS CLIENT_INFO,
+GROUP_CONCAT(DISTINCT CLIENT_NAME SEPARATOR '<br>') AS CLIENT_NAME, 
+GROUP_CONCAT( DISTINCT `PHONE_NUMBER` SEPARATOR '<br>' ) AS PHONE_NUMBER , 
+GROUP_CONCAT( DISTINCT `ATTENTION_NAME` SEPARATOR '<br>' )  AS ATTENTION_NAME, 
+GROUP_CONCAT( DISTINCT `PAYMENT_TERM` SEPARATOR '<br>' ) AS PAYMENT_TERM, 
+CREDIT_LIMIT , 
+GROUP_CONCAT( `LAST_PAY_DATE` SEPARATOR '<br>' ) AS LAST_PAY_DATE, 
+SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL, 
+SUM( `BEFORE_DUE_7`*EXCHANGE_RATE ) AS BEFORE_DUE_7, 
+SUM( `PER1`*EXCHANGE_RATE ) AS PER1, 
+SUM( `PER2`*EXCHANGE_RATE ) AS PER2, 
+SUM( `PER3`*EXCHANGE_RATE ) AS PER3, 
+SUM( `PER4`*EXCHANGE_RATE ) AS PER4, 
+SUM( `PER5`*EXCHANGE_RATE ) AS PER5, 
+SUM( `PER6`*EXCHANGE_RATE ) AS PER6, 
+SUM( `PER7`*EXCHANGE_RATE ) AS PER7
+FROM `t2`
+WHERE REF IS NULL GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A 
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B ON A.CLIENT_NUMBER=B.CLIENT_NUMBER AND 
+A.DIVISION=B.DIVISION AND A.RECEIVABLE_GROUP=B.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C ON A.CLIENT_NUMBER=C.CLIENT_NUMBER 
+AND 
+A.DIVISION=C.DIVISION AND A.RECEIVABLE_GROUP=C.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS D ON A.CLIENT_NUMBER=D.CLIENT_NUMBER AND 
+A.DIVISION=D.DIVISION AND A.RECEIVABLE_GROUP=D.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=D.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS F ON A.CLIENT_NUMBER=F.CLIENT_NUMBER AND 
+A.DIVISION=F.DIVISION AND A.RECEIVABLE_GROUP=F.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=F.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS G ON A.CLIENT_NUMBER=G.CLIENT_NUMBER AND 
+A.DIVISION=G.DIVISION AND A.RECEIVABLE_GROUP=G.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=G.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS H ON A.CLIENT_NUMBER=H.CLIENT_NUMBER AND 
+A.DIVISION=H.DIVISION AND A.RECEIVABLE_GROUP=H.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=H.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS I ON A.CLIENT_NUMBER=I.CLIENT_NUMBER  AND 
+A.DIVISION=I.DIVISION AND A.RECEIVABLE_GROUP=I.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=I.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS J ON A.CLIENT_NUMBER=J.CLIENT_NUMBER AND 
+A.DIVISION=J.DIVISION AND A.RECEIVABLE_GROUP=J.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=J.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS K ON A.CLIENT_NUMBER=K.CLIENT_NUMBER AND 
+A.DIVISION=K.DIVISION AND A.RECEIVABLE_GROUP=K.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=K.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS L ON A.CLIENT_NUMBER=L.CLIENT_NUMBER AND 
+A.DIVISION=L.DIVISION AND A.RECEIVABLE_GROUP=L.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=L.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS M ON A.CLIENT_NUMBER=M.CLIENT_NUMBER AND 
+A.DIVISION=M.DIVISION AND A.RECEIVABLE_GROUP=M.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=M.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS N ON A.CLIENT_NUMBER=N.CLIENT_NUMBER AND 
+A.DIVISION=N.DIVISION AND A.RECEIVABLE_GROUP=N.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=N.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS O ON A.CLIENT_NUMBER=O.CLIENT_NUMBER AND 
+A.DIVISION=O.DIVISION AND A.RECEIVABLE_GROUP=O.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=O.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS P ON A.CLIENT_NUMBER=P.CLIENT_NUMBER AND 
+A.DIVISION=P.DIVISION AND A.RECEIVABLE_GROUP=P.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=P.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS R ON A.CLIENT_NUMBER=R.CLIENT_NUMBER AND 
+A.DIVISION=R.DIVISION AND A.RECEIVABLE_GROUP=R.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=R.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS S ON A.CLIENT_NUMBER=S.CLIENT_NUMBER AND 
+A.DIVISION=S.DIVISION AND A.RECEIVABLE_GROUP=S.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=S.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS T ON A.CLIENT_NUMBER=T.CLIENT_NUMBER AND 
+A.DIVISION=T.DIVISION AND A.RECEIVABLE_GROUP=T.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=T.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS U ON A.CLIENT_NUMBER=U.CLIENT_NUMBER AND 
+A.DIVISION=U.DIVISION AND A.RECEIVABLE_GROUP=U.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=U.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS V ON A.CLIENT_NUMBER=V.CLIENT_NUMBER AND 
+A.DIVISION=V.DIVISION AND A.RECEIVABLE_GROUP=V.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=V.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS X ON A.CLIENT_NUMBER=X.CLIENT_NUMBER AND 
+A.DIVISION=X.DIVISION AND A.RECEIVABLE_GROUP=X.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=X.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Z ON A.CLIENT_NUMBER=Z.CLIENT_NUMBER AND 
+A.DIVISION=Z.DIVISION AND A.RECEIVABLE_GROUP=Z.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Z.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Q ON A.CLIENT_NUMBER=Q.CLIENT_NUMBER AND 
+A.DIVISION=Q.DIVISION AND A.RECEIVABLE_GROUP=Q.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Q.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Y ON A.CLIENT_NUMBER=Y.CLIENT_NUMBER AND 
+A.DIVISION=Y.DIVISION AND A.RECEIVABLE_GROUP=Y.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Y.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS W ON A.CLIENT_NUMBER=W.CLIENT_NUMBER AND 
+A.DIVISION=W.DIVISION AND A.RECEIVABLE_GROUP=W.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=W.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MCL
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A1 ON A.CLIENT_NUMBER=A1.CLIENT_NUMBER AND 
+A.DIVISION=A1.DIVISION AND A.RECEIVABLE_GROUP=A1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=A1.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MFS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B1 ON A.CLIENT_NUMBER=B1.CLIENT_NUMBER AND 
+A.DIVISION=B1.DIVISION AND A.RECEIVABLE_GROUP=B1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B1.CREDIT_LIMIT
+LEFT JOIN
+(SELECT  RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MIS
+FROM `t2`
+WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C1 ON A.CLIENT_NUMBER=C1.CLIENT_NUMBER AND 
+A.DIVISION=C1.DIVISION AND A.RECEIVABLE_GROUP=C1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C1.CREDIT_LIMIT
+ORDER BY TOTAL DESC;
+
+DROP TABLES t1,t2;
diff --git a/mysql-test/t/events_2.test b/mysql-test/t/events_2.test
index 3d60965..5443f76 100644
--- a/mysql-test/t/events_2.test
+++ b/mysql-test/t/events_2.test
@@ -13,7 +13,7 @@ use events_test;
 # mysql.event intact checking end
 #
 
-create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
+create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5;
 select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
 drop event e_26;
 --error ER_WRONG_VALUE
@@ -67,10 +67,10 @@ select /*2*/ user, host, db, command, state, info
 select release_lock("test_lock2");
 drop event закачка;
 
-# Wait for release_lock("test_lock2") to complete,
+# Wait for get_lock("test_lock2") to complete,
 # to avoid polluting the next test information_schema.processlist
 let $wait_condition= select count(*) = 0 from information_schema.processlist
-  where (state like 'User lock%' AND info like 'select get_lock%');
+  where info='select get_lock("test_lock2", 20)';
 --source include/wait_condition.inc
 
 
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index b843cf8..cd90184 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -484,6 +484,14 @@ SELECT -a FROM t1;
 --error ER_DATA_OUT_OF_RANGE
 SELECT -b FROM t1;
 
+# try with two rows now
+INSERT INTO t1 VALUES(0,0);
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT -a FROM t1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -b FROM t1;
+
 DROP TABLE t1;
 
 # Decimal overflows
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index f6afef9..45214ae 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1039,6 +1039,24 @@ insert into t1 values ('00:00:00'),('00:01:00');
 select 1 from t1 where 1 < some (select cast(a as datetime) from t1);
 drop table t1;
 
+--echo #
+--echo # Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6
+--echo #                UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M"
+--echo #
+
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"));
+SELECT UNIX_TIMESTAMP('2015-06-00');
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'));
+
+set sql_mode= 'TRADITIONAL';
+SELECT @@sql_mode;
+
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m"));
+SELECT UNIX_TIMESTAMP('2015-06-00');
+SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s'));
+
+set sql_mode= default;
+
 select time('10:10:10') > 10;
 select time('10:10:10') > 1010;
 select time('10:10:09') > 101010;
diff --git a/mysql-test/t/insert_innodb.test b/mysql-test/t/insert_innodb.test
new file mode 100644
index 0000000..8c8d269
--- /dev/null
+++ b/mysql-test/t/insert_innodb.test
@@ -0,0 +1,43 @@
+--source include/have_innodb.inc
+
+#
+# MDEV-8979 IGNORE does not ignore the error 1452
+#
+
+--echo #
+--echo # BUG#22037930: INSERT IGNORE FAILS TO IGNORE
+--echo #               FOREIGN KEY CONSTRAINT
+
+--echo # Setup.
+CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1))
+ENGINE=INNODB;
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(0);
+
+--echo # Without fix, an error is reported.
+INSERT IGNORE INTO t2 VALUES(1);
+UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0;
+UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0;
+
+--echo # Test for multi update.
+UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3;
+UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3;
+
+--echo # Reports an error since IGNORE is not used.
+--error ER_NO_REFERENCED_ROW_2
+INSERT INTO t2 VALUES(1);
+
+--error ER_NO_REFERENCED_ROW_2
+UPDATE t2 SET fld2=20 WHERE fld2=0;
+
+--error ER_ROW_IS_REFERENCED_2
+UPDATE t1 SET fld1=20 WHERE fld1=0;
+
+--error ER_NO_REFERENCED_ROW_2
+UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
+
+--error ER_ROW_IS_REFERENCED_2
+UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
+
+DROP TABLE t2, t1;
diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test
index 2333f02..d73859c 100644
--- a/mysql-test/t/kill_processlist-6619.test
+++ b/mysql-test/t/kill_processlist-6619.test
@@ -5,8 +5,6 @@
 --enable_connect_log
 --connect (con1,localhost,root,,)
 --let $con_id = `SELECT CONNECTION_ID()`
---replace_column 1 # 3 # 6 # 7 #
-SHOW PROCESSLIST;
 --connection default
 --replace_result $con_id con_id
 eval KILL QUERY $con_id;
diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test
index 04ac95c..899d293 100644
--- a/mysql-test/t/locale.test
+++ b/mysql-test/t/locale.test
@@ -54,3 +54,12 @@ SELECT DATE_FORMAT('2001-01-05', '%w %a %W');
 SELECT DATE_FORMAT('2001-01-06', '%w %a %W');
 SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
 --echo End of 5.4 tests
+
+#
+# MDEV-9928 LC_TIME_NAMES=de_AT; unusual name for february
+#
+SET NAMES utf8;
+SET lc_time_names=de_AT;
+SELECT monthname('2001-01-01');
+SELECT monthname('2001-02-01');
+SELECT monthname('2001-03-01');
diff --git a/mysql-test/t/mdev6830-master.opt b/mysql-test/t/mdev6830-master.opt
deleted file mode 100644
index 2a8c27d..0000000
--- a/mysql-test/t/mdev6830-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---debug
diff --git a/mysql-test/t/mdev6830.test b/mysql-test/t/mdev6830.test
index 24565d0..3898d5b 100644
--- a/mysql-test/t/mdev6830.test
+++ b/mysql-test/t/mdev6830.test
@@ -1,10 +1,10 @@
-
+#
+# MDEV-6830 Server crashes in best_access_path after a sequence of SELECTs invollving a temptable view
+#
 --source include/have_debug.inc
 
---disable_warnings
-drop table if exists t1,t2,t3;
-drop view if exists v2,v3;
---enable_warnings
+set @@debug_dbug= 'd,opt';
+
 CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM;
 
 CREATE TABLE t2 (
diff --git a/mysql-test/t/merge_innodb.test b/mysql-test/t/merge_innodb.test
index 7f0b1a0..9f87f24 100644
--- a/mysql-test/t/merge_innodb.test
+++ b/mysql-test/t/merge_innodb.test
@@ -39,3 +39,34 @@ SELECT * FROM t2;
 SELECT * FROM t1;
 DROP TABLE t1, t2, t3, t4, t5;
 
+#
+# Bug#20691429 temporary merge over view under lock tables
+#
+create table t1 (c1 varchar(100));
+create table t2 (c1 varchar(100));
+create view t3 as select * from t1;
+insert into t1 values ('ann'), ('alice');
+insert into t2 values ('bob'), ('brian');
+create temporary table t4 (c1 varchar(100)) engine=MERGE union=(t2, t1);
+create temporary table t5 (c1 varchar(100)) engine=MERGE union=(t3, t1);
+--error ER_WRONG_MRG_TABLE
+select * from t5;
+lock tables t1 read, t2 read, t3 read, t4 read;
+--error ER_WRONG_MRG_TABLE
+select * from t5;
+select * from t4;
+unlock tables;
+drop table t2;
+create view t2 as select * from t1;
+--error ER_WRONG_MRG_TABLE
+select * from t4;
+lock tables t1 read, t2 read, t3 read;
+--error ER_WRONG_MRG_TABLE
+select * from t4;
+--error ER_WRONG_MRG_TABLE
+select * from t4;
+--error ER_WRONG_MRG_TABLE
+select * from t4;
+unlock tables;
+drop view t2, t3;
+drop table t1;
diff --git a/mysql-test/t/mysql_upgrade_view.test b/mysql-test/t/mysql_upgrade_view.test
index 7a098aa..c98c88f 100644
--- a/mysql-test/t/mysql_upgrade_view.test
+++ b/mysql-test/t/mysql_upgrade_view.test
@@ -157,5 +157,30 @@ rename table mysql.ev_bk to mysql.event;
 
 drop table if exists kv;
 drop view v1,v2,v3,v4;
-drop table t1;
 
+#
+# MDEV-9453 mysql_upgrade.exe error when mysql is migrated to mariadb
+# (mysql_upgrade.exe --upgrade-system-tables fails on fixing views)
+#
+
+# Make it look like a MySQL directory again
+
+rename table mysql.event to mysql.ev_bk;
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.MYI $MYSQLD_DATADIR/mysql/event.MYI
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.MYD $MYSQLD_DATADIR/mysql/event.MYD
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.frm $MYSQLD_DATADIR/mysql/event.frm
+
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v1.frm $MYSQLD_DATADIR/test/v1.frm
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v2.frm $MYSQLD_DATADIR/test/v2.frm
+--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v3.frm $MYSQLD_DATADIR/test/v3.frm
+
+flush tables;
+
+--replace_result $MYSQLTEST_VARDIR var
+--exec $MYSQL_UPGRADE --force --upgrade-system-tables 2>&1
+
+# back to mariadb default
+drop table mysql.event;
+rename table mysql.ev_bk to mysql.event;
+drop view v1,v2,v3;
+drop table t1;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index b028574..f0ada44 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -2502,5 +2502,10 @@ CREATE DATABASE `a\"'``b`;
 USE `a\"'``b`;
 CREATE PROCEDURE p1() BEGIN END;
 ALTER DATABASE `a\"'``b` COLLATE utf8_general_ci;
---exec $MYSQL_DUMP --routines --compact a\\\"\'\`b 2>&1
+--let shell_ready_db_name="a\\\\\\"'`b"
+if (`select convert(@@version_compile_os using latin1) IN ("Win32","Win64","Windows") = 0`)
+{
+  --let shell_ready_db_name=a\\\\\\"\\'\\`b
+}
+--exec $MYSQL_DUMP --routines --compact $shell_ready_db_name
 DROP DATABASE `a\"'``b`;
diff --git a/mysql-test/t/second_frac-9175.test b/mysql-test/t/second_frac-9175.test
new file mode 100644
index 0000000..91baf99
--- /dev/null
+++ b/mysql-test/t/second_frac-9175.test
@@ -0,0 +1,9 @@
+#
+# MDEV-9175 Query parser tansforms MICROSECOND into SECOND_FRAC, which does not work
+#
+
+select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456');
+select * from v1;
+drop view v1;
diff --git a/mysql-test/t/select_debug.test b/mysql-test/t/select_debug.test
index 4b77f9f..4941540 100644
--- a/mysql-test/t/select_debug.test
+++ b/mysql-test/t/select_debug.test
@@ -10,7 +10,7 @@ create table t2 (a int);
 insert into t2 values (2), (3);
 
 set session join_cache_level=3;
-set @@debug_dbug= 'd:t:O,/tmp/trace.out';
+set @@debug_dbug= 'd,opt';
 
 explain select t1.b from t1,t2 where t1.b=t2.a;
 select t1.b from t1,t2 where t1.b=t2.a;
diff --git a/mysql-test/t/set_password_plugin-9835.test b/mysql-test/t/set_password_plugin-9835.test
new file mode 100644
index 0000000..a10a339
--- /dev/null
+++ b/mysql-test/t/set_password_plugin-9835.test
@@ -0,0 +1,128 @@
+#
+# MDEV-9835 Valid password is not working after server restart.
+#
+# Various combinations of SET PASSWORD and not-empty mysql.user.plugin field
+#
+--source include/not_embedded.inc
+
+--enable_connect_log
+
+# The hash (old and new) is for 'test'
+create user natauth at localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user newpass at localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user newpassnat at localhost identified via 'mysql_native_password';
+set password for newpassnat at localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user oldauth at localhost identified with 'mysql_old_password' using '378b243e220ca493';
+
+create user oldpass at localhost identified by password '378b243e220ca493';
+
+create user oldpassold at localhost identified with 'mysql_old_password';
+set password for oldpassold at localhost = '378b243e220ca493';
+
+--sorted_result
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+
+--connect(con,localhost,natauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test,)
+select current_user();
+--disconnect con
+
+--connection default
+
+flush privileges;
+
+--connect(con,localhost,natauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test,)
+select current_user();
+--disconnect con
+
+--connection default
+
+# changing to the NEW password hash
+set password for natauth at localhost = PASSWORD('test2');
+set password for newpass at localhost = PASSWORD('test2');
+set password for newpassnat at localhost = PASSWORD('test2');
+set password for oldauth at localhost = PASSWORD('test2');
+set password for oldpass at localhost = PASSWORD('test2');
+set password for oldpassold at localhost = PASSWORD('test2');
+
+--sorted_result
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+
+--connect(con,localhost,natauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test2,)
+select current_user();
+--disconnect con
+
+--connection default
+
+flush privileges;
+
+--connect(con,localhost,natauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test2,)
+select current_user();
+--disconnect con
+
+--connection default
+drop user natauth at localhost, newpass at localhost, newpassnat at localhost;
+drop user oldauth at localhost, oldpass at localhost, oldpassold at localhost;
+
diff --git a/mysql-test/t/ssl_cert_verify.test b/mysql-test/t/ssl_cert_verify.test
new file mode 100644
index 0000000..83f621b
--- /dev/null
+++ b/mysql-test/t/ssl_cert_verify.test
@@ -0,0 +1,43 @@
+# Want to skip this test from Valgrind execution
+--source include/no_valgrind_without_big.inc
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+-- source include/have_ssl_communication.inc
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+let $ssl_verify_fail_path = --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-key=$MYSQL_TEST_DIR/std_data/server-key-verify-fail.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert-verify-fail.pem;
+let $ssl_verify_pass_path = --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-key=$MYSQL_TEST_DIR/std_data/server-key-verify-pass.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert-verify-pass.pem;
+
+--echo #T1: Host name (/CN=localhost/) as OU name in the server certificate, server certificate verification should fail.
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--exec echo "restart:" $ssl_verify_fail_path  > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--error 1
+--exec $MYSQL --protocol=tcp --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-verify-server-cert -e "SHOW STATUS like 'Ssl_version'"
+
+--echo #T2: Host name (localhost) as common name in the server certificate, server certificate verification should pass.
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--exec echo "restart:" $ssl_verify_pass_path  > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--replace_result TLSv1.2 TLS_VERSION TLSv1.1 TLS_VERSION TLSv1 TLS_VERSION
+--exec $MYSQL --protocol=tcp --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-verify-server-cert -e "SHOW STATUS like 'Ssl_version'"
+
+--echo # restart server using restart
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--exec echo "restart: " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
diff --git a/mysql-test/t/ssl_timeout-9836.opt b/mysql-test/t/ssl_timeout-9836.opt
new file mode 100644
index 0000000..7a26968
--- /dev/null
+++ b/mysql-test/t/ssl_timeout-9836.opt
@@ -0,0 +1 @@
+--loose-thread-handling=pool-of-threads
diff --git a/mysql-test/t/ssl_timeout-9836.test b/mysql-test/t/ssl_timeout-9836.test
new file mode 100644
index 0000000..5b57917
--- /dev/null
+++ b/mysql-test/t/ssl_timeout-9836.test
@@ -0,0 +1,11 @@
+#
+# MDEV-9836 Connection lost when using SSL
+#
+-- source include/have_ssl_communication.inc
+connect(con1,localhost,root,,,,,SSL);
+SET @@net_read_timeout=1;
+SELECT 1;
+# MDEV-9836 - YASSL bug - SSL connection lost if it has been idle, for longer than net_read_timeout
+-- sleep 2
+SELECT 1;
+disconnect con1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 67eac0d..b802761 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -5964,3 +5964,13 @@ EXECUTE stmt;
 
 deallocate prepare stmt;
 drop table t1,t2,t3,t4;
+
+--echo # MDEV-7122
+--echo # Assertion `0' failed in subselect_hash_sj_engine::init
+--echo #
+SET SESSION big_tables=1;
+CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+INSERT INTO t1 VALUES(0),(0),(0);
+SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
+DROP TABLE t1;
+SET SESSION big_tables=0;
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index 9d7ea17..51bed53 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -2700,5 +2700,74 @@ explain
 select 1 from t1 where _cp932 "1" in (select '1' from t1);
 drop table t1;
 
+--echo #
+--echo # MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside
+--echo #
+set @tmp_mdev7823=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f2 INT, KEY(f2));
+INSERT INTO t2 VALUES (8),(0);
+
+CREATE TABLE t3 (f3 INT);
+INSERT INTO t3 VALUES (1),(2);
+
+CREATE TABLE t4 (f4 INT);
+INSERT INTO t4 VALUES (0),(5);
+
+explain 
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) );
+
+drop table t1,t2,t3,t4;
+set optimizer_switch= @tmp_mdev7823;
+
+--echo #
+--echo # MDEV-6859: scalar subqueries in a comparison produced unexpected result
+--echo #
+set @tmp_mdev6859=@@optimizer_switch;
+set optimizer_switch=default;
+CREATE TABLE t1 (
+  project_number varchar(50) NOT NULL,
+  PRIMARY KEY (project_number)
+) ENGINE=MyISAM;
+
+INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb');
+
+CREATE TABLE t2 (
+  id int(10) unsigned NOT NULL AUTO_INCREMENT,
+  project_number varchar(50) NOT NULL,
+  history_date date NOT NULL,
+  country varchar(50) NOT NULL,
+  PRIMARY KEY (id)
+) ENGINE=MyISAM;
+
+INSERT INTO t2 (id, project_number, history_date, country) VALUES
+(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore');
+
+CREATE TABLE t3 (
+  region varchar(50) NOT NULL,
+  country varchar(50) NOT NULL
+) ENGINE=MyISAM;
+
+INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france');
+
+SELECT SQL_NO_CACHE a.project_number 
+FROM t1 a 
+WHERE ( SELECT z.country 
+        FROM t2 z 
+        WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' 
+        ORDER BY z.id DESC LIMIT 1 
+      ) IN ( 
+         SELECT r.country 
+         FROM t3 r 
+         WHERE r.region = 'eame'
+      );
+
+drop table t1, t2, t3;
+set optimizer_switch= @tmp_mdev6859;
+
 # The following command must be the last one the file 
 set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index 66dd71d..d5f6fc6 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -643,6 +643,10 @@ DROP TABLE t1;
 
 --echo End of 5.1 tests
 
+--echo #
+--echo # Start of 5.5 tests
+--echo #
+
 #
 # Problem when comparing blobs #778901
 #
@@ -651,3 +655,24 @@ CREATE TABLE t1 ( f1 blob, f2 blob );
 INSERT INTO t1 VALUES ('','');
 SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ;
 DROP TABLE t1;
+
+--echo #
+--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
+--echo #
+CREATE TABLE t1 (a MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT(0x61,128000));
+SELECT LENGTH(a) FROM t1;
+ALTER TABLE t1 MODIFY a BLOB;
+SELECT LENGTH(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (REPEAT(0x61,65000));
+SELECT LENGTH(a) FROM t1;
+ALTER TABLE t1 MODIFY a TINYBLOB;
+SELECT LENGTH(a) FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 0b2ce16..4b05817 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -386,3 +386,32 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
 select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
 drop table t1;
 
+--echo #
+--echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
+--echo #
+CREATE TABLE t1 (
+  id BIGINT NOT NULL,
+  date_debut DATE NOT NULL,
+  date_fin DATE DEFAULT NULL);
+CREATE TABLE t2(
+  id BIGINT NOT NULL,
+  date_debut DATE NOT NULL,
+  date_fin DATE DEFAULT NULL);
+INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t1 VALUES (2,'2016-02-01',null);
+INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31');
+INSERT INTO t1 VALUES (4,'2016-04-01',null);
+
+INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28');
+INSERT INTO t2 VALUES (3,'2016-03-01',null);
+INSERT INTO t2 VALUES (4,'2016-04-01',null);
+SELECT t1.id,
+ GREATEST(t2.date_debut, t1.date_debut) AS date_debut,
+ LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)),
+       IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin
+FROM t1 LEFT JOIN t2 ON (t1.id=t2.id);
+DROP TABLE t1,t2;
+SELECT
+  LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0,
+  LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1;
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 575c304..0cc9c37 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -446,4 +446,12 @@ SELECT MAX(ts) = '2011-01-06 12:34:30' FROM t1;
 SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1;
 DROP TABLE t1;
 
+--echo #
+--echo # MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL
+--echo #
+CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1;
+DROP TABLE t1;
+
 --echo End of 5.5 tests
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 815be87..a25a4d1 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -5480,6 +5480,16 @@ deallocate prepare stmt;
 
 drop view v1,v2;
 drop table `t1`;
+
+#
+# Bug#19817021
+#
+create table t1 (a int, b int);
+create view v1 as select a+b from t1;
+alter table v1 check partition p1;
+drop view v1;
+drop table t1;
+
 --echo # -----------------------------------------------------------------
 --echo # -- End of 5.5 tests.
 --echo # -----------------------------------------------------------------
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index b09ab09..29897e4 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -1,5 +1,5 @@
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates.
-# Copyright (c) 2008-2011, Monty Program Ab
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates.
+# Copyright (c) 2008, 2016, MariaDB
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
@@ -1057,8 +1057,8 @@
 # write_keys() and find_all_keys().
 # They both return ha_rows, which is platform dependent.
 #
-# The '...' wildcards are for 'fun:inline_mysql_file_write' which *may*
-# be inlined.
+# The '...' wildcards are for 'fun:inline_mysql_file_write' and
+# 'fun:find_all_keys' which *may* be inlined.
 {
    Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / one
    Memcheck:Param
@@ -1069,7 +1069,7 @@
    fun:my_b_flush_io_cache
    fun:_my_b_write
    fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_
-   fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_
+   ...
    fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy
 }
 
diff --git a/mysys/default.c b/mysys/default.c
index f235947..39c9b02 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -577,6 +577,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
                                      handle_default_option, (void *) &ctx,
                                      dirs)))
   {
+    delete_dynamic(&args);
     free_root(&alloc,MYF(0));
     DBUG_RETURN(error);
   }
diff --git a/mysys/file_logger.c b/mysys/file_logger.c
index 394b59f..b94cb70 100644
--- a/mysys/file_logger.c
+++ b/mysys/file_logger.c
@@ -14,11 +14,13 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 
+#ifndef FLOGGER_SKIP_INCLUDES
 #include "my_global.h"
 #include <my_sys.h>
 #include <m_string.h>
 #include <mysql/service_logger.h>
 #include <my_pthread.h>
+#endif /*FLOGGER_SKIP_INCLUDES*/
 
 #ifndef flogger_mutex_init
 #define flogger_mutex_init(A,B,C) mysql_mutex_init(A,B,C)
diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c
index 6ab6ba3..59f60f0 100644
--- a/mysys/lf_alloc-pin.c
+++ b/mysys/lf_alloc-pin.c
@@ -103,6 +103,12 @@
 #include <my_sys.h>
 #include <lf.h>
 
+/*
+  when using alloca() leave at least that many bytes of the stack -
+  for functions we might be calling from within this stack frame
+*/
+#define ALLOCA_SAFETY_MARGIN 8192
+
 #define LF_PINBOX_MAX_PINS 65536
 
 static void _lf_pinbox_real_free(LF_PINS *pins);
@@ -349,7 +355,8 @@ static void _lf_pinbox_real_free(LF_PINS *pins)
   {
     int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;
     /* create a sorted list of pinned addresses, to speed up searches */
-    if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size)
+    if (available_stack_size(&pinbox, *pins->stack_ends_here) >
+        alloca_size + ALLOCA_SAFETY_MARGIN)
     {
       struct st_harvester hv;
       addr= (void **) alloca(alloca_size);
diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c
index 38b212c..797c20e 100644
--- a/mysys/lf_hash.c
+++ b/mysys/lf_hash.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2010, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -45,7 +46,7 @@ const int LF_HASH_OVERHEAD= sizeof(LF_SLIST);
 
 /*
   a structure to pass the context (pointers two the three successive elements
-  in a list) from lfind to linsert/ldelete
+  in a list) from l_find to l_insert/l_delete
 */
 typedef struct {
   intptr volatile *prev;
@@ -72,7 +73,7 @@ typedef struct {
     cursor is positioned in either case
     pins[0..2] are used, they are NOT removed on return
 */
-static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
+static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
                  const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins)
 {
   uint32       cur_hashnr;
@@ -140,7 +141,7 @@ retry:
 /*
   DESCRIPTION
     insert a 'node' in the list that starts from 'head' in the correct
-    position (as found by lfind)
+    position (as found by l_find)
 
   RETURN
     0     - inserted
@@ -150,7 +151,7 @@ retry:
     it uses pins[0..2], on return all pins are removed.
     if there're nodes with the same key value, a new node is added before them.
 */
-static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
+static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
                          LF_SLIST *node, LF_PINS *pins, uint flags)
 {
   CURSOR         cursor;
@@ -158,7 +159,7 @@ static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
 
   for (;;)
   {
-    if (lfind(head, cs, node->hashnr, node->key, node->keylen,
+    if (l_find(head, cs, node->hashnr, node->key, node->keylen,
               &cursor, pins) &&
         (flags & LF_HASH_UNIQUE))
     {
@@ -202,7 +203,7 @@ static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
   NOTE
     it uses pins[0..2], on return all pins are removed.
 */
-static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
+static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
                    const uchar *key, uint keylen, LF_PINS *pins)
 {
   CURSOR cursor;
@@ -210,7 +211,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
 
   for (;;)
   {
-    if (!lfind(head, cs, hashnr, key, keylen, &cursor, pins))
+    if (!l_find(head, cs, hashnr, key, keylen, &cursor, pins))
     {
       res= 1; /* not found */
       break;
@@ -234,7 +235,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
             (to ensure the number of "set DELETED flag" actions
             is equal to the number of "remove from the list" actions)
           */
-          lfind(head, cs, hashnr, key, keylen, &cursor, pins);
+          l_find(head, cs, hashnr, key, keylen, &cursor, pins);
         }
         res= 0;
         break;
@@ -260,12 +261,12 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
     it uses pins[0..2], on return the pin[2] keeps the node found
     all other pins are removed.
 */
-static LF_SLIST *lsearch(LF_SLIST * volatile *head, CHARSET_INFO *cs,
+static LF_SLIST *l_search(LF_SLIST * volatile *head, CHARSET_INFO *cs,
                          uint32 hashnr, const uchar *key, uint keylen,
                          LF_PINS *pins)
 {
   CURSOR cursor;
-  int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins);
+  int res= l_find(head, cs, hashnr, key, keylen, &cursor, pins);
   if (res)
     _lf_pin(pins, 2, cursor.curr);
   else
@@ -365,7 +366,7 @@ void lf_hash_destroy(LF_HASH *hash)
    -1 - out of memory
 
   NOTE
-    see linsert() for pin usage notes
+    see l_insert() for pin usage notes
 */
 int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
 {
@@ -386,7 +387,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
   if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
     return -1;
   node->hashnr= my_reverse_bits(hashnr) | 1; /* normal node */
-  if (linsert(el, hash->charset, node, pins, hash->flags))
+  if (l_insert(el, hash->charset, node, pins, hash->flags))
   {
     _lf_alloc_free(pins, node);
     lf_rwunlock_by_pins(pins);
@@ -409,7 +410,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
     1 - didn't (not found)
    -1 - out of memory
   NOTE
-    see ldelete() for pin usage notes
+    see l_delete() for pin usage notes
 */
 int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
 {
@@ -429,7 +430,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
   */
   if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
     return -1;
-  if (ldelete(el, hash->charset, my_reverse_bits(hashnr) | 1,
+  if (l_delete(el, hash->charset, my_reverse_bits(hashnr) | 1,
               (uchar *)key, keylen, pins))
   {
     lf_rwunlock_by_pins(pins);
@@ -448,7 +449,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
     MY_ERRPTR    if OOM
 
   NOTE
-    see lsearch() for pin usage notes
+    see l_search() for pin usage notes
 */
 void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
 {
@@ -462,7 +463,7 @@ void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
     return MY_ERRPTR;
   if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
     return MY_ERRPTR;
-  found= lsearch(el, hash->charset, my_reverse_bits(hashnr) | 1,
+  found= l_search(el, hash->charset, my_reverse_bits(hashnr) | 1,
                  (uchar *)key, keylen, pins);
   lf_rwunlock_by_pins(pins);
   return found ? found+1 : 0;
@@ -490,16 +491,16 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node,
   dummy->hashnr= my_reverse_bits(bucket) | 0; /* dummy node */
   dummy->key= dummy_key;
   dummy->keylen= 0;
-  if ((cur= linsert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE)))
+  if ((cur= l_insert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE)))
   {
     my_free(dummy);
     dummy= cur;
   }
   my_atomic_casptr((void **)node, (void **)(char*) &tmp, dummy);
   /*
-    note that if the CAS above failed (after linsert() succeeded),
-    it would mean that some other thread has executed linsert() for
-    the same dummy node, its linsert() failed, it picked up our
+    note that if the CAS above failed (after l_insert() succeeded),
+    it would mean that some other thread has executed l_insert() for
+    the same dummy node, its l_insert() failed, it picked up our
     dummy node (in "dummy= cur") and executed the same CAS as above.
     Which means that even if CAS above failed we don't need to retry,
     and we should not free(dummy) - there's no memory leak here
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 21de1e9..82cb2cc 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -18,7 +18,6 @@
 #include "mysys_err.h"
 #include <my_dir.h> /* for stat */
 #include <m_string.h>
-#include "mysys_err.h"
 #if defined(HAVE_UTIME_H)
 #include <utime.h>
 #elif defined(HAVE_SYS_UTIME_H)
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index db026c1..c7aa7f1 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -72,7 +72,7 @@ err:
   return res;
 }
 
-#elif defined(__linux__) || defined(__sun__)
+#elif defined(__linux__) || defined(__sun)
 #include <net/if.h>
 #include <sys/ioctl.h>
 #include <net/if_arp.h>
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index c761064..07ba4f5 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    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
diff --git a/mysys/string.c b/mysys/string.c
index d979134..a63b1f5 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -142,16 +142,16 @@ my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n)
 my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
 {
 #ifdef __WIN__
-  const char *quote_str= "\"";
-  const uint  quote_len= 1;
+  LEX_CSTRING quote= { C_STRING_WITH_LEN("\"") };
+  LEX_CSTRING replace= { C_STRING_WITH_LEN("\\\"") };
 #else
-  const char *quote_str= "\'";
-  const uint  quote_len= 1;
+  LEX_CSTRING quote= { C_STRING_WITH_LEN("\'") };
+  LEX_CSTRING replace= { C_STRING_WITH_LEN("'\"'\"'") };
 #endif /* __WIN__ */
   my_bool ret= TRUE;
   va_list dirty_text;
 
-  ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */
+  ret&= dynstr_append_mem(str, quote.str, quote.length); /* Leading quote */
   va_start(dirty_text, append);
   while (append != NullS)
   {
@@ -159,18 +159,17 @@ my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
     const char *next_pos= cur_pos;
 
     /* Search for quote in each string and replace with escaped quote */
-    while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0')
+    while(*(next_pos= strcend(cur_pos, quote.str[0])) != '\0')
     {
       ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
-      ret&= dynstr_append_mem(str ,"\\", 1);
-      ret&= dynstr_append_mem(str, quote_str, quote_len);
+      ret&= dynstr_append_mem(str, replace.str, replace.length);
       cur_pos= next_pos + 1;
     }
     ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
     append= va_arg(dirty_text, char *);
   }
   va_end(dirty_text);
-  ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */
+  ret&= dynstr_append_mem(str, quote.str, quote.length); /* Trailing quote */
 
   return ret;
 }
diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc
index a06c0e6..79436bd 100644
--- a/plugin/feedback/feedback.cc
+++ b/plugin/feedback/feedback.cc
@@ -29,7 +29,7 @@ ulong debug_startup_interval, debug_first_interval, debug_interval;
 char server_uid_buf[SERVER_UID_SIZE+1]; ///< server uid will be written here
 
 /* backing store for system variables */
-static char *server_uid= server_uid_buf, *url;
+static char *server_uid= server_uid_buf, *url, *http_proxy;
 char *user_info;
 ulong send_timeout, send_retry_wait;
 
@@ -284,7 +284,13 @@ static int init(void *p)
       if (*e == 0 || *e == ' ')
       {
         if (e > s && (urls[slot]= Url::create(s, e - s)))
+        {
+          if (urls[slot]->set_proxy(http_proxy,
+                                    http_proxy ? strlen(http_proxy) : 0))
+            sql_print_error("feedback plugin: invalid proxy '%s'",
+                            http_proxy ? http_proxy : "");
           slot++;
+        }
         else
         {
           if (e > s)
@@ -362,6 +368,9 @@ static MYSQL_SYSVAR_ULONG(send_timeout, send_timeout, PLUGIN_VAR_RQCMDARG,
 static MYSQL_SYSVAR_ULONG(send_retry_wait, send_retry_wait, PLUGIN_VAR_RQCMDARG,
        "Wait this many seconds before retrying a failed send.",
        NULL, NULL, 60, 1, 60*60*24, 1);
+static MYSQL_SYSVAR_STR(http_proxy, http_proxy,
+                        PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
+       "Proxy server host:port.", NULL, NULL,0);
 
 #ifndef DBUG_OFF
 static MYSQL_SYSVAR_ULONG(debug_startup_interval, debug_startup_interval,
@@ -381,6 +390,7 @@ static struct st_mysql_sys_var* settings[] = {
   MYSQL_SYSVAR(url),
   MYSQL_SYSVAR(send_timeout),
   MYSQL_SYSVAR(send_retry_wait),
+  MYSQL_SYSVAR(http_proxy),
 #ifndef DBUG_OFF
   MYSQL_SYSVAR(debug_startup_interval),
   MYSQL_SYSVAR(debug_first_interval),
diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h
index 98939c2..0542b73 100644
--- a/plugin/feedback/feedback.h
+++ b/plugin/feedback/feedback.h
@@ -51,8 +51,14 @@ class Url {
   const char *url()   { return full_url.str; }
   size_t url_length() { return full_url.length; }
   virtual int send(const char* data, size_t data_length) =  0;
+  virtual int set_proxy(const char *proxy, size_t proxy_len)
+  {
+    return 0;
+  }
 
   static Url* create(const char *url, size_t url_length);
+  static int parse_proxy_server(const char *proxy_server, size_t proxy_length,
+                                LEX_STRING *host, LEX_STRING *port);
 };
 
 extern Url **urls;
diff --git a/plugin/feedback/url_base.cc b/plugin/feedback/url_base.cc
index e7d038f..6afbcd7 100644
--- a/plugin/feedback/url_base.cc
+++ b/plugin/feedback/url_base.cc
@@ -48,4 +48,49 @@ Url* Url::create(const char *url, size_t url_length)
   return self;
 }
 
+int Url::parse_proxy_server(const char *proxy_server, size_t proxy_length,
+                            LEX_STRING *host, LEX_STRING *port)
+{
+  const char *s;
+
+  host->length= 0;
+  if (proxy_server == NULL)
+    return 0;
+
+  for (; proxy_length > 0 && my_isspace(system_charset_info, *proxy_server);
+         proxy_server++, proxy_length--) /* no-op */;
+
+  if (proxy_length == 0)
+    return 0;
+
+  for (s=proxy_server; *s && *s != ':'; s++) /* no-op */;
+
+  host->str= const_cast<char*>(proxy_server);
+  if ((host->length= s-proxy_server) == 0)
+    return 0;
+
+  port->length= 0;
+
+  if (*s == ':')
+  {
+    s++;
+    port->str= const_cast<char*>(s);
+    while (*s >= '0' && *s <= '9')
+    {
+      s++;
+      port->length++;
+    }
+  }
+
+  if (port->length == 0)
+  {
+    port->str= const_cast<char*>("80");
+    port->length= 2;
+  }
+
+  host->str= my_strndup(host->str, host->length, MYF(MY_WME));
+  port->str= my_strndup(port->str, port->length, MYF(MY_WME));
+  return 0;
+}
+
 } // namespace feedback
diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc
index dd39adb..dff5da5 100644
--- a/plugin/feedback/url_http.cc
+++ b/plugin/feedback/url_http.cc
@@ -38,20 +38,39 @@ class Url_http: public Url {
   protected:
   const LEX_STRING host, port, path;
   bool ssl;
+  LEX_STRING proxy_host, proxy_port;
+
+  int use_proxy()
+  {
+    return proxy_host.length;
+  }
 
   Url_http(LEX_STRING &url_arg, LEX_STRING &host_arg,
           LEX_STRING &port_arg, LEX_STRING &path_arg, bool ssl_arg) :
     Url(url_arg), host(host_arg), port(port_arg), path(path_arg), ssl(ssl_arg)
-    {}
+    {
+      proxy_host.length= 0;
+    }
   ~Url_http()
   {
     my_free(host.str);
     my_free(port.str);
     my_free(path.str);
+    set_proxy(0,0);
   }
 
   public:
   int send(const char* data, size_t data_length);
+  int set_proxy(const char *proxy, size_t proxy_len)
+  {
+    if (use_proxy())
+    {
+      my_free(proxy_host.str);
+      my_free(proxy_port.str);
+    }
+
+    return parse_proxy_server(proxy, proxy_len, &proxy_host, &proxy_port);
+  }
 
   friend Url* http_create(const char *url, size_t url_length);
 };
@@ -150,7 +169,9 @@ int Url_http::send(const char* data, size_t data_length)
   uint len= 0;
 
   addrinfo *addrs, *addr, filter= {0, AF_UNSPEC, SOCK_STREAM, 6, 0, 0, 0, 0};
-  int res= getaddrinfo(host.str, port.str, &filter, &addrs);
+  int res= use_proxy() ?
+    getaddrinfo(proxy_host.str, proxy_port.str, &filter, &addrs) :
+    getaddrinfo(host.str, port.str, &filter, &addrs);
 
   if (res)
   {
@@ -228,16 +249,20 @@ int Url_http::send(const char* data, size_t data_length)
   };
 
   len= my_snprintf(buf, sizeof(buf),
-                   "POST %s HTTP/1.0\r\n"
-                   "User-Agent: MariaDB User Feedback Plugin\r\n"
-                   "Host: %s:%s\r\n"
-                   "Accept: */*\r\n"
-                   "Content-Length: %u\r\n"
-                   "Content-Type: multipart/form-data; boundary=%s\r\n"
-                   "\r\n",
-                   path.str, host.str, port.str,
-                   (uint)(2*boundary.length + header.length + data_length + 4),
-                   boundary.str + 2);
+                   use_proxy() ? "POST http://%s:%s/" : "POST ",
+                   host.str, port.str);
+
+  len+= my_snprintf(buf+len, sizeof(buf)-len,
+                    "%s HTTP/1.0\r\n"
+                    "User-Agent: MariaDB User Feedback Plugin\r\n"
+                    "Host: %s:%s\r\n"
+                    "Accept: */*\r\n"
+                    "Content-Length: %u\r\n"
+                    "Content-Type: multipart/form-data; boundary=%s\r\n"
+                    "\r\n",
+                    path.str, host.str, port.str,
+                    (uint)(2*boundary.length + header.length + data_length + 4),
+                    boundary.str + 2);
 
   vio_timeout(vio, FOR_READING, send_timeout);
   vio_timeout(vio, FOR_WRITING, send_timeout);
diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc
index 625f744..3c22bcb 100644
--- a/plugin/semisync/semisync_master.cc
+++ b/plugin/semisync/semisync_master.cc
@@ -1,6 +1,6 @@
 /* Copyright (C) 2007 Google Inc.
-   Copyright (c) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
-   Use is subject to license terms.
+   Copyright (c) 2008, 2013, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    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
diff --git a/plugin/server_audit/CMakeLists.txt b/plugin/server_audit/CMakeLists.txt
index 527d0d7..3de8c43 100644
--- a/plugin/server_audit/CMakeLists.txt
+++ b/plugin/server_audit/CMakeLists.txt
@@ -13,4 +13,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-MYSQL_ADD_PLUGIN(server_audit server_audit.c MODULE_ONLY)
+SET(SERVER_AUDIT_SOURCES
+   server_audit.c test_audit_v4.c plugin_audit_v4.h)
+
+ MYSQL_ADD_PLUGIN(server_audit ${SERVER_AUDIT_SOURCES} MODULE_ONLY)
diff --git a/plugin/server_audit/plugin_audit_v4.h b/plugin/server_audit/plugin_audit_v4.h
new file mode 100644
index 0000000..5f8e43b
--- /dev/null
+++ b/plugin/server_audit/plugin_audit_v4.h
@@ -0,0 +1,561 @@
+/* Copyright (c) 2007, 2015, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#ifndef _my_audit_h
+#define _my_audit_h
+
+#ifndef PLUGIN_CONTEXT
+#include "plugin.h"
+#include "mysql/mysql_lex_string.h"
+#ifndef MYSQL_ABI_CHECK
+#include "m_string.h"
+#endif
+#include "my_command.h"
+#include "my_sqlcommand.h"
+#endif /*PLUGIN_CONTEXT*/
+
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0401
+
+/**
+ @enum mysql_event_class_t
+
+ Audit event classes.
+*/
+typedef enum
+{
+  MYSQL_AUDIT_GENERAL_CLASS          = 0,
+  MYSQL_AUDIT_CONNECTION_CLASS       = 1,
+  MYSQL_AUDIT_PARSE_CLASS            = 2,
+  MYSQL_AUDIT_AUTHORIZATION_CLASS    = 3,
+  MYSQL_AUDIT_TABLE_ACCESS_CLASS     = 4,
+  MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS  = 5,
+  MYSQL_AUDIT_SERVER_STARTUP_CLASS   = 6,
+  MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS  = 7,
+  MYSQL_AUDIT_COMMAND_CLASS          = 8,
+  MYSQL_AUDIT_QUERY_CLASS            = 9,
+  MYSQL_AUDIT_STORED_PROGRAM_CLASS   = 10,
+  /* This item must be last in the list. */
+  MYSQL_AUDIT_CLASS_MASK_SIZE
+} mysql_event_class_t;
+
+/**
+  @struct st_mysql_audit
+
+  The descriptor structure that is referred from st_mysql_plugin.
+*/
+struct st_mysql_audit
+{
+  /**
+    Interface version.
+  */
+  int interface_version;
+
+  /**
+    Event occurs when the event class consumer is to be
+    disassociated from the specified THD.This would typically occur
+    before some operation which may require sleeping - such as when
+    waiting for the next query from the client.
+  */
+  void (*release_thd)(MYSQL_THD);
+
+  /**
+    Invoked whenever an event occurs which is of any
+    class for which the plugin has interest.The second argument
+    indicates the specific event class and the third argument is data
+    as required for that class.
+  */
+  int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
+
+  /**
+    An array of bits used to indicate what event classes
+    that this plugin wants to receive.
+  */
+  unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
+};
+
+/**
+  @typedef enum_sql_command_t
+
+  SQL command type definition.
+*/
+typedef enum enum_sql_command enum_sql_command_t;
+
+/**
+  @enum mysql_event_general_subclass_t
+
+  Events for the MYSQL_AUDIT_GENERAL_CLASS event class.
+*/
+typedef enum
+{
+  /** occurs before emitting to the general query log. */
+  MYSQL_AUDIT_GENERAL_LOG    = 1 << 0,
+  /** occurs before transmitting errors to the user. */
+  MYSQL_AUDIT_GENERAL_ERROR  = 1 << 1,
+  /** occurs after transmitting a resultset to the user. */
+  MYSQL_AUDIT_GENERAL_RESULT = 1 << 2,
+  /** occurs after transmitting a resultset or errors */
+  MYSQL_AUDIT_GENERAL_STATUS = 1 << 3
+} mysql_event_general_subclass_t;
+
+#define MYSQL_AUDIT_GENERAL_ALL (MYSQL_AUDIT_GENERAL_LOG | \
+                                 MYSQL_AUDIT_GENERAL_ERROR | \
+                                 MYSQL_AUDIT_GENERAL_RESULT | \
+                                 MYSQL_AUDIT_GENERAL_STATUS)
+/**
+  @struct mysql_event_general
+
+  Structure for the MYSQL_AUDIT_GENERAL_CLASS event class.
+*/
+struct mysql_event_general
+{
+  mysql_event_general_subclass_t event_subclass;
+  int                            general_error_code;
+  unsigned long                  general_thread_id;
+  MYSQL_LEX_CSTRING              general_user;
+  MYSQL_LEX_CSTRING              general_command;
+  MYSQL_LEX_CSTRING              general_query;
+  struct charset_info_st         *general_charset;
+  unsigned long long             general_time;
+  unsigned long long             general_rows;
+  MYSQL_LEX_CSTRING              general_host;
+  MYSQL_LEX_CSTRING              general_sql_command;
+  MYSQL_LEX_CSTRING              general_external_user;
+  MYSQL_LEX_CSTRING              general_ip;
+};
+
+/**
+  @enum mysql_event_connection_subclass_t
+
+  Events for MYSQL_AUDIT_CONNECTION_CLASS event class.
+*/
+typedef enum
+{
+  /** occurs after authentication phase is completed. */
+  MYSQL_AUDIT_CONNECTION_CONNECT          = 1 << 0,
+  /** occurs after connection is terminated. */
+  MYSQL_AUDIT_CONNECTION_DISCONNECT       = 1 << 1,
+  /** occurs after COM_CHANGE_USER RPC is completed. */
+  MYSQL_AUDIT_CONNECTION_CHANGE_USER      = 1 << 2,
+  /** occurs before authentication. */
+  MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE = 1 << 3
+} mysql_event_connection_subclass_t;
+
+#define MYSQL_AUDIT_CONNECTION_ALL (MYSQL_AUDIT_CONNECTION_CONNECT | \
+                                    MYSQL_AUDIT_CONNECTION_DISCONNECT | \
+                                    MYSQL_AUDIT_CONNECTION_CHANGE_USER | \
+                                    MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE)
+/**
+  @struct mysql_event_connection
+
+  Structure for the MYSQL_AUDIT_CONNECTION_CLASS event class.
+*/
+struct mysql_event_connection
+{
+  /** Event subclass. */
+  mysql_event_connection_subclass_t event_subclass;
+  /** Current status of the connection. */
+  int                               status;
+  /** Connection id. */
+  unsigned long                     connection_id;
+  /** User name of this connection. */
+  MYSQL_LEX_CSTRING                 user;
+  /** Priv user name. */
+  MYSQL_LEX_CSTRING                 priv_user;
+  /** External user name. */
+  MYSQL_LEX_CSTRING                 external_user;
+  /** Proxy user used for this connection. */
+  MYSQL_LEX_CSTRING                 proxy_user;
+  /** Connection host. */
+  MYSQL_LEX_CSTRING                 host;
+  /** IP of the connection. */
+  MYSQL_LEX_CSTRING                 ip;
+  /** Database name specified at connection time. */
+  MYSQL_LEX_CSTRING                 database;
+  /** Connection type:
+        - 0 Undefined
+        - 1 TCP/IP
+        - 2 Socket
+        - 3 Named pipe
+        - 4 SSL
+        - 5 Shared memory
+  */
+  int                               connection_type;
+};
+
+/**
+ at enum mysql_event_parse_subclass_t
+
+Events for MYSQL_AUDIT_PARSE_CLASS event class.
+*/
+typedef enum
+{
+  /** occurs before the query parsing. */
+  MYSQL_AUDIT_PARSE_PREPARSE  = 1 << 0,
+  /** occurs after the query parsing. */
+  MYSQL_AUDIT_PARSE_POSTPARSE = 1 << 1
+} mysql_event_parse_subclass_t;
+
+#define MYSQL_AUDIT_PARSE_ALL (MYSQL_AUDIT_PARSE_PREPARSE | \
+                               MYSQL_AUDIT_PARSE_POSTPARSE)
+
+typedef enum
+{
+  MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_NONE                  = 0,
+  /// mysql_event_parse::flags Must be set by a plugin if the query is rewritten.
+  MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_QUERY_REWRITTEN       = 1 << 0,
+  /// mysql_event_parse::flags Is set by the server if the query is prepared statement.
+  MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_IS_PREPARED_STATEMENT = 1 << 1
+} mysql_event_parse_rewrite_plugin_flag;
+
+/** Data for the MYSQL_AUDIT_PARSE events */
+struct mysql_event_parse
+{
+  /** MYSQL_AUDIT_[PRE|POST]_PARSE event id */
+  mysql_event_parse_subclass_t           event_subclass;
+
+  /** one of FLAG_REWRITE_PLUGIN_* */
+  mysql_event_parse_rewrite_plugin_flag *flags;
+
+  /** input: the original query text */
+  MYSQL_LEX_CSTRING                     query;
+
+  /** output: returns the null-terminated rewriten query allocated by my_malloc() */
+  MYSQL_LEX_CSTRING                     *rewritten_query;
+};
+
+/**
+  @enum mysql_event_authorization_subclass_t
+
+  Events for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
+*/
+typedef enum
+{
+  MYSQL_AUDIT_AUTHORIZATION_USER      = 1 << 0,
+  /** Occurs when database privilege is checked. */
+  MYSQL_AUDIT_AUTHORIZATION_DB        = 1 << 1,
+  /** Occurs when table privilege is checked. */
+  MYSQL_AUDIT_AUTHORIZATION_TABLE     = 1 << 2,
+  /** Occurs when column privilege is checked. */
+  MYSQL_AUDIT_AUTHORIZATION_COLUMN    = 1 << 3,
+  /** Occurs when procedure privilege is checked. */
+  MYSQL_AUDIT_AUTHORIZATION_PROCEDURE = 1 << 4,
+  /** Occurs when proxy privilege is checked. */
+  MYSQL_AUDIT_AUTHORIZATION_PROXY     = 1 << 5
+} mysql_event_authorization_subclass_t;
+
+#define MYSQL_AUDIT_AUTHORIZATION_ALL (MYSQL_AUDIT_AUTHORIZATION_USER | \
+                                       MYSQL_AUDIT_AUTHORIZATION_DB | \
+                                       MYSQL_AUDIT_AUTHORIZATION_TABLE | \
+                                       MYSQL_AUDIT_AUTHORIZATION_COLUMN  | \
+                                       MYSQL_AUDIT_AUTHORIZATION_PROCEDURE | \
+                                       MYSQL_AUDIT_AUTHORIZATION_PROXY)
+/**
+  @struct mysql_event_authorization
+
+  Structure for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
+*/
+struct mysql_event_authorization
+{
+  /** Event subclass. */
+  mysql_event_authorization_subclass_t event_subclass;
+  /** Event status. */
+  int                                  status;
+  /** Connection id. */
+  unsigned int                         connection_id;
+  /** SQL command id. */
+  enum_sql_command_t                   sql_command_id;
+  /** SQL query text. */
+  MYSQL_LEX_CSTRING                    query;
+  /** SQL query charset. */
+  const struct charset_info_st         *query_charset;
+  /** Database name. */
+  MYSQL_LEX_CSTRING                    database;
+  /** Table name. */
+  MYSQL_LEX_CSTRING                    table;
+  /** Other name associated with the event. */
+  MYSQL_LEX_CSTRING                    object;
+  /** Requested authorization privileges. */
+  unsigned long                        requested_privilege;
+  /** Currently granted authorization privileges. */
+  unsigned long                        granted_privilege;
+};
+
+/**
+  @enum mysql_event_table_row_access_subclass_t
+
+  Events for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
+*/
+typedef enum
+{
+  /** Occurs when table data are read. */
+  MYSQL_AUDIT_TABLE_ACCESS_READ   = 1 << 0,
+  /** Occurs when table data are inserted. */
+  MYSQL_AUDIT_TABLE_ACCESS_INSERT = 1 << 1,
+  /** Occurs when table data are updated. */
+  MYSQL_AUDIT_TABLE_ACCESS_UPDATE = 1 << 2,
+  /** Occurs when table data are deleted. */
+  MYSQL_AUDIT_TABLE_ACCESS_DELETE = 1 << 3
+} mysql_event_table_access_subclass_t;
+
+#define MYSQL_AUDIT_TABLE_ACCESS_ALL (MYSQL_AUDIT_TABLE_ACCESS_READ | \
+                                      MYSQL_AUDIT_TABLE_ACCESS_INSERT | \
+                                      MYSQL_AUDIT_TABLE_ACCESS_UPDATE | \
+                                      MYSQL_AUDIT_TABLE_ACCESS_DELETE)
+
+/**
+  @struct mysql_event_table_row_access
+
+  Structure for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
+*/
+struct mysql_event_table_access
+{
+  /** Event subclass. */
+  mysql_event_table_access_subclass_t event_subclass;
+  /** Connection id. */
+  unsigned long                           connection_id;
+  /** SQL command id. */
+  enum_sql_command_t                      sql_command_id;
+  /** SQL query. */
+  MYSQL_LEX_CSTRING                       query;
+  /** SQL query charset. */
+  const struct charset_info_st            *query_charset;
+  /** Database name. */
+  MYSQL_LEX_CSTRING                       table_database;
+  /** Table name. */
+  MYSQL_LEX_CSTRING                       table_name;
+};
+
+/**
+  @enum mysql_event_global_variable_subclass_t
+
+  Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class.
+*/
+typedef enum
+{
+  /** Occurs when global variable is retrieved. */
+  MYSQL_AUDIT_GLOBAL_VARIABLE_GET = 1 << 0,
+  /** Occurs when global variable is set. */
+  MYSQL_AUDIT_GLOBAL_VARIABLE_SET = 1 << 1
+} mysql_event_global_variable_subclass_t;
+
+#define MYSQL_AUDIT_GLOBAL_VARIABLE_ALL (MYSQL_AUDIT_GLOBAL_VARIABLE_GET | \
+                                         MYSQL_AUDIT_GLOBAL_VARIABLE_SET)
+
+/** Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class. */
+struct mysql_event_global_variable
+{
+  /** Event subclass. */
+  mysql_event_global_variable_subclass_t event_subclass;
+  /** Connection id. */
+  unsigned long                          connection_id;
+  /** SQL command id. */
+  enum_sql_command_t                     sql_command_id;
+  /** Variable name. */
+  MYSQL_LEX_CSTRING                      variable_name;
+  /** Variable value. */
+  MYSQL_LEX_CSTRING                      variable_value;
+};
+
+/**
+  @enum mysql_event_server_startup_subclass_t
+
+  Events for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
+*/
+typedef enum
+{
+  /** Occurs after all subsystem are initialized during system start. */
+  MYSQL_AUDIT_SERVER_STARTUP_STARTUP = 1 << 0
+} mysql_event_server_startup_subclass_t;
+
+#define MYSQL_AUDIT_SERVER_STARTUP_ALL (MYSQL_AUDIT_SERVER_STARTUP_STARTUP)
+
+/**
+  @struct mysql_event_server_startup
+
+  Structure for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
+*/
+struct mysql_event_server_startup
+{
+  /** Event subclass. */
+  mysql_event_server_startup_subclass_t event_subclass;
+  /** Command line arguments. */
+  const char                            **argv;
+  /** Command line arguments count. */
+  unsigned int                          argc;
+};
+
+/**
+  @enum mysql_event_server_shutdown_subclass_t
+
+  Events for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
+*/
+typedef enum
+{
+  /** Occurs when global variable is set. */
+  MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN = 1 << 0
+} mysql_event_server_shutdown_subclass_t;
+
+#define MYSQL_AUDIT_SERVER_SHUTDOWN_ALL (MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN)
+
+/**
+  @enum mysql_server_shutdown_reason_t
+
+  Server shutdown reason.
+*/
+typedef enum
+{
+  /** User requested shut down. */
+  MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
+  /** The server aborts. */
+  MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT
+} mysql_server_shutdown_reason_t;
+
+/**
+  @struct mysql_event_server_shutdown
+
+  Structure for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
+*/
+struct mysql_event_server_shutdown
+{
+  /** Shutdown event. */
+  mysql_event_server_shutdown_subclass_t event_subclass;
+  /** Exit code associated with the shutdown event. */
+  int                                    exit_code;
+  /** Shutdown reason. */
+  mysql_server_shutdown_reason_t         reason;
+};
+
+/**
+  @enum mysql_event_command_subclass_t
+
+  Events for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+typedef enum
+{
+  /** Command start event. */
+  MYSQL_AUDIT_COMMAND_START = 1 << 0,
+  /** Command end event. */
+  MYSQL_AUDIT_COMMAND_END   = 1 << 1
+} mysql_event_command_subclass_t;
+
+#define MYSQL_AUDIT_COMMAND_ALL (MYSQL_AUDIT_COMMAND_START | \
+                                 MYSQL_AUDIT_COMMAND_END)
+/**
+  @typedef enum_server_command_t
+
+  Server command type definition.
+*/
+typedef enum enum_server_command enum_server_command_t;
+
+/**
+  @struct mysql_event_command
+
+  Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+  Events generated as a result of RPC command requests.
+*/
+struct mysql_event_command
+{
+  /** Command event subclass. */
+  mysql_event_command_subclass_t event_subclass;
+  /** Command event status. */
+  int                            status;
+  /** Connection id. */
+  unsigned long                  connection_id;
+  /** Command id. */
+  enum_server_command_t          command_id;
+};
+
+/**
+  @enum mysql_event_query_subclass_t
+
+  Events for MYSQL_AUDIT_QUERY_CLASS event class.
+*/
+typedef enum
+{
+  /** Query start event. */
+  MYSQL_AUDIT_QUERY_START             = 1 << 0,
+  /** Nested query start event. */
+  MYSQL_AUDIT_QUERY_NESTED_START      = 1 << 1,
+  /** Query post parse event. */
+  MYSQL_AUDIT_QUERY_STATUS_END        = 1 << 2,
+  /** Nested query status end event. */
+  MYSQL_AUDIT_QUERY_NESTED_STATUS_END = 1 << 3
+} mysql_event_query_subclass_t;
+
+#define MYSQL_AUDIT_QUERY_ALL (MYSQL_AUDIT_QUERY_START | \
+                               MYSQL_AUDIT_QUERY_NESTED_START | \
+                               MYSQL_AUDIT_QUERY_STATUS_END | \
+                               MYSQL_AUDIT_QUERY_NESTED_STATUS_END)
+/**
+  @struct mysql_event_command
+
+  Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+struct mysql_event_query
+{
+  /** Event subclass. */
+  mysql_event_query_subclass_t event_subclass;
+  /** Event status. */
+  int                          status;
+  /** Connection id. */
+  unsigned long                connection_id;
+  /** SQL command id. */
+  enum_sql_command_t           sql_command_id;
+  /** SQL query. */
+  MYSQL_LEX_CSTRING            query;
+  /** SQL query charset. */
+  const struct charset_info_st *query_charset;
+};
+
+/**
+  @enum mysql_event_stored_program_subclass_t
+
+  Events for MYSQL_AUDIT_STORED_PROGRAM_CLASS event class.
+*/
+typedef enum
+{
+  /** Stored program execution event. */
+  MYSQL_AUDIT_STORED_PROGRAM_EXECUTE = 1 << 0
+} mysql_event_stored_program_subclass_t;
+
+#define MYSQL_AUDIT_STORED_PROGRAM_ALL (MYSQL_AUDIT_STORED_PROGRAM_EXECUTE)
+
+/**
+  @struct mysql_event_command
+
+Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+struct mysql_event_stored_program
+{
+  /** Event subclass. */
+  mysql_event_stored_program_subclass_t event_subclass;
+  /** Connection id. */
+  unsigned long                         connection_id;
+  /** SQL command id. */
+  enum_sql_command_t                    sql_command_id;
+  /** SQL query text. */
+  MYSQL_LEX_CSTRING                     query;
+  /** SQL query charset. */
+  const struct charset_info_st          *query_charset;
+  /** The Database the procedure is defined in. */
+  MYSQL_LEX_CSTRING                     database;
+  /** Name of the stored program. */
+  MYSQL_LEX_CSTRING                     name;
+  /** Stored program parameters. */
+  void                                  *parameters;
+};
+
+#endif
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index bede4c9..30b7cdb 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Alexey Botchkov and SkySQL Ab
+/* Copyright (C) 2013, 2015, Alexey Botchkov and SkySQL Ab
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -14,13 +14,16 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 
-#define PLUGIN_VERSION 0x103
-#define PLUGIN_STR_VERSION "1.3.0"
+#define PLUGIN_VERSION 0x104
+#define PLUGIN_STR_VERSION "1.4.0"
+
+#define _my_thread_var loc_thread_var
 
 #include <my_config.h>
 #include <stdio.h>
 #include <time.h>
 #include <string.h>
+#include <fcntl.h>
 
 #ifndef _WIN32
 #include <syslog.h>
@@ -80,8 +83,7 @@ static void closelog() {}
 #endif /*MARIADB_ONLY*/
 
 #include <my_base.h>
-//#include <hash.h>
-#include <my_dir.h>
+//#include <my_dir.h>
 #include <typelib.h>
 #include <mysql/plugin.h>
 #include <mysql/plugin_audit.h>
@@ -89,65 +91,176 @@ static void closelog() {}
 #define RTLD_DEFAULT NULL
 #endif
 
-#undef my_init_dynamic_array_ci
-#define init_dynamic_array2 loc_init_dynamic_array2
-#define my_init_dynamic_array_ci(A,B,C,D) loc_init_dynamic_array2(A,B,NULL,C,D)
-#define _my_hash_init loc_my_hash_init
-#define my_hash_search loc_my_hash_search
-#define my_hash_insert loc_my_hash_insert
-#define my_hash_delete loc_my_hash_delete
-#define my_hash_update loc_my_hash_update
-#define my_hash_free loc_my_hash_free
-#define my_hash_first loc_my_hash_first
-#define my_hash_reset loc_my_hash_reset
-#define my_hash_search_using_hash_value loc_my_hash_search_using_hash_value
-#define my_hash_first_from_hash_value loc_my_hash_first_from_hash_value
-#define my_calc_hash loc_my_calc_hash
-#undef my_hash_first_from_hash_value
-#define my_hash_first_from_hash_value loc_my_my_hash_first_from_hash_value
-#define my_hash_next loc_my_hash_next
-#define my_hash_element loc_my_hash_element
-#define my_hash_replace loc_my_hash_replace
-#define my_hash_iterate loc_my_hash_iterate
-
-#define alloc_dynamic loc_alloc_dynamic
-#define pop_dynamic loc_pop_dynamic
-#define delete_dynamic loc_delete_dynamic
-uchar *loc_alloc_dynamic(DYNAMIC_ARRAY *array);
-#ifdef my_strnncoll
-#undef my_strnncoll
-#define my_strnncoll(s, a, b, c, d) (my_strnncoll_binary((s), (a), (b), (c), (d), 0))
-#endif
-
-static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
-    const uchar *s, size_t slen,
-    const uchar *t, size_t tlen,
-    my_bool t_is_prefix)
-{
-  size_t len=min(slen,tlen);
-  int cmp= memcmp(s,t,len);
-  return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
-}
-
-#include "../../mysys/array.c"
-#include "../../mysys/hash.c"
-
 #ifndef MARIADB_ONLY
 #undef MYSQL_SERVICE_LOGGER_INCLUDED
 #undef MYSQL_DYNAMIC_PLUGIN
 #define FLOGGER_NO_PSI
-#define flogger_mutex_init(A,B,C) pthread_mutex_init(&(B)->m_mutex, C)
-#define flogger_mutex_destroy(A) pthread_mutex_destroy(&(A)->m_mutex)
-#define flogger_mutex_lock(A) pthread_mutex_lock(&(A)->m_mutex)
-#define flogger_mutex_unlock(A) pthread_mutex_unlock(&(A)->m_mutex)
+
+/* How to access the pthread_mutex in mysql_mutex_t */
+//#ifdef SAFE_MUTEX
+//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
+//#elif defined(MY_PTHREAD_FASTMUTEX)
+//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
+//#else
+#define mysql_mutex_real_mutex(A) &(A)->m_mutex
+//#endif
+
+#define flogger_mutex_init(A,B,C) do{}while(0)
+#define flogger_mutex_destroy(A) do{}while(0)
+#define flogger_mutex_lock(A) do{}while(0)
+#define flogger_mutex_unlock(A) do{}while(0)
 
 static char **int_mysql_data_home;
 static char *default_home= (char *)".";
 #define mysql_data_home (*int_mysql_data_home)
 
+#define FLOGGER_SKIP_INCLUDES
+#define my_open(A, B, C) loc_open(A, B)
+#define my_close(A, B) loc_close(A)
+#define my_rename(A, B, C) loc_rename(A, B)
+#define my_tell(A, B) loc_tell(A)
+#define my_write(A, B, C, D) loc_write(A, B, C)
+#define my_malloc(A, B) malloc(A)
+#define my_free(A) free(A)
+#ifdef my_errno
+  #undef my_errno
+#endif
+static int loc_file_errno;
+#define my_errno loc_file_errno
+#ifdef my_vsnprintf
+  #undef my_vsnprintf
+#endif
+#define my_vsnprintf vsnprintf
+#define logger_open loc_logger_open
+#define logger_close loc_logger_close
+#define logger_write loc_logger_write
+#define logger_rotate loc_logger_rotate
+#define logger_init_mutexts loc_logger_init_mutexts
+
+
+static size_t loc_write(File Filedes, const uchar *Buffer, size_t Count)
+{
+  size_t writtenbytes;
+#ifdef _WIN32
+  writtenbytes= my_win_write(Filedes, Buffer, Count);
+#else
+  writtenbytes= write(Filedes, Buffer, Count);
+#endif
+  return writtenbytes;
+}
+
+
+static File loc_open(const char *FileName, int Flags)
+				/* Path-name of file */
+				/* Read | write .. */
+				/* Special flags */
+{
+  File fd;
+#if defined(_WIN32)
+  fd= my_win_open(FileName, Flags);
+#elif !defined(NO_OPEN_3)
+  fd = open(FileName, Flags, my_umask);     /* Normal unix */
+#else
+  fd = open((char *) FileName, Flags);
+#endif
+  my_errno= errno;
+  return fd;
+} 
+
+
+static int loc_close(File fd)
+{
+  int err;
+#ifndef _WIN32
+  do
+  {
+    err= close(fd);
+  } while (err == -1 && errno == EINTR);
+#else
+  err= my_win_close(fd);
+#endif
+  my_errno=errno;
+  return err;
+}
+
+
+static int loc_rename(const char *from, const char *to)
+{
+  int error = 0;
+
+#if defined(__WIN__)
+  if (!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED |
+                            MOVEFILE_REPLACE_EXISTING))
+  {
+    my_osmaperr(GetLastError());
+#elif defined(HAVE_RENAME)
+  if (rename(from,to))
+  {
+#else
+  if (link(from, to) || unlink(from))
+  {
+#endif
+    my_errno=errno;
+    error = -1;
+  }
+  return error;
+}
+
+
+static my_off_t loc_seek(File fd, my_off_t pos, int whence)
+{
+  os_off_t newpos= -1;
+#ifdef _WIN32
+  newpos= my_win_lseek(fd, pos, whence);
+#else
+  newpos= lseek(fd, pos, whence);
+#endif
+  if (newpos == (os_off_t) -1)
+  {
+    my_errno= errno;
+    return MY_FILEPOS_ERROR;
+  }
+
+  return (my_off_t) newpos;
+}
+
+
+static my_off_t loc_tell(File fd)
+{
+  os_off_t pos;
+#if defined (HAVE_TELL) && !defined (_WIN32)
+  pos= tell(fd);
+#else
+  pos= loc_seek(fd, 0L, MY_SEEK_CUR);
+#endif
+  if (pos == (os_off_t) -1)
+  {
+    my_errno= errno;
+  }
+  return (my_off_t) pos;
+}
+
+#ifdef HAVE_PSI_INTERFACE
+#undef HAVE_PSI_INTERFACE
+#include <mysql/service_logger.h>
+#include "../../mysys/file_logger.c"
+#define HAVE_PSI_INTERFACE
+#else
+#include <mysql/service_logger.h>
 #include "../../mysys/file_logger.c"
+#endif
 #endif /*!MARIADB_ONLY*/
 
+#undef flogger_mutex_init
+#undef flogger_mutex_destroy
+#undef flogger_mutex_lock
+#undef flogger_mutex_unlock
+
+#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C)
+#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A))
+#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A))
+#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A))
+
 #ifndef DBUG_OFF
 #define PLUGIN_DEBUG_VERSION "-debug"
 #else
@@ -168,7 +281,11 @@ static char *default_home= (char *)".";
 extern char server_version[];
 static const char *serv_ver= NULL;
 static int started_mysql= 0;
+static int mysql_57_started= 0;
+static int debug_server_started= 0;
+static int use_event_data_for_disconnect= 0;
 static int started_mariadb= 0;
+static int maria_55_started= 0;
 static int maria_above_5= 0;
 static char *incl_users, *excl_users,
             *file_path, *syslog_info;
@@ -193,6 +310,27 @@ static char servhost[256];
 static size_t servhost_len;
 static char *syslog_ident;
 static char syslog_ident_buffer[128]= "mysql-server_auditing";
+
+struct connection_info
+{
+  int header;
+  unsigned long thread_id;
+  unsigned long long query_id;
+  char db[256];
+  int db_length;
+  char user[64];
+  int user_length;
+  char host[64];
+  int host_length;
+  char ip[64];
+  int ip_length;
+  const char *query;
+  int query_length;
+  char query_buffer[1024];
+  time_t query_time;
+  int log_always;
+};
+
 #define DEFAULT_FILENAME_LEN 16
 static char default_file_name[DEFAULT_FILENAME_LEN+1]= "server_audit.log";
 
@@ -246,7 +384,8 @@ static TYPELIB events_typelib=
   array_elements(event_names) - 1, "", event_names, NULL
 };
 static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG,
-       "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE, QUERY_DDL, QUERY_DML.",
+       "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE,"
+           " QUERY_DDL, QUERY_DML, QUERY_DCL.",
        NULL, NULL, 0, &events_typelib);
 #define OUTPUT_SYSLOG 0
 #define OUTPUT_FILE 1
@@ -287,6 +426,13 @@ static MYSQL_SYSVAR_UINT(query_log_limit, query_log_limit,
        PLUGIN_VAR_OPCMDARG, "Limit on the length of the query string in a record.",
        NULL, NULL, 1024, 0, 0x7FFFFFFF, 1);
 
+char locinfo_ini_value[sizeof(struct connection_info)+4];
+
+static MYSQL_THDVAR_STR(loc_info,
+                        PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
+                        "Auxiliary info.", NULL, NULL,
+                        locinfo_ini_value);
+
 static const char *syslog_facility_names[]=
 {
   "LOG_USER", "LOG_MAIL", "LOG_DAEMON", "LOG_AUTH",
@@ -366,6 +512,7 @@ static struct st_mysql_sys_var* vars[] = {
     MYSQL_SYSVAR(syslog_facility),
     MYSQL_SYSVAR(syslog_priority),
     MYSQL_SYSVAR(query_log_limit),
+    MYSQL_SYSVAR(loc_info),
     NULL
 };
 
@@ -376,6 +523,8 @@ static long log_write_failures= 0;
 static char current_log_buf[FN_REFLEN]= "";
 static char last_error_buf[512]= "";
 
+extern void *mysql_v4_descriptor;
+
 static struct st_mysql_show_var audit_status[]=
 {
   {"server_audit_active", (char *)&is_active, SHOW_BOOL},
@@ -388,10 +537,14 @@ static struct st_mysql_show_var audit_status[]=
 #if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
 /* These belong to the service initialization */
 static PSI_mutex_key key_LOCK_operations;
+static PSI_mutex_key key_LOCK_bigbuffer;
 static PSI_mutex_info mutex_key_list[]=
-{{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
-{{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
-   PSI_FLAG_GLOBAL}};
+{
+  { &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
+    PSI_FLAG_GLOBAL},
+  { &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
+    PSI_FLAG_GLOBAL}
+};
 #endif
 static mysql_mutex_t lock_operations;
 static mysql_mutex_t lock_bigbuffer;
@@ -415,7 +568,7 @@ static uchar *getkey_user(const char *entry, size_t *length,
 }
 
 
-static void blank_user(uchar *user)
+static void blank_user(char *user)
 {
   for (; *user && *user != ','; user++)
     *user= ' ';
@@ -475,19 +628,98 @@ static void remove_blanks(char *user)
 }
 
 
-static int user_hash_fill(HASH *h, char *users,
-                          HASH *cmp_hash, int take_over_cmp)
+struct user_name
+{
+  int name_len;
+  char *name;
+};
+
+
+struct user_coll
+{
+  int n_users;
+  struct user_name *users;
+  int n_alloced;
+};
+
+
+static void coll_init(struct user_coll *c)
+{
+  c->n_users= 0;
+  c->users= 0;
+  c->n_alloced= 0;
+}
+
+
+static void coll_free(struct user_coll *c)
+{
+  if (c->users)
+  {
+    free(c->users);
+    coll_init(c);
+  }
+}
+
+
+static int cmp_users(const void *ia, const void *ib)
+{
+  const struct user_name *a= (const struct user_name *) ia;
+  const struct user_name *b= (const struct user_name *) ib;
+  int dl= a->name_len - b->name_len;
+  if (dl != 0)
+    return dl;
+
+  return strncmp(a->name, b->name, a->name_len);
+}
+
+
+static char *coll_search(struct user_coll *c, const char *n, int len)
+{
+  struct user_name un;
+  struct user_name *found;
+  un.name_len= len;
+  un.name= (char *) n;
+  found= (struct user_name*)  bsearch(&un, c->users, c->n_users,
+                                      sizeof(c->users[0]), cmp_users);
+  return found ? found->name : 0;
+}
+
+
+static int coll_insert(struct user_coll *c, char *n, int len)
+{
+  if (c->n_users >= c->n_alloced)
+  {
+    c->n_alloced+= 128;
+    if (c->users == NULL)
+      c->users= malloc(c->n_alloced * sizeof(c->users[0]));
+    else
+      c->users= realloc(c->users, c->n_alloced * sizeof(c->users[0]));
+
+    if (c->users == NULL)
+      return 1;
+  }
+  c->users[c->n_users].name= n;
+  c->users[c->n_users].name_len= len;
+  c->n_users++;
+  return 0;
+}
+
+
+static void coll_sort(struct user_coll *c)
+{
+  qsort(c->users, c->n_users, sizeof(c->users[0]), cmp_users);
+}
+
+
+static int user_coll_fill(struct user_coll *c, char *users,
+                          struct user_coll *cmp_c, int take_over_cmp)
 {
   char *orig_users= users;
-  uchar *cmp_user= 0;
+  char *cmp_user= 0;
   size_t cmp_length;
-  int refill_cmp_hash= 0;
+  int refill_cmp_coll= 0;
 
-  if (my_hash_inited(h))
-    my_hash_reset(h);
-  else
-    loc_my_hash_init(h, 0, &my_charset_bin, 0x100, 0, 0,
-                  (my_hash_get_key) getkey_user, 0, 0);
+  c->n_users= 0;
 
   while (*users)
   {
@@ -496,11 +728,10 @@ static int user_hash_fill(HASH *h, char *users,
     if (!*users)
       return 0;
 
-
-    if (cmp_hash)
+    (void) getkey_user(users, &cmp_length, FALSE);
+    if (cmp_c)
     {
-      (void) getkey_user(users, &cmp_length, FALSE);
-      cmp_user= my_hash_search(cmp_hash, (const uchar *) users, cmp_length);
+      cmp_user= coll_search(cmp_c, users, cmp_length);
 
       if (cmp_user && take_over_cmp)
       {
@@ -510,7 +741,7 @@ static int user_hash_fill(HASH *h, char *users,
             MYF(ME_JUST_WARNING), (int) cmp_length, users);
         internal_stop_logging= 0;
         blank_user(cmp_user);
-        refill_cmp_hash= 1;
+        refill_cmp_coll= 1;
       }
       else if (cmp_user)
       {
@@ -522,7 +753,7 @@ static int user_hash_fill(HASH *h, char *users,
         continue;
       }
     }
-    if (my_hash_insert(h, (const uchar *) users))
+    if (coll_insert(c, users, cmp_length))
       return 1;
     while (*users && *users != ',')
       users++;
@@ -531,15 +762,17 @@ static int user_hash_fill(HASH *h, char *users,
     users++;
   }
 
-  if (refill_cmp_hash)
+  if (refill_cmp_coll)
   {
     remove_blanks(excl_users);
-    return user_hash_fill(cmp_hash, excl_users, 0, 0);
+    return user_coll_fill(cmp_c, excl_users, 0, 0);
   }
 
   if (users > orig_users && users[-1] == ',')
     users[-1]= 0;
 
+  coll_sort(c);
+
   return 0;
 }
 
@@ -668,48 +901,19 @@ static void error_header()
 
 
 static LOGGER_HANDLE *logfile;
-static HASH incl_user_hash, excl_user_hash;
+static struct user_coll incl_user_coll, excl_user_coll;
 static unsigned long long query_counter= 1;
 
-struct connection_info
-{
-  unsigned long thread_id;
-  unsigned long long query_id;
-  char db[256];
-  int db_length;
-  char user[64];
-  int user_length;
-  char host[64];
-  int host_length;
-  char ip[64];
-  int ip_length;
-  const char *query;
-  int query_length;
-  char query_buffer[1024];
-  time_t query_time;
-  int log_always;
-};
-
-
-static HASH connection_hash;
-
-
-struct connection_info *alloc_connection()
-{
-  return malloc(ALIGN_SIZE(sizeof(struct connection_info)));
-}
-
 
-void free_connection(void* pconn)
+static struct connection_info *get_loc_info(MYSQL_THD thd)
 {
-  (void) free(pconn);
+  return (struct connection_info *) THDVAR(thd, loc_info);
 }
 
 
-static struct connection_info *find_connection(unsigned long id)
+static int ci_needs_setup(const struct connection_info *ci)
 {
-  return (struct connection_info *)
-    my_hash_search(&connection_hash, (const uchar *) &id, sizeof(id));
+  return ci->header != 0;
 }
 
 
@@ -873,15 +1077,24 @@ static int stop_logging()
   return 0;
 }
 
-static struct connection_info *
-  add_connection(const struct mysql_event_connection *event)
+
+static void setup_connection_simple(struct connection_info *ci)
+{
+  ci->db_length= 0;
+  ci->user_length= 0;
+  ci->host_length= 0;
+  ci->ip_length= 0;
+  ci->query_length= 0;
+  ci->header= 0;
+}
+
+
+static void setup_connection_connect(struct connection_info *cn,
+    const struct mysql_event_connection *event)
 {
-  struct connection_info *cn= alloc_connection();
-  if (!cn)
-    return 0;
-  cn->thread_id= event->thread_id;
   cn->query_id= 0;
   cn->log_always= 0;
+  cn->thread_id= event->thread_id;
   get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
             event->database, event->database_length);
   get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
@@ -890,11 +1103,7 @@ static struct connection_info *
             event->host, event->host_length);
   get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
             event->ip, event->ip_length);
-
-  if (my_hash_insert(&connection_hash, (const uchar *) cn))
-    return 0;
-
-  return cn;
+  cn->header= 0;
 }
 
 
@@ -917,46 +1126,43 @@ do { \
 
 
 
-static struct connection_info *
-  add_connection_initdb(const struct mysql_event_general *event)
+static void setup_connection_initdb(struct connection_info *cn,
+    const struct mysql_event_general *event)
 {
-  struct connection_info *cn;
   size_t user_len, host_len, ip_len;
   char uh_buffer[512];
 
-  if (get_user_host(event->general_user, event->general_user_length,
-                    uh_buffer, sizeof(uh_buffer),
-                    &user_len, &host_len, &ip_len) ||
-      (cn= alloc_connection()) == NULL)
-    return 0;
-
   cn->thread_id= event->general_thread_id;
   cn->query_id= 0;
   cn->log_always= 0;
   get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
             event->general_query, event->general_query_length);
-  get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
-            uh_buffer, user_len);
-  get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
-            uh_buffer+user_len+1, host_len);
-  get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
-            uh_buffer+user_len+1+host_len+1, ip_len);
-
-  if (my_hash_insert(&connection_hash, (const uchar *) cn))
-    return 0;
 
-  return cn;
+  if (get_user_host(event->general_user, event->general_user_length,
+                    uh_buffer, sizeof(uh_buffer),
+                    &user_len, &host_len, &ip_len))
+  {
+    /* The user at host line is incorrect. */
+    cn->user_length= 0;
+    cn->host_length= 0;
+    cn->ip_length= 0;
+  }
+  else
+  {
+    get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
+              uh_buffer, user_len);
+    get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
+              uh_buffer+user_len+1, host_len);
+    get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
+              uh_buffer+user_len+1+host_len+1, ip_len);
+  }
+  cn->header= 0;
 }
 
 
-static struct connection_info *
-  add_connection_table(const struct mysql_event_table *event)
+static void setup_connection_table(struct connection_info *cn,
+    const struct mysql_event_table *event)
 {
-  struct connection_info *cn;
-
-  if ((cn= alloc_connection()) == NULL)
-    return 0;
-
   cn->thread_id= event->thread_id;
   cn->query_id= query_counter++;
   cn->log_always= 0;
@@ -968,42 +1174,40 @@ static struct connection_info *
             event->host, SAFE_STRLEN(event->host));
   get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
             event->ip, SAFE_STRLEN(event->ip));
-
-  if (my_hash_insert(&connection_hash, (const uchar *) cn))
-    return 0;
-
-  return cn;
+  cn->header= 0;
 }
 
 
-static struct connection_info *
-  add_connection_query(const struct mysql_event_general *event)
+static void setup_connection_query(struct connection_info *cn,
+    const struct mysql_event_general *event)
 {
-  struct connection_info *cn;
   size_t user_len, host_len, ip_len;
   char uh_buffer[512];
 
-  if (get_user_host(event->general_user, event->general_user_length,
-                    uh_buffer, sizeof(uh_buffer),
-                    &user_len, &host_len, &ip_len) ||
-      (cn= alloc_connection()) == NULL)
-    return 0;
-
   cn->thread_id= event->general_thread_id;
   cn->query_id= query_counter++;
   cn->log_always= 0;
   get_str_n(cn->db, &cn->db_length, sizeof(cn->db), "", 0);
-  get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
-            uh_buffer, user_len);
-  get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
-            uh_buffer+user_len+1, host_len);
-  get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
-            uh_buffer+user_len+1+host_len+1, ip_len);
 
-  if (my_hash_insert(&connection_hash, (const uchar *) cn))
-    return 0;
-
-  return cn;
+  if (get_user_host(event->general_user, event->general_user_length,
+                    uh_buffer, sizeof(uh_buffer),
+                    &user_len, &host_len, &ip_len))
+  {
+    /* The user at host line is incorrect. */
+    cn->user_length= 0;
+    cn->host_length= 0;
+    cn->ip_length= 0;
+  }
+  else
+  {
+    get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
+              uh_buffer, user_len);
+    get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
+              uh_buffer+user_len+1, host_len);
+    get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
+              uh_buffer+user_len+1+host_len+1, ip_len);
+  }
+  cn->header= 0;
 }
 
 
@@ -1095,6 +1299,27 @@ static int log_connection(const struct connection_info *cn,
 }
 
 
+static int log_connection_event(const struct mysql_event_connection *event,
+                                const char *type)
+{
+  time_t ctime;
+  size_t csize;
+  char message[1024];
+
+  (void) time(&ctime);
+  csize= log_header(message, sizeof(message)-1, &ctime,
+                    servhost, servhost_len,
+                    event->user, event->user_length,
+                    event->host, event->host_length,
+                    event->ip, event->ip_length,
+                    event->thread_id, 0, type);
+  csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+    ",%.*s,,%d", event->database_length, event->database, event->status);
+  message[csize]= '\n';
+  return write_log(message, csize + 1);
+}
+
+
 static size_t escape_string(const char *str, unsigned int len,
                           char *result, size_t result_len)
 {
@@ -1240,11 +1465,11 @@ static int do_log_user(const char *name)
     return 0;
   len= strlen(name);
 
-  if (incl_user_hash.records)
-    return my_hash_search(&incl_user_hash, (const uchar *) name, len) != 0;
+  if (incl_user_coll.n_users)
+    return coll_search(&incl_user_coll, name, len) != 0;
 
-  if (excl_user_hash.records)
-    return my_hash_search(&excl_user_hash, (const uchar *) name, len) == 0;
+  if (excl_user_coll.n_users)
+    return coll_search(&excl_user_coll, name, len) == 0;
 
   return 1;
 }
@@ -1582,14 +1807,14 @@ static void update_general_user(struct connection_info *cn,
 }
 
 
+static struct connection_info ci_disconnect_buffer;
+
 #define AA_FREE_CONNECTION 1
 #define AA_CHANGE_USER 2
 
-static struct connection_info *update_connection_hash(unsigned int event_class,
-                                                      const void *ev,
-                                                      int *after_action)
+static void update_connection_info(struct connection_info *cn,
+    unsigned int event_class, const void *ev, int *after_action)
 {
-  struct connection_info *cn= NULL;
   *after_action= 0;
 
   switch (event_class) {
@@ -1602,13 +1827,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
       {
         int init_db_command= event->general_command_length == 7 &&
           strncmp(event->general_command, "Init DB", 7) == 0;
-        if ((cn= find_connection(event->general_thread_id)))
+        if (!ci_needs_setup(cn))
         {
           if (init_db_command)
           {
             /* Change DB */
-            get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
-                event->general_query, event->general_query_length);
+            if (mysql_57_started)
+              get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
+                  event->database, event->database_length);
+            else
+              get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
+                  event->general_query, event->general_query_length);
           }
           cn->query_id= mode ? query_counter++ : event->query_id;
           cn->query= event->general_query;
@@ -1617,18 +1846,19 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
           update_general_user(cn, event);
         }
         else if (init_db_command)
-          cn= add_connection_initdb(event);
+          setup_connection_initdb(cn, event);
         else if (event_query_command(event))
-          cn= add_connection_query(event);
+          setup_connection_query(cn, event);
+        else
+          setup_connection_simple(cn);
         break;
       }
 
       case MYSQL_AUDIT_GENERAL_STATUS:
         if (event_query_command(event))
         {
-          if (!(cn= find_connection(event->general_thread_id)) &&
-              !(cn= add_connection_query(event)))
-            return 0;
+          if (ci_needs_setup(cn))
+            setup_connection_query(cn, event);
 
           if (mode == 0 && cn->db_length == 0 && event->database_length > 0)
             get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
@@ -1654,13 +1884,13 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
         }
         break;
       case MYSQL_AUDIT_GENERAL_ERROR:
-        /* We need this because of a bug in the MariaDB */
-        /* that it returns NULL query field for the     */
-        /* MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare. */
-        /* As a result we get empty QUERY field for errors. */
-        if (!(cn= find_connection(event->general_thread_id)) &&
-            !(cn= add_connection_query(event)))
-          return 0;
+        /*
+          We need this because the MariaDB returns NULL query field for the
+          MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare.
+          As a result we get empty QUERY field for errors.
+        */
+        if (ci_needs_setup(cn))
+          setup_connection_query(cn, event);
         cn->query_id= mode ? query_counter++ : event->query_id;
         get_str_n(cn->query_buffer, &cn->query_length, sizeof(cn->query_buffer),
             event->general_query, event->general_query_length);
@@ -1675,9 +1905,9 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
   {
     const struct mysql_event_table *event =
       (const struct mysql_event_table *) ev;
-    if (!(cn= find_connection(event->thread_id)) &&
-        !(cn= add_connection_table(event)))
-      return 0;
+    if (ci_needs_setup(cn))
+      setup_connection_table(cn, event);
+
     if (cn->user_length == 0 && cn->host_length == 0 && cn->ip_length == 0)
     {
       get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
@@ -1703,17 +1933,10 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
     switch (event->event_subclass)
     {
       case MYSQL_AUDIT_CONNECTION_CONNECT:
-        cn= add_connection(ev);
-        break;
-      case MYSQL_AUDIT_CONNECTION_DISCONNECT:
-        cn= find_connection(event->thread_id);
-        if (cn)
-          *after_action= AA_FREE_CONNECTION;
+        setup_connection_connect(cn, event);
         break;
       case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
-        cn= find_connection(event->thread_id);
-        if (cn)
-          *after_action= AA_CHANGE_USER;
+        *after_action= AA_CHANGE_USER;
         break;
       default:;
     }
@@ -1722,17 +1945,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
   default:
     break;
   }
-  return cn;
 }
 
 
+struct connection_info cn_error_buffer;
+
+
 #define FILTER(MASK) (events == 0 || (events & MASK))
-static void auditing(MYSQL_THD thd __attribute__((unused)),
-                     unsigned int event_class,
-                     const void *ev)
+void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
 {
-  struct connection_info *cn;
-  int after_action;
+  struct connection_info *cn= 0;
+  int after_action= 0;
 
   /* That one is important as this function can be called with      */
   /* &lock_operations locked when the server logs an error reported */
@@ -1742,8 +1965,35 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
 
   flogger_mutex_lock(&lock_operations);
 
-  if (!(cn= update_connection_hash(event_class, ev, &after_action)))
-    goto exit_func;
+  if (maria_55_started && debug_server_started &&
+      event_class == MYSQL_AUDIT_GENERAL_CLASS)
+  {
+    /*
+      There's a bug in MariaDB 5.5 that prevents using thread local
+      variables in some cases.
+      The 'select * from notexisting_table;' query produces such case.
+      So just use the static buffer in this case.
+    */
+    const struct mysql_event_general *event =
+      (const struct mysql_event_general *) ev;
+
+    if (event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR ||
+        (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS && 
+         event->general_query_length == 0 &&
+         cn_error_buffer.query_id == event->query_id))
+    {
+      cn= &cn_error_buffer;
+      cn->header= 1;
+    }
+    else
+      cn= get_loc_info(thd);
+  }
+  else
+  {
+    cn= get_loc_info(thd);
+  }
+
+  update_connection_info(cn, event_class, ev, &after_action);
 
   if (!logging)
     goto exit_func;
@@ -1757,8 +2007,11 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
     /*
       Only one subclass is logged.
     */
-    if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS)
+    if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
+        event_query_command(event))
+    {
       log_statement(cn, event, "QUERY");
+    }
   }
   else if (event_class == MYSQL_AUDIT_TABLE_CLASS && FILTER(EVENT_TABLE) && cn)
   {
@@ -1799,7 +2052,10 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
         log_connection(cn, event, event->status ? "FAILED_CONNECT": "CONNECT");
         break;
       case MYSQL_AUDIT_CONNECTION_DISCONNECT:
-        log_connection(cn, event, "DISCONNECT");
+        if (use_event_data_for_disconnect)
+          log_connection_event(event, "DISCONNECT");
+        else
+          log_connection(&ci_disconnect_buffer, event, "DISCONNECT");
         break;
       case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
         log_connection(cn, event, "CHANGEUSER");
@@ -1814,10 +2070,6 @@ exit_func:
   if (after_action)
   {
     switch (after_action) {
-    case AA_FREE_CONNECTION:
-      my_hash_delete(&connection_hash, (uchar *) cn);
-      cn= 0;
-      break;
     case AA_CHANGE_USER:
     {
       const struct mysql_event_connection *event =
@@ -1835,28 +2087,6 @@ exit_func:
 }
 
 
-#ifdef DBUG_OFF
-  #ifdef __x86_64__
-static const int cmd_off= 4200;
-static const int db_off= 120;
-static const int db_len_off= 128;
-  #else
-static const int cmd_off= 2668;
-static const int db_off= 60;
-static const int db_len_off= 64;
-  #endif /*x86_64*/
-#else
-  #ifdef __x86_64__
-static const int cmd_off= 4432;
-static const int db_off= 120;
-static const int db_len_off= 128;
-  #else
-static const int cmd_off= 2808;
-static const int db_off= 64;
-static const int db_len_off= 68;
-  #endif /*x86_64*/
-#endif /*DBUG_OFF*/
-
 struct mysql_event_general_v8
 {
   unsigned int event_class;
@@ -1874,8 +2104,31 @@ struct mysql_event_general_v8
   unsigned long long general_rows;
 };
 
+
 static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8)
 {
+#ifdef DBUG_OFF
+  #ifdef __x86_64__
+  static const int cmd_off= 4200;
+  static const int db_off= 120;
+  static const int db_len_off= 128;
+  #else
+  static const int cmd_off= 2668;
+  static const int db_off= 60;
+  static const int db_len_off= 64;
+  #endif /*x86_64*/
+#else
+  #ifdef __x86_64__
+  static const int cmd_off= 4432;
+  static const int db_off= 120;
+  static const int db_len_off= 128;
+  #else
+  static const int cmd_off= 2808;
+  static const int db_off= 64;
+  static const int db_len_off= 68;
+  #endif /*x86_64*/
+#endif /*DBUG_OFF*/
+
   struct mysql_event_general event;
 
   if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS)
@@ -1934,6 +2187,41 @@ static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0)
 }
 
 
+int get_db_mysql57(MYSQL_THD thd, char **name, int *len)
+{
+  int db_off;
+  int db_len_off;
+  if (debug_server_started)
+  {
+#ifdef __x86_64__
+    db_off= 608;
+    db_len_off= 616;
+#else
+    db_off= 0;
+    db_len_off= 0;
+#endif /*x86_64*/
+  }
+  else
+  {
+#ifdef __x86_64__
+    db_off= 536;
+    db_len_off= 544;
+#else
+    db_off= 0;
+    db_len_off= 0;
+#endif /*x86_64*/
+  }
+
+#ifdef __linux__
+  *name= *(char **) (((char *) thd) + db_off);
+  *len= *((int *) (((char*) thd) + db_len_off));
+  if (*name && (*name)[*len] != 0)
+    return 1;
+  return 0;
+#else
+  return 1;
+#endif
+}
 /*
    As it's just too difficult to #include "sql_class.h",
    let's just copy the necessary part of the system_variables
@@ -2060,8 +2348,8 @@ static int server_audit_init(void *p __attribute__((unused)))
   flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST);
   flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
 
-  my_hash_clear(&incl_user_hash);
-  my_hash_clear(&excl_user_hash);
+  coll_init(&incl_user_coll);
+  coll_init(&excl_user_coll);
 
   if (incl_users)
   {
@@ -2079,9 +2367,6 @@ static int server_audit_init(void *p __attribute__((unused)))
     update_excl_users(NULL, NULL, NULL, &excl_users);
   }
 
-  loc_my_hash_init(&connection_hash, 0, &my_charset_bin, 0x100, 0,
-               sizeof(unsigned long), 0, free_connection, 0); 
-
   error_header();
   fprintf(stderr, "MariaDB Audit Plugin version %s%s STARTED.\n",
           PLUGIN_STR_VERSION, PLUGIN_DEBUG_VERSION);
@@ -2105,6 +2390,16 @@ static int server_audit_init(void *p __attribute__((unused)))
     }
   }
 
+  ci_disconnect_buffer.header= 10;
+  ci_disconnect_buffer.thread_id= 0;
+  ci_disconnect_buffer.query_id= 0;
+  ci_disconnect_buffer.db_length= 0;
+  ci_disconnect_buffer.user_length= 0;
+  ci_disconnect_buffer.host_length= 0;
+  ci_disconnect_buffer.ip_length= 0;
+  ci_disconnect_buffer.query= empty_str;
+  ci_disconnect_buffer.query_length= 0;
+
   if (logging)
     start_logging();
 
@@ -2123,13 +2418,8 @@ static int server_audit_init_mysql(void *p)
 
 static int server_audit_deinit(void *p __attribute__((unused)))
 {
-  if (my_hash_inited(&incl_user_hash))
-    my_hash_free(&incl_user_hash);
-
-  if (my_hash_inited(&excl_user_hash))
-    my_hash_free(&excl_user_hash);
-
-  my_hash_free(&connection_hash);
+  coll_free(&incl_user_coll);
+  coll_free(&excl_user_coll);
 
   if (output_type == OUTPUT_FILE && logfile)
     logger_close(logfile);
@@ -2164,6 +2454,7 @@ static struct st_mysql_audit mysql_descriptor =
   { MYSQL_AUDIT_GENERAL_CLASSMASK | MYSQL_AUDIT_CONNECTION_CLASSMASK }
 };
 
+
 mysql_declare_plugin(server_audit)
 {
   MYSQL_AUDIT_PLUGIN,
@@ -2206,7 +2497,7 @@ maria_declare_plugin(server_audit)
   audit_status,
   vars,
   PLUGIN_STR_VERSION,
-  MariaDB_PLUGIN_MATURITY_GAMMA
+  MariaDB_PLUGIN_MATURITY_STABLE
 }
 maria_declare_plugin_end;
 
@@ -2214,22 +2505,21 @@ maria_declare_plugin_end;
 static void mark_always_logged(MYSQL_THD thd)
 {
   struct connection_info *cn;
-  if (thd && (cn= find_connection(thd_get_thread_id(thd))))
+  if (thd && (cn= get_loc_info(thd)))
     cn->log_always= 1;
 }
 
 
 static void log_current_query(MYSQL_THD thd)
 {
-  unsigned long thd_id;
   struct connection_info *cn;
-  if (!thd ||
-      !(cn= find_connection((thd_id= thd_get_thread_id(thd)))))
+  if (!thd)
     return;
-  if (FILTER(EVENT_QUERY) && do_log_user(cn->user))
+  cn= get_loc_info(thd);
+  if (!ci_needs_setup(cn) && FILTER(EVENT_QUERY) && do_log_user(cn->user))
   {
-    log_statement_ex(cn, cn->query_time, thd_id, cn->query, cn->query_length,
-                     0, "QUERY");
+    log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),
+        cn->query, cn->query_length, 0, "QUERY");
     cn->log_always= 1;
   }
 }
@@ -2241,7 +2531,8 @@ static void update_file_path(MYSQL_THD thd,
 {
   char *new_name= (*(char **) save) ? *(char **) save : empty_str;
 
-  flogger_mutex_lock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_lock(&lock_operations);
   internal_stop_logging= 1;
   error_header();
   fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
@@ -2277,7 +2568,8 @@ static void update_file_path(MYSQL_THD thd,
   file_path= path_buffer;
 exit_func:
   internal_stop_logging= 0;
-  flogger_mutex_unlock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_unlock(&lock_operations);
 }
 
 
@@ -2321,14 +2613,16 @@ static void update_incl_users(MYSQL_THD thd,
               void *var_ptr  __attribute__((unused)), const void *save)
 {
   char *new_users= (*(char **) save) ? *(char **) save : empty_str;
-  flogger_mutex_lock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_lock(&lock_operations);
   mark_always_logged(thd);
   strncpy(incl_user_buffer, new_users, sizeof(incl_user_buffer));
   incl_users= incl_user_buffer;
-  user_hash_fill(&incl_user_hash, incl_users, &excl_user_hash, 1);
+  user_coll_fill(&incl_user_coll, incl_users, &excl_user_coll, 1);
   error_header();
   fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
-  flogger_mutex_unlock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_unlock(&lock_operations);
 }
 
 
@@ -2337,14 +2631,16 @@ static void update_excl_users(MYSQL_THD thd  __attribute__((unused)),
               void *var_ptr  __attribute__((unused)), const void *save)
 {
   char *new_users= (*(char **) save) ? *(char **) save : empty_str;
-  flogger_mutex_lock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_lock(&lock_operations);
   mark_always_logged(thd);
   strncpy(excl_user_buffer, new_users, sizeof(excl_user_buffer));
   excl_users= excl_user_buffer;
-  user_hash_fill(&excl_user_hash, excl_users, &incl_user_hash, 0);
+  user_coll_fill(&excl_user_coll, excl_users, &incl_user_coll, 0);
   error_header();
   fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
-  flogger_mutex_unlock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_unlock(&lock_operations);
 }
 
 
@@ -2420,7 +2716,8 @@ static void update_logging(MYSQL_THD thd,
   if (new_logging == logging)
     return;
 
-  flogger_mutex_lock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_lock(&lock_operations);
   internal_stop_logging= 1;
   if ((logging= new_logging))
   {
@@ -2437,7 +2734,8 @@ static void update_logging(MYSQL_THD thd,
   }
 
   internal_stop_logging= 0;
-  flogger_mutex_unlock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_unlock(&lock_operations);
 }
 
 
@@ -2449,14 +2747,16 @@ static void update_mode(MYSQL_THD thd  __attribute__((unused)),
   if (mode_readonly || new_mode == mode)
     return;
 
-  flogger_mutex_lock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_lock(&lock_operations);
   internal_stop_logging= 1;
   mark_always_logged(thd);
   error_header();
   fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
   mode= new_mode;
   internal_stop_logging= 0;
-  flogger_mutex_unlock(&lock_operations);
+  if (!maria_55_started || !debug_server_started)
+    flogger_mutex_unlock(&lock_operations);
 }
 
 
@@ -2480,6 +2780,13 @@ static void update_syslog_ident(MYSQL_THD thd  __attribute__((unused)),
 }
 
 
+struct st_my_thread_var *loc_thread_var(void)
+{
+  return 0;
+}
+
+
+
 #ifdef _WIN32
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
@@ -2497,9 +2804,18 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void)
     goto exit;
 
   started_mariadb= strstr(serv_ver, "MariaDB") != 0;
+  debug_server_started= strstr(serv_ver, "debug") != 0;
 
-  if (!started_mariadb)
+  if (started_mariadb)
+  {
+    if (serv_ver[0] == '1')
+      use_event_data_for_disconnect= 1;
+    else
+      maria_55_started= 1;
+  }
+  else
   {
+    /* Started MySQL. */
     if (serv_ver[0] == '5' && serv_ver[2] == '5')
     {
       int sc= serv_ver[4] - '0';
@@ -2516,7 +2832,25 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void)
         mysql_descriptor.event_notify= (void *) auditing_v13;
       }
     }
+    else if (serv_ver[0] == '5' && serv_ver[2] == '6')
+    {
+      int sc= serv_ver[4] - '0';
+      if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
+        sc= sc * 10 + serv_ver[5] - '0';
+      if (sc >= 24)
+        use_event_data_for_disconnect= 1;
+    }
+    else if (serv_ver[0] == '5' && serv_ver[2] == '7')
+    {
+      mysql_57_started= 1;
+      _mysql_plugin_declarations_[0].info= mysql_v4_descriptor;
+      use_event_data_for_disconnect= 1;
+    }
   }
+
+  memset(locinfo_ini_value, 'O', sizeof(locinfo_ini_value)-1);
+  locinfo_ini_value[sizeof(locinfo_ini_value)-1]= 0;
+
 exit:
 #ifdef _WIN32
   return 1;
diff --git a/plugin/server_audit/test_audit_v4.c b/plugin/server_audit/test_audit_v4.c
new file mode 100644
index 0000000..ae7527f
--- /dev/null
+++ b/plugin/server_audit/test_audit_v4.c
@@ -0,0 +1,162 @@
+#define PLUGIN_CONTEXT
+
+#include <stdio.h>
+
+typedef void *MYSQL_THD;
+struct st_mysql_const_lex_string
+{
+  const char *str;
+  size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING;
+enum enum_sql_command{ SQLCOM_A, SQLCOM_B };
+enum enum_server_command{ SERVCOM_A, SERVCOM_B };
+
+#include "plugin_audit_v4.h"
+
+extern void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev);
+extern int get_db_mysql57(MYSQL_THD thd, char **name, int *len);
+
+
+struct mysql_event_general_302
+{
+  unsigned int event_subclass;
+  int general_error_code;
+  unsigned long general_thread_id;
+  const char *general_user;
+  unsigned int general_user_length;
+  const char *general_command;
+  unsigned int general_command_length;
+  const char *general_query;
+  unsigned int general_query_length;
+  struct charset_info_st *general_charset;
+  unsigned long long general_time;
+  unsigned long long general_rows;
+  unsigned long long query_id;
+  char *database;
+  int database_length;
+};
+
+
+static int auditing_v4(MYSQL_THD thd, mysql_event_class_t class, const void *ev)
+{
+  int *subclass= (int *)ev;
+  struct mysql_event_general_302 ev_302;
+  int subclass_v3, subclass_orig;
+
+  if (class != MYSQL_AUDIT_GENERAL_CLASS &&
+      class != MYSQL_AUDIT_CONNECTION_CLASS)
+    return 0;
+
+  subclass_orig= *subclass;
+
+  if (class == MYSQL_AUDIT_GENERAL_CLASS)
+  {
+    struct mysql_event_general *event= (struct mysql_event_general *) ev;
+    ev_302.general_error_code= event->general_error_code;
+    ev_302.general_thread_id= event->general_thread_id;
+    ev_302.general_user= event->general_user.str;
+    ev_302.general_user_length= event->general_user.length;
+    ev_302.general_command= event->general_command.str;
+    ev_302.general_command_length= event->general_command.length;
+    ev_302.general_query= event->general_query.str;
+    ev_302.general_query_length= event->general_query.length;
+    ev_302.general_charset= event->general_charset;
+    ev_302.general_time= event->general_time;
+    ev_302.general_rows= event->general_rows;
+    if (get_db_mysql57(thd, &ev_302.database, &ev_302.database_length))
+    {
+      ev_302.database= 0;
+      ev_302.database_length= 0;
+    }
+    ev= &ev_302;
+    switch (subclass_orig)
+    {
+      case MYSQL_AUDIT_GENERAL_LOG:
+        subclass_v3= 0;
+        ev_302.event_subclass= 0;
+        break;
+      case MYSQL_AUDIT_GENERAL_ERROR:
+        subclass_v3= 1;
+        ev_302.event_subclass= 1;
+        break;
+      case MYSQL_AUDIT_GENERAL_RESULT:
+        subclass_v3= 2;
+        ev_302.event_subclass= 2;
+        break;
+      case MYSQL_AUDIT_GENERAL_STATUS:
+      {
+        subclass_v3= 3;
+        ev_302.event_subclass= 3;
+        break;
+      }
+      default:
+        return 0;
+    }
+  }
+  else /* if (class == MYSQL_AUDIT_CONNECTION_CLASS) */
+  {
+    switch (subclass_orig)
+    {
+      case MYSQL_AUDIT_CONNECTION_CONNECT:
+        subclass_v3= 0;
+        break;
+      case MYSQL_AUDIT_CONNECTION_DISCONNECT:
+        subclass_v3= 1;
+        break;
+      default:
+        return 0;
+    }
+  }
+
+  *subclass= subclass_v3;
+
+  auditing(thd, (int) class, ev);
+
+  *subclass= subclass_orig;
+  return 0;
+}
+
+
+static struct st_mysql_audit mysql_descriptor =
+{
+  MYSQL_AUDIT_INTERFACE_VERSION,
+  NULL,
+  auditing_v4,
+  { (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
+    (unsigned long) MYSQL_AUDIT_CONNECTION_ALL,
+    (unsigned long) MYSQL_AUDIT_PARSE_ALL,
+    0, /* This event class is currently not supported. */
+    0, /* This event class is currently not supported. */
+    (unsigned long) MYSQL_AUDIT_GLOBAL_VARIABLE_ALL,
+    (unsigned long) MYSQL_AUDIT_SERVER_STARTUP_ALL,
+    (unsigned long) MYSQL_AUDIT_SERVER_SHUTDOWN_ALL,
+    (unsigned long) MYSQL_AUDIT_COMMAND_ALL,
+    (unsigned long) MYSQL_AUDIT_QUERY_ALL,
+    (unsigned long) MYSQL_AUDIT_STORED_PROGRAM_ALL }
+#ifdef WHEN_MYSQL_BUG_FIXED
+  /*
+    By this moment MySQL just sends no notifications at all
+    when we request only those we actually need.
+    So we have to request everything and filter them inside the
+    handling function.                                
+  */
+  { (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
+    (unsigned long) (MYSQL_AUDIT_CONNECTION_CONNECT |
+                     MYSQL_AUDIT_CONNECTION_DISCONNECT),
+    0,
+    0, /* This event class is currently not supported. */
+    0, /* This event class is currently not supported. */
+    0,
+    0,
+    0,
+    0,
+    0,
+    0
+  }
+#endif /*WHEN_MYSQL_BUG_FIXED*/
+};
+
+
+void *mysql_v4_descriptor= &mysql_descriptor;
+
diff --git a/sql-common/client.c b/sql-common/client.c
index 1bb4a25..09548cb 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2003, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015, MariaDB
+/* Copyright (c) 2003, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -1884,38 +1884,39 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
 static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr)
 {
   SSL *ssl;
-  X509 *server_cert;
-  X509_NAME *x509sn;
-  int cn_pos;
-  X509_NAME_ENTRY *cn_entry;
-  ASN1_STRING *cn_asn1;
-  const char *cn_str;
+  X509 *server_cert= NULL;
+  char *cn= NULL;
+  int cn_loc= -1;
+  ASN1_STRING *cn_asn1= NULL;
+  X509_NAME_ENTRY *cn_entry= NULL;
+  X509_NAME *subject= NULL;
+  int ret_validation= 1;
+
   DBUG_ENTER("ssl_verify_server_cert");
   DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
 
   if (!(ssl= (SSL*)vio->ssl_arg))
   {
     *errptr= "No SSL pointer found";
-    DBUG_RETURN(1);
+    goto error;
   }
 
   if (!server_hostname)
   {
     *errptr= "No server hostname supplied";
-    DBUG_RETURN(1);
+    goto error;
   }
 
   if (!(server_cert= SSL_get_peer_certificate(ssl)))
   {
     *errptr= "Could not get server certificate";
-    DBUG_RETURN(1);
+    goto error;
   }
 
   if (X509_V_OK != SSL_get_verify_result(ssl))
   {
     *errptr= "Failed to verify the server certificate";
-    X509_free(server_cert);
-    DBUG_RETURN(1);
+    goto error;
   }
   /*
     We already know that the certificate exchanged was valid; the SSL library
@@ -1923,33 +1924,57 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const c
     are what we expect.
   */
 
-  x509sn= X509_get_subject_name(server_cert);
-
-  if ((cn_pos= X509_NAME_get_index_by_NID(x509sn, NID_commonName, -1)) < 0)
-    goto err;
+  /*
+   Some notes for future development
+   We should check host name in alternative name first and then if needed check in common name.
+   Currently yssl doesn't support alternative name.
+   openssl 1.0.2 support X509_check_host method for host name validation, we may need to start using
+   X509_check_host in the future.
+  */
 
-  if (!(cn_entry= X509_NAME_get_entry(x509sn, cn_pos)))
-    goto err;
+  subject= X509_get_subject_name(server_cert);
+  cn_loc= X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
+  if (cn_loc < 0)
+  {
+    *errptr= "Failed to get CN location in the certificate subject";
+    goto error;
+  }
 
-  if (!(cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry)))
-    goto err;
+  cn_entry= X509_NAME_get_entry(subject, cn_loc);
+  if (cn_entry == NULL)
+  {
+    *errptr= "Failed to get CN entry using CN location";
+    goto error;
+  }
 
-  cn_str = (char *)ASN1_STRING_data(cn_asn1);
+  cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
+  if (cn_asn1 == NULL)
+  {
+    *errptr= "Failed to get CN from CN entry";
+    goto error;
+  }
 
-  /* Make sure there is no embedded \0 in the CN */
-  if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn_str))
-    goto err;
+  cn= (char *) ASN1_STRING_data(cn_asn1);
 
-  if (strcmp(cn_str, server_hostname))
-    goto err;
+  if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn))
+  {
+    *errptr= "NULL embedded in the certificate CN";
+    goto error;
+  }
 
-  X509_free (server_cert);
-  DBUG_RETURN(0);
+  DBUG_PRINT("info", ("Server hostname in cert: %s", cn));
+  if (!strcmp(cn, server_hostname))
+  {
+    /* Success */
+    ret_validation= 0;
+  }
 
-err:
-  X509_free(server_cert);
   *errptr= "SSL certificate validation failure";
-  DBUG_RETURN(1);
+
+error:
+  if (server_cert != NULL)
+    X509_free (server_cert);
+  DBUG_RETURN(ret_validation);
 }
 
 #endif /* HAVE_OPENSSL */
@@ -4293,6 +4318,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
       stacksize= ASYNC_CONTEXT_DEFAULT_STACK_SIZE;
     if (my_context_init(&ctxt->async_context, stacksize))
     {
+      set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
       my_free(ctxt);
       DBUG_RETURN(1);
     }
diff --git a/sql/field.cc b/sql/field.cc
index aeeacf7..ceea089 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7068,6 +7068,35 @@ uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg)
 }
 
 
+/**
+  Copy a value from another BLOB field of the same character set.
+  This method is used by Copy_field, e.g. during ALTER TABLE.
+*/
+int Field_blob::copy_value(Field_blob *from)
+{
+  DBUG_ASSERT(field_charset == from->charset());
+  int rc= 0;
+  uint32 length= from->get_length();
+  uchar *data;
+  from->get_ptr(&data);
+  if (packlength < from->packlength)
+  {
+    int well_formed_errors;
+    set_if_smaller(length, Field_blob::max_data_length());
+    length= field_charset->cset->well_formed_len(field_charset,
+                                                 (const char *) data,
+                                                 (const char *) data + length,
+                                                 length, &well_formed_errors);
+    rc= report_if_important_data((const char *) data + length,
+                                 (const char *) data + from->get_length(),
+                                 true);
+  }
+  store_length(length);
+  bmove(ptr + packlength, (uchar*) &data, sizeof(char*));
+  return rc;
+}
+
+
 int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
diff --git a/sql/field.h b/sql/field.h
index 4c79847..f761aa8 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1935,6 +1935,7 @@ public:
   {
     set_ptr_offset(0, length, data);
   }
+  int copy_value(Field_blob *from);
   uint get_key_image(uchar *buff,uint length, imagetype type);
   void set_key_image(const uchar *buff,uint length);
   void sql_type(String &str) const;
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index d24f31e..5781f1d 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -1,6 +1,5 @@
-/*
-   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -332,9 +331,7 @@ static void do_copy_next_number(Copy_field *copy)
 
 static void do_copy_blob(Copy_field *copy)
 {
-  ulong length=((Field_blob*) copy->from_field)->get_length();
-  ((Field_blob*) copy->to_field)->store_length(length);
-  memcpy(copy->to_ptr, copy->from_ptr, sizeof(char*));
+  ((Field_blob*) copy->to_field)->copy_value(((Field_blob*) copy->from_field));
 }
 
 static void do_conv_blob(Copy_field *copy)
@@ -709,12 +706,7 @@ Copy_field::get_copy_func(Field *to,Field *from)
     if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
       return do_conv_blob;
     if (from_length != to_length)
-    {
-      // Correct pointer to point at char pointer
-      to_ptr+=   to_length - to->table->s->blob_ptr_size;
-      from_ptr+= from_length- from->table->s->blob_ptr_size;
       return do_copy_blob;
-    }
   }
   else
   {
@@ -863,7 +855,12 @@ int field_conv(Field *to,Field *from)
     Field_blob *blob=(Field_blob*) to;
     from->val_str(&blob->value);
 
-    if (!blob->value.is_alloced() && from->is_updatable())
+    /*
+      Copy value if copy_blobs is set, or source is part of the table's
+      writeset.
+    */
+    if (to->table->copy_blobs ||
+        (!blob->value.is_alloced() && from->is_updatable()))
       blob->value.copy();
 
     return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc
index 251869c..c5db505 100644
--- a/sql/gcalc_slicescan.cc
+++ b/sql/gcalc_slicescan.cc
@@ -49,14 +49,14 @@ typedef int (*sc_compare_func)(const void*, const void*);
 static Gcalc_scan_iterator::point *eq_sp(const Gcalc_heap::Info *pi)
 {
   GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_eq_node);
-  return (Gcalc_scan_iterator::point *) pi->eq_data;
+  return (Gcalc_scan_iterator::point *) pi->node.eq.data;
 }
 
 
 static Gcalc_scan_iterator::intersection_info *i_data(const Gcalc_heap::Info *pi)
 {
   GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_intersection);
-  return (Gcalc_scan_iterator::intersection_info *) pi->intersection_data;
+  return (Gcalc_scan_iterator::intersection_info *) pi->node.intersection.data;
 }
 
 
@@ -103,8 +103,8 @@ const char *gcalc_ev_name(int ev)
 static int gcalc_pi_str(char *str, const Gcalc_heap::Info *pi, const char *postfix)
 {
   return sprintf(str, "%s %d %d | %s %d %d%s",
-                     GCALC_SIGN(pi->ix[0]) ? "-":"", FIRST_DIGIT(pi->ix[0]),pi->ix[1],
-                     GCALC_SIGN(pi->iy[0]) ? "-":"", FIRST_DIGIT(pi->iy[0]),pi->iy[1],
+                     GCALC_SIGN(pi->node.shape.ix[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.ix[0]),pi->node.shape.ix[1],
+                     GCALC_SIGN(pi->node.shape.iy[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.iy[0]),pi->node.shape.iy[1],
                      postfix);
 
 }
@@ -594,8 +594,8 @@ void Gcalc_scan_iterator::intersection_info::do_calc_t()
   Gcalc_coord1 a2_a1x, a2_a1y;
   Gcalc_coord2 x1y2, x2y1;
 
-  gcalc_sub_coord1(a2_a1x, edge_b->pi->ix, edge_a->pi->ix);
-  gcalc_sub_coord1(a2_a1y, edge_b->pi->iy, edge_a->pi->iy);
+  gcalc_sub_coord1(a2_a1x, edge_b->pi->node.shape.ix, edge_a->pi->node.shape.ix);
+  gcalc_sub_coord1(a2_a1y, edge_b->pi->node.shape.iy, edge_a->pi->node.shape.iy);
 
   GCALC_DBUG_ASSERT(!gcalc_is_zero(edge_a->dy, GCALC_COORD_BASE) ||
                     !gcalc_is_zero(edge_b->dy, GCALC_COORD_BASE));
@@ -619,7 +619,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_y()
   Gcalc_coord3 a_tb, b_ta;
 
   gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
-                  t_b, GCALC_COORD_BASE2, edge_a->pi->iy, GCALC_COORD_BASE);
+                  t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.iy, GCALC_COORD_BASE);
   gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
                   t_a, GCALC_COORD_BASE2, edge_a->dy, GCALC_COORD_BASE);
 
@@ -635,7 +635,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_x()
   Gcalc_coord3 a_tb, b_ta;
 
   gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
-                  t_b, GCALC_COORD_BASE2, edge_a->pi->ix, GCALC_COORD_BASE);
+                  t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.ix, GCALC_COORD_BASE);
   gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
                   t_a, GCALC_COORD_BASE2, edge_a->dx, GCALC_COORD_BASE);
 
@@ -656,7 +656,7 @@ static int cmp_node_isc(const Gcalc_heap::Info *node,
   inf->calc_y_exp();
 
   gcalc_mul_coord(exp, GCALC_COORD_BASE3,
-                  inf->t_b, GCALC_COORD_BASE2, node->iy, GCALC_COORD_BASE);
+                  inf->t_b, GCALC_COORD_BASE2, node->node.shape.iy, GCALC_COORD_BASE);
 
   result= gcalc_cmp_coord(exp, inf->y_exp, GCALC_COORD_BASE3);
 #ifdef GCALC_CHECK_WITH_FLOAT
@@ -664,18 +664,18 @@ static int cmp_node_isc(const Gcalc_heap::Info *node,
   isc->calc_xy_ld(&int_x, &int_y);
   if (result < 0)
   {
-    if (!de_check(int_y, node->y) && node->y > int_y)
-      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->y, int_y));
+    if (!de_check(int_y, node->node.shape.y) && node->node.shape.y > int_y)
+      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->node.shape.y, int_y));
   }
   else if (result > 0)
   {
-    if (!de_check(int_y, node->y) && node->y < int_y)
-      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->y, int_y));
+    if (!de_check(int_y, node->node.shape.y) && node->node.shape.y < int_y)
+      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->node.shape.y, int_y));
   }
   else
   {
-    if (!de_check(int_y, node->y))
-      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->y, int_y));
+    if (!de_check(int_y, node->node.shape.y))
+      GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->node.shape.y, int_y));
   }
 #endif /*GCALC_CHECK_WITH_FLOAT*/
   if (result)
@@ -684,27 +684,27 @@ static int cmp_node_isc(const Gcalc_heap::Info *node,
 
   inf->calc_x_exp();
   gcalc_mul_coord(exp, GCALC_COORD_BASE3,
-                  inf->t_b, GCALC_COORD_BASE2, node->ix, GCALC_COORD_BASE);
+                  inf->t_b, GCALC_COORD_BASE2, node->node.shape.ix, GCALC_COORD_BASE);
 
   result= gcalc_cmp_coord(exp, inf->x_exp, GCALC_COORD_BASE3);
 #ifdef GCALC_CHECK_WITH_FLOAT
   if (result < 0)
   {
-    if (!de_check(int_x, node->x) && node->x > int_x)
+    if (!de_check(int_x, node->node.shape.x) && node->node.shape.x > int_x)
       GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g < %LG",
-                         node->x, int_x));
+                         node->node.shape.x, int_x));
   }
   else if (result > 0)
   {
-    if (!de_check(int_x, node->x) && node->x < int_x)
+    if (!de_check(int_x, node->node.shape.x) && node->node.shape.x < int_x)
       GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g > %LG",
-                        node->x, int_x));
+                        node->node.shape.x, int_x));
   }
   else
   {
-    if (!de_check(int_x, node->x))
+    if (!de_check(int_x, node->node.shape.x))
       GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g == %LG",
-                        node->x, int_x));
+                        node->node.shape.x, int_x));
   }
 #endif /*GCALC_CHECK_WITH_FLOAT*/
 exit:
@@ -844,13 +844,13 @@ Gcalc_heap::Info *Gcalc_heap::new_point_info(double x, double y,
     return NULL;
   *m_hook= result;
   m_hook= &result->next;
-  result->x= x;
-  result->y= y;
-  result->shape= shape;
-  result->top_node= 1;
+  result->node.shape.x= x;
+  result->node.shape.y= y;
+  result->node.shape.shape= shape;
+  result->node.shape.top_node= 1;
   result->type= nt_shape_node;
-  gcalc_set_double(result->ix, x, coord_extent);
-  gcalc_set_double(result->iy, y, coord_extent);
+  gcalc_set_double(result->node.shape.ix, x, coord_extent);
+  gcalc_set_double(result->node.shape.iy, y, coord_extent);
 
   m_n_points++;
   return result;
@@ -864,11 +864,11 @@ static Gcalc_heap::Info *new_intersection(
   if (!isc)
     return 0;
   isc->type= Gcalc_heap::nt_intersection;
-  isc->p1= ii->edge_a->pi;
-  isc->p2= ii->edge_a->next_pi;
-  isc->p3= ii->edge_b->pi;
-  isc->p4= ii->edge_b->next_pi;
-  isc->intersection_data= ii;
+  isc->node.intersection.p1= ii->edge_a->pi;
+  isc->node.intersection.p2= ii->edge_a->next_pi;
+  isc->node.intersection.p3= ii->edge_b->pi;
+  isc->node.intersection.p4= ii->edge_b->next_pi;
+  isc->node.intersection.data= ii;
   return isc;
 }
 
@@ -881,46 +881,46 @@ static Gcalc_heap::Info *new_eq_point(
   if (!eqp)
     return 0;
   eqp->type= Gcalc_heap::nt_eq_node;
-  eqp->node= p;
-  eqp->eq_data= edge;
+  eqp->node.eq.node= p;
+  eqp->node.eq.data= edge;
   return eqp;
 }
 
 
 void Gcalc_heap::Info::calc_xy(double *x, double *y) const
 {
-  double b0_x= p2->x - p1->x;
-  double b0_y= p2->y - p1->y;
-  double b1_x= p4->x - p3->x;
-  double b1_y= p4->y - p3->y;
+  double b0_x= node.intersection.p2->node.shape.x - node.intersection.p1->node.shape.x;
+  double b0_y= node.intersection.p2->node.shape.y - node.intersection.p1->node.shape.y;
+  double b1_x= node.intersection.p4->node.shape.x - node.intersection.p3->node.shape.x;
+  double b1_y= node.intersection.p4->node.shape.y - node.intersection.p3->node.shape.y;
   double b0xb1= b0_x * b1_y - b0_y * b1_x;
-  double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x;
+  double t= (node.intersection.p3->node.shape.x - node.intersection.p1->node.shape.x) * b1_y - (node.intersection.p3->node.shape.y - node.intersection.p1->node.shape.y) * b1_x;
 
   t/= b0xb1;
 
-  *x= p1->x + b0_x * t;
-  *y= p1->y + b0_y * t;
+  *x= node.intersection.p1->node.shape.x + b0_x * t;
+  *y= node.intersection.p1->node.shape.y + b0_y * t;
 }
 
 
 #ifdef GCALC_CHECK_WITH_FLOAT
 void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const
 {
-  long double b0_x= ((long double) p2->x) - p1->x;
-  long double b0_y= ((long double) p2->y) - p1->y;
-  long double b1_x= ((long double) p4->x) - p3->x;
-  long double b1_y= ((long double) p4->y) - p3->y;
+  long double b0_x= ((long double) p2->node.shape.x) - p1->node.shape.x;
+  long double b0_y= ((long double) p2->node.shape.y) - p1->node.shape.y;
+  long double b1_x= ((long double) p4->node.shape.x) - p3->node.shape.x;
+  long double b1_y= ((long double) p4->node.shape.y) - p3->node.shape.y;
   long double b0xb1= b0_x * b1_y - b0_y * b1_x;
-  long double ax=   ((long double) p3->x) - p1->x;
-  long double ay=   ((long double) p3->y) - p1->y;
+  long double ax=   ((long double) p3->node.shape.x) - p1->node.shape.x;
+  long double ay=   ((long double) p3->node.shape.y) - p1->node.shape.y;
   long double t_a= ax * b1_y - ay * b1_x;
-  long double hx= (b0xb1 * (long double) p1->x + b0_x * t_a);
-  long double hy= (b0xb1 * (long double) p1->y + b0_y * t_a);
+  long double hx= (b0xb1 * (long double) p1->node.shape.x + b0_x * t_a);
+  long double hy= (b0xb1 * (long double) p1->node.shape.y + b0_y * t_a);
 
   if (fabs(b0xb1) < 1e-15)
   {
-    *x= p1->x;
-    *y= p1->y;
+    *x= p1->node.shape.x;
+    *y= p1->node.shape.y;
     return;
   }
 
@@ -933,10 +933,10 @@ void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const
 static int cmp_point_info(const Gcalc_heap::Info *i0,
                           const Gcalc_heap::Info *i1)
 {
-  int cmp_y= gcalc_cmp_coord1(i0->iy, i1->iy);
+  int cmp_y= gcalc_cmp_coord1(i0->node.shape.iy, i1->node.shape.iy);
   if (cmp_y)
     return cmp_y;
-  return gcalc_cmp_coord1(i0->ix, i1->ix);
+  return gcalc_cmp_coord1(i0->node.shape.ix, i1->node.shape.ix);
 }
 
 
@@ -944,11 +944,11 @@ static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node
 {
   if (!node)
     return;
-  node->top_node= 0;
-  GCALC_DBUG_ASSERT((node->left == prev_node) || (node->right == prev_node));
-  if (node->left == prev_node)
-    node->left= node->right;
-  node->right= NULL;
+  node->node.shape.top_node= 0;
+  GCALC_DBUG_ASSERT((node->node.shape.left == prev_node) || (node->node.shape.right == prev_node));
+  if (node->node.shape.left == prev_node)
+    node->node.shape.left= node->node.shape.right;
+  node->node.shape.right= NULL;
   GCALC_DBUG_ASSERT(cmp_point_info(node, prev_node));
 }
 
@@ -972,8 +972,8 @@ void Gcalc_heap::prepare_operation()
   /* TODO - move this to the 'normal_scan' loop */
   for (cur= get_first(); cur; cur= cur->get_next())
   {
-    trim_node(cur->left, cur);
-    trim_node(cur->right, cur);
+    trim_node(cur->node.shape.left, cur);
+    trim_node(cur->node.shape.right, cur);
   }
 }
 
@@ -995,7 +995,7 @@ int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info,
   Gcalc_heap::Info *point= m_heap->new_point_info(x, y, Info);
   if (!point)
     return 1;
-  point->left= point->right= 0;
+  point->node.shape.left= point->node.shape.right= 0;
   return 0;
 }
 
@@ -1018,9 +1018,9 @@ int Gcalc_shape_transporter::int_add_point(gcalc_shape_info Info,
       m_heap->free_point_info(point, hook);
       return 0;
     }
-    GCALC_DBUG_ASSERT(!m_prev || m_prev->x != x || m_prev->y != y);
-    m_prev->left= point;
-    point->right= m_prev;
+    GCALC_DBUG_ASSERT(!m_prev || m_prev->node.shape.x != x || m_prev->node.shape.y != y);
+    m_prev->node.shape.left= point;
+    point->node.shape.right= m_prev;
   }
   else
     m_first= point;
@@ -1040,16 +1040,16 @@ void Gcalc_shape_transporter::int_complete()
   /* simple point */
   if (m_first == m_prev)
   {
-    m_first->right= m_first->left= NULL;
+    m_first->node.shape.right= m_first->node.shape.left= NULL;
     return;
   }
 
   /* line */
   if (m_shape_started == 1)
   {
-    m_first->right= NULL;
-    m_prev->left= m_prev->right;
-    m_prev->right= NULL;
+    m_first->node.shape.right= NULL;
+    m_prev->node.shape.left= m_prev->node.shape.right;
+    m_prev->node.shape.right= NULL;
     return;
   }
 
@@ -1057,32 +1057,32 @@ void Gcalc_shape_transporter::int_complete()
   if (cmp_point_info(m_first, m_prev) == 0)
   {
     /* Coinciding points, remove the last one from the list */
-    m_prev->right->left= m_first;
-    m_first->right= m_prev->right;
+    m_prev->node.shape.right->node.shape.left= m_first;
+    m_first->node.shape.right= m_prev->node.shape.right;
     m_heap->free_point_info(m_prev, m_prev_hook);
   }
   else
   {
-    GCALC_DBUG_ASSERT(m_prev->x != m_first->x || m_prev->y != m_first->y);
-    m_first->right= m_prev;
-    m_prev->left= m_first;
+    GCALC_DBUG_ASSERT(m_prev->node.shape.x != m_first->node.shape.x || m_prev->node.shape.y != m_first->node.shape.y);
+    m_first->node.shape.right= m_prev;
+    m_prev->node.shape.left= m_first;
   }
 }
 
 
 inline void calc_dx_dy(Gcalc_scan_iterator::point *p)
 {
-  gcalc_sub_coord1(p->dx, p->next_pi->ix, p->pi->ix);
-  gcalc_sub_coord1(p->dy, p->next_pi->iy, p->pi->iy);
+  gcalc_sub_coord1(p->dx, p->next_pi->node.shape.ix, p->pi->node.shape.ix);
+  gcalc_sub_coord1(p->dy, p->next_pi->node.shape.iy, p->pi->node.shape.iy);
   if (GCALC_SIGN(p->dx[0]))
   {
-    p->l_border= &p->next_pi->ix;
-    p->r_border= &p->pi->ix;
+    p->l_border= &p->next_pi->node.shape.ix;
+    p->r_border= &p->pi->node.shape.ix;
   }
   else
   {
-    p->r_border= &p->next_pi->ix;
-    p->l_border= &p->pi->ix;
+    p->r_border= &p->next_pi->node.shape.ix;
+    p->l_border= &p->pi->node.shape.ix;
   }
 }
 
@@ -1143,10 +1143,10 @@ int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_heap::Info *p1,
                                           const Gcalc_heap::Info *p4)
 {
   Gcalc_coord1 dx_a, dy_a, dx_b, dy_b;
-  gcalc_sub_coord1(dx_a, p2->ix, p1->ix);
-  gcalc_sub_coord1(dy_a, p2->iy, p1->iy);
-  gcalc_sub_coord1(dx_b, p4->ix, p3->ix);
-  gcalc_sub_coord1(dy_b, p4->iy, p3->iy);
+  gcalc_sub_coord1(dx_a, p2->node.shape.ix, p1->node.shape.ix);
+  gcalc_sub_coord1(dy_a, p2->node.shape.iy, p1->node.shape.iy);
+  gcalc_sub_coord1(dx_b, p4->node.shape.ix, p3->node.shape.ix);
+  gcalc_sub_coord1(dy_b, p4->node.shape.iy, p3->node.shape.iy);
   return cmp_dx_dy(dx_a, dy_a, dx_b, dy_b);
 }
 
@@ -1168,8 +1168,8 @@ void Gcalc_scan_iterator::point::calc_x(long double *x, long double y,
     *x= ix;
   }
   else
-    *x= (ddy * (long double) pi->x + gcalc_get_double(dx, GCALC_COORD_BASE) *
-          (y - pi->y)) / ddy;
+    *x= (ddy * (long double) pi->node.shape.x + gcalc_get_double(dx, GCALC_COORD_BASE) *
+          (y - pi->node.shape.y)) / ddy;
 }
 #endif /*GCALC_CHECK_WITH_FLOAT*/
 
@@ -1280,7 +1280,7 @@ int Gcalc_scan_iterator::arrange_event(int do_sorting, int n_intersections)
 int Gcalc_heap::Info::equal_pi(const Info *pi) const
 {
   if (type == nt_intersection)
-    return equal_intersection;
+    return node.intersection.equal;
   if (pi->type == nt_eq_node)
     return 1;
   if (type == nt_eq_node || pi->type == nt_intersection)
@@ -1322,7 +1322,7 @@ int Gcalc_scan_iterator::step()
 #ifndef GCALC_DBUG_OFF
     if (m_cur_pi->type == Gcalc_heap::nt_intersection &&
         m_cur_pi->get_next()->type == Gcalc_heap::nt_intersection &&
-        m_cur_pi->equal_intersection)
+        m_cur_pi->node.intersection.equal)
       GCALC_DBUG_ASSERT(cmp_intersections(m_cur_pi, m_cur_pi->get_next()) == 0);
 #endif /*GCALC_DBUG_OFF*/
     GCALC_DBUG_CHECK_COUNTER();
@@ -1377,23 +1377,23 @@ static int node_on_right(const Gcalc_heap::Info *node,
   Gcalc_coord2 ax_by, ay_bx;
   int result;
 
-  gcalc_sub_coord1(a_x, node->ix, edge_a->ix);
-  gcalc_sub_coord1(a_y, node->iy, edge_a->iy);
-  gcalc_sub_coord1(b_x, edge_b->ix, edge_a->ix);
-  gcalc_sub_coord1(b_y, edge_b->iy, edge_a->iy);
+  gcalc_sub_coord1(a_x, node->node.shape.ix, edge_a->node.shape.ix);
+  gcalc_sub_coord1(a_y, node->node.shape.iy, edge_a->node.shape.iy);
+  gcalc_sub_coord1(b_x, edge_b->node.shape.ix, edge_a->node.shape.ix);
+  gcalc_sub_coord1(b_y, edge_b->node.shape.iy, edge_a->node.shape.iy);
   gcalc_mul_coord1(ax_by, a_x, b_y);
   gcalc_mul_coord1(ay_bx, a_y, b_x);
   result= gcalc_cmp_coord(ax_by, ay_bx, GCALC_COORD_BASE2);
 #ifdef GCALC_CHECK_WITH_FLOAT
   {
-    long double dx= gcalc_get_double(edge_b->ix, GCALC_COORD_BASE) -
-                      gcalc_get_double(edge_a->ix, GCALC_COORD_BASE);
-    long double dy= gcalc_get_double(edge_b->iy, GCALC_COORD_BASE) -
-                      gcalc_get_double(edge_a->iy, GCALC_COORD_BASE);
-    long double ax= gcalc_get_double(node->ix, GCALC_COORD_BASE) -
-                      gcalc_get_double(edge_a->ix, GCALC_COORD_BASE);
-    long double ay= gcalc_get_double(node->iy, GCALC_COORD_BASE) -
-                      gcalc_get_double(edge_a->iy, GCALC_COORD_BASE);
+    long double dx= gcalc_get_double(edge_b->node.shape.ix, GCALC_COORD_BASE) -
+                      gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE);
+    long double dy= gcalc_get_double(edge_b->node.shape.iy, GCALC_COORD_BASE) -
+                      gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE);
+    long double ax= gcalc_get_double(node->node.shape.ix, GCALC_COORD_BASE) -
+                      gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE);
+    long double ay= gcalc_get_double(node->node.shape.iy, GCALC_COORD_BASE) -
+                      gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE);
     long double d= ax * dy - ay * dx;
     if (result == 0)
       GCALC_DBUG_ASSERT(de_check(d, 0.0));
@@ -1412,8 +1412,8 @@ static int cmp_tops(const Gcalc_heap::Info *top_node,
 {
   int cmp_res_a, cmp_res_b;
 
-  cmp_res_a= gcalc_cmp_coord1(edge_a->ix, top_node->ix);
-  cmp_res_b= gcalc_cmp_coord1(edge_b->ix, top_node->ix);
+  cmp_res_a= gcalc_cmp_coord1(edge_a->node.shape.ix, top_node->node.shape.ix);
+  cmp_res_b= gcalc_cmp_coord1(edge_b->node.shape.ix, top_node->node.shape.ix);
 
   if (cmp_res_a <= 0 && cmp_res_b > 0)
     return -1;
@@ -1438,26 +1438,26 @@ int Gcalc_scan_iterator::insert_top_node()
   if (!sp0)
     GCALC_DBUG_RETURN(1);
   sp0->pi= m_cur_pi;
-  sp0->next_pi= m_cur_pi->left;
+  sp0->next_pi= m_cur_pi->node.shape.left;
 #ifndef GCALC_DBUG_OFF
   sp0->thread= m_cur_thread++;
 #endif /*GCALC_DBUG_OFF*/
-  if (m_cur_pi->left)
+  if (m_cur_pi->node.shape.left)
   {
     calc_dx_dy(sp0);
-    if (m_cur_pi->right)
+    if (m_cur_pi->node.shape.right)
     {
       if (!(sp1= new_slice_point()))
         GCALC_DBUG_RETURN(1);
       sp1->event= sp0->event= scev_two_threads;
       sp1->pi= m_cur_pi;
-      sp1->next_pi= m_cur_pi->right;
+      sp1->next_pi= m_cur_pi->node.shape.right;
 #ifndef GCALC_DBUG_OFF
       sp1->thread= m_cur_thread++;
 #endif /*GCALC_DBUG_OFF*/
       calc_dx_dy(sp1);
       /* We have two threads so should decide which one will be first */
-      cmp_res= cmp_tops(m_cur_pi, m_cur_pi->left, m_cur_pi->right);
+      cmp_res= cmp_tops(m_cur_pi, m_cur_pi->node.shape.left, m_cur_pi->node.shape.right);
       if (cmp_res > 0)
       {
         point *tmp= sp0;
@@ -1467,7 +1467,7 @@ int Gcalc_scan_iterator::insert_top_node()
       else if (cmp_res == 0)
       {
         /* Exactly same direction of the edges. */
-        cmp_res= gcalc_cmp_coord1(m_cur_pi->left->iy, m_cur_pi->right->iy);
+        cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.iy, m_cur_pi->node.shape.right->node.shape.iy);
         if (cmp_res != 0)
         {
           if (cmp_res < 0)
@@ -1483,7 +1483,7 @@ int Gcalc_scan_iterator::insert_top_node()
         }
         else
         {
-          cmp_res= gcalc_cmp_coord1(m_cur_pi->left->ix, m_cur_pi->right->ix);
+          cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.ix, m_cur_pi->node.shape.right->node.shape.ix);
           if (cmp_res != 0)
           {
             if (cmp_res < 0)
@@ -1517,7 +1517,7 @@ int Gcalc_scan_iterator::insert_top_node()
     /* We need to find the place to insert. */
     for (; sp; prev_hook= sp->next_ptr(), sp=sp->get_next())
     {
-      if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->ix) < 0)
+      if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->node.shape.ix) < 0)
         continue;
       cmp_res= node_on_right(m_cur_pi, sp->pi, sp->next_pi);
       if (cmp_res == 0)
@@ -1743,7 +1743,7 @@ int Gcalc_scan_iterator::node_scan()
   GCALC_DBUG_PRINT(("node for %d", sp->thread));
   /* Handle the point itself. */
   sp->pi= cur_pi;
-  sp->next_pi= cur_pi->left;
+  sp->next_pi= cur_pi->node.shape.left;
   sp->event= scev_point;
   calc_dx_dy(sp);
 
@@ -1794,7 +1794,7 @@ void Gcalc_scan_iterator::intersection_scan()
   ii->edge_a->event= ii->edge_b->event= scev_intersection;
   ii->edge_a->ev_pi= ii->edge_b->ev_pi= m_cur_pi;
   free_item(ii);
-  m_cur_pi->intersection_data= NULL;
+  m_cur_pi->node.intersection.data= NULL;
 
   GCALC_DBUG_VOID_RETURN;
 }
@@ -1813,7 +1813,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b,
       !(ii= new_intersection(m_heap, i_calc)))
     GCALC_DBUG_RETURN(1);
 
-  ii->equal_intersection= 0;
+  ii->node.intersection.equal= 0;
 
   for (;
        pi_from->get_next() != sp_a->next_pi &&
@@ -1824,7 +1824,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b,
     if (skip_next)
     {
       if (cur->type == Gcalc_heap::nt_intersection)
-        skip_next= cur->equal_intersection;
+        skip_next= cur->node.intersection.equal;
       else
         skip_next= 0;
       continue;
@@ -1832,7 +1832,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b,
     if (cur->type == Gcalc_heap::nt_intersection)
     {
       cmp_res= cmp_intersections(cur, ii);
-      skip_next= cur->equal_intersection;
+      skip_next= cur->node.intersection.equal;
     }
     else if (cur->type == Gcalc_heap::nt_eq_node)
       continue;
@@ -1840,7 +1840,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b,
       cmp_res= cmp_node_isc(cur, ii);
     if (cmp_res == 0)
     {
-      ii->equal_intersection= 1;
+      ii->node.intersection.equal= 1;
       break;
     }
     else if (cmp_res > 0)
@@ -1881,13 +1881,13 @@ void calc_t(Gcalc_coord2 t_a, Gcalc_coord2 t_b,
   Gcalc_coord2 x1y2, x2y1;
   Gcalc_coord1 dya, dyb;
 
-  gcalc_sub_coord1(a2_a1x, p3->ix, p1->ix);
-  gcalc_sub_coord1(a2_a1y, p3->iy, p1->iy);
+  gcalc_sub_coord1(a2_a1x, p3->node.shape.ix, p1->node.shape.ix);
+  gcalc_sub_coord1(a2_a1y, p3->node.shape.iy, p1->node.shape.iy);
 
-  gcalc_sub_coord1(dxa, p2->ix, p1->ix);
-  gcalc_sub_coord1(dya, p2->iy, p1->iy);
-  gcalc_sub_coord1(dxb, p4->ix, p3->ix);
-  gcalc_sub_coord1(dyb, p4->iy, p3->iy);
+  gcalc_sub_coord1(dxa, p2->node.shape.ix, p1->node.shape.ix);
+  gcalc_sub_coord1(dya, p2->node.shape.iy, p1->node.shape.iy);
+  gcalc_sub_coord1(dxb, p4->node.shape.ix, p3->node.shape.ix);
+  gcalc_sub_coord1(dyb, p4->node.shape.iy, p3->node.shape.iy);
 
   gcalc_mul_coord1(x1y2, dxa, dyb);
   gcalc_mul_coord1(x2y1, dya, dxb);
@@ -1908,11 +1908,11 @@ double Gcalc_scan_iterator::get_y() const
     Gcalc_coord2 t_a, t_b;
     Gcalc_coord3 a_tb, b_ta, y_exp;
     calc_t(t_a, t_b, dxa, dya,
-           state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4);
+           state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4);
 
 
     gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
-        t_b, GCALC_COORD_BASE2, state.pi->p1->iy, GCALC_COORD_BASE);
+        t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.iy, GCALC_COORD_BASE);
     gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
         t_a, GCALC_COORD_BASE2, dya, GCALC_COORD_BASE);
 
@@ -1922,7 +1922,7 @@ double Gcalc_scan_iterator::get_y() const
              get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent;
   }
   else
-    return state.pi->y;
+    return state.pi->node.shape.y;
 }
 
 
@@ -1934,11 +1934,11 @@ double Gcalc_scan_iterator::get_event_x() const
     Gcalc_coord2 t_a, t_b;
     Gcalc_coord3 a_tb, b_ta, x_exp;
     calc_t(t_a, t_b, dxa, dya,
-           state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4);
+           state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4);
 
 
     gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
-        t_b, GCALC_COORD_BASE2, state.pi->p1->ix, GCALC_COORD_BASE);
+        t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.ix, GCALC_COORD_BASE);
     gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
         t_a, GCALC_COORD_BASE2, dxa, GCALC_COORD_BASE);
 
@@ -1948,7 +1948,7 @@ double Gcalc_scan_iterator::get_event_x() const
              get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent;
   }
   else
-    return state.pi->x;
+    return state.pi->node.shape.x;
 }
 
 double Gcalc_scan_iterator::get_h() const
@@ -1961,7 +1961,7 @@ double Gcalc_scan_iterator::get_h() const
     state.pi->calc_xy(&x, &next_y);
   }
   else
-    next_y= state.pi->y;
+    next_y= state.pi->node.shape.y;
   return next_y - cur_y;
 }
 
@@ -1970,11 +1970,11 @@ double Gcalc_scan_iterator::get_sp_x(const point *sp) const
 {
   double dy;
   if (sp->event & (scev_end | scev_two_ends | scev_point))
-    return sp->pi->x;
-  dy= sp->next_pi->y - sp->pi->y;
+    return sp->pi->node.shape.x;
+  dy= sp->next_pi->node.shape.y - sp->pi->node.shape.y;
   if (fabs(dy) < 1e-12)
-    return sp->pi->x;
-  return (sp->next_pi->x - sp->pi->x) * dy;
+    return sp->pi->node.shape.x;
+  return (sp->next_pi->node.shape.x - sp->pi->node.shape.x) * dy;
 }
 
 
diff --git a/sql/gcalc_slicescan.h b/sql/gcalc_slicescan.h
index 55de497..4996287 100644
--- a/sql/gcalc_slicescan.h
+++ b/sql/gcalc_slicescan.h
@@ -26,7 +26,7 @@
 
 #ifndef GCALC_DBUG_OFF
 #define GCALC_DBUG_PRINT(b) DBUG_PRINT("Gcalc", b)
-#define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc "a)
+#define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc " a)
 #define GCALC_DBUG_RETURN(r) DBUG_RETURN(r)
 #define GCALC_DBUG_VOID_RETURN DBUG_VOID_RETURN
 #define GCALC_DBUG_ASSERT(r) DBUG_ASSERT(r)
@@ -188,7 +188,7 @@ public:
         double x,y;
         Gcalc_coord1 ix, iy;
         int top_node;
-      };
+      } shape;
       struct
       {
         /* nt_intersection */
@@ -197,21 +197,21 @@ public:
         const Info *p2;
         const Info *p3;
         const Info *p4;
-        void *intersection_data;
-        int equal_intersection;
-      };
+        void *data;
+        int equal;
+      } intersection;
       struct
       {
         /* nt_eq_node */
         const Info *node;
-        void *eq_data;
-      };
-    };
+        void *data;
+      } eq;
+    } node;
 
     bool is_bottom() const
-      { GCALC_DBUG_ASSERT(type == nt_shape_node); return !left; }
+      { GCALC_DBUG_ASSERT(type == nt_shape_node); return !node.shape.left; }
     bool is_top() const
-      { GCALC_DBUG_ASSERT(type == nt_shape_node); return top_node; }
+      { GCALC_DBUG_ASSERT(type == nt_shape_node); return node.shape.top_node; }
     bool is_single_node() const
       { return is_bottom() && is_top(); }
 
@@ -383,7 +383,7 @@ public:
     inline const point *c_get_next() const
       { return (const point *)next; }
     inline bool is_bottom() const { return !next_pi; }
-    gcalc_shape_info get_shape() const { return pi->shape; }
+    gcalc_shape_info get_shape() const { return pi->node.shape.shape; }
     inline point *get_next() { return (point *)next; }
     inline const point *get_next() const { return (const point *)next; }
     /* Compare the dx_dy parameters regarding the horiz_dir */
diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc
index 8644374..f3c24f9 100644
--- a/sql/gcalc_tools.cc
+++ b/sql/gcalc_tools.cc
@@ -1243,7 +1243,7 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res,
       GCALC_DBUG_RETURN(1);
   }
   else
-    if (storage->single_point(res->pi->x, res->pi->y))
+    if (storage->single_point(res->pi->node.shape.x, res->pi->node.shape.y))
       GCALC_DBUG_RETURN(1);
   free_result(res);
   GCALC_DBUG_RETURN(0);
@@ -1269,8 +1269,8 @@ int Gcalc_operation_reducer::get_result_thread(res_point *cur,
       }
       else
       {
-	x= cur->pi->x;
-        y= cur->pi->y;
+	x= cur->pi->node.shape.x;
+        y= cur->pi->node.shape.y;
       }
       if (storage->add_point(x, y))
         GCALC_DBUG_RETURN(1);
diff --git a/sql/handler.cc b/sql/handler.cc
index 7e756ff..d528c0a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
diff --git a/sql/handler.h b/sql/handler.h
index 642a922..3d6c8de 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1,8 +1,8 @@
 #ifndef HANDLER_INCLUDED
 #define HANDLER_INCLUDED
 /*
-   Copyright (c) 2000, 2011, Oracle and/or its affiliates.
-   Copyright (c) 2009-2011 Monty Program Ab
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -333,7 +333,9 @@
 /* Flags for method is_fatal_error */
 #define HA_CHECK_DUP_KEY 1
 #define HA_CHECK_DUP_UNIQUE 2
+#define HA_CHECK_FK_ERROR 4
 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE)
+#define HA_CHECK_ALL (~0U)
 
 enum legacy_db_type
 {
@@ -2023,7 +2025,10 @@ public:
         ((flags & HA_CHECK_DUP_KEY) &&
          (error == HA_ERR_FOUND_DUPP_KEY ||
           error == HA_ERR_FOUND_DUPP_UNIQUE)) ||
-        error == HA_ERR_AUTOINC_ERANGE)
+        error == HA_ERR_AUTOINC_ERANGE ||
+        ((flags & HA_CHECK_FK_ERROR) &&
+         (error == HA_ERR_ROW_IS_REFERENCED ||
+          error == HA_ERR_NO_REFERENCED_ROW)))
       return FALSE;
     return TRUE;
   }
@@ -3105,4 +3110,5 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 {
   return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 }
-#endif
+
+#endif /* HANDLER_INCLUDED */
diff --git a/sql/item.cc b/sql/item.cc
index 6d2983f..3d33933 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2014, Monty Program Ab.
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -1272,6 +1272,11 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
   {
     uint cnv_errors;
     String *ostr= val_str(&cnvstr);
+    if (null_value)
+    {
+      Item_null *n= new Item_null();
+      return n ? n->safe_charset_converter(tocs) : NULL;
+    }
     cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
                             ostr->charset(), tocs, &cnv_errors);
     if (cnv_errors)
@@ -3888,7 +3893,7 @@ Item_param::eq(const Item *arg, bool binary_cmp) const
 
 void Item_param::print(String *str, enum_query_type query_type)
 {
-  if (state == NO_VALUE)
+  if (state == NO_VALUE || query_type & QT_NO_DATA_EXPANSION)
   {
     str->append('?');
   }
@@ -6753,7 +6758,8 @@ Item *Item_field::update_value_transformer(uchar *select_arg)
 
 void Item_field::print(String *str, enum_query_type query_type)
 {
-  if (field && field->table->const_table)
+  if (field && field->table->const_table &&
+      !(query_type & QT_NO_DATA_EXPANSION))
   {
     print_value(str);
     return;
diff --git a/sql/item.h b/sql/item.h
index f8e8ead..41e6fe0 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2,7 +2,7 @@
 #define SQL_ITEM_INCLUDED
 
 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015 Monty Program Ab.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -2175,7 +2175,7 @@ public:
     max_length= 0;
     name= name_par ? name_par : (char*) "NULL";
     fixed= 1;
-    collation.set(&my_charset_bin, DERIVATION_IGNORABLE);
+    collation.set(&my_charset_bin, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
   }
   enum Type type() const { return NULL_ITEM; }
   bool eq(const Item *item, bool binary_cmp) const;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d5f5087..fb75c9a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015, MariaDB
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -2558,10 +2558,7 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
   DBUG_ASSERT(fixed == 1);
   if (!args[0]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
     return (null_value= false);
-  if (!args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
-    return (null_value= false);
-  bzero((char*) ltime,sizeof(*ltime));
-  return null_value= !(fuzzydate & TIME_FUZZY_DATES);
+  return (null_value= args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES));
 }
 
 
@@ -3018,24 +3015,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
 }
 
 
-void Item_func_case::agg_str_lengths(Item* arg)
-{
-  fix_char_length(max(max_char_length(), arg->max_char_length()));
-  set_if_bigger(decimals, arg->decimals);
-  unsigned_flag= unsigned_flag && arg->unsigned_flag;
-}
-
-
-void Item_func_case::agg_num_lengths(Item *arg)
-{
-  uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals,
-                                           arg->unsigned_flag) - arg->decimals;
-  set_if_bigger(max_length, len); 
-  set_if_bigger(decimals, arg->decimals);
-  unsigned_flag= unsigned_flag && arg->unsigned_flag; 
-}
-
-
 /**
   Check if (*place) and new_value points to different Items and call
   THD::change_item_tree() if needed.
@@ -3101,17 +3080,7 @@ void Item_func_case::fix_length_and_dec()
   }
   else
   {
-    collation.set_numeric();
-    max_length=0;
-    decimals=0;
-    unsigned_flag= TRUE;
-    for (uint i= 0; i < ncases; i+= 2)
-      agg_num_lengths(args[i + 1]);
-    if (else_expr_num != -1) 
-      agg_num_lengths(args[else_expr_num]);
-    max_length= my_decimal_precision_to_length_no_truncation(max_length +
-                                                             decimals, decimals,
-                                               unsigned_flag);
+    fix_attributes(agg, nagg);
   }
   
   /*
@@ -3311,15 +3280,12 @@ double Item_func_coalesce::real_op()
 bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
 {
   DBUG_ASSERT(fixed == 1);
-  null_value= 0;
   for (uint i= 0; i < arg_count; i++)
   {
-    bool res= args[i]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES);
-    if (!args[i]->null_value)
-      return res;
+    if (!args[i]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
+      return (null_value= false);
   }
-  bzero((char*) ltime,sizeof(*ltime));
-  return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+  return (null_value= true);
 }
 
 
@@ -3342,19 +3308,32 @@ void Item_func_coalesce::fix_length_and_dec()
 {
   cached_field_type= agg_field_type(args, arg_count);
   agg_result_type(&cached_result_type, args, arg_count);
+  fix_attributes(args, arg_count);
+}
+
+
+#if MYSQL_VERSION_ID > 100100
+#error Rename this to Item_hybrid_func::fix_attributes() when mering to 10.1
+#endif
+void Item_func_hybrid_result_type::fix_attributes(Item **items, uint nitems)
+{
   switch (cached_result_type) {
   case STRING_RESULT:
-    if (count_string_result_length(cached_field_type, args, arg_count))
+    if (count_string_result_length(field_type(),
+                                   items, nitems))
       return;          
     break;
   case DECIMAL_RESULT:
-    count_decimal_length();
+    collation.set_numeric();
+    count_decimal_length(items, nitems);
     break;
   case REAL_RESULT:
-    count_real_length();
+    collation.set_numeric();
+    count_real_length(items, nitems);
     break;
   case INT_RESULT:
-    count_only_length(args, arg_count);
+    collation.set_numeric();
+    count_only_length(items, nitems);
     decimals= 0;
     break;
   case ROW_RESULT:
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index babe1d7..0194f9c 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1,7 +1,7 @@
 #ifndef ITEM_CMPFUNC_INCLUDED
 #define ITEM_CMPFUNC_INCLUDED
 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015, MariaDB
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -1255,8 +1255,6 @@ public:
   Item *find_item(String *str);
   CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
   void cleanup();
-  void agg_str_lengths(Item *arg);
-  void agg_num_lengths(Item *arg);
 };
 
 /*
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 252ca9e..bd6553d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -641,16 +641,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems)
   result length/precision depends on argument ones.
 */
 
-void Item_func::count_decimal_length()
+void Item_func::count_decimal_length(Item **item, uint nitems)
 {
   int max_int_part= 0;
   decimals= 0;
   unsigned_flag= 1;
-  for (uint i=0 ; i < arg_count ; i++)
+  for (uint i=0 ; i < nitems ; i++)
   {
-    set_if_bigger(decimals, args[i]->decimals);
-    set_if_bigger(max_int_part, args[i]->decimal_int_part());
-    set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
+    set_if_bigger(decimals, item[i]->decimals);
+    set_if_bigger(max_int_part, item[i]->decimal_int_part());
+    set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
   }
   int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
   fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
@@ -681,19 +681,19 @@ void Item_func::count_only_length(Item **item, uint nitems)
   result length/precision depends on argument ones.
 */
 
-void Item_func::count_real_length()
+void Item_func::count_real_length(Item **item, uint nitems)
 {
   uint32 length= 0;
   decimals= 0;
   max_length= 0;
-  for (uint i=0 ; i < arg_count ; i++)
+  for (uint i=0 ; i < nitems ; i++)
   {
     if (decimals != NOT_FIXED_DEC)
     {
-      set_if_bigger(decimals, args[i]->decimals);
-      set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
+      set_if_bigger(decimals, item[i]->decimals);
+      set_if_bigger(length, (item[i]->max_length - item[i]->decimals));
     }
-    set_if_bigger(max_length, args[i]->max_length);
+    set_if_bigger(max_length, item[i]->max_length);
   }
   if (decimals != NOT_FIXED_DEC)
   {
@@ -811,7 +811,7 @@ void Item_num_op::fix_length_and_dec(void)
   if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
       r0 == STRING_RESULT || r1 ==STRING_RESULT)
   {
-    count_real_length();
+    count_real_length(args, arg_count);
     max_length= float_length(decimals);
     cached_result_type= REAL_RESULT;
   }
diff --git a/sql/item_func.h b/sql/item_func.h
index 33fa49f..667be3c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1,7 +1,7 @@
 #ifndef ITEM_FUNC_INCLUDED
 #define ITEM_FUNC_INCLUDED
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -39,6 +39,13 @@ protected:
     0 means get this number from first argument
   */
   uint allowed_arg_cols;
+
+  void count_only_length(Item **item, uint nitems);
+  void count_real_length(Item **item, uint nitems);
+  void count_decimal_length(Item **item, uint nitems);
+  void count_datetime_length(Item **item, uint nitems);
+  bool count_string_result_length(enum_field_types field_type,
+                                  Item **item, uint nitems);
 public:
   uint arg_count;
   table_map used_tables_cache, not_null_tables_cache;
@@ -146,16 +153,10 @@ public:
   virtual void print(String *str, enum_query_type query_type);
   void print_op(String *str, enum_query_type query_type);
   void print_args(String *str, uint from, enum_query_type query_type);
-  void count_only_length(Item **item, uint nitems);
-  void count_real_length();
-  void count_decimal_length();
   inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
   {
     return (null_value=args[0]->get_date(ltime, fuzzy_date));
   }
-  void count_datetime_length(Item **item, uint nitems);
-  bool count_string_result_length(enum_field_types field_type,
-                                  Item **item, uint nitems);
   inline bool get_arg0_time(MYSQL_TIME *ltime)
   {
     null_value= args[0]->get_time(ltime);
@@ -245,7 +246,7 @@ public:
     char buf[256];
     String str(buf, sizeof(buf), system_charset_info);
     str.length(0);
-    print(&str, QT_ORDINARY);
+    print(&str, QT_NO_DATA_EXPANSION);
     my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe());
   }
   inline double raise_float_overflow()
@@ -436,7 +437,7 @@ class Item_func_hybrid_result_type: public Item_func
   }
 protected:
   Item_result cached_result_type;
-
+  void fix_attributes(Item **item, uint nitems);
 public:
   Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT)
   { collation.set_numeric(); }
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 5e1c0ad..8815dac 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -636,10 +636,10 @@ static double count_edge_t(const Gcalc_heap::Info *ea,
                            double &ex, double &ey, double &vx, double &vy,
                            double &e_sqrlen)
 {
-  ex= eb->x - ea->x;
-  ey= eb->y - ea->y;
-  vx= v->x - ea->x;
-  vy= v->y - ea->y;
+  ex= eb->node.shape.x - ea->node.shape.x;
+  ey= eb->node.shape.y - ea->node.shape.y;
+  vx= v->node.shape.x - ea->node.shape.x;
+  vy= v->node.shape.y - ea->node.shape.y;
   e_sqrlen= ex * ex + ey * ey;
   return (ex * vx + ey * vy) / e_sqrlen;
 }
@@ -655,8 +655,8 @@ static double distance_to_line(double ex, double ey, double vx, double vy,
 static double distance_points(const Gcalc_heap::Info *a,
                               const Gcalc_heap::Info *b)
 {
-  double x= a->x - b->x;
-  double y= a->y - b->y;
+  double x= a->node.shape.x - b->node.shape.x;
+  double y= a->node.shape.y - b->node.shape.y;
   return sqrt(x * x + y * y);
 }
 
@@ -1697,7 +1697,7 @@ double Item_func_distance::val_real()
       continue;
 
 count_distance:
-    if (cur_point->shape >= obj2_si)
+    if (cur_point->node.shape.shape >= obj2_si)
       continue;
     cur_point_edge= !cur_point->is_bottom();
 
@@ -1705,13 +1705,13 @@ count_distance:
     {
       /* We only check vertices of object 2 */
       if (dist_point->type != Gcalc_heap::nt_shape_node ||
-          dist_point->shape < obj2_si)
+          dist_point->node.shape.shape < obj2_si)
         continue;
 
       /* if we have an edge to check */
-      if (dist_point->left)
+      if (dist_point->node.shape.left)
       {
-        t= count_edge_t(dist_point, dist_point->left, cur_point,
+        t= count_edge_t(dist_point, dist_point->node.shape.left, cur_point,
                         ex, ey, vx, vy, e_sqrlen);
         if ((t>0.0) && (t<1.0))
         {
@@ -1722,7 +1722,7 @@ count_distance:
       }
       if (cur_point_edge)
       {
-        t= count_edge_t(cur_point, cur_point->left, dist_point,
+        t= count_edge_t(cur_point, cur_point->node.shape.left, dist_point,
                         ex, ey, vx, vy, e_sqrlen);
         if ((t>0.0) && (t<1.0))
         {
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index a2a6175..922593f 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -1,8 +1,8 @@
 #ifndef ITEM_GEOFUNC_INCLUDED
 #define ITEM_GEOFUNC_INCLUDED
 
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
-   Copyright (C) 2011 Monty Program Ab.
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
+   Copyright (C) 2011, 2016, MariaDB
 
    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
@@ -191,7 +191,7 @@ public:
       if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
       {
         String str;
-        args[i]->print(&str, QT_ORDINARY);
+        args[i]->print(&str, QT_NO_DATA_EXPANSION);
         str.append('\0');
         my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
                  str.ptr());
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index aca66fc..94370d4 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1212,7 +1212,7 @@ String *Item_func_insert::val_str(String *str)
    length= res->charpos((int) length, (uint32) start);
 
   /* Re-testing with corrected params */
-  if (start > res->length())
+  if (start + 1 > res->length()) // remember, start = args[1].val_int() - 1
     return res; /* purecov: inspected */        // Wrong param; skip insert
   if (length > res->length() - start)
     length= res->length() - start;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 3020faf..ba67474 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1748,27 +1748,6 @@ Item_in_subselect::single_value_transformer(JOIN *join)
       runtime created Ref item which is deleted at the end
       of the statement. Thus one of 'substitution' arguments
       can be broken in case of PS.
-
-      @todo
-      Why do we use real_item()/substitutional_item() instead of the plain
-      left_expr?
-      Because left_expr might be a rollbackable item, and we fail to properly
-      rollback all copies of left_expr at end of execution, so we want to
-      avoid creating copies of left_expr as much as possible, so we use
-      real_item() instead.
-      Doing a proper rollback is difficult: the change was registered for the
-      original item which was the left argument of IN. Then this item was
-      copied to left_expr, which is copied below to substitution->args[0]. To
-      do a proper rollback, we would have to restore the content
-      of both copies as well as the original item. There might be more copies,
-      if AND items have been constructed.
-      The same applies to the right expression.
-      However, using real_item()/substitutional_item() brings its own
-      problems: for example, we lose information that the item is an outer
-      reference; the item can thus wrongly be considered for a Keyuse (causing
-      bug#17766653).
-      When WL#6570 removes the "rolling back" system, all
-      real_item()/substitutional_item() in this file should be removed.
     */ 
     substitution= func->create(left_expr, where_item);
     have_to_be_excluded= 1;
@@ -2055,9 +2034,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
   }
   else
   {
-    /*
-      Grep for "WL#6570" to see the relevant comment about real_item.
-    */
     Item *item= (Item*) select_lex->item_list.head()->real_item();
 
     if (select_lex->table_list.elements)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 522004e..873dcda 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2012, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2013, Monty Program Ab
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -2916,7 +2916,7 @@ void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
     str->append(STRING_WITH_LEN("SECOND"));
     break;		
   case INTERVAL_MICROSECOND:
-    str->append(STRING_WITH_LEN("SECOND_FRAC"));
+    str->append(STRING_WITH_LEN("MICROSECOND"));
     break;
   default:
     break;
diff --git a/sql/log.cc b/sql/log.cc
index a87ec72..a753403 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, SkySQL Ab.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c962f19..82d747a 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, Monty Program Ab.
+   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -3093,7 +3093,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
   
   slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
   exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
-  db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
+  db_len = (uchar)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
   error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
 
   /*
@@ -9692,8 +9692,8 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file)
   DBUG_ASSERT(m_dbnam != NULL);
   DBUG_ASSERT(m_tblnam != NULL);
   /* We use only one byte per length for storage in event: */
-  DBUG_ASSERT(m_dblen < 128);
-  DBUG_ASSERT(m_tbllen < 128);
+  DBUG_ASSERT(m_dblen <= min(NAME_LEN, 255));
+  DBUG_ASSERT(m_tbllen <= min(NAME_LEN, 255));
 
   uchar const dbuf[]= { (uchar) m_dblen };
   uchar const tbuf[]= { (uchar) m_tbllen };
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6a14b5c..3450447 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -279,7 +279,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
 
 static const char *tc_heuristic_recover_names[]=
 {
-  "COMMIT", "ROLLBACK", NullS
+  "OFF", "COMMIT", "ROLLBACK", NullS
 };
 static TYPELIB tc_heuristic_recover_typelib=
 {
@@ -1254,7 +1254,6 @@ static openssl_lock_t *openssl_dynlock_create(const char *, int);
 static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
 static void openssl_lock_function(int, int, const char *, int);
 static void openssl_lock(int, openssl_lock_t *, const char *, int);
-static unsigned long openssl_id_function();
 #endif
 char *des_key_file;
 #ifndef EMBEDDED_LIBRARY
@@ -3984,7 +3983,6 @@ static int init_thread_environment()
   CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
   CRYPTO_set_dynlock_lock_callback(openssl_lock);
   CRYPTO_set_locking_callback(openssl_lock_function);
-  CRYPTO_set_id_callback(openssl_id_function);
 #endif
 #endif
   mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
@@ -4021,12 +4019,6 @@ static int init_thread_environment()
 
 
 #if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
-static unsigned long openssl_id_function()
-{
-  return (unsigned long) pthread_self();
-}
-
-
 static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
 {
   openssl_lock_t *lock= new openssl_lock_t;
@@ -7386,7 +7378,7 @@ static int mysql_init_variables(void)
   global_query_id= thread_id= 1L;
   my_atomic_rwlock_init(&global_query_id_lock);
   my_atomic_rwlock_init(&thread_running_lock);
-  strmov(server_version, MYSQL_SERVER_VERSION);
+  strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1);
   threads.empty();
   thread_cache.empty();
   key_caches.empty();
@@ -7808,6 +7800,7 @@ mysqld_get_one_option(int optid,
 
 
   case OPT_IGNORE_DB_DIRECTORY:
+    opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions
     if (*argument == 0)
       ignore_db_dirs_reset();
     else
@@ -8113,17 +8106,20 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
 
 void set_server_version(void)
 {
-  char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
-                     MYSQL_SERVER_SUFFIX_STR, NullS);
+  char *version_end= server_version+sizeof(server_version)-1;
+  char *end= strxnmov(server_version, sizeof(server_version)-1,
+                      MYSQL_SERVER_VERSION,
+                      MYSQL_SERVER_SUFFIX_STR, NullS);
 #ifdef EMBEDDED_LIBRARY
-  end= strmov(end, "-embedded");
+  end= strnmov(end, "-embedded", (version_end-end));
 #endif
 #ifndef DBUG_OFF
   if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
-    end= strmov(end, "-debug");
+    end= strnmov(end, "-debug", (version_end-end));
 #endif
   if (opt_log || opt_slow_log || opt_bin_log)
-    strmov(end, "-log");                        // This may slow down system
+    strnmov(end, "-log", (version_end-end)); // This may slow down system
+  *end= 0;
 }
 
 
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 24ae9ec..d0679a3 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2006, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+/* Copyright (c) 2006, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -427,7 +427,13 @@ enum enum_query_type
   /// Without character set introducers.
   QT_WITHOUT_INTRODUCERS= (1 << 1),
   /// view internal representation (like QT_ORDINARY except ORDER BY clause)
-  QT_VIEW_INTERNAL= (1 << 2)
+  QT_VIEW_INTERNAL= (1 << 2),
+  /**
+    If an expression is constant, print the expression, not the value
+    it evaluates to. Should be used for error messages, so that they
+    don't reveal values.
+  */
+  QT_NO_DATA_EXPANSION= (1 << 9),
 };
 
 /* query_id */
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 827290f..5137d8a 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -830,12 +830,14 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
   in_subs->sjm_scan_allowed= FALSE;
   
   bool all_are_fields= TRUE;
+  uint32 total_key_length = 0;
   for (uint i= 0; i < elements; i++)
   {
     Item *outer= in_subs->left_expr->element_index(i);
     Item *inner= it++;
     all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && 
                        inner->real_item()->type() == Item::FIELD_ITEM);
+    total_key_length += inner->max_length;
     if (outer->cmp_type() != inner->cmp_type())
       DBUG_RETURN(FALSE);
     switch (outer->cmp_type()) {
@@ -866,6 +868,15 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
     }
   }
 
+  /*
+     Make sure that create_tmp_table will not fail due to too long keys.
+     See MDEV-7122. This check is performed inside create_tmp_table also and
+     we must do it so that we know the table has keys created.
+  */
+  if (total_key_length > tmp_table_max_key_length() ||
+      elements > tmp_table_max_key_parts())
+    DBUG_RETURN(FALSE);
+
   in_subs->types_allow_materialization= TRUE;
   in_subs->sjm_scan_allowed= all_are_fields;
   DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
@@ -5463,7 +5474,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
           outer join has not been optimized yet).
     */
     if (outer_join && outer_join->table_count > 0 && // (1)
-        outer_join->join_tab)                        // (2)
+        outer_join->join_tab &&                      // (2)
+        !in_subs->const_item())
     {
       /*
         TODO:
diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc
index f442f3a..ebb0dbe 100644
--- a/sql/rpl_reporting.cc
+++ b/sql/rpl_reporting.cc
@@ -57,6 +57,7 @@ Slave_reporting_capability::report(loglevel level, int err_code,
     report_function= sql_print_information;
     break;
   default:
+    va_end(args);
     DBUG_ASSERT(0);                            // should not come here
     return;          // don't crash production builds, just do nothing
   }
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index da7c3f1..0a1c11e 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, SkySQL Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -557,9 +557,8 @@ static void init_check_host(void);
 static void rebuild_check_host(void);
 static ACL_USER *find_acl_user(const char *host, const char *user,
                                my_bool exact);
-static bool update_user_table(THD *thd, TABLE *table, const char *host,
-                              const char *user, const char *new_password,
-                              uint new_password_len);
+static bool update_user_table(THD *, TABLE *, const char *, const char *, const
+                              char *, uint, bool);
 static my_bool acl_load(THD *thd, TABLE_LIST *tables);
 static my_bool grant_load(THD *thd, TABLE_LIST *tables);
 static inline void get_grantor(THD *thd, char* grantor);
@@ -770,7 +769,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
     goto end;
 
   table->use_all_columns();
-  (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50);
   while (!(read_record_info.read_record(&read_record_info)))
   {
     ACL_HOST host;
@@ -827,7 +825,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
     goto end;
 
   table->use_all_columns();
-  (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100);
   username_char_length= min(table->field[1]->char_length(), USERNAME_CHAR_LENGTH);
   password_length= table->field[2]->field_length /
     table->field[2]->charset()->mbmaxlen;
@@ -1030,7 +1027,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
     goto end;
 
   table->use_all_columns();
-  (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100);
   while (!(read_record_info.read_record(&read_record_info)))
   {
     ACL_DB db;
@@ -1092,8 +1088,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
   end_read_record(&read_record_info);
   freeze_size(&acl_dbs);
 
-  (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 
-                               50, 100);
   if (tables[3].table)
   {
     init_read_record(&read_record_info, thd, table= tables[3].table, NULL, 1, 
@@ -1129,6 +1123,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
   return_val= FALSE;
 
 end:
+  end_read_record(&read_record_info);
   thd->variables.sql_mode= old_sql_mode;
   DBUG_RETURN(return_val);
 }
@@ -1143,12 +1138,12 @@ void acl_free(bool end)
   delete_dynamic(&acl_wild_hosts);
   delete_dynamic(&acl_proxy_users);
   my_hash_free(&acl_check_hosts);
-  plugin_unlock(0, native_password_plugin);
-  plugin_unlock(0, old_password_plugin);
   if (!end)
     acl_cache->clear(1); /* purecov: inspected */
   else
   {
+    plugin_unlock(0, native_password_plugin);
+    plugin_unlock(0, old_password_plugin);
     delete acl_cache;
     acl_cache=0;
   }
@@ -1222,6 +1217,10 @@ my_bool acl_reload(THD *thd)
   old_acl_users= acl_users;
   old_acl_proxy_users= acl_proxy_users;
   old_acl_dbs= acl_dbs;
+  my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50);
+  my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100);
+  my_init_dynamic_array(&acl_dbs, sizeof(ACL_DB), 50, 100);
+  my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100);
   old_mem= mem;
   delete_dynamic(&acl_wild_hosts);
   my_hash_free(&acl_check_hosts);
@@ -1912,6 +1911,7 @@ bool change_password(THD *thd, const char *host, const char *user,
   bool save_binlog_row_based;
   uint new_password_len= (uint) strlen(new_password);
   bool result= 1;
+  bool use_salt= 0;
   DBUG_ENTER("change_password");
   DBUG_PRINT("enter",("host: '%s'  user: '%s'  new_password: '%s'",
 		      host,user,new_password));
@@ -1967,6 +1967,7 @@ bool change_password(THD *thd, const char *host, const char *user,
     acl_user->auth_string.length= new_password_len;
     set_user_salt(acl_user, new_password, new_password_len);
     set_user_plugin(acl_user, new_password_len);
+    use_salt= 1;
   }
   else
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
@@ -1975,7 +1976,7 @@ bool change_password(THD *thd, const char *host, const char *user,
   if (update_user_table(thd, table,
 			acl_user->host.hostname ? acl_user->host.hostname : "",
 			acl_user->user ? acl_user->user : "",
-			new_password, new_password_len))
+			new_password, new_password_len, use_salt))
   {
     mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */
     goto end;
@@ -2223,7 +2224,8 @@ bool hostname_requires_resolving(const char *hostname)
 
 static bool update_user_table(THD *thd, TABLE *table,
                               const char *host, const char *user,
-			      const char *new_password, uint new_password_len)
+			      const char *new_password, uint new_password_len,
+                              bool reset_plugin)
 {
   char user_key[MAX_KEY_LENGTH];
   int error;
@@ -2246,6 +2248,11 @@ static bool update_user_table(THD *thd, TABLE *table,
   }
   store_record(table,record[1]);
   table->field[2]->store(new_password, new_password_len, system_charset_info);
+  if (reset_plugin && table->s->fields >= 41)
+  {
+    table->field[40]->reset();
+    table->field[41]->reset();
+  }
   if ((error=table->file->ha_update_row(table->record[1],table->record[0])) &&
       error != HA_ERR_RECORD_IS_THE_SAME)
   {
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 9827c67..12a59fa 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    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
@@ -293,7 +294,8 @@ static inline bool table_not_corrupt_error(uint sql_errno)
           sql_errno == ER_LOCK_WAIT_TIMEOUT ||
           sql_errno == ER_LOCK_DEADLOCK ||
           sql_errno == ER_CANT_LOCK_LOG_TABLE ||
-          sql_errno == ER_OPEN_AS_READONLY);
+          sql_errno == ER_OPEN_AS_READONLY ||
+          sql_errno == ER_WRONG_OBJECT);
 }
 
 
@@ -380,7 +382,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
       lex->query_tables_last= &table->next_global;
       lex->query_tables_own_last= 0;
 
-      if (view_operator_func == NULL)
+      /*
+        CHECK TABLE command is allowed for views as well. Check on alter flags
+        to differentiate from ALTER TABLE...CHECK PARTITION on which view is not
+        allowed.
+      */
+      if (lex->alter_info.flags & ALTER_ADMIN_PARTITION ||
+          view_operator_func == NULL)
       {
         table->required_type=FRMTYPE_TABLE;
         DBUG_ASSERT(!lex->only_view);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1403fe9..cb302de 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -217,11 +217,6 @@ static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables,
 static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry);
 static bool auto_repair_table(THD *thd, TABLE_LIST *table_list);
 static void free_cache_entry(TABLE *entry);
-static bool
-has_write_table_with_auto_increment(TABLE_LIST *tables);
-static bool
-has_write_table_with_auto_increment_and_select(TABLE_LIST *tables);
-static bool has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables);
 
 uint cached_open_tables(void)
 {
@@ -2913,6 +2908,16 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
       */
       if (dd_frm_type(thd, path, &not_used) == FRMTYPE_VIEW)
       {
+        /*
+          If parent_l of the table_list is non null then a merge table
+          has this view as child table, which is not supported.
+        */
+        if (table_list->parent_l)
+        {
+          my_error(ER_WRONG_MRG_TABLE, MYF(0));
+          DBUG_RETURN(true);
+        }
+
         if (!tdc_open_view(thd, table_list, alias, key, key_length,
                            mem_root, 0))
         {
@@ -5892,63 +5897,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
 	*(ptr++)= table->table;
     }
 
-    /*
-    DML statements that modify a table with an auto_increment column based on
-    rows selected from a table are unsafe as the order in which the rows are
-    fetched fron the select tables cannot be determined and may differ on
-    master and slave.
-    */
-    if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables &&
-        has_write_table_with_auto_increment_and_select(tables))
-      thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT);
-    /* Todo: merge all has_write_table_auto_inc with decide_logging_format */
-    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(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST);
-    }
-
-    /* 
-     INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
-     can be unsafe.
-     */
-    uint unique_keys= 0;
-    for (TABLE_LIST *query_table= tables; query_table && unique_keys <= 1;
-         query_table= query_table->next_global)
-      if(query_table->table)
-      {
-        uint keys= query_table->table->s->keys, i= 0;
-        unique_keys= 0;
-        for (KEY* keyinfo= query_table->table->s->key_info;
-             i < keys && unique_keys <= 1; i++, keyinfo++)
-        {
-          if (keyinfo->flags & HA_NOSAME)
-            unique_keys++;
-        }
-        if (!query_table->placeholder() &&
-            query_table->lock_type >= TL_WRITE_ALLOW_WRITE &&
-            unique_keys > 1 && thd->lex->sql_command == SQLCOM_INSERT &&
-            /* Duplicate key update is not supported by INSERT DELAYED */
-            thd->command != COM_DELAYED_INSERT &&
-            thd->lex->duplicates == DUP_UPDATE)
-          thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
-      }
- 
-    /* We have to emulate LOCK TABLES if we are statement needs prelocking. */
-    if (thd->lex->requires_prelocking())
-    {
-
-      /*
-        A query that modifies autoinc column in sub-statement can make the 
-        master and slave inconsistent.
-        We can solve these problems in mixed mode by switching to binlogging 
-        if at least one updated table is used by sub-statement
-      */
-      if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && 
-          has_write_table_with_auto_increment(thd->lex->first_not_own_table()))
-        thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS);
-    }
-
     DEBUG_SYNC(thd, "before_lock_tables_takes_lock");
 
     if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start),
@@ -9673,98 +9621,6 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
   return a->length == b->length && !strncmp(a->str, b->str, a->length);
 }
 
-
-/*
-  Tells if two (or more) tables have auto_increment columns and we want to
-  lock those tables with a write lock.
-
-  SYNOPSIS
-    has_two_write_locked_tables_with_auto_increment
-      tables        Table list
-
-  NOTES:
-    Call this function only when you have established the list of all tables
-    which you'll want to update (including stored functions, triggers, views
-    inside your statement).
-*/
-
-static bool
-has_write_table_with_auto_increment(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))
-      return 1;
-  }
-
-  return 0;
-}
-
-/*
-   checks if we have select tables in the table list and write tables
-   with auto-increment column.
-
-  SYNOPSIS
-   has_two_write_locked_tables_with_auto_increment_and_select
-      tables        Table list
-
-  RETURN VALUES
-
-   -true if the table list has atleast one table with auto-increment column
-
-
-         and atleast one table to select from.
-   -false otherwise
-*/
-
-static bool
-has_write_table_with_auto_increment_and_select(TABLE_LIST *tables)
-{
-  bool has_select= false;
-  bool has_auto_increment_tables = has_write_table_with_auto_increment(tables);
-  for(TABLE_LIST *table= tables; table; table= table->next_global)
-  {
-     if (!table->placeholder() &&
-        (table->lock_type <= TL_READ_NO_INSERT))
-      {
-        has_select= true;
-        break;
-      }
-  }
-  return(has_select && has_auto_increment_tables);
-}
-
-/*
-  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 7b97d58..05a8ee8 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1,6 +1,6 @@
 /*
    Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2008, 2015, MariaDB
+   Copyright (c) 2008, 2016, MariaDB
 
    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
@@ -4493,6 +4493,94 @@ void xid_cache_delete(XID_STATE *xid_state)
   mysql_mutex_unlock(&LOCK_xid_cache);
 }
 
+/*
+  Tells if two (or more) tables have auto_increment columns and we want to
+  lock those tables with a write lock.
+
+  SYNOPSIS
+    has_two_write_locked_tables_with_auto_increment
+      tables        Table list
+
+  NOTES:
+    Call this function only when you have established the list of all tables
+    which you'll want to update (including stored functions, triggers, views
+    inside your statement).
+*/
+
+static bool
+has_write_table_with_auto_increment(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))
+      return 1;
+  }
+
+  return 0;
+}
+
+/*
+   checks if we have select tables in the table list and write tables
+   with auto-increment column.
+
+  SYNOPSIS
+   has_two_write_locked_tables_with_auto_increment_and_select
+      tables        Table list
+
+  RETURN VALUES
+
+   -true if the table list has atleast one table with auto-increment column
+
+
+         and atleast one table to select from.
+   -false otherwise
+*/
+
+static bool
+has_write_table_with_auto_increment_and_select(TABLE_LIST *tables)
+{
+  bool has_select= false;
+  bool has_auto_increment_tables = has_write_table_with_auto_increment(tables);
+  for(TABLE_LIST *table= tables; table; table= table->next_global)
+  {
+     if (!table->placeholder() &&
+        (table->lock_type <= TL_READ_NO_INSERT))
+      {
+        has_select= true;
+        break;
+      }
+  }
+  return(has_select && has_auto_increment_tables);
+}
+
+/*
+  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;
+}
 
 /**
   Decide on logging format to use for the statement and issue errors
@@ -4656,6 +4744,31 @@ int THD::decide_logging_format(TABLE_LIST *tables)
     }
 #endif
 
+    if (variables.binlog_format != BINLOG_FORMAT_ROW && tables)
+    {
+      /*
+        DML statements that modify a table with an auto_increment column based on
+        rows selected from a table are unsafe as the order in which the rows are
+        fetched fron the select tables cannot be determined and may differ on
+        master and slave.
+       */
+      if (has_write_table_with_auto_increment_and_select(tables))
+        lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT);
+
+      if (has_write_table_auto_increment_not_first_in_pk(tables))
+        lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST);
+
+      /*
+        A query that modifies autoinc column in sub-statement can make the
+        master and slave inconsistent.
+        We can solve these problems in mixed mode by switching to binlogging
+        if at least one updated table is used by sub-statement
+       */
+      if (lex->requires_prelocking() &&
+          has_write_table_with_auto_increment(lex->first_not_own_table()))
+        lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS);
+    }
+
     /*
       Get the capabilities vector for all involved storage engines and
       mask out the flags for the binary log.
@@ -4694,6 +4807,26 @@ int THD::decide_logging_format(TABLE_LIST *tables)
 
         prev_write_table= table->table;
 
+        /*
+          INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
+          can be unsafe. Check for it if the flag is already not marked for the
+          given statement.
+        */
+        if (!lex->is_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS) &&
+            lex->sql_command == SQLCOM_INSERT &&
+            /* Duplicate key update is not supported by INSERT DELAYED */
+            command != COM_DELAYED_INSERT && lex->duplicates == DUP_UPDATE)
+        {
+          uint keys= table->table->s->keys, i= 0, unique_keys= 0;
+          for (KEY* keyinfo= table->table->s->key_info;
+               i < keys && unique_keys <= 1; i++, keyinfo++)
+          {
+            if (keyinfo->flags & HA_NOSAME)
+              unique_keys++;
+          }
+          if (unique_keys > 1 )
+            lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
+        }
       }
       flags_access_some_set |= flags;
 
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 68563ab..d24dad7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, MariaDB
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -1807,6 +1807,18 @@ public:
                 current_stmt_binlog_format == BINLOG_FORMAT_ROW);
     return current_stmt_binlog_format == BINLOG_FORMAT_ROW;
   }
+  /**
+    Determine if binlogging is disabled for this session
+    @retval 0 if the current statement binlogging is disabled
+              (could be because of binlog closed/binlog option
+               is set to false).
+    @retval 1 if the current statement will be binlogged
+  */
+  inline bool is_current_stmt_binlog_disabled() const
+  {
+    return (!(variables.option_bits & OPTION_BIN_LOG) ||
+            !mysql_bin_log.is_open());
+  }
 
 private:
   /**
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 52e059b..c60ef6f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -1609,9 +1609,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
       else
         table->file->insert_id_for_cur_row= insert_id_for_cur_row;
       bool is_duplicate_key_error;
-      if (table->file->is_fatal_error(error, HA_CHECK_DUP))
+      if (table->file->is_fatal_error(error, HA_CHECK_ALL))
 	goto err;
-      is_duplicate_key_error= table->file->is_fatal_error(error, 0);
+      is_duplicate_key_error=
+        table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP);
       if (!is_duplicate_key_error)
       {
         /*
@@ -1712,7 +1713,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
               error != HA_ERR_RECORD_IS_THE_SAME)
           {
             if (info->ignore &&
-                !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+                !table->file->is_fatal_error(error, HA_CHECK_ALL))
             {
               if (!(thd->variables.old_behavior &
                     OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -1844,7 +1845,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
   {
     DEBUG_SYNC(thd, "write_row_noreplace");
     if (!info->ignore ||
-        table->file->is_fatal_error(error, HA_CHECK_DUP))
+        table->file->is_fatal_error(error, HA_CHECK_ALL))
       goto err;
     if (!(thd->variables.old_behavior &
           OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -4151,6 +4152,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
     DBUG_RETURN(1);
   table->mark_columns_needed_for_insert();
   table->file->extra(HA_EXTRA_WRITE_CACHE);
+  // Mark table as used
+  table->query_id= thd->query_id;
   DBUG_RETURN(0);
 }
 
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 957764c..7b8b37f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2014, Monty Program Ab.
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -3866,6 +3866,19 @@ void SELECT_LEX::update_used_tables()
       tl->on_expr->update_used_tables();
       tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
     }
+    /*
+      - There is no need to check sj_on_expr, because merged semi-joins inject
+        sj_on_expr into the parent's WHERE clase.
+      - For non-merged semi-joins (aka JTBMs), we need to check their
+        left_expr. There is no need to check the rest of the subselect, we know
+        it is uncorrelated and so cannot refer to any tables in this select.
+    */
+    if (tl->jtbm_subselect)
+    {
+      Item *left_expr= tl->jtbm_subselect->left_expr;
+      left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL);
+    }
+
     embedding= tl->embedding;
     while (embedding)
     {
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6454da2..b13befd 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2014, Monty Program Ab.
+/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -1060,6 +1060,13 @@ private:
   index_clause_map current_index_hint_clause;
   /* a list of USE/FORCE/IGNORE INDEX */
   List<Index_hint> *index_hints;
+
+public:
+  inline void add_where_field(st_select_lex *sel)
+  {
+    DBUG_ASSERT(this != sel);
+    select_n_where_fields+= sel->select_n_where_fields;
+  }
 };
 typedef class st_select_lex SELECT_LEX;
 
@@ -1474,6 +1481,11 @@ public:
     return get_stmt_unsafe_flags() != 0;
   }
 
+  inline bool is_stmt_unsafe(enum_binlog_stmt_unsafe unsafe)
+  {
+    return binlog_stmt_flags & (1 << unsafe);
+  }
+
   /**
     Flag the current (top-level) statement as unsafe.
     The flag will be reset after the statement has finished.
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 75ddf80..fba6dcf 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -255,6 +255,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   {
     DBUG_RETURN(TRUE);
   }
+  thd_proc_info(thd, "executing");
   /*
     Let us emit an error if we are loading data to table which is used
     in subselect in SET clause like we do it for INSERT.
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index 13e00c9..3123474 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -426,7 +426,7 @@ MY_LOCALE my_locale_da_DK
 
 /***** LOCALE BEGIN de_AT: German - Austria *****/
 static const char *my_locale_month_names_de_AT[13] = 
- {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
+ {"Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
 static const char *my_locale_ab_month_names_de_AT[13] = 
  {"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS };
 static const char *my_locale_day_names_de_AT[8] = 
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1b14640..91aecad 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2015 Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015 MariaDB
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
+   Copyright (c) 2009, 2016 MariaDB
 
    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
@@ -4114,17 +4114,6 @@ add_key_field(JOIN *join,
               Field *field, bool eq_func, Item **value, uint num_values,
               table_map usable_tables, SARGABLE_PARAM **sargables)
 {
-  if (field->table->reginfo.join_tab == NULL)
-  {
-    /*
-       Due to a bug in IN-to-EXISTS (grep for real_item() in item_subselect.cc
-       for more info), an index over a field from an outer query might be
-       considered here, which is incorrect. Their query has been fully
-       optimized already so their reginfo.join_tab is NULL and we reject them.
-    */
-    return;
-  }
-
   uint optimize= 0;  
   if (eq_func &&
       ((join->is_allowed_hash_join_access() &&
@@ -14555,6 +14544,14 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
   Field *new_field;
   LINT_INIT(new_field);
 
+  /*
+    To preserve type or DATE/TIME and GEOMETRY fields,
+    they need to be handled separately.
+  */
+  if (item->cmp_type() == TIME_RESULT ||
+      item->field_type() == MYSQL_TYPE_GEOMETRY)
+    new_field= item->tmp_table_field_from_field_type(table, 1);
+  else
   switch (item->result_type()) {
   case REAL_RESULT:
     new_field= new Field_double(item->max_length, maybe_null,
@@ -14577,18 +14574,11 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
   case STRING_RESULT:
     DBUG_ASSERT(item->collation.collation);
   
-    /*
-      DATE/TIME and GEOMETRY fields have STRING_RESULT result type. 
-      To preserve type they needed to be handled separately.
-    */
-    if (item->cmp_type() == TIME_RESULT ||
-        item->field_type() == MYSQL_TYPE_GEOMETRY)
-      new_field= item->tmp_table_field_from_field_type(table, 1);
     /* 
       Make sure that the blob fits into a Field_varstring which has 
       2-byte lenght. 
     */
-    else if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
+    if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
              convert_blob_length <= Field_varstring::MAX_SIZE && 
              convert_blob_length)
       new_field= new Field_varstring(convert_blob_length, maybe_null,
@@ -15444,9 +15434,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
              field->real_type() == MYSQL_TYPE_STRING &&
 	     length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
       recinfo->type= FIELD_SKIP_ENDSPACE;
-    else if (use_packed_rows &&
-             field->real_type() == MYSQL_TYPE_VARCHAR &&
-             length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
+    else if (field->real_type() == MYSQL_TYPE_VARCHAR)
       recinfo->type= FIELD_VARCHAR;
     else
       recinfo->type= FIELD_NORMAL;
@@ -15953,6 +15941,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
       goto err;
 
     bzero(seg, sizeof(*seg) * keyinfo->key_parts);
+    /*
+       Note that a similar check is performed during
+       subquery_types_allow_materialization. See MDEV-7122 for more details as
+       to why. Whenever this changes, it must be updated there as well, for
+       all tmp_table engines.
+    */
     if (keyinfo->key_length > table->file->max_key_length() ||
 	keyinfo->key_parts > table->file->max_key_parts() ||
 	share->uniques)
@@ -16139,6 +16133,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
       goto err;
 
     bzero(seg, sizeof(*seg) * keyinfo->key_parts);
+    /*
+       Note that a similar check is performed during
+       subquery_types_allow_materialization. See MDEV-7122 for more details as
+       to why. Whenever this changes, it must be updated there as well, for
+       all tmp_table engines.
+    */
     if (keyinfo->key_length > table->file->max_key_length() ||
 	keyinfo->key_parts > table->file->max_key_parts() ||
 	share->uniques)
@@ -17593,7 +17593,18 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref)
     }
   }
 
+  /*
+    The following is needed when one makes ref (or eq_ref) access from row
+    comparisons: one must call row->bring_value() to get the new values.
+  */
+  if (tab && tab->bush_children)
+  {
+    TABLE_LIST *emb_sj_nest= tab->bush_children->start->emb_sj_nest;
+    emb_sj_nest->sj_subq_pred->left_expr->bring_value();
+  }
+
   /* TODO: Why don't we do "Late NULLs Filtering" here? */
+
   if (cmp_buffer_with_ref(thd, table, table_ref) ||
       (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
   {
@@ -23117,32 +23128,52 @@ static void print_join(THD *thd,
   /* List is reversed => we should reverse it before using */
   List_iterator_fast<TABLE_LIST> ti(*tables);
   TABLE_LIST **table;
-  uint non_const_tables= 0;
+
+  /*
+    If the QT_NO_DATA_EXPANSION flag is specified, we print the
+    original table list, including constant tables that have been
+    optimized away, as the constant tables may be referenced in the
+    expression printed by Item_field::print() when this flag is given.
+    Otherwise, only non-const tables are printed.
+
+    Example:
+
+    Original SQL:
+    select * from (select 1) t
+
+    Printed without QT_NO_DATA_EXPANSION:
+    select '1' AS `1` from dual
+
+    Printed with QT_NO_DATA_EXPANSION:
+    select `t`.`1` from (select 1 AS `1`) `t`
+  */
+  const bool print_const_tables= (query_type & QT_NO_DATA_EXPANSION);
+  size_t tables_to_print= 0;
 
   for (TABLE_LIST *t= ti++; t ; t= ti++)
   {
-    /* 
-      See comment in print_table_array() about the second part of the
-      condition 
-    */
-    if (!t->optimized_away && !is_eliminated_table(eliminated_tables, t))
-      non_const_tables++;
+    /* See comment in print_table_array() about the second condition */
+    if (print_const_tables || !t->optimized_away)
+      if (!is_eliminated_table(eliminated_tables, t))
+        tables_to_print++;
   }
-  if (!non_const_tables)
+  if (tables_to_print == 0)
   {
     str->append(STRING_WITH_LEN("dual"));
     return; // all tables were optimized away
   }
   ti.rewind();
 
-  if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
-                                                non_const_tables)))
+  if (!(table= static_cast<TABLE_LIST **>(thd->alloc(sizeof(TABLE_LIST*) *
+                                                     tables_to_print))))
     return;  // out of memory
 
-  TABLE_LIST *tmp, **t= table + (non_const_tables - 1);
+  TABLE_LIST *tmp, **t= table + (tables_to_print - 1);
   while ((tmp= ti++))
   {
-    if (tmp->optimized_away || is_eliminated_table(eliminated_tables, tmp))
+    if (tmp->optimized_away && !print_const_tables)
+      continue;
+    if (is_eliminated_table(eliminated_tables, tmp))
       continue;
     *t--= tmp;
   }
@@ -23162,7 +23193,7 @@ static void print_join(THD *thd,
   */
   if ((*table)->sj_inner_tables)
   {
-    TABLE_LIST **end= table + non_const_tables;
+    TABLE_LIST **end= table + tables_to_print;
     for (TABLE_LIST **t2= table; t2!=end; t2++)
     {
       if (!(*t2)->sj_inner_tables)
@@ -23175,7 +23206,7 @@ static void print_join(THD *thd,
     }
   }
   print_table_array(thd, eliminated_tables, str, table, 
-                    table +  non_const_tables, query_type);
+                    table +  tables_to_print, query_type);
 }
 
 /**
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 4f807ff..4650bc2 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -40,8 +40,21 @@
 #endif
 #if defined(USE_ARIA_FOR_TMP_TABLES)
 #define TMP_ENGINE_HTON maria_hton
+inline uint tmp_table_max_key_length() {
+  return maria_max_key_length();
+}
+
+inline uint tmp_table_max_key_parts() {
+  return maria_max_key_segments();
+}
 #else
 #define TMP_ENGINE_HTON myisam_hton
+inline uint tmp_table_max_key_length() {
+  return MI_MAX_KEY_LENGTH;
+}
+inline uint tmp_table_max_key_parts() {
+  return MI_MAX_KEY_SEG;
+}
 #endif
 /* Values in optimize */
 #define KEY_OPTIMIZE_EXISTS		1
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 45bddc2..98cade4 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,5 +1,5 @@
 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2009, 2015, MariaDB
+   Copyright (c) 2009, 2016, MariaDB
 
    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
@@ -1255,20 +1255,17 @@ static const char *require_quotes(const char *name, uint name_length)
 }
 
 
-/*
-  Quote the given identifier if needed and append it to the target string.
-  If the given identifier is empty, it will be quoted.
-
-  SYNOPSIS
-  append_identifier()
-  thd                   thread handler
-  packet                target string
-  name                  the identifier to be appended
-  name_length           length of the appending identifier
+/**
+  Convert and quote the given identifier if needed and append it to the
+  target string. If the given identifier is empty, it will be quoted.
+  @thd                         thread handler
+  @packet                      target string
+  @name                        the identifier to be appended
+  @length                      length of the appending identifier
 
-  RETURN VALUES
-    true                Error
-    false               Ok
+  @return
+    0             success
+    1             error
 */
 
 bool
@@ -1611,7 +1608,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
 	For string types dump collation name only if
 	collation is not primary for the given charset
       */
-      if (!(field->charset()->state & MY_CS_PRIMARY))
+      if (!(field->charset()->state & MY_CS_PRIMARY) && !field->vcol_info)
       {
 	packet->append(STRING_WITH_LEN(" COLLATE "));
 	packet->append(field->charset()->name);
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 6e87f60..0a0d4a4 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2005, 2010, Oracle and/or its affiliates.
+   Copyright (c) 2012, 2016, MariaDB
 
    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
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index a771f64..024ca9b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2000, 2015, Oracle and/or its affiliates.
-   Copyright (c) 2010, 2015, MariaDB
+   Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2010, 2016, MariaDB
 
    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
@@ -2092,7 +2092,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
       const char *comment_start;
       uint32 comment_len;
 
-      built_query.set_charset(system_charset_info);
+      built_query.set_charset(thd->charset());
       if (if_exists)
         built_query.append("DROP TABLE IF EXISTS ");
       else
@@ -3135,8 +3135,31 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 	else
 	{
 	  /* Field redefined */
+
+          /*
+            If we are replacing a BIT field, revert the increment
+            of total_uneven_bit_length that was done above.
+          */
+          if (sql_field->sql_type == MYSQL_TYPE_BIT &&
+              file->ha_table_flags() & HA_CAN_BIT_FIELD)
+            total_uneven_bit_length-= sql_field->length & 7;
+
 	  sql_field->def=		dup_field->def;
 	  sql_field->sql_type=		dup_field->sql_type;
+
+          /*
+            If we are replacing a field with a BIT field, we need
+            to initialize pack_flag. Note that we do not need to
+            increment total_uneven_bit_length here as this dup_field
+            has already been processed.
+          */
+          if (sql_field->sql_type == MYSQL_TYPE_BIT)
+          {
+            sql_field->pack_flag= FIELDFLAG_NUMBER;
+            if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
+              sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
+          }
+
 	  sql_field->charset=		(dup_field->charset ?
 					 dup_field->charset :
 					 create_info->default_table_charset);
@@ -4857,6 +4880,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
   /*
     We have to write the query before we unlock the tables.
   */
+  if (thd->is_current_stmt_binlog_disabled())
+    goto err;
+
   if (thd->is_current_stmt_binlog_format_row())
   {
     /*
@@ -4899,6 +4925,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
           if (open_table(thd, table, thd->mem_root, &ot_ctx))
             goto err;
 
+          /*
+            After opening a MERGE table add the children to the query list of
+            tables, so that children tables info can be used on "CREATE TABLE"
+            statement generation by the binary log.
+            Note that placeholders don't have the handler open.
+          */
+          if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST))
+            goto err;
+
+          /*
+            As the reference table is temporary and may not exist on slave, we must
+            force the ENGINE to be present into CREATE TABLE.
+          */
+          create_info->used_fields|= HA_CREATE_USED_ENGINE;
+
           int result __attribute__((unused))=
             store_create_info(thd, table, &query,
                               create_info, TRUE /* show_database */);
diff --git a/sql/sql_time.h b/sql/sql_time.h
index 443d22c..ad75212 100644
--- a/sql/sql_time.h
+++ b/sql/sql_time.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2010, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    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
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c8a7990..f134e0b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
-   Copyright (c) 2011, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+   Copyright (c) 2011, 2016, MariaDB
 
    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
@@ -774,7 +774,7 @@ int mysql_update(THD *thd,
             error= 0;
 	}
  	else if (!ignore ||
-                 table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+                 table->file->is_fatal_error(error, HA_CHECK_ALL))
 	{
           /*
             If (ignore && error is ignorable) we don't have to
@@ -782,7 +782,7 @@ int mysql_update(THD *thd,
           */
           myf flags= 0;
 
-          if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+          if (table->file->is_fatal_error(error, HA_CHECK_ALL))
             flags|= ME_FATALERROR; /* Other handler errors are fatal */
 
           prepare_record_for_error_message(error, table);
@@ -1969,7 +1969,7 @@ int multi_update::send_data(List<Item> &not_used_values)
         {
           updated--;
           if (!ignore ||
-              table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+              table->file->is_fatal_error(error, HA_CHECK_ALL))
           {
             /*
               If (ignore && error == is ignorable) we don't have to
@@ -1977,7 +1977,7 @@ int multi_update::send_data(List<Item> &not_used_values)
             */
             myf flags= 0;
 
-            if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+            if (table->file->is_fatal_error(error, HA_CHECK_ALL))
               flags|= ME_FATALERROR; /* Other handler errors are fatal */
 
             prepare_record_for_error_message(error, table);
@@ -2234,6 +2234,12 @@ int multi_update::do_updates()
       if (!can_compare_record || compare_record(table))
       {
         int error;
+        if (table->vfield &&
+            update_virtual_fields(thd, table,
+                                  (table->triggers ?
+                                   VCOL_UPDATE_ALL :
+                                   VCOL_UPDATE_FOR_WRITE)))
+          goto err2;
         if ((error= cur_table->view_check_option(thd, ignore)) !=
             VIEW_CHECK_OK)
         {
@@ -2250,7 +2256,7 @@ int multi_update::do_updates()
             local_error != HA_ERR_RECORD_IS_THE_SAME)
 	{
 	  if (!ignore ||
-              table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY))
+              table->file->is_fatal_error(local_error, HA_CHECK_ALL))
           {
             err_table= table;
 	    goto err;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index e6c5ffd..5bd82fd 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1523,8 +1523,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
 
       /* Fields in this view can be used in upper select in case of merge.  */
       if (table->select_lex)
-        table->select_lex->select_n_where_fields+=
-          lex->select_lex.select_n_where_fields;
+        table->select_lex->add_where_field(&lex->select_lex);
     }
     /*
       This method has a dependency on the proper lock type being set,
diff --git a/sql/sql_yacc.cc b/sql/sql_yacc.cc
index c1b6c8e..7958074 100644
--- a/sql/sql_yacc.cc
+++ b/sql/sql_yacc.cc
@@ -30562,15 +30562,6 @@ yyreduce:
               sel->add_joined_table((yyval.table_list));
               lex->pop_context();
               lex->nest_level--;
-              /*
-                Fields in derived table can be used in upper select in
-                case of merge. We do not add HAVING fields because we do
-                not merge such derived. We do not add union because
-                also do not merge them
-              */
-              if (!sel->next_select())
-                (yyvsp[(2) - (5)].select_lex)->select_n_where_fields+=
-                  sel->select_n_where_fields;
             }
             /*else if (($3->select_lex &&
                       $3->select_lex->master_unit()->is_union() &&
@@ -30591,6 +30582,15 @@ yyreduce:
                  nest_level is the same as in the outer query */
               (yyval.table_list)= (yyvsp[(3) - (5)].table_list);
             }
+            /*
+              Fields in derived table can be used in upper select in
+              case of merge. We do not add HAVING fields because we do
+              not merge such derived. We do not add union because
+              also do not merge them
+            */
+            if ((yyval.table_list) && (yyval.table_list)->derived &&
+                !(yyval.table_list)->derived->first_select()->next_select())
+              (yyval.table_list)->select_lex->add_where_field((yyval.table_list)->derived->first_select());
           }
     break;
 
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 11d7efd..2cb0205 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9872,15 +9872,6 @@ table_factor:
               sel->add_joined_table($$);
               lex->pop_context();
               lex->nest_level--;
-              /*
-                Fields in derived table can be used in upper select in
-                case of merge. We do not add HAVING fields because we do
-                not merge such derived. We do not add union because
-                also do not merge them
-              */
-              if (!sel->next_select())
-                $2->select_n_where_fields+=
-                  sel->select_n_where_fields;
             }
             /*else if (($3->select_lex &&
                       $3->select_lex->master_unit()->is_union() &&
@@ -9901,6 +9892,15 @@ table_factor:
                  nest_level is the same as in the outer query */
               $$= $3;
             }
+            /*
+              Fields in derived table can be used in upper select in
+              case of merge. We do not add HAVING fields because we do
+              not merge such derived. We do not add union because
+              also do not merge them
+            */
+            if ($$ && $$->derived &&
+                !$$->derived->first_select()->next_select())
+              $$->select_lex->add_where_field($$->derived->first_select());
           }
         ;
 
diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
index da58d83..d15f2e4 100644
--- a/storage/innobase/buf/buf0flu.c
+++ b/storage/innobase/buf/buf0flu.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, 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
@@ -2103,12 +2103,7 @@ buf_flush_stat_update(void)
 	ib_uint64_t		lsn;
 	ulint			n_flushed;
 
-	lsn = log_get_lsn_nowait();
-
-	/* log_get_lsn_nowait tries to get log_sys->mutex with
-	mutex_enter_nowait, if this does not succeed function
-	returns 0, do not use that value to update stats. */
-	if (lsn == 0) {
+	if (!log_peek_lsn(&lsn)) {
 		return;
 	}
 
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index dcce3c1..8102f57 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2016, 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
@@ -1140,7 +1140,7 @@ dict_create_index_step(
 			>= DICT_TF_FORMAT_ZIP);
 
 		node->index = dict_index_get_if_in_cache_low(index_id);
-		ut_a(err == DB_SUCCESS ? node->index != NULL : node->index == NULL);
+		ut_a((node->index == NULL) == (err != DB_SUCCESS));
 
 		if (err != DB_SUCCESS) {
 
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 17e9eb1..33b110c 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2010,7 +2010,7 @@ dict_index_find_cols(
 		dict_field_t*	field = dict_index_get_nth_field(index, i);
 
 		for (j = 0; j < table->n_cols; j++) {
-			if (!strcmp(dict_table_get_col_name(table, j),
+			if (!innobase_strcasecmp(dict_table_get_col_name(table, j),
 				    field->name)) {
 				field->col = dict_table_get_nth_col(table, j);
 
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f2a2eec..b3e6b3c 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3443,7 +3443,7 @@ Normalizes a table name string. A normalized name consists of the
 database name catenated to '/' and table name. An example:
 test/mytable. On Windows normalization puts both the database name and the
 table name always to lower case if "set_lower_case" is set to TRUE. */
-static
+extern "C" UNIV_INTERN
 void
 normalize_table_name_low(
 /*=====================*/
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index a69d3d1..83fa1d5 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -336,4 +336,18 @@ ib_push_warning(
 	const char	*format,/*!< in: warning message */
 	...);
 
+/*****************************************************************//**
+Normalizes a table name string. A normalized name consists of the
+database name catenated to '/' and table name. An example:
+test/mytable. On Windows normalization puts both the database name and the
+table name always to lower case if "set_lower_case" is set to TRUE. */
+void
+normalize_table_name_low(
+/*=====================*/
+	char*		norm_name,	/*!< out: normalized name as a
+					null-terminated string */
+	const char*	name,		/*!< in: table name string */
+	ibool		set_lower_case); /*!< in: TRUE if we want to set
+					name to lower case */
+
 #endif
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index 22b0fa4..213974b 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -335,28 +335,7 @@ amount of increment. */
 # define os_atomic_increment_ulint(ptr, amount) \
 	os_atomic_increment(ptr, amount)
 
-# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
-
-/** Do an atomic test-and-set.
- at param[in,out]	ptr		Memory location to set to non-zero
- at return the previous value */
-static inline
-lock_word_t
-os_atomic_test_and_set(volatile lock_word_t* ptr)
-{
-       return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
-}
-
-/** Do an atomic clear.
- at param[in,out]	ptr		Memory location to set to zero */
-static inline
-void
-os_atomic_clear(volatile lock_word_t* ptr)
-{
-	__atomic_clear(ptr, __ATOMIC_RELEASE);
-}
-
-# elif defined(IB_STRONG_MEMORY_MODEL)
+# if defined(IB_STRONG_MEMORY_MODEL)
 
 /** Do an atomic test and set.
 @param[in,out]	ptr		Memory location to set to non-zero
@@ -385,6 +364,27 @@ os_atomic_clear(volatile lock_word_t* ptr)
 	return(__sync_lock_test_and_set(ptr, 0));
 }
 
+# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
+
+/** Do an atomic test-and-set.
+ at param[in,out]	ptr		Memory location to set to non-zero
+ at return the previous value */
+static inline
+lock_word_t
+os_atomic_test_and_set(volatile lock_word_t* ptr)
+{
+       return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
+}
+
+/** Do an atomic clear.
+ at param[in,out]	ptr		Memory location to set to zero */
+static inline
+void
+os_atomic_clear(volatile lock_word_t* ptr)
+{
+	__atomic_clear(ptr, __ATOMIC_RELEASE);
+}
+
 # else
 
 #  error "Unsupported platform"
diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index da3ea78..eee3b9f 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2016, 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
@@ -1767,7 +1767,7 @@ loop:
 		goto loop;
 	}
 
-	ut_ad(allow_ibuf == FALSE ? mutex_own(&log_sys->mutex) : !mutex_own(&log_sys->mutex));
+	ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex));
 
 	if (!allow_ibuf) {
 		recv_no_ibuf_operations = TRUE;
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 181ca96..1a11e39 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -3838,6 +3838,7 @@ row_rename_table_for_mysql(
 	ibool		old_is_tmp, new_is_tmp;
 	pars_info_t*	info			= NULL;
 	int		retry;
+	char*			is_part = NULL;
 
 	ut_a(old_name != NULL);
 	ut_a(new_name != NULL);
@@ -3872,6 +3873,54 @@ row_rename_table_for_mysql(
 
 	table = dict_table_get_low(old_name, DICT_ERR_IGNORE_NONE);
 
+	/* We look for pattern #P# to see if the table is partitioned
+	MySQL table. */
+#ifdef __WIN__
+	is_part = strstr(old_name, "#p#");
+#else
+	is_part = strstr(old_name, "#P#");
+#endif /* __WIN__ */
+
+	/* MySQL partition engine hard codes the file name
+	separator as "#P#". The text case is fixed even if
+	lower_case_table_names is set to 1 or 2. This is true
+	for sub-partition names as well. InnoDB always
+	normalises file names to lower case on Windows, this
+	can potentially cause problems when copying/moving
+	tables between platforms.
+
+	1) If boot against an installation from Windows
+	platform, then its partition table name could
+	be all be in lower case in system tables. So we
+	will need to check lower case name when load table.
+
+	2) If  we boot an installation from other case
+	sensitive platform in Windows, we might need to
+	check the existence of table name without lowering
+	case them in the system table. */
+	if (!table &&
+	    is_part &&
+	    innobase_get_lower_case_table_names() == 1) {
+		char par_case_name[MAX_FULL_NAME_LEN + 1];
+#ifndef __WIN__
+		/* Check for the table using lower
+		case name, including the partition
+		separator "P" */
+		memcpy(par_case_name, old_name,
+			strlen(old_name));
+		par_case_name[strlen(old_name)] = 0;
+		innobase_casedn_str(par_case_name);
+#else
+		/* On Windows platfrom, check
+		whether there exists table name in
+		system table whose name is
+		not being normalized to lower case */
+		normalize_table_name_low(
+			par_case_name, old_name, FALSE);
+#endif
+		table = dict_table_get_low(par_case_name, DICT_ERR_IGNORE_NONE);
+	}
+
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;
 		ut_print_timestamp(stderr);
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index 49e5133..1cd21ac 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, 2009 Google Inc.
 Copyright (c) 2009, Percona Inc.
 Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -2433,6 +2433,8 @@ exit_func:
 /*********************************************************************//**
 A thread which prints warnings about semaphore waits which have lasted
 too long. These can be used to track bugs which cause hangs.
+Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
+we should avoid waiting any mutexes in this function!
 @return	a dummy parameter */
 UNIV_INTERN
 os_thread_ret_t
@@ -2470,24 +2472,21 @@ loop:
 
 	/* Try to track a strange bug reported by Harald Fuchs and others,
 	where the lsn seems to decrease at times */
+	if (log_peek_lsn(&new_lsn)) {
+		if (new_lsn < old_lsn) {
+			ut_print_timestamp(stderr);
+			fprintf(stderr,
+				"  InnoDB: Error: old log sequence number %llu"
+				" was greater\n"
+				"InnoDB: than the new log sequence number %llu!\n"
+				"InnoDB: Please submit a bug report"
+				" to http://bugs.mysql.com\n",
+				old_lsn, new_lsn);
+			ut_ad(0);
+		}
 
-        /* We have to use nowait to ensure we don't block */
-	new_lsn= log_get_lsn_nowait();
-
-	if (new_lsn && new_lsn < old_lsn) {
-		ut_print_timestamp(stderr);
-		fprintf(stderr,
-			"  InnoDB: Error: old log sequence number %llu"
-			" was greater\n"
-			"InnoDB: than the new log sequence number %llu!\n"
-			"InnoDB: Please submit a bug report"
-			" to http://bugs.mysql.com\n",
-			old_lsn, new_lsn);
-		ut_ad(0);
-	}
-
-        if (new_lsn)
 		old_lsn = new_lsn;
+	}
 
 	if (difftime(time(NULL), srv_last_monitor_time) > 60) {
 		/* We referesh InnoDB Monitor values so that averages are
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 8b61e1d..b67f1ea 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2001, 2016, 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
@@ -197,7 +197,8 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
       ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root,
                                    sizeof(FTB_WORD) +
                                    (info->trunc ? HA_MAX_KEY_BUFF :
-                                    word_len * ftb_param->ftb->charset->mbmaxlen +
+                                    (word_len + 1) *
+                                    ftb_param->ftb->charset->mbmaxlen +
                                     HA_FT_WLEN +
                                     ftb_param->ftb->info->s->rec_reflength));
       ftbw->len= word_len + 1;
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 7285060..35e761d 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1,4 +1,5 @@
 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates
+   Copyright (c) 2009, 2016, MariaDB
 
    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
diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc
index 822f695..9edf6ea 100644
--- a/storage/sphinx/ha_sphinx.cc
+++ b/storage/sphinx/ha_sphinx.cc
@@ -598,8 +598,10 @@ protected:
 	void			SendFloat ( float v )			{ SendDword ( sphF2DW(v) ); }
 };
 
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 template int CSphSEQuery::ParseArray<uint32> ( uint32 **, const char * );
 template int CSphSEQuery::ParseArray<longlong> ( longlong **, const char * );
+#endif
 
 //////////////////////////////////////////////////////////////////////////////
 
diff --git a/storage/tokudb/ft-index/buildheader/make_tdb.cc b/storage/tokudb/ft-index/buildheader/make_tdb.cc
index 5370664..610ce67 100644
--- a/storage/tokudb/ft-index/buildheader/make_tdb.cc
+++ b/storage/tokudb/ft-index/buildheader/make_tdb.cc
@@ -481,7 +481,9 @@ static void print_db_key_range_struct (void) {
 
 static void print_db_lsn_struct (void) {
     field_counter=0;
-    sort_and_dump_fields("db_lsn", false, NULL);
+    /* A dummy field to make sizeof(DB_LSN) equal in C and C++ */
+    const char *extra[] = { "char dummy", NULL };
+    sort_and_dump_fields("db_lsn", false, extra);
 }
 
 static void print_dbt_struct (void) {
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
index 99629e4..fe99c91 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
@@ -61,12 +61,13 @@ endmacro(set_cflags_if_supported_named)
 ## adds a compiler flag if the compiler supports it
 macro(set_cflags_if_supported)
   foreach(flag ${ARGN})
-    check_c_compiler_flag(${flag} HAVE_C_${flag})
-    if (HAVE_C_${flag})
+    STRING(REGEX REPLACE "[-,= ]" "_" res ${flag})
+    check_c_compiler_flag(${flag} HAVE_C_${res})
+    if (HAVE_C_${res})
       set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}")
     endif ()
-    check_cxx_compiler_flag(${flag} HAVE_CXX_${flag})
-    if (HAVE_CXX_${flag})
+    check_cxx_compiler_flag(${flag} HAVE_CXX_${res})
+    if (HAVE_CXX_${res})
       set(CMAKE_CXX_FLAGS "${flag} ${CMAKE_CXX_FLAGS}")
     endif ()
   endforeach(flag)
@@ -75,8 +76,9 @@ endmacro(set_cflags_if_supported)
 ## adds a linker flag if the compiler supports it
 macro(set_ldflags_if_supported)
   foreach(flag ${ARGN})
-    check_cxx_compiler_flag(${flag} HAVE_${flag})
-    if (HAVE_${flag})
+    STRING(REGEX REPLACE "[-,= ]" "_" res ${flag})
+    check_cxx_compiler_flag(${flag} HAVE_${res})
+    if (HAVE_${res})
       set(CMAKE_EXE_LINKER_FLAGS "${flag} ${CMAKE_EXE_LINKER_FLAGS}")
       set(CMAKE_SHARED_LINKER_FLAGS "${flag} ${CMAKE_SHARED_LINKER_FLAGS}")
     endif ()
@@ -103,8 +105,8 @@ set_cflags_if_supported(
 
 if (CMAKE_CXX_FLAGS MATCHES -fno-implicit-templates)
   # must append this because mysql sets -fno-implicit-templates and we need to override it
-  check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_-fimplicit-templates)
-  if (HAVE_CXX_-fimplicit-templates)
+  check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_IMPLICIT_TEMPLATES)
+  if (HAVE_CXX_IMPLICIT_TEMPLATES)
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fimplicit-templates")
   endif ()
 endif()
diff --git a/storage/tokudb/ft-index/ft/txn/rollback.cc b/storage/tokudb/ft-index/ft/txn/rollback.cc
index 6204803..ea2f2a0 100644
--- a/storage/tokudb/ft-index/ft/txn/rollback.cc
+++ b/storage/tokudb/ft-index/ft/txn/rollback.cc
@@ -147,9 +147,7 @@ static inline PAIR_ATTR make_rollback_pair_attr(long size) {
 PAIR_ATTR
 rollback_memory_size(ROLLBACK_LOG_NODE log) {
     size_t size = sizeof(*log);
-    if (&log->rollentry_arena) {
-        size += log->rollentry_arena.total_footprint();
-    }
+    size += log->rollentry_arena.total_footprint();
     return make_rollback_pair_attr(size);
 }
 
diff --git a/storage/tokudb/ft-index/tools/tokudb_dump.cc b/storage/tokudb/ft-index/tools/tokudb_dump.cc
index 2da50bb..b162c5c 100644
--- a/storage/tokudb/ft-index/tools/tokudb_dump.cc
+++ b/storage/tokudb/ft-index/tools/tokudb_dump.cc
@@ -248,76 +248,6 @@ outputplaintextstring(char* str)
 }
 
 static inline int
-hextoint(int ch)
-{
-   if (ch >= '0' && ch <= '9') {
-      return ch - '0';
-   }
-   if (ch >= 'a' && ch <= 'z') {
-      return ch - 'a' + 10;
-   }
-   if (ch >= 'A' && ch <= 'Z') {
-      return ch - 'A' + 10;
-   }
-   return EOF;
-}
-
-static inline int
-printabletocstring(char* inputstr, char** poutputstr)
-{
-   char highch;
-   char lowch;
-   char nextch;
-   char* cstring;
-
-   assert(inputstr);
-   assert(poutputstr);
-   assert(*poutputstr == NULL);
-
-   cstring = (char*)toku_malloc((strlen(inputstr) + 1) * sizeof(char));
-   if (cstring == NULL) {
-      PRINT_ERROR(errno, "printabletocstring");
-      goto error;
-   }
-
-   for (*poutputstr = cstring; *inputstr != '\0'; inputstr++) {
-      if (*inputstr == '\\') {
-         if ((highch = *++inputstr) == '\\') {
-            *cstring++ = '\\';
-            continue;
-         }
-         if (highch == '\0' || (lowch = *++inputstr) == '\0') {
-            PRINT_ERROR(0, "unexpected end of input data or key/data pair");
-            goto error;
-         }
-         if (!isxdigit(highch)) {
-            PRINT_ERROR(0, "Unexpected '%c' (non-hex) input.\n", highch);
-            goto error;
-         }
-         if (!isxdigit(lowch)) {
-            PRINT_ERROR(0, "Unexpected '%c' (non-hex) input.\n", lowch);
-            goto error;
-         }
-         nextch = (char)((hextoint(highch) << 4) | hextoint(lowch));
-         if (nextch == '\0') {
-            /* Database names are c strings, and cannot have extra NULL terminators. */
-            PRINT_ERROR(0, "Unexpected '\\00' in input.\n");
-            goto error;
-         }
-         *cstring++ = nextch;
-      }
-      else *cstring++ = *inputstr;
-   }
-   /* Terminate the string. */
-   *cstring = '\0';
-   return EXIT_SUCCESS;
-
-error:
-   PRINT_ERROR(0, "Quitting out due to errors.\n");
-   return EXIT_FAILURE;
-}
-
-static inline int
 verify_library_version(void)
 {
    int major;
diff --git a/storage/tokudb/ft-index/util/dmt.h b/storage/tokudb/ft-index/util/dmt.h
index d4b032f..43e44df 100644
--- a/storage/tokudb/ft-index/util/dmt.h
+++ b/storage/tokudb/ft-index/util/dmt.h
@@ -679,16 +679,16 @@ private:
     __attribute__((nonnull))
     void rebalance(subtree *const subtree);
 
-    __attribute__((nonnull))
+    __attribute__((nonnull(3)))
     static void copyout(uint32_t *const outlen, dmtdata_t *const out, const dmt_node *const n);
 
-    __attribute__((nonnull))
+    __attribute__((nonnull(3)))
     static void copyout(uint32_t *const outlen, dmtdata_t **const out, dmt_node *const n);
 
-    __attribute__((nonnull))
+    __attribute__((nonnull(4)))
     static void copyout(uint32_t *const outlen, dmtdata_t *const out, const uint32_t len, const dmtdata_t *const stored_value_ptr);
 
-    __attribute__((nonnull))
+    __attribute__((nonnull(4)))
     static void copyout(uint32_t *const outlen, dmtdata_t **const out, const uint32_t len, dmtdata_t *const stored_value_ptr);
 
     template<typename dmtcmp_t,
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index b4e2c1a..2eb8004 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -379,7 +379,7 @@ static int free_share(TOKUDB_SHARE * share) {
     }
 
 const char *ha_tokudb::table_type() const {
-    extern const char * const tokudb_hton_name;
+    extern const char *tokudb_hton_name;
     return tokudb_hton_name;
 } 
 
diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c
index 43f6a45..45fe2aa 100644
--- a/storage/xtradb/buf/buf0flu.c
+++ b/storage/xtradb/buf/buf0flu.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, 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
@@ -2214,12 +2214,7 @@ buf_flush_stat_update(void)
 	ib_uint64_t		lsn;
 	ulint			n_flushed;
 
-	lsn = log_get_lsn_nowait();
-
-	/* log_get_lsn_nowait tries to get log_sys->mutex with
-	mutex_enter_nowait, if this does not succeed function
-	returns 0, do not use that value to update stats. */
-	if (lsn == 0) {
+	if (!log_peek_lsn(&lsn)) {
 		return;
 	}
 
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 7351de5..87d7a3b 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -2142,7 +2142,7 @@ dict_index_find_cols(
 		dict_field_t*	field = dict_index_get_nth_field(index, i);
 
 		for (j = 0; j < table->n_cols; j++) {
-			if (!strcmp(dict_table_get_col_name(table, j),
+			if (!innobase_strcasecmp(dict_table_get_col_name(table, j),
 				    field->name)) {
 				field->col = dict_table_get_nth_col(table, j);
 
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index f3b9167..fcf387b 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -4181,7 +4181,7 @@ Normalizes a table name string. A normalized name consists of the
 database name catenated to '/' and table name. An example:
 test/mytable. On Windows normalization puts both the database name and the
 table name always to lower case if "set_lower_case" is set to TRUE. */
-static
+extern "C" UNIV_INTERN
 void
 normalize_table_name_low(
 /*=====================*/
@@ -4440,7 +4440,7 @@ building based on the assumption that there is no concurrent
 index creation/drop and DMLs that requires index lookup. All table
 handle will be closed before the index creation/drop.
 @return TRUE if index translation table built successfully */
-static
+UNIV_INTERN
 ibool
 innobase_build_index_translation(
 /*=============================*/
@@ -7744,7 +7744,8 @@ create_table_def(
 
 	/* MySQL does the name length check. But we do additional check
 	on the name length here */
-	if (strlen(table_name) > MAX_FULL_NAME_LEN) {
+	const size_t	table_name_len = strlen(table_name);
+	if (table_name_len > MAX_FULL_NAME_LEN) {
 		push_warning_printf(
 			(THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 			ER_TABLE_NAME,
@@ -7753,6 +7754,15 @@ create_table_def(
 		DBUG_RETURN(ER_TABLE_NAME);
 	}
 
+	if (table_name[table_name_len - 1] == '/') {
+		push_warning_printf(
+			(THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+			ER_TABLE_NAME,
+			"InnoDB: Table name is empty");
+
+		DBUG_RETURN(ER_WRONG_TABLE_NAME);
+	}
+
 	n_cols = form->s->fields;
 
 	/* We pass 0 as the space id, and determine at a lower level the space
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 39ca89c..914055a 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -412,3 +412,26 @@ innobase_index_name_is_reserved(
 	ulint		num_of_keys);	/*!< in: Number of indexes to
 					be created. */
 
+/*******************************************************************//**
+This function builds a translation table in INNOBASE_SHARE
+structure for fast index location with mysql array number from its
+table->key_info structure. This also provides the necessary translation
+between the key order in mysql key_info and Innodb ib_table->indexes if
+they are not fully matched with each other.
+Note we do not have any mutex protecting the translation table
+building based on the assumption that there is no concurrent
+index creation/drop and DMLs that requires index lookup. All table
+handle will be closed before the index creation/drop.
+ at return TRUE if index translation table built successfully */
+UNIV_INTERN
+ibool
+innobase_build_index_translation(
+/*=============================*/
+	const TABLE*		table,	  /*!< in: table in MySQL data
+					  dictionary */
+	dict_table_t*		ib_table, /*!< in: table in Innodb data
+					  dictionary */
+	INNOBASE_SHARE*		share);	  /*!< in/out: share structure
+					  where index translation table
+					  will be constructed in. */
+
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 2b2b2b5..65b2c2f 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -1083,6 +1083,22 @@ ha_innobase::final_add_index(
 
 	trx_free_for_mysql(trx);
 
+	/* Rebuild index translation table now for temporary tables if we are
+	restoring secondary keys, as ha_innobase::open will not be called for
+	the next access. */
+	if (add->indexed_table == prebuilt->table
+	    && dict_table_is_temporary(prebuilt->table))
+	{
+		if (!innobase_build_index_translation(add_arg->table,
+						      prebuilt->table, share))
+		{
+			/* We don't know whether index translation build failed
+			because of DD mismatch or OOM, return non-specific
+			error code. */
+			err = -1;
+		}
+	}
+
 	/* There might be work for utility threads.*/
 	srv_active_wake_master_thread();
 
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index c127e63..c430d7c 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -373,4 +373,18 @@ ib_push_warning(
 	const char	*format,/*!< in: warning message */
 	...);
 
+/*****************************************************************//**
+Normalizes a table name string. A normalized name consists of the
+database name catenated to '/' and table name. An example:
+test/mytable. On Windows normalization puts both the database name and the
+table name always to lower case if "set_lower_case" is set to TRUE. */
+void
+normalize_table_name_low(
+/*=====================*/
+	char*		norm_name,	/*!< out: normalized name as a
+					null-terminated string */
+	const char*	name,		/*!< in: table name string */
+	ibool		set_lower_case); /*!< in: TRUE if we want to set
+					name to lower case */
+
 #endif
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 6e130b1..aced1fd 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -64,10 +64,10 @@ component, i.e. we show M.N.P as M.N */
 	(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
 
 #ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 37.6
+#define PERCONA_INNODB_VERSION 37.8
 #endif
 
-#define INNODB_VERSION_STR	"5.5.46-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
+#define INNODB_VERSION_STR	"5.5.48-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
 
 #define REFMAN "http://dev.mysql.com/doc/refman/"	\
 	IB_TO_STR(MYSQL_MAJOR_VERSION) "."		\
diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c
index e465f9a..b0b481b 100644
--- a/storage/xtradb/log/log0recv.c
+++ b/storage/xtradb/log/log0recv.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2015, 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
@@ -766,6 +766,10 @@ not_consistent:
 
 		fprintf(stderr,
 			"InnoDB: No valid checkpoint found.\n"
+			"InnoDB: If you are attempting downgrade"
+			" from MySQL 5.7.9 or later,\n"
+			"InnoDB: please refer to " REFMAN
+			"upgrading-downgrading.html\n"
 			"InnoDB: If this error appears when you are"
 			" creating an InnoDB database,\n"
 			"InnoDB: the problem may be that during"
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index 9496df8..e6ccf44 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -3978,6 +3978,7 @@ row_rename_table_for_mysql(
 	ibool		old_is_tmp, new_is_tmp;
 	pars_info_t*	info			= NULL;
 	int		retry;
+	char*			is_part = NULL;
 
 	ut_a(old_name != NULL);
 	ut_a(new_name != NULL);
@@ -4012,6 +4013,54 @@ row_rename_table_for_mysql(
 
 	table = dict_table_get_low(old_name, DICT_ERR_IGNORE_NONE);
 
+	/* We look for pattern #P# to see if the table is partitioned
+	MySQL table. */
+#ifdef __WIN__
+	is_part = strstr(old_name, "#p#");
+#else
+	is_part = strstr(old_name, "#P#");
+#endif /* __WIN__ */
+
+	/* MySQL partition engine hard codes the file name
+	separator as "#P#". The text case is fixed even if
+	lower_case_table_names is set to 1 or 2. This is true
+	for sub-partition names as well. InnoDB always
+	normalises file names to lower case on Windows, this
+	can potentially cause problems when copying/moving
+	tables between platforms.
+
+	1) If boot against an installation from Windows
+	platform, then its partition table name could
+	be all be in lower case in system tables. So we
+	will need to check lower case name when load table.
+
+	2) If  we boot an installation from other case
+	sensitive platform in Windows, we might need to
+	check the existence of table name without lowering
+	case them in the system table. */
+	if (!table &&
+	    is_part &&
+	    innobase_get_lower_case_table_names() == 1) {
+		char par_case_name[MAX_FULL_NAME_LEN + 1];
+#ifndef __WIN__
+		/* Check for the table using lower
+		case name, including the partition
+		separator "P" */
+		memcpy(par_case_name, old_name,
+			strlen(old_name));
+		par_case_name[strlen(old_name)] = 0;
+		innobase_casedn_str(par_case_name);
+#else
+		/* On Windows platfrom, check
+		whether there exists table name in
+		system table whose name is
+		not being normalized to lower case */
+		normalize_table_name_low(
+			par_case_name, old_name, FALSE);
+#endif
+		table = dict_table_get_low(par_case_name, DICT_ERR_IGNORE_NONE);
+	}
+
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;
 		ut_print_timestamp(stderr);
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 5efb5d0..90a1291 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, 2009 Google Inc.
 Copyright (c) 2009, Percona Inc.
 Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -2902,6 +2902,8 @@ exit_func:
 /*********************************************************************//**
 A thread which prints warnings about semaphore waits which have lasted
 too long. These can be used to track bugs which cause hangs.
+Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
+we should avoid waiting any mutexes in this function!
 @return	a dummy parameter */
 UNIV_INTERN
 os_thread_ret_t
@@ -2939,24 +2941,21 @@ loop:
 
 	/* Try to track a strange bug reported by Harald Fuchs and others,
 	where the lsn seems to decrease at times */
+	if (log_peek_lsn(&new_lsn)) {
+		if (new_lsn < old_lsn) {
+			ut_print_timestamp(stderr);
+			fprintf(stderr,
+				"  InnoDB: Error: old log sequence number %llu"
+				" was greater\n"
+				"InnoDB: than the new log sequence number %llu!\n"
+				"InnoDB: Please submit a bug report"
+				" to http://bugs.mysql.com\n",
+				old_lsn, new_lsn);
+			ut_ad(0);
+		}
 
-        /* We have to use nowait to ensure we don't block */
-	new_lsn= log_get_lsn_nowait();
-
-	if (new_lsn && new_lsn < old_lsn) {
-		ut_print_timestamp(stderr);
-		fprintf(stderr,
-			"  InnoDB: Error: old log sequence number %llu"
-			" was greater\n"
-			"InnoDB: than the new log sequence number %llu!\n"
-			"InnoDB: Please submit a bug report"
-			" to http://bugs.mysql.com\n",
-			old_lsn, new_lsn);
-		ut_ad(0);
-	}
-
-        if (new_lsn)
 		old_lsn = new_lsn;
+	}
 
 	if (difftime(time(NULL), srv_last_monitor_time) > 60) {
 		/* We referesh InnoDB Monitor values so that averages are
diff --git a/strings/decimal.c b/strings/decimal.c
index 07ccc53..8dbe1bd 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -383,7 +383,8 @@ int decimal2string(const decimal_t *from, char *to, int *to_len,
     }
     else
       frac-=j;
-    len= from->sign + intg_len + test(frac) + frac_len;
+    frac_len= frac;
+    len= from->sign + intg_len + test(frac) + frac;
   }
   *to_len=len;
   s[len]=0;
diff --git a/unittest/my_decimal/CMakeLists.txt b/unittest/my_decimal/CMakeLists.txt
index 0a38a18..85d203e 100644
--- a/unittest/my_decimal/CMakeLists.txt
+++ b/unittest/my_decimal/CMakeLists.txt
@@ -20,4 +20,4 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
                     ${CMAKE_SOURCE_DIR}/unittest/mytap)
 
 #
-MY_ADD_TESTS(my_decimal EXT "cc" LINK_LIBRARIES mysys)
+MY_ADD_TESTS(my_decimal EXT "cc" LINK_LIBRARIES strings dbug)
diff --git a/unittest/my_decimal/my_decimal-t.cc b/unittest/my_decimal/my_decimal-t.cc
index 48d0046..92c4bde 100644
--- a/unittest/my_decimal/my_decimal-t.cc
+++ b/unittest/my_decimal/my_decimal-t.cc
@@ -61,12 +61,42 @@ test_copy_and_compare()
 
 }
 
+static int
+test_decimal2string()
+{
+  decimal_t d1;
+  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH+2];
+  char *str_end;
+  const char strnum[]= "0.1234567890123456789012345678901234567890123467";
+  char strbuff[50];
+  int len= 40;
+  int i;
+
+  bzero(strbuff, sizeof(strbuff));
+  str_end= (char *)(strnum + (sizeof(strnum) - 1));
+
+  d1.len= DECIMAL_BUFF_LENGTH + 2;
+  d1.buf= buffer;
+
+  string2decimal(strnum, &d1, &str_end);
+  decimal2string(&d1, strbuff, &len, 0, 0, 'X');
+
+  /* last digit is not checked due to possible rounding */
+  for (i= 0; i < 38 && strbuff[i] == strnum[i]; i++);
+  ok(i == 38, "Number");
+  for (i= 39; i < 50 && strbuff[i] == 0; i++);
+  ok(i == 50, "No overrun");
+
+  return 0;
+
+}
 int main()
 {
-  plan(13);
+  plan(15);
   diag("Testing my_decimal constructor and assignment operators");
 
   test_copy_and_compare();
-  
+  test_decimal2string();
+
   return exit_status();
 }
diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt
index c4af782..95f54ac 100644
--- a/unittest/mysys/CMakeLists.txt
+++ b/unittest/mysys/CMakeLists.txt
@@ -13,9 +13,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
-MY_ADD_TESTS(bitmap base64 my_vsnprintf my_atomic my_rdtsc lf my_malloc
-             my_getopt
+MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring
              LINK_LIBRARIES mysys)
+MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
 
 IF(WIN32)
   MY_ADD_TESTS(my_delete LINK_LIBRARIES mysys)
diff --git a/unittest/mysys/dynstring-t.c b/unittest/mysys/dynstring-t.c
new file mode 100644
index 0000000..fed8488
--- /dev/null
+++ b/unittest/mysys/dynstring-t.c
@@ -0,0 +1,74 @@
+/* Copyright (c) 2016, MariaDB
+
+   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+//#include <my_global.h>
+#include <m_string.h>
+#include <my_sys.h>
+#include <tap.h>
+
+DYNAMIC_STRING str1;
+
+static void check(const char *res)
+{
+  ok(strcmp(str1.str, res) == 0, "strcmp: %s", str1.str);
+  str1.length= 0;
+}
+
+int main(void)
+{
+  plan(23);
+
+  IF_WIN(skip_all("Test of POSIX shell escaping rules, not for CMD.EXE\n"), );
+
+  ok(init_dynamic_string(&str1, NULL, 0, 32) == 0, "init");
+
+  ok(dynstr_append_os_quoted(&str1, "test1", NULL) == 0, "append");
+  check("'test1'");
+
+  ok(dynstr_append_os_quoted(&str1, "con", "cat", NULL) == 0, "append");
+  check("'concat'");
+
+  ok(dynstr_append_os_quoted(&str1, "", NULL) == 0, "append");
+  check("''");
+
+  ok(dynstr_append_os_quoted(&str1, "space inside", NULL) == 0, "append");
+  check("'space inside'");
+
+  ok(dynstr_append_os_quoted(&str1, "single'quote", NULL) == 0, "append");
+  check("'single'\"'\"'quote'");
+
+  ok(dynstr_append_os_quoted(&str1, "many'single'quotes", NULL) == 0, "append");
+  check("'many'\"'\"'single'\"'\"'quotes'");
+
+  ok(dynstr_append_os_quoted(&str1, "'single quoted'", NULL) == 0, "append");
+  check("''\"'\"'single quoted'\"'\"''");
+
+  ok(dynstr_append_os_quoted(&str1, "double\"quote", NULL) == 0, "append");
+  check("'double\"quote'");
+
+  ok(dynstr_append_os_quoted(&str1, "mixed\"single'and\"double'quotes", NULL) == 0, "append");
+  check("'mixed\"single'\"'\"'and\"double'\"'\"'quotes'");
+
+  ok(dynstr_append_os_quoted(&str1, "back\\space", NULL) == 0, "append");
+  check("'back\\space'");
+
+  ok(dynstr_append_os_quoted(&str1, "backspace\\'and\\\"quote", NULL) == 0, "append");
+  check("'backspace\\'\"'\"'and\\\"quote'");
+
+  dynstr_free(&str1);
+
+  return exit_status();
+}
+
diff --git a/unittest/strings/CMakeLists.txt b/unittest/strings/CMakeLists.txt
index 10791ed..2457475 100644
--- a/unittest/strings/CMakeLists.txt
+++ b/unittest/strings/CMakeLists.txt
@@ -1,3 +1,3 @@
 
-MY_ADD_TESTS(strings LINK_LIBRARIES strings)
+MY_ADD_TESTS(strings LINK_LIBRARIES strings mysys)
 
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index c889b90..11d01ea 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -17,6 +17,10 @@
 #include "vio_priv.h"
 
 #ifdef HAVE_OPENSSL
+#ifndef HAVE_YASSL
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#endif
 
 static my_bool     ssl_algorithms_added    = FALSE;
 static my_bool     ssl_error_strings_loaded= FALSE;
diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt
index 95547ac..0535a48 100644
--- a/win/packaging/CMakeLists.txt
+++ b/win/packaging/CMakeLists.txt
@@ -17,35 +17,62 @@ IF(NOT WIN32)
   RETURN()
 ENDIF()
 
+IF(MSVC_VERSION LESS 1600)
+ RETURN()
+ENDIF()
+
+
+
 SET(MANUFACTURER "MariaDB Corporation Ab")
 FIND_PATH(WIX_DIR heat.exe
-   $ENV{WIX_DIR}/bin
-   $ENV{ProgramFiles}/wix/bin
-  "$ENV{ProgramFiles}/Windows Installer XML v3/bin"
-  "$ENV{ProgramFiles}/Windows Installer XML v3.5/bin"
-  "$ENV{ProgramFiles}/Windows Installer XML v3.6/bin"
-  "$ENV{WIX}/bin"
+  "$ENV{ProgramFiles}/WiX Toolset v3.9/bin"
+  "$ENV{ProgramFiles}/WiX Toolset v3.10/bin"
 )
-
 SET(CPACK_WIX_PACKAGE_BASE_NAME "MariaDB")
 IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
  SET(CPACK_WIX_UPGRADE_CODE "49EB7A6A-1CEF-4A1E-9E89-B9A4993963E3")
- SET(CPACK_WIX_PACKAGE_NAME "MariaDB @MAJOR_VERSION at .@MINOR_VERSION@")
+ SET(CPACK_WIX_PACKAGE_NAME "MariaDB ${MAJOR_VERSION}.${MINOR_VERSION}")
 ELSE()
  SET(CPACK_WIX_UPGRADE_CODE "2331E7BD-EE58-431B-9E18-B2B918BCEB1B")
- SET(CPACK_WIX_PACKAGE_NAME "MariaDB @MAJOR_VERSION at .@MINOR_VERSION@ (x64)")
+ SET(CPACK_WIX_PACKAGE_NAME "MariaDB ${MAJOR_VERSION}.${MINOR_VERSION} (x64)")
 ENDIF()
 
+IF(WIX_DIR)
+IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  SET(WIX_ARCH_SUFFIX "x64")
+ELSE()
+  SET(WIX_ARCH_SUFFIX "x86")
+ENDIF()
+# Need some Wix SDK libraries to link with customaction
+IF(MSVC_VERSION EQUAL 1600 OR MSVC_VERSION EQUAL 1700 )
+  SET(WIX_MSVC_SUFFIX "VS2010")
+ELSEIF(MSVC_VERSION EQUAL 1800)
+  SET(WIX_MSVC_SUFFIX "VS2013")
+ELSEIF (MSVC_VERSION EQUAL 1900)
+  SET(WIX_MSVC_SUFFIX "VS2015")
+ENDIF()
+
+
+FIND_LIBRARY(WIX_WCAUTIL_LIBRARY 
+  NAMES wcautil${WIX_ARCH_SUFFIX}  wcautil${WIX_MSVC_SUFFIX}${WIX_ARCH_SUFFIX}
+  wcautil
+  PATHS 
+  ${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/lib/${WIX_ARCH_SUFFIX}
+  )
+
+FIND_LIBRARY(WIX_DUTIL_LIBRARY 
+  NAMES dutil${WIX_ARCH_SUFFIX} 
+  dutil
+  PATHS 
+  ${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/lib/${WIX_ARCH_SUFFIX}
+  )
+ENDIF()
 
-IF(NOT WIX_DIR)
-  IF(NOT _WIX_DIR_CHECKED)
-    SET(_WIX_DIR_CHECKED 1 CACHE INTERNAL "")
-    MESSAGE(STATUS "Cannot find wix 3, installer project will not be generated")
-    IF(BUILD_RELEASE)
+IF(NOT WIX_DUTIL_LIBRARY)
+  MESSAGE(STATUS "Cannot find wix 3, installer project will not be generated")
+  IF(BUILD_RELEASE)
       MESSAGE(FATAL_ERROR
-        "Can't find Wix. It is necessary for producing official package"
-      )
-    ENDIF()
+        "Can't find Wix. It is necessary for producing official package")
   ENDIF()
   RETURN()
 ENDIF()
diff --git a/win/packaging/ca/CMakeLists.txt b/win/packaging/ca/CMakeLists.txt
index 0da1e5d..04d5408 100644
--- a/win/packaging/ca/CMakeLists.txt
+++ b/win/packaging/ca/CMakeLists.txt
@@ -13,50 +13,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/inc)
-LINK_DIRECTORIES(${WIX_DIR}/../SDK/lib)
-
+INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/inc)
 SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def)
 
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql)
 
-IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
-  SET(WIX_ARCH_SUFFIX "_x64")
-  SET(WIX36_ARCH_SUFFIX "x64")
-ELSE()
-  SET(WIX_ARCH_SUFFIX)
-  SET(WIX36_ARCH_SUFFIX "x86")
-ENDIF()
-
-IF(MSVC_VERSION EQUAL 1400)
-  SET(WIX35_MSVC_SUFFIX "_2005")
-ELSEIF(MSVC_VERSION EQUAL 1500)
-  SET(WIX35_MSVC_SUFFIX "_2008")
-  SET(WIX36_MSVC_SUFFIX "VS2008")
-ELSEIF(MSVC_VERSION EQUAL 1600 OR MSVC_VERSION EQUAL 1700 )
-  SET(WIX35_MSVC_SUFFIX "_2010")
-  SET(WIX36_MSVC_SUFFIX "VS2010")
-ELSE()
-  # When next VS is out, add the correct version here
-  MESSAGE(FATAL_ERROR "Unknown VS version")
-ENDIF()
-INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/inc)
-
-FIND_LIBRARY(WIX_WCAUTIL_LIBRARY 
-  NAMES wcautil${WIX_ARCH_SUFFIX}  wcautil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX}
-  wcautil
-  PATHS 
-  ${WIX_DIR}/../SDK/lib 
-  ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX})
-
-FIND_LIBRARY(WIX_DUTIL_LIBRARY 
-  NAMES dutil${WIX_ARCH_SUFFIX}  dutil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX}
-  dutil
-  PATHS 
-  ${WIX_DIR}/../SDK/lib
-  ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX}
-  )
-
 ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES)
 ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES})
 TARGET_LINK_LIBRARIES(wixca ${WIX_WCAUTIL_LIBRARY} ${WIX_DUTIL_LIBRARY} 

-- 
Alioth's hooks/post-receive on /srv/git.debian.org/git/pkg-mysql/mariadb-5.5.git



More information about the Pkg-mysql-commits mailing list