summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@mariadb.com>2016-02-13 18:28:36 -0500
committerNirbhay Choubey <nirbhay@mariadb.com>2016-02-13 18:28:36 -0500
commitd23bd26bec787ebbdbd41be0204e9cb83baf4dbd (patch)
treedda05b0ebb3858e913b0ca3b864705e989bb7661
parentb83de1151aab6dcc9f300159e31198364000de70 (diff)
parenta9a08b1e2f5b7a9e3ab7c7f75c768389b1d8238f (diff)
downloadmariadb-git-d23bd26bec787ebbdbd41be0204e9cb83baf4dbd.tar.gz
Merge tag 'mariadb-5.5.48' into 5.5-galera
-rw-r--r--VERSION2
-rw-r--r--client/mysql.cc2
-rw-r--r--client/mysql_upgrade.c15
-rw-r--r--client/mysqltest.cc2
-rw-r--r--cmake/libutils.cmake5
-rw-r--r--cmake/os/Windows.cmake11
-rw-r--r--cmake/os/WindowsCache.cmake4
-rw-r--r--cmake/ssl.cmake5
-rw-r--r--config.h.cmake10
-rw-r--r--configure.cmake5
-rw-r--r--extra/yassl/README11
-rw-r--r--extra/yassl/include/crypto_wrapper.hpp1
-rw-r--r--extra/yassl/include/openssl/ssl.h2
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp11
-rw-r--r--extra/yassl/src/yassl_imp.cpp15
-rw-r--r--extra/yassl/src/yassl_int.cpp15
-rw-r--r--include/my_context.h2
-rw-r--r--include/my_global.h2
-rw-r--r--include/my_pthread.h2
-rw-r--r--include/violite.h4
-rw-r--r--include/welcome_copyright_notice.h6
-rw-r--r--libmysql/errmsg.c2
-rw-r--r--mysql-test/lib/My/SafeProcess/safe_process_win.cc10
-rw-r--r--mysql-test/r/create.result16
-rw-r--r--mysql-test/r/ctype_utf8.result23
-rw-r--r--mysql-test/r/ctype_utf8mb4.result18
-rw-r--r--mysql-test/r/ctype_utf8mb4_heap.result2
-rw-r--r--mysql-test/r/ctype_utf8mb4_innodb.result2
-rw-r--r--mysql-test/r/ctype_utf8mb4_myisam.result2
-rw-r--r--mysql-test/r/derived.result344
-rw-r--r--mysql-test/r/func_str.result6
-rw-r--r--mysql-test/r/func_time.result35
-rw-r--r--mysql-test/r/merge_innodb.result33
-rw-r--r--mysql-test/r/myisam-blob.result4
-rw-r--r--mysql-test/r/mysql_upgrade.result2
-rw-r--r--mysql-test/r/mysql_upgrade_view.result15
-rw-r--r--mysql-test/r/second_frac-9175.result13
-rw-r--r--mysql-test/r/sp.result18
-rw-r--r--mysql-test/r/ssl_cert_verify.result5
-rw-r--r--mysql-test/r/subselect.result13
-rw-r--r--mysql-test/r/subselect_extra_no_semijoin.result8
-rw-r--r--mysql-test/r/subselect_no_mat.result13
-rw-r--r--mysql-test/r/subselect_no_opts.result13
-rw-r--r--mysql-test/r/subselect_no_scache.result13
-rw-r--r--mysql-test/r/subselect_no_semijoin.result13
-rw-r--r--mysql-test/r/subselect_sj.result65
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result65
-rw-r--r--mysql-test/r/type_blob.result33
-rw-r--r--mysql-test/r/view.result20
-rw-r--r--mysql-test/std_data/ca-cert-verify.pem20
-rw-r--r--mysql-test/std_data/server-cert-verify-fail.pem19
-rw-r--r--mysql-test/std_data/server-cert-verify-pass.pem19
-rw-r--r--mysql-test/std_data/server-key-verify-fail.pem27
-rw-r--r--mysql-test/std_data/server-key-verify-pass.pem27
-rw-r--r--mysql-test/suite/innodb/r/innodb-dict.result40
-rw-r--r--mysql-test/suite/innodb/t/innodb-dict.test31
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_install.result1
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_load.result1
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_send.result1
-rw-r--r--mysql-test/suite/plugins/r/server_audit.result9
-rw-r--r--mysql-test/suite/plugins/r/thread_pool_server_audit.result9
-rw-r--r--mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result29
-rw-r--r--mysql-test/suite/rpl/r/rpl_unsafe_statements.result53
-rw-r--r--mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test87
-rw-r--r--mysql-test/suite/rpl/t/rpl_unsafe_statements.test176
-rw-r--r--mysql-test/suite/vcol/inc/vcol_ins_upd.inc27
-rw-r--r--mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result26
-rw-r--r--mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result26
-rw-r--r--mysql-test/suite/vcol/r/vcol_misc.result8
-rw-r--r--mysql-test/suite/vcol/t/vcol_misc.test7
-rw-r--r--mysql-test/t/create.test21
-rw-r--r--mysql-test/t/ctype_utf8.test14
-rw-r--r--mysql-test/t/ctype_utf8mb4.test12
-rw-r--r--mysql-test/t/derived.test290
-rw-r--r--mysql-test/t/func_time.test18
-rw-r--r--mysql-test/t/merge_innodb.test31
-rw-r--r--mysql-test/t/mysql_upgrade_view.test27
-rw-r--r--mysql-test/t/mysqldump.test7
-rw-r--r--mysql-test/t/second_frac-9175.test9
-rw-r--r--mysql-test/t/ssl_cert_verify.test43
-rw-r--r--mysql-test/t/subselect.test10
-rw-r--r--mysql-test/t/subselect_sj.test69
-rw-r--r--mysql-test/t/type_blob.test25
-rw-r--r--mysql-test/t/view.test10
-rw-r--r--mysql-test/valgrind.supp10
-rw-r--r--mysys/file_logger.c2
-rw-r--r--mysys/lf_hash.c43
-rw-r--r--mysys/my_wincond.c3
-rw-r--r--mysys/string.c17
-rw-r--r--plugin/feedback/feedback.cc12
-rw-r--r--plugin/feedback/feedback.h6
-rw-r--r--plugin/feedback/url_base.cc45
-rw-r--r--plugin/feedback/url_http.cc49
-rw-r--r--plugin/semisync/semisync_master.cc4
-rw-r--r--plugin/server_audit/CMakeLists.txt5
-rw-r--r--plugin/server_audit/plugin_audit_v4.h561
-rw-r--r--plugin/server_audit/server_audit.c870
-rw-r--r--plugin/server_audit/test_audit_v4.c162
-rw-r--r--sql-common/client.c90
-rw-r--r--sql/field.cc29
-rw-r--r--sql/field.h1
-rw-r--r--sql/field_conv.cc21
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_subselect.cc24
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/mysqld.cc23
-rw-r--r--sql/opt_subselect.cc14
-rw-r--r--sql/rpl_reporting.cc1
-rw-r--r--sql/sql_admin.cc14
-rw-r--r--sql/sql_base.cc166
-rw-r--r--sql/sql_class.cc135
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc15
-rw-r--r--sql/sql_lex.h16
-rw-r--r--sql/sql_select.cc40
-rw-r--r--sql/sql_select.h13
-rw-r--r--sql/sql_show.cc27
-rw-r--r--sql/sql_show.h3
-rw-r--r--sql/sql_table.cc27
-rw-r--r--sql/sql_time.h3
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_view.cc3
-rw-r--r--sql/sql_yacc.yy18
-rw-r--r--storage/innobase/buf/buf0flu.c9
-rw-r--r--storage/innobase/dict/dict0dict.c2
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/include/ha_prototypes.h14
-rw-r--r--storage/innobase/row/row0mysql.c49
-rw-r--r--storage/innobase/srv/srv0srv.c33
-rw-r--r--storage/tokudb/ft-index/buildheader/make_tdb.cc4
-rw-r--r--storage/tokudb/ft-index/ft/txn/rollback.cc4
-rw-r--r--storage/tokudb/ft-index/tools/tokudb_dump.cc70
-rw-r--r--storage/tokudb/ft-index/util/dmt.h8
-rw-r--r--storage/tokudb/ha_tokudb.cc2
-rw-r--r--storage/xtradb/dict/dict0dict.c2
-rw-r--r--storage/xtradb/handler/ha_innodb.cc14
-rw-r--r--storage/xtradb/include/ha_prototypes.h14
-rw-r--r--storage/xtradb/include/univ.i4
-rw-r--r--storage/xtradb/log/log0recv.c6
-rw-r--r--storage/xtradb/row/row0mysql.c49
-rw-r--r--strings/decimal.c3
-rw-r--r--unittest/my_decimal/CMakeLists.txt2
-rw-r--r--unittest/my_decimal/my_decimal-t.cc34
-rw-r--r--unittest/mysys/CMakeLists.txt2
-rw-r--r--unittest/mysys/dynstring-t.c74
-rw-r--r--vio/viosslfactories.c4
-rw-r--r--win/packaging/CMakeLists.txt61
-rw-r--r--win/packaging/ca/CMakeLists.txt41
155 files changed, 4293 insertions, 889 deletions
diff --git a/VERSION b/VERSION
index b85da230659..4bf30e8600e 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=47
+MYSQL_VERSION_PATCH=48
MYSQL_VERSION_EXTRA=
diff --git a/client/mysql.cc b/client/mysql.cc
index 8e40cf072cd..d33f8b186a0 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1107,7 +1107,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;
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 1298a4fc5de..9082c87883a 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1056,16 +1056,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/mysqltest.cc b/client/mysqltest.cc
index 9b925d6bfb8..8e8ddc8718b 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -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/libutils.cmake b/cmake/libutils.cmake
index cca0032962d..41b7d9d1d86 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 5999ae681f7..e1055ab5894 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 8f8d8df6b10..21a2b3e0d49 100644
--- a/cmake/os/WindowsCache.cmake
+++ b/cmake/os/WindowsCache.cmake
@@ -102,7 +102,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 "")
@@ -232,7 +231,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 "")
@@ -325,10 +323,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 ca950229129..43665d04a88 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 9bffc646f97..df4426a62a5 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
@@ -292,7 +293,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
@@ -320,6 +320,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
@@ -466,7 +468,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
@@ -516,6 +518,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 c88a6cc4767..7b6fac7baea 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -1099,3 +1099,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/extra/yassl/README b/extra/yassl/README
index bf0e1c9f40f..81d573d0b20 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -12,6 +12,17 @@ before calling SSL_new();
*** end Note ***
+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@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 b09b662c88c..0472b304679 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 b0a7592f870..095b3c6aa80 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.9"
#if defined(__cplusplus)
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
index cc74690a061..c40599880b2 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/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
index e1a410086fb..5158bd2d004 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 a98b4f3c9bd..77f3cf302cf 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 {
diff --git a/include/my_context.h b/include/my_context.h
index b5daca25bba..dd44103d3b2 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 09adc9989ef..9e9651b7409 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -436,7 +436,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 17c971cd621..9b5703dedb7 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/violite.h b/include/violite.h
index 14c99e8d8fe..ea7e3d7897c 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 096d42446bc..e9891856221 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/errmsg.c b/libmysql/errmsg.c
index 23c8e99cebc..9c241c2bd67 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/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc
index 87a14481e25..dca2faded71 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/create.result b/mysql-test/r/create.result
index 327b53ce6cd..0164aa4b610 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_utf8.result b/mysql-test/r/ctype_utf8.result
index 91dbe853a38..09bb5195b74 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
@@ -5092,9 +5092,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 +5805,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 64556308de2..448645ebbae 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 5959205ad1e..a9a84821f5e 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 4dcac1d9d7b..d8649d3238c 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 e07e3472a37..b0c673fdae5 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 7c44466ae92..2c316a829a7 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/func_str.result b/mysql-test/r/func_str.result
index 05d975b548b..5a7a13bacb6 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 08d46ab10fa..ef5e3487a99 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/merge_innodb.result b/mysql-test/r/merge_innodb.result
index f6057d279b1..5aa344a9391 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 43db7c8badd..6b41a244621 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 5f81ee567f1..49adac312cd 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 fa0ea5e3e64..fc174e9cfd1 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/second_frac-9175.result b/mysql-test/r/second_frac-9175.result
new file mode 100644
index 00000000000..dbf268b5c3b
--- /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/sp.result b/mysql-test/r/sp.result
index 962b834e4ac..6214fbcde35 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 00000000000..1da77329509
--- /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/subselect.result b/mysql-test/r/subselect.result
index ba52fd90da6..16ab4cf9d82 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 525b80e60ac..b8f1ba7cc5e 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 d8d5c4ef604..aed4fb39a84 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 78908bc61db..e1f08537788 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 d1de4b8f370..b5fa7b1dd8f 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 524a5ddc1a6..b815559433c 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 21acd463b59..1662d4eb14a 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 d9aa187e717..96bae673184 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 723efbdcb23..f49b2a7d5ef 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/view.result b/mysql-test/r/view.result
index b008e623b5d..dbfdf3f0f56 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 00000000000..21d6264a0ad
--- /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 00000000000..4203425a344
--- /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 00000000000..f8780f1f94e
--- /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 00000000000..af1ae1e3ae1
--- /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 00000000000..7ecc44f6d48
--- /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/innodb/r/innodb-dict.result b/mysql-test/suite/innodb/r/innodb-dict.result
new file mode 100644
index 00000000000..e3b2f0d5288
--- /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 00000000000..25a284569db
--- /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 c52fdb8f85b..ee74435e05a 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 e2cf3247022..ee433feb666 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 10378673829..881a5aa5040 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 69c9bc3a4be..67338506001 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 69c9bc3a4be..67338506001 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 00000000000..b03c0057a69
--- /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_unsafe_statements.result b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result
new file mode 100644
index 00000000000..2efb3eba2b1
--- /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 00000000000..a93fcbac82f
--- /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_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test
new file mode 100644
index 00000000000..cbb4b54a220
--- /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/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
index 8d0a51f42c0..d9a1e062870 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 44fcae7a6e5..af03cc4d482 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 66745862c22..351dfd2858c 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 8631789f15f..0aaed59ed6c 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 a4c1fc06ce9..12f46e9b002 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/create.test b/mysql-test/t/create.test
index e066dc6277d..5c90c3e17a4 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_utf8.test b/mysql-test/t/ctype_utf8.test
index 8cd70e9261a..a9b5cee11ce 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 fda20ca0ec5..66f5a3ba5ac 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 ddce7f55292..e10349b451c 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/func_time.test b/mysql-test/t/func_time.test
index f6afef99134..45214aed6e7 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/merge_innodb.test b/mysql-test/t/merge_innodb.test
index 7f0b1a0c36e..9f87f241d00 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 7a098aa701b..c98c88f840e 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 b0285747e4e..f0ada44fafd 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 00000000000..91baf997459
--- /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/ssl_cert_verify.test b/mysql-test/t/ssl_cert_verify.test
new file mode 100644
index 00000000000..83f621b7ca9
--- /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/subselect.test b/mysql-test/t/subselect.test
index 67eac0d228c..b802761aff3 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 9d7ea17bbe2..51bed53be17 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 66dd71d2305..d5f6fc6ed32 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/view.test b/mysql-test/t/view.test
index 815be87b04e..a25a4d129aa 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 b09ab0904e7..29897e4bd6c 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/file_logger.c b/mysys/file_logger.c
index 394b59f6378..b94cb705d3f 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_hash.c b/mysys/lf_hash.c
index 38b212c65f0..797c20e819e 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_wincond.c b/mysys/my_wincond.c
index c761064dd96..07ba4f5c587 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 d9791341c60..a63b1f502e5 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 a06c0e6c496..79436bd5268 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 98939c29d34..0542b7399f1 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 e7d038f02e2..6afbcd7c8f4 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 dd39adbf7a7..dff5da56a4f 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 625f7448945..3c22bcb94f2 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 527d0d702da..3de8c43c871 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 00000000000..5f8e43b3811
--- /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;
+};
+
+/**
+@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 bede4c9545d..d988f7e8317 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},
@@ -415,7 +564,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 +624,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 +724,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 +737,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 +749,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 +758,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 +897,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 +1073,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 +1099,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 +1122,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@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 +1170,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@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 +1295,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 +1461,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 +1803,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 +1823,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 +1842,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 +1880,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 +1901,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 +1929,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 +1941,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 +1961,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 +2003,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 +2048,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 +2066,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 +2083,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 +2100,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 +2183,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 +2344,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 +2363,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 +2386,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 +2414,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 +2450,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 +2493,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 +2501,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 +2527,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 +2564,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 +2609,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 +2627,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 +2712,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 +2730,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 +2743,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 +2776,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 +2800,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 +2828,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)]= 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 00000000000..ae7527f8449
--- /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 1bb4a250c69..09548cb58a7 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 aeeacf7f88d..ceea0893a3f 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 4c79847228e..f761aa8d3ea 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 d24f31e4fa1..5781f1da576 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/item.cc b/sql/item.cc
index 6d2983f249d..3d3f472afc5 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) 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/sql/item.h b/sql/item.h
index f8e8ead47dd..d09f6572487 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
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d5f50871ddf..81688f3321c 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
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index babe1d76ea4..0faba016ba8 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
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index aca66fc29e0..94370d45cef 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 3020faf29d3..ba674743724 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 522004e965b..873dcdac4b9 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 cf0c066c750..9194838d424 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 a2fb263d2dd..f71b245b942 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
@@ -3103,7 +3103,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);
/*
@@ -9778,8 +9778,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 3e2cc40e181..a9359ba047e 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1320,7 +1320,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
@@ -4152,7 +4151,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);
@@ -4210,12 +4208,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;
@@ -8194,7 +8186,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();
@@ -8967,20 +8959,23 @@ 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
#ifdef WITH_WSREP
end= strmov(end, "-wsrep");
#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/opt_subselect.cc b/sql/opt_subselect.cc
index 827290fd15b..5137d8a0986 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 f442f3a37c0..ebb0dbec1cb 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_admin.cc b/sql/sql_admin.cc
index 8909e5ae05d..b6f337aade5 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 dd9813795d0..402905f6af0 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
@@ -220,11 +220,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)
{
@@ -2916,6 +2911,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))
{
@@ -5914,63 +5919,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 (WSREP_BINLOG_FORMAT(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),
@@ -9722,98 +9670,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 09533599ac0..5322f49768e 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
@@ -4752,6 +4752,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
@@ -4915,6 +5003,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.
@@ -4953,6 +5066,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 6e80eeb7096..6c072fe513e 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) 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/sql_insert.cc b/sql/sql_insert.cc
index 75a62a0f120..8e8745f322f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -4197,6 +4197,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 bb76d33ef2e..2d7926017c2 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
@@ -3877,6 +3877,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 6454da24af3..b13befd8dbe 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_select.cc b/sql/sql_select.cc
index 1b1464049df..b1e22537b37 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) 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() &&
@@ -15444,9 +15433,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 +15940,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 +16132,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 +17592,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)))
{
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 4f807ff5b93..4650bc24c68 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 0ad1b8f1bdb..be45eecabf7 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 04997fe8965..864216ebc06 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 f30b004accf..d8e9aaf1f5f 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) 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);
diff --git a/sql/sql_time.h b/sql/sql_time.h
index 443d22c5419..ad752121044 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 e3084108dad..9f80b063901 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2242,6 +2242,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)
{
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index e6c5ffddfcf..5bd82fdd842 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.yy b/sql/sql_yacc.yy
index 2b9647cc043..3b42fe1e74a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9878,15 +9878,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() &&
@@ -9907,6 +9898,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 da58d8392cf..d15f2e4601e 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/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 7f128771ca0..2a59347bc78 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 891584962a8..03385d374bf 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3533,7 +3533,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 1d8c5072a6f..add494d394f 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -349,4 +349,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/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 181ca966451..1a11e398959 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 3f7c2c80bd9..3f0d3cb7062 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.
@@ -2563,6 +2563,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
@@ -2600,24 +2602,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/tokudb/ft-index/buildheader/make_tdb.cc b/storage/tokudb/ft-index/buildheader/make_tdb.cc
index 53706649231..610ce670db5 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/ft/txn/rollback.cc b/storage/tokudb/ft-index/ft/txn/rollback.cc
index 62048039c26..ea2f2a07c50 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 2da50bb793a..b162c5caece 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 d4b032f5d6f..43e44df6a70 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 b4e2c1a311e..2eb8004a296 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/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index c0f355d8846..6f16fc0bce0 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 0834f4d08b1..0f5952ce5f2 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -4271,7 +4271,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(
/*=====================*/
@@ -8805,7 +8805,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,
@@ -8814,6 +8815,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/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 411dcfa578c..73741ed911e 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -386,4 +386,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 6e130b1c936..116d3115c97 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.7
#endif
-#define INNODB_VERSION_STR "5.5.46-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
+#define INNODB_VERSION_STR "5.5.47-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 e465f9a60bc..b0b481b0094 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 9496df8774a..e6ccf44b884 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/strings/decimal.c b/strings/decimal.c
index 07ccc537e47..8dbe1bd57f4 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 0a38a18b7ba..85d203e8f47 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 48d00465af9..92c4bdee8e4 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 c4af7828e42..5a46efc8e5a 100644
--- a/unittest/mysys/CMakeLists.txt
+++ b/unittest/mysys/CMakeLists.txt
@@ -14,7 +14,7 @@
# 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_getopt dynstring
LINK_LIBRARIES mysys)
IF(WIN32)
diff --git a/unittest/mysys/dynstring-t.c b/unittest/mysys/dynstring-t.c
new file mode 100644
index 00000000000..fed8488da2c
--- /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/vio/viosslfactories.c b/vio/viosslfactories.c
index c889b90a2e2..11d01ea534d 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 95547ac9f3a..0535a486d57 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@.@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@.@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 0da1e5d67b1..04d5408b9c9 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}