diff options
335 files changed, 7433 insertions, 2281 deletions
diff --git a/.gitignore b/.gitignore index ae36c2696af..bb393224588 100644 --- a/.gitignore +++ b/.gitignore @@ -94,7 +94,6 @@ packaging/rpm-oel/mysql.spec packaging/rpm-uln/mysql.10.0.11.spec packaging/solaris/postinstall-solaris pcre/config.h -pcre/pcre*test.sh pcre/pcre.h pcre/pcre_chartables.c pcre/pcregrep diff --git a/CMakeLists.txt b/CMakeLists.txt index 58b6cc62e9f..7779f298ea5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,22 +14,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) -# explicitly set the policy to OLD -# (cannot use NEW, not everyone is on cmake-2.8.12 yet) IF(POLICY CMP0022) - CMAKE_POLICY(SET CMP0022 OLD) -ENDIF() - -# We use the LOCATION target property (CMP0026) -# and get_target_property() for non-existent targets (CMP0045) -# and INSTALL_NAME_DIR (CMP0042) -IF(CMAKE_VERSION VERSION_EQUAL "3.0.0" OR - CMAKE_VERSION VERSION_GREATER "3.0.0") - CMAKE_POLICY(SET CMP0026 OLD) - CMAKE_POLICY(SET CMP0045 OLD) - CMAKE_POLICY(SET CMP0042 OLD) + CMAKE_POLICY(SET CMP0022 NEW) ENDIF() IF(POLICY CMP0054) CMAKE_POLICY(SET CMP0054 NEW) @@ -181,6 +169,12 @@ IF(UNIX) ENDIF() OPTION (WITH_UNIT_TESTS "Compile MySQL with unit tests" ON) +IF (WITHOUT_SERVER) + SET (SKIP_COMPONENTS "Server|IniFiles|SuportFiles|Readme") +ELSE() + SET (SKIP_COMPONENTS "N-O-N-E") +ENDIF() + OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system libraries. Only set it you never plan to distribute the resulting binaries" OFF) INCLUDE(check_compiler_flag) @@ -445,7 +439,7 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/mysql_version.h.in CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in ${CMAKE_BINARY_DIR}/sql/sql_builtin.cc) -IF(GIT_EXECUTABLE) +IF(GIT_EXECUTABLE AND EXISTS ${PROJECT_SOURCE_DIR}/.git) EXECUTE_PROCESS( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 4c8709bfca6..14656705805 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -82,7 +82,7 @@ ulong bytes_sent = 0L, bytes_received = 0L; ulong mysqld_net_retry_count = 10L; ulong open_files_limit; ulong opt_binlog_rows_event_max_size; -uint test_flags = 0; +ulonglong test_flags = 0; static uint opt_protocol= 0; static FILE *result_file; static char *result_file_name= 0; diff --git a/cmake/FindZSTD.cmake b/cmake/FindZSTD.cmake deleted file mode 100644 index 0fd73501327..00000000000 --- a/cmake/FindZSTD.cmake +++ /dev/null @@ -1,18 +0,0 @@ -find_path( - ZSTD_INCLUDE_DIR - NAMES "zstd.h" -) - -find_library( - ZSTD_LIBRARY - NAMES zstd -) - -set(ZSTD_LIBRARIES ${ZSTD_LIBRARY}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - ZSTD DEFAULT_MSG ZSTD_INCLUDE_DIR ZSTD_LIBRARIES) - -mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARIES ZSTD_FOUND) - diff --git a/cmake/Findzstd.cmake b/cmake/Findzstd.cmake new file mode 100644 index 00000000000..8cd4c248145 --- /dev/null +++ b/cmake/Findzstd.cmake @@ -0,0 +1,25 @@ +# - Find zstd +# Find the zstd compression library and includes +# +# ZSTD_INCLUDE_DIR - where to find zstd.h, etc. +# ZSTD_LIBRARIES - List of libraries when using zstd. +# ZSTD_FOUND - True if zstd found. + +if (DEFINED ZSTD_LIBRARIES) + return() +endif() + +find_path(ZSTD_INCLUDE_DIR + NAMES zstd.h + HINTS ${ZSTD_ROOT_DIR}/include) + +find_library(ZSTD_LIBRARIES + NAMES zstd + HINTS ${ZSTD_ROOT_DIR}/lib) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(zstd DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIR) + +mark_as_advanced( + ZSTD_LIBRARIES + ZSTD_INCLUDE_DIR) diff --git a/cmake/create_initial_db.cmake.in b/cmake/create_initial_db.cmake index baa48847815..df972cf379a 100644 --- a/cmake/create_initial_db.cmake.in +++ b/cmake/create_initial_db.cmake @@ -14,11 +14,6 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This script creates initial database for packaging on Windows -SET(CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@") -SET(CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@") -SET(MYSQLD_EXECUTABLE "@MYSQLD_EXECUTABLE@") -SET(CMAKE_CFG_INTDIR "@CMAKE_CFG_INTDIR@") -SET(WIN32 "@WIN32@") # Force Visual Studio to output to stdout IF(ENV{VS_UNICODE_OUTPUT}) SET ($ENV{VS_UNICODE_OUTPUT}) @@ -32,30 +27,27 @@ ENDIF() # Create bootstrapper SQL script FILE(WRITE bootstrap.sql "use mysql;\n" ) FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql mysql_performance_tables.sql) - FILE(STRINGS ${CMAKE_SOURCE_DIR}/scripts/${FILENAME} CONTENTS) + FILE(STRINGS ${TOP_SRCDIR}/scripts/${FILENAME} CONTENTS) FOREACH(STR ${CONTENTS}) IF(NOT STR MATCHES "@current_hostname") FILE(APPEND bootstrap.sql "${STR}\n") ENDIF() ENDFOREACH() ENDFOREACH() -FILE(READ ${CMAKE_SOURCE_DIR}/scripts/fill_help_tables.sql CONTENTS) +FILE(READ ${TOP_SRCDIR}/scripts/fill_help_tables.sql CONTENTS) FILE(APPEND bootstrap.sql "${CONTENTS}") FILE(REMOVE_RECURSE mysql performance_schema) FILE(REMOVE ibdata1 ib_logfile0 ib_logfile1) MAKE_DIRECTORY(mysql) -IF(WIN32) - SET(CONSOLE --console) -ENDIF() SET(BOOTSTRAP_COMMAND ${MYSQLD_EXECUTABLE} --no-defaults - ${CONSOLE} + --console --bootstrap - --lc-messages-dir=${CMAKE_CURRENT_BINARY_DIR}/share + --lc-messages-dir=${BINDIR}/share --basedir=. --datadir=. --default-storage-engine=MyISAM @@ -65,10 +57,10 @@ SET(BOOTSTRAP_COMMAND GET_FILENAME_COMPONENT(CWD . ABSOLUTE) EXECUTE_PROCESS( - COMMAND "@CMAKE_COMMAND@" -E echo Executing ${BOOTSTRAP_COMMAND} + COMMAND "${CMAKE_COMMAND}" -E echo Executing ${BOOTSTRAP_COMMAND} ) EXECUTE_PROCESS ( - COMMAND "@CMAKE_COMMAND@" -E + COMMAND "${CMAKE_COMMAND}" -E echo input file bootstrap.sql, current directory ${CWD} ) EXECUTE_PROCESS ( diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake index d7ab0f31991..bb45eaf865b 100644 --- a/cmake/dtrace.cmake +++ b/cmake/dtrace.cmake @@ -46,6 +46,10 @@ MACRO(CHECK_DTRACE) AND NOT CMAKE_SYSTEM_NAME MATCHES "SunOS") SET(ENABLE_DTRACE ON CACHE BOOL "Enable dtrace") ENDIF() + # On GNU/Hurd, dtrace is not supported + IF(DTRACE AND CMAKE_SYSTEM_NAME MATCHES "GNU") + SET(ENABLE_DTRACE OFF CACHE BOOL "Disable dtrace") + ENDIF() SET(HAVE_DTRACE ${ENABLE_DTRACE}) IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") IF(CMAKE_SIZEOF_VOID_P EQUAL 4) diff --git a/cmake/for_clients.cmake b/cmake/for_clients.cmake index e5916c56ddc..2c2c965df64 100644 --- a/cmake/for_clients.cmake +++ b/cmake/for_clients.cmake @@ -11,9 +11,6 @@ SET(LIBS "") IF(POLICY CMP0011) CMAKE_POLICY(SET CMP0011 NEW) ENDIF() -IF(POLICY CMP0007) - CMAKE_POLICY(SET CMP0007 OLD) -ENDIF() # Extract dependencies using CMake's internal ${target}_LIB_DEPENDS variable # returned string in ${var} is can be passed to linker's command line diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 5ca147d0d60..71657e32308 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -115,7 +115,12 @@ FUNCTION(INSTALL_SCRIPT) SET(COMP) ENDIF() + IF (COMP MATCHES ${SKIP_COMPONENTS}) + RETURN() + ENDIF() + INSTALL(PROGRAMS ${script} DESTINATION ${ARG_DESTINATION} ${COMP}) + INSTALL_MANPAGE(${script}) ENDFUNCTION() @@ -132,6 +137,10 @@ FUNCTION(INSTALL_DOCUMENTATION) SET(destination ${INSTALL_DOCDIR}) ENDIF() + IF (ARG_COMPONENT MATCHES ${SKIP_COMPONENTS}) + RETURN() + ENDIF() + STRING(TOUPPER ${ARG_COMPONENT} COMPUP) IF(CPACK_COMPONENT_${COMPUP}_GROUP) SET(group ${CPACK_COMPONENT_${COMPUP}_GROUP}) @@ -150,21 +159,17 @@ ENDFUNCTION() # Install symbolic link to CMake target. -# the link is created in the same directory as target +# the link is created in the current build directory # and extension will be the same as for target file. MACRO(INSTALL_SYMLINK linkname target destination component) IF(UNIX) - GET_TARGET_PROPERTY(location ${target} LOCATION) - GET_FILENAME_COMPONENT(path ${location} PATH) - GET_FILENAME_COMPONENT(name ${location} NAME) - SET(output ${path}/${linkname}) + SET(output ${CMAKE_CURRENT_BINARY_DIR}/${linkname}) ADD_CUSTOM_COMMAND( OUTPUT ${output} - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${output} + COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${linkname} COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink - ${name} + $<TARGET_FILE_NAME:${target}> ${linkname} - WORKING_DIRECTORY ${path} DEPENDS ${target} ) @@ -250,8 +255,7 @@ FUNCTION(MYSQL_INSTALL_TARGETS) ENDIF() # Install man pages on Unix IF(UNIX) - GET_TARGET_PROPERTY(target_location ${target} LOCATION) - INSTALL_MANPAGE(${target_location}) + INSTALL_MANPAGE($<TARGET_FILE:${target}>) ENDIF() ENDFOREACH() @@ -268,6 +272,7 @@ SET(DEBUGBUILDDIR "${BINARY_PARENTDIR}/debug" CACHE INTERNAL "Directory of debug FUNCTION(INSTALL_DEBUG_TARGET target) + RETURN() # XXX unused? CMAKE_PARSE_ARGUMENTS(ARG "" "DESTINATION;RENAME;PDB_DESTINATION;COMPONENT" diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index a31fe0d4510..cdc7af5d228 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -139,17 +139,17 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) SET(OSLIBS) FOREACH(LIB ${LIBS_TO_MERGE}) - GET_TARGET_PROPERTY(LIB_LOCATION ${LIB} LOCATION) - GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE) - IF(NOT LIB_LOCATION) + IF(NOT TARGET ${LIB}) # 3rd party library like libz.so. Make sure that everything # that links to our library links to this one as well. LIST(APPEND OSLIBS ${LIB}) ELSE() + GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE) # This is a target in current project # (can be a static or shared lib) IF(LIB_TYPE STREQUAL "STATIC_LIBRARY") - SET(STATIC_LIBS ${STATIC_LIBS} ${LIB_LOCATION}) + SET(STATIC_TGTS ${STATIC_TGTS} ${LIB}) + SET(STATIC_LIBS ${STATIC_LIBS} $<TARGET_FILE:${LIB}>) ADD_DEPENDENCIES(${TARGET} ${LIB}) # Extract dependent OS libraries GET_DEPENDEND_OS_LIBS(${LIB} LIB_OSLIBS) @@ -171,7 +171,7 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) ADD_CUSTOM_COMMAND( OUTPUT ${SOURCE_FILE} COMMAND ${CMAKE_COMMAND} -E touch ${SOURCE_FILE} - DEPENDS ${STATIC_LIBS}) + DEPENDS ${STATIC_TGTS}) IF(MSVC) # To merge libs, just pass them to lib.exe command line. @@ -182,29 +182,27 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) SET_TARGET_PROPERTIES(${TARGET} PROPERTIES STATIC_LIBRARY_FLAGS "${LINKER_EXTRA_FLAGS}") ELSE() - GET_TARGET_PROPERTY(TARGET_LOCATION ${TARGET} LOCATION) IF(APPLE) # Use OSX's libtool to merge archives (ihandles universal # binaries properly) ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD - COMMAND rm ${TARGET_LOCATION} - COMMAND libtool -static -o ${TARGET_LOCATION} + COMMAND rm $<TARGET_FILE:${TARGET}> + COMMAND libtool -static -o $<TARGET_FILE:${TARGET}> ${STATIC_LIBS} ) ELSE() # Generic Unix, Cygwin or MinGW. In post-build step, call # script, that extracts objects from archives with "ar x" # and repacks them with "ar r" - SET(TARGET ${TARGET}) - CONFIGURE_FILE( - ${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake - @ONLY - ) ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD - COMMAND rm ${TARGET_LOCATION} - COMMAND ${CMAKE_COMMAND} -P - ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake + COMMAND ${CMAKE_COMMAND} + -DTARGET_LOCATION="$<TARGET_FILE:${TARGET}>" + -DTARGET="${TARGET}" + -DSTATIC_LIBS="${STATIC_LIBS}" + -DCMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}" + -DCMAKE_AR="${CMAKE_AR}" + -DCMAKE_RANLIB="${CMAKE_RANLIB}" + -P "${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake" ) ENDIF() ENDIF() @@ -269,7 +267,7 @@ MACRO(MERGE_LIBRARIES) IF (ARG_SOVERSION) SET_TARGET_PROPERTIES(${TARGET} PROPERTIES SOVERSION ${ARG_VERSION}) ENDIF() - TARGET_LINK_LIBRARIES(${TARGET} ${LIBS}) + TARGET_LINK_LIBRARIES(${TARGET} LINK_PRIVATE ${LIBS}) IF(ARG_OUTPUT_NAME) SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}") ENDIF() @@ -282,7 +280,6 @@ MACRO(MERGE_LIBRARIES) ENDIF() MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}" ${COMP}) ENDIF() - SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_INTERFACE_LIBRARIES "") IF(ARG_SHARED AND LINK_FLAG_NO_UNDEFINED) # Do not allow undefined symbols in shared libraries GET_TARGET_PROPERTY(TARGET_LINK_FLAGS ${TARGET} LINK_FLAGS) @@ -295,18 +292,11 @@ MACRO(MERGE_LIBRARIES) ENDMACRO() FUNCTION(GET_DEPENDEND_OS_LIBS target result) - SET(deps ${${target}_LIB_DEPENDS}) - IF(deps) - FOREACH(lib ${deps}) - # Filter out keywords for used for debug vs optimized builds - IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized") - GET_TARGET_PROPERTY(lib_location ${lib} LOCATION) - IF(NOT lib_location) - SET(ret ${ret} ${lib}) - ENDIF() + FOREACH(lib ${${target}_LIB_DEPENDS}) + IF(NOT TARGET ${lib}) + SET(ret ${ret} ${lib}) ENDIF() - ENDFOREACH() - ENDIF() + ENDFOREACH() SET(${result} ${ret} PARENT_SCOPE) ENDFUNCTION() diff --git a/cmake/merge_archives_unix.cmake.in b/cmake/merge_archives_unix.cmake index d05336d6c91..08b1931c3d3 100644 --- a/cmake/merge_archives_unix.cmake.in +++ b/cmake/merge_archives_unix.cmake @@ -14,19 +14,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# This script merges many static libraries into -# one big library on Unix. -SET(TARGET_LOCATION "@TARGET_LOCATION@") -SET(TARGET "@TARGET@") -SET(STATIC_LIBS "@STATIC_LIBS@") -SET(CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@") -SET(CMAKE_AR "@CMAKE_AR@") -SET(CMAKE_RANLIB "@CMAKE_RANLIB@") - +FILE(REMOVE "${TARGET_LOCATION}") SET(TEMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}) MAKE_DIRECTORY(${TEMP_DIR}) # Extract each archive to its own subdirectory(avoid object filename clashes) +SEPARATE_ARGUMENTS(STATIC_LIBS UNIX_COMMAND "${STATIC_LIBS}") FOREACH(LIB ${STATIC_LIBS}) GET_FILENAME_COMPONENT(NAME_NO_EXT ${LIB} NAME_WE) SET(TEMP_SUBDIR ${TEMP_DIR}/${NAME_NO_EXT}) diff --git a/cmake/mysql_add_executable.cmake b/cmake/mysql_add_executable.cmake index de4d49a7cd1..c61a23a978f 100644 --- a/cmake/mysql_add_executable.cmake +++ b/cmake/mysql_add_executable.cmake @@ -75,6 +75,9 @@ FUNCTION (MYSQL_ADD_EXECUTABLE) ELSE() SET(COMP COMPONENT Client) ENDIF() + IF (COMP MATCHES ${SKIP_COMPONENTS}) + RETURN() + ENDIF() MYSQL_INSTALL_TARGETS(${target} DESTINATION ${ARG_DESTINATION} ${COMP}) ENDIF() ENDFUNCTION() diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index 4930a6bf40a..73a53b0766a 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -77,6 +77,9 @@ IF(NOT VERSION) SET(DEFAULT_MACHINE "i386") ENDIF() ENDIF() + ELSEIF(CMAKE_SYSTEM_NAME MATCHES "GNU") + SET(DEFAULT_PLATFORM "GNU") + SET(DEFAULT_MACHINE "i386") ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") IF(CMAKE_OSX_DEPLOYMENT_TARGET) SET(DEFAULT_PLATFORM "osx${CMAKE_OSX_DEPLOYMENT_TARGET}") @@ -132,7 +135,7 @@ IF(NOT VERSION) SET(package_name "mariadb${PRODUCT_TAG}-${VERSION}-${SYSTEM_NAME_AND_PROCESSOR}") - MESSAGE(STATUS "Packaging as: ${package_name}") + MESSAGE_ONCE(package_name "Packaging as: ${package_name}") # Sometimes package suffix is added (something like "-icc-glibc23") IF(PACKAGE_SUFFIX) diff --git a/cmake/systemd.cmake b/cmake/systemd.cmake index f7365066ef6..fc36d7cefbf 100644 --- a/cmake/systemd.cmake +++ b/cmake/systemd.cmake @@ -20,10 +20,12 @@ MACRO(CHECK_SYSTEMD) SET(WITH_SYSTEMD "auto" CACHE STRING "Enable systemd scripts and notification support") IF(WITH_SYSTEMD STREQUAL "yes" OR WITH_SYSTEMD STREQUAL "auto") IF(PKG_CONFIG_FOUND) - IF(WITH_SYSTEMD STREQUAL "yes") - pkg_search_module(LIBSYSTEMD REQUIRED libsystemd libsystemd-daemon) - ELSE() - pkg_search_module(LIBSYSTEMD libsystemd libsystemd-daemon) + IF (NOT DEFINED LIBSYSTEMD_FOUND) + IF(WITH_SYSTEMD STREQUAL "yes") + pkg_search_module(LIBSYSTEMD REQUIRED libsystemd libsystemd-daemon) + ELSE() + pkg_search_module(LIBSYSTEMD libsystemd libsystemd-daemon) + ENDIF() ENDIF() IF(HAVE_DLOPEN) SET(LIBSYSTEMD ${LIBSYSTEMD_LIBRARIES}) diff --git a/debian/additions/innotop/changelog.innotop b/debian/additions/innotop/changelog.innotop index 67bc52698e7..1816595240b 100644 --- a/debian/additions/innotop/changelog.innotop +++ b/debian/additions/innotop/changelog.innotop @@ -77,7 +77,7 @@ Changelog for innotop: * remove cxn from $meta->{group_by} if there's only one connection displayed * fix for issue 19 - cxn column won't become visible when viewing two connections after having viewed one connection - * supress errors resulting from the addition of a 'BACKGROUND THREAD' + * suppress errors resulting from the addition of a 'BACKGROUND THREAD' section in the output of 'show innodb status' * possible fix for issue 22 - Useless use of a constant in void context * small change to set_to_tbl() around hiding the cxn column if there diff --git a/debian/additions/innotop/innotop b/debian/additions/innotop/innotop index f958eba432b..b0134e0bc91 100644 --- a/debian/additions/innotop/innotop +++ b/debian/additions/innotop/innotop @@ -17,7 +17,7 @@ # 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 -# Street, Fifth Floor, Boston, MA 02110-1301 USA +# Street, Fifth Floor, Boston, MA 02111-1301 USA use strict; use warnings FATAL => 'all'; @@ -1438,8 +1438,8 @@ systems, you can issue `man perlgpl' or `man perlartistic' to read these licenses. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA. +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02111-1301 USA. LICENSE # Configuration information and global setup {{{1 @@ -4657,7 +4657,7 @@ my %stmt_maker_for = ( my $sth; eval { # This can fail if the table doesn't exist, INFORMATION_SCHEMA doesn't exist, etc. my $cols = $dbh->selectall_arrayref(q{SHOW /*innotop*/ COLUMNS FROM INFORMATION_SCHEMA.PROCESSLIST LIKE 'TIME_MS'}); - if ( @$cols ) { # The TIME_MS colum exists + if ( @$cols ) { # The TIME_MS column exists $sth = $dbh->prepare(q{SELECT /*innotop*/ ID, USER, HOST, DB, COMMAND, CASE WHEN TIME_MS/1000 > 365*86400 THEN TIME ELSE TIME_MS/1000 END AS TIME, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST}); } }; @@ -11653,7 +11653,7 @@ show you something like this: pages_modified Dirty Pages Pages modified (dirty IB_bp_pages_m buf_pool_hit_rate Hit Rate Buffer pool hit rate IB_bp_buf_poo total_mem_alloc Memory Total memory allocate IB_bp_total_m - add_pool_alloc Add'l Pool Additonal pool alloca IB_bp_add_poo + add_pool_alloc Add'l Pool Additional pool alloca IB_bp_add_poo The first line shows which table you're editing, and reminds you again to press '?' for a list of key mappings. The rest is a tabular representation of the @@ -12233,8 +12233,8 @@ systems, you can issue `man perlgpl' or `man perlartistic' to read these licenses. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA. +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02111-1301 USA. Execute innotop and press '!' to see this information at any time. diff --git a/debian/additions/innotop/innotop.1 b/debian/additions/innotop/innotop.1 index 7cd275a79f2..7079ff2c4a4 100644 --- a/debian/additions/innotop/innotop.1 +++ b/debian/additions/innotop/innotop.1 @@ -1678,7 +1678,7 @@ show you something like this: \& pages_modified Dirty Pages Pages modified (dirty IB_bp_pages_m \& buf_pool_hit_rate Hit Rate Buffer pool hit rate IB_bp_buf_poo \& total_mem_alloc Memory Total memory allocate IB_bp_total_m -\& add_pool_alloc Add\*(Aql Pool Additonal pool alloca IB_bp_add_poo +\& add_pool_alloc Add\*(Aql Pool Additional pool alloca IB_bp_add_poo .Ve .PP The first line shows which table you're editing, and reminds you again to press @@ -2183,8 +2183,8 @@ systems, you can issue `man perlgpl' or `man perlartistic' to read these licenses. .PP You should have received a copy of the \s-1GNU\s0 General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, \s-1MA 02111\-1307 USA.\s0 +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, \s-1MA\s0 02111\-1301 \s-1USA\s0. .PP Execute innotop and press '!' to see this information at any time. .SH "AUTHOR" diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 3d713776dc4..252ceb967fa 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -471,6 +471,21 @@ struct datafile_cur_t { size_t buf_size; size_t buf_read; size_t buf_offset; + + explicit datafile_cur_t(const char* filename = NULL) : + file(), thread_n(0), orig_buf(NULL), buf(NULL), buf_size(0), + buf_read(0), buf_offset(0) + { + memset(rel_path, 0, sizeof rel_path); + if (filename) { + strncpy(abs_path, filename, sizeof abs_path); + abs_path[(sizeof abs_path) - 1] = 0; + } else { + abs_path[0] = '\0'; + } + rel_path[0] = '\0'; + memset(&statinfo, 0, sizeof statinfo); + } }; static @@ -489,9 +504,7 @@ datafile_open(const char *file, datafile_cur_t *cursor, uint thread_n) { bool success; - memset(cursor, 0, sizeof(datafile_cur_t)); - - strncpy(cursor->abs_path, file, sizeof(cursor->abs_path)); + new (cursor) datafile_cur_t(file); /* Get the relative path for the destination tablespace name, i.e. the one that can be appended to the backup root directory. Non-system @@ -630,32 +643,36 @@ static int mkdirp(const char *pathname, int Flags, myf MyFlags) { - char parent[PATH_MAX], *p; + char *parent, *p; /* make a parent directory path */ - strncpy(parent, pathname, sizeof(parent)); - parent[sizeof(parent) - 1] = 0; + if (!(parent= strdup(pathname))) + return(-1); for (p = parent + strlen(parent); - !is_path_separator(*p) && p != parent; p--); + !is_path_separator(*p) && p != parent; p--) ; *p = 0; /* try to make parent directory */ if (p != parent && mkdirp(parent, Flags, MyFlags) != 0) { + free(parent); return(-1); } /* make this one if parent has been made */ if (my_mkdir(pathname, Flags, MyFlags) == 0) { + free(parent); return(0); } /* if it already exists that is fine */ if (errno == EEXIST) { + free(parent); return(0); } + free(parent); return(-1); } @@ -665,17 +682,24 @@ bool equal_paths(const char *first, const char *second) { #ifdef HAVE_REALPATH - char real_first[PATH_MAX]; - char real_second[PATH_MAX]; + char *real_first, *real_second; + int result; - if (realpath(first, real_first) == NULL) { + real_first = realpath(first, 0); + if (real_first == NULL) { return false; } - if (realpath(second, real_second) == NULL) { + + real_second = realpath(second, 0); + if (real_second == NULL) { + free(real_first); return false; } - return (strcmp(real_first, real_second) == 0); + result = strcmp(real_first, real_second); + free(real_first); + free(real_second); + return result == 0; #else return strcmp(first, second) == 0; #endif @@ -1360,6 +1384,30 @@ out: return(ret); } +void backup_fix_ddl(void); + +#define LSN_PREFIX_IN_SHOW_STATUS "\nLog sequence number " +static lsn_t get_current_lsn(MYSQL *connection) { + MYSQL_RES *res = xb_mysql_query(connection, "SHOW ENGINE INNODB STATUS", true, false); + if (!res) + return 0; + MYSQL_ROW row = mysql_fetch_row(res); + DBUG_ASSERT(row); + if (row) { + const char *p = strstr(row[2],LSN_PREFIX_IN_SHOW_STATUS); + DBUG_ASSERT(p); + if (p) + { + p += sizeof(LSN_PREFIX_IN_SHOW_STATUS) - 1; + return (lsn_t)strtoll(p, NULL, 10); + } + } + mysql_free_result(res); + return 0; +} + +lsn_t server_lsn_after_lock; +extern void backup_wait_for_lsn(lsn_t lsn); /** Start --backup */ bool backup_start() { @@ -1379,6 +1427,7 @@ bool backup_start() if (!lock_tables(mysql_connection)) { return(false); } + server_lsn_after_lock = get_current_lsn(mysql_connection); } if (!backup_files(fil_path_to_mysql_datadir, false)) { @@ -1393,6 +1442,10 @@ bool backup_start() rocksdb_create_checkpoint(); } + msg_ts("Waiting for log copy thread to read lsn %llu\n", (ulonglong)server_lsn_after_lock); + backup_wait_for_lsn(server_lsn_after_lock); + backup_fix_ddl(); + // There is no need to stop slave thread before coping non-Innodb data when // --no-lock option is used because --no-lock option requires that no DDL or // DML to non-transaction tables can occur. @@ -2202,6 +2255,7 @@ static void rocksdb_lock_checkpoint() msg_ts("Could not obtain rocksdb checkpont lock\n"); exit(EXIT_FAILURE); } + mysql_free_result(res); } static void rocksdb_unlock_checkpoint() diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index d04f680c8ef..c0b509abdbf 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -1795,7 +1795,12 @@ mdl_lock_table(ulint space_id) std::ostringstream lock_query; lock_query << "SELECT 1 FROM " << full_table_name << " LIMIT 0"; msg_ts("Locking MDL for %s\n", full_table_name.c_str()); - xb_mysql_query(mdl_con, lock_query.str().c_str(), false, true); + if (mysql_query(mdl_con, lock_query.str().c_str())) { + msg_ts("Warning : locking MDL failed for space id %zu, name %s\n", space_id, full_table_name.c_str()); + } else { + MYSQL_RES *r = mysql_store_result(mdl_con); + mysql_free_result(r); + } } pthread_mutex_unlock(&mdl_lock_con_mutex); diff --git a/extra/mariabackup/datasink.c b/extra/mariabackup/datasink.c index 19ea132c1c7..f6d924f7e06 100644 --- a/extra/mariabackup/datasink.c +++ b/extra/mariabackup/datasink.c @@ -109,6 +109,9 @@ Write to a datasink file. int ds_write(ds_file_t *file, const void *buf, size_t len) { + if (len == 0) { + return 0; + } return file->datasink->write(file, (const uchar *)buf, len); } diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 799405b3d42..1c6070378ab 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -130,14 +130,15 @@ Open a source file cursor and initialize the associated read filter. be skipped and XB_FIL_CUR_ERROR on error. */ xb_fil_cur_result_t xb_fil_cur_open( -/*============*/ + /*============*/ xb_fil_cur_t* cursor, /*!< out: source file cursor */ xb_read_filt_t* read_filter, /*!< in/out: the read filter */ fil_node_t* node, /*!< in: source tablespace node */ - uint thread_n) /*!< thread number for diagnostics */ + uint thread_n, /*!< thread number for diagnostics */ + ulonglong max_file_size) { bool success; - + int err; /* Initialize these first so xb_fil_cur_close() handles them correctly in case of error */ cursor->orig_buf = NULL; @@ -172,7 +173,7 @@ xb_fil_cur_open( "tablespace %s\n", thread_n, cursor->abs_path); - return(XB_FIL_CUR_ERROR); + return(XB_FIL_CUR_SKIP); } mutex_enter(&fil_system.mutex); @@ -193,14 +194,31 @@ xb_fil_cur_open( cursor->node = node; cursor->file = node->handle; - - if (stat(cursor->abs_path, &cursor->statinfo)) { - msg("[%02u] mariabackup: error: cannot stat %s\n", +#ifdef _WIN32 + HANDLE hDup; + DuplicateHandle(GetCurrentProcess(),cursor->file.m_file, + GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS); + int filenr = _open_osfhandle((intptr_t)hDup, 0); + if (filenr < 0) { + err = EINVAL; + } + else { + err = _fstat64(filenr, &cursor->statinfo); + close(filenr); + } +#else + err = fstat(cursor->file.m_file, &cursor->statinfo); +#endif + if (max_file_size < (ulonglong)cursor->statinfo.st_size) { + cursor->statinfo.st_size = (ulonglong)max_file_size; + } + if (err) { + msg("[%02u] mariabackup: error: cannot fstat %s\n", thread_n, cursor->abs_path); xb_fil_cur_close(cursor); - return(XB_FIL_CUR_ERROR); + return(XB_FIL_CUR_SKIP); } if (srv_file_flush_method == SRV_O_DIRECT @@ -373,7 +391,9 @@ xb_fil_cur_close( /*=============*/ xb_fil_cur_t *cursor) /*!< in/out: source file cursor */ { - cursor->read_filter->deinit(&cursor->read_filter_ctxt); + if (cursor->read_filter) { + cursor->read_filter->deinit(&cursor->read_filter_ctxt); + } free(cursor->orig_buf); diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h index 6e0dda8c885..ad023d93208 100644 --- a/extra/mariabackup/fil_cur.h +++ b/extra/mariabackup/fil_cur.h @@ -58,7 +58,7 @@ struct xb_fil_cur_t { ulint space_size; /*!< space size in pages */ /** TODO: remove this default constructor */ - xb_fil_cur_t() : page_size(0), read_filter_ctxt() {} + xb_fil_cur_t() : page_size(0), read_filter(0), read_filter_ctxt() {} /** @return whether this is not a file-per-table tablespace */ bool is_system() const @@ -87,7 +87,8 @@ xb_fil_cur_open( xb_fil_cur_t* cursor, /*!< out: source file cursor */ xb_read_filt_t* read_filter, /*!< in/out: the read filter */ fil_node_t* node, /*!< in: source tablespace node */ - uint thread_n); /*!< thread number for diagnostics */ + uint thread_n, /*!< thread number for diagnostics */ + ulonglong max_file_size = ULLONG_MAX); /************************************************************************ Reads and verifies the next block of pages from the source diff --git a/extra/mariabackup/wsrep.cc b/extra/mariabackup/wsrep.cc index fac1fdcf583..c3ad1b53a21 100644 --- a/extra/mariabackup/wsrep.cc +++ b/extra/mariabackup/wsrep.cc @@ -75,8 +75,7 @@ xb_write_galera_info(bool incremental_prepare) return; } - memset(&xid, 0, sizeof(xid)); - xid.formatID = -1; + xid.null(); if (!trx_rseg_read_wsrep_checkpoint(xid)) { diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index ff81bd2fd82..8006404de15 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -344,6 +344,25 @@ const char *opt_history = NULL; char mariabackup_exe[FN_REFLEN]; char orig_argv1[FN_REFLEN]; +pthread_mutex_t backup_mutex; +pthread_cond_t scanned_lsn_cond; + +typedef std::map<space_id_t,std::string> space_id_to_name_t; + +struct ddl_tracker_t { + /** Tablspaces with their ID and name, as they were copied to backup.*/ + space_id_to_name_t tables_in_backup; + /** Tablespaces for that optimized DDL without redo log was found.*/ + std::set<space_id_t> optimized_ddl; + /** Drop operations found in redo log. */ + std::set<space_id_t> drops; + /* For DDL operation found in redo log, */ + space_id_to_name_t id_to_name; +}; +const space_id_t REMOVED_SPACE_ID = ULINT_MAX; +static ddl_tracker_t ddl_tracker; + + /* Whether xtrabackup_binlog_info should be created on recovery */ static bool recover_binlog_info; @@ -536,49 +555,79 @@ void mdl_lock_all() mdl_lock_table(node->space->id); } datafiles_iter_free(it); - - DBUG_EXECUTE_IF("check_mdl_lock_works", - dbug_alter_thread_done = - dbug_start_query_thread("ALTER TABLE test.t ADD COLUMN mdl_lock_column int", - "Waiting for table metadata lock",1, ER_QUERY_INTERRUPTED);); } -/** Check if the space id belongs to the table which name should -be skipped based on the --tables, --tables-file and --table-exclude -options. -@param[in] space_id space id to check -@return true if the space id belongs to skip table/database list. */ -static bool backup_includes(space_id_t space_id) -{ - datafiles_iter_t *it = datafiles_iter_new(); - if (!it) - return true; - while (fil_node_t *node = datafiles_iter_next(it)){ - if (space_id == 0 - || (node->space->id == space_id - && !check_if_skip_table(node->space->name))) { +// Convert non-null terminated filename to space name +std::string filename_to_spacename(const byte *filename, size_t len) +{ + // null- terminate filename + char *f = (char *)malloc(len + 1); + ut_a(f); + memcpy(f, filename, len); + f[len] = 0; + for (size_t i = 0; i < len; i++) + if (f[i] == '\\') + f[i] = '/'; + char *p = strrchr(f, '.'); + ut_a(p); + *p = 0; + char *table = strrchr(f, '/'); + ut_a(table); + *table = 0; + char *db = strrchr(f, '/'); + ut_a(db); + *table = '/'; + return std::string(db+1); +} - msg("mariabackup: Unsupported redo log detected " - "and it belongs to %s\n", - space_id ? node->name: "the InnoDB system tablespace"); +/** Report an operation to create, delete, or rename a file during backup. +@param[in] space_id tablespace identifier +@param[in] flags tablespace flags (NULL if not create) +@param[in] name file name (not NUL-terminated) +@param[in] len length of name, in bytes +@param[in] new_name new file name (NULL if not rename) +@param[in] new_len length of new_name, in bytes (0 if NULL) */ +void backup_file_op(ulint space_id, const byte* flags, + const byte* name, ulint len, + const byte* new_name, ulint new_len) +{ - msg("mariabackup: ALTER TABLE or OPTIMIZE TABLE " - "was being executed during the backup.\n"); + ut_ad(!flags || !new_name); + ut_ad(name); + ut_ad(len); + ut_ad(!new_name == !new_len); + pthread_mutex_lock(&backup_mutex); + + if (flags) { + ddl_tracker.id_to_name[space_id] = filename_to_spacename(name, len); + msg("DDL tracking : create %zu \"%.*s\": %x\n", + space_id, int(len), name, mach_read_from_4(flags)); + } + else if (new_name) { + ddl_tracker.id_to_name[space_id] = filename_to_spacename(new_name, new_len); + msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"\n", + space_id, int(len), name, int(new_len), new_name); + } else { + ddl_tracker.drops.insert(space_id); + msg("DDL tracking : delete %zu \"%.*s\"\n", space_id, int(len), name); + } + pthread_mutex_unlock(&backup_mutex); +} - if (!opt_lock_ddl_per_table) { - msg("mariabackup: Use --lock-ddl-per-table " - "parameter to lock all the table before " - "backup operation.\n"); - } - datafiles_iter_free(it); - return false; - } - } +/** Callback whenever MLOG_INDEX_LOAD happens. +@param[in] space_id space id to check +@return false */ +void backup_optimized_ddl_op(ulint space_id) +{ + // TODO : handle incremental + if (xtrabackup_incremental) + return; - datafiles_iter_free(it); - return true; + pthread_mutex_lock(&backup_mutex); + ddl_tracker.optimized_ddl.insert(space_id); + pthread_mutex_unlock(&backup_mutex); } /* ======== Date copying thread context ======== */ @@ -1363,7 +1412,7 @@ static int prepare_export() // which is* unfortunately* still necessary to get mysqld up if (strncmp(orig_argv1,"--defaults-file=",16) == 0) { - sprintf(cmdline, + snprintf(cmdline, sizeof cmdline, IF_WIN("\"","") "\"%s\" --mysqld \"%s\" " " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0" @@ -2326,7 +2375,7 @@ xb_get_copy_action(const char *dflt) static my_bool -xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) +xtrabackup_copy_datafile(fil_node_t* node, uint thread_n, const char *dest_name=0, ulonglong max_size=ULLONG_MAX) { char dst_name[FN_REFLEN]; ds_file_t *dstfile = NULL; @@ -2356,20 +2405,35 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) return(FALSE); } + bool was_dropped; + pthread_mutex_lock(&backup_mutex); + was_dropped = (ddl_tracker.drops.find(node->space->id) != ddl_tracker.drops.end()); + pthread_mutex_unlock(&backup_mutex); + if (was_dropped) { + if (node->is_open()) { + mutex_enter(&fil_system.mutex); + node->close(); + mutex_exit(&fil_system.mutex); + } + goto skip; + } + if (!changed_page_bitmap) { read_filter = &rf_pass_through; } else { read_filter = &rf_bitmap; } - res = xb_fil_cur_open(&cursor, read_filter, node, thread_n); + + res = xb_fil_cur_open(&cursor, read_filter, node, thread_n,max_size); if (res == XB_FIL_CUR_SKIP) { goto skip; } else if (res == XB_FIL_CUR_ERROR) { goto error; } - strncpy(dst_name, cursor.rel_path, sizeof(dst_name)); + strncpy(dst_name, (dest_name)?dest_name : cursor.rel_path, sizeof(dst_name)); + /* Setup the page write filter */ if (xtrabackup_incremental) { @@ -2421,6 +2485,10 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) goto error; } + pthread_mutex_lock(&backup_mutex); + ddl_tracker.tables_in_backup[node->space->id] = node_name; + pthread_mutex_unlock(&backup_mutex); + /* close */ msg_ts("[%02u] ...done\n", thread_n); xb_fil_cur_close(&cursor); @@ -2583,7 +2651,7 @@ static bool xtrabackup_copy_logfile(bool last = false) if (!start_lsn) { msg("mariabackup: Error: xtrabackup_copy_logfile()" " failed.\n"); - return(true); + exit(EXIT_FAILURE); } } while (start_lsn == end_lsn); @@ -2592,12 +2660,30 @@ static bool xtrabackup_copy_logfile(bool last = false) msg_ts(">> log scanned up to (" LSN_PF ")\n", start_lsn); /* update global variable*/ + pthread_mutex_lock(&backup_mutex); log_copy_scanned_lsn = start_lsn; + pthread_cond_broadcast(&scanned_lsn_cond); + pthread_mutex_unlock(&backup_mutex); debug_sync_point("xtrabackup_copy_logfile_pause"); return(false); } +/** +Wait until redo log copying thread processes given lsn +*/ +void backup_wait_for_lsn(lsn_t lsn) { + bool completed = false; + pthread_mutex_lock(&backup_mutex); + do { + pthread_cond_wait(&scanned_lsn_cond, &backup_mutex); + completed = log_copy_scanned_lsn >= lsn; + } while (!completed); + pthread_mutex_unlock(&backup_mutex); +} + +extern lsn_t server_lsn_after_lock; + static os_thread_ret_t DECLARE_THREAD(log_copying_thread)(void*) { /* @@ -2654,6 +2740,42 @@ static os_thread_ret_t DECLARE_THREAD(io_watching_thread)(void*) return(0); } +#ifndef DBUG_OFF +/* +In debug mode, execute SQL statement that was passed via environment. +To use this facility, you need to + +1. Add code DBUG_EXECUTE_MARIABACKUP_EVENT("my_event_name", key);); + to the code. key is usually a table name +2. Set environment variable my_event_name_$key SQL statement you want to execute + when event occurs, in DBUG_EXECUTE_IF from above. + In mtr , you can set environment via 'let' statement (do not use $ as the first char + for the variable) +3. start mariabackup with --dbug=+d,debug_mariabackup_events +*/ +static void dbug_mariabackup_event(const char *event,const char *key) +{ + char envvar[FN_REFLEN]; + if (key) { + snprintf(envvar, sizeof(envvar), "%s_%s", event, key); + char *slash = strchr(envvar, '/'); + if (slash) + *slash = '_'; + } else { + strncpy(envvar, event, sizeof(envvar)); + } + char *sql = getenv(envvar); + if (sql) { + msg("dbug_mariabackup_event : executing '%s'\n", sql); + xb_mysql_query(mysql_connection, sql, false, true); + } + +} +#define DBUG_MARIABACKUP_EVENT(A, B) DBUG_EXECUTE_IF("mariabackup_events", dbug_mariabackup_event(A,B);); +#else +#define DBUG_MARIABACKUP_EVENT(A,B) +#endif + /************************************************************************** Datafiles copying thread.*/ static @@ -2676,12 +2798,18 @@ DECLARE_THREAD(data_copy_thread_func)( while ((node = datafiles_iter_next(ctxt->it)) != NULL) { + DBUG_MARIABACKUP_EVENT("before_copy", node->space->name); + + /* copy the datafile */ if(xtrabackup_copy_datafile(node, num)) { msg("[%02u] mariabackup: Error: " "failed to copy datafile.\n", num); exit(EXIT_FAILURE); } + + DBUG_MARIABACKUP_EVENT("after_copy", node->space->name); + } pthread_mutex_lock(&ctxt->count_mutex); @@ -2853,6 +2981,7 @@ xb_load_single_table_tablespace( Datafile *file = xb_new_datafile(name, is_remote); if (file->open_read_only(true) != DB_SUCCESS) { + msg("Can't open datafile %s\n", name); ut_free(name); exit(EXIT_FAILURE); } @@ -3170,7 +3299,7 @@ xb_load_tablespaces() } debug_sync_point("xtrabackup_load_tablespaces_pause"); - + DBUG_MARIABACKUP_EVENT("after_load_tablespaces", 0); return(DB_SUCCESS); } @@ -3765,6 +3894,8 @@ xtrabackup_backup_func() uint count; pthread_mutex_t count_mutex; data_thread_ctxt_t *data_threads; + pthread_mutex_init(&backup_mutex, NULL); + pthread_cond_init(&scanned_lsn_cond, NULL); #ifdef USE_POSIX_FADVISE msg("mariabackup: uses posix_fadvise().\n"); @@ -3778,7 +3909,7 @@ xtrabackup_backup_func() return(false); } msg("mariabackup: cd to %s\n", mysql_real_data_home); - + encryption_plugin_backup_init(mysql_connection); msg("mariabackup: open files limit requested %u, set to %u\n", (uint) xb_open_files_limit, xb_set_max_open_files(xb_open_files_limit)); @@ -3791,6 +3922,7 @@ xtrabackup_backup_func() srv_read_only_mode = TRUE; srv_operation = SRV_OPERATION_BACKUP; + log_file_op = backup_file_op; metadata_to_lsn = 0; if (xb_close_files) @@ -3804,6 +3936,7 @@ xtrabackup_backup_func() fail: metadata_to_lsn = log_copying_running; stop_backup_threads(); + log_file_op = NULL; if (dst_log_file) { ds_close(dst_log_file); dst_log_file = NULL; @@ -4053,6 +4186,7 @@ fail_before_log_copying_thread_start: goto fail_before_log_copying_thread_start; log_copying_stop = os_event_create(0); + log_optimized_ddl_op = backup_optimized_ddl_op; os_thread_create(log_copying_thread, NULL, &log_copying_thread_id); /* FLUSH CHANGED_PAGE_BITMAPS call */ @@ -4084,6 +4218,11 @@ fail_before_log_copying_thread_start: if (opt_lock_ddl_per_table) { mdl_lock_all(); + + DBUG_EXECUTE_IF("check_mdl_lock_works", + dbug_alter_thread_done = + dbug_start_query_thread("ALTER TABLE test.t ADD COLUMN mdl_lock_column int", + "Waiting for table metadata lock", 1, ER_QUERY_INTERRUPTED);); } it = datafiles_iter_new(); @@ -4121,10 +4260,6 @@ fail_before_log_copying_thread_start: pthread_mutex_destroy(&count_mutex); free(data_threads); datafiles_iter_free(it); - - if (changed_page_bitmap) { - xb_page_bitmap_deinit(changed_page_bitmap); - } } bool ok = backup_start(); @@ -4148,6 +4283,9 @@ fail_before_log_copying_thread_start: goto fail; } + if (changed_page_bitmap) { + xb_page_bitmap_deinit(changed_page_bitmap); + } xtrabackup_destroy_datasinks(); msg("mariabackup: Redo log (from LSN " LSN_PF " to " LSN_PF @@ -4165,9 +4303,182 @@ fail_before_log_copying_thread_start: } innodb_shutdown(); + log_file_op = NULL; + pthread_mutex_destroy(&backup_mutex); + pthread_cond_destroy(&scanned_lsn_cond); return(true); } + +/** +This function handles DDL changes at the end of backup, under protection of +FTWRL. This ensures consistent backup in presence of DDL. + +- New tables, that were created during backup, are now copied into backup. + Also, tablespaces with optimized (no redo loggin DDL) are re-copied into + backup. This tablespaces will get the extension ".new" in the backup + +- Tables that were renamed during backup, are marked as renamed + For these, file <old_name>.ren will be created. + The content of the file is the new tablespace name. + +- Tables that were deleted during backup, are marked as deleted + For these , an empty file <name>.del will be created + + It is the responsibility of the prepare phase to deal with .new, .ren, and .del + files. +*/ +void backup_fix_ddl(void) +{ + std::set<std::string> new_tables; + std::set<std::string> dropped_tables; + std::map<std::string, std::string> renamed_tables; + + for (space_id_to_name_t::iterator iter = ddl_tracker.tables_in_backup.begin(); + iter != ddl_tracker.tables_in_backup.end(); + iter++) { + + const std::string name = iter->second; + ulint id = iter->first; + + if (ddl_tracker.drops.find(id) != ddl_tracker.drops.end()) { + dropped_tables.insert(name); + continue; + } + + bool has_optimized_ddl = + ddl_tracker.optimized_ddl.find(id) != ddl_tracker.optimized_ddl.end(); + + if (ddl_tracker.id_to_name.find(id) == ddl_tracker.id_to_name.end()) { + if (has_optimized_ddl) { + new_tables.insert(name); + } + continue; + } + + /* tablespace was affected by DDL. */ + const std::string new_name = ddl_tracker.id_to_name[id]; + if (new_name != name) { + if (has_optimized_ddl) { + /* table was renamed, but we need a full copy + of it because of optimized DDL. We emulate a drop/create.*/ + dropped_tables.insert(name); + new_tables.insert(new_name); + } else { + /* Renamed, and no optimized DDL*/ + renamed_tables[name] = new_name; + } + } else if (has_optimized_ddl) { + /* Table was recreated, or optimized DDL ran. + In both cases we need a full copy in the backup.*/ + new_tables.insert(name); + } + } + + /* Find tables that were created during backup (and not removed).*/ + for(space_id_to_name_t::iterator iter = ddl_tracker.id_to_name.begin(); + iter != ddl_tracker.id_to_name.end(); + iter++) { + + ulint id = iter->first; + std::string name = iter->second; + + if (ddl_tracker.tables_in_backup.find(id) != ddl_tracker.tables_in_backup.end()) { + /* already processed above */ + continue; + } + + if (ddl_tracker.drops.find(id) == ddl_tracker.drops.end()) { + dropped_tables.erase(name); + new_tables.insert(name); + } + } + + // Mark tablespaces for rename + for (std::map<std::string, std::string>::iterator iter = renamed_tables.begin(); + iter != renamed_tables.end(); ++iter) { + const std::string old_name = iter->first; + std::string new_name = iter->second; + backup_file_printf((old_name + ".ren").c_str(), "%s", new_name.c_str()); + } + + // Mark tablespaces for drop + for (std::set<std::string>::iterator iter = dropped_tables.begin(); + iter != dropped_tables.end(); + iter++) { + const std::string name(*iter); + backup_file_printf((name + ".del").c_str(), "%s", ""); + } + + // Load and copy new tables. + // Close all datanodes first, reload only new tables. + std::vector<fil_node_t *> all_nodes; + datafiles_iter_t *it = datafiles_iter_new(); + if (!it) + return; + while (fil_node_t *node = datafiles_iter_next(it)) { + all_nodes.push_back(node); + } + for (size_t i = 0; i < all_nodes.size(); i++) { + fil_node_t *n = all_nodes[i]; + if (n->space->id == 0) + continue; + if (n->is_open()) { + mutex_enter(&fil_system.mutex); + n->close(); + mutex_exit(&fil_system.mutex); + } + fil_space_free(n->space->id, false); + } + + + for (std::set<std::string>::iterator iter = new_tables.begin(); + iter != new_tables.end(); iter++) { + const char *space_name = iter->c_str(); + if (check_if_skip_table(space_name)) + continue; + std::string name(*iter); + bool is_remote = access((name + ".ibd").c_str(), R_OK) != 0; + const char *extension = is_remote ? ".isl" : ".ibd"; + name.append(extension); + char buf[FN_REFLEN]; + strncpy(buf, name.c_str(), sizeof(buf)); + const char *dbname = buf; + char *p = strchr(buf, '/'); + if (p == 0) { + msg("Unexpected tablespace %s filename %s\n", space_name, name.c_str()); + ut_a(0); + } + ut_a(p); + *p = 0; + const char *tablename = p + 1; + xb_load_single_table_tablespace(dbname, tablename, is_remote); + } + + it = datafiles_iter_new(); + if (!it) + return; + + while (fil_node_t *node = datafiles_iter_next(it)) { + fil_space_t * space = node->space; + if (!fil_is_user_tablespace_id(space->id)) + continue; + std::string dest_name(node->space->name); + dest_name.append(".new"); +#if 0 + bool do_full_copy = ddl_tracker.optimized_ddl.find(n->space->id) != ddl_tracker.optimized_ddl.end(); + if (do_full_copy) { + msg( + "Performing a full copy of the tablespace %s, because optimized (without redo logging) DDL operation" + "ran during backup. You can use set innodb_log_optimize_ddl=OFF to improve backup performance" + "in the future.\n", + n->space->name); + } +#endif + xtrabackup_copy_datafile(node, 0, dest_name.c_str()/*, do_full_copy ? ULONGLONG_MAX:UNIV_PAGE_SIZE */); + } +} + /* ================= prepare ================= */ /*********************************************************************** @@ -4680,6 +4991,27 @@ error: return FALSE; } + +std::string change_extension(std::string filename, std::string new_ext) { + DBUG_ASSERT(new_ext.size() == 3); + std::string new_name(filename); + new_name.resize(new_name.size() - new_ext.size()); + new_name.append(new_ext); + return new_name; +} + + +static void rename_file(const char *from,const char *to) { + msg("Renaming %s to %s\n", from, to); + if (my_rename(from, to, MY_WME)) { + msg("Cannot rename %s to %s errno %d", from, to, errno); + exit(EXIT_FAILURE); + } +} + +static void rename_file(const std::string& from, const std::string &to) { + rename_file(from.c_str(), to.c_str()); +} /************************************************************************ Callback to handle datadir entry. Function of this type will be called for each entry which matches the mask by xb_process_datadir. @@ -4691,6 +5023,37 @@ typedef ibool (*handle_datadir_entry_func_t)( const char* file_name, /*!<in: file name with suffix */ void* arg); /*!<in: caller-provided data */ +/** Rename, and replace destination file, if exists */ +static void rename_force(const char *from, const char *to) { + if (access(to, R_OK) == 0) { + msg("Removing %s\n", to); + if (my_delete(to, MYF(MY_WME))) { + msg("Can't remove %s, errno %d", to, errno); + exit(EXIT_FAILURE); + } + } + rename_file(from,to); +} + +/* During prepare phase, rename ".new" files , that were created in backup_fix_ddl(), + to ".ibd".*/ +static ibool prepare_handle_new_files( + const char* data_home_dir, /*!<in: path to datadir */ + const char* db_name, /*!<in: database name */ + const char* file_name, /*!<in: file name with suffix */ + void *) +{ + + std::string src_path = std::string(data_home_dir) + '/' + std::string(db_name) + '/' + file_name; + std::string dest_path = src_path; + + size_t index = dest_path.find(".new"); + DBUG_ASSERT(index != std::string::npos); + dest_path.replace(index, 4, ".ibd"); + rename_force(src_path.c_str(),dest_path.c_str()); + return TRUE; +} + /************************************************************************ Callback to handle datadir entry. Deletes entry if it has no matching fil_space in fil_system directory. @@ -4896,6 +5259,103 @@ store_binlog_info(const char* filename, const char* name, ulonglong pos) return(true); } +/** Check if file exists*/ +static bool file_exists(std::string name) +{ + return access(name.c_str(), R_OK) == 0 ; +} + +/** Read file content into STL string */ +static std::string read_file_as_string(const std::string file) { + char content[FN_REFLEN]; + FILE *f = fopen(file.c_str(), "r"); + if (!f) { + msg("Can not open %s\n", file.c_str()); + } + size_t len = fread(content, 1, FN_REFLEN, f); + fclose(f); + return std::string(content, len); +} + +/** Delete file- Provide verbose diagnostics and exit, if operation fails. */ +static void delete_file(const std::string& file, bool if_exists = false) { + if (if_exists && !file_exists(file)) + return; + if (my_delete(file.c_str(), MYF(MY_WME))) { + msg("Can't remove %s, errno %d", file.c_str(), errno); + exit(EXIT_FAILURE); + } +} + +/** +Rename tablespace during prepare. +Backup in its end phase may generate some .ren files, recording +tablespaces that should be renamed in --prepare. +*/ +static void rename_table_in_prepare(const std::string &datadir, const std::string& from , const std::string& to, + const char *extension=0) { + if (!extension) { + static const char *extensions_nonincremental[] = { ".ibd", 0 }; + static const char *extensions_incremental[] = { ".ibd.delta", ".ibd.meta", 0 }; + const char **extensions = xtrabackup_incremental_dir ? + extensions_incremental : extensions_nonincremental; + for (size_t i = 0; extensions[i]; i++) { + rename_table_in_prepare(datadir, from, to, extensions[i]); + } + return; + } + std::string src = std::string(datadir) + "/" + from + extension; + std::string dest = std::string(datadir) + "/" + to + extension; + std::string ren2, tmp; + if (file_exists(dest)) { + ren2= std::string(datadir) + "/" + to + ".ren"; + if (!file_exists(ren2)) { + msg("ERROR : File %s was not found, but expected during rename processing\n", ren2.c_str()); + ut_a(0); + } + tmp = to + "#"; + rename_table_in_prepare(datadir, to, tmp); + } + rename_file(src, dest); + if (ren2.size()) { + // Make sure the temp. renamed file is processed. + std::string to2 = read_file_as_string(ren2); + rename_table_in_prepare(datadir, tmp, to2); + delete_file(ren2); + } +} + +static ibool prepare_handle_ren_files(const char *datadir, const char *db, const char *filename, void *) { + + std::string ren_file = std::string(datadir) + "/" + db + "/" + filename; + if (!file_exists(ren_file)) + return TRUE; + + std::string to = read_file_as_string(ren_file); + std::string source_space_name = std::string(db) + "/" + filename; + source_space_name.resize(source_space_name.size() - 4); // remove extension + + rename_table_in_prepare(datadir, source_space_name.c_str(), to.c_str()); + delete_file(ren_file); + return TRUE; +} + +/* Remove tablespaces during backup, based on */ +static ibool prepare_handle_del_files(const char *datadir, const char *db, const char *filename, void *) { + std::string del_file = std::string(datadir) + "/" + db + "/" + filename; + std::string path(del_file); + path.resize(path.size() - 4); // remove extension; + if (xtrabackup_incremental) { + delete_file(path + ".ibd.delta", true); + delete_file(path + ".ibd.meta", true); + } + else { + delete_file(path + ".ibd", true); + } + delete_file(del_file); + return TRUE; +} + /** Implement --prepare @return whether the operation succeeded */ static bool @@ -4913,6 +5373,21 @@ xtrabackup_prepare_func(char** argv) } msg("mariabackup: cd to %s\n", xtrabackup_real_target_dir); + fil_path_to_mysql_datadir = "."; + + if (xtrabackup_incremental_dir) { + xb_process_datadir(xtrabackup_incremental_dir, ".new.meta", prepare_handle_new_files); + xb_process_datadir(xtrabackup_incremental_dir, ".new.delta", prepare_handle_new_files); + } + else { + xb_process_datadir(".", ".new", prepare_handle_new_files); + } + xb_process_datadir(xtrabackup_incremental_dir? xtrabackup_incremental_dir:".", + ".ren", prepare_handle_ren_files); + xb_process_datadir(xtrabackup_incremental_dir ? xtrabackup_incremental_dir : ".", + ".del", prepare_handle_del_files); + + int argc; for (argc = 0; argv[argc]; argc++) {} encryption_plugin_prepare_init(argc, argv); @@ -5203,7 +5678,6 @@ xb_init() return(false); } - encryption_plugin_backup_init(mysql_connection); history_start_time = time(NULL); } @@ -5261,7 +5735,7 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) srv_operation = SRV_OPERATION_RESTORE; files_charset_info = &my_charset_utf8_general_ci; - check_if_backup_includes = backup_includes; + setup_error_messages(); sys_var_init(); diff --git a/extra/perror.c b/extra/perror.c index 3bc5120db48..bd62401c8b2 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -105,11 +105,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case 'V': print_version(); + my_end(0); exit(0); break; case 'I': case '?': usage(); + my_end(0); exit(0); break; } @@ -122,7 +124,10 @@ static int get_options(int *argc,char ***argv) int ho_error; if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) + { + my_end(0); exit(ho_error); + } if (!*argc && !print_all_codes) { @@ -260,7 +265,10 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); if (get_options(&argc,&argv)) + { + my_end(0); exit(1); + } my_handler_error_register(); diff --git a/extra/resolveip.c b/extra/resolveip.c index b6840d9d463..20941a05257 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -79,6 +79,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'I': case '?': usage(); + my_end(0); exit(0); } return 0; @@ -91,7 +92,10 @@ static int get_options(int *argc,char ***argv) int ho_error; if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) + { + my_end(0); exit(ho_error); + } if (*argc == 0) { @@ -113,10 +117,14 @@ int main(int argc, char **argv) MY_INIT(argv[0]); if (get_options(&argc,&argv)) + { + my_end(0); exit(1); + } while (argc--) { + my_bool do_more; #ifndef WIN32 struct in_addr addr; #endif @@ -125,13 +133,13 @@ int main(int argc, char **argv) /* Not compatible with IPv6! Probably should use getnameinfo(). */ #ifdef WIN32 taddr = inet_addr(ip); - if(taddr != INADDR_NONE) - { + do_more= (taddr != INADDR_NONE); #else - if (inet_aton(ip, &addr) != 0) - { + if ((do_more= (inet_aton(ip, &addr) != 0))) taddr= addr.s_addr; #endif + if (do_more) + { if (taddr == htonl(INADDR_BROADCAST)) { puts("Broadcast"); @@ -205,5 +213,6 @@ int main(int argc, char **argv) } } } + my_end(0); exit(error); } diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt index c456af9be15..0e28da012ae 100644 --- a/extra/yassl/CMakeLists.txt +++ b/extra/yassl/CMakeLists.txt @@ -20,9 +20,6 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL) ADD_DEFINITIONS(${SSL_DEFINES}) -#Remove -fno-implicit-templates -#(yassl sources cannot be compiled with it) -STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) SET(YASSL_SOURCES src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp src/handshake.cpp src/lock.cpp src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp src/yassl_imp.cpp src/yassl_int.cpp) diff --git a/include/m_ctype.h b/include/m_ctype.h index fc51ebd3c8b..a4aa5b51218 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -370,7 +370,7 @@ typedef int (*my_charset_conv_mb_wc)(CHARSET_INFO *, my_wc_t *, typedef int (*my_charset_conv_wc_mb)(CHARSET_INFO *, my_wc_t, uchar *, uchar *); typedef size_t (*my_charset_conv_case)(CHARSET_INFO *, - char *, size_t, char *, size_t); + const char *, size_t, char *, size_t); /* A structure to return the statistics of a native string copying, @@ -725,9 +725,11 @@ size_t my_copy_fix_mb(CHARSET_INFO *cs, /* Functions for 8bit */ extern size_t my_caseup_str_8bit(CHARSET_INFO *, char *); extern size_t my_casedn_str_8bit(CHARSET_INFO *, char *); -extern size_t my_caseup_8bit(CHARSET_INFO *, char *src, size_t srclen, +extern size_t my_caseup_8bit(CHARSET_INFO *, + const char *src, size_t srclen, char *dst, size_t dstlen); -extern size_t my_casedn_8bit(CHARSET_INFO *, char *src, size_t srclen, +extern size_t my_casedn_8bit(CHARSET_INFO *, + const char *src, size_t srclen, char *dst, size_t dstlen); extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *); @@ -821,17 +823,17 @@ int my_charlen_8bit(CHARSET_INFO *, const uchar *str, const uchar *end); /* Functions for multibyte charsets */ extern size_t my_caseup_str_mb(CHARSET_INFO *, char *); extern size_t my_casedn_str_mb(CHARSET_INFO *, char *); -extern size_t my_caseup_mb(CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_casedn_mb(CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_caseup_mb_varlen(CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_casedn_mb_varlen(CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_caseup_ujis(CHARSET_INFO *, char *src, size_t srclen, +extern size_t my_caseup_mb(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_mb(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_caseup_ujis(CHARSET_INFO *, + const char *src, size_t srclen, char *dst, size_t dstlen); -extern size_t my_casedn_ujis(CHARSET_INFO *, char *src, size_t srclen, +extern size_t my_casedn_ujis(CHARSET_INFO *, + const char *src, size_t srclen, char *dst, size_t dstlen); extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *); diff --git a/include/sql_common.h b/include/sql_common.h index bbf459e1e55..ca7d2618bb9 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -1,7 +1,7 @@ #ifndef SQL_COMMON_INCLUDED #define SQL_COMMON_INCLUDED -/* Copyright (c) 2003, 2012, Oracle and/or its affiliates. - Copyright (c) 2010, 2012, Monty Program Ab +/* Copyright (c) 2003, 2018, Oracle and/or its affiliates. + Copyright (c) 2010, 2018, 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/libmariadb b/libmariadb -Subproject ebf5db6cd0c7d10b0632a1389faa9731e3c09cf +Subproject b948553b3464d37240c4d129fae47ce147e6dab diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index d7450eb3e87..99b620882de 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -155,8 +155,7 @@ SET(LIBS # (with corresponding target ${engine}_embedded) SET(EMBEDDED_LIBS) FOREACH(LIB ${LIBS}) - GET_TARGET_PROPERTY(EMBEDDED_LOCATION ${LIB}_embedded LOCATION) - IF(EMBEDDED_LOCATION) + IF(TARGET ${LIB}_embedded) LIST(APPEND EMBEDDED_LIBS ${LIB}_embedded) ELSE() LIST(APPEND EMBEDDED_LIBS ${LIB}) diff --git a/mysql-test/include/ctype_mdev13118.inc b/mysql-test/include/ctype_mdev13118.inc new file mode 100644 index 00000000000..efcb57299df --- /dev/null +++ b/mysql-test/include/ctype_mdev13118.inc @@ -0,0 +1,15 @@ +--echo # +--echo # MDEV-13118 Wrong results with LOWER and UPPER and subquery +--echo # + +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +--sorted_result +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +--sorted_result +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index 110cf8a20e0..29c47028b31 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -112,6 +112,8 @@ sub check_socket_path_length { return 0 if ($^O eq 'aix'); # See Debian bug #670722 - failing on kFreeBSD even after setting short path return 0 if $^O eq 'gnukfreebsd' and length $path < 40; + # GNU/Hurd doesn't have hostpath(), but no limitation either + return 0 if $^O eq 'gnu'; require IO::Socket::UNIX; diff --git a/mysql-test/main/bootstrap.test b/mysql-test/main/bootstrap.test index 7c5586a8784..d75be403f13 100644 --- a/mysql-test/main/bootstrap.test +++ b/mysql-test/main/bootstrap.test @@ -114,4 +114,14 @@ EOF --source include/kill_mysqld.inc --exec $MYSQLD_BOOTSTRAP_CMD --ignore-db-dirs='some_dir' --ignore-db-dirs='some_dir' < $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql + +# +# MDEV-13397 MariaDB upgrade fail when using default_time_zone +# +--write_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql +use test; +EOF +--exec $MYSQLD_BOOTSTRAP_CMD --default-time-zone=Europe/Moscow < $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 +--remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql + --source include/start_mysqld.inc diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result index 0afe5298411..8059e02611e 100644 --- a/mysql-test/main/ctype_binary.result +++ b/mysql-test/main/ctype_binary.result @@ -3048,6 +3048,29 @@ DROP TABLE t1; SELECT _binary 0x7E, _binary X'7E', _binary B'01111110'; _binary 0x7E _binary X'7E' _binary B'01111110' ~ ~ ~ +SET NAMES utf8, character_set_connection=binary; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varbinary(10) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +abcdefghi-abcdefghi +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_binary.test b/mysql-test/main/ctype_binary.test index 8da4eaff572..155d8548f77 100644 --- a/mysql-test/main/ctype_binary.test +++ b/mysql-test/main/ctype_binary.test @@ -24,6 +24,9 @@ SET NAMES binary; --echo # SELECT _binary 0x7E, _binary X'7E', _binary B'01111110'; +SET NAMES utf8, character_set_connection=binary; +--source include/ctype_mdev13118.inc + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_eucjpms.result b/mysql-test/main/ctype_eucjpms.result index bc7b4b9ef9d..507d0021a1f 100644 --- a/mysql-test/main/ctype_eucjpms.result +++ b/mysql-test/main/ctype_eucjpms.result @@ -33844,6 +33844,29 @@ HEX(a) CHAR_LENGTH(a) DROP TABLE t1; SELECT _eucjpms 0x8EA0; ERROR HY000: Invalid eucjpms character string: '8EA0' +SET NAMES eucjpms; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET eucjpms DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_eucjpms.test b/mysql-test/main/ctype_eucjpms.test index c69abc32a03..867ca809dbf 100644 --- a/mysql-test/main/ctype_eucjpms.test +++ b/mysql-test/main/ctype_eucjpms.test @@ -537,6 +537,8 @@ DROP TABLE t1; --error ER_INVALID_CHARACTER_STRING SELECT _eucjpms 0x8EA0; +SET NAMES eucjpms; +--source include/ctype_mdev13118.inc --echo # --echo # End of 10.0 tests diff --git a/mysql-test/main/ctype_euckr.result b/mysql-test/main/ctype_euckr.result index 3fb6f98b2eb..cc50ddd20be 100644 --- a/mysql-test/main/ctype_euckr.result +++ b/mysql-test/main/ctype_euckr.result @@ -25405,6 +25405,35 @@ A1A1A1A1A1A120202020202020202020202020202020202020 # End of 5.6 tests # # +# Start of 10.0 tests +# +SET NAMES utf8, character_set_connection=euckr; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET euckr DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; +# +# End of 10.0 tests +# +# # Start of 10.2 tests # # diff --git a/mysql-test/main/ctype_euckr.test b/mysql-test/main/ctype_euckr.test index 950c60c47e5..46955360217 100644 --- a/mysql-test/main/ctype_euckr.test +++ b/mysql-test/main/ctype_euckr.test @@ -197,6 +197,16 @@ set collation_connection=euckr_bin; --echo # End of 5.6 tests --echo # +--echo # +--echo # Start of 10.0 tests +--echo # + +SET NAMES utf8, character_set_connection=euckr; +--source include/ctype_mdev13118.inc + +--echo # +--echo # End of 10.0 tests +--echo # --echo # --echo # Start of 10.2 tests diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index 6bbb9bb3094..4515b9fbdbf 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -5081,6 +5081,29 @@ E05C5B E05B DROP TABLE t1; # Start of ctype_E05C.inc +SET NAMES utf8, character_set_connection=gbk; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET gbk DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # MDEV-9886 Illegal mix of collations with a view comparing a field to a binary constant # diff --git a/mysql-test/main/ctype_gbk.test b/mysql-test/main/ctype_gbk.test index a3dc7f4af44..d9d0a4d0ee4 100644 --- a/mysql-test/main/ctype_gbk.test +++ b/mysql-test/main/ctype_gbk.test @@ -199,6 +199,9 @@ let $ctype_unescape_combinations=selected; SET NAMES gbk; --source include/ctype_E05C.inc +SET NAMES utf8, character_set_connection=gbk; +--source include/ctype_mdev13118.inc + --echo # --echo # MDEV-9886 Illegal mix of collations with a view comparing a field to a binary constant --echo # diff --git a/mysql-test/main/ctype_latin1.result b/mysql-test/main/ctype_latin1.result index d5906cb74dd..43a84275629 100644 --- a/mysql-test/main/ctype_latin1.result +++ b/mysql-test/main/ctype_latin1.result @@ -8022,6 +8022,29 @@ a 0 DROP VIEW v1; DROP TABLE t1; +SET NAMES latin1; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_latin1.test b/mysql-test/main/ctype_latin1.test index 38f147708b8..61df80e2186 100644 --- a/mysql-test/main/ctype_latin1.test +++ b/mysql-test/main/ctype_latin1.test @@ -262,6 +262,9 @@ SELECT * FROM v1; DROP VIEW v1; DROP TABLE t1; +SET NAMES latin1; +--source include/ctype_mdev13118.inc + --echo # --echo # End of 10.0 tests diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index a68309831c6..5641726a831 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -5690,6 +5690,29 @@ c2 YWJjZGVmZ2hp-YWJjZGVmZ2hp DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; +SET NAMES utf8, character_set_connection=ucs2; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET ucs2 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index 9592e27f8e1..d0d463c0340 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -992,6 +992,10 @@ DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; +SET NAMES utf8, character_set_connection=ucs2; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_ujis.result b/mysql-test/main/ctype_ujis.result index cb9de83fedc..0b1cf606f0b 100644 --- a/mysql-test/main/ctype_ujis.result +++ b/mysql-test/main/ctype_ujis.result @@ -26149,6 +26149,29 @@ HEX(a) CHAR_LENGTH(a) DROP TABLE t1; SELECT _ujis 0x8EA0; ERROR HY000: Invalid ujis character string: '8EA0' +SET NAMES ujis; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET ujis DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_ujis.test b/mysql-test/main/ctype_ujis.test index ff9c61c05ba..cf247763b46 100644 --- a/mysql-test/main/ctype_ujis.test +++ b/mysql-test/main/ctype_ujis.test @@ -1368,6 +1368,10 @@ DROP TABLE t1; SELECT _ujis 0x8EA0; +SET NAMES ujis; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_utf16.result b/mysql-test/main/ctype_utf16.result index 8de21a14bd9..a105017b726 100644 --- a/mysql-test/main/ctype_utf16.result +++ b/mysql-test/main/ctype_utf16.result @@ -2142,6 +2142,29 @@ EXECUTE stmt USING @arg00; CONCAT(_utf16'a' COLLATE utf16_unicode_ci, ?) aÿ DEALLOCATE PREPARE stmt; +SET NAMES utf8, character_set_connection=utf16; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET utf16 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_utf16.test b/mysql-test/main/ctype_utf16.test index 526f5251055..504e62e3e89 100644 --- a/mysql-test/main/ctype_utf16.test +++ b/mysql-test/main/ctype_utf16.test @@ -870,6 +870,11 @@ SET @arg00=_binary 0x00FF; EXECUTE stmt USING @arg00; DEALLOCATE PREPARE stmt; + +SET NAMES utf8, character_set_connection=utf16; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_utf16le.result b/mysql-test/main/ctype_utf16le.result index 0fedff7d3bf..6d8d7ddca2a 100644 --- a/mysql-test/main/ctype_utf16le.result +++ b/mysql-test/main/ctype_utf16le.result @@ -2326,6 +2326,35 @@ DFFFFFDFFFFF9CFFFF9DFFFF9EFFFF # End of 5.6 tests # # +# Start of 10.0 tests +# +SET NAMES utf8, character_set_connection=utf16le; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET utf16le DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; +# +# Start of 10.0 tests +# +# # Start of 10.1 tests # # diff --git a/mysql-test/main/ctype_utf16le.test b/mysql-test/main/ctype_utf16le.test index 79cf875852a..b8728b52db2 100644 --- a/mysql-test/main/ctype_utf16le.test +++ b/mysql-test/main/ctype_utf16le.test @@ -747,6 +747,19 @@ SET NAMES utf8, collation_connection=utf16le_bin; --echo # End of 5.6 tests --echo # + +--echo # +--echo # Start of 10.0 tests +--echo # + + +SET NAMES utf8, character_set_connection=utf16le; +--source include/ctype_mdev13118.inc + +--echo # +--echo # Start of 10.0 tests +--echo # + --echo # --echo # Start of 10.1 tests --echo # diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index 59ce4c2f445..28b9caf6ffe 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -2241,6 +2241,29 @@ EXECUTE stmt USING @arg00; CONCAT(_utf32'a' COLLATE utf32_unicode_ci, ?) aÿ DEALLOCATE PREPARE stmt; +SET NAMEs utf8, character_set_connection=utf32; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET utf32 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test index 6f036898d15..2e739ebfdbc 100644 --- a/mysql-test/main/ctype_utf32.test +++ b/mysql-test/main/ctype_utf32.test @@ -983,6 +983,14 @@ SET @arg00=_binary 0x00FF; EXECUTE stmt USING @arg00; DEALLOCATE PREPARE stmt; + +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET NAMEs utf8, character_set_connection=utf32; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index 10d0efeff3c..d696ff78831 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -10286,6 +10286,29 @@ SELECT * FROM v1; c ß DROP VIEW v1; +SET NAMES utf8; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_utf8.test b/mysql-test/main/ctype_utf8.test index 20a60d370a0..6f8657dacb5 100644 --- a/mysql-test/main/ctype_utf8.test +++ b/mysql-test/main/ctype_utf8.test @@ -1890,6 +1890,13 @@ SELECT * FROM v1; DROP VIEW v1; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET NAMES utf8; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/ctype_utf8mb4.result b/mysql-test/main/ctype_utf8mb4.result index 7e5e99354ea..27ffd5552fa 100644 --- a/mysql-test/main/ctype_utf8mb4.result +++ b/mysql-test/main/ctype_utf8mb4.result @@ -3478,6 +3478,29 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; SET NAMES default; +SET NAMES utf8mb4; +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_latin1'derived_merge=on'; +CREATE TABLE t1 AS SELECT REPEAT('a', 10) AS t LIMIT 0; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` varchar(10) CHARACTER SET utf8mb4 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES ('abcdefghi'),('ABCDEFGHI'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LOWER(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UPPER(t) t2 FROM t1) sub; +c2 +ABCDEFGHI-ABCDEFGHI +ABCDEFGHI-ABCDEFGHI +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; # # End of 10.0 tests # diff --git a/mysql-test/main/ctype_utf8mb4.test b/mysql-test/main/ctype_utf8mb4.test index 545347fcd26..9cf87d12340 100644 --- a/mysql-test/main/ctype_utf8mb4.test +++ b/mysql-test/main/ctype_utf8mb4.test @@ -1959,6 +1959,14 @@ DROP TABLE t1; SET NAMES default; + +# +# MDEV-13118 Wrong results with LOWER and UPPER and subquery +# +SET NAMES utf8mb4; +--source include/ctype_mdev13118.inc + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result index a1dd1a77d3b..9874f16aa8a 100644 --- a/mysql-test/main/derived.result +++ b/mysql-test/main/derived.result @@ -1053,6 +1053,7 @@ INSERT INTO t2 VALUES (NULL),(NULL); CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; INSERT INTO t3 VALUES ('abc',NULL),('def',4); +set @save_join_cache_level= @@join_cache_level; SET join_cache_level= 8; explain SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; @@ -1082,6 +1083,38 @@ i drop procedure pr; drop view v1; drop table t1; +set @@join_cache_level= @save_join_cache_level; +# +# MDEV-16307: Incorrect results when using BNLH join instead of BNL join with views +# +CREATE TABLE t1 (c1 text, c2 int); +INSERT INTO t1 VALUES ('a',1), ('c',3), ('g',7), ('d',4), ('c',3); +CREATE TABLE t2 (c1 text, c2 int); +INSERT INTO t2 VALUES ('b',2), ('c',3); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +2 DERIVED t1 ALL NULL NULL NULL NULL 5 +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +c1 c2 c1 c2 +c 3 c 3 +c 3 c 3 +set @save_join_cache_level= @@join_cache_level; +set @@join_cache_level=4; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +1 PRIMARY <derived2> hash_ALL NULL #hash#$hj 3 test.t2.c1 5 Using where; Using join buffer (flat, BNLH join) +2 DERIVED t1 ALL NULL NULL NULL NULL 5 +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +c1 c2 c1 c2 +c 3 c 3 +c 3 c 3 +drop table t1,t2; +drop view v1; +set @@join_cache_level= @save_join_cache_level; # end of 5.5 # # Start of 10.1 tests diff --git a/mysql-test/main/derived.test b/mysql-test/main/derived.test index 466d79af409..6c51f23c51e 100644 --- a/mysql-test/main/derived.test +++ b/mysql-test/main/derived.test @@ -913,6 +913,7 @@ CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; INSERT INTO t3 VALUES ('abc',NULL),('def',4); +set @save_join_cache_level= @@join_cache_level; SET join_cache_level= 8; explain SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; @@ -935,7 +936,27 @@ call pr(2); drop procedure pr; drop view v1; drop table t1; +set @@join_cache_level= @save_join_cache_level; +--echo # +--echo # MDEV-16307: Incorrect results when using BNLH join instead of BNL join with views +--echo # + +CREATE TABLE t1 (c1 text, c2 int); +INSERT INTO t1 VALUES ('a',1), ('c',3), ('g',7), ('d',4), ('c',3); +CREATE TABLE t2 (c1 text, c2 int); +INSERT INTO t2 VALUES ('b',2), ('c',3); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; + +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +set @save_join_cache_level= @@join_cache_level; +set @@join_cache_level=4; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +drop table t1,t2; +drop view v1; +set @@join_cache_level= @save_join_cache_level; --echo # end of 5.5 --echo # diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index f882dbba466..2c983e3de3e 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -15960,3 +15960,123 @@ f c 9 1 DROP VIEW v1; DROP TABLE t1; +# +# MDEV-15087: error from inexpensive subquery before check +# for condition pushdown into derived +# +CREATE TABLE t1 (i1 int, v1 varchar(1)); +INSERT INTO t1 VALUES (7,'x'); +CREATE TABLE t2 (i1 int); +INSERT INTO t2 VALUES (8); +CREATE TABLE t3 (i1 int ,v1 varchar(1), v2 varchar(1)); +INSERT INTO t3 VALUES (4, 'v','v'),(62,'v','k'),(7, 'n', NULL); +SELECT 1 +FROM (t1 AS a1 +JOIN (((SELECT DISTINCT t3.* +FROM t3) AS a2 +JOIN t1 ON (t1.v1 = a2.v2))) ON (t1.v1 = a2.v1)) +WHERE (SELECT BIT_COUNT(t2.i1) +FROM (t2 JOIN t3)) IS NULL; +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1, t2, t3; +# +# MDEV-16614 signal 7 after calling stored procedure, that uses regexp +# +CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5)) +BEGIN +SELECT a FROM +(SELECT "aa" a) t +JOIN (SELECT "aa" b) t1 on t.a=t1.b +WHERE t.a regexp m1 and t1.b regexp m2 +GROUP BY a; +END$$ +CALL p1('a','a'); +a +aa +DROP PROCEDURE p1; +CREATE PROCEDURE p1(m1 varchar(5)) +BEGIN +SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1; +END$$ +CALL p1('a'); +a +aa +DROP PROCEDURE p1; +SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +a +aa +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN +RETURN 1; +END;$$ +CREATE OR REPLACE PROCEDURE p1(m1 varchar(5)) +BEGIN +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1); +END$$ +CALL p1('a'); +a +aa +DROP PROCEDURE p1; +DROP FUNCTION f1; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN +RETURN 1; +END;$$ +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +a +aa +DROP FUNCTION f1; +# +# MDEV-16801: splittable materialized derived/views with +# one grouping field from table without keys +# +CREATE TABLE t1 (a int, b int, INDEX idx_a(a), INDEX idx_b(b)) ENGINE=MYISAM; +CREATE TABLE t2 (c int) ENGINE=MYISAM; +CREATE TABLE t3 (d int) ENGINE=MYISAM; +INSERT INTO t1 VALUES +(77,7), (11,1), (33,3), (44,4), (8,88), +(78,7), (98,9), (38,3), (28,2), (79,7), +(58,5), (42,4), (71,7), (27,2), (91,9); +INSERT INTO t1 SELECT a+100, b+10 FROM t1; +INSERT INTO t2 VALUES +(100), (700), (200), (100), (200); +INSERT INTO t3 VALUES +(3), (4), (1), (8), (3); +ANALYZE tables t1,t2,t3; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +test.t3 analyze status OK +SELECT * +FROM t3, +(SELECT t1.b, t2.c +FROM t1, t2 +GROUP BY t1.b,t2.c) dt +WHERE t3.d = dt.b; +d b c +3 3 700 +3 3 200 +3 3 100 +4 4 700 +4 4 200 +4 4 100 +1 1 700 +1 1 200 +1 1 100 +3 3 700 +3 3 200 +3 3 100 +EXPLAIN EXTENDED SELECT * +FROM t3, +(SELECT t1.b, t2.c +FROM t1, t2 +GROUP BY t1.b,t2.c) dt +WHERE t3.d = dt.b; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 5 100.00 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t3.d 2 100.00 +2 LATERAL DERIVED t1 ref idx_b idx_b 5 test.t3.d 2 100.00 Using index; Using temporary; Using filesort +2 LATERAL DERIVED t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join) +Warnings: +Note 1003 /* select#1 */ select `test`.`t3`.`d` AS `d`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from `test`.`t3` join (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`b` = `test`.`t3`.`d` group by `test`.`t1`.`b`,`test`.`t2`.`c`) `dt` where `dt`.`b` = `test`.`t3`.`d` +DROP TABLE t1,t2,t3; diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index e51646a9764..b75c56e9ff2 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -2906,3 +2906,116 @@ SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; DROP VIEW v1; DROP TABLE t1; + +--echo # +--echo # MDEV-15087: error from inexpensive subquery before check +--echo # for condition pushdown into derived +--echo # + +CREATE TABLE t1 (i1 int, v1 varchar(1)); +INSERT INTO t1 VALUES (7,'x'); + +CREATE TABLE t2 (i1 int); +INSERT INTO t2 VALUES (8); + +CREATE TABLE t3 (i1 int ,v1 varchar(1), v2 varchar(1)); +INSERT INTO t3 VALUES (4, 'v','v'),(62,'v','k'),(7, 'n', NULL); + +--error ER_SUBQUERY_NO_1_ROW +SELECT 1 +FROM (t1 AS a1 + JOIN (((SELECT DISTINCT t3.* + FROM t3) AS a2 + JOIN t1 ON (t1.v1 = a2.v2))) ON (t1.v1 = a2.v1)) +WHERE (SELECT BIT_COUNT(t2.i1) + FROM (t2 JOIN t3)) IS NULL; + +DROP TABLE t1, t2, t3; + +--echo # +--echo # MDEV-16614 signal 7 after calling stored procedure, that uses regexp +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5)) +BEGIN +SELECT a FROM + (SELECT "aa" a) t + JOIN (SELECT "aa" b) t1 on t.a=t1.b +WHERE t.a regexp m1 and t1.b regexp m2 +GROUP BY a; +END$$ +DELIMITER ;$$ +CALL p1('a','a'); +DROP PROCEDURE p1; + + +DELIMITER $$; +CREATE PROCEDURE p1(m1 varchar(5)) +BEGIN + SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1; +END$$ +DELIMITER ;$$ +CALL p1('a'); +DROP PROCEDURE p1; + + +SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); + + +DELIMITER $$; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN + RETURN 1; +END;$$ +CREATE OR REPLACE PROCEDURE p1(m1 varchar(5)) +BEGIN + SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1); +END$$ +DELIMITER ;$$ +CALL p1('a'); +DROP PROCEDURE p1; +DROP FUNCTION f1; + + +DELIMITER $$; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN + RETURN 1; +END;$$ +DELIMITER ;$$ +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +DROP FUNCTION f1; + +--echo # +--echo # MDEV-16801: splittable materialized derived/views with +--echo # one grouping field from table without keys +--echo # + +CREATE TABLE t1 (a int, b int, INDEX idx_a(a), INDEX idx_b(b)) ENGINE=MYISAM; +CREATE TABLE t2 (c int) ENGINE=MYISAM; +CREATE TABLE t3 (d int) ENGINE=MYISAM; +INSERT INTO t1 VALUES + (77,7), (11,1), (33,3), (44,4), (8,88), + (78,7), (98,9), (38,3), (28,2), (79,7), + (58,5), (42,4), (71,7), (27,2), (91,9); +INSERT INTO t1 SELECT a+100, b+10 FROM t1; +INSERT INTO t2 VALUES + (100), (700), (200), (100), (200); +INSERT INTO t3 VALUES + (3), (4), (1), (8), (3); + +ANALYZE tables t1,t2,t3; + +let $q= +SELECT * + FROM t3, + (SELECT t1.b, t2.c + FROM t1, t2 + GROUP BY t1.b,t2.c) dt +WHERE t3.d = dt.b; + +eval $q; +eval EXPLAIN EXTENDED $q; + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index a7e8b5c9e59..cc3764c9ed2 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -761,6 +761,36 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; # +# MDEV-16054 simple json functions flatline cpu on garbage input. +# +select json_array(1,uuid(),compress(5.140264e+307)); +json_array(1,uuid(),compress(5.140264e+307)) +NULL +# +# MDEV-16869 String functions don't respect character set of JSON_VALUE. +# +create table t1(json_col TEXT) DEFAULT CHARSET=latin1; +insert into t1 values (_latin1 X'7B226B657931223A2253EC227D'); +select JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' from t1; +JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' +1 +select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' from t1; +REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' +1 +drop table t1; +# +# MDEV-16750 JSON_SET mishandles unicode every second pair of arguments. +# +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6); +JSON_SET('{}', '$.a', _utf8 0xC3B6) +{"a": "ö"} +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6); +JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6) +{"a": "ö", "b": "ö"} +SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6'); +JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6') +{"a": "ö", "x": 1, "b": "ö"} +# # End of 10.2 tests # # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 8d72e5afa59..4ef752e3d32 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -423,6 +423,30 @@ SHOW CREATE TABLE t1; DROP TABLE t1; --echo # +--echo # MDEV-16054 simple json functions flatline cpu on garbage input. +--echo # + +select json_array(1,uuid(),compress(5.140264e+307)); + +--echo # +--echo # MDEV-16869 String functions don't respect character set of JSON_VALUE. +--echo # + +create table t1(json_col TEXT) DEFAULT CHARSET=latin1; +insert into t1 values (_latin1 X'7B226B657931223A2253EC227D'); +select JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' from t1; +select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' from t1; +drop table t1; + +--echo # +--echo # MDEV-16750 JSON_SET mishandles unicode every second pair of arguments. +--echo # + +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6); +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6); +SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6'); + +--echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 075f5b9ec51..b6f9ca8e628 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -3554,6 +3554,38 @@ DROP FUNCTION fn_sleep_before_now; DROP TRIGGER trg_insert_t_ts; DROP TABLE t_ts, t_trig; # +# MDEV-16878 Functions ADDTIME and SUBTIME get wrongly removed from WHERE by the equal expression optimizer +# +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:10'),('00:00:20'); +SELECT a, SUBTIME(a,TIME'00:00:01'), ADDTIME(a,TIME'00:00:01') FROM t1; +a SUBTIME(a,TIME'00:00:01') ADDTIME(a,TIME'00:00:01') +00:00:10 00:00:09 00:00:11 +00:00:20 00:00:19 00:00:21 +SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09'; +a +00:00:10 +SELECT * FROM t1 WHERE ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +a +SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09' AND ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +a +EXPLAIN EXTENDED SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09' AND ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where subtime(`test`.`t1`.`a`,TIME'00:00:01') = TIME'00:00:09' and addtime(`test`.`t1`.`a`,TIME'00:00:01') <= TIME'00:00:09' +DROP TABLE t1; +# +# MDEV-15363 Wrong result for CAST(LAST_DAY(TIME'00:00:00') AS TIME) +# +SELECT +LAST_DAY(TIME'00:00:00') AS c1, +CAST(CAST(LAST_DAY(TIME'00:00:00') AS DATE) AS TIME) AS c2, +CAST(LAST_DAY(TIME'00:00:00') AS TIME) AS c3; +c1 c2 c3 +2018-08-31 00:00:00 00:00:00 +# End of 10.3 tests +# # MDEV-14032 SEC_TO_TIME executes side effect two times # SET @a=10000000; diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index f6f39d967f2..b03c14fb8ba 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -2141,6 +2141,31 @@ DROP TABLE t_ts, t_trig; --echo # +--echo # MDEV-16878 Functions ADDTIME and SUBTIME get wrongly removed from WHERE by the equal expression optimizer +--echo # + +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:10'),('00:00:20'); +SELECT a, SUBTIME(a,TIME'00:00:01'), ADDTIME(a,TIME'00:00:01') FROM t1; +SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09'; +SELECT * FROM t1 WHERE ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09' AND ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE SUBTIME(a,TIME'00:00:01')=TIME'00:00:09' AND ADDTIME(a,TIME'00:00:01')<=TIME'00:00:09'; +DROP TABLE t1; + + +--echo # +--echo # MDEV-15363 Wrong result for CAST(LAST_DAY(TIME'00:00:00') AS TIME) +--echo # + +SELECT + LAST_DAY(TIME'00:00:00') AS c1, + CAST(CAST(LAST_DAY(TIME'00:00:00') AS DATE) AS TIME) AS c2, + CAST(LAST_DAY(TIME'00:00:00') AS TIME) AS c3; + +--echo # End of 10.3 tests + +--echo # --echo # MDEV-14032 SEC_TO_TIME executes side effect two times --echo # diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index ff7ff2b3611..4b639bf969c 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -1759,6 +1759,7 @@ drop user mysqltest@localhost; disconnect user1; drop database mysqltest; use test; +call mtr.add_suppression("Can't open and lock privilege tables"); FLUSH PRIVILEGES without procs_priv table. RENAME TABLE mysql.procs_priv TO mysql.procs_gone; FLUSH PRIVILEGES; @@ -1852,8 +1853,6 @@ BEGIN SET @x = 0; REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; END ;|| -Warnings: -Warning 1404 Failed to grant EXECUTE and ALTER ROUTINE privileges connection default; SHOW GRANTS FOR 'user1'@'localhost'; Grants for user1@localhost @@ -1864,6 +1863,7 @@ SHOW GRANTS FOR 'user2'; Grants for user2@% GRANT USAGE ON *.* TO 'user2'@'%' GRANT CREATE, CREATE ROUTINE ON `db1`.* TO 'user2'@'%' +GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `db1`.`proc2` TO 'user2'@'%' disconnect con1; disconnect con2; DROP PROCEDURE db1.proc1; diff --git a/mysql-test/main/grant.test b/mysql-test/main/grant.test index cb4254fe8c6..c3bb987acc8 100644 --- a/mysql-test/main/grant.test +++ b/mysql-test/main/grant.test @@ -1598,6 +1598,9 @@ use test; # # Bug#16470 crash on grant if old grant tables # + +call mtr.add_suppression("Can't open and lock privilege tables"); + --echo FLUSH PRIVILEGES without procs_priv table. RENAME TABLE mysql.procs_priv TO mysql.procs_gone; FLUSH PRIVILEGES; diff --git a/mysql-test/main/invisible_field_debug.result b/mysql-test/main/invisible_field_debug.result index 4c4ebffbdfc..b3c84d18333 100644 --- a/mysql-test/main/invisible_field_debug.result +++ b/mysql-test/main/invisible_field_debug.result @@ -369,3 +369,8 @@ t1 1 invisible 1 c A NULL NULL NULL YES BTREE t1 1 invisible_2 1 invisible A NULL NULL NULL YES BTREE drop table t1; set @old_debug= @@debug_dbug; +CREATE TABLE t1 (i INT ); +SET debug_dbug="+d,test_completely_invisible,test_invisible_index"; +CREATE TABLE t2 LIKE t1; +SET debug_dbug= DEFAULT; +DROP TABLE t1, t2; diff --git a/mysql-test/main/invisible_field_debug.test b/mysql-test/main/invisible_field_debug.test index 8674620e055..c1d6899d16e 100644 --- a/mysql-test/main/invisible_field_debug.test +++ b/mysql-test/main/invisible_field_debug.test @@ -270,3 +270,9 @@ explain select * from t1 where invisible =9; show indexes in t1; drop table t1; set @old_debug= @@debug_dbug; +## MDEV 15127 +CREATE TABLE t1 (i INT ); +SET debug_dbug="+d,test_completely_invisible,test_invisible_index"; +CREATE TABLE t2 LIKE t1; +SET debug_dbug= DEFAULT; +DROP TABLE t1, t2; diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result index 5978b261b3a..bd015ae351c 100644 --- a/mysql-test/main/join.result +++ b/mysql-test/main/join.result @@ -1506,6 +1506,46 @@ DROP VIEW v2; DROP TABLE t1,t2; SET optimizer_switch=@save_optimizer_switch; # +# MDEV-16512 +# Server crashes in find_field_in_table_ref on 2nd execution of SP referring to +# non-existing field +# +CREATE TABLE t (i INT); +CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +FLUSH TABLES; +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP TABLE t; +CREATE TABLE t (f INT); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP TABLE t; +CREATE TABLE t (i INT); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP PROCEDURE p; +DROP TABLE t; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, c INT); +CREATE TABLE t4 (a INT, c INT); +CREATE TABLE t5 (a INT, c INT); +CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a) +LEFT JOIN t5 USING (a)) USING (a); +CALL p1; +ERROR 23000: Column 'c' in field list is ambiguous +CALL p1; +ERROR 23000: Column 'c' in field list is ambiguous +DROP PROCEDURE p1; +DROP TABLE t1,t2,t3,t4,t5; +# +# End of MariaDB 5.5 tests +# +# # Bug #35268: Parser can't handle STRAIGHT_JOIN with USING # CREATE TABLE t1 (a int); diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test index e07a3665920..8a088de91cc 100644 --- a/mysql-test/main/join.test +++ b/mysql-test/main/join.test @@ -1161,6 +1161,59 @@ DROP TABLE t1,t2; SET optimizer_switch=@save_optimizer_switch; --echo # +--echo # MDEV-16512 +--echo # Server crashes in find_field_in_table_ref on 2nd execution of SP referring to +--echo # non-existing field +--echo # + +CREATE TABLE t (i INT); +CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f); +--error ER_BAD_FIELD_ERROR +CALL p; +--error ER_BAD_FIELD_ERROR +CALL p; +FLUSH TABLES; +--error ER_BAD_FIELD_ERROR +CALL p; +DROP TABLE t; + +# +# Fix the table definition to match the using +# + +CREATE TABLE t (f INT); +# +# The following shouldn't fail as the table is now matching the using +# +--error ER_BAD_FIELD_ERROR +CALL p; +DROP TABLE t; +CREATE TABLE t (i INT); +--error ER_BAD_FIELD_ERROR +CALL p; +DROP PROCEDURE p; +DROP TABLE t; + +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, c INT); +CREATE TABLE t4 (a INT, c INT); +CREATE TABLE t5 (a INT, c INT); +CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a) +LEFT JOIN t5 USING (a)) USING (a); +--error ER_NON_UNIQ_ERROR +CALL p1; +--error ER_NON_UNIQ_ERROR +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1,t2,t3,t4,t5; + +--echo # +--echo # End of MariaDB 5.5 tests +--echo # + + +--echo # --echo # Bug #35268: Parser can't handle STRAIGHT_JOIN with USING --echo # diff --git a/mysql-test/main/join_cache.result b/mysql-test/main/join_cache.result index eea397402ad..fde6e0fec6b 100644 --- a/mysql-test/main/join_cache.result +++ b/mysql-test/main/join_cache.result @@ -5925,6 +5925,39 @@ SET join_buffer_space_limit= default; set optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t4,t5,t2; # +# MDEV-16603: BNLH for query with materialized semi-join +# +set join_cache_level=4; +CREATE TABLE t1 ( i1 int, v1 varchar(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (7,'x'); +CREATE TABLE t2 (i1 int, v1 varchar(1), KEY v1 (v1,i1)) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(NULL,'x'),(1,'x'),(3,'x'),(5,'x'),(8,'x'),(48,'x'), +(228,'x'),(3,'y'),(1,'z'),(9,'z'); +CREATE TABLE temp +SELECT t1.i1 AS f1, t1.v1 AS f2 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1)); +SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); +f1 f2 +7 x +7 x +7 x +7 x +7 x +7 x +7 x +EXPLAIN EXTENDED SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1 100.00 +1 PRIMARY temp hash_ALL NULL #hash#$hj 9 test.t1.i1,test.t1.v1 7 100.00 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 1 100.00 Using where +2 MATERIALIZED t2 hash_index v1 #hash#v1:v1 4:9 test.t1.v1 10 10.00 Using index; Using join buffer (flat, BNLH join) +Warnings: +Note 1003 select `test`.`temp`.`f1` AS `f1`,`test`.`temp`.`f2` AS `f2` from `test`.`temp` semi join (`test`.`t2` join `test`.`t1`) where `test`.`temp`.`f1` = `test`.`t1`.`i1` and `test`.`t2`.`v1` = `test`.`t1`.`v1` and `test`.`temp`.`f2` = `test`.`t1`.`v1` +DROP TABLE t1,t2,temp; +SET join_cache_level = default; +# # MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins. # set join_cache_level=default; diff --git a/mysql-test/main/join_cache.test b/mysql-test/main/join_cache.test index b775725903c..df89fc30dee 100644 --- a/mysql-test/main/join_cache.test +++ b/mysql-test/main/join_cache.test @@ -3870,6 +3870,37 @@ set optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t4,t5,t2; --echo # +--echo # MDEV-16603: BNLH for query with materialized semi-join +--echo # + +--source include/have_innodb.inc + +set join_cache_level=4; + +CREATE TABLE t1 ( i1 int, v1 varchar(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (7,'x'); + +CREATE TABLE t2 (i1 int, v1 varchar(1), KEY v1 (v1,i1)) ENGINE=InnoDB; + +INSERT INTO t2 VALUES + (NULL,'x'),(1,'x'),(3,'x'),(5,'x'),(8,'x'),(48,'x'), + (228,'x'),(3,'y'),(1,'z'),(9,'z'); + +CREATE TABLE temp +SELECT t1.i1 AS f1, t1.v1 AS f2 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1)); + +let $q = +SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); + +eval $q; +eval EXPLAIN EXTENDED $q; + +DROP TABLE t1,t2,temp; + +SET join_cache_level = default; + +--echo # --echo # MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins. --echo # @@ -3958,5 +3989,4 @@ drop table t1, t2; set join_buffer_size = default; # The following command must be the last one the file -# this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index 6753349dece..9245111369f 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -2460,5 +2460,55 @@ id sid id 1 NULL NULL 2 NULL NULL drop table t1, t2; +# +# MDEV-16726: SELECT with STRAGHT JOIN containing NESTED RIGHT JOIN +# converted to INNER JOIN with first constant inner table +# +CREATE TABLE t1 ( +pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1), KEY v1 (v1,i1) +) engine=MyISAM; +INSERT INTO t1 VALUES +(8,3,'c','c'),(9,4,'z','z'),(10,3,'i','i'),(11,186,'x','x'), +(14,226,'m','m'),(15,133,'p','p'); +CREATE TABLE t2 ( +pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1) +) engine=MyISAM; +INSERT INTO t2 VALUES (10,6,'p','p'); +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +RIGHT JOIN +(t2,t1) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select straight_join 'p' AS `v2` from `test`.`t1` join `test`.`t1` `tb1` left join `test`.`t1` `tb2` on(multiple equal(NULL, NULL)) where 0 order by NULL +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM +(t2,t1) +LEFT JOIN +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select straight_join 'p' AS `v2` from `test`.`t1` join `test`.`t1` `tb1` left join `test`.`t1` `tb2` on(multiple equal(NULL, NULL)) where 0 order by NULL +SELECT STRAIGHT_JOIN DISTINCT t2.v2 +FROM +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +RIGHT JOIN +(t2,t1) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +v2 +DROP TABLE t1,t2; # end of 5.5 tests SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/main/join_outer.test b/mysql-test/main/join_outer.test index 34b0551a32e..6d20c089bd9 100644 --- a/mysql-test/main/join_outer.test +++ b/mysql-test/main/join_outer.test @@ -1992,6 +1992,54 @@ select * from t1 t on t.id=r.id ; drop table t1, t2; +--echo # +--echo # MDEV-16726: SELECT with STRAGHT JOIN containing NESTED RIGHT JOIN +--echo # converted to INNER JOIN with first constant inner table +--echo # + +CREATE TABLE t1 ( + pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1), KEY v1 (v1,i1) +) engine=MyISAM; +INSERT INTO t1 VALUES + (8,3,'c','c'),(9,4,'z','z'),(10,3,'i','i'),(11,186,'x','x'), + (14,226,'m','m'),(15,133,'p','p'); + +CREATE TABLE t2 ( + pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1) +) engine=MyISAM; +INSERT INTO t2 VALUES (10,6,'p','p'); + +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM + (t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) + RIGHT JOIN + (t2,t1) + ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; + +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM + (t2,t1) + LEFT JOIN + (t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) + ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; + +SELECT STRAIGHT_JOIN DISTINCT t2.v2 +FROM + (t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) + RIGHT JOIN + (t2,t1) + ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; + +DROP TABLE t1,t2; + --echo # end of 5.5 tests SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index 9ff501baf6a..cb582b1399f 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -2471,6 +2471,56 @@ id sid id 1 NULL NULL 2 NULL NULL drop table t1, t2; +# +# MDEV-16726: SELECT with STRAGHT JOIN containing NESTED RIGHT JOIN +# converted to INNER JOIN with first constant inner table +# +CREATE TABLE t1 ( +pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1), KEY v1 (v1,i1) +) engine=MyISAM; +INSERT INTO t1 VALUES +(8,3,'c','c'),(9,4,'z','z'),(10,3,'i','i'),(11,186,'x','x'), +(14,226,'m','m'),(15,133,'p','p'); +CREATE TABLE t2 ( +pk int PRIMARY KEY, i1 int, v1 varchar(1), v2 varchar(1) +) engine=MyISAM; +INSERT INTO t2 VALUES (10,6,'p','p'); +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +RIGHT JOIN +(t2,t1) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select straight_join 'p' AS `v2` from `test`.`t1` join `test`.`t1` `tb1` left join `test`.`t1` `tb2` on(multiple equal(NULL, NULL)) where 0 order by NULL +EXPLAIN EXTENDED +SELECT STRAIGHT_JOIN t2.v2 +FROM +(t2,t1) +LEFT JOIN +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select straight_join 'p' AS `v2` from `test`.`t1` join `test`.`t1` `tb1` left join `test`.`t1` `tb2` on(multiple equal(NULL, NULL)) where 0 order by NULL +SELECT STRAIGHT_JOIN DISTINCT t2.v2 +FROM +(t1 as tb1 LEFT JOIN t1 AS tb2 ON tb2.v1 = tb1.v2) +RIGHT JOIN +(t2,t1) +ON t1.pk = t2.pk AND t2.v2 = tb1.v1 +WHERE tb1.pk = 40 +ORDER BY tb1.i1; +v2 +DROP TABLE t1,t2; # end of 5.5 tests SET optimizer_switch=@save_optimizer_switch; set join_cache_level=default; diff --git a/mysql-test/main/rename.result b/mysql-test/main/rename.result index 3ee9dd593d4..da9e4b62ecd 100644 --- a/mysql-test/main/rename.result +++ b/mysql-test/main/rename.result @@ -144,3 +144,7 @@ select * from t2; a 1 drop table tmp,t2; +create table t1 (a int) engine=memory; +rename table t1 to non_existent.t2; +ERROR 42000: Unknown database 'non_existent' +drop table t1; diff --git a/mysql-test/main/rename.test b/mysql-test/main/rename.test index 67732d5b5b9..215ecbcbb18 100644 --- a/mysql-test/main/rename.test +++ b/mysql-test/main/rename.test @@ -141,3 +141,10 @@ select * from tmp; select * from t2; drop table tmp,t2; +# +# MDEV-11741 handler::ha_reset(): Assertion `bitmap_is_set_all(&table->s->all_set)' failed or server crash in mi_reset or buffer overrun or unexpected ER_CANT_REMOVE_ALL_FIELDS +# +create table t1 (a int) engine=memory; +--error ER_BAD_DB_ERROR +rename table t1 to non_existent.t2; +drop table t1; diff --git a/mysql-test/main/session_tracker_last_gtid.result b/mysql-test/main/session_tracker_last_gtid.result index 795d0aaa2a2..deffeca1333 100644 --- a/mysql-test/main/session_tracker_last_gtid.result +++ b/mysql-test/main/session_tracker_last_gtid.result @@ -2,7 +2,13 @@ # MDEV-15477: SESSION_SYSVARS_TRACKER does not track last_gtid # SET gtid_seq_no=1000; +-- Tracker : SESSION_TRACK_SCHEMA +-- test + SET @@session.session_track_system_variables='last_gtid'; +-- Tracker : SESSION_TRACK_SCHEMA +-- test + create table t1 (a int) engine=innodb; -- Tracker : SESSION_TRACK_SYSTEM_VARIABLES -- last_gtid diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index 190f8f78d23..8edb9e79b70 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -228,8 +228,6 @@ FLUSH PRIVILEGES; connect con1, localhost, mysqltest_1,,; connection con1; CREATE PROCEDURE p1(i INT) BEGIN END; -Warnings: -Warning 1404 Failed to grant EXECUTE and ALTER ROUTINE privileges disconnect con1; connection default; DROP PROCEDURE p1; diff --git a/mysql-test/main/stat_tables.result b/mysql-test/main/stat_tables.result index fcced761283..ceadb61feea 100644 --- a/mysql-test/main/stat_tables.result +++ b/mysql-test/main/stat_tables.result @@ -516,4 +516,133 @@ use test; drop database db1; drop database db2; drop table t1; +# +# MDEV-16552: [10.0] ASAN global-buffer-overflow in is_stat_table / statistics_for_tables_is_needed +# +SET use_stat_tables = PREFERABLY; +SELECT CONVERT_TZ( '1991-09-20 10:11:02', '+00:00', 'GMT' ); +CONVERT_TZ( '1991-09-20 10:11:02', '+00:00', 'GMT' ) +NULL +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +pk c +1 foo +2 bar +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +pk a +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +pk c +1 foo +2 bar +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +pk a +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +SELECT MAX(pk) FROM t1; +MAX(pk) +NULL +DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/main/stat_tables.test b/mysql-test/main/stat_tables.test index bd77dec2b77..2cb6b55f665 100644 --- a/mysql-test/main/stat_tables.test +++ b/mysql-test/main/stat_tables.test @@ -305,4 +305,116 @@ drop database db1; drop database db2; drop table t1; +--echo # +--echo # MDEV-16552: [10.0] ASAN global-buffer-overflow in is_stat_table / statistics_for_tables_is_needed +--echo # + +SET use_stat_tables = PREFERABLY; +SELECT CONVERT_TZ( '1991-09-20 10:11:02', '+00:00', 'GMT' ); +set use_stat_tables=@save_use_stat_tables; + +--echo # +--echo # MDEV-16757: manual addition of min/max statistics for BLOB +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +--sorted_result +SELECT * FROM mysql.column_stats; +DELETE FROM mysql.column_stats + WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES + ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +--sorted_result +SELECT * FROM mysql.column_stats; + +SELECT pk FROM t1; + +DROP TABLE t1; + +set use_stat_tables=@save_use_stat_tables; + +--echo # +--echo # MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +SELECT * FROM t1; +SELECT * FROM mysql.column_stats; + +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +SELECT * FROM mysql.column_stats; + +DROP TABLE t1; + +set use_stat_tables=@save_use_stat_tables; + +--echo # +--echo # MDEV-16757: manual addition of min/max statistics for BLOB +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +--sorted_result +SELECT * FROM mysql.column_stats; +DELETE FROM mysql.column_stats + WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES + ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +--sorted_result +SELECT * FROM mysql.column_stats; + +SELECT pk FROM t1; + +DROP TABLE t1; + +set use_stat_tables=@save_use_stat_tables; + +--echo # +--echo # MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +SELECT * FROM t1; +SELECT * FROM mysql.column_stats; + +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +SELECT * FROM mysql.column_stats; + +DROP TABLE t1; + +set use_stat_tables=@save_use_stat_tables; + + +--echo # +--echo # MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); + +SELECT MAX(pk) FROM t1; + +DROP TABLE t1; + set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/main/stat_tables_innodb.result b/mysql-test/main/stat_tables_innodb.result index 42443bfcb72..7b98ca4259f 100644 --- a/mysql-test/main/stat_tables_innodb.result +++ b/mysql-test/main/stat_tables_innodb.result @@ -543,6 +543,135 @@ use test; drop database db1; drop database db2; drop table t1; +# +# MDEV-16552: [10.0] ASAN global-buffer-overflow in is_stat_table / statistics_for_tables_is_needed +# +SET use_stat_tables = PREFERABLY; +SELECT CONVERT_TZ( '1991-09-20 10:11:02', '+00:00', 'GMT' ); +CONVERT_TZ( '1991-09-20 10:11:02', '+00:00', 'GMT' ) +NULL +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +pk c +1 foo +2 bar +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +pk a +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk int PRIMARY KEY, c varchar(32)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +pk c +1 foo +2 bar +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL +CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); +SELECT * FROM t1; +pk a +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# +# MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +SELECT MAX(pk) FROM t1; +MAX(pk) +NULL +DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index d5034bc49b0..fb651fe6e2d 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -7237,6 +7237,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 37d57e51f1b..86ac9649d16 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -6098,6 +6098,21 @@ and t1.a in (select `test`.`t3`.`c` from `test`.`t3`); SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-16820: impossible where with inexpensive subquery +--echo # + +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); + +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); + +explain select * from t1 where (select max(b) from t2) = 10; +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; + +drop table t1,t2; + --echo End of 5.5 tests --echo # End of 10.0 tests diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index 39c0d1dd22b..e208dfe74c1 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -2391,6 +2391,99 @@ ec70316637232000158bbfc8bcbe5d60 ebb4620037332000158bbfc8bcbe5d89 DROP TABLE t1,t2,t3; set optimizer_switch=@save_optimizer_switch; +# +# MDEV-16751: Server crashes in st_join_table::cleanup or +# TABLE_LIST::is_with_table_recursive_reference with join_cache_level>2 +# +set @save_join_cache_level= @@join_cache_level; +set join_cache_level=4; +CREATE TABLE t1 ( id int NOT NULL); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL) ; +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +1 +1 +1 +1 +set @@join_cache_level= @save_join_cache_level; +alter table t1 add key(id); +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +1 +1 +1 +1 +drop table t1,t2; +# +# MDEV-15454: Nested SELECT IN returns wrong results +# +CREATE TABLE t1 ( a int NOT NULL PRIMARY KEY); +CREATE TABLE t2 ( a int, b int ); +INSERT INTO t2 VALUES (7878, 96),(3465, 96),(1403, 96),(4189, 96),(8732, 96), (5,96); +CREATE TABLE t3 (c int unsigned NOT NULL, b int unsigned NOT NULL, PRIMARY KEY (c,b)); +INSERT INTO t3 (c, b) VALUES (27, 96); +CREATE PROCEDURE prepare_data() +BEGIN +DECLARE i INT DEFAULT 1; +WHILE i < 1000 DO +INSERT INTO t1 (a) VALUES (i); +INSERT INTO t2 (a,b) VALUES (i,56); +INSERT INTO t3 (c,b) VALUES (i,i); +SET i = i + 1; +END WHILE; +END$$ +CALL prepare_data(); +SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27); +a +7878 +3465 +1403 +4189 +8732 +5 +set @save_optimizer_switch= @@optimizer_switch; +SET optimizer_switch='materialization=off'; +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; +a +5 +SET optimizer_switch='materialization=on'; +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; +a +5 +drop procedure prepare_data; +set @@optimizer_switch= @save_optimizer_switch; +drop table t1,t2,t3; +CREATE TABLE t1 ( id int NOT NULL, key(id)); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL); +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); +CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2; +explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +1 +1 +1 +1 +drop table t1,t2; +drop view v1; # End of 5.5 tests # # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT diff --git a/mysql-test/main/subselect_mat_cost_bugs.result b/mysql-test/main/subselect_mat_cost_bugs.result index 658722112d2..6377ae556d2 100644 --- a/mysql-test/main/subselect_mat_cost_bugs.result +++ b/mysql-test/main/subselect_mat_cost_bugs.result @@ -442,7 +442,7 @@ SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1 id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 2 DEPENDENT SUBQUERY t3 const PRIMARY PRIMARY 4 const 1 -2 DEPENDENT SUBQUERY t2 index NULL i2 11 NULL 2 Using where; Using index +2 DEPENDENT SUBQUERY t2 index i2 i2 11 NULL 2 Using where; Using index DROP TABLE t1,t2,t3; # # MDEV-7599: in-to-exists chosen after min/max optimization diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index afbd82fb359..655f3f4e9ce 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -7237,6 +7237,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 2e9caf22ca0..f766f5b6d6a 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -7230,6 +7230,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 2e82f98e01e..59dc3fd8328 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -7228,6 +7228,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 0dc83d85a74..6a8939aef3c 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -7243,6 +7243,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index 18333df11cb..b088bbc310d 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -7228,6 +7228,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result index 62248536e34..884451d7dff 100644 --- a/mysql-test/main/subselect_sj2_mat.result +++ b/mysql-test/main/subselect_sj2_mat.result @@ -1728,6 +1728,57 @@ id 13 drop table t1; # +# MDEV-15982: Incorrect results when subquery is materialized +# +CREATE TABLE `t1` (`id` int(32) NOT NULL primary key); +INSERT INTO `t1` VALUES +(45), (46), (47), (48), (49), (50), (51), (52), (53), (54), (55), (56), (57), (58), (59), (60), (61), (62), +(63), (64), (65), (66), (67), (68), (69), (70), (71), (72), (73), (74), (75), (76), (77), (78), (79), (80), +(81), (82), (83), (84), (85), (86), (87), (88), (89), (90), (91), (92),(93),(94),(95),(96), (97), (98), +(99), (100), (101), (102), (103), (104), (105), (106), (107), (108), (109), (110), (111), (112), (113), +(114), (115), (116), (117), (118), (119), (120), (121), (122), (123), (124), (125), (126), (127), (128), +(129), (130), (131), (132), (133), (134), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), +(147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), +(162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), +(174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (2), (3), (4), (5), (6), (19), (35), +(7), (20), (8), (36), (219), (22), (10), (23), (37), (11), (24); +CREATE TABLE `t2` (`type` int , `id` int(32) NOT NULL primary key); +INSERT INTO `t2` VALUES +(2,2),(2,3),(1,4),(2,5),(1,6),(1,19),(5,7),(1,20),(1,8),(1,21),(1,9), +(1,22),(2,10),(1,23),(2,11),(1,24),(1,12),(1,25),(2,13),(2,26),(2,14), +(2,27),(1,15),(1,28),(3,16),(1,29),(2,17),(1,30),(5,18),(2,1); +CREATE TABLE `t3` (`ref_id` int(32) unsigned ,`type` varchar(80),`id` int(32) NOT NULL ); +INSERT INTO `t3` VALUES +(1,'incident',31),(2,'faux pas',32), +(5,'oopsies',33),(3,'deniable',34), +(11,'wasntme',35),(10,'wasntme',36), +(17,'faux pas',37),(13,'unlikely',38), +(13,'improbable',39),(14,'incident',40), +(26,'problem',41),(14,'problem',42), +(26,'incident',43),(27,'incident',44); +explain +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 30 Using index +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 Using index +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 14 +2 MATERIALIZED t1 eq_ref PRIMARY PRIMARY 4 test.t3.id 1 Using index +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id +10 +11 +set optimizer_switch='materialization=off'; +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id +11 +10 +set optimizer_switch='materialization=on'; +DROP TABLE t1,t2,t3; +# # MDEV-15247: Crash when SET NAMES 'utf8' is set # CREATE TABLE t1 ( diff --git a/mysql-test/main/subselect_sj2_mat.test b/mysql-test/main/subselect_sj2_mat.test index bba436078e3..6ae687aa99a 100644 --- a/mysql-test/main/subselect_sj2_mat.test +++ b/mysql-test/main/subselect_sj2_mat.test @@ -347,6 +347,55 @@ WHERE ( drop table t1; --echo # +--echo # MDEV-15982: Incorrect results when subquery is materialized +--echo # + +CREATE TABLE `t1` (`id` int(32) NOT NULL primary key); +INSERT INTO `t1` VALUES +(45), (46), (47), (48), (49), (50), (51), (52), (53), (54), (55), (56), (57), (58), (59), (60), (61), (62), +(63), (64), (65), (66), (67), (68), (69), (70), (71), (72), (73), (74), (75), (76), (77), (78), (79), (80), +(81), (82), (83), (84), (85), (86), (87), (88), (89), (90), (91), (92),(93),(94),(95),(96), (97), (98), +(99), (100), (101), (102), (103), (104), (105), (106), (107), (108), (109), (110), (111), (112), (113), +(114), (115), (116), (117), (118), (119), (120), (121), (122), (123), (124), (125), (126), (127), (128), +(129), (130), (131), (132), (133), (134), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), +(147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), +(162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), +(174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (2), (3), (4), (5), (6), (19), (35), +(7), (20), (8), (36), (219), (22), (10), (23), (37), (11), (24); + +CREATE TABLE `t2` (`type` int , `id` int(32) NOT NULL primary key); +INSERT INTO `t2` VALUES +(2,2),(2,3),(1,4),(2,5),(1,6),(1,19),(5,7),(1,20),(1,8),(1,21),(1,9), +(1,22),(2,10),(1,23),(2,11),(1,24),(1,12),(1,25),(2,13),(2,26),(2,14), +(2,27),(1,15),(1,28),(3,16),(1,29),(2,17),(1,30),(5,18),(2,1); + +CREATE TABLE `t3` (`ref_id` int(32) unsigned ,`type` varchar(80),`id` int(32) NOT NULL ); +INSERT INTO `t3` VALUES +(1,'incident',31),(2,'faux pas',32), +(5,'oopsies',33),(3,'deniable',34), +(11,'wasntme',35),(10,'wasntme',36), +(17,'faux pas',37),(13,'unlikely',38), +(13,'improbable',39),(14,'incident',40), +(26,'problem',41),(14,'problem',42), +(26,'incident',43),(27,'incident',44); + +explain +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; + +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; + +set optimizer_switch='materialization=off'; + +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +set optimizer_switch='materialization=on'; + +DROP TABLE t1,t2,t3; + + +--echo # --echo # MDEV-15247: Crash when SET NAMES 'utf8' is set --echo # diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index b241be77df7..7630b0b9c0f 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -2431,6 +2431,99 @@ ec70316637232000158bbfc8bcbe5d60 ebb4620037332000158bbfc8bcbe5d89 DROP TABLE t1,t2,t3; set optimizer_switch=@save_optimizer_switch; +# +# MDEV-16751: Server crashes in st_join_table::cleanup or +# TABLE_LIST::is_with_table_recursive_reference with join_cache_level>2 +# +set @save_join_cache_level= @@join_cache_level; +set join_cache_level=4; +CREATE TABLE t1 ( id int NOT NULL); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL) ; +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +1 +1 +1 +1 +set @@join_cache_level= @save_join_cache_level; +alter table t1 add key(id); +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +1 +1 +1 +1 +drop table t1,t2; +# +# MDEV-15454: Nested SELECT IN returns wrong results +# +CREATE TABLE t1 ( a int NOT NULL PRIMARY KEY); +CREATE TABLE t2 ( a int, b int ); +INSERT INTO t2 VALUES (7878, 96),(3465, 96),(1403, 96),(4189, 96),(8732, 96), (5,96); +CREATE TABLE t3 (c int unsigned NOT NULL, b int unsigned NOT NULL, PRIMARY KEY (c,b)); +INSERT INTO t3 (c, b) VALUES (27, 96); +CREATE PROCEDURE prepare_data() +BEGIN +DECLARE i INT DEFAULT 1; +WHILE i < 1000 DO +INSERT INTO t1 (a) VALUES (i); +INSERT INTO t2 (a,b) VALUES (i,56); +INSERT INTO t3 (c,b) VALUES (i,i); +SET i = i + 1; +END WHILE; +END$$ +CALL prepare_data(); +SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27); +a +7878 +3465 +1403 +4189 +8732 +5 +set @save_optimizer_switch= @@optimizer_switch; +SET optimizer_switch='materialization=off'; +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; +a +5 +SET optimizer_switch='materialization=on'; +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; +a +5 +drop procedure prepare_data; +set @@optimizer_switch= @save_optimizer_switch; +drop table t1,t2,t3; +CREATE TABLE t1 ( id int NOT NULL, key(id)); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL); +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); +CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2; +explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 +1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +1 +1 +1 +1 +drop table t1,t2; +drop view v1; # End of 5.5 tests # # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 66c11b61435..7b8179bba38 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -2157,6 +2157,85 @@ eval $q; DROP TABLE t1,t2,t3; set optimizer_switch=@save_optimizer_switch; +--echo # +--echo # MDEV-16751: Server crashes in st_join_table::cleanup or +--echo # TABLE_LIST::is_with_table_recursive_reference with join_cache_level>2 +--echo # + +set @save_join_cache_level= @@join_cache_level; +set join_cache_level=4; +CREATE TABLE t1 ( id int NOT NULL); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); + +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL) ; +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); + +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); + +set @@join_cache_level= @save_join_cache_level; +alter table t1 add key(id); + +explain +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); +SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2); + +drop table t1,t2; + +--echo # +--echo # MDEV-15454: Nested SELECT IN returns wrong results +--echo # + +CREATE TABLE t1 ( a int NOT NULL PRIMARY KEY); + +CREATE TABLE t2 ( a int, b int ); +INSERT INTO t2 VALUES (7878, 96),(3465, 96),(1403, 96),(4189, 96),(8732, 96), (5,96); + +CREATE TABLE t3 (c int unsigned NOT NULL, b int unsigned NOT NULL, PRIMARY KEY (c,b)); +INSERT INTO t3 (c, b) VALUES (27, 96); + +DELIMITER $$; +CREATE PROCEDURE prepare_data() +BEGIN + DECLARE i INT DEFAULT 1; + WHILE i < 1000 DO + INSERT INTO t1 (a) VALUES (i); + INSERT INTO t2 (a,b) VALUES (i,56); + INSERT INTO t3 (c,b) VALUES (i,i); + SET i = i + 1; + END WHILE; +END$$ +DELIMITER ;$$ + +CALL prepare_data(); + +SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27); + +set @save_optimizer_switch= @@optimizer_switch; +SET optimizer_switch='materialization=off'; + +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; + +SET optimizer_switch='materialization=on'; + +SELECT t1.a FROM t1 +WHERE t1.a IN (SELECT t2.a FROM t2 WHERE t2.b IN (SELECT t3.b FROM t3 WHERE t3.c= 27)) LIMIT 5; + +drop procedure prepare_data; +set @@optimizer_switch= @save_optimizer_switch; +drop table t1,t2,t3; + +CREATE TABLE t1 ( id int NOT NULL, key(id)); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19); +CREATE TABLE t2 (i1 int NOT NULL, i2 int NOT NULL); +INSERT INTO t2 VALUES (11,11),(12,12),(13,13); +CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2; +explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1); +drop table t1,t2; +drop view v1; --echo # End of 5.5 tests --echo # --echo # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result index fe80f67045c..0c6ddd3675a 100644 --- a/mysql-test/main/union.result +++ b/mysql-test/main/union.result @@ -2149,6 +2149,22 @@ DROP VIEW v1; UNION (SELECT 2, 2); ERROR 42S02: Table 'test.v1' doesn't exist +# +# Bug#27197235 USER VARIABLE + UINON + DECIMAL COLUMN RETURNS +# WRONG VALUES +# +SET NAMES utf8; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; +a +1000003.0 +1.0 +SET NAMES latin1; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; +a +1000003.0 +1.0 End of 5.5 tests # # WL#1763 Avoid creating temporary table in UNION ALL diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test index d0a8e335d88..ca14731600e 100644 --- a/mysql-test/main/union.test +++ b/mysql-test/main/union.test @@ -1480,6 +1480,21 @@ DROP VIEW v1; UNION (SELECT 2, 2); +--echo # +--echo # Bug#27197235 USER VARIABLE + UINON + DECIMAL COLUMN RETURNS +--echo # WRONG VALUES +--echo # + +let $old_charset= `SELECT @@character_set_client`; + +SET NAMES utf8; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; + +eval SET NAMES $old_charset; +SET @advertAcctId = 1000003; +select @advertAcctId as a from dual union all select 1.0 from dual; + --echo End of 5.5 tests --echo # diff --git a/mysql-test/suite/binlog/include/check_binlog_size.inc b/mysql-test/suite/binlog/include/check_binlog_size.inc new file mode 100644 index 00000000000..9df161ec843 --- /dev/null +++ b/mysql-test/suite/binlog/include/check_binlog_size.inc @@ -0,0 +1,31 @@ +# This file runs the query and checks +# whether the size of binlog is increased or not +# If size is changed it issue die command +# Parameters +# $sql_query = query to run + +#Only last row of show binlog events matter +--let $tmp= 0 +--let $counter= 1 +while ($tmp != "No such row") +{ + --let $initial_binlog_size= $tmp + --let $tmp= query_get_value(show binary logs, File_size, $counter) + --inc $counter +} + +--eval $sql_query + +--let $tmp= 0 +--let $counter= 1 +while ($tmp != "No such row") +{ + --let $current_binlog_size= $tmp + --let $tmp= query_get_value(show binary logs, File_size, $counter) + --inc $counter +} + +if ($initial_binlog_size != $current_binlog_size) +{ + die "Binlog size changed"; +} diff --git a/mysql-test/suite/binlog/r/binlog_tmp_table_row.result b/mysql-test/suite/binlog/r/binlog_tmp_table_row.result new file mode 100644 index 00000000000..71bd75d89cb --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_tmp_table_row.result @@ -0,0 +1,7 @@ +RESET MASTER; +#Create table test +create temporary table t1(a int, b int); +#Add index test +create index index_a on t1(a); +#drop index test +drop index index_a on t1; diff --git a/mysql-test/suite/binlog/t/binlog_tmp_table_row.test b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test new file mode 100644 index 00000000000..ce11c880679 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test @@ -0,0 +1,30 @@ +# ==== Purpose ==== +# +# Test if statements used temporary tables are not binlogged in the case of +# binlog_format=row +# +# ==== Method ==== +# +# We will see if binlog file size is increased or not, It should be constant for the +# entire period of test. +# +# ==== Related bugs ==== +# +# Mdev-9266 +# +source include/have_log_bin.inc; +source include/have_binlog_format_row.inc; + +RESET MASTER; + +--echo #Create table test +--let $sql_query= create temporary table t1(a int, b int) +--source suite/binlog/include/check_binlog_size.inc + +--echo #Add index test +--let $sql_query= create index index_a on t1(a) +--source suite/binlog/include/check_binlog_size.inc + +--echo #drop index test +--let $sql_query= drop index index_a on t1 +--source suite/binlog/include/check_binlog_size.inc diff --git a/mysql-test/suite/compat/oracle/r/events.result b/mysql-test/suite/compat/oracle/r/events.result new file mode 100644 index 00000000000..7b4ad5679eb --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/events.result @@ -0,0 +1,16 @@ +set sql_mode='ORACLE'; +# +# MDEV-16891 EVENTs created with SQL_MODE=ORACLE fail to execute +# +SET GLOBAL event_scheduler=off; +SET sql_mode='ORACLE'; +CREATE TABLE t1 (a TIMESTAMP); +CREATE EVENT e1 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MICROSECOND +DO INSERT INTO t1 VALUES(NOW()); +SET GLOBAL event_scheduler=on; +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +DROP TABLE t1; +SET GLOBAL event_scheduler=off; diff --git a/mysql-test/suite/compat/oracle/t/events.test b/mysql-test/suite/compat/oracle/t/events.test new file mode 100644 index 00000000000..e898528636a --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/events.test @@ -0,0 +1,29 @@ +-- source include/not_embedded.inc + +set sql_mode='ORACLE'; + +--echo # +--echo # MDEV-16891 EVENTs created with SQL_MODE=ORACLE fail to execute +--echo # + +SET GLOBAL event_scheduler=off; + +SET sql_mode='ORACLE'; +CREATE TABLE t1 (a TIMESTAMP); +CREATE EVENT e1 + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MICROSECOND + DO INSERT INTO t1 VALUES(NOW()); +SET GLOBAL event_scheduler=on; + +let $wait_timeout = 10; +let $wait_condition = + SELECT COUNT(*) = 0 + FROM INFORMATION_SCHEMA.EVENTS + WHERE event_schema = 'test' AND event_name = 'e1'; +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; +DROP TABLE t1; + + +SET GLOBAL event_scheduler=off; diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 5d4e8fdf19d..f5452e0c8e8 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -125,13 +125,13 @@ def mysql innodb_index_stats sample_size 7 NULL YES bigint NULL NULL 20 0 NULL N def mysql innodb_index_stats stat_description 8 NULL NO varchar 1024 3072 NULL NULL NULL utf8 utf8_bin varchar(1024) select,insert,update,references NEVER NULL def mysql innodb_index_stats stat_name 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql innodb_index_stats stat_value 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL -def mysql innodb_index_stats table_name 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL +def mysql innodb_index_stats table_name 2 NULL NO varchar 199 597 NULL NULL NULL utf8 utf8_bin varchar(199) PRI select,insert,update,references NEVER NULL def mysql innodb_table_stats clustered_index_size 5 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql innodb_table_stats database_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql innodb_table_stats last_update 3 current_timestamp() NO timestamp NULL NULL NULL NULL 0 NULL NULL timestamp on update current_timestamp() select,insert,update,references NEVER NULL def mysql innodb_table_stats n_rows 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql innodb_table_stats sum_of_other_index_sizes 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL -def mysql innodb_table_stats table_name 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL +def mysql innodb_table_stats table_name 2 NULL NO varchar 199 597 NULL NULL NULL utf8 utf8_bin varchar(199) PRI select,insert,update,references NEVER NULL def mysql plugin dl 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select,insert,update,references NEVER NULL def mysql plugin name 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) PRI select,insert,update,references NEVER NULL def mysql proc aggregate 21 'NONE' NO enum 5 15 NULL NULL NULL utf8 utf8_general_ci enum('NONE','GROUP') select,insert,update,references NEVER NULL @@ -462,7 +462,7 @@ NULL mysql help_topic help_category_id smallint NULL NULL NULL NULL smallint(5) NULL mysql index_stats prefix_arity int NULL NULL NULL NULL int(11) unsigned NULL mysql index_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4) 3.0000 mysql innodb_index_stats database_name varchar 64 192 utf8 utf8_bin varchar(64) -3.0000 mysql innodb_index_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 mysql innodb_index_stats table_name varchar 199 597 utf8 utf8_bin varchar(199) 3.0000 mysql innodb_index_stats index_name varchar 64 192 utf8 utf8_bin varchar(64) NULL mysql innodb_index_stats last_update timestamp NULL NULL NULL NULL timestamp 3.0000 mysql innodb_index_stats stat_name varchar 64 192 utf8 utf8_bin varchar(64) @@ -470,7 +470,7 @@ NULL mysql innodb_index_stats stat_value bigint NULL NULL NULL NULL bigint(20) u NULL mysql innodb_index_stats sample_size bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql innodb_index_stats stat_description varchar 1024 3072 utf8 utf8_bin varchar(1024) 3.0000 mysql innodb_table_stats database_name varchar 64 192 utf8 utf8_bin varchar(64) -3.0000 mysql innodb_table_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 mysql innodb_table_stats table_name varchar 199 597 utf8 utf8_bin varchar(199) NULL mysql innodb_table_stats last_update timestamp NULL NULL NULL NULL timestamp NULL mysql innodb_table_stats n_rows bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql innodb_table_stats clustered_index_size bigint NULL NULL NULL NULL bigint(20) unsigned diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 322eff3506f..c3b5e070158 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -36,3 +36,4 @@ galera_kill_applier : race condition at the start of the test galera_ist_progress: MDEV-15236 galera_ist_progress fails when trying to read transfer status galera_concurrent_ctas : MDEV-15845 Test failure on galera.galera_concurrent_ctas pxc-421: Lock timeout exceeded +galera_sst_mysqldump_with_key : MDEV-16890 Galera test failure diff --git a/mysql-test/suite/galera/r/galera_bf_background_statistics.result b/mysql-test/suite/galera/r/galera_bf_background_statistics.result new file mode 100644 index 00000000000..c2c3fce2b14 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_background_statistics.result @@ -0,0 +1,33 @@ +SELECT @@innodb_stats_persistent; +@@innodb_stats_persistent +1 +CREATE TABLE t1 (f1 INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, f2 INTEGER DEFAULT 1) ENGINE=InnoDB; +INSERT INTO t1(f1) values (NULL); +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +SELECT count(1) from t1; +count(1) +16384 +connection node_2; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (9999999,NULL); +SELECT SLEEP(1000);; +connection node_1; +ALTER TABLE t1 CHANGE f2 f2 INTEGER NOT NULL DEFAULT 1; +connection node_2; +ERROR 40001: Deadlock: wsrep aborted transaction +wsrep_local_aborts_increment +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result index 93ab4a3f3d4..02dde169911 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result @@ -14,7 +14,7 @@ CREATE USER sslsst; GRANT ALL PRIVILEGES ON *.* TO sslsst; GRANT USAGE ON *.* TO sslsst REQUIRE SSL; SET GLOBAL wsrep_sst_auth = 'sslsst:'; -Performing State Transfer on a server that has been temporarily disconnected +Performing State Transfer on a server that has been shut down cleanly and restarted connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; @@ -34,8 +34,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; -Unloading wsrep provider ... -SET GLOBAL wsrep_provider = 'none'; +Shutting down server ... connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -51,7 +50,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -60,7 +59,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); connection node_2; -Loading wsrep provider ... +Starting server ... SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_after'); @@ -84,7 +83,7 @@ INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); COMMIT; -connection node_1a_galera_st_disconnect_slave; +connection node_1a_galera_st_shutdown_slave; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -109,6 +108,210 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; connection node_1; CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); DROP USER sst; diff --git a/mysql-test/suite/galera/t/galera_bf_background_statistics.opt b/mysql-test/suite/galera/t/galera_bf_background_statistics.opt new file mode 100644 index 00000000000..f9b1414a974 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_background_statistics.opt @@ -0,0 +1 @@ +--innodb_stats_persistent=ON diff --git a/mysql-test/suite/galera/t/galera_bf_background_statistics.test b/mysql-test/suite/galera/t/galera_bf_background_statistics.test new file mode 100644 index 00000000000..a9a98b1b567 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_background_statistics.test @@ -0,0 +1,49 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one while it is running a SLEEP() +# + +SELECT @@innodb_stats_persistent; + +CREATE TABLE t1 (f1 INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, f2 INTEGER DEFAULT 1) ENGINE=InnoDB; +INSERT INTO t1(f1) values (NULL); +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +INSERT INTO t1(f1) select NULL from t1; +SELECT count(1) from t1; + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +INSERT INTO t1 VALUES (9999999,NULL); +--send SELECT SLEEP(1000); + +--connection node_1 +ALTER TABLE t1 CHANGE f2 f2 INTEGER NOT NULL DEFAULT 1; + +--connection node_2 +--error ER_LOCK_DEADLOCK +--reap + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +# Check that wsrep_local_bf_aborts has been incremented by exactly 1 +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test index 0dbc63b531c..57244cb50c7 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test @@ -19,7 +19,12 @@ GRANT USAGE ON *.* TO sslsst REQUIRE SSL; SET GLOBAL wsrep_sst_auth = 'sslsst:'; ---source suite/galera/include/galera_st_disconnect_slave.inc +# We set the required mysqldump SST options here so that they are used every time the server is restarted during the test +--let $start_mysqld_params = --wsrep_sst_auth=sst:'sslsst:' --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2 --skip-grant-tables + +--source suite/galera/include/galera_st_shutdown_slave.inc +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc --source include/auto_increment_offset_restore.inc --source suite/galera/include/galera_sst_restore.inc diff --git a/mysql-test/suite/innodb/r/default_row_format_compatibility.result b/mysql-test/suite/innodb/r/default_row_format_compatibility.result index 765e25c776e..5070fa33a2e 100644 --- a/mysql-test/suite/innodb/r/default_row_format_compatibility.result +++ b/mysql-test/suite/innodb/r/default_row_format_compatibility.result @@ -25,7 +25,7 @@ SET GLOBAL innodb_default_row_format=Dynamic; CREATE TABLE tab(a INT) ENGINE=InnoDB; ALTER TABLE tab DISCARD TABLESPACE; ALTER TABLE tab IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1; .cfg file uses ROW_FORMAT=COMPACT) DROP TABLE tab; SET GLOBAL innodb_default_row_format=Compact; SELECT @@innodb_default_row_format; diff --git a/mysql-test/suite/innodb/r/innodb-wl5522.result b/mysql-test/suite/innodb/r/innodb-wl5522.result index 1ed857af473..62f03292baa 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522.result @@ -115,7 +115,7 @@ ALTER TABLE t2 DISCARD TABLESPACE; db.opt t2.frm ALTER TABLE t2 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1; .cfg file uses ROW_FORMAT=COMPACT) ALTER TABLE t2 IMPORT TABLESPACE; ERROR HY000: Schema mismatch (Expected FSP_SPACE_FLAGS=0x*, .ibd file contains 0x*.) DROP TABLE t2; @@ -603,7 +603,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x0) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x0; .cfg file uses ROW_FORMAT=REDUNDANT) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -615,7 +615,19 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x0) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x0; .cfg file uses ROW_FORMAT=REDUNDANT) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x29 and the meta-data file has 0x0; .cfg file uses ROW_FORMAT=REDUNDANT) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -789,7 +801,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x1; .cfg file uses ROW_FORMAT=COMPACT) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -801,7 +813,19 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x1; .cfg file uses ROW_FORMAT=COMPACT) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x29 and the meta-data file has 0x1; .cfg file uses ROW_FORMAT=COMPACT) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -978,7 +1002,7 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x21) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x21; .cfg file uses ROW_FORMAT=DYNAMIC) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -990,7 +1014,19 @@ SELECT * FROM t1; ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x21) +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x21; .cfg file uses ROW_FORMAT=DYNAMIC) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x29 and the meta-data file has 0x21; .cfg file uses ROW_FORMAT=DYNAMIC) unlink: t1.ibd unlink: t1.cfg DROP TABLE t1; @@ -1049,6 +1085,220 @@ c1 c2 42 1 43 1 DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +INSERT INTO t1(c2) VALUES(1); +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `idx` (`c2`) +) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +SELECT * FROM t1; +c1 c2 +1 1 +2 1 +3 1 +4 1 +6 1 +7 1 +8 1 +9 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 1 +43 1 +FLUSH TABLES t1 FOR EXPORT; +backup: t1 +UNLOCK TABLES; +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +unlink: t1.cfg +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `idx` (`c2`) +) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +SELECT * FROM t1; +c1 c2 +1 1 +2 1 +3 1 +4 1 +6 1 +7 1 +8 1 +9 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 1 +43 1 +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x0 and the meta-data file has 0x29; .cfg file uses ROW_FORMAT=COMPRESSED) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPACT; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x1 and the meta-data file has 0x29; .cfg file uses ROW_FORMAT=COMPRESSED) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x21 and the meta-data file has 0x29; .cfg file uses ROW_FORMAT=COMPRESSED) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB +ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +ERROR HY000: Schema mismatch (Table flags don't match, server table has 0x23 and the meta-data file has 0x29; .cfg file uses ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8) +unlink: t1.ibd +unlink: t1.cfg +DROP TABLE t1; +CREATE TABLE t1( +c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +SELECT * FROM t1; +ERROR HY000: Tablespace has been discarded for table `t1` +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +unlink: t1.cfg +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `idx` (`c2`) +) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +SELECT * FROM t1; +c1 c2 +1 1 +2 1 +3 1 +4 1 +6 1 +7 1 +8 1 +9 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 1 +43 1 +DROP TABLE t1; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index a70a3d077e0..bb15b665d49 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -446,6 +446,25 @@ ALTER TABLE t1 ADD COLUMN c INT; UPDATE t1 SET c = 1; UPDATE t1 SET c = 2; DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a)) +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET b=1; +ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD INDEX(a); +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try ALGORITHM=COPY +SET foreign_key_checks=0; +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a), +ALGORITHM=INSTANT; +SET foreign_key_checks=1; +ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk; +ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1; +DROP TABLE t2, t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -838,6 +857,25 @@ ALTER TABLE t1 ADD COLUMN c INT; UPDATE t1 SET c = 1; UPDATE t1 SET c = 2; DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPACT; +CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a)) +ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET b=1; +ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD INDEX(a); +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try ALGORITHM=COPY +SET foreign_key_checks=0; +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a), +ALGORITHM=INSTANT; +SET foreign_key_checks=1; +ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk; +ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1; +DROP TABLE t2, t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -1230,10 +1268,29 @@ ALTER TABLE t1 ADD COLUMN c INT; UPDATE t1 SET c = 1; UPDATE t1 SET c = 2; DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a)) +ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET b=1; +ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD INDEX(a); +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try ALGORITHM=COPY +SET foreign_key_checks=0; +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a), +ALGORITHM=INSTANT; +SET foreign_key_checks=1; +ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk; +ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1; +DROP TABLE t2, t1; disconnect analyze; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -39 +45 SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 389a04007e2..72e42763569 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -175,10 +175,65 @@ SET DEBUG_SYNC='now WAIT_FOR copied'; BEGIN; INSERT INTO t1 SET b=1; ROLLBACK; -disconnect stop_purge; +connection stop_purge; +COMMIT; +connection default; InnoDB 2 transactions not purged SET DEBUG_SYNC='now SIGNAL logged'; -disconnect ddl; +connection ddl; +connection default; DROP TABLE t1; SET DEBUG_SYNC='RESET'; +# +# MDEV-16131 Assertion failed in dict_index_t::instant_field_value() +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET a=0; +ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2, ADD COLUMN c INT; +connection stop_purge; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +ALTER TABLE t1 FORCE; +disconnect stop_purge; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +InnoDB 1 transactions not purged +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET a=2,b=3,c=4; +SET DEBUG_SYNC = 'now SIGNAL logged'; +connection ddl; +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; +a b c +1 2 NULL +2 3 4 +# +# MDEV-15872 Crash in online ALTER TABLE...ADD PRIMARY KEY +# after instant ADD COLUMN ... NULL +# +ALTER TABLE t1 ADD COLUMN d INT, ALGORITHM=INSTANT; +UPDATE t1 SET d=1; +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +ALTER IGNORE TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY (a,d); +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +INSERT INTO t1 SET a=3; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL logged'; +connection ddl; +ERROR 22004: Invalid use of NULL value +disconnect ddl; +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; +a b c d +1 2 NULL 1 +2 3 4 1 +DROP TABLE t1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result index 63172897927..8852bfd8e6a 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -72,7 +72,7 @@ DROP TABLE t1; Warnings: Warning 1932 Table 'test.t1' doesn't exist in engine DROP TABLE t2,t3; -FOUND 49 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err +FOUND 50 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err ib_buffer_pool ib_logfile0 ib_logfile1 diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result index 533d32089c3..94c2cfc63b1 100644 --- a/mysql-test/suite/innodb/r/temporary_table.result +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -650,6 +650,19 @@ SELECT * FROM t1; f1 0 DROP TABLE t1; +create procedure t1_proc() +begin +DECLARE var INT UNSIGNED; +CREATE TEMPORARY TABLE t1(f1 INT UNSIGNED, f2 INT UNSIGNED, KEY( f1, f2 ) )engine=innodb; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +INSERT INTO t1 SET f1 = 1, f2 = 1; +UPDATE t1 SET f2 = 2; +SET var = ( SELECT 1 FROM t1 ); +DROP TABLE t1; +END// +call t1_proc; +drop procedure t1_proc; # # MDEV-15874 CREATE TABLE creates extra transaction # diff --git a/mysql-test/suite/innodb/t/innodb-wl5522.test b/mysql-test/suite/innodb/t/innodb-wl5522.test index 66dfaac0996..24dad21b3af 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522.test @@ -485,7 +485,7 @@ SELECT * FROM t1; DROP TABLE t1; # -# Row format tests [EXPORT REDUNDANT - IMPORT COMPACT & DYNAMIC] +# EXPORT ROW_FORMAT=REDUNDANT # CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -587,6 +587,29 @@ EOF DROP TABLE t1; +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + # This should be OK. CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -615,7 +638,7 @@ SELECT * FROM t1; DROP TABLE t1; # -# Row format tests [EXPORT COMPACT - IMPORT REDUNDANT & DYNAMIC] +# EXPORT ROW_FORMAT=COMPACT # CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -717,6 +740,29 @@ EOF DROP TABLE t1; +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + # This should be OK. CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -746,7 +792,7 @@ SELECT * FROM t1; DROP TABLE t1; # -# Row format tests [EXPORT DYNAMIC- IMPORT REDUNDANT & DYNAMIC] +# EXPORT ROW_FORMAT=DYNAMIC # CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -848,6 +894,29 @@ EOF DROP TABLE t1; +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + # This should be OK. CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -876,6 +945,185 @@ SELECT * FROM t1; DROP TABLE t1; +# +# EXPORT ROW_FORMAT=COMPRESSED +# +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; + +INSERT INTO t1(c2) VALUES(1); +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; +INSERT INTO t1(c2) SELECT c2 FROM t1; + +SHOW CREATE TABLE t1; +SELECT * FROM t1; + +FLUSH TABLES t1 FOR EXPORT; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_backup_tablespaces("test", "t1"); +EOF + +UNLOCK TABLES; + +DROP TABLE t1; + +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; + +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +ALTER TABLE t1 IMPORT TABLESPACE; +CHECK TABLE t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_cleanup("test", "t1"); +EOF + +SHOW CREATE TABLE t1; +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; + +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPACT; + +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + + +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB + ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +--error ER_TABLE_SCHEMA_MISMATCH +ALTER TABLE t1 IMPORT TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_unlink_tablespace("test", "t1"); +EOF + +DROP TABLE t1; + +# This should be OK. +CREATE TABLE t1( + c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c2 INT, INDEX idx(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; + +ALTER TABLE t1 DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +SELECT * FROM t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +ALTER TABLE t1 IMPORT TABLESPACE; +CHECK TABLE t1; + +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_cleanup("test", "t1"); +EOF + +SHOW CREATE TABLE t1; +SELECT * FROM t1; + +DROP TABLE t1; + call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index c414b92f713..18c07bdac73 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -319,6 +319,27 @@ UPDATE t1 SET c = 1; UPDATE t1 SET c = 2; DROP TABLE t1; +# MDEV-16830 Crash in ALTER TABLE DROP FOREIGN KEY +eval CREATE TABLE t1 (a INT PRIMARY KEY) $engine; +eval CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY(b) REFERENCES t1(a)) +$engine; +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET b=1; +ALTER TABLE t2 ADD COLUMN a INT, DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD INDEX(a); +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +SET foreign_key_checks=0; +ALTER TABLE t1 ADD COLUMN b INT, ADD FOREIGN KEY(a) REFERENCES t2(a), +ALGORITHM=INSTANT; +ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a), +ALGORITHM=INSTANT; +SET foreign_key_checks=1; +ALTER TABLE t2 COMMENT 'domestic keys only', DROP FOREIGN KEY fk; +ALTER TABLE t1 DROP FOREIGN KEY t1_ibfk_1; +DROP TABLE t2, t1; + dec $format; } disconnect analyze; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 27056089767..cab9decd3d0 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -189,7 +189,9 @@ SET DEBUG_SYNC='now WAIT_FOR copied'; BEGIN; INSERT INTO t1 SET b=1; ROLLBACK; -disconnect stop_purge; +connection stop_purge; +COMMIT; +connection default; # Wait for purge to empty the table. let $wait_all_purged=2; @@ -197,8 +199,72 @@ let $wait_all_purged=2; let $wait_all_purged=0; SET DEBUG_SYNC='now SIGNAL logged'; -disconnect ddl; +connection ddl; +reap; +connection default; DROP TABLE t1; SET DEBUG_SYNC='RESET'; +--echo # +--echo # MDEV-16131 Assertion failed in dict_index_t::instant_field_value() +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET a=0; +ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2, ADD COLUMN c INT; + +connection stop_purge; +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1; + +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +send ALTER TABLE t1 FORCE; + +disconnect stop_purge; + +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +let $wait_all_purged = 1; +--source include/wait_all_purged.inc +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET a=2,b=3,c=4; +SET DEBUG_SYNC = 'now SIGNAL logged'; + +connection ddl; +reap; + +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; + +--echo # +--echo # MDEV-15872 Crash in online ALTER TABLE...ADD PRIMARY KEY +--echo # after instant ADD COLUMN ... NULL +--echo # +ALTER TABLE t1 ADD COLUMN d INT, ALGORITHM=INSTANT; +UPDATE t1 SET d=1; + +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +send ALTER IGNORE TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY (a,d); + +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +INSERT INTO t1 SET a=3; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL logged'; + +connection ddl; +--error ER_INVALID_USE_OF_NULL +reap; +disconnect ddl; + +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; +DROP TABLE t1; + SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index 52334b05999..8e3ddf95634 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -477,6 +477,23 @@ ROLLBACK; SELECT * FROM t1; DROP TABLE t1; +delimiter //; +create procedure t1_proc() +begin +DECLARE var INT UNSIGNED; +CREATE TEMPORARY TABLE t1(f1 INT UNSIGNED, f2 INT UNSIGNED, KEY( f1, f2 ) )engine=innodb; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +INSERT INTO t1 SET f1 = 1, f2 = 1; +UPDATE t1 SET f2 = 2; +SET var = ( SELECT 1 FROM t1 ); +DROP TABLE t1; +END// +delimiter ;// + +call t1_proc; +drop procedure t1_proc; + --echo # --echo # MDEV-15874 CREATE TABLE creates extra transaction --echo # diff --git a/mysql-test/suite/innodb_fts/r/fts_kill_query.result b/mysql-test/suite/innodb_fts/r/fts_kill_query.result new file mode 100644 index 00000000000..53ad9b3a37c --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/fts_kill_query.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 (a VARCHAR(7), b text, FULLTEXT KEY idx (a,b)) ENGINE=InnoDB; +COMMIT; +SELECT COUNT(*) FROM t1 +WHERE MATCH (a,b) AGAINST ('foo bar' IN BOOLEAN MODE); +connect con1,localhost,root,,; +KILL QUERY @id; +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/sync_ddl.result b/mysql-test/suite/innodb_fts/r/sync_ddl.result new file mode 100644 index 00000000000..441954dc77b --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/sync_ddl.result @@ -0,0 +1,105 @@ +CREATE TABLE t1 ( +id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET @save_debug = @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_sync_before_syncing,ib_trunc_sleep_before_fts_cache_clear'; +INSERT INTO t1 (value) VALUES +('By default or with the IN NATURAL LANGUAGE MODE modifier') +; +TRUNCATE TABLE t1; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; +CREATE TABLE t1 ( +id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_write_words_before_select_index,ib_trunc_sleep_before_fts_cache_clear'; +INSERT INTO t1 (value) VALUES +('By default or with the IN NATURAL LANGUAGE MODE modifier'), +('performs a natural language search for a string'), +('collection is a set of one or more columns included'), +('returns a relevance value; that is, a similarity measure'), +('and the text in that row in the columns named in'), +('By default, the search is performed in case-insensitive'), +('sensitive full-text search, use a binary collation '), +('example, a column that uses the latin1 character'), +('collation of latin1_bin to make it case sensitive') +; +TRUNCATE TABLE t1; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; +CREATE TABLE t1 ( +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; +INSERT INTO t1 (value) VALUES +('By default or with the IN NATURAL LANGUAGE MODE modifier'), +('performs a natural language search for a string'), +('collection is a set of one or more columns included'), +('returns a relevance value; that is, a similarity measure'), +('and the text in that row in the columns named in'), +('By default, the search is performed in case-insensitive'), +('sensitive full-text search, use a binary collation '), +('example, a column that uses the latin1 character'), +('collation of latin1_bin to make it case sensitive') +; +DROP INDEX idx1 ON t1; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; +CREATE TABLE t1 ( +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; +INSERT INTO t1 (value) VALUES +('By default or with the IN NATURAL LANGUAGE MODE modifier'), +('performs a natural language search for a string'), +('collection is a set of one or more columns included'), +('returns a relevance value; that is, a similarity measure'), +('and the text in that row in the columns named in'), +('By default, the search is performed in case-insensitive'), +('sensitive full-text search, use a binary collation '), +('example, a column that uses the latin1 character'), +('collation of latin1_bin to make it case sensitive') +; +ALTER TABLE t1 +DROP INDEX idx1, +ALGORITHM=INPLACE; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; +CREATE TABLE t1 ( +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; +INSERT INTO t1 (value) VALUES +('example, a column that uses the latin1 character'), +('collation of latin1_bin to make it case sensitive') +; +ALTER TABLE t1 +DROP INDEX idx1, +ALGORITHM=COPY; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; +CREATE TABLE t1 ( +id1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +value VARCHAR(1024) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx1 ON t1(value); +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; +INSERT INTO t1 (value) VALUES +('example, a column that uses the latin1 character'), +('collation of latin1_bin to make it case sensitive') +; +ALTER TABLE t1 +DROP COLUMN id1, +ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +DROP INDEX idx1, +ADD FULLTEXT INDEX idx2(value), +ALGORITHM=INPLACE; +DROP TABLE t1; +SET GLOBAL debug_dbug = @save_debug; diff --git a/mysql-test/suite/innodb_fts/t/fts_kill_query.test b/mysql-test/suite/innodb_fts/t/fts_kill_query.test new file mode 100644 index 00000000000..3dda29a3876 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/fts_kill_query.test @@ -0,0 +1,30 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 (a VARCHAR(7), b text, FULLTEXT KEY idx (a,b)) ENGINE=InnoDB; + +--disable_query_log +BEGIN; +let $n=1000; +while ($n) { +INSERT INTO t1 VALUES('foo bar','boo far'); +dec $n; +} +--enable_query_log +COMMIT; + +let $id = `SELECT CONNECTION_ID()`; +send SELECT COUNT(*) FROM t1 +WHERE MATCH (a,b) AGAINST ('foo bar' IN BOOLEAN MODE); + +connect (con1,localhost,root,,); +let $ignore= `SELECT @id := $ID`; +KILL QUERY @id; +disconnect con1; + +connection default; +# The following would return a result set if the KILL was not fast enough. +--disable_result_log +--error 0,ER_QUERY_INTERRUPTED,HA_ERR_ABORTED_BY_USER +reap; +--enable_result_log +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test b/mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test index 012881173e0..c8293655d1b 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test @@ -25,7 +25,7 @@ ALTER TABLE t1 ADD FULLTEXT INDEX idx_1 (a); ALTER TABLE t1 ADD FULLTEXT INDEX idx_2 (b); EVAL SHOW CREATE TABLE t1; -# check mutiple index with transaction +# check multiple index with transaction START TRANSACTION; # Insert rows INSERT INTO t1 (a,b) VALUES diff --git a/mysql-test/suite/innodb_fts/t/sync_ddl.test b/mysql-test/suite/innodb_fts/t/sync_ddl.test new file mode 100644 index 00000000000..2950297d5bb --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/sync_ddl.test @@ -0,0 +1,177 @@ +# +# BUG#27082268 FTS synchronization issues +# + +--source include/have_innodb.inc +--source include/have_debug.inc + +#-------------------------------------- +# Check FTS_sync vs TRUNCATE (1) +#-------------------------------------- + +CREATE TABLE t1 ( + id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET @save_debug = @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_sync_before_syncing,ib_trunc_sleep_before_fts_cache_clear'; + +INSERT INTO t1 (value) VALUES + ('By default or with the IN NATURAL LANGUAGE MODE modifier') + ; + +TRUNCATE TABLE t1; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; + +#-------------------------------------- +# Check FTS sync vs DROP INDEX (2) +#-------------------------------------- + +CREATE TABLE t1 ( + id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_write_words_before_select_index,ib_trunc_sleep_before_fts_cache_clear'; + +INSERT INTO t1 (value) VALUES + ('By default or with the IN NATURAL LANGUAGE MODE modifier'), + ('performs a natural language search for a string'), + ('collection is a set of one or more columns included'), + ('returns a relevance value; that is, a similarity measure'), + ('and the text in that row in the columns named in'), + ('By default, the search is performed in case-insensitive'), + ('sensitive full-text search, use a binary collation '), + ('example, a column that uses the latin1 character'), + ('collation of latin1_bin to make it case sensitive') + ; + +TRUNCATE TABLE t1; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; + +#-------------------------------------- +# Check FTS sync vs DROP INDEX +#-------------------------------------- + +CREATE TABLE t1 ( + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; + +INSERT INTO t1 (value) VALUES + ('By default or with the IN NATURAL LANGUAGE MODE modifier'), + ('performs a natural language search for a string'), + ('collection is a set of one or more columns included'), + ('returns a relevance value; that is, a similarity measure'), + ('and the text in that row in the columns named in'), + ('By default, the search is performed in case-insensitive'), + ('sensitive full-text search, use a binary collation '), + ('example, a column that uses the latin1 character'), + ('collation of latin1_bin to make it case sensitive') + ; + +DROP INDEX idx1 ON t1; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; + +#-------------------------------------- +# Check FTS sync vs ALTER TABLE DROP INDEX (INPLACE) +#-------------------------------------- + +CREATE TABLE t1 ( + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; + +INSERT INTO t1 (value) VALUES + ('By default or with the IN NATURAL LANGUAGE MODE modifier'), + ('performs a natural language search for a string'), + ('collection is a set of one or more columns included'), + ('returns a relevance value; that is, a similarity measure'), + ('and the text in that row in the columns named in'), + ('By default, the search is performed in case-insensitive'), + ('sensitive full-text search, use a binary collation '), + ('example, a column that uses the latin1 character'), + ('collation of latin1_bin to make it case sensitive') + ; + +ALTER TABLE t1 + DROP INDEX idx1, + ALGORITHM=INPLACE; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; + +#-------------------------------------- +# Check FTS sync vs ALTER TABLE DROP INDEX (COPY) +#-------------------------------------- + +CREATE TABLE t1 ( + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; + +INSERT INTO t1 (value) VALUES + ('example, a column that uses the latin1 character'), + ('collation of latin1_bin to make it case sensitive') + ; + +ALTER TABLE t1 + DROP INDEX idx1, + ALGORITHM=COPY; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; + +#-------------------------------------- +# Check FTS sync vs ALTER TABLE (INPLACE, new cluster) +#-------------------------------------- + +CREATE TABLE t1 ( + id1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(1024) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx1 ON t1(value); + +SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep'; + +INSERT INTO t1 (value) VALUES + ('example, a column that uses the latin1 character'), + ('collation of latin1_bin to make it case sensitive') + ; + +ALTER TABLE t1 + DROP COLUMN id1, + ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + DROP INDEX idx1, + ADD FULLTEXT INDEX idx2(value), + ALGORITHM=INPLACE; + +DROP TABLE t1; + +SET GLOBAL debug_dbug = @save_debug; diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result index fe46ef2e2f8..1af03c251bf 100644 --- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result @@ -1286,7 +1286,7 @@ CREATE SPATIAL INDEX idx2 ON t1(c1); DROP TABLE t1; CREATE TABLE mysql.innodb_table_stats ( database_name varchar(64) COLLATE utf8_bin NOT NULL, -table_name varchar(64) COLLATE utf8_bin NOT NULL, +table_name varchar(199) COLLATE utf8_bin NOT NULL, last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows bigint(20) unsigned NOT NULL, clustered_index_size bigint(20) unsigned NOT NULL, diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test index f8626b3c052..7ddece9ad86 100644 --- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test @@ -1168,7 +1168,7 @@ CREATE SPATIAL INDEX idx2 ON t1(c1); DROP TABLE t1; CREATE TABLE mysql.innodb_table_stats ( database_name varchar(64) COLLATE utf8_bin NOT NULL, - table_name varchar(64) COLLATE utf8_bin NOT NULL, + table_name varchar(199) COLLATE utf8_bin NOT NULL, last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows bigint(20) unsigned NOT NULL, clustered_index_size bigint(20) unsigned NOT NULL, diff --git a/mysql-test/suite/mariabackup/create_during_backup.result b/mysql-test/suite/mariabackup/create_during_backup.result new file mode 100644 index 00000000000..f99c2633ab5 --- /dev/null +++ b/mysql-test/suite/mariabackup/create_during_backup.result @@ -0,0 +1,10 @@ +# xtrabackup backup +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT COUNT(*) from t1; +COUNT(*) +10000 +DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/create_during_backup.test b/mysql-test/suite/mariabackup/create_during_backup.test new file mode 100644 index 00000000000..985a5a3e53a --- /dev/null +++ b/mysql-test/suite/mariabackup/create_during_backup.test @@ -0,0 +1,26 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $targetdir; + +# this will table and populate it, after backup has list of tables to be copied +--let after_load_tablespaces =CREATE TABLE test.t1 ENGINE=INNODB SELECT UUID() from test.seq_1_to_10000 + +echo # xtrabackup backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log + +--let after_load_tables= + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +# Check that new table is there after restore. +SELECT COUNT(*) from t1; +DROP TABLE t1; +rmdir $targetdir; + + diff --git a/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.result b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.result new file mode 100644 index 00000000000..a06150bcb6a --- /dev/null +++ b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.result @@ -0,0 +1,10 @@ +# xtrabackup backup +# xtrabackup prepare +DROP TABLE t; +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT * FROM t; +i +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test new file mode 100644 index 00000000000..d0cb83d069f --- /dev/null +++ b/mysql-test/suite/mariabackup/create_with_data_directory_during_backup.test @@ -0,0 +1,24 @@ +--source include/have_debug.inc +let $table_data_dir=$MYSQLTEST_VARDIR/tmp/ddir; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $table_data_dir; +--replace_result $table_data_dir table_data_dir +--let after_load_tablespaces=CREATE TABLE test.t(i int) ENGINE=INNODB DATA DIRECTORY='$table_data_dir' +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log +--source include/shutdown_mysqld.inc +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +--source include/start_mysqld.inc +DROP TABLE t; +rmdir $table_data_dir; +-- source include/restart_and_restore.inc +--enable_result_log +SELECT * FROM t; +DROP TABLE t; +rmdir $targetdir; +rmdir $table_data_dir; diff --git a/mysql-test/suite/mariabackup/disabled.def b/mysql-test/suite/mariabackup/disabled.def index 8b137891791..a7be04bfc16 100644 --- a/mysql-test/suite/mariabackup/disabled.def +++ b/mysql-test/suite/mariabackup/disabled.def @@ -1 +1 @@ - +unsupported_redo : MDEV-16791 allows optimized redo
\ No newline at end of file diff --git a/mysql-test/suite/mariabackup/drop_table_during_backup.result b/mysql-test/suite/mariabackup/drop_table_during_backup.result new file mode 100644 index 00000000000..1472ddbddcf --- /dev/null +++ b/mysql-test/suite/mariabackup/drop_table_during_backup.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (i int) ENGINE=INNODB; +CREATE TABLE t2 (i int) ENGINE=INNODB; +CREATE TABLE t3 (i int) ENGINE=INNODB; +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +CREATE TABLE t1(i int); +DROP TABLE t1; +CREATE TABLE t2(i int); +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/mariabackup/drop_table_during_backup.test b/mysql-test/suite/mariabackup/drop_table_during_backup.test new file mode 100644 index 00000000000..02c7710145b --- /dev/null +++ b/mysql-test/suite/mariabackup/drop_table_during_backup.test @@ -0,0 +1,24 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +CREATE TABLE t1 (i int) ENGINE=INNODB; +CREATE TABLE t2 (i int) ENGINE=INNODB; +CREATE TABLE t3 (i int) ENGINE=INNODB; +--let before_copy_test_t1=DROP TABLE test.t1 +--let after_copy_test_t2=DROP TABLE test.t2; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +#check that the table t1 does not exist in backup +CREATE TABLE t1(i int); +DROP TABLE t1; +CREATE TABLE t2(i int); +DROP TABLE t2; +DROP TABLE t3; +rmdir $targetdir; diff --git a/mysql-test/suite/mariabackup/incremental_ddl_during_backup.result b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.result new file mode 100644 index 00000000000..ffca1ef0e1f --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.result @@ -0,0 +1,22 @@ +call mtr.add_suppression("InnoDB: New log files created"); +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t3(i INT) ENGINE INNODB; +# Create full backup , modify table, then create incremental/differential backup +INSERT into t1 values(1); +# Prepare full backup, apply incremental one +# Restore and check results +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +CREATE TABLE t1(i int); +DROP TABLE t1; +SELECT * from t1_renamed; +i +1 +DROP TABLE t1_renamed; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test new file mode 100644 index 00000000000..60780b13920 --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test @@ -0,0 +1,52 @@ +--source include/have_debug.inc + +call mtr.add_suppression("InnoDB: New log files created"); + +let $basedir=$MYSQLTEST_VARDIR/tmp/backup; +let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1; + +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t3(i INT) ENGINE INNODB; + +echo # Create full backup , modify table, then create incremental/differential backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; +--enable_result_log + +INSERT into t1 values(1); + +--let after_load_tablespaces=CREATE TABLE test.t4 ENGINE=INNODB SELECT UUID() from test.seq_1_to_10000 +--let after_copy_test_t1=RENAME TABLE test.t1 TO test.t1_renamed +--let after_copy_test_t2=DROP TABLE test.t2 +--let after_copy_test_t3=CREATE INDEX a_i ON test.t3(i); + +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir --dbug=+d,mariabackup_events; +--let after_load_tablespaces= +--disable_result_log +echo # Prepare full backup, apply incremental one; +exec $XTRABACKUP --apply-log-only --prepare --target-dir=$basedir; +exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir ; + +echo # Restore and check results; +let $targetdir=$basedir; +-- source include/restart_and_restore.inc +--enable_result_log + +# Test that t1 does not exist, but t1_renamed does +CREATE TABLE t1(i int); +DROP TABLE t1; + +SELECT * from t1_renamed; +DROP TABLE t1_renamed; + +# Test that t2 does not exist; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +DROP TABLE t2; + +DROP TABLE t3; +DROP TABLE t4; + +# Cleanup +rmdir $basedir; +rmdir $incremental_dir; diff --git a/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result new file mode 100644 index 00000000000..47b74e0f709 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result @@ -0,0 +1,37 @@ +SET GLOBAL innodb_log_optimize_ddl=OFF; +CREATE TABLE tz(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +INSERT INTO tz(id) select * from seq_1_to_10000; +CREATE TABLE tr(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO tr(id) select * from seq_1_to_10000; +CREATE TABLE td(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB; +INSERT INTO td(id) select * from seq_1_to_10000; +CREATE PROCEDURE a() +BEGIN +ALTER TABLE tz ADD INDEX(i); +ALTER TABLE tr ADD INDEX(i); +ALTER TABLE td ADD INDEX(i); +END // +call a(); +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +DROP PROCEDURE a; +CHECK TABLE tz,tr,td; +Table Op Msg_type Msg_text +test.tz check status OK +test.tr check status OK +test.td check status OK +SELECT COUNT(*) FROM tz; +COUNT(*) +10000 +SELECT COUNT(*) FROM tr; +COUNT(*) +10000 +SELECT COUNT(*) FROM td; +COUNT(*) +10000 +DROP TABLE tz,tr,td; diff --git a/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test new file mode 100644 index 00000000000..d6680bec077 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test @@ -0,0 +1,47 @@ +# see unsupported_redo.test for the opposite (default) case +--source include/have_innodb.inc +--source include/have_sequence.inc + +SET GLOBAL innodb_log_optimize_ddl=OFF; + +CREATE TABLE tz(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +INSERT INTO tz(id) select * from seq_1_to_10000; +CREATE TABLE tr(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO tr(id) select * from seq_1_to_10000; +CREATE TABLE td(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB; +INSERT INTO td(id) select * from seq_1_to_10000; + +DELIMITER //; +CREATE PROCEDURE a() +BEGIN + ALTER TABLE tz ADD INDEX(i); + ALTER TABLE tr ADD INDEX(i); + ALTER TABLE td ADD INDEX(i); +END // +DELIMITER ;// + +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +send call a(); + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; + +reap; + +-- source include/restart_and_restore.inc +--rmdir $targetdir + +DROP PROCEDURE a; + +CHECK TABLE tz,tr,td; +SELECT COUNT(*) FROM tz; +SELECT COUNT(*) FROM tr; +SELECT COUNT(*) FROM td; + +DROP TABLE tz,tr,td; diff --git a/mysql-test/suite/mariabackup/mlog_index_load.result b/mysql-test/suite/mariabackup/mlog_index_load.result new file mode 100644 index 00000000000..bc83981106e --- /dev/null +++ b/mysql-test/suite/mariabackup/mlog_index_load.result @@ -0,0 +1,15 @@ +CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; +INSERT INTO t1(a) SELECT * from seq_1_to_10000; +# xtrabackup backup +t1.frm +t1.ibd +t1.new +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT COUNT(*) from t1; +COUNT(*) +10000 +DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/mlog_index_load.test b/mysql-test/suite/mariabackup/mlog_index_load.test new file mode 100644 index 00000000000..fb29041fd3c --- /dev/null +++ b/mysql-test/suite/mariabackup/mlog_index_load.test @@ -0,0 +1,27 @@ +--source include/have_debug.inc + +CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; +INSERT INTO t1(a) SELECT * from seq_1_to_10000; + +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +let after_copy_test_t1=CREATE INDEX a_ind ON test.t1(a) ALGORITHM=INPLACE; +echo # xtrabackup backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log + +--list_files $targetdir/test t1* +--let before_copy_test_t1= + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +# Check that new table is there after restore. +SELECT COUNT(*) from t1; +DROP TABLE t1; +rmdir $targetdir; + diff --git a/mysql-test/suite/mariabackup/recreate_table_during_backup.result b/mysql-test/suite/mariabackup/recreate_table_during_backup.result new file mode 100644 index 00000000000..4e038fee71a --- /dev/null +++ b/mysql-test/suite/mariabackup/recreate_table_during_backup.result @@ -0,0 +1,23 @@ +CREATE TABLE t1(i int) ENGINE=INNODB; +CREATE TABLE t2(i int) ENGINE=INNODB; +CREATE TABLE t3(a CHAR(36)) ENGINE INNODB; +INSERT INTO t3 SELECT UUID() FROM seq_1_to_1000; +# xtrabackup backup +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT COUNT(*) from t1; +COUNT(*) +100 +SELECT COUNT(*) from t2; +COUNT(*) +1000 +SELECT COUNT(*) from t3; +COUNT(*) +1000 +DROP INDEX index_a ON t3; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/mariabackup/recreate_table_during_backup.test b/mysql-test/suite/mariabackup/recreate_table_during_backup.test new file mode 100644 index 00000000000..c3c9cf5aeef --- /dev/null +++ b/mysql-test/suite/mariabackup/recreate_table_during_backup.test @@ -0,0 +1,37 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $targetdir; + +CREATE TABLE t1(i int) ENGINE=INNODB; +CREATE TABLE t2(i int) ENGINE=INNODB; +CREATE TABLE t3(a CHAR(36)) ENGINE INNODB; +INSERT INTO t3 SELECT UUID() FROM seq_1_to_1000; + +# this will table and populate it, after backup has list of tables to be copied +--let before_copy_test_t1=BEGIN NOT ATOMIC DROP TABLE test.t1;CREATE TABLE test.t1 ENGINE=INNODB SELECT UUID() from test.seq_1_to_100; END +--let after_copy_test_t2=BEGIN NOT ATOMIC DROP TABLE test.t2;CREATE TABLE test.t2 ENGINE=INNODB SELECT UUID() from test.seq_1_to_1000; END +--let after_copy_test_t3=ALTER TABLE test.t3 ADD INDEX index_a(a),ALGORITHM=COPY +echo # xtrabackup backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --close-files --dbug=+d,mariabackup_events; +--enable_result_log +--let after_load_tables= + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +# Check that new table is there after restore. +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +DROP INDEX index_a ON t3; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +rmdir $targetdir; + + + diff --git a/mysql-test/suite/mariabackup/rename_during_backup.result b/mysql-test/suite/mariabackup/rename_during_backup.result new file mode 100644 index 00000000000..6e8f365f643 --- /dev/null +++ b/mysql-test/suite/mariabackup/rename_during_backup.result @@ -0,0 +1,53 @@ +CREATE TABLE t1(i int) ENGINE INNODB; +INSERT into t1 values(1); +CREATE TABLE t2(i int) ENGINE INNODB; +INSERT INTO t2 values(2); +CREATE TABLE t3(i int) ENGINE INNODB; +CREATE TABLE t4(i int) ENGINE INNODB; +CREATE TABLE a(a int) ENGINE INNODB; +INSERT INTO a values(1); +CREATE TABLE b(b CHAR(1)) ENGINE INNODB; +INSERT INTO b VALUES('b'); +CREATE TABLE a1(a1 int) ENGINE INNODB; +INSERT INTO a1 VALUES(1); +CREATE TABLE b1(b1 CHAR(2)) ENGINE INNODB; +INSERT INTO b1 VALUES('b1'); +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +CREATE TABLE t1(i int); +DROP TABLE t1; +SELECT * from t1_renamed; +i +1 +DROP TABLE t1_renamed; +CREATE TABLE t2(i int); +DROP TABLE t2; +SELECT * from t2_renamed; +i +2 +DROP TABLE t2_renamed; +SELECT * from t3; +i +3 +DROP TABLE t3; +SELECT * from t4; +i +DROP TABLE t4; +CREATE TABLE tmp(i int); +DROP TABLE tmp; +SELECT * FROM a; +b +b +SELECT * FROM b; +a +1 +SELECT * FROM a1; +b1 +b1 +SELECT * FROM b1; +a1 +1 +DROP TABLE a,b,a1,b1; diff --git a/mysql-test/suite/mariabackup/rename_during_backup.test b/mysql-test/suite/mariabackup/rename_during_backup.test new file mode 100644 index 00000000000..f176af1451b --- /dev/null +++ b/mysql-test/suite/mariabackup/rename_during_backup.test @@ -0,0 +1,86 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $targetdir; + +CREATE TABLE t1(i int) ENGINE INNODB; +INSERT into t1 values(1); + +CREATE TABLE t2(i int) ENGINE INNODB; +INSERT INTO t2 values(2); + +CREATE TABLE t3(i int) ENGINE INNODB; +CREATE TABLE t4(i int) ENGINE INNODB; + +CREATE TABLE a(a int) ENGINE INNODB; +INSERT INTO a values(1); +CREATE TABLE b(b CHAR(1)) ENGINE INNODB; +INSERT INTO b VALUES('b'); + +CREATE TABLE a1(a1 int) ENGINE INNODB; +INSERT INTO a1 VALUES(1); + +CREATE TABLE b1(b1 CHAR(2)) ENGINE INNODB; +INSERT INTO b1 VALUES('b1'); + +# Test renames before of after copying tablespaces +--let before_copy_test_t1=RENAME TABLE test.t1 TO test.t1_renamed +--let after_copy_test_t2=RENAME TABLE test.t2 TO test.t2_renamed +--let after_copy_test_t3=BEGIN NOT ATOMIC RENAME TABLE test.t3 TO test.t3_tmp; INSERT INTO test.t3_tmp VALUES(3); RENAME TABLE test.t3_tmp TO test.t3; END +--let before_copy_test_t4=RENAME TABLE test.t4 TO test.t4_tmp +--let after_copy_test_t4=RENAME TABLE test.t4_tmp TO test.t4 + +# Test circular renames +--let before_copy_test_b=RENAME TABLE test.a to test.tmp, test.b to test.a, test.tmp to test.b +--let after_copy_test_b1=RENAME TABLE test.a1 to test.tmp, test.b1 to test.a1, test.tmp to test.b1 + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log + +--let before_copy_test_t1='' +--let after_copy_test_t2='' +--let before_copy_test_a='' +--let after_copy_test_a1='' + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +# the table was renamed from t1 to t1_renamed +# make sure t1 does not exist, and t1_renamed does. + +CREATE TABLE t1(i int); +DROP TABLE t1; + +SELECT * from t1_renamed; +DROP TABLE t1_renamed; + + +CREATE TABLE t2(i int); +DROP TABLE t2; + +SELECT * from t2_renamed; +DROP TABLE t2_renamed; + +#rename to itself +SELECT * from t3; +DROP TABLE t3; + +SELECT * from t4; +DROP TABLE t4; + +# For circular renames , make sure intermediate tables do not exist +CREATE TABLE tmp(i int); +DROP TABLE tmp; + +SELECT * FROM a; +SELECT * FROM b; +SELECT * FROM a1; +SELECT * FROM b1; + +DROP TABLE a,b,a1,b1; +rmdir $targetdir; + + diff --git a/mysql-test/suite/mariabackup/rename_during_mdl_lock.result b/mysql-test/suite/mariabackup/rename_during_mdl_lock.result index 982851438f2..3b64cdc38bc 100644 --- a/mysql-test/suite/mariabackup/rename_during_mdl_lock.result +++ b/mysql-test/suite/mariabackup/rename_during_mdl_lock.result @@ -1,3 +1,11 @@ CREATE TABLE t1(i int) ENGINE INNODB; -FOUND 1 /failed to execute query SELECT 1 FROM/ in backup.log +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +CREATE TABLE t1(i int); +DROP TABLE t1; +SELECT * from t2; +i DROP TABLE t2; diff --git a/mysql-test/suite/mariabackup/rename_during_mdl_lock.test b/mysql-test/suite/mariabackup/rename_during_mdl_lock.test index 0a41f1dfe74..6d22e0db4a7 100644 --- a/mysql-test/suite/mariabackup/rename_during_mdl_lock.test +++ b/mysql-test/suite/mariabackup/rename_during_mdl_lock.test @@ -1,13 +1,21 @@ --source include/have_debug.inc -let $targetdir=$MYSQLTEST_VARDIR/backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; mkdir $targetdir; CREATE TABLE t1(i int) ENGINE INNODB; ---error 1 -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --lock-ddl-per-table --dbug=+d,rename_during_mdl_lock_table 2>$targetdir/backup.log; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --lock-ddl-per-table --dbug=+d,rename_during_mdl_lock_table; -let SEARCH_FILE=$targetdir/backup.log; -let SEARCH_PATTERN=failed to execute query SELECT 1 FROM; -source include/search_pattern_in_file.inc; +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log +# the table was renamed from t1 to t2 +# make sure t1 does not exist, and t2 does +CREATE TABLE t1(i int); +DROP TABLE t1; +SELECT * from t2; DROP TABLE t2; + rmdir $targetdir; + diff --git a/mysql-test/suite/mariabackup/suite.opt b/mysql-test/suite/mariabackup/suite.opt index de3637814b2..1df4643562e 100644 --- a/mysql-test/suite/mariabackup/suite.opt +++ b/mysql-test/suite/mariabackup/suite.opt @@ -1 +1 @@ ---innodb --loose-changed_page_bitmaps --innodb-sys-tables --innodb-flush-log-at-trx-commit=2 +--innodb --loose-changed_page_bitmaps --innodb-sys-tables --innodb-flush-log-at-trx-commit=2 --sequence diff --git a/mysql-test/suite/mariabackup/xb_aws_key_management.result b/mysql-test/suite/mariabackup/xb_aws_key_management.result index fd12344dfa0..6efc76a8be3 100644 --- a/mysql-test/suite/mariabackup/xb_aws_key_management.result +++ b/mysql-test/suite/mariabackup/xb_aws_key_management.result @@ -11,4 +11,6 @@ INSERT INTO t VALUES('foobar1'); SELECT * from t; c foobar1 +Warnings: +Note 1105 AWS KMS plugin: loaded key 1, version 1, key length 128 bit DROP TABLE t; diff --git a/mysql-test/suite/parts/r/truncate_locked.result b/mysql-test/suite/parts/r/truncate_locked.result new file mode 100644 index 00000000000..54a3722938e --- /dev/null +++ b/mysql-test/suite/parts/r/truncate_locked.result @@ -0,0 +1,7 @@ +create table t1 (i int) engine=myisam partition by hash(i) partitions 2 ; +lock table t1 write; +truncate table t1; +desc t1; +Field Type Null Key Default Extra +i int(11) YES NULL +drop table t1; diff --git a/mysql-test/suite/parts/t/truncate_locked.test b/mysql-test/suite/parts/t/truncate_locked.test new file mode 100644 index 00000000000..4ff1016fb05 --- /dev/null +++ b/mysql-test/suite/parts/t/truncate_locked.test @@ -0,0 +1,10 @@ +# +# MDEV-15551 Server hangs or assertion `strcmp(share->unique_file_name,filename) || share->last_version' fails in test_if_reopen or unexpected ER_LOCK_DEADLOCK +# +--source include/have_partition.inc +create table t1 (i int) engine=myisam partition by hash(i) partitions 2 ; +lock table t1 write; +truncate table t1; +desc t1; +drop table t1; + diff --git a/mysql-test/suite/rpl/include/rpl_row_001.test b/mysql-test/suite/rpl/include/rpl_row_001.test index 97b3a93b4ed..4df2d793244 100644 --- a/mysql-test/suite/rpl/include/rpl_row_001.test +++ b/mysql-test/suite/rpl/include/rpl_row_001.test @@ -21,7 +21,7 @@ connection slave; sync_with_master; STOP SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; START SLAVE; connection master; @@ -29,7 +29,7 @@ connection master; # Give slave time to do at last one failed connect retry # This one must be short so that the slave will not stop retrying real_sleep 2; -SET PASSWORD FOR root@"localhost" = PASSWORD(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; # Give slave time to connect (will retry every second) sleep 2; diff --git a/mysql-test/suite/rpl/r/rpl_row_001.result b/mysql-test/suite/rpl/r/rpl_row_001.result index b5b2b370e61..f7684d5ad97 100644 --- a/mysql-test/suite/rpl/r/rpl_row_001.result +++ b/mysql-test/suite/rpl/r/rpl_row_001.result @@ -19,11 +19,11 @@ create temporary table tmp select * from mysql.user where host="localhost" and u connection slave; STOP SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; START SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; CREATE TABLE t3(n INT); INSERT INTO t3 VALUES(1),(2); connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result new file mode 100644 index 00000000000..786e1682bb0 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result @@ -0,0 +1,33 @@ +include/master-slave.inc +[connection master] +connection master; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +connection slave; +include/stop_slave.inc +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +include/start_slave.inc +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; +connection slave; +connection master; +# Shutdown master +include/rpl_stop_server.inc [server_number=1] +connection slave; +include/stop_slave.inc +# Restart master +include/rpl_start_server.inc [server_number=1] +connection slave; +include/stop_slave.inc +Warnings: +Note 1255 Slave already has been stopped +include/start_slave.inc +connection master; +SET @@GLOBAL.debug_dbug=""; +SET @@GLOBAL. rpl_semi_sync_master_enabled = 0; +connection master; +DROP TABLE t1; +connection slave; +include/stop_slave.inc +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 0; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test new file mode 100644 index 00000000000..2224f78d6d0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test @@ -0,0 +1,60 @@ +# MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling +# +# The test verifies that the semisync-enabled slave io thread +# finishes off as specified in particular trying to connect even to a shut down +# master for a semisync firewell routine. + +source include/not_embedded.inc; +source include/have_debug.inc; +source include/master-slave.inc; + +--connection master + +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled ` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--connection slave +source include/stop_slave.inc; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled ` +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; + +--sync_slave_with_master + +connection master; +--echo # Shutdown master +--let $rpl_server_number=1 +source include/rpl_stop_server.inc; + +--connection slave +--source include/stop_slave.inc + +#connection master; +--echo # Restart master +--let $rpl_server_number=1 +source include/rpl_start_server.inc; + +# +# Clean up +# +--connection slave +--source include/stop_slave.inc +--source include/start_slave.inc + +--connection master +SET @@GLOBAL.debug_dbug=""; +--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master + +--connection master +DROP TABLE t1; + +--sync_slave_with_master +source include/stop_slave.inc; +--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/innodb_log_optimize_ddl_basic.result b/mysql-test/suite/sys_vars/r/innodb_log_optimize_ddl_basic.result new file mode 100644 index 00000000000..993bb13ebf0 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_log_optimize_ddl_basic.result @@ -0,0 +1,39 @@ +SELECT COUNT(@@GLOBAL.innodb_log_optimize_ddl); +COUNT(@@GLOBAL.innodb_log_optimize_ddl) +1 +1 Expected +SELECT COUNT(@@SESSION.innodb_log_optimize_ddl); +ERROR HY000: Variable 'innodb_log_optimize_ddl' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT @@GLOBAL.innodb_log_optimize_ddl; +@@GLOBAL.innodb_log_optimize_ddl +1 +SELECT @@GLOBAL.innodb_log_optimize_ddl INTO @innodb_log_optimize_ddl_save; +SET @@GLOBAL.innodb_log_optimize_ddl = ON; +SET @@GLOBAL.innodb_log_optimize_ddl = OFF; +SET @@GLOBAL.innodb_log_optimize_ddl = 13; +ERROR 42000: Variable 'innodb_log_optimize_ddl' can't be set to the value of '13' +SET @@GLOBAL.innodb_log_optimize_ddl = 'ABC'; +ERROR 42000: Variable 'innodb_log_optimize_ddl' can't be set to the value of 'ABC' +SELECT @@GLOBAL.innodb_log_optimize_ddl = 0 +OR @@GLOBAL.innodb_log_optimize_ddl = 1 AS col; +col +1 +1 Expected +SELECT @@innodb_log_optimize_ddl = @@GLOBAL.innodb_log_optimize_ddl AS col; +col +1 +1 Expected +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_log_optimize_ddl'; +VARIABLE_VALUE +OFF +SHOW VARIABLES WHERE VARIABLE_NAME='innodb_log_optimize_ddl'; +Variable_name Value +innodb_log_optimize_ddl OFF +SELECT @@local.innodb_log_optimize_ddl; +ERROR HY000: Variable 'innodb_log_optimize_ddl' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT innodb_log_optimize_ddl; +ERROR 42S22: Unknown column 'innodb_log_optimize_ddl' in 'field list' +SET GLOBAL innodb_log_optimize_ddl = @innodb_log_optimize_ddl_save; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index e98cf8e41ff..4b2024d1445 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1450,6 +1450,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_LOG_OPTIMIZE_DDL +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Reduce redo logging when natively creating indexes or rebuilding tables. Setting this OFF avoids delay due to page flushing and allows concurrent backup. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_LOG_WRITE_AHEAD_SIZE SESSION_VALUE NULL GLOBAL_VALUE 8192 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 079f63ba354..01c426b117f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -586,6 +586,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME CORE_FILE +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NULL +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT write a core-file on crashes +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DATADIR SESSION_VALUE NULL GLOBAL_VALUE PATH diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 2e2ea63d50a..9f9513867a9 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -586,6 +586,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME CORE_FILE +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NULL +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT write a core-file on crashes +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DATADIR SESSION_VALUE NULL GLOBAL_VALUE PATH diff --git a/mysql-test/suite/sys_vars/t/innodb_log_optimize_ddl_basic.test b/mysql-test/suite/sys_vars/t/innodb_log_optimize_ddl_basic.test new file mode 100644 index 00000000000..8e7612b0d9e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_log_optimize_ddl_basic.test @@ -0,0 +1,65 @@ +############# suite/sys_vars/t/innodb_log_optimize_ddl_basic.test ############# +# # +# Variable Name: innodb_log_optimize_ddl # +# Scope: Global # +# Access Type: Dynamic # +# Data Type: boolean # +# # +# The variable was introduced by # +# MDEV-16809 Allow full redo logging for ALTER TABLE # +# # +############################################################################### + +--source include/have_innodb.inc + +#### Reveal that the global innodb system variable exists +SELECT COUNT(@@GLOBAL.innodb_log_optimize_ddl); +--echo 1 Expected + +#### Reveal that no session innodb system variable exists +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT COUNT(@@SESSION.innodb_log_optimize_ddl); +--echo Expected error 'Variable is a GLOBAL variable' + +#### Display the default value +SELECT @@GLOBAL.innodb_log_optimize_ddl; + +SELECT @@GLOBAL.innodb_log_optimize_ddl INTO @innodb_log_optimize_ddl_save; +#### Check if the value can be set +SET @@GLOBAL.innodb_log_optimize_ddl = ON; +SET @@GLOBAL.innodb_log_optimize_ddl = OFF; + +#### Check if disallowed values are refused +--error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.innodb_log_optimize_ddl = 13; +--error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.innodb_log_optimize_ddl = 'ABC'; + +#### Check if the initial value was in the range of supported values +# We use 0 and 1 in order to avoid a warning. +SELECT @@GLOBAL.innodb_log_optimize_ddl = 0 + OR @@GLOBAL.innodb_log_optimize_ddl = 1 AS col; +--echo 1 Expected + +#### Check if the value presented without GLOBAL point is the same +SELECT @@innodb_log_optimize_ddl = @@GLOBAL.innodb_log_optimize_ddl AS col; +--echo 1 Expected + +#### Show the value presented in information_schema and SHOW VARIABLES +# We do not want to get and than maybe suppress the print of +# Warning 1292 Truncated incorrect DOUBLE value: 'OFF' +# and so we simply print the value and do not compare. +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_log_optimize_ddl'; +SHOW VARIABLES WHERE VARIABLE_NAME='innodb_log_optimize_ddl'; + +#### Show that variants with @@local. and without @@ do not exist. +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@local.innodb_log_optimize_ddl; +--echo Expected error 'Variable is a GLOBAL variable' +--Error ER_BAD_FIELD_ERROR +SELECT innodb_log_optimize_ddl; + +#### Restore the initial value +SET GLOBAL innodb_log_optimize_ddl = @innodb_log_optimize_ddl_save; + diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 3def1bd083b..a5b65f5315c 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -626,6 +626,19 @@ } # +# Warning caused by small memory leak in _dl_init +# + +{ + dl_init memory leak + Memcheck:Leak + fun:malloc + obj:*/libstdc++.so* + fun:call_init.part* + fun:_dl_init +} + +# # In glibc (checked version 2.7), inet_ntoa allocates an 18-byte # per-thread static buffer for the return value. That memory is freed # at thread exit, however if called from the main thread, Valgrind diff --git a/mysys/my_rename.c b/mysys/my_rename.c index 49c5abc5c19..f3831c2e73e 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -39,7 +39,10 @@ int my_rename(const char *from, const char *to, myf MyFlags) if (link(from, to) || unlink(from)) { #endif - my_errno=errno; + if (errno == ENOENT && !access(from, F_OK)) + my_errno= ENOTDIR; + else + my_errno= errno; error = -1; if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_LINK, MYF(ME_BELL),from,to,my_errno); diff --git a/pcre/CMakeLists.txt b/pcre/CMakeLists.txt index 80e402e5713..857a96b9ef9 100644 --- a/pcre/CMakeLists.txt +++ b/pcre/CMakeLists.txt @@ -364,12 +364,6 @@ IF(PCRE_BUILD_TESTS) # exes in Debug location tested by the RunTest shell script # via "make test" - IF(PCRE_BUILD_PCREGREP) - GET_TARGET_PROPERTY(PCREGREP_EXE pcregrep DEBUG_LOCATION) - ENDIF(PCRE_BUILD_PCREGREP) - - GET_TARGET_PROPERTY(PCRETEST_EXE pcretest DEBUG_LOCATION) - STRING(REGEX REPLACE "[^/]+$" "" PCRETEST_DIR ${PCRETEST_EXE}) # ================================================= # Write out a CTest configuration file @@ -381,36 +375,24 @@ MESSAGE(\"When testing is complete, review test output in the MESSAGE(\" \") ") - FILE(WRITE ${PROJECT_BINARY_DIR}/pcre_test.sh - "#! /bin/sh -# This is a generated file. -srcdir=${PROJECT_SOURCE_DIR} -pcretest=${PCRETEST_EXE} -cd ${PCRETEST_DIR} -. ${PROJECT_SOURCE_DIR}/RunTest -if test \"$?\" != \"0\"; then exit 1; fi -# End -") - IF(UNIX) - ADD_TEST(pcre_test sh ${PROJECT_BINARY_DIR}/pcre_test.sh) + ADD_TEST(NAME pcre_test + COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/pcre_test.sh + ${PROJECT_SOURCE_DIR} + $<TARGET_FILE:pcretest> + $<TARGET_FILE_DIR:pcretest> + ) ENDIF(UNIX) IF(PCRE_BUILD_PCREGREP) - FILE(WRITE ${PROJECT_BINARY_DIR}/pcre_grep_test.sh - "#! /bin/sh -# This is a generated file. -srcdir=${PROJECT_SOURCE_DIR} -pcregrep=${PCREGREP_EXE} -pcretest=${PCRETEST_EXE} -cd ${PCRETEST_DIR} -. ${PROJECT_SOURCE_DIR}/RunGrepTest -if test \"$?\" != \"0\"; then exit 1; fi -# End -") - IF(UNIX) - ADD_TEST(pcre_grep_test sh ${PROJECT_BINARY_DIR}/pcre_grep_test.sh) + ADD_TEST(NAME pcre_grep_test + COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/pcre_grep_test.sh + ${PROJECT_SOURCE_DIR} + $<TARGET_FILE:pcregrep> + $<TARGET_FILE:pcretest> + $<TARGET_FILE_DIR:pcretest> + ) ENDIF(UNIX) ENDIF(PCRE_BUILD_PCREGREP) @@ -418,22 +400,13 @@ if test \"$?\" != \"0\"; then exit 1; fi # Provide environment for executing the bat file version of RunTest FILE(TO_NATIVE_PATH ${PROJECT_SOURCE_DIR} winsrc) FILE(TO_NATIVE_PATH ${PROJECT_BINARY_DIR} winbin) - FILE(TO_NATIVE_PATH ${PCRETEST_EXE} winexe) - - FILE(WRITE ${PROJECT_BINARY_DIR}/pcre_test.bat - "\@REM This is a generated file. -\@echo off -setlocal -SET srcdir=\"${winsrc}\" -SET pcretest=\"${winexe}\" -if not [%CMAKE_CONFIG_TYPE%]==[] SET pcretest=\"${winbin}\\%CMAKE_CONFIG_TYPE%\\pcretest.exe\" -call %srcdir%\\RunTest.Bat -if errorlevel 1 exit /b 1 -echo RunTest.bat tests successfully completed -") ADD_TEST(NAME pcre_test_bat - COMMAND pcre_test.bat) + COMMAND pcre_test.bat + ${winsrc} + ${winbin} + $<TARGET_FILE:pcretest> + ) SET_TESTS_PROPERTIES(pcre_test_bat PROPERTIES PASS_REGULAR_EXPRESSION "RunTest\\.bat tests successfully completed") diff --git a/pcre/pcre_grep_test.sh b/pcre/pcre_grep_test.sh new file mode 100644 index 00000000000..7165aeeb0e2 --- /dev/null +++ b/pcre/pcre_grep_test.sh @@ -0,0 +1,13 @@ +#! /bin/sh +# +srcdir="$1" +pcregrep="$2" +pcretest="$3" +cd "$4" +shift +shift +shift +shift +. "$srcdir"/RunGrepTest +if test "$?" != "0"; then exit 1; fi +# End diff --git a/pcre/pcre_test.bat b/pcre/pcre_test.bat new file mode 100644 index 00000000000..c3f8dc3d43b --- /dev/null +++ b/pcre/pcre_test.bat @@ -0,0 +1,9 @@ +@echo off +setlocal +SET srcdir="%1" +SET bindir="%1" +SET pcretest="%3" +if not [%CMAKE_CONFIG_TYPE%]==[] SET pcretest="%bindir%\%CMAKE_CONFIG_TYPE%\pcretest.exe" +call %srcdir%\RunTest.Bat +if errorlevel 1 exit /b 1 +echo RunTest.bat tests successfully completed diff --git a/pcre/pcre_test.sh b/pcre/pcre_test.sh new file mode 100644 index 00000000000..8fadc671c9a --- /dev/null +++ b/pcre/pcre_test.sh @@ -0,0 +1,11 @@ +#! /bin/sh +# +srcdir="$1" +pcretest="$2" +cd "$3" +shift +shift +shift +. "$srcdir"/RunTest +if test "$?" != "0"; then exit 1; fi +# End diff --git a/plugin/handler_socket/CMakeLists.txt b/plugin/handler_socket/CMakeLists.txt index bd656ebc5b7..329ff58d7f2 100644 --- a/plugin/handler_socket/CMakeLists.txt +++ b/plugin/handler_socket/CMakeLists.txt @@ -5,14 +5,7 @@ IF(WIN32) RETURN() ENDIF() -#Remove -fno-implicit-templates from compiler flags(handlersocket would not work with it) -STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - -include(CheckCXXCompilerFlag) -check_cxx_compiler_flag(" -Wdeprecated-declarations" HAVE_CXX_WDEPRECATED_DECLARATIONS) -IF (HAVE_CXX_WDEPRECATED_DECLARATIONS) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") -ENDIF() +MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-deprecated-declarations") INCLUDE_DIRECTORIES(libhsclient) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index fe14edba139..464c00d57da 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -91,6 +91,7 @@ SET(ADD_GIS_SP_EOL ";") CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql ESCAPE_QUOTES @ONLY) +IF (NOT WITHOUT_SERVER) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables.sql ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables_data.sql @@ -104,6 +105,7 @@ INSTALL(FILES ${FIX_PRIVILEGES_SQL} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server ) +ENDIF() # TCMalloc hacks IF(MALLOC_LIB) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 294d0816a6b..8a0ade99d69 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -242,6 +242,11 @@ cannot_find_file() echo "If you don't want to do a full install, you can use the --srcdir" echo "option to only install the mysql database and privilege tables" echo + echo "If you compiled from source, you need to either run 'make install' to" + echo "copy the software into the correct location ready for operation." + echo "If you don't want to do a full install, you can use the --srcdir" + echo "option to only install the mysql database and privilege tables" + echo echo "If you are using a binary release, you must either be at the top" echo "level of the extracted archive, or pass the --basedir option" echo "pointing to that location." @@ -343,7 +348,7 @@ else basedir="@prefix@" bindir="@bindir@" resolveip="$bindir/resolveip" - mysqld="@libexecdir@/mysqld" + mysqld="@sbindir@/mysqld" srcpkgdatadir="@pkgdatadir@" buildpkgdatadir="@pkgdatadir@" plugindir="@pkgplugindir@" diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 676b1a97257..7aafcb2c5de 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -1,4 +1,4 @@ --- Copyright (c) 2007, 2013, Oracle and/or its affiliates. +-- Copyright (c) 2007, 2018, Oracle and/or its affiliates. -- Copyright (c) 2008, 2014, Monty Program Ab & SkySQL Ab -- -- This program is free software; you can redistribute it and/or modify @@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( database_name VARCHAR(64) NOT NULL, - table_name VARCHAR(64) NOT NULL, + table_name VARCHAR(199) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows BIGINT UNSIGNED NOT NULL, clustered_index_size BIGINT UNSIGNED NOT NULL, @@ -117,7 +117,7 @@ SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( SET @create_innodb_index_stats="CREATE TABLE IF NOT EXISTS innodb_index_stats ( database_name VARCHAR(64) NOT NULL, - table_name VARCHAR(64) NOT NULL, + table_name VARCHAR(199) NOT NULL, index_name VARCHAR(64) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, /* there are at least: diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 0b33e5ff63a..e430646ceed 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -1,5 +1,5 @@ -- Copyright (C) 2003, 2013 Oracle and/or its affiliates. --- Copyright (C) 2010, 2015 MariaDB Corporation Ab. +-- Copyright (C) 2010, 2018 MariaDB Corporation -- -- 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 @@ -28,15 +28,24 @@ set sql_mode=''; set storage_engine=Aria; set enforce_storage_engine=NULL; -ALTER TABLE user add File_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; +ALTER TABLE user add File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; # Detect whether or not we had the Grant_priv column SET @hadGrantPriv:=0; SELECT @hadGrantPriv:=1 FROM user WHERE Grant_priv LIKE '%'; -ALTER TABLE user add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; -ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; -ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; +ALTER TABLE user add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE host add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + add Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; # Fix privileges for old tables UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; @@ -48,11 +57,11 @@ UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Cr # Adding columns needed by GRANT .. REQUIRE (openssl) ALTER TABLE user -ADD ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci NOT NULL, +ADD ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ADD ssl_cipher BLOB NOT NULL, ADD x509_issuer BLOB NOT NULL, ADD x509_subject BLOB NOT NULL; -ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL; +ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL; # # tables_priv @@ -63,9 +72,9 @@ ALTER TABLE tables_priv ALTER TABLE tables_priv MODIFY Host char(60) NOT NULL default '', MODIFY Db char(64) NOT NULL default '', - MODIFY User char(80) NOT NULL default '', + MODIFY User char(80) binary NOT NULL default '', MODIFY Table_name char(64) NOT NULL default '', - MODIFY Grantor char(141) NOT NULL default '', + MODIFY Grantor char(141) COLLATE utf8_bin NOT NULL default '', ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; @@ -91,7 +100,7 @@ ALTER TABLE columns_priv ALTER TABLE columns_priv MODIFY Host char(60) NOT NULL default '', MODIFY Db char(64) NOT NULL default '', - MODIFY User char(80) NOT NULL default '', + MODIFY User char(80) binary NOT NULL default '', MODIFY Table_name char(64) NOT NULL default '', MODIFY Column_name char(64) NOT NULL default '', ENGINE=Aria, @@ -162,7 +171,7 @@ alter table func comment='User defined functions'; # and reset all char columns to correct width ALTER TABLE user MODIFY Host char(60) NOT NULL default '', - MODIFY User char(80) NOT NULL default '', + MODIFY User char(80) binary NOT NULL default '', ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; # In MySQL 5.7.6 the Password column is removed. Recreate it to preserve the number @@ -198,7 +207,7 @@ ALTER TABLE user ALTER TABLE db MODIFY Host char(60) NOT NULL default '', MODIFY Db char(64) NOT NULL default '', - MODIFY User char(80) NOT NULL default '', + MODIFY User char(80) binary NOT NULL default '', ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE db MODIFY Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, @@ -462,7 +471,7 @@ ALTER TABLE proc MODIFY db MODIFY definer char(141) collate utf8_bin DEFAULT '' NOT NULL, MODIFY comment - char(64) collate utf8_bin DEFAULT '' NOT NULL; + text collate utf8_bin NOT NULL; ALTER TABLE proc ADD character_set_client char(32) collate utf8_bin DEFAULT NULL @@ -540,19 +549,18 @@ ALTER TABLE proc ADD aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL SET @hadEventPriv := 0; SELECT @hadEventPriv :=1 FROM user WHERE Event_priv LIKE '%'; -ALTER TABLE user add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv; +ALTER TABLE user ADD Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv; ALTER TABLE user MODIFY Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv; UPDATE user SET Event_priv=Super_priv WHERE @hadEventPriv = 0; -ALTER TABLE db add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL; +ALTER TABLE db ADD Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL; ALTER TABLE db MODIFY Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL; # # EVENT table # -ALTER TABLE event DROP PRIMARY KEY; -ALTER TABLE event ADD PRIMARY KEY(db, name); +ALTER TABLE event DROP PRIMARY KEY, ADD PRIMARY KEY(db, name); # Add sql_mode column just in case. ALTER TABLE event ADD sql_mode set ('IGNORE_BAD_TABLE_OPTIONS') AFTER on_completion; # Update list of sql_mode values. @@ -594,8 +602,8 @@ ALTER TABLE event MODIFY sql_mode ) DEFAULT '' NOT NULL AFTER on_completion; ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default ''; -ALTER TABLE event MODIFY COLUMN originator INT UNSIGNED NOT NULL; ALTER TABLE event ADD COLUMN originator INT UNSIGNED NOT NULL AFTER comment; +ALTER TABLE event MODIFY COLUMN originator INT UNSIGNED NOT NULL; ALTER TABLE event MODIFY COLUMN status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED'; @@ -674,12 +682,14 @@ ALTER TABLE db modify Delete_history_priv enum('N','Y') COLLATE utf8_general_ci UPDATE user SET Delete_history_priv = Super_priv WHERE @had_user_delete_history_priv = 0; -ALTER TABLE user ADD plugin char(64) DEFAULT '', ADD authentication_string TEXT; +ALTER TABLE user ADD plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, + ADD authentication_string TEXT NOT NULL; +ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, + MODIFY authentication_string TEXT NOT NULL; ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD default_role char(80) binary DEFAULT '' NOT NULL; ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL; -ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL; -- Somewhere above, we ran ALTER TABLE user .... CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin. -- we want password_expired column to have collation utf8_general_ci. ALTER TABLE user MODIFY password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; @@ -722,13 +732,13 @@ set @str=replace(@str, "innodb_index_stats", "innodb_table_stats"); prepare stmt from @str; execute stmt; -# update timestamp fields in the innodb stat tables -set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp"; +# update table_name and timestamp fields in the innodb stat tables +set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)"; set @str=if(@have_innodb <> 0, @str, "set @dummy = 0"); prepare stmt from @str; execute stmt; -set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp"; +set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)"; set @str=if(@have_innodb <> 0, @str, "set @dummy = 0"); prepare stmt from @str; execute stmt; diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index c6515a3986b..10fcf2ae2b4 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -30,7 +30,7 @@ $opt_example = 0; $opt_help = 0; $opt_log = undef(); $opt_mysqladmin = "@bindir@/mysqladmin"; -$opt_mysqld = "@libexecdir@/mysqld"; +$opt_mysqld = "@sbindir@/mysqld"; $opt_no_log = 0; $opt_password = undef(); $opt_tcp_ip = 0; @@ -492,12 +492,19 @@ sub list_defaults_files return ($opt{file}) if exists $opt{file}; - return ('@sysconfdir@/my.cnf', - '@sysconfdir@/mysql/my.cnf', - '@prefix@/my.cnf', - ($ENV{MYSQL_HOME} ? "$ENV{MYSQL_HOME}/my.cnf" : undef), - $opt{'extra-file'}, - ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); + my @dirs; + + # same rule as in mysys/my_default.c + if ('@sysconfdir@') { + push @dirs, '@sysconfdir@/my.cnf'; + } else { + push @dirs, '/etc/my.cnf', '/etc/mysql/my.cnf'; + } + push @dirs, "$ENV{MYSQL_HOME}/my.cnf" if $ENV{MYSQL_HOME}; + push @dirs, $opt{'extra-file'} if $opt{'extra-file'}; + push @dirs, "$ENV{HOME}/.my.cnf" if $ENV{HOME}; + + return @dirs; } diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index aee2f0b7f64..8173db26291 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -33,7 +33,6 @@ ssystag="" XTRABACKUP_PID="" SST_PORT="" REMOTEIP="" -REMOTEHOST="" tcert="" tpem="" tkey="" @@ -219,7 +218,7 @@ get_transfer() tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},cafile=${tcert}${sockopt} stdio" else wsrep_log_info "Encrypting with cert=${tpem}, cafile=${tcert}" - tcmd="socat -u stdio openssl-connect:${REMOTEHOST}:${TSST_PORT},cert=${tpem},cafile=${tcert}${sockopt}" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},cafile=${tcert}${sockopt}" fi elif [[ $encrypt -eq 3 ]];then wsrep_log_info "Using openssl based encryption with socat: with key and crt" @@ -242,7 +241,7 @@ get_transfer() tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},verify=0${sockopt}" else wsrep_log_info "Encrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" - tcmd="socat -u stdio openssl-connect:${REMOTEHOST}:${TSST_PORT},cert=${tpem},key=${tkey},cafile=${tcert}${sockopt}" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},cafile=${tcert}${sockopt}" fi fi @@ -512,10 +511,6 @@ setup_ports() if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - REMOTEHOST=$(getent hosts $REMOTEIP | awk '{ print $2 }') - if [[ -z $REMOTEHOST ]];then - REMOTEHOST=$REMOTEIP - fi lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') sst_ver=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $5 }') else @@ -638,6 +633,27 @@ send_donor() } +monitor_process() +{ + local sst_stream_pid=$1 + + while true ; do + + if ! ps --pid "${WSREP_SST_OPT_PARENT}" &>/dev/null; then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." + kill -- -"${WSREP_SST_OPT_PARENT}" + exit 32 + fi + + if ! ps --pid "${sst_stream_pid}" &>/dev/null; then + break + fi + + sleep 0.1 + + done +} + wsrep_check_programs "$INNOBACKUPEX_BIN" rm -f "${MAGIC_FILE}" @@ -923,7 +939,7 @@ then MAGIC_FILE="${DATA}/${INFO_FILE}" wsrep_log_info "Waiting for SST streaming to complete!" - wait $jpid + monitor_process $jpid get_proc diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index e5c534eef56..ca78d4917ff 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -375,6 +375,8 @@ EOF then wsrep_log_error \ "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." + kill -- -"${MYSQLD_PID}" + sleep 1 exit 32 fi diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 79442d415e9..11977249569 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -795,6 +795,27 @@ check_for_version() fi } +monitor_process() +{ + local sst_stream_pid=$1 + + while true ; do + + if ! ps --pid "${WSREP_SST_OPT_PARENT}" &>/dev/null; then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." + kill -- -"${WSREP_SST_OPT_PARENT}" + exit 32 + fi + + if ! ps --pid "${sst_stream_pid}" &>/dev/null; then + break + fi + + sleep 0.1 + + done +} + wsrep_check_programs "$INNOBACKUPEX_BIN" @@ -1093,7 +1114,7 @@ then MAGIC_FILE="${DATA}/${INFO_FILE}" wsrep_log_info "Waiting for SST streaming to complete!" - wait $jpid + monitor_process $jpid get_proc diff --git a/sql-common/client.c b/sql-common/client.c index 088377f8c52..1d354cefb0b 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1458,6 +1458,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if ((pkt_len= cli_safe_read(mysql)) == packet_error) DBUG_RETURN(0); + if (pkt_len == 0) DBUG_RETURN(0); if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) { @@ -2576,6 +2577,9 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, enum enum_ssl_init_error ssl_init_error; const char *cert_error; unsigned long ssl_error; +#ifdef EMBEDDED_LIBRARY + DBUG_ASSERT(0); // embedded should not do SSL connect +#endif /* Send mysql->client_flag, max_packet_size - unencrypted otherwise @@ -3657,7 +3661,7 @@ error: end_server(mysql); mysql_close_free(mysql); if (!(client_flag & CLIENT_REMEMBER_OPTIONS) && - !mysql->options.extension->async_context) + !(mysql->options.extension && mysql->options.extension->async_context)) mysql_close_free_options(mysql); } DBUG_RETURN(0); diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 0037ff23153..708c36a58b0 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -203,9 +203,7 @@ IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) SET(MYSQLD_LIB ${CMAKE_CURRENT_BINARY_DIR}/mysqld_lib.lib) SET(MYSQLD_CORELIBS sql mysys dbug strings) FOREACH (CORELIB ${MYSQLD_CORELIBS}) - GET_TARGET_PROPERTY(LOC ${CORELIB} LOCATION) - FILE(TO_NATIVE_PATH ${LOC} LOC) - SET (LIB_LOCATIONS ${LIB_LOCATIONS} ${LOC}) + SET (LIB_LOCATIONS ${LIB_LOCATIONS} $<TARGET_FILE:${CORELIB}>) ENDFOREACH (CORELIB) SET(_PLATFORM x86) @@ -307,8 +305,7 @@ TARGET_LINK_LIBRARIES(mysqld sql) # Provide plugins with minimal set of libraries SET(INTERFACE_LIBS ${LIBRT}) IF(INTERFACE_LIBS) - SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_INTERFACE_LIBRARIES - "${INTERFACE_LIBS}") + TARGET_LINK_LIBRARIES(mysqld LINK_PUBLIC ${INTERFACE_LIBS}) ENDIF() # On Solaris, some extra effort is required in order to get dtrace probes @@ -421,23 +418,20 @@ SET(DBOPT_FILE ${CMAKE_SOURCE_DIR}/support-files/db.opt ) INSTALL(FILES ${DBOPT_FILE} DESTINATION data/test COMPONENT DataFiles) # Install initial database on windows -IF(NOT CMAKE_CROSSCOMPILING) - GET_TARGET_PROPERTY(MYSQLD_EXECUTABLE mysqld LOCATION) -ENDIF() -IF(WIN32 AND MYSQLD_EXECUTABLE) - CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake - @ONLY - ) - +IF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING) + IF(MSVC_IDE OR CMAKE_GENERATOR MATCHES "Xcode") SET (CONFIG_PARAM -DCONFIG=${CMAKE_CFG_INTDIR}) ENDIF() MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/data) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep - COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -P ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake + COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} + -DTOP_SRCDIR="${CMAKE_SOURCE_DIR}" + -DBINDIR="${CMAKE_CURRENT_BINARY_DIR}" + -DMYSQLD_EXECUTABLE="$<TARGET_FILE:mysqld>" + -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}" + -P ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data DEPENDS mysqld @@ -455,7 +449,7 @@ IF(WIN32 AND MYSQLD_EXECUTABLE) ELSE() # Not windows or cross compiling, just install an empty directory INSTALL(FILES ${DUMMY_FILE} DESTINATION data/mysql COMPONENT DataFiles) -ENDIF(WIN32 AND MYSQLD_EXECUTABLE) +ENDIF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING) ENDIF(INSTALL_LAYOUT STREQUAL "STANDALONE") IF(WIN32) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 19cb4865ee6..02da3c31c3e 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1284,7 +1284,11 @@ Event_job_data::construct_sp_sql(THD *thd, String *sp_sql) */ sp_sql->append(STRING_WITH_LEN("() SQL SECURITY INVOKER ")); + if (thd->variables.sql_mode & MODE_ORACLE) + sp_sql->append(STRING_WITH_LEN(" AS BEGIN ")); sp_sql->append(&body); + if (thd->variables.sql_mode & MODE_ORACLE) + sp_sql->append(STRING_WITH_LEN("; END")); DBUG_RETURN(thd->is_fatal_error); } @@ -1387,9 +1391,6 @@ Event_job_data::execute(THD *thd, bool drop) goto end; } - if (construct_sp_sql(thd, &sp_sql)) - goto end; - /* Set up global thread attributes to reflect the properties of this Event. We can simply reset these instead of usual @@ -1401,6 +1402,9 @@ Event_job_data::execute(THD *thd, bool drop) thd->variables.sql_mode= sql_mode; thd->variables.time_zone= time_zone; + if (construct_sp_sql(thd, &sp_sql)) + goto end; + thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length()); { diff --git a/sql/field.cc b/sql/field.cc index e014b62788a..549fc157da9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8064,7 +8064,13 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs) return 0; } - if (table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT + /* + For min/max fields of statistical data 'table' is set to NULL. + It could not be otherwise as this data is shared by many instances + of the same base table. + */ + + if (table && table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT { DBUG_ASSERT(!f_is_hex_escape(flags)); DBUG_ASSERT(field_charset == cs); diff --git a/sql/handler.cc b/sql/handler.cc index b3481c7e429..e45607cad66 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6773,7 +6773,7 @@ int del_global_index_stats_for_table(THD *thd, uchar* cache_key, size_t cache_ke /* Remove a table from global table statistics */ -int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table) +int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table) { TABLE_STATS *table_stats; int res = 0; diff --git a/sql/handler.h b/sql/handler.h index 4bcb6438e08..f1080d56bb9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2,7 +2,7 @@ #define HANDLER_INCLUDED /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation. + Copyright (c) 2009, 2018, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -818,7 +818,7 @@ struct xid_t { bqual_length= b; memcpy(data, d, g+b); } - bool is_null() { return formatID == -1; } + bool is_null() const { return formatID == -1; } void null() { formatID= -1; } my_xid quick_get_my_xid() { @@ -4829,5 +4829,5 @@ void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag); void print_keydup_error(TABLE *table, KEY *key, myf errflag); int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); -int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table); +int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table); #endif /* HANDLER_INCLUDED */ diff --git a/sql/item.cc b/sql/item.cc index 8782efc88e3..77e751d7789 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. Copyright (c) 2010, 2018, MariaDB Corporation This program is free software; you can redistribute it and/or modify diff --git a/sql/item.h b/sql/item.h index 727d1f33f5f..c013781f30f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1765,6 +1765,11 @@ public: virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; } virtual bool exists2in_processor(void *arg) { return 0; } virtual bool find_selective_predicates_list_processor(void *arg) { return 0; } + bool cleanup_is_expensive_cache_processor(void *arg) + { + is_expensive_cache= (int8)(-1); + return 0; + } /* TRUE if the expression depends only on the table indicated by tab_map diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 856aae54a6b..e58644c1699 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2846,16 +2846,7 @@ public: bool fix_length_and_dec(); const char *func_name() const { return "regexp"; } enum precedence precedence() const { return CMP_PRECEDENCE; } - Item *get_copy(THD *thd) - { return get_item_copy<Item_func_regex>(thd, this); } - Item *build_clone(THD *thd) - { - Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd); - if (clone) - clone->re.reset(); - return clone; - } - + Item *get_copy(THD *) { return 0; } void print(String *str, enum_query_type query_type) { print_op(str, query_type); @@ -2895,8 +2886,7 @@ public: bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); const char *func_name() const { return "regexp_instr"; } - Item *get_copy(THD *thd) - { return get_item_copy<Item_func_regexp_instr>(thd, this); } + Item *get_copy(THD *thd) { return 0; } }; diff --git a/sql/item_func.h b/sql/item_func.h index 48b2ad2afeb..079775bb971 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -3165,15 +3165,7 @@ public: { return TRUE; } - Item *get_copy(THD *thd) - { return get_item_copy<Item_func_sp>(thd, this); } - Item *build_clone(THD *thd) - { - Item_func_sp *clone= (Item_func_sp *) Item_func::build_clone(thd); - if (clone) - clone->sp_result_field= NULL; - return clone; - } + Item *get_copy(THD *) { return 0; } bool eval_not_null_tables(void *opt_arg) { not_null_tables_cache= 0; diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 5e7f49e2a26..205f2c5d65f 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -479,7 +479,7 @@ String *Item_func_json_value::val_str(String *str) (const uchar *) js->ptr() + js->length()); str->length(0); - str->set_charset(&my_charset_utf8mb4_bin); + str->set_charset(collation.collation); path.cur_step= path.p.steps; continue_search: @@ -2387,8 +2387,9 @@ String *Item_func_json_insert::val_str(String *str) if ((null_value= args[0]->null_value)) return 0; - str->set_charset(js->charset()); - json_string_set_cs(&key_name, js->charset()); + str->set_charset(collation.collation); + tmp_js.set_charset(collation.collation); + json_string_set_cs(&key_name, collation.collation); for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++) { @@ -2602,7 +2603,6 @@ continue_point: json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); str->length(0); - str->set_charset(js->charset()); if (json_nice(&je, str, Item_func_json_format::LOOSE)) goto js_error; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 12618d68c27..50fe1624d48 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1568,32 +1568,18 @@ String *Item_str_conv::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res; - if (!(res=args[0]->val_str(str))) - { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ - } - null_value=0; - if (multiply == 1) - { - size_t len; - res= copy_if_not_alloced(&tmp_value, res, res->length()); - len= converter(collation.collation, (char*) res->ptr(), res->length(), - (char*) res->ptr(), res->length()); - DBUG_ASSERT(len <= res->length()); - res->length(len); - } - else - { - size_t len= res->length() * multiply; - tmp_value.alloc(len); - tmp_value.set_charset(collation.collation); - len= converter(collation.collation, (char*) res->ptr(), res->length(), - (char*) tmp_value.ptr(), len); - tmp_value.length(len); - res= &tmp_value; - } - return res; + size_t alloced_length, len; + + if ((null_value= (!(res= args[0]->val_str(&tmp_value)) || + str->alloc((alloced_length= res->length() * multiply))))) + return 0; + + len= converter(collation.collation, (char*) res->ptr(), res->length(), + (char*) str->ptr(), alloced_length); + DBUG_ASSERT(len <= alloced_length); + str->set_charset(collation.collation); + str->length(len); + return str; } @@ -1796,7 +1782,7 @@ String *Item_func_substr_index::val_str(String *str) DBUG_ASSERT(fixed == 1); char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),system_charset_info); - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); String *delimiter= args[1]->val_str(&tmp); int32 count= (int32) args[2]->val_int(); uint offset; @@ -1845,20 +1831,31 @@ String *Item_func_substr_index::val_str(String *str) if (pass == 0) /* count<0 */ { c+=n+1; - if (c<=0) return res; /* not found, return original string */ + if (c<=0) + { + str->copy(res->ptr(), res->length(), collation.collation); + return str; // not found, return the original string + } ptr=res->ptr(); } else { - if (c) return res; /* Not found, return original string */ + if (c) + { + str->copy(res->ptr(), res->length(), collation.collation); + return str; // not found, return the original string + } if (count>0) /* return left part */ { - tmp_value.set(*res,0,(ulong) (ptr-res->ptr())); + str->copy(res->ptr(), (uint32) (ptr-res->ptr()), collation.collation); + return str; } else /* return right part */ { - ptr+= delimiter_length; - tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr)); + ptr+= delimiter_length; + str->copy(res->ptr() + (ptr-res->ptr()), (uint32) (strend - ptr), + collation.collation); + return str; } } } @@ -1870,13 +1867,16 @@ String *Item_func_substr_index::val_str(String *str) { // start counting from the beginning for (offset=0; ; offset+= delimiter_length) { - if ((int) (offset= res->strstr(*delimiter, offset)) < 0) - return res; // Didn't find, return org string - if (!--count) - { - tmp_value.set(*res,0,offset); - break; - } + if ((int) (offset= res->strstr(*delimiter, offset)) < 0) + { + str->copy(res->ptr(), res->length(), collation.collation); + return str; // not found, return the original string + } + if (!--count) + { + str->copy(res->ptr(), offset, collation.collation); + return str; + } } } else @@ -1891,30 +1891,32 @@ String *Item_func_substr_index::val_str(String *str) address space less than where the found substring is located in res */ - if ((int) (offset= res->strrstr(*delimiter, offset)) < 0) - return res; // Didn't find, return org string + if ((int) (offset= res->strrstr(*delimiter, offset)) < 0) + { + str->copy(res->ptr(), res->length(), collation.collation); + return str; // not found, return the original string + } /* At this point, we've searched for the substring the number of times as supplied by the index value */ - if (!++count) - { - offset+= delimiter_length; - tmp_value.set(*res,offset,res->length()- offset); - break; - } + if (!++count) + { + offset+= delimiter_length; + str->copy(res->ptr() + offset, res->length() - offset, + collation.collation); + return str; + } } if (count) - return res; // Didn't find, return org string + { + str->copy(res->ptr(), res->length(), collation.collation); + return str; // not found, return the original string + } } } - /* - We always mark tmp_value as const so that if val_str() is called again - on this object, we don't disrupt the contents of tmp_value when it was - derived from another String. - */ - tmp_value.mark_as_const(); - return (&tmp_value); + DBUG_ASSERT(0); + return NULL; } /* diff --git a/sql/log.cc b/sql/log.cc index 6975b58dfb7..93f034543a5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2746,14 +2746,14 @@ void MYSQL_LOG::close(uint exiting) if (log_type == LOG_BIN && mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } if (!(exiting & LOG_CLOSE_DELAYED_CLOSE) && mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } } @@ -2937,7 +2937,7 @@ err: if (!write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } mysql_mutex_unlock(&LOCK_log); return TRUE; @@ -8474,8 +8474,7 @@ void MYSQL_BIN_LOG::close(uint exiting) ! write_error) { write_error= 1; - sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), - index_file_name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), index_file_name, errno); } } log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce14dc678c6..31ee89a7cd3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -484,7 +484,7 @@ my_bool opt_master_verify_checksum= 0; my_bool opt_slave_sql_verify_checksum= 1; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */ -uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; +uint mysqld_port, select_errors, dropping_tables, ha_open_options; uint mysqld_extra_port; uint mysqld_port_timeout; ulong delay_key_write_options; @@ -512,6 +512,7 @@ ulonglong max_binlog_cache_size=0; ulong slave_max_allowed_packet= 0; ulonglong binlog_stmt_cache_size=0; ulonglong max_binlog_stmt_cache_size=0; +ulonglong test_flags; ulonglong query_cache_size=0; ulong query_cache_limit=0; ulong executed_events=0; @@ -5769,6 +5770,11 @@ int win_main(int argc, char **argv) int mysqld_main(int argc, char **argv) #endif { +#ifndef _WIN32 + /* We can't close stdin just now, because it may be booststrap mode. */ + bool please_close_stdin= fcntl(STDIN_FILENO, F_GETFD) >= 0; +#endif + /* Perform basic thread library and malloc initialization, to be able to read defaults files and parse options. @@ -6166,7 +6172,7 @@ int mysqld_main(int argc, char **argv) #ifndef _WIN32 // try to keep fd=0 busy - if (!freopen("/dev/null", "r", stdin)) + if (please_close_stdin && !freopen("/dev/null", "r", stdin)) { // fall back on failure fclose(stdin); @@ -8330,7 +8336,7 @@ my_asn1_time_to_string(const ASN1_TIME *time, char *buf, size_t len) if (bio == NULL) return NULL; - if (!ASN1_TIME_print(bio, time)) + if (!ASN1_TIME_print(bio, const_cast<ASN1_TIME*>(time))) goto end; n_read= BIO_read(bio, buf, (int) (len - 1)); diff --git a/sql/mysqld.h b/sql/mysqld.h index 4a392eaf196..6c0c7308d91 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -169,7 +169,8 @@ extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size; extern ulong tc_log_page_waits; extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb; extern my_bool relay_log_recovery; -extern uint test_flags,select_errors,ha_open_options; +extern uint select_errors,ha_open_options; +extern ulonglong test_flags; extern uint protocol_version, mysqld_port, dropping_tables; extern ulong delay_key_write_options; extern char *opt_logname, *opt_slow_logname, *opt_bin_logname, diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 576ef5009b5..c289fb2bc85 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -110,7 +110,7 @@ void sql_print_error(const char *format,...); extern, but as it's hard to include sql_priv.h here, we have to live with this for a while. */ -extern uint test_flags; +extern ulonglong test_flags; extern ulong bytes_sent, bytes_received, net_big_packet_count; #ifdef HAVE_QUERY_CACHE #define USE_QUERY_CACHE diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 6f28ab59c15..107c0d8ed89 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7628,9 +7628,8 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, param->current_table); #ifdef HAVE_SPATIAL Field::geometry_type sav_geom_type; - LINT_INIT_STRUCT(sav_geom_type); - - if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) + const bool geometry= field_item->field->type() == MYSQL_TYPE_GEOMETRY; + if (geometry) { sav_geom_type= ((Field_geom*) field_item->field)->geom_type; /* We have to be able to store all sorts of spatial features here */ @@ -7665,7 +7664,7 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, } #ifdef HAVE_SPATIAL - if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) + if (geometry) { ((Field_geom*) field_item->field)->geom_type= sav_geom_type; } diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 37853bdbbe9..611e70376c8 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -413,7 +413,8 @@ bool JOIN::check_for_splittable_materialized() for (cand= cand_start; cand < cand_end; cand++) { - if (cand->underlying_field->field_index + 1 == fldnr) + if (cand->underlying_field->table == table && + cand->underlying_field->field_index + 1 == fldnr) { cand->is_usable_for_ref_access= true; break; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 06358b3cc20..d1877c6c245 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -441,6 +441,7 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs); static bool replace_where_subcondition(JOIN *, Item **, Item *, Item *, bool); static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2, void *arg); +static void reset_equality_number_for_subq_conds(Item * cond); static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred); static bool convert_subq_to_jtbm(JOIN *parent_join, Item_in_subselect *subq_pred, bool *remove); @@ -816,6 +817,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join) details) * require that compared columns have exactly the same type. This is a temporary measure to avoid BUG#36752-type problems. + + JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan expects that for Semi Join Materialization + Scan all the items in the select list of the IN Subquery are of the type Item::FIELD_ITEM. */ static @@ -1430,6 +1434,67 @@ static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2, } +/** + @brief + reset the value of the field in_eqaulity_no for all Item_func_eq + items in the where clause of the subquery. + + Look for in_equality_no description in Item_func_eq class + + DESCRIPTION + Lets have an example: + SELECT t1.a FROM t1 WHERE t1.a IN + (SELECT t2.a FROM t2 where t2.b IN + (select t3.b from t3 where t3.c=27 )) + + So for such a query we have the parent, child and + grandchild select. + + So for the equality t2.b = t3.b we set the value for in_equality_no to + 0 according to its description. Wewe do the same for t1.a = t2.a. + But when we look at the child select (with the grandchild select merged), + the query would be + + SELECT t1.a FROM t1 WHERE t1.a IN + (SELECT t2.a FROM t2 where t2.b = t3.b and t3.c=27) + + and then when the child select is merged into the parent select the query + would look like + + SELECT t1.a FROM t1, semi-join-nest(t2,t3) + WHERE t1.a =t2.a and t2.b = t3.b and t3.c=27 + + Still we would have in_equality_no set for t2.b = t3.b + though it does not take part in the semi-join equality for the parent select, + so we should reset its value to UINT_MAX. + + @param cond WHERE clause of the subquery +*/ + +static void reset_equality_number_for_subq_conds(Item * cond) +{ + if (!cond) + return; + if (cond->type() == Item::COND_ITEM) + { + List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); + Item *item; + while ((item=li++)) + { + if (item->type() == Item::FUNC_ITEM && + ((Item_func*)item)->functype()== Item_func::EQ_FUNC) + ((Item_func_eq*)item)->in_equality_no= UINT_MAX; + } + } + else + { + if (cond->type() == Item::FUNC_ITEM && + ((Item_func*)cond)->functype()== Item_func::EQ_FUNC) + ((Item_func_eq*)cond)->in_equality_no= UINT_MAX; + } + return; +} + /* Convert a subquery predicate into a TABLE_LIST semi-join nest @@ -1694,6 +1759,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) */ sj_nest->sj_in_exprs= subq_pred->left_expr->cols(); sj_nest->nested_join->sj_outer_expr_list.empty(); + reset_equality_number_for_subq_conds(sj_nest->sj_on_expr); if (subq_pred->left_expr->cols() == 1) { @@ -3506,7 +3572,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) first= tablenr - sjm->tables + 1; join->best_positions[first].n_sj_tables= sjm->tables; join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE; - join->sjm_lookup_tables|= s->table->map; + for (uint i= first; i < first+ sjm->tables; i++) + join->sjm_lookup_tables |= join->best_positions[i].table->table->map; } else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN) { diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc index ac17c7de40b..fc36ee35d5d 100644 --- a/sql/semisync_master_ack_receiver.cc +++ b/sql/semisync_master_ack_receiver.cc @@ -43,8 +43,7 @@ Ack_receiver::Ack_receiver() DBUG_ENTER("Ack_receiver::Ack_receiver"); m_status= ST_DOWN; - mysql_mutex_init(key_LOCK_ack_receiver, &m_mutex, - MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_ack_receiver, &m_mutex, NULL); mysql_cond_init(key_COND_ack_receiver, &m_cond, NULL); m_pid= 0; diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 86d0176dac1..df8baf045ac 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -144,8 +144,7 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) { sql_print_information("cannot connect to master to kill slave io_thread's " "connection"); - if (!ret) - mysql_close(kill_mysql); + mysql_close(kill_mysql); return; } size_t kill_buffer_length = my_snprintf(kill_buffer, 30, "KILL %lu", diff --git a/sql/share/CMakeLists.txt b/sql/share/CMakeLists.txt index 1461c57c5c3..2980e6153f5 100644 --- a/sql/share/CMakeLists.txt +++ b/sql/share/CMakeLists.txt @@ -45,12 +45,14 @@ SET(files errmsg-utf8.txt ) -FOREACH (dir ${dirs}) - INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} - DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) -ENDFOREACH() INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/charsets DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Common PATTERN "languages.html" EXCLUDE ) -INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) +IF (NOT WITHOUT_SERVER) + FOREACH (dir ${dirs}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} + DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) + ENDFOREACH() + INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) +ENDIF() diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d00ee3e07ef..88d1630d94b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. Copyright (c) 2009, 2018, MariaDB This program is free software; you can redistribute it and/or modify @@ -3362,7 +3362,8 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, ulong query_length= 0; bool clear_role= FALSE; char buff[512]; - enum_binlog_format save_binlog_format; + enum_binlog_format save_binlog_format= + thd->get_current_stmt_binlog_format(); const CSET_STRING query_save __attribute__((unused)) = thd->query_string; DBUG_ENTER("acl_set_default_role"); @@ -3402,6 +3403,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)) { thd->set_query(buff, query_length, system_charset_info); + // Attention!!! here is implicit goto error; WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); } @@ -10984,17 +10986,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, if (!(combo=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))) DBUG_RETURN(TRUE); - combo->user.str= sctx->user; + combo->user.str= (char *) sctx->priv_user; mysql_mutex_lock(&acl_cache->lock); - if ((au= find_user_wild(combo->host.str=(char*)sctx->host_or_ip, combo->user.str))) - goto found_acl; - if ((au= find_user_wild(combo->host.str=(char*)sctx->host, combo->user.str))) - goto found_acl; - if ((au= find_user_wild(combo->host.str=(char*)sctx->ip, combo->user.str))) - goto found_acl; - if ((au= find_user_wild(combo->host.str=(char*)"%", combo->user.str))) + if ((au= find_user_wild(combo->host.str= (char *) sctx->priv_host, + combo->user.str))) goto found_acl; mysql_mutex_unlock(&acl_cache->lock); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e46b7675bbe..4f1e149c291 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6837,6 +6837,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, Query_arena *arena, backup; bool result= TRUE; List<Natural_join_column> *non_join_columns; + List<Natural_join_column> *join_columns; DBUG_ENTER("store_natural_using_join_columns"); DBUG_ASSERT(!natural_using_join->join_columns); @@ -6844,7 +6845,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, arena= thd->activate_stmt_arena_if_needed(&backup); if (!(non_join_columns= new List<Natural_join_column>) || - !(natural_using_join->join_columns= new List<Natural_join_column>)) + !(join_columns= new List<Natural_join_column>)) goto err; /* Append the columns of the first join operand. */ @@ -6853,7 +6854,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, nj_col_1= it_1.get_natural_column_ref(); if (nj_col_1->is_common) { - natural_using_join->join_columns->push_back(nj_col_1, thd->mem_root); + join_columns->push_back(nj_col_1, thd->mem_root); /* Reset the common columns for the next call to mark_common_columns. */ nj_col_1->is_common= FALSE; } @@ -6874,7 +6875,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, { const char *using_field_name_ptr= using_field_name->c_ptr(); List_iterator_fast<Natural_join_column> - it(*(natural_using_join->join_columns)); + it(*join_columns); Natural_join_column *common_field; for (;;) @@ -6907,7 +6908,8 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, } if (non_join_columns->elements > 0) - natural_using_join->join_columns->append(non_join_columns); + join_columns->append(non_join_columns); + natural_using_join->join_columns= join_columns; natural_using_join->is_join_columns_complete= TRUE; result= FALSE; @@ -7139,7 +7141,6 @@ static bool setup_natural_join_row_types(THD *thd, DBUG_PRINT("info", ("using cached setup_natural_join_row_types")); DBUG_RETURN(false); } - context->select_lex->first_natural_join_processing= false; List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause); TABLE_LIST *table_ref; /* Current table reference. */ @@ -7184,6 +7185,7 @@ static bool setup_natural_join_row_types(THD *thd, change on re-execution */ context->natural_join_first_table= context->first_name_resolution_table; + context->select_lex->first_natural_join_processing= false; DBUG_RETURN (false); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 25e2d736cdc..8dc9dde2b18 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4036,6 +4036,10 @@ public: *format= (enum_binlog_format) variables.binlog_format; *current_format= current_stmt_binlog_format; } + inline enum_binlog_format get_current_stmt_binlog_format() + { + return current_stmt_binlog_format; + } inline void set_binlog_format(enum_binlog_format format, enum_binlog_format current_format) { @@ -4081,11 +4085,6 @@ public: DBUG_VOID_RETURN; } - inline enum_binlog_format get_current_stmt_binlog_format() - { - return current_stmt_binlog_format; - } - inline void set_current_stmt_binlog_format(enum_binlog_format format) { current_stmt_binlog_format= format; diff --git a/sql/sql_list.h b/sql/sql_list.h index 9f4eaae43f1..27827b42be5 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -278,10 +278,13 @@ public: */ inline void swap(base_list &rhs) { + list_node **rhs_last=rhs.last; swap_variables(list_node *, first, rhs.first); - swap_variables(list_node **, last, rhs.last); swap_variables(uint, elements, rhs.elements); + rhs.last= last == &first ? &rhs.first : last; + last = rhs_last == &rhs.first ? &first : rhs_last; } + inline list_node* last_node() { return *last; } inline list_node* first_node() { return first;} inline void *head() { return first->info; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1baa26ab465..49bee1889bd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -736,6 +736,9 @@ void init_update_queries(void) /* We don't want to replicate DROP for temp tables in row format */ sql_command_flags[SQLCOM_DROP_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT; sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT; + /* We don't want to replicate CREATE/DROP INDEX for temp tables in row format */ + sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT; + sql_command_flags[SQLCOM_DROP_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT; /* One can change replication mode with SET */ sql_command_flags[SQLCOM_SET_OPTION]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT; @@ -1597,10 +1600,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (thd->wsrep_conflict_state == ABORTED && command != COM_STMT_CLOSE && command != COM_QUIT) { + mysql_mutex_unlock(&thd->LOCK_thd_data); my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", MYF(0)); WSREP_DEBUG("Deadlock error for: %s", thd->query()); - mysql_mutex_unlock(&thd->LOCK_thd_data); thd->reset_killed(); thd->mysys_var->abort = 0; thd->wsrep_conflict_state = NO_CONFLICT; @@ -7895,36 +7898,46 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->lex->sql_command != SQLCOM_SELECT && (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) { - WSREP_DEBUG("wsrep retrying AC query: %s", + mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_DEBUG("wsrep retrying AC query: %s", (thd->query()) ? thd->query() : "void"); /* Performance Schema Interface instrumentation, end */ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); thd->m_statement_psi= NULL; thd->m_digest= NULL; + // Released thd->LOCK_thd_data above as below could end up + // close_thread_tables()/close_open_tables()/close_thread_table()/mysql_mutex_lock(&thd->LOCK_thd_data) close_thread_tables(thd); + mysql_mutex_lock(&thd->LOCK_thd_data); thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; thd->wsrep_retry_counter++; // grow wsrep_copy_query(thd); thd->set_time(); parser_state->reset(rawbuf, length); + mysql_mutex_unlock(&thd->LOCK_thd_data); } else { - WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", - (thd->wsrep_conflict_state == ABORTED) ? + mysql_mutex_unlock(&thd->LOCK_thd_data); + // This does dirty read to wsrep variables but it is only a debug code + WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", + (thd->wsrep_conflict_state == ABORTED) ? "BF Aborted" : "cert failure", (longlong) thd->thread_id, is_autocommit, - thd->wsrep_retry_counter, + thd->wsrep_retry_counter, thd->variables.wsrep_retry_autocommit, thd->query()); my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", MYF(0)); + + mysql_mutex_lock(&thd->LOCK_thd_data); thd->wsrep_conflict_state= NO_CONFLICT; if (thd->wsrep_conflict_state != REPLAYING) thd->wsrep_retry_counter= 0; // reset + mysql_mutex_unlock(&thd->LOCK_thd_data); } - mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->reset_killed(); } else @@ -7960,6 +7973,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, #endif /* WITH_WSREP */ } + /* When you modify mysql_parse(), you may need to modify mysql_test_parse_for_slave() in this same file. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bfd1c7580fc..7a8631a4ac1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1642,6 +1642,13 @@ JOIN::optimize_inner() if (optimize_constant_subqueries()) DBUG_RETURN(1); + if (conds && conds->with_subquery()) + (void) conds->walk(&Item::cleanup_is_expensive_cache_processor, + 0, (void *) 0); + if (having && having->with_subquery()) + (void) having->walk(&Item::cleanup_is_expensive_cache_processor, + 0, (void *) 0); + List<Item> eq_list; if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list)) @@ -1687,6 +1694,13 @@ JOIN::optimize_inner() conds= optimize_cond(this, conds, join_list, FALSE, &cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS); + if (thd->is_error()) + { + error= 1; + DBUG_PRINT("error",("Error from optimize_cond")); + DBUG_RETURN(1); + } + if (thd->lex->sql_command == SQLCOM_SELECT && optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)) { @@ -1752,13 +1766,6 @@ JOIN::optimize_inner() DBUG_RETURN(1); } - if (unlikely(thd->is_error())) - { - error= 1; - DBUG_PRINT("error",("Error from optimize_cond")); - DBUG_RETURN(1); - } - { having= optimize_cond(this, having, join_list, TRUE, &having_value, &having_equal); @@ -4618,8 +4625,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, int ref_changed; do { - more_const_tables_found: ref_changed = 0; + more_const_tables_found: found_ref=0; /* @@ -4788,7 +4795,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, } } } - } while (join->const_table_map & found_ref && ref_changed); + } while (ref_changed); join->sort_by_table= get_sort_by_table(join->order, join->group_list, join->select_lex->leaf_tables, @@ -9025,8 +9032,13 @@ bool JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, st_select_lex *sjm_sel= emb_sj_nest->sj_subq_pred->unit->first_select(); for (uint i= 0; i < sjm_sel->item_list.elements; i++) { - if (sjm_sel->ref_pointer_array[i] == keyuse->val) - return true; + DBUG_ASSERT(sjm_sel->ref_pointer_array[i]->real_item()->type() == Item::FIELD_ITEM); + if (keyuse->val->real_item()->type() == Item::FIELD_ITEM) + { + Field *field = ((Item_field*)sjm_sel->ref_pointer_array[i]->real_item())->field; + if (field->eq(((Item_field*)keyuse->val->real_item())->field)) + return true; + } } return false; } @@ -9674,7 +9686,6 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, if (first_keyuse) { key_parts++; - first_keyuse= FALSE; } else { @@ -9684,7 +9695,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, if (curr->keypart == keyuse->keypart && !(~used_tables & curr->used_tables) && join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, - keyuse) && + curr) && are_tables_local(join_tab, curr->used_tables)) break; } @@ -9692,6 +9703,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, key_parts++; } } + first_keyuse= FALSE; keyuse++; } while (keyuse->table == table && keyuse->is_for_hash_join()); if (!key_parts) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 00ed7fb0202..ea18484f8a4 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3060,6 +3060,39 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) /** + @breif + Cleanup of min/max statistical values for table share +*/ + +void delete_stat_values_for_table_share(TABLE_SHARE *table_share) +{ + TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb; + Table_statistics *table_stats= stats_cb->table_stats; + if (!table_stats) + return; + Column_statistics *column_stats= table_stats->column_stats; + if (!column_stats) + return; + + for (Field **field_ptr= table_share->field; + *field_ptr; + field_ptr++, column_stats++) + { + if (column_stats->min_value) + { + delete column_stats->min_value; + column_stats->min_value= NULL; + } + if (column_stats->max_value) + { + delete column_stats->max_value; + column_stats->max_value= NULL; + } + } +} + + +/** @brief Check whether any statistics is to be read for tables from a table list @@ -3289,7 +3322,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) The function is called when executing the statement DROP TABLE 'tab'. */ -int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab) +int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab) { int err; enum_binlog_format save_binlog_format; diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 7ec742b70db..c2700eaee41 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -92,9 +92,10 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables); int collect_statistics_for_table(THD *thd, TABLE *table); int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share, bool is_safe); +void delete_stat_values_for_table_share(TABLE_SHARE *table_share); int alloc_statistics_for_table(THD *thd, TABLE *table); int update_statistics_for_table(THD *thd, TABLE *table); -int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab); +int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab); int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col); int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, bool ext_prefixes_only); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 08e1c1c69d3..92fcba4972f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4860,6 +4860,8 @@ int create_table_impl(THD *thd, { if (options.or_replace()) { + (void) delete_statistics_for_table(thd, db, table_name); + TABLE_LIST table_list; table_list.init_one_table(db, table_name, 0, TL_WRITE_ALLOW_WRITE); table_list.table= create_info->table; @@ -5483,13 +5485,13 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db, } delete file; - if (unlikely(error)) - { - if (error == HA_ERR_WRONG_COMMAND) - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE"); - else - my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error); - } + if (error == HA_ERR_WRONG_COMMAND) + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE"); + else if (error == ENOTDIR) + my_error(ER_BAD_DB_ERROR, MYF(0), new_db->str); + else if (error) + my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error); + else if (!(flags & FN_IS_TMP)) mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name); diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index d515aacd1d0..34177242704 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -350,7 +350,8 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref, { DEBUG_SYNC(thd, "upgrade_lock_for_truncate"); /* To remove the table from the cache we need an exclusive lock. */ - if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DROP)) + if (wait_while_table_is_used(thd, table, + *hton_can_recreate ? HA_EXTRA_PREPARE_FOR_DROP : HA_EXTRA_NOT_USED)) DBUG_RETURN(TRUE); m_ticket_downgrade= table->mdl_ticket; /* Close if table is going to be recreated. */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 75a962939ae..6f65b960132 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -471,6 +471,10 @@ bool check_has_super(sys_var *self, THD *thd, set_var *var) return false; } +static Sys_var_bit Sys_core_file("core_file", "write a core-file on crashes", + READ_ONLY GLOBAL_VAR(test_flags), NO_CMD_LINE, + TEST_CORE_ON_SIGNAL, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, + 0,0,0); static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) { diff --git a/sql/table.cc b/sql/table.cc index e98836cd93c..5b6ed0921e3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2183,7 +2183,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, keyinfo= share->key_info; uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0], primary_key_name) ? MAX_KEY : 0; - KEY* key_first_info; + KEY* key_first_info= NULL; if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME) { @@ -6207,7 +6207,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col); } - DBUG_ASSERT(!nj_col->table_field || + DBUG_ASSERT(!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table); /* @@ -6256,7 +6256,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ RETURN # Pointer to a column of a natural join (or its operand) - NULL No memory to allocate the column + NULL We didn't originally have memory to allocate the column */ Natural_join_column * @@ -6272,7 +6272,7 @@ Field_iterator_table_ref::get_natural_column_ref() */ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && - (!nj_col->table_field || + (!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } @@ -7096,6 +7096,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info, The function checks whether a possible key satisfies the constraints imposed on the keys of any temporary table. + We need to filter out BLOB columns here, because ref access optimizer creates + KEYUSE objects for equalities for non-key columns for two puproses: + 1. To discover possible keys for derived_with_keys optimization + 2. To do hash joins + For the purpose of #1, KEYUSE objects are not created for "blob_column=..." . + However, they might be created for #2. In order to catch that case, we filter + them out here. + @return TRUE if the key is valid @return FALSE otherwise */ @@ -7111,11 +7119,12 @@ bool TABLE::check_tmp_key(uint key, uint key_parts, { uint fld_idx= next_field_no(arg); reg_field= field + fld_idx; + if ((*reg_field)->type() == MYSQL_TYPE_BLOB) + return FALSE; uint fld_store_len= (uint16) (*reg_field)->key_length(); if ((*reg_field)->real_maybe_null()) fld_store_len+= HA_KEY_NULL_LENGTH; - if ((*reg_field)->type() == MYSQL_TYPE_BLOB || - (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || + if ((*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || (*reg_field)->type() == MYSQL_TYPE_GEOMETRY) fld_store_len+= HA_KEY_BLOB_LENGTH; key_len+= fld_store_len; diff --git a/sql/table_cache.cc b/sql/table_cache.cc index a26a62bcfde..e82bb13228b 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -50,6 +50,7 @@ #include "lf.h" #include "table.h" #include "sql_base.h" +#include "sql_statistics.h" /** Configuration. */ @@ -991,6 +992,7 @@ void tdc_release_share(TABLE_SHARE *share) } if (share->tdc->flushed || tdc_records() > tdc_size) { + delete_stat_values_for_table_share(share); mysql_mutex_unlock(&LOCK_unused_shares); tdc_delete_share_from_hash(share->tdc); DBUG_VOID_RETURN; diff --git a/sql/tztime.cc b/sql/tztime.cc index 61fbee1731a..177521e5a55 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1653,7 +1653,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) { /* If we are in bootstrap mode we should not load time zone tables */ return_val= time_zone_tables_exist= 0; - goto end_with_setting_default_tz; + goto end_with_cleanup; } /* diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index cafd41b2653..0cbcdcd64aa 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -322,13 +322,28 @@ int wsrep_write_cache(wsrep_t* const wsrep, void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) { - char filename[PATH_MAX]= {0}; - int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log", + int len= snprintf(NULL, 0, "%s/GRA_%lld_%lld.log", wsrep_data_home_dir, (longlong) thd->thread_id, (longlong) wsrep_thd_trx_seqno(thd)); - if (len >= PATH_MAX) + if (len < 0) { - WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); + WSREP_ERROR("snprintf error: %d, skipping dump.", len); + return; + } + /* + len doesn't count the \0 end-of-string. Use len+1 below + to alloc and pass as an argument to snprintf. + */ + + char *filename= (char *)malloc(len+1); + int len1= snprintf(filename, len+1, "%s/GRA_%lld_%lld.log", + wsrep_data_home_dir, (longlong) thd->thread_id, + (long long)wsrep_thd_trx_seqno(thd)); + + if (len > len1) + { + WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len); + free(filename); return; } @@ -347,6 +362,7 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) WSREP_ERROR("Failed to open file '%s': %d (%s)", filename, errno, strerror(errno)); } + free(filename); } /* @@ -452,19 +468,34 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, { DBUG_ENTER("wsrep_dump_rbr_buf_with_header"); - char filename[PATH_MAX]= {0}; File file; IO_CACHE cache; Log_event_writer writer(&cache, 0); Format_description_log_event *ev= 0; - int len= my_snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld_v2.log", - wsrep_data_home_dir, (longlong) thd->thread_id, - (long long) wsrep_thd_trx_seqno(thd)); + longlong thd_trx_seqno= (long long)wsrep_thd_trx_seqno(thd); + int len= snprintf(NULL, 0, "%s/GRA_%lld_%lld_v2.log", + wsrep_data_home_dir, (longlong)thd->thread_id, + thd_trx_seqno); + /* + len doesn't count the \0 end-of-string. Use len+1 below + to alloc and pass as an argument to snprintf. + */ + char *filename; + if (len < 0 || !(filename= (char*)malloc(len+1))) + { + WSREP_ERROR("snprintf error: %d, skipping dump.", len); + DBUG_VOID_RETURN; + } + + int len1= snprintf(filename, len+1, "%s/GRA_%lld_%lld_v2.log", + wsrep_data_home_dir, (longlong) thd->thread_id, + thd_trx_seqno); - if (len >= PATH_MAX) + if (len > len1) { - WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); + WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len); + free(filename); DBUG_VOID_RETURN; } @@ -505,6 +536,7 @@ cleanup2: end_io_cache(&cache); cleanup1: + free(filename); mysql_file_close(file, MYF(MY_WME)); if (!thd->wsrep_applier) delete ev; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 0a2735fe0b7..667fdb779ea 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1480,6 +1480,25 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table, } } +static const char* wsrep_get_query_or_msg(const THD* thd) +{ + switch(thd->lex->sql_command) + { + case SQLCOM_CREATE_USER: + return "CREATE USER"; + case SQLCOM_GRANT: + return "GRANT"; + case SQLCOM_REVOKE: + return "REVOKE"; + case SQLCOM_SET_OPTION: + if (thd->lex->definer) + return "SET PASSWORD"; + /* fallthrough */ + default: + return thd->query(); + } +} + /* returns: 0: statement was replicated as TOI @@ -1502,7 +1521,8 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, } WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, thd->query() ); + thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd)); + switch (thd->lex->sql_command) { case SQLCOM_CREATE_VIEW: @@ -1576,8 +1596,8 @@ static void wsrep_TOI_end(THD *thd) { wsrep_status_t ret; wsrep_to_isolation--; - WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); + WSREP_DEBUG("TO END: %lld, %d: %s", (long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd)); wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index d5b0344c456..8816a31330e 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -192,8 +192,7 @@ void wsrep_sst_grab () // Wait for end of SST bool wsrep_sst_wait () { - struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0}; - uint32 total_wtime = 0; + double total_wtime = 0; if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); @@ -202,14 +201,18 @@ bool wsrep_sst_wait () while (!sst_complete) { + struct timespec wtime; + set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); + time_t start_time = time(NULL); mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime); + time_t end_time = time(NULL); if (!sst_complete) { - total_wtime += wtime.tv_sec; - WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime); + total_wtime += difftime(end_time, start_time); + WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime); service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP state transfer ongoing, current seqno: %ld", local_seqno); + "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); } } @@ -1365,19 +1368,22 @@ void wsrep_SE_init_grab() void wsrep_SE_init_wait() { - struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0}; - uint32 total_wtime=0; + double total_wtime=0; while (SE_initialized == false) { + struct timespec wtime; + set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); + time_t start_time = time(NULL); mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime); + time_t end_time = time(NULL); if (!SE_initialized) { - total_wtime += wtime.tv_sec; - WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime); + total_wtime += difftime(end_time, start_time); + WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime); service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP SE initialization ongoing."); + "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); } } diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc index 618c98eade7..2834100568a 100644 --- a/sql/wsrep_xid.cc +++ b/sql/wsrep_xid.cc @@ -156,15 +156,14 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) seqno= WSREP_SEQNO_UNDEFINED; XID xid; - memset(&xid, 0, sizeof(xid)); - xid.formatID= -1; + xid.null(); if (wsrep_get_SE_checkpoint(xid)) { return true; } - if (xid.formatID == -1) // nil XID + if (xid.is_null()) { return false; } diff --git a/storage/cassandra/CMakeLists.txt b/storage/cassandra/CMakeLists.txt index a5d58234d97..7f94c94f69d 100644 --- a/storage/cassandra/CMakeLists.txt +++ b/storage/cassandra/CMakeLists.txt @@ -21,7 +21,6 @@ IF(EXISTS ${Thrift_LIBS}) SET(CMAKE_REQUIRED_INCLUDES ${Thrift_INCLUDE_DIRS}) STRING(REPLACE "-fno-exceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") SET(CMAKE_REQUIRED_INCLUDES "${Thrift_INCLUDE_DIRS}/..") CHECK_CXX_SOURCE_COMPILES( diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 782d1f44bdf..9a08ff08425 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -338,14 +338,7 @@ IF(WIN32) # Install some extra files that belong to connect engine - # install ha_connect.lib - GET_TARGET_PROPERTY(CONNECT_LOCATION connect LOCATION) - STRING(REPLACE "dll" "lib" CONNECT_LIB ${CONNECT_LOCATION}) - IF(CMAKE_CONFIGURATION_TYPES) - STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}" - CONNECT_LIB ${CONNECT_LIB}) - ENDIF() - INSTALL(FILES ${CONNECT_LIB} + INSTALL(FILES "$<TARGET_FILE_DIR:connect>/ha_connect.lib" DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) ENDIF(WIN32) diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index 490ca3a5fba..ca48fc765a1 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -1173,11 +1173,11 @@ int DOSFAM::RenameTempFile(PGLOBAL g) remove(filetemp); // May still be there from previous error if (rename(filename, filetemp)) { // Save file for security - sprintf(g->Message, MSG(RENAME_ERROR), + snprintf(g->Message, MAX_STR, MSG(RENAME_ERROR), filename, filetemp, strerror(errno)); throw 51; } else if (rename(tempname, filename)) { - sprintf(g->Message, MSG(RENAME_ERROR), + snprintf(g->Message, MAX_STR, MSG(RENAME_ERROR), tempname, filename, strerror(errno)); rc = rename(filetemp, filename); // Restore saved file throw 52; diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index a660461e9ee..6d0779b150a 100644 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -65,11 +65,6 @@ extern int num_read, num_there; // Statistics static int num_write; -#if defined(UNIX) -// Add dummy strerror (NGC) -char *strerror(int num); -#endif // UNIX - /***********************************************************************/ /* Header containing block info for not split VEC tables. */ /* Block and last values can be calculated from NumRec and Nrec. */ @@ -353,7 +348,7 @@ int VCTFAM::Cardinality(PGLOBAL g) } // endif split - return (Block) ? ((Block - 1) * Nrec + Last) : 0; + return (Block) ? ((Block - 1) * Nrec + Last) : 0; } // end of Cardinality /***********************************************************************/ @@ -2458,11 +2453,11 @@ int VECFAM::RenameTempFile(PGLOBAL g) remove(filetemp); // May still be there from previous error if (rename(filename, filetemp)) { // Save file for security - sprintf(g->Message, MSG(RENAME_ERROR), + snprintf(g->Message, MAX_STR, MSG(RENAME_ERROR), filename, filetemp, strerror(errno)); rc = RC_FX; } else if (rename(tempname, filename)) { - sprintf(g->Message, MSG(RENAME_ERROR), + snprintf(g->Message, MAX_STR, MSG(RENAME_ERROR), tempname, filename, strerror(errno)); rc = rename(filetemp, filename); // Restore saved file rc = RC_FX; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index d78ee9ecc44..95885606dd0 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -170,7 +170,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.06.0007 March 11, 2018"; + char version[]= "Version 1.06.0007 August 06, 2018"; #if defined(__WIN__) char compver[]= "Version 1.06.0007 " __DATE__ " " __TIME__; char slash= '\\'; @@ -3299,23 +3299,15 @@ bool ha_connect::get_error_message(int error, String* buf) { DBUG_ENTER("ha_connect::get_error_message"); - if (xp && xp->g) { - PGLOBAL g= xp->g; - char msg[3072]; // MAX_STR * 3 - uint dummy_errors; - uint32 len= copy_and_convert(msg, strlen(g->Message) * 3, - system_charset_info, - g->Message, strlen(g->Message), - &my_charset_latin1, - &dummy_errors); + if (xp && xp->g) { + PGLOBAL g = xp->g; - if (trace(1)) - htrc("GEM(%d): len=%u %s\n", error, len, g->Message); + if (trace(1)) + htrc("GEM(%d): %s\n", error, g->Message); - msg[len]= '\0'; - buf->copy(msg, (uint)strlen(msg), system_charset_info); - } else - buf->copy("Cannot retrieve msg", 19, system_charset_info); + buf->append(g->Message); + } else + buf->append("Cannot retrieve error message"); DBUG_RETURN(false); } // end of get_error_message diff --git a/storage/connect/javaconn.cpp b/storage/connect/javaconn.cpp index d1be0ca1848..37a96351a3b 100644 --- a/storage/connect/javaconn.cpp +++ b/storage/connect/javaconn.cpp @@ -138,6 +138,16 @@ JAVAConn::JAVAConn(PGLOBAL g, PCSZ wrapper) // EndCom(); // } // end of ~JAVAConn +char *JAVAConn::GetUTFString(jstring s) +{ + char *str; + const char *utf = env->GetStringUTFChars(s, nullptr); + + str = PlugDup(m_G, utf); + env->ReleaseStringUTFChars(s, utf); + env->DeleteLocalRef(s); + return str; +} // end of GetUTFString /***********************************************************************/ /* Screen for errors. */ @@ -152,17 +162,15 @@ bool JAVAConn::Check(jint rc) "toString", "()Ljava/lang/String;"); if (exc != nullptr && tid != nullptr) { - jstring s = (jstring)env->CallObjectMethod(exc, tid); - const char *utf = env->GetStringUTFChars(s, (jboolean)false); - env->DeleteLocalRef(s); - Msg = PlugDup(m_G, utf); + s = (jstring)env->CallObjectMethod(exc, tid); + Msg = GetUTFString(s); } else Msg = "Exception occured"; env->ExceptionClear(); } else if (rc < 0) { s = (jstring)env->CallObjectMethod(job, errid); - Msg = (char*)env->GetStringUTFChars(s, (jboolean)false); + Msg = GetUTFString(s); } else Msg = NULL; diff --git a/storage/connect/javaconn.h b/storage/connect/javaconn.h index 54b7c4e92b7..73812f6ab3b 100644 --- a/storage/connect/javaconn.h +++ b/storage/connect/javaconn.h @@ -90,6 +90,7 @@ public: // Java operations protected: + char *GetUTFString(jstring s); bool gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig); bool Check(jint rc = 0); diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 33414ca74c2..24da65cf6a8 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -707,21 +707,14 @@ bool JDBConn::SetUUID(PGLOBAL g, PTDBJDBC tjp) goto err; } // endif rc - // Returns 666 is case of error - //jtyp = env->CallIntMethod(job, typid, 5, nullptr); + // Should return 666 is case of error (not done yet) + ctyp = (int)env->CallIntMethod(job, intfldid, 5, nullptr); - //if (Check((jtyp == 666) ? -1 : 1)) { - // sprintf(g->Message, "Getting jtyp: %s", Msg); + //if (Check((ctyp == 666) ? -1 : 1)) { + // sprintf(g->Message, "Getting ctyp: %s", Msg); // goto err; //} // endif ctyp - ctyp = (int)env->CallIntMethod(job, intfldid, 5, nullptr); - - if (Check(ctyp)) { - sprintf(g->Message, "Getting ctyp: %s", Msg); - goto err; - } // endif ctyp - if (ctyp == 1111) ((PJDBCCOL)colp)->uuid = true; @@ -836,11 +829,11 @@ bool JDBConn::Connect(PJPARM sop) jstring s = (jstring)env->CallObjectMethod(job, qcid); if (s != nullptr) { - char *qch = (char*)env->GetStringUTFChars(s, (jboolean)false); + char *qch = GetUTFString(s); m_IDQuoteChar[0] = *qch; } else { s = (jstring)env->CallObjectMethod(job, errid); - Msg = (char*)env->GetStringUTFChars(s, (jboolean)false); + Msg = GetUTFString(s); } // endif s } // endif qcid @@ -1018,7 +1011,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) cn = nullptr; if (cn) { - field = env->GetStringUTFChars(cn, (jboolean)false); + field = GetUTFString(cn); val->SetValue_psz((PSZ)field); } else val->Reset(); @@ -1092,8 +1085,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) cn = nullptr; if (cn) { - const char *field = env->GetStringUTFChars(cn, (jboolean)false); - val->SetValue_psz((PSZ)field); + val->SetValue_psz((PSZ)GetUTFString(cn)); } else val->Reset(); @@ -1372,19 +1364,19 @@ bool JDBConn::SetParam(JDBCCOL *colp) for (i = 0, n = 0; i < size; i++) { crp = qrp->Colresp; js = (jstring)env->GetObjectArrayElement(s, n++); - sval = (PSZ)env->GetStringUTFChars(js, 0); + sval = GetUTFString(js); crp->Kdata->SetValue(sval, i); crp = crp->Next; js = (jstring)env->GetObjectArrayElement(s, n++); - sval = (PSZ)env->GetStringUTFChars(js, 0); + sval = GetUTFString(js); crp->Kdata->SetValue(sval, i); crp = crp->Next; js = (jstring)env->GetObjectArrayElement(s, n++); - sval = (PSZ)env->GetStringUTFChars(js, 0); + sval = GetUTFString(js); crp->Kdata->SetValue(sval, i); crp = crp->Next; js = (jstring)env->GetObjectArrayElement(s, n++); - sval = (PSZ)env->GetStringUTFChars(js, 0); + sval = GetUTFString(js); crp->Kdata->SetValue(sval, i); } // endfor i @@ -1470,7 +1462,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) return NULL; } // endif label - name = env->GetStringUTFChars(label, (jboolean)false); + name = GetUTFString(label); crp = qrp->Colresp; // Column_Name crp->Kdata->SetValue((char*)name, i); n = env->GetIntArrayElements(val, 0); diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp index 0f5b18df4b4..84473534747 100644 --- a/storage/connect/jmgoconn.cpp +++ b/storage/connect/jmgoconn.cpp @@ -522,7 +522,7 @@ PSZ JMgoConn::GetDocument(void) jdc = (jstring)env->CallObjectMethod(job, getdocid); if (jdc) - doc = (PSZ)env->GetStringUTFChars(jdc, (jboolean)false); + doc = (PSZ)GetUTFString(jdc); } // endif getdocid @@ -690,7 +690,7 @@ jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp) } // endif Jncolp - return parent; + return parent; } // end of MakeDoc /***********************************************************************/ @@ -807,7 +807,7 @@ PSZ JMgoConn::GetColumnValue(PSZ path) fn = (jstring)env->CallObjectMethod(job, objfldid, jn); if (fn) - fld = (PSZ)env->GetStringUTFChars(fn, (jboolean)false); + fld = (PSZ)GetUTFString(fn); } // endif objfldid diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 3cc541c608f..145c48b81d5 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -4632,7 +4632,7 @@ char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result, bsp = NULL; if (!bsp && (bsp = JbinAlloc(g, args, initid->max_length, NULL))) - strncpy(bsp->Msg, g->Message, 139); + strncpy(bsp->Msg, g->Message, BMX); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; diff --git a/storage/connect/mysql-test/connect/r/jdbc.result b/storage/connect/mysql-test/connect/r/jdbc.result index 895b4070d70..a16f2791e8f 100644 --- a/storage/connect/mysql-test/connect/r/jdbc.result +++ b/storage/connect/mysql-test/connect/r/jdbc.result @@ -238,8 +238,7 @@ DROP TABLE t1, connect.emp; CREATE TABLE t2 (command varchar(128) not null,number int(5) not null flag=1,message varchar(255) flag=2) ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:mariadb://localhost:PORT/connect' OPTION_LIST='User=root,Execsrc=1'; SELECT * FROM t2 WHERE command='drop table tx1'; command number message -drop table tx1 0 Execute: java.sql.SQLSyntaxErrorException: Unknown table 'connect.tx1' -Query is : drop table tx1 +drop table tx1 0 Execute: java.sql.SQLSyntaxErrorException: (conn:24) Unknown table 'connect.tx1' SELECT * FROM t2 WHERE command = 'create table tx1 (a int not null, b char(32), c double(8,2))'; command number message create table tx1 (a int not null, b char(32), c double(8,2)) 0 Affected rows diff --git a/storage/connect/mysql-test/connect/r/xml2_mult.result b/storage/connect/mysql-test/connect/r/xml2_mult.result index a9592e986c0..87d1118edd5 100644 --- a/storage/connect/mysql-test/connect/r/xml2_mult.result +++ b/storage/connect/mysql-test/connect/r/xml2_mult.result @@ -51,14 +51,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -91,12 +91,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; diff --git a/storage/connect/mysql-test/connect/r/xml_mult.result b/storage/connect/mysql-test/connect/r/xml_mult.result index d89debadfab..9922b40060c 100644 --- a/storage/connect/mysql-test/connect/r/xml_mult.result +++ b/storage/connect/mysql-test/connect/r/xml_mult.result @@ -49,14 +49,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -89,12 +89,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index ba3e1c3e7c0..850d9e5fa9b 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -72,7 +72,7 @@ bool JMGDISC::Find(PGLOBAL g) bool JMGDISC::ColDesc(PGLOBAL g, jobject obj, char *pcn, char *pfmt, int ncol, int k) { - const char *key; + const char *key, *utf; char colname[65]; char fmt[129]; bool rc = true; @@ -101,7 +101,10 @@ bool JMGDISC::ColDesc(PGLOBAL g, jobject obj, char *pcn, char *pfmt, continue; jkey = (jstring)Jcp->env->CallObjectMethod(Jcp->job, bvnameid); - key = Jcp->env->GetStringUTFChars(jkey, (jboolean)false); + utf = Jcp->env->GetStringUTFChars(jkey, nullptr); + key = PlugDup(g, utf); + Jcp->env->ReleaseStringUTFChars(jkey, utf); + Jcp->env->DeleteLocalRef(jkey); if (pcn) { strncpy(colname, pcn, 64); @@ -457,8 +460,8 @@ PSZ JMGCOL::GetJpath(PGLOBAL g, bool proj) } else *p2++ = *p1; - *p2 = 0; - return projpath; + *p2 = 0; + return projpath; } else return Jpath; diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index da5d134f347..9121a0453e5 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -107,12 +107,12 @@ bool PIVAID::SkipColumn(PCOLRES crp, char *skc) /***********************************************************************/ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) { - char *p, *query, *colname, *skc, buf[64]; - int ndif, nblin, w = 0; - bool b = false; - PVAL valp; - PQRYRES qrp; - PCOLRES *pcrp, crp, fncrp = NULL; + char *p, *query, *colname, *skc, buf[64]; + int ndif, nblin, w = 0; + bool b = false; + PVAL valp; + PQRYRES qrp; + PCOLRES *pcrp, crp, fncrp = NULL; try { // Are there columns to skip? @@ -186,7 +186,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } // endif picol - // Prepare the column list + // Prepare the column list for (pcrp = &Qryp->Colresp; crp = *pcrp; ) if (SkipColumn(crp, skc)) { // Ignore this column @@ -205,95 +205,95 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } else pcrp = &crp->Next; - if (!Rblkp) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - goto err; - } else if (!fncrp) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - goto err; - } // endif + if (!Rblkp) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + goto err; + } else if (!fncrp) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + goto err; + } // endif - if (Tabsrc) { - Myc.Close(); - b = false; + if (Tabsrc) { + Myc.Close(); + b = false; - // Before calling sort, initialize all - nblin = Qryp->Nblin; + // Before calling sort, initialize all + nblin = Qryp->Nblin; - Index.Size = nblin * sizeof(int); - Index.Sub = TRUE; // Should be small enough + Index.Size = nblin * sizeof(int); + Index.Sub = TRUE; // Should be small enough - if (!PlgDBalloc(g, NULL, Index)) - goto err; + if (!PlgDBalloc(g, NULL, Index)) + goto err; - Offset.Size = (nblin + 1) * sizeof(int); - Offset.Sub = TRUE; // Should be small enough + Offset.Size = (nblin + 1) * sizeof(int); + Offset.Sub = TRUE; // Should be small enough - if (!PlgDBalloc(g, NULL, Offset)) - goto err; + if (!PlgDBalloc(g, NULL, Offset)) + goto err; - ndif = Qsort(g, nblin); + ndif = Qsort(g, nblin); - if (ndif < 0) // error - goto err; + if (ndif < 0) // error + goto err; - } else { - // The query was limited, we must get pivot column values - // Returned values must be in their original character set - // if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) - // goto err; + } else { + // The query was limited, we must get pivot column values + // Returned values must be in their original character set + // if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX) + // goto err; - query = (char*)PlugSubAlloc(g, NULL, 0); - sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname); - PlugSubAlloc(g, NULL, strlen(query) + 1); - Myc.FreeResult(); + query = (char*)PlugSubAlloc(g, NULL, 0); + sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname); + PlugSubAlloc(g, NULL, strlen(query) + 1); + Myc.FreeResult(); - // Send the source command to MySQL - if (Myc.ExecSQL(g, query, &w) == RC_FX) - goto err; + // Send the source command to MySQL + if (Myc.ExecSQL(g, query, &w) == RC_FX) + goto err; - // We must have a storage query to get pivot column values - if (!(qrp = Myc.GetResult(g, true))) - goto err; + // We must have a storage query to get pivot column values + if (!(qrp = Myc.GetResult(g, true))) + goto err; - Myc.Close(); - b = false; + Myc.Close(); + b = false; - // Get the column list - crp = qrp->Colresp; - Rblkp = crp->Kdata; - ndif = qrp->Nblin; - } // endif Tabsrc + // Get the column list + crp = qrp->Colresp; + Rblkp = crp->Kdata; + ndif = qrp->Nblin; + } // endif Tabsrc - // Allocate the Value used to retieve column names - if (!(valp = AllocateValue(g, Rblkp->GetType(), - Rblkp->GetVlen(), - Rblkp->GetPrec()))) - goto err; + // Allocate the Value used to retieve column names + if (!(valp = AllocateValue(g, Rblkp->GetType(), + Rblkp->GetVlen(), + Rblkp->GetPrec()))) + goto err; - // Now make the functional columns - for (int i = 0; i < ndif; i++) { - if (i) { - crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); - memcpy(crp, fncrp, sizeof(COLRES)); - } else - crp = fncrp; - - // Get the value that will be the generated column name - if (Tabsrc) - valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); - else - valp->SetValue_pvblk(Rblkp, i); - - colname = valp->GetCharString(buf); - crp->Name = PlugDup(g, colname); - crp->Flag = 1; - - // Add this column - *pcrp = crp; - crp->Next = NULL; - pcrp = &crp->Next; - } // endfor i + // Now make the functional columns + for (int i = 0; i < ndif; i++) { + if (i) { + crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + memcpy(crp, fncrp, sizeof(COLRES)); + } else + crp = fncrp; + + // Get the value that will be the generated column name + if (Tabsrc) + valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); + else + valp->SetValue_pvblk(Rblkp, i); + + colname = valp->GetCharString(buf); + crp->Name = PlugDup(g, colname); + crp->Flag = 1; + + // Add this column + *pcrp = crp; + crp->Next = NULL; + pcrp = &crp->Next; + } // endfor i // We added ndif columns and removed 2 (picol and fncol) Qryp->Nbcol += (ndif - 2); @@ -306,10 +306,10 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } // end catch err: - if (b) - Myc.Close(); + if (b) + Myc.Close(); - return NULL; + return NULL; } // end of MakePivotColumns /***********************************************************************/ diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 59666d4e127..325f36b1e19 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -429,7 +429,7 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) char buf[MAX_STR]; strcpy(buf, g->Message); - sprintf(g->Message, "Error accessing %s.%s: %s", db, name, buf); + snprintf(g->Message, MAX_STR, "Error accessing %s.%s: %s", db, name, buf); hc->tshp = NULL; goto err; } // endif Define diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index c96e0844497..16bc9f91017 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -1845,7 +1845,7 @@ void XMULCOL::ReadColumn(PGLOBAL g) if (N > Tdbp->Limit) { N = Tdbp->Limit; - sprintf(g->Message, "Mutiple values limited to %d", Tdbp->Limit); + sprintf(g->Message, "Multiple values limited to %d", Tdbp->Limit); PushWarning(g, Tdbp); } // endif N diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 9486f37f2f4..539ee522e2b 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -29,9 +29,12 @@ Created 03/11/2014 Shaohua Wang #include "btr0cur.h" #include "btr0pcur.h" #include "ibuf0ibuf.h" +#include "trx0trx.h" /** Innodb B-tree index fill factor for bulk load. */ uint innobase_fill_factor; +/** whether to reduce redo logging during ALTER TABLE */ +my_bool innodb_log_optimize_ddl; /** Initialize members, allocate page if needed and start mtr. Note: we commit all mtrs on failure. @@ -39,7 +42,6 @@ Note: we commit all mtrs on failure. dberr_t PageBulk::init() { - mtr_t* mtr; buf_block_t* new_block; page_t* new_page; page_zip_des_t* new_page_zip; @@ -48,12 +50,14 @@ PageBulk::init() ut_ad(m_heap == NULL); m_heap = mem_heap_create(1000); - mtr = static_cast<mtr_t*>( - mem_heap_alloc(m_heap, sizeof(mtr_t))); - mtr_start(mtr); - mtr_x_lock(dict_index_get_lock(m_index), mtr); - mtr_set_log_mode(mtr, MTR_LOG_NO_REDO); - mtr_set_flush_observer(mtr, m_flush_observer); + m_mtr.start(); + mtr_x_lock(&m_index->lock, &m_mtr); + if (m_flush_observer) { + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); + } else { + m_index->set_modified(m_mtr); + } if (m_page_no == FIL_NULL) { mtr_t alloc_mtr; @@ -71,14 +75,14 @@ PageBulk::init() m_index->table->space, 1, FSP_NORMAL, &alloc_mtr); if (!success) { - mtr_commit(&alloc_mtr); - mtr_commit(mtr); + alloc_mtr.commit(); + m_mtr.commit(); return(DB_OUT_OF_FILE_SPACE); } /* Allocate a new page. */ new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level, - &alloc_mtr, mtr); + &alloc_mtr, &m_mtr); m_index->table->space->release_free_extents(n_reserved); @@ -90,24 +94,35 @@ PageBulk::init() if (new_page_zip) { page_create_zip(new_block, m_index, m_level, 0, - NULL, mtr); + NULL, &m_mtr); + memset(FIL_PAGE_PREV + new_page, 0xff, 8); + page_zip_write_header(new_page_zip, + FIL_PAGE_PREV + new_page, + 8, &m_mtr); + mach_write_to_8(PAGE_HEADER + PAGE_INDEX_ID + new_page, + m_index->id); + page_zip_write_header(new_page_zip, + PAGE_HEADER + PAGE_INDEX_ID + + new_page, 8, &m_mtr); } else { ut_ad(!dict_index_is_spatial(m_index)); - page_create(new_block, mtr, + page_create(new_block, &m_mtr, dict_table_is_comp(m_index->table), false); - btr_page_set_level(new_page, NULL, m_level, mtr); + mlog_write_ulint(FIL_PAGE_PREV + new_page, FIL_NULL, + MLOG_4BYTES, &m_mtr); + mlog_write_ulint(FIL_PAGE_NEXT + new_page, FIL_NULL, + MLOG_4BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_LEVEL + new_page, + m_level, MLOG_2BYTES, &m_mtr); + mlog_write_ull(PAGE_HEADER + PAGE_INDEX_ID + new_page, + m_index->id, &m_mtr); } - - btr_page_set_next(new_page, NULL, FIL_NULL, mtr); - btr_page_set_prev(new_page, NULL, FIL_NULL, mtr); - - btr_page_set_index_id(new_page, NULL, m_index->id, mtr); } else { new_block = btr_block_get( page_id_t(m_index->table->space->id, m_page_no), page_size_t(m_index->table->space->flags), - RW_X_LATCH, m_index, mtr); + RW_X_LATCH, m_index, &m_mtr); new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); @@ -116,16 +131,14 @@ PageBulk::init() ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW); - btr_page_set_level(new_page, NULL, m_level, mtr); + btr_page_set_level(new_page, new_page_zip, m_level, &m_mtr); } - if (dict_index_is_sec_or_ibuf(m_index) - && !m_index->table->is_temporary() - && page_is_leaf(new_page)) { - page_update_max_trx_id(new_block, NULL, m_trx_id, mtr); + if (!m_level && dict_index_is_sec_or_ibuf(m_index)) { + page_update_max_trx_id(new_block, new_page_zip, m_trx_id, + &m_mtr); } - m_mtr = mtr; m_block = new_block; m_block->skip_flush_check = true; m_page = new_page; @@ -149,7 +162,9 @@ PageBulk::init() m_rec_no = page_header_get_field(new_page, PAGE_N_RECS); ut_d(m_total_data = 0); - page_header_set_field(m_page, NULL, PAGE_HEAP_TOP, srv_page_size - 1); + /* See page_copy_rec_list_end_to_created_page() */ + ut_d(page_header_set_field(m_page, NULL, PAGE_HEAP_TOP, + srv_page_size - 1)); return(DB_SUCCESS); } @@ -217,6 +232,14 @@ PageBulk::insert( m_free_space -= rec_size + slot_size; m_heap_top += rec_size; m_rec_no += 1; + + if (!m_flush_observer && !m_page_zip) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + page_cur_insert_rec_write_log(insert_rec, rec_size, + m_cur_rec, m_index, &m_mtr); + } + m_cur_rec = insert_rec; } @@ -227,15 +250,10 @@ void PageBulk::finish() { ut_ad(m_rec_no > 0); - -#ifdef UNIV_DEBUG ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no) <= page_get_free_space_of_empty(m_is_comp)); - - /* To pass the debug tests we have to set these dummy values - in the debug version */ - page_dir_set_n_slots(m_page, NULL, srv_page_size / 2); -#endif + /* See page_copy_rec_list_end_to_created_page() */ + ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2)); ulint count = 0; ulint n_recs = 0; @@ -286,15 +304,45 @@ PageBulk::finish() page_dir_slot_set_n_owned(slot, NULL, count + 1); ut_ad(!dict_index_is_spatial(m_index)); - page_dir_set_n_slots(m_page, NULL, 2 + slot_index); - page_header_set_ptr(m_page, NULL, PAGE_HEAP_TOP, m_heap_top); - page_dir_set_n_heap(m_page, NULL, PAGE_HEAP_NO_USER_LOW + m_rec_no); - page_header_set_ptr(m_page, NULL, PAGE_LAST_INSERT, m_cur_rec); - mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no); ut_ad(!page_get_instant(m_page)); - m_page[PAGE_HEADER + PAGE_DIRECTION_B] = PAGE_RIGHT; - *reinterpret_cast<uint16_t*>(PAGE_HEADER + PAGE_N_DIRECTION + m_page) - = 0; + + if (!m_flush_observer && !m_page_zip) { + mlog_write_ulint(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page, + 2 + slot_index, MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_HEAP_TOP + m_page, + ulint(m_heap_top - m_page), + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_HEAP + m_page, + (PAGE_HEAP_NO_USER_LOW + m_rec_no) + | ulint(m_is_comp) << 15, + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no, + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_LAST_INSERT + m_page, + ulint(m_cur_rec - m_page), + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page, + PAGE_RIGHT, MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0, + MLOG_2BYTES, &m_mtr); + } else { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_2(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page, + 2 + slot_index); + mach_write_to_2(PAGE_HEADER + PAGE_HEAP_TOP + m_page, + ulint(m_heap_top - m_page)); + mach_write_to_2(PAGE_HEADER + PAGE_N_HEAP + m_page, + (PAGE_HEAP_NO_USER_LOW + m_rec_no) + | ulint(m_is_comp) << 15); + mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no); + mach_write_to_2(PAGE_HEADER + PAGE_LAST_INSERT + m_page, + ulint(m_cur_rec - m_page)); + mach_write_to_2(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page, + PAGE_RIGHT); + mach_write_to_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0); + } + m_block->skip_flush_check = false; } @@ -308,15 +356,13 @@ PageBulk::commit( ut_ad(page_validate(m_page, m_index)); /* Set no free space left and no buffered changes in ibuf. */ - if (!dict_index_is_clust(m_index) - && !m_index->table->is_temporary() - && page_is_leaf(m_page)) { + if (!dict_index_is_clust(m_index) && page_is_leaf(m_page)) { ibuf_set_bitmap_for_bulk_load( m_block, innobase_fill_factor == 100); } } - mtr_commit(m_mtr); + m_mtr.commit(); } /** Compress a page of compressed table @@ -328,7 +374,7 @@ PageBulk::compress() ut_ad(m_page_zip != NULL); return(page_zip_compress(m_page_zip, m_page, m_index, - page_zip_level, NULL, m_mtr)); + page_zip_level, NULL, &m_mtr)); } /** Get node pointer @@ -475,20 +521,30 @@ PageBulk::copyOut( /** Set next page @param[in] next_page_no next page no */ -void -PageBulk::setNext( - ulint next_page_no) +inline void PageBulk::setNext(ulint next_page_no) { - btr_page_set_next(m_page, NULL, next_page_no, m_mtr); + if (UNIV_LIKELY_NULL(m_page_zip)) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no); + } else { + mlog_write_ulint(m_page + FIL_PAGE_NEXT, next_page_no, + MLOG_4BYTES, &m_mtr); + } } /** Set previous page @param[in] prev_page_no previous page no */ -void -PageBulk::setPrev( - ulint prev_page_no) +inline void PageBulk::setPrev(ulint prev_page_no) { - btr_page_set_prev(m_page, NULL, prev_page_no, m_mtr); + if (UNIV_LIKELY_NULL(m_page_zip)) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no); + } else { + mlog_write_ulint(m_page + FIL_PAGE_PREV, prev_page_no, + MLOG_4BYTES, &m_mtr); + } } /** Check if required space is available in the page for the rec to be inserted. @@ -561,7 +617,7 @@ PageBulk::storeExt( page_cur->block = m_block; dberr_t err = btr_store_big_rec_extern_fields( - &btr_pcur, offsets, big_rec, m_mtr, BTR_STORE_INSERT_BULK); + &btr_pcur, offsets, big_rec, &m_mtr, BTR_STORE_INSERT_BULK); ut_ad(page_offset(m_cur_rec) == page_offset(page_cur->rec)); @@ -587,30 +643,30 @@ PageBulk::release() /* No other threads can modify this block. */ m_modify_clock = buf_block_get_modify_clock(m_block); - mtr_commit(m_mtr); + m_mtr.commit(); } /** Start mtr and latch the block */ dberr_t PageBulk::latch() { - ibool ret; - - mtr_start(m_mtr); - mtr_x_lock(dict_index_get_lock(m_index), m_mtr); - mtr_set_log_mode(m_mtr, MTR_LOG_NO_REDO); - mtr_set_flush_observer(m_mtr, m_flush_observer); + m_mtr.start(); + mtr_x_lock(&m_index->lock, &m_mtr); + if (m_flush_observer) { + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); + } else { + m_index->set_modified(m_mtr); + } - /* TODO: need a simple and wait version of buf_page_optimistic_get. */ - ret = buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, - __FILE__, __LINE__, m_mtr); /* In case the block is S-latched by page_cleaner. */ - if (!ret) { + if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, + __FILE__, __LINE__, &m_mtr)) { m_block = buf_page_get_gen( page_id_t(m_index->table->space->id, m_page_no), page_size_t(m_index->table->space->flags), RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL, - __FILE__, __LINE__, m_mtr, &m_err); + __FILE__, __LINE__, &m_mtr, &m_err); if (m_err != DB_SUCCESS) { return (m_err); @@ -643,7 +699,7 @@ BtrBulk::pageSplit( } /* 2. create a new page. */ - PageBulk new_page_bulk(m_index, m_trx_id, FIL_NULL, + PageBulk new_page_bulk(m_index, m_trx->id, FIL_NULL, page_bulk->getLevel(), m_flush_observer); dberr_t err = new_page_bulk.init(); if (err != DB_SUCCESS) { @@ -722,8 +778,7 @@ BtrBulk::pageCommit( } /** Log free check */ -void -BtrBulk::logFreeCheck() +inline void BtrBulk::logFreeCheck() { if (log_sys.check_flush_or_checkpoint) { release(); @@ -738,10 +793,10 @@ BtrBulk::logFreeCheck() void BtrBulk::release() { - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->release(); } @@ -751,10 +806,10 @@ BtrBulk::release() void BtrBulk::latch() { - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->latch(); } } @@ -771,28 +826,26 @@ BtrBulk::insert( bool is_left_most = false; dberr_t err = DB_SUCCESS; - ut_ad(m_heap != NULL); - /* Check if we need to create a PageBulk for the level. */ - if (level + 1 > m_page_bulks->size()) { + if (level + 1 > m_page_bulks.size()) { PageBulk* new_page_bulk - = UT_NEW_NOKEY(PageBulk(m_index, m_trx_id, FIL_NULL, + = UT_NEW_NOKEY(PageBulk(m_index, m_trx->id, FIL_NULL, level, m_flush_observer)); err = new_page_bulk->init(); if (err != DB_SUCCESS) { return(err); } - m_page_bulks->push_back(new_page_bulk); - ut_ad(level + 1 == m_page_bulks->size()); + m_page_bulks.push_back(new_page_bulk); + ut_ad(level + 1 == m_page_bulks.size()); m_root_level = level; is_left_most = true; } - ut_ad(m_page_bulks->size() > level); + ut_ad(m_page_bulks.size() > level); - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); if (is_left_most && level > 0 && page_bulk->getRecNo() == 0) { /* The node pointer must be marked as the predefined minimum @@ -829,7 +882,7 @@ BtrBulk::insert( if (!page_bulk->isSpaceAvailable(rec_size)) { /* Create a sibling page_bulk. */ PageBulk* sibling_page_bulk; - sibling_page_bulk = UT_NEW_NOKEY(PageBulk(m_index, m_trx_id, + sibling_page_bulk = UT_NEW_NOKEY(PageBulk(m_index, m_trx->id, FIL_NULL, level, m_flush_observer)); err = sibling_page_bulk->init(); @@ -848,15 +901,18 @@ BtrBulk::insert( /* Set new page bulk to page_bulks. */ ut_ad(sibling_page_bulk->getLevel() <= m_root_level); - m_page_bulks->at(level) = sibling_page_bulk; + m_page_bulks.at(level) = sibling_page_bulk; UT_DELETE(page_bulk); page_bulk = sibling_page_bulk; /* Important: log_free_check whether we need a checkpoint. */ if (page_is_leaf(sibling_page_bulk->getPage())) { - /* Check whether trx is interrupted */ - if (m_flush_observer->check_interrupted()) { + if (trx_is_interrupted(m_trx)) { + if (m_flush_observer) { + m_flush_observer->interrupted(); + } + err = DB_INTERRUPTED; goto func_exit; } @@ -881,11 +937,11 @@ BtrBulk::insert( if (big_rec != NULL) { ut_ad(dict_index_is_clust(m_index)); ut_ad(page_bulk->getLevel() == 0); - ut_ad(page_bulk == m_page_bulks->at(0)); + ut_ad(page_bulk == m_page_bulks.at(0)); /* Release all latched but leaf node. */ for (ulint level = 1; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->release(); } @@ -894,7 +950,7 @@ BtrBulk::insert( /* Latch */ for (ulint level = 1; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->latch(); } } @@ -919,17 +975,17 @@ BtrBulk::finish(dberr_t err) ut_ad(!m_index->table->is_temporary()); - if (m_page_bulks->size() == 0) { + if (m_page_bulks.size() == 0) { /* The table is empty. The root page of the index tree is already in a consistent state. No need to flush. */ return(err); } - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); /* Finish all page bulks */ for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); last_page_no = page_bulk->getPageNo(); @@ -949,7 +1005,7 @@ BtrBulk::finish(dberr_t err) rec_t* first_rec; mtr_t mtr; buf_block_t* last_block; - PageBulk root_page_bulk(m_index, m_trx_id, + PageBulk root_page_bulk(m_index, m_trx->id, m_index->page, m_root_level, m_flush_observer); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 11dc5b43059..3d8d08573f7 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. Copyright (c) 2015, 2018, MariaDB Corporation. @@ -65,6 +65,8 @@ Created 10/16/1994 Heikki Tuuri #include "lock0lock.h" #include "zlib.h" #include "srv0start.h" +#include "mysql_com.h" +#include "dict0stats.h" /** Buffered B-tree operation types, introduced as part of delete buffering. */ enum btr_op_t { @@ -781,13 +783,15 @@ btr_cur_will_modify_tree( first record and following compress might delete the record and causes the uppper level node_ptr modification. */ + const ulint n_recs = page_get_n_recs(page); + if (lock_intention <= BTR_INTENTION_BOTH) { ulint margin; /* check delete will cause. (BTR_INTENTION_BOTH or BTR_INTENTION_DELETE) */ /* first, 2nd, 2nd-last and last records are 4 records */ - if (page_get_n_recs(page) < 5) { + if (n_recs < 5) { return(true); } @@ -833,8 +837,7 @@ btr_cur_will_modify_tree( /* Once we invoke the btr_cur_limit_optimistic_insert_debug, we should check it here in advance, since the max allowable records in a page is limited. */ - LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), - return(true)); + LIMIT_OPTIMISTIC_INSERT_DEBUG(n_recs, return true); /* needs 2 records' space for the case the single split and insert cannot fit. @@ -847,18 +850,16 @@ btr_cur_will_modify_tree( || max_size < rec_size * 2) { return(true); } - /* TODO: optimize this condition for compressed page. - this is based on the worst compress rate. - currently looking only uncompressed page, but we can look - also compressed page page_zip_available() if already in the - buffer pool */ + + /* TODO: optimize this condition for ROW_FORMAT=COMPRESSED. + This is based on the worst case, and we could invoke + page_zip_available() on the block->page.zip. */ /* needs 2 records' space also for worst compress rate. */ if (page_size.is_compressed() && page_zip_empty_size(index->n_fields, page_size.physical()) - < rec_size * 2 + page_get_data_size(page) - + page_dir_calc_reserved_space( - ulint(page_get_n_recs(page)) + 2) + 1) { + <= rec_size * 2 + page_get_data_size(page) + + page_dir_calc_reserved_space(n_recs + 2)) { return(true); } } @@ -893,6 +894,114 @@ btr_cur_need_opposite_intention( return(false); } +/** +@param[in] index b-tree +@return maximum size of a node pointer record in bytes */ +static ulint btr_node_ptr_max_size(const dict_index_t* index) +{ + if (dict_index_is_ibuf(index)) { + /* cannot estimate accurately */ + /* This is universal index for change buffer. + The max size of the entry is about max key length * 2. + (index key + primary key to be inserted to the index) + (The max key length is UNIV_PAGE_SIZE / 16 * 3 at + ha_innobase::max_supported_key_length(), + considering MAX_KEY_LENGTH = 3072 at MySQL imposes + the 3500 historical InnoDB value for 16K page size case.) + For the universal index, node_ptr contains most of the entry. + And 512 is enough to contain ibuf columns and meta-data */ + return srv_page_size / 8 * 3 + 512; + } + + /* Each record has page_no, length of page_no and header. */ + ulint comp = dict_table_is_comp(index->table); + ulint rec_max_size = comp + ? REC_NODE_PTR_SIZE + 1 + REC_N_NEW_EXTRA_BYTES + + UT_BITS_IN_BYTES(index->n_nullable) + : REC_NODE_PTR_SIZE + 2 + REC_N_OLD_EXTRA_BYTES + + 2 * index->n_fields; + + /* Compute the maximum possible record size. */ + for (ulint i = 0; i < dict_index_get_n_unique_in_tree(index); i++) { + const dict_field_t* field + = dict_index_get_nth_field(index, i); + const dict_col_t* col + = dict_field_get_col(field); + ulint field_max_size; + ulint field_ext_max_size; + + /* Determine the maximum length of the index field. */ + + field_max_size = dict_col_get_fixed_size(col, comp); + if (field_max_size) { + /* dict_index_add_col() should guarantee this */ + ut_ad(!field->prefix_len + || field->fixed_len == field->prefix_len); + /* Fixed lengths are not encoded + in ROW_FORMAT=COMPACT. */ + rec_max_size += field_max_size; + continue; + } + + field_max_size = dict_col_get_max_size(col); + if (UNIV_UNLIKELY(!field_max_size)) { + /* SYS_FOREIGN.ID is defined as CHAR in the + InnoDB internal SQL parser, which translates + into the incorrect VARCHAR(0). InnoDB does + not enforce maximum lengths of columns, so + that is why any data can be inserted in the + first place. + + Likewise, SYS_FOREIGN.FOR_NAME, + SYS_FOREIGN.REF_NAME, SYS_FOREIGN_COLS.ID, are + defined as CHAR, and also they are part of a key. */ + + ut_ad(!strcmp(index->table->name.m_name, + "SYS_FOREIGN") + || !strcmp(index->table->name.m_name, + "SYS_FOREIGN_COLS")); + ut_ad(!comp); + + rec_max_size += (srv_page_size == UNIV_PAGE_SIZE_MAX) + ? REDUNDANT_REC_MAX_DATA_SIZE + : page_get_free_space_of_empty(FALSE) / 2; + } else if (field_max_size == NAME_LEN && i == 1 + && (!strcmp(index->table->name.m_name, + TABLE_STATS_NAME) + || !strcmp(index->table->name.m_name, + INDEX_STATS_NAME))) { + ut_ad(!strcmp(field->name, "table_name")); + /* Interpret "table_name" as VARCHAR(199) even + if it was incorrectly defined as VARCHAR(64). + While the caller of ha_innobase enforces the + maximum length on any data written, the InnoDB + internal SQL parser will happily write as much + data as is provided. The purpose of this hack + is to avoid InnoDB hangs after persistent + statistics on partitioned tables are + deleted. */ + field_max_size = 199 * SYSTEM_CHARSET_MBMAXLEN; + } + field_ext_max_size = field_max_size < 256 ? 1 : 2; + + if (field->prefix_len + && field->prefix_len < field_max_size) { + field_max_size = field->prefix_len; + } + + if (comp) { + /* Add the extra size for ROW_FORMAT=COMPACT. + For ROW_FORMAT=REDUNDANT, these bytes were + added to rec_max_size before this loop. */ + rec_max_size += field_ext_max_size; + } + + rec_max_size += field_max_size; + } + + return rec_max_size; +} + /********************************************************************//** Searches an index tree and positions a tree cursor on a given level. NOTE: n_fields_cmp in tuple must be set so that it cannot be compared @@ -1218,7 +1327,7 @@ btr_cur_search_to_nth_level_func( page_id_t page_id(index->table->space->id, index->page); if (root_leaf_rw_latch == RW_X_LATCH) { - node_ptr_max_size = dict_index_node_ptr_max_size(index); + node_ptr_max_size = btr_node_ptr_max_size(index); } up_match = 0; @@ -2327,7 +2436,7 @@ btr_cur_open_at_index_side_func( const page_size_t page_size(index->table->space->flags); if (root_leaf_rw_latch == RW_X_LATCH) { - node_ptr_max_size = dict_index_node_ptr_max_size(index); + node_ptr_max_size = btr_node_ptr_max_size(index); } height = ULINT_UNDEFINED; @@ -2685,7 +2794,7 @@ btr_cur_open_at_rnd_pos_func( dberr_t err = DB_SUCCESS; if (root_leaf_rw_latch == RW_X_LATCH) { - node_ptr_max_size = dict_index_node_ptr_max_size(index); + node_ptr_max_size = btr_node_ptr_max_size(index); } height = ULINT_UNDEFINED; @@ -5657,23 +5766,45 @@ discard_page: } } - page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, offsets, mtr); + /* SPATIAL INDEX never use SX locks; we can allow page merges + while holding X lock on the spatial index tree. + Do not allow merges of non-leaf B-tree pages unless it is + safe to do so. */ + { + const bool allow_merge = page_is_leaf(page) + || dict_index_is_spatial(index) + || btr_cur_will_modify_tree( + index, page, BTR_INTENTION_DELETE, rec, + btr_node_ptr_max_size(index), + block->page.size, mtr); + page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, + offsets, mtr); #ifdef UNIV_ZIP_DEBUG - ut_a(!page_zip || page_zip_validate(page_zip, page, index)); + ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ -return_after_reservations: - /* btr_check_node_ptr() needs parent block latched */ - ut_ad(!parent_latched || btr_check_node_ptr(index, block, mtr)); + ut_ad(!parent_latched + || btr_check_node_ptr(index, block, mtr)); + + if (!ret && btr_cur_compress_recommendation(cursor, mtr)) { + if (UNIV_LIKELY(allow_merge)) { + ret = btr_cur_compress_if_useful( + cursor, FALSE, mtr); + } else { + ib::warn() << "Not merging page " + << block->page.id + << " in index " << index->name + << " of " << index->table->name; + ut_ad(!"MDEV-14637"); + } + } + } +return_after_reservations: *err = DB_SUCCESS; mem_heap_free(heap); - if (ret == FALSE) { - ret = btr_cur_compress_if_useful(cursor, FALSE, mtr); - } - if (!srv_read_only_mode && page_is_leaf(page) && !dict_index_is_online_ddl(index)) { diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index 27a45654966..f932195897c 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -124,7 +124,7 @@ buf_buddy_stamp_free( buf_buddy_free_t* buf, /*!< in/out: block to stamp */ ulint i) /*!< in: block size */ { - ut_d(memset(buf, static_cast<int>(i), BUF_BUDDY_LOW << i)); + ut_d(memset(&buf->stamp.bytes, int(i), BUF_BUDDY_LOW << i)); buf_buddy_mem_invalid(buf, i); mach_write_to_4(buf->stamp.bytes + BUF_BUDDY_STAMP_OFFSET, BUF_BUDDY_STAMP_FREE); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index f053c170c0e..bd64334c3ba 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2258,7 +2258,7 @@ buf_page_realloc( mutex_enter(&new_block->mutex); memcpy(new_block->frame, block->frame, srv_page_size); - memcpy(&new_block->page, &block->page, sizeof block->page); + new (&new_block->page) buf_page_t(block->page); /* relocate LRU list */ ut_ad(block->page.in_LRU_list); @@ -3389,7 +3389,7 @@ buf_relocate( } #endif /* UNIV_DEBUG */ - memcpy(dpage, bpage, sizeof *dpage); + new (dpage) buf_page_t(*bpage); /* Important that we adjust the hazard pointer before removing bpage from LRU list. */ diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index a0c4baad64d..7ede67fd0e4 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -262,7 +262,7 @@ buf_dump( #define SHOULD_QUIT() (SHUTTING_DOWN() && obey_shutdown) char full_filename[OS_FILE_MAX_PATH]; - char tmp_filename[OS_FILE_MAX_PATH]; + char tmp_filename[OS_FILE_MAX_PATH + sizeof "incomplete"]; char now[32]; FILE* f; ulint i; diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index e3c351eca67..f8ec51d00f0 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -3769,18 +3769,12 @@ FlushObserver::~FlushObserver() DBUG_LOG("flush", "~FlushObserver(): trx->id=" << m_trx->id); } -/** Check whether trx is interrupted -@return true if trx is interrupted */ -bool -FlushObserver::check_interrupted() +/** Check whether the operation has been interrupted */ +void FlushObserver::check_interrupted() { if (trx_is_interrupted(m_trx)) { interrupted(); - - return(true); } - - return(false); } /** Notify observer of a flush diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index ebd5c2a828b..125c5beb47c 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1610,7 +1610,7 @@ func_exit: } else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { b = buf_page_alloc_descriptor(); ut_a(b); - memcpy(b, bpage, sizeof *b); + new (b) buf_page_t(*bpage); } ut_ad(buf_pool_mutex_own(buf_pool)); diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc index 949bbbc0d74..69038d4cb77 100644 --- a/storage/innobase/dict/dict0defrag_bg.cc +++ b/storage/innobase/dict/dict0defrag_bg.cc @@ -39,27 +39,13 @@ static ib_mutex_t defrag_pool_mutex; static mysql_pfs_key_t defrag_pool_mutex_key; #endif -/** Indices whose defrag stats need to be saved to persistent storage.*/ -struct defrag_pool_item_t { - table_id_t table_id; - index_id_t index_id; -}; - -/** Allocator type, used by std::vector */ -typedef ut_allocator<defrag_pool_item_t> - defrag_pool_allocator_t; - -/** The multitude of tables to be defragmented- an STL vector */ -typedef std::vector<defrag_pool_item_t, defrag_pool_allocator_t> - defrag_pool_t; - /** Iterator type for iterating over the elements of objects of type defrag_pool_t. */ typedef defrag_pool_t::iterator defrag_pool_iterator_t; /** Pool where we store information on which tables are to be processed by background defragmentation. */ -static defrag_pool_t* defrag_pool; +defrag_pool_t defrag_pool; extern bool dict_stats_start_shutdown; @@ -70,14 +56,6 @@ dict_defrag_pool_init(void) /*=======================*/ { ut_ad(!srv_read_only_mode); - /* JAN: TODO: MySQL 5.7 PSI - const PSI_memory_key key2 = mem_key_dict_defrag_pool_t; - - defrag_pool = UT_NEW(defrag_pool_t(defrag_pool_allocator_t(key2)), key2); - - recalc_pool->reserve(RECALC_POOL_INITIAL_SLOTS); - */ - defrag_pool = new std::vector<defrag_pool_item_t, defrag_pool_allocator_t>(); /* We choose SYNC_STATS_DEFRAG to be below SYNC_FSP_PAGE. */ mutex_create(LATCH_ID_DEFRAGMENT_MUTEX, &defrag_pool_mutex); @@ -92,10 +70,7 @@ dict_defrag_pool_deinit(void) { ut_ad(!srv_read_only_mode); - defrag_pool->clear(); mutex_free(&defrag_pool_mutex); - - UT_DELETE(defrag_pool); } /*****************************************************************//** @@ -115,16 +90,16 @@ dict_stats_defrag_pool_get( mutex_enter(&defrag_pool_mutex); - if (defrag_pool->empty()) { + if (defrag_pool.empty()) { mutex_exit(&defrag_pool_mutex); return(false); } - defrag_pool_item_t& item = defrag_pool->back(); + defrag_pool_item_t& item = defrag_pool.back(); *table_id = item.table_id; *index_id = item.index_id; - defrag_pool->pop_back(); + defrag_pool.pop_back(); mutex_exit(&defrag_pool_mutex); @@ -149,8 +124,8 @@ dict_stats_defrag_pool_add( mutex_enter(&defrag_pool_mutex); /* quit if already in the list */ - for (defrag_pool_iterator_t iter = defrag_pool->begin(); - iter != defrag_pool->end(); + for (defrag_pool_iterator_t iter = defrag_pool.begin(); + iter != defrag_pool.end(); ++iter) { if ((*iter).table_id == index->table->id && (*iter).index_id == index->id) { @@ -161,7 +136,7 @@ dict_stats_defrag_pool_add( item.table_id = index->table->id; item.index_id = index->id; - defrag_pool->push_back(item); + defrag_pool.push_back(item); mutex_exit(&defrag_pool_mutex); @@ -183,14 +158,14 @@ dict_stats_defrag_pool_del( mutex_enter(&defrag_pool_mutex); - defrag_pool_iterator_t iter = defrag_pool->begin(); - while (iter != defrag_pool->end()) { + defrag_pool_iterator_t iter = defrag_pool.begin(); + while (iter != defrag_pool.end()) { if ((table && (*iter).table_id == table->id) || (index && (*iter).table_id == index->table->id && (*iter).index_id == index->id)) { /* erase() invalidates the iterator */ - iter = defrag_pool->erase(iter); + iter = defrag_pool.erase(iter); if (index) break; } else { @@ -252,7 +227,7 @@ void dict_defrag_process_entries_from_defrag_pool() /*==========================================*/ { - while (defrag_pool->size() && !dict_stats_start_shutdown) { + while (defrag_pool.size() && !dict_stats_start_shutdown) { dict_stats_process_entry_from_defrag_pool(); } } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index f088e6d356c..51190ff2ef6 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2089,93 +2089,6 @@ dict_col_name_is_reserved( } /****************************************************************//** -Return maximum size of the node pointer record. -@return maximum size of the record in bytes */ -ulint -dict_index_node_ptr_max_size( -/*=========================*/ - const dict_index_t* index) /*!< in: index */ -{ - ulint comp; - ulint i; - /* maximum possible storage size of a record */ - ulint rec_max_size; - - if (dict_index_is_ibuf(index)) { - /* cannot estimate accurately */ - /* This is universal index for change buffer. - The max size of the entry is about max key length * 2. - (index key + primary key to be inserted to the index) - (The max key length is srv_page_size / 16 * 3 at - ha_innobase::max_supported_key_length(), - considering MAX_KEY_LENGTH = 3072 at MySQL imposes - the 3500 historical InnoDB value for 16K page size case.) - For the universal index, node_ptr contains most of the entry. - And 512 is enough to contain ibuf columns and meta-data */ - return(srv_page_size / 8 * 3 + 512); - } - - comp = dict_table_is_comp(index->table); - - /* Each record has page_no, length of page_no and header. */ - rec_max_size = comp - ? REC_NODE_PTR_SIZE + 1 + REC_N_NEW_EXTRA_BYTES - : REC_NODE_PTR_SIZE + 2 + REC_N_OLD_EXTRA_BYTES; - - if (comp) { - /* Include the "null" flags in the - maximum possible record size. */ - rec_max_size += UT_BITS_IN_BYTES(unsigned(index->n_nullable)); - } else { - /* For each column, include a 2-byte offset and a - "null" flag. */ - rec_max_size += 2 * unsigned(index->n_fields); - } - - /* Compute the maximum possible record size. */ - for (i = 0; i < dict_index_get_n_unique_in_tree(index); i++) { - const dict_field_t* field - = dict_index_get_nth_field(index, i); - const dict_col_t* col - = dict_field_get_col(field); - ulint field_max_size; - ulint field_ext_max_size; - - /* Determine the maximum length of the index field. */ - - field_max_size = dict_col_get_fixed_size(col, comp); - if (field_max_size) { - /* dict_index_add_col() should guarantee this */ - ut_ad(!field->prefix_len - || field->fixed_len == field->prefix_len); - /* Fixed lengths are not encoded - in ROW_FORMAT=COMPACT. */ - rec_max_size += field_max_size; - continue; - } - - field_max_size = dict_col_get_max_size(col); - field_ext_max_size = field_max_size < 256 ? 1 : 2; - - if (field->prefix_len - && field->prefix_len < field_max_size) { - field_max_size = field->prefix_len; - } - - if (comp) { - /* Add the extra size for ROW_FORMAT=COMPACT. - For ROW_FORMAT=REDUNDANT, these bytes were - added to rec_max_size before this loop. */ - rec_max_size += field_ext_max_size; - } - - rec_max_size += field_max_size; - } - - return(rec_max_size); -} - -/****************************************************************//** If a record of this index might not fit on a single B-tree page, return TRUE. @return TRUE if the index record could become too big */ @@ -6460,8 +6373,17 @@ dict_table_schema_check( compare column types and flags */ /* check length for exact match */ - if (req_schema->columns[i].len != table->cols[j].len) { - + if (req_schema->columns[i].len == table->cols[j].len) { + } else if (!strcmp(req_schema->table_name, TABLE_STATS_NAME) + || !strcmp(req_schema->table_name, + INDEX_STATS_NAME)) { + ut_ad(table->cols[j].len < req_schema->columns[i].len); + ib::warn() << "Table " << req_schema->table_name + << " has length mismatch in the" + << " column name " + << req_schema->columns[i].name + << ". Please run mysql_upgrade"; + } else { CREATE_TYPES_NAMES(); snprintf(errstr, errstr_sz, diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 51dcdc9e140..69eebab8e17 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2015, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -108,9 +108,7 @@ where n=1..n_uniq. @} */ /* names of the tables from the persistent statistics storage */ -#define TABLE_STATS_NAME "mysql/innodb_table_stats" #define TABLE_STATS_NAME_PRINT "mysql.innodb_table_stats" -#define INDEX_STATS_NAME "mysql/innodb_index_stats" #define INDEX_STATS_NAME_PRINT "mysql.innodb_index_stats" #ifdef UNIV_STATS_DEBUG @@ -181,7 +179,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"table_name", DATA_VARMYSQL, - DATA_NOT_NULL, 192}, + DATA_NOT_NULL, 597}, {"last_update", DATA_FIXBINARY, DATA_NOT_NULL, 4}, @@ -209,7 +207,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"table_name", DATA_VARMYSQL, - DATA_NOT_NULL, 192}, + DATA_NOT_NULL, 597}, {"index_name", DATA_VARMYSQL, DATA_NOT_NULL, 192}, diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 6fde5654dd1..f15e98b8a4d 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -32,6 +32,12 @@ Created Apr 25, 2012 Vasil Dimov #include "srv0start.h" #include "ut0new.h" #include "fil0fil.h" +#ifdef WITH_WSREP +# include "mysql/service_wsrep.h" +# include "wsrep.h" +# include "log.h" +# include "wsrep_mysqld.h" +#endif #include <vector> @@ -76,41 +82,31 @@ typedef recalc_pool_t::iterator /** Pool where we store information on which tables are to be processed by background statistics gathering. */ -static recalc_pool_t* recalc_pool; - - -/*****************************************************************//** -Initialize the recalc pool, called once during thread initialization. */ -static -void -dict_stats_recalc_pool_init() -/*=========================*/ -{ - ut_ad(!srv_read_only_mode); - /* JAN: TODO: MySQL 5.7 PSI - const PSI_memory_key key = mem_key_dict_stats_bg_recalc_pool_t; - - recalc_pool = UT_NEW(recalc_pool_t(recalc_pool_allocator_t(key)), key); - - recalc_pool->reserve(RECALC_POOL_INITIAL_SLOTS); - */ - recalc_pool = new std::vector<table_id_t, recalc_pool_allocator_t>(); -} +static recalc_pool_t recalc_pool; +/** Whether the global data structures have been initialized */ +static bool stats_initialised; /*****************************************************************//** Free the resources occupied by the recalc pool, called once during thread de-initialization. */ -static -void -dict_stats_recalc_pool_deinit() -/*===========================*/ +static void dict_stats_recalc_pool_deinit() { ut_ad(!srv_read_only_mode); - recalc_pool->clear(); - - UT_DELETE(recalc_pool); - recalc_pool = NULL; + recalc_pool.clear(); + defrag_pool.clear(); + /* + recalc_pool may still have its buffer allocated. It will free it when + its destructor is called. + The problem is, memory leak detector is run before the recalc_pool's + destructor is invoked, and will report recalc_pool's buffer as leaked + memory. To avoid that, we force recalc_pool to surrender its buffer + to empty_pool object, which will free it when leaving this function: + */ + recalc_pool_t recalc_empty_pool; + defrag_pool_t defrag_empty_pool; + recalc_pool.swap(recalc_empty_pool); + defrag_pool.swap(defrag_empty_pool); } /*****************************************************************//** @@ -130,8 +126,8 @@ dict_stats_recalc_pool_add( mutex_enter(&recalc_pool_mutex); /* quit if already in the list */ - for (recalc_pool_iterator_t iter = recalc_pool->begin(); - iter != recalc_pool->end(); + for (recalc_pool_iterator_t iter = recalc_pool.begin(); + iter != recalc_pool.end(); ++iter) { if (*iter == table->id) { @@ -140,18 +136,25 @@ dict_stats_recalc_pool_add( } } - recalc_pool->push_back(table->id); + recalc_pool.push_back(table->id); mutex_exit(&recalc_pool_mutex); os_event_set(dict_stats_event); } +#ifdef WITH_WSREP +/** Update the table modification counter and if necessary, +schedule new estimates for table and index statistics to be calculated. +@param[in,out] table persistent or temporary table +@param[in] thd current session */ +void dict_stats_update_if_needed(dict_table_t* table, THD* thd) +#else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void -dict_stats_update_if_needed(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t* table) +#endif { ut_ad(table->stat_initialized); ut_ad(!mutex_own(&dict_sys->mutex)); @@ -163,6 +166,15 @@ dict_stats_update_if_needed(dict_table_t* table) if (counter > n_rows / 10 /* 10% */ && dict_stats_auto_recalc_is_enabled(table)) { +#ifdef WITH_WSREP + if (thd && wsrep_on(thd) && wsrep_thd_is_BF(thd, 0)) { + WSREP_DEBUG("Avoiding background statistics" + " calculation for table %s", + table->name.m_name); + return; + } +#endif /* WITH_WSREP */ + dict_stats_recalc_pool_add(table); table->stat_modified_counter = 0; } @@ -200,14 +212,14 @@ dict_stats_recalc_pool_get( mutex_enter(&recalc_pool_mutex); - if (recalc_pool->empty()) { + if (recalc_pool.empty()) { mutex_exit(&recalc_pool_mutex); return(false); } - *id = recalc_pool->at(0); + *id = recalc_pool.at(0); - recalc_pool->erase(recalc_pool->begin()); + recalc_pool.erase(recalc_pool.begin()); mutex_exit(&recalc_pool_mutex); @@ -229,13 +241,13 @@ dict_stats_recalc_pool_del( ut_ad(table->id > 0); - for (recalc_pool_iterator_t iter = recalc_pool->begin(); - iter != recalc_pool->end(); + for (recalc_pool_iterator_t iter = recalc_pool.begin(); + iter != recalc_pool.end(); ++iter) { if (*iter == table->id) { /* erase() invalidates the iterator */ - recalc_pool->erase(iter); + recalc_pool.erase(iter); break; } } @@ -274,7 +286,6 @@ dict_stats_thread_init() dict_stats_event = os_event_create(0); dict_stats_shutdown_event = os_event_create(0); - ut_d(dict_stats_disabled_event = os_event_create(0)); /* The recalc_pool_mutex is acquired from: @@ -293,9 +304,8 @@ dict_stats_thread_init() mutex_create(LATCH_ID_RECALC_POOL, &recalc_pool_mutex); - dict_stats_recalc_pool_init(); dict_defrag_pool_init(); - + stats_initialised = true; } /*****************************************************************//** @@ -308,10 +318,12 @@ dict_stats_thread_deinit() ut_a(!srv_read_only_mode); ut_ad(!srv_dict_stats_thread_active); - if (recalc_pool == NULL) { + if (!stats_initialised) { return; } + stats_initialised = false; + dict_stats_recalc_pool_deinit(); dict_defrag_pool_deinit(); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 176ab0370c6..d5b369265a8 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -738,42 +738,35 @@ retry: return(true); } -/** Close a file node. -@param[in,out] node File node */ -static -void -fil_node_close_file( - fil_node_t* node) +/** Close the file handle. */ +void fil_node_t::close() { bool ret; - ut_ad(mutex_own(&(fil_system.mutex))); - ut_a(node->is_open()); - ut_a(node->n_pending == 0); - ut_a(node->n_pending_flushes == 0); - ut_a(!node->being_extended); - ut_a(node->modification_counter == node->flush_counter - || node->space->purpose == FIL_TYPE_TEMPORARY + ut_ad(mutex_own(&fil_system.mutex)); + ut_a(is_open()); + ut_a(n_pending == 0); + ut_a(n_pending_flushes == 0); + ut_a(!being_extended); + ut_a(modification_counter == flush_counter + || space->purpose == FIL_TYPE_TEMPORARY || srv_fast_shutdown == 2 || !srv_was_started); - ret = os_file_close(node->handle); + ret = os_file_close(handle); ut_a(ret); - /* printf("Closing file %s\n", node->name); */ + /* printf("Closing file %s\n", name); */ - node->handle = OS_FILE_CLOSED; - ut_ad(!node->is_open()); + handle = OS_FILE_CLOSED; + ut_ad(!is_open()); ut_a(fil_system.n_open > 0); fil_system.n_open--; fil_n_file_opened--; - if (fil_space_belongs_in_lru(node->space)) { - + if (fil_space_belongs_in_lru(space)) { ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); - - /* The node is in the LRU list, remove it */ - UT_LIST_REMOVE(fil_system.LRU, node); + UT_LIST_REMOVE(fil_system.LRU, this); } } @@ -809,7 +802,7 @@ fil_try_to_close_file_in_LRU( && node->n_pending_flushes == 0 && !node->being_extended) { - fil_node_close_file(node); + node->close(); return(true); } @@ -1239,7 +1232,7 @@ fil_node_close_to_free( ut_a(!node->being_extended); if (node->is_open()) { - /* We fool the assertion in fil_node_close_file() to think + /* We fool the assertion in fil_node_t::close() to think there are no unflushed modifications in the file */ node->modification_counter = node->flush_counter; @@ -1258,7 +1251,7 @@ fil_node_close_to_free( UT_LIST_REMOVE(fil_system.unflushed_spaces, space); } - fil_node_close_file(node); + node->close(); } } @@ -1749,7 +1742,7 @@ void fil_space_t::close() node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { if (node->is_open()) { - fil_node_close_file(node); + node->close(); } } @@ -1910,7 +1903,7 @@ fil_close_all_files(void) node = UT_LIST_GET_NEXT(chain, node)) { if (node->is_open()) { - fil_node_close_file(node); + node->close(); } } @@ -1957,7 +1950,7 @@ fil_close_log_files( node = UT_LIST_GET_NEXT(chain, node)) { if (node->is_open()) { - fil_node_close_file(node); + node->close(); } } diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc index 82c4438196b..d6695cec5be 100644 --- a/storage/innobase/fts/fts0ast.cc +++ b/storage/innobase/fts/fts0ast.cc @@ -1,6 +1,7 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -28,6 +29,7 @@ Created 2007/3/16 Sunny Bains. #include "fts0ast.h" #include "fts0pars.h" #include "fts0fts.h" +#include "row0sel.h" /* The FTS ast visit pass. */ enum fts_ast_visit_pass_t { @@ -602,6 +604,7 @@ fts_ast_visit( bool revisit = false; bool will_be_ignored = false; fts_ast_visit_pass_t visit_pass = FTS_PASS_FIRST; + const trx_t* trx = node->trx; start_node = node->list.head; @@ -700,6 +703,10 @@ fts_ast_visit( } } + if (trx_is_interrupted(trx)) { + return DB_INTERRUPTED; + } + if (revisit) { /* Exist pass processes the skipped FTS_EXIST operation. */ for (node = start_node; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index d874725c374..7c26614b309 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2016, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -202,7 +202,7 @@ FTS auxiliary INDEX table and clear the cache at the end. @param[in,out] sync sync state @param[in] unlock_cache whether unlock cache lock when write node @param[in] wait whether wait when a sync is in progress -@param[in] has_dict whether has dict operation lock +@param[in] has_dict whether has dict operation lock @return DB_SUCCESS if all OK */ static dberr_t @@ -860,37 +860,28 @@ fts_drop_index( err = fts_drop_index_tables(trx, index); - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry){ - fts_free(table); - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + + fts_free(table); + return(err); } - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry){ - current_doc_id = table->fts->cache->next_doc_id; - first_doc_id = table->fts->cache->first_doc_id; - fts_cache_clear(table->fts->cache); - fts_cache_destroy(table->fts->cache); - table->fts->cache = fts_cache_create(table); - table->fts->cache->next_doc_id = current_doc_id; - table->fts->cache->first_doc_id = first_doc_id; - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + + current_doc_id = table->fts->cache->next_doc_id; + first_doc_id = table->fts->cache->first_doc_id; + fts_cache_clear(table->fts->cache); + fts_cache_destroy(table->fts->cache); + table->fts->cache = fts_cache_create(table); + table->fts->cache->next_doc_id = current_doc_id; + table->fts->cache->first_doc_id = first_doc_id; } else { fts_cache_t* cache = table->fts->cache; fts_index_cache_t* index_cache; @@ -900,18 +891,14 @@ fts_drop_index( index_cache = fts_find_index_cache(cache, index); if (index_cache != NULL) { - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry && index_cache->words) { - fts_words_free(index_cache->words); - rbt_free(index_cache->words); - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + if (index_cache->words) { + fts_words_free(index_cache->words); + rbt_free(index_cache->words); + } ib_vector_remove(cache->indexes, *(void**) index_cache); } @@ -4048,6 +4035,9 @@ fts_sync_write_words( word = rbt_value(fts_tokenizer_word_t, rbt_node); + DBUG_EXECUTE_IF("fts_instrument_write_words_before_select_index", + os_thread_sleep(300000);); + selected = fts_select_index( index_cache->charset, word->text.f_str, word->text.f_len); @@ -4332,7 +4322,7 @@ FTS auxiliary INDEX table and clear the cache at the end. @param[in,out] sync sync state @param[in] unlock_cache whether unlock cache lock when write node @param[in] wait whether wait when a sync is in progress -@param[in] has_dict whether has dict operation lock +@param[in] has_dict whether has dict operation lock @return DB_SUCCESS if all OK */ static dberr_t @@ -4398,15 +4388,13 @@ begin_sync: continue; } + DBUG_EXECUTE_IF("fts_instrument_sync_before_syncing", + os_thread_sleep(300000);); index_cache->index->index_fts_syncing = true; - DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits", - os_thread_sleep(10000000); - ); error = fts_sync_index(sync, index_cache); - if (error != DB_SUCCESS && !sync->interrupted) { - + if (error != DB_SUCCESS) { goto end_sync; } } @@ -4441,8 +4429,8 @@ end_sync: } rw_lock_x_lock(&cache->lock); - /* Clear fts syncing flags of any indexes incase sync is - interrupeted */ + /* Clear fts syncing flags of any indexes in case sync is + interrupted */ for (i = 0; i < ib_vector_size(cache->indexes); ++i) { static_cast<fts_index_cache_t*>( ib_vector_get(cache->indexes, i)) diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 4d93451a40d..c523ac5270e 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -62,12 +62,6 @@ static const ulint FTS_WORD_NODES_INIT_SIZE = 64; /** Last time we did check whether system need a sync */ static ib_time_t last_check_sync_time; -#if 0 -/** Check each table in round robin to see whether they'd -need to be "optimized" */ -static ulint fts_optimize_sync_iterator = 0; -#endif - /** State of a table within the optimization sub system. */ enum fts_state_t { FTS_STATE_LOADED, @@ -79,17 +73,11 @@ enum fts_state_t { /** FTS optimize thread message types. */ enum fts_msg_type_t { - FTS_MSG_START, /*!< Start optimizing thread */ - - FTS_MSG_PAUSE, /*!< Pause optimizing thread */ - FTS_MSG_STOP, /*!< Stop optimizing and exit thread */ FTS_MSG_ADD_TABLE, /*!< Add table to the optimize thread's work queue */ - FTS_MSG_OPTIMIZE_TABLE, /*!< Optimize a table */ - FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize threads work queue */ FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */ @@ -234,7 +222,7 @@ struct fts_msg_t { /** The number of words to read and optimize in a single pass. */ ulong fts_num_word_optimize; -// FIXME +/** Whether to enable additional FTS diagnostic printout. */ char fts_enable_diag_print; /** ZLib compressed block size.*/ @@ -2554,12 +2542,9 @@ fts_optimize_create_msg( return(msg); } -/**********************************************************************//** -Add the table to add to the OPTIMIZER's list. */ -void -fts_optimize_add_table( -/*===================*/ - dict_table_t* table) /*!< in: table to add */ +/** Add the table to add to the OPTIMIZER's list. +@param[in] table table to add */ +void fts_optimize_add_table(dict_table_t* table) { fts_msg_t* msg; @@ -2575,28 +2560,6 @@ fts_optimize_add_table( ib_wqueue_add(fts_optimize_wq, msg, msg->heap); } -#if 0 -/**********************************************************************//** -Optimize a table. */ -static -void -fts_optimize_do_table( -/*==================*/ - dict_table_t* table) /*!< in: table to optimize */ -{ - fts_msg_t* msg; - - /* Optimizer thread could be shutdown */ - if (!fts_optimize_wq) { - return; - } - - msg = fts_optimize_create_msg(FTS_MSG_OPTIMIZE_TABLE, table); - - ib_wqueue_add(fts_optimize_wq, msg, msg->heap); -} -#endif - /**********************************************************************//** Remove the table from the OPTIMIZER's list. We do wait for acknowledgement from the consumer of the message. */ @@ -2672,53 +2635,6 @@ fts_optimize_request_sync_table( } /**********************************************************************//** -Find the slot for a particular table. -@return slot if found else NULL. */ -static -fts_slot_t* -fts_optimize_find_slot( -/*===================*/ - ib_vector_t* tables, /*!< in: vector of tables */ - const dict_table_t* table) /*!< in: table to add */ -{ - ulint i; - - for (i = 0; i < ib_vector_size(tables); ++i) { - fts_slot_t* slot; - - slot = static_cast<fts_slot_t*>(ib_vector_get(tables, i)); - - if (slot->table == table) { - return(slot); - } - } - - return(NULL); -} - -/**********************************************************************//** -Start optimizing table. */ -static -void -fts_optimize_start_table( -/*=====================*/ - ib_vector_t* tables, /*!< in/out: vector of tables */ - dict_table_t* table) /*!< in: table to optimize */ -{ - fts_slot_t* slot; - - slot = fts_optimize_find_slot(tables, table); - - if (slot == NULL) { - ib::error() << "Table " << table->name << " not registered" - " with the optimize thread."; - } else { - slot->last_run = 0; - slot->completed = 0; - } -} - -/**********************************************************************//** Add the table to the vector if it doesn't already exist. */ static ibool @@ -2741,7 +2657,7 @@ fts_optimize_new_table( empty_slot = i; } else if (slot->table == table) { /* Already exists in our optimize queue. */ - ut_ad(slot->table_id = table->id); + ut_ad(slot->table_id == table->id); return(FALSE); } } @@ -2900,57 +2816,6 @@ fts_is_sync_needed( return(false); } -#if 0 -/*********************************************************************//** -Check whether a table needs to be optimized. */ -static -void -fts_optimize_need_sync( -/*===================*/ - ib_vector_t* tables) /*!< in: list of tables */ -{ - dict_table_t* table = NULL; - fts_slot_t* slot; - ulint num_table = ib_vector_size(tables); - - if (!num_table) { - return; - } - - if (fts_optimize_sync_iterator >= num_table) { - fts_optimize_sync_iterator = 0; - } - - slot = ib_vector_get(tables, fts_optimize_sync_iterator); - table = slot->table; - - if (!table) { - return; - } - - ut_ad(table->fts); - - if (table->fts->cache) { - ulint deleted = table->fts->cache->deleted; - - if (table->fts->cache->added - >= fts_optimize_add_threshold) { - fts_sync_table(table); - } else if (deleted >= fts_optimize_delete_threshold) { - fts_optimize_do_table(table); - - mutex_enter(&table->fts->cache->deleted_lock); - table->fts->cache->deleted -= deleted; - mutex_exit(&table->fts->cache->deleted_lock); - } - } - - fts_optimize_sync_iterator++; - - return; -} -#endif - /** Sync fts cache of a table @param[in] table_id table id */ void @@ -2963,7 +2828,7 @@ fts_optimize_sync_table( if (table) { if (dict_table_has_fts_index(table) && table->fts->cache) { - fts_sync_table(table, true, false, true); + fts_sync_table(table, true, false, false); } dict_table_close(table, FALSE, FALSE); @@ -3031,8 +2896,7 @@ DECLARE_THREAD(fts_optimize_thread)( fts_msg_t* msg; msg = static_cast<fts_msg_t*>( - ib_wqueue_timedwait(wq, - FTS_QUEUE_WAIT_IN_USECS)); + ib_wqueue_timedwait(wq, FTS_QUEUE_WAIT_IN_USECS)); /* Timeout ? */ if (msg == NULL) { @@ -3044,12 +2908,6 @@ DECLARE_THREAD(fts_optimize_thread)( } switch (msg->type) { - case FTS_MSG_START: - break; - - case FTS_MSG_PAUSE: - break; - case FTS_MSG_STOP: done = TRUE; break; @@ -3064,15 +2922,6 @@ DECLARE_THREAD(fts_optimize_thread)( } break; - case FTS_MSG_OPTIMIZE_TABLE: - if (!done) { - fts_optimize_start_table( - fts_slots, - static_cast<dict_table_t*>( - msg->ptr)); - } - break; - case FTS_MSG_DEL_TABLE: if (fts_optimize_del_table( fts_slots, static_cast<fts_msg_del_t*>( @@ -3087,6 +2936,10 @@ DECLARE_THREAD(fts_optimize_thread)( break; case FTS_MSG_SYNC_TABLE: + DBUG_EXECUTE_IF( + "fts_instrument_msg_sync_sleep", + os_thread_sleep(300000);); + fts_optimize_sync_table( *static_cast<table_id_t*>(msg->ptr)); break; @@ -3149,7 +3002,7 @@ fts_optimize_init(void) ut_ad(!srv_read_only_mode); /* For now we only support one optimize thread. */ - ut_a(fts_optimize_wq == NULL); + ut_a(!fts_optimize_wq); /* Create FTS optimize work queue */ fts_optimize_wq = ib_wqueue_create(); diff --git a/storage/innobase/fts/fts0pars.cc b/storage/innobase/fts/fts0pars.cc index e4d1bba2be6..56cc8d6052c 100644 --- a/storage/innobase/fts/fts0pars.cc +++ b/storage/innobase/fts/fts0pars.cc @@ -88,7 +88,7 @@ extern int fts_lexer(YYSTYPE*, fts_lexer_t*); extern int fts_blexer(YYSTYPE*, yyscan_t); extern int fts_tlexer(YYSTYPE*, yyscan_t); -typedef int (*fts_scan)(); + extern int ftserror(const char* p); @@ -103,8 +103,8 @@ extern int ftserror(const char* p); #define YYTOKENFREE(token) fts_ast_string_free((token)) -typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner); -typedef int (*fts_scanner)(); + +typedef int (*fts_scanner)(YYSTYPE* val, yyscan_t yyscanner); struct fts_lexer_t { fts_scanner scanner; @@ -1948,7 +1948,7 @@ fts_lexer_create( reinterpret_cast<const char*>(query), static_cast<int>(query_len), fts_lexer->yyscanner); - fts_lexer->scanner = reinterpret_cast<fts_scan>(fts_blexer); + fts_lexer->scanner = fts_blexer; /* FIXME: Debugging */ /* fts0bset_debug(1 , fts_lexer->yyscanner); */ } else { @@ -1957,7 +1957,7 @@ fts_lexer_create( reinterpret_cast<const char*>(query), static_cast<int>(query_len), fts_lexer->yyscanner); - fts_lexer->scanner = reinterpret_cast<fts_scan>(fts_tlexer); + fts_lexer->scanner = fts_tlexer; } return(fts_lexer); @@ -1971,7 +1971,7 @@ fts_lexer_free( /*===========*/ fts_lexer_t* fts_lexer) { - if (fts_lexer->scanner == (fts_scan) fts_blexer) { + if (fts_lexer->scanner == fts_blexer) { fts0blex_destroy(fts_lexer->yyscanner); } else { fts0tlex_destroy(fts_lexer->yyscanner); @@ -1988,9 +1988,9 @@ fts_lexer( YYSTYPE* val, fts_lexer_t* fts_lexer) { - fts_scanner_alt func_ptr; + fts_scanner func_ptr; - func_ptr = (fts_scanner_alt) fts_lexer->scanner; + func_ptr = fts_lexer->scanner; return(func_ptr(val, fts_lexer->yyscanner)); } diff --git a/storage/innobase/fts/fts0pars.y b/storage/innobase/fts/fts0pars.y index 1f4ec9922e3..4db72ca65ad 100644 --- a/storage/innobase/fts/fts0pars.y +++ b/storage/innobase/fts/fts0pars.y @@ -36,7 +36,7 @@ extern int fts_lexer(YYSTYPE*, fts_lexer_t*); extern int fts_blexer(YYSTYPE*, yyscan_t); extern int fts_tlexer(YYSTYPE*, yyscan_t); -typedef int (*fts_scan)(); + extern int ftserror(const char* p); @@ -49,8 +49,8 @@ extern int ftserror(const char* p); #define YYPARSE_PARAM state #define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer -typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner); -typedef int (*fts_scanner)(); + +typedef int (*fts_scanner)(YYSTYPE* val, yyscan_t yyscanner); struct fts_lexer_struct { fts_scanner scanner; @@ -238,13 +238,13 @@ fts_lexer_create( if (boolean_mode) { fts0blex_init(&fts_lexer->yyscanner); fts0b_scan_bytes((char*) query, (int) query_len, fts_lexer->yyscanner); - fts_lexer->scanner = (fts_scan) fts_blexer; + fts_lexer->scanner = fts_blexer; /* FIXME: Debugging */ /* fts0bset_debug(1 , fts_lexer->yyscanner); */ } else { fts0tlex_init(&fts_lexer->yyscanner); fts0t_scan_bytes((char*) query, (int) query_len, fts_lexer->yyscanner); - fts_lexer->scanner = (fts_scan) fts_tlexer; + fts_lexer->scanner = fts_tlexer; } return(fts_lexer); @@ -258,7 +258,7 @@ fts_lexer_free( /*===========*/ fts_lexer_t* fts_lexer) { - if (fts_lexer->scanner == (fts_scan) fts_blexer) { + if (fts_lexer->scanner == fts_blexer) { fts0blex_destroy(fts_lexer->yyscanner); } else { fts0tlex_destroy(fts_lexer->yyscanner); @@ -275,9 +275,9 @@ fts_lexer( YYSTYPE* val, fts_lexer_t* fts_lexer) { - fts_scanner_alt func_ptr; + fts_scanner func_ptr; - func_ptr = (fts_scanner_alt) fts_lexer->scanner; + func_ptr = fts_lexer->scanner; return(func_ptr(val, fts_lexer->yyscanner)); } diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 6a0496bedcd..5ae8e28974e 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -3920,6 +3920,7 @@ fts_query_can_optimize( } /** FTS Query entry point. +@param[in,out] trx transaction @param[in] index fts index to search @param[in] flags FTS search mode @param[in] query_str FTS query @@ -3928,6 +3929,7 @@ fts_query_can_optimize( @return DB_SUCCESS if successful otherwise error code */ dberr_t fts_query( + trx_t* trx, dict_index_t* index, uint flags, const byte* query_str, @@ -3940,7 +3942,7 @@ fts_query( ulint lc_query_str_len; ulint result_len; bool boolean_mode; - trx_t* query_trx; + trx_t* query_trx; /* FIXME: use provided trx */ CHARSET_INFO* charset; ulint start_time_ms; bool will_be_ignored = false; @@ -4055,6 +4057,7 @@ fts_query( /* Parse the input query string. */ if (fts_query_parse(&query, lc_query_str, result_len)) { fts_ast_node_t* ast = query.root; + ast->trx = trx; /* Optimize query to check if it's a single term */ fts_query_can_optimize(&query, flags); @@ -4068,6 +4071,11 @@ fts_query( query.error = fts_ast_visit( FTS_NONE, ast, fts_query_visitor, &query, &will_be_ignored); + if (query.error == DB_INTERRUPTED) { + error = DB_INTERRUPTED; + ut_free(lc_query_str); + goto func_exit; + } /* If query expansion is requested, extend the search with first search pass result */ @@ -4094,6 +4102,15 @@ fts_query( ut_zalloc_nokey(sizeof(**result))); } + if (trx_is_interrupted(trx)) { + error = DB_INTERRUPTED; + ut_free(lc_query_str); + if (*result) { + fts_query_free_result(*result); + } + goto func_exit; + } + ut_free(lc_query_str); if (fts_enable_diag_print && (*result)) { diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index eac904e5b24..146d1616347 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -658,7 +658,7 @@ rtr_adjust_upper_level( /* Create a memory heap where the data tuple is stored */ heap = mem_heap_create(1024); - memset(&cursor, 0, sizeof(cursor)); + cursor.init(); cursor.thr = sea_cur->thr; @@ -1367,7 +1367,7 @@ rtr_ins_enlarge_mbr( rtr_page_cal_mbr(index, block, &new_mbr, heap); /* Get father block. */ - memset(&cursor, 0, sizeof(cursor)); + cursor.init(); offsets = rtr_page_get_father_block( NULL, heap, index, block, mtr, btr_cur, &cursor); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 67b2feb7af6..b137a768830 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1546,7 +1546,7 @@ rtr_copy_buf( will be copied. It is also undefined what will happen with the newly memcpy()ed mutex if the source mutex was acquired by (another) thread while it was copied. */ - memcpy(&matches->block.page, &block->page, sizeof(buf_page_t)); + new (&matches->block.page) buf_page_t(block->page); matches->block.frame = block->frame; matches->block.unzip_LRU = block->unzip_LRU; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b0af34814af..0bdb3834f6f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5322,15 +5322,16 @@ ha_innobase::max_supported_key_length() const switch (srv_page_size) { case 4096: - return(768); + /* Hack: allow mysql.innodb_index_stats to be created. */ + /* FIXME: rewrite this API, and in sql_table.cc consider + that in index-organized tables (such as InnoDB), secondary + index records will be padded with the PRIMARY KEY, instead + of some short ROWID or record heap address. */ + return(1173); case 8192: return(1536); default: -#ifdef WITH_WSREP - return(3500); -#else return(3500); -#endif } } @@ -10069,8 +10070,7 @@ ha_innobase::ft_init_ext( const_cast<char*>(query)); // FIXME: support ft_init_ext_with_hints(), pass LIMIT - // FIXME: use trx - dberr_t error = fts_query(index, flags, q, query_len, &result); + dberr_t error = fts_query(trx, index, flags, q, query_len, &result); if (error != DB_SUCCESS) { my_error(convert_error_code_to_mysql(error, 0, NULL), MYF(0)); @@ -13262,6 +13262,36 @@ innobase_rename_table( row_mysql_lock_data_dictionary(trx); + dict_table_t* table = dict_table_open_on_name(norm_from, TRUE, FALSE, + DICT_ERR_IGNORE_NONE); + + /* Since DICT_BG_YIELD has sleep for 250 milliseconds, + Convert lock_wait_timeout unit from second to 250 milliseconds */ + long int lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd) * 4; + if (table != NULL) { + for (dict_index_t* index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + + if (index->type & DICT_FTS) { + /* Found */ + while (index->index_fts_syncing + && !trx_is_interrupted(trx) + && (lock_wait_timeout--) > 0) { + DICT_BG_YIELD(trx); + } + } + } + dict_table_close(table, TRUE, FALSE); + } + + /* FTS sync is in progress. We shall timeout this operation */ + if (lock_wait_timeout < 0) { + error = DB_LOCK_WAIT_TIMEOUT; + row_mysql_unlock_data_dictionary(trx); + DBUG_RETURN(error); + } + error = row_rename_table_for_mysql(norm_from, norm_to, trx, TRUE); if (error != DB_SUCCESS) { @@ -13391,6 +13421,10 @@ ha_innobase::rename_table( my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); error = DB_ERROR; + } else if (error == DB_LOCK_WAIT_TIMEOUT) { + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), to); + + error = DB_LOCK_WAIT; } DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL)); @@ -19413,6 +19447,13 @@ static MYSQL_SYSVAR_BOOL(log_compressed_pages, page_zip_log_pages, " compression algorithm doesn't change.", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(log_optimize_ddl, innodb_log_optimize_ddl, + PLUGIN_VAR_OPCMDARG, + "Reduce redo logging when natively creating indexes or rebuilding tables." + " Setting this OFF avoids delay due to page flushing and" + " allows concurrent backup.", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_ULONG(autoextend_increment, sys_tablespace_auto_extend_increment, PLUGIN_VAR_RQCMDARG, @@ -20302,6 +20343,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(log_write_ahead_size), MYSQL_SYSVAR(log_group_home_dir), MYSQL_SYSVAR(log_compressed_pages), + MYSQL_SYSVAR(log_optimize_ddl), MYSQL_SYSVAR(max_dirty_pages_pct), MYSQL_SYSVAR(max_dirty_pages_pct_lwm), MYSQL_SYSVAR(adaptive_flushing_lwm), diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 63695e8b4cf..aadb0641a72 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -77,8 +77,8 @@ static const alter_table_operations INNOBASE_DEFAULTS static const alter_table_operations INNOBASE_ALTER_REBUILD = ALTER_ADD_PK_INDEX | ALTER_DROP_PK_INDEX - | ALTER_CHANGE_CREATE_OPTION - /* CHANGE_CREATE_OPTION needs to check create_option_need_rebuild() */ + | ALTER_OPTIONS + /* ALTER_OPTIONS needs to check create_option_need_rebuild() */ | ALTER_COLUMN_NULLABLE | INNOBASE_DEFAULTS | ALTER_STORED_COLUMN_ORDER @@ -498,8 +498,7 @@ static bool create_option_need_rebuild( const Alter_inplace_info* ha_alter_info, const TABLE* table) { - DBUG_ASSERT(ha_alter_info->handler_flags - & ALTER_CHANGE_CREATE_OPTION); + DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_OPTIONS); if (ha_alter_info->create_info->used_fields & (HA_CREATE_USED_ROW_FORMAT @@ -541,7 +540,7 @@ innobase_need_rebuild( { if ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_INSTANT)) - == ALTER_CHANGE_CREATE_OPTION) { + == ALTER_OPTIONS) { return create_option_need_rebuild(ha_alter_info, table); } @@ -662,8 +661,7 @@ instant_alter_column_possible( return false; } - if (~ha_alter_info->handler_flags - & ALTER_ADD_STORED_BASE_COLUMN) { + if (~ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) { return false; } @@ -686,13 +684,11 @@ instant_alter_column_possible( columns. */ if (ha_alter_info->handler_flags & ((INNOBASE_ALTER_REBUILD | INNOBASE_ONLINE_CREATE) - & ~ALTER_ADD_STORED_BASE_COLUMN - & ~ALTER_CHANGE_CREATE_OPTION)) { + & ~ALTER_ADD_STORED_BASE_COLUMN & ~ALTER_OPTIONS)) { return false; } - return !(ha_alter_info->handler_flags - & ALTER_CHANGE_CREATE_OPTION) + return !(ha_alter_info->handler_flags & ALTER_OPTIONS) || !create_option_need_rebuild(ha_alter_info, table); } @@ -5457,8 +5453,7 @@ not_instant_add_column: } } - if (ha_alter_info->handler_flags - & ALTER_CHANGE_CREATE_OPTION) { + if (ha_alter_info->handler_flags & ALTER_OPTIONS) { const ha_table_option_struct& alt_opt= *ha_alter_info->create_info->option_struct; const ha_table_option_struct& opt= @@ -6827,7 +6822,7 @@ err_exit: if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) || ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_INSTANT)) - == ALTER_CHANGE_CREATE_OPTION + == ALTER_OPTIONS && !create_option_need_rebuild(ha_alter_info, table))) { if (heap) { @@ -7107,8 +7102,9 @@ ok_exit: DBUG_RETURN(false); } - if ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) - == ALTER_CHANGE_CREATE_OPTION + if ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE + | INNOBASE_ALTER_INSTANT)) + == ALTER_OPTIONS && !create_option_need_rebuild(ha_alter_info, table)) { goto ok_exit; } @@ -9431,24 +9427,24 @@ ha_innobase::commit_inplace_alter_table( trx_t* trx = ctx0->trx; bool fail = false; - if (new_clustered) { - for (inplace_alter_handler_ctx** pctx = ctx_array; - *pctx; pctx++) { - ha_innobase_inplace_ctx* ctx - = static_cast<ha_innobase_inplace_ctx*>(*pctx); - DBUG_ASSERT(ctx->need_rebuild()); + /* Stop background FTS operations. */ + for (inplace_alter_handler_ctx** pctx = ctx_array; + *pctx; pctx++) { + ha_innobase_inplace_ctx* ctx + = static_cast<ha_innobase_inplace_ctx*>(*pctx); + + DBUG_ASSERT(new_clustered == ctx->need_rebuild()); + if (new_clustered) { if (ctx->old_table->fts) { ut_ad(!ctx->old_table->fts->add_wq); - fts_optimize_remove_table( - ctx->old_table); + fts_optimize_remove_table(ctx->old_table); } + } - if (ctx->new_table->fts) { - ut_ad(!ctx->new_table->fts->add_wq); - fts_optimize_remove_table( - ctx->new_table); - } + if (ctx->new_table->fts) { + ut_ad(!ctx->new_table->fts->add_wq); + fts_optimize_remove_table(ctx->new_table); } } @@ -9495,41 +9491,39 @@ ha_innobase::commit_inplace_alter_table( /* Make a concurrent Drop fts Index to wait until sync of that fts index is happening in the background */ - for (;;) { + for (int retry_count = 0;;) { bool retry = false; for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) { - int count =0; ha_innobase_inplace_ctx* ctx = static_cast<ha_innobase_inplace_ctx*>(*pctx); DBUG_ASSERT(new_clustered == ctx->need_rebuild()); if (dict_fts_index_syncing(ctx->old_table)) { - count++; - if (count == 100) { - fprintf(stderr, - "Drop index waiting for background sync" - "to finish\n"); - } retry = true; + break; } if (new_clustered && dict_fts_index_syncing(ctx->new_table)) { - count++; - if (count == 100) { - fprintf(stderr, - "Drop index waiting for background sync" - "to finish\n"); - } retry = true; + break; } } - if (!retry) { + if (!retry) { break; } + /* Print a message if waiting for a long time. */ + if (retry_count < 100) { + retry_count++; + } else { + ib::info() << "Drop index waiting for background sync" + " to finish"; + retry_count = 0; + } + DICT_BG_YIELD(trx); } @@ -9806,6 +9800,11 @@ foreign_fail: ut_a(fts_check_cached_index(ctx->old_table)); DBUG_INJECT_CRASH("ib_commit_inplace_crash_fail", crash_fail_inject_count++); + + /* Restart the FTS background operations. */ + if (ctx->old_table->fts) { + fts_optimize_add_table(ctx->old_table); + } } row_mysql_unlock_data_dictionary(trx); @@ -9889,8 +9888,6 @@ foreign_fail: (*pctx); DBUG_ASSERT(ctx->need_rebuild() == new_clustered); - bool add_fts = false; - /* Publish the created fulltext index, if any. Note that a fulltext index can be created without creating the clustered index, if there already exists @@ -9905,14 +9902,14 @@ foreign_fail: is left unset when a drop proceeds the add. */ DICT_TF2_FLAG_SET(ctx->new_table, DICT_TF2_FTS); fts_add_index(index, ctx->new_table); - add_fts = true; } } ut_d(dict_table_check_for_dup_indexes( ctx->new_table, CHECK_ALL_COMPLETE)); - if (add_fts) { + /* Start/Restart the FTS background operations. */ + if (ctx->new_table->fts) { fts_optimize_add_table(ctx->new_table); } diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 25dd9e9993d..f0df1bc9839 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1359,12 +1359,14 @@ i_s_cmp_fill_low( page0zip.cc. */ table->field[1]->store(zip_stat->compressed, true); table->field[2]->store(zip_stat->compressed_ok, true); - table->field[3]->store(zip_stat->compressed_usec / 1000000, true); + table->field[3]->store(zip_stat->compressed_usec / 1000000, + true); table->field[4]->store(zip_stat->decompressed, true); - table->field[5]->store(zip_stat->decompressed_usec / 1000000, true); + table->field[5]->store(zip_stat->decompressed_usec / 1000000, + true); if (reset) { - memset(zip_stat, 0, sizeof *zip_stat); + new (zip_stat) page_zip_stat_t(); } if (schema_table_store_record(thd, table)) { diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 6a7b532f277..5047dce38b4 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -34,6 +34,8 @@ Created 03/11/2014 Shaohua Wang /** Innodb B-tree index fill factor for bulk load. */ extern uint innobase_fill_factor; +/** whether to reduce redo logging during ALTER TABLE */ +extern my_bool innodb_log_optimize_ddl; /* The proper function call sequence of PageBulk is as below: @@ -63,7 +65,7 @@ public: : m_heap(NULL), m_index(index), - m_mtr(NULL), + m_mtr(), m_trx_id(trx_id), m_block(NULL), m_page(NULL), @@ -84,6 +86,7 @@ public: m_err(DB_SUCCESS) { ut_ad(!dict_index_is_spatial(m_index)); + ut_ad(!m_index->table->is_temporary()); } /** Deconstructor */ @@ -145,11 +148,11 @@ public: /** Set next page @param[in] next_page_no next page no */ - void setNext(ulint next_page_no); + inline void setNext(ulint next_page_no); /** Set previous page @param[in] prev_page_no previous page no */ - void setPrev(ulint prev_page_no); + inline void setPrev(ulint prev_page_no); /** Release block by commiting mtr */ inline void release(); @@ -205,8 +208,8 @@ private: /** The index B-tree */ dict_index_t* m_index; - /** The min-transaction */ - mtr_t* m_mtr; + /** The mini-transaction */ + mtr_t m_mtr; /** The transaction id */ trx_id_t m_trx_id; @@ -256,7 +259,7 @@ private: when the block is re-pinned */ ib_uint64_t m_modify_clock; - /** Flush observer */ + /** Flush observer, or NULL if redo logging is enabled */ FlushObserver* m_flush_observer; /** Operation result DB_SUCCESS or error code */ @@ -271,41 +274,32 @@ class BtrBulk public: /** Constructor @param[in] index B-tree index - @param[in] trx_id transaction id + @param[in] trx transaction @param[in] observer flush observer */ BtrBulk( dict_index_t* index, - trx_id_t trx_id, + const trx_t* trx, FlushObserver* observer) : - m_heap(NULL), m_index(index), - m_trx_id(trx_id), + m_trx(trx), m_flush_observer(observer) { - ut_ad(m_flush_observer != NULL); - ut_d(my_atomic_addlint( - &m_index->table->space->redo_skipped_count, 1)); +#ifdef UNIV_DEBUG + if (m_flush_observer) + my_atomic_addlint(&m_index->table->space->redo_skipped_count, + 1); +#endif /* UNIV_DEBUG */ } /** Destructor */ ~BtrBulk() { - mem_heap_free(m_heap); - UT_DELETE(m_page_bulks); - ut_d(my_atomic_addlint( - &m_index->table->space->redo_skipped_count, - ulint(-1))); - } - - /** Initialization - Note: must be called right after constructor. */ - void init() - { - ut_ad(m_heap == NULL); - m_heap = mem_heap_create(1000); - - m_page_bulks = UT_NEW_NOKEY(page_bulk_vector()); +#ifdef UNIV_DEBUG + if (m_flush_observer) + my_atomic_addlint(&m_index->table->space->redo_skipped_count, + ulint(-1)); +#endif /* UNIV_DEBUG */ } /** Insert a tuple @@ -365,26 +359,23 @@ private: } /** Log free check */ - void logFreeCheck(); + inline void logFreeCheck(); private: - /** Memory heap for allocation */ - mem_heap_t* m_heap; - /** B-tree index */ - dict_index_t* m_index; + dict_index_t*const m_index; - /** Transaction id */ - trx_id_t m_trx_id; + /** Transaction */ + const trx_t*const m_trx; /** Root page level */ ulint m_root_level; - /** Flush observer */ - FlushObserver* m_flush_observer; + /** Flush observer, or NULL if redo logging is enabled */ + FlushObserver*const m_flush_observer; /** Page cursor vector for all level */ - page_bulk_vector* m_page_bulks; + page_bulk_vector m_page_bulks; }; #endif diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index dc1f6dd82d8..f87370be70c 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -955,6 +955,26 @@ struct btr_cur_t { rtr_info_t* rtr_info; /*!< rtree search info */ btr_cur_t():thr(NULL), rtr_info(NULL) {} /* default values */ + /** Zero-initialize all fields */ + void init() + { + index = NULL; + memset(&page_cur, 0, sizeof page_cur); + purge_node = NULL; + left_block = NULL; + thr = NULL; + flag = btr_cur_method(0); + tree_height = 0; + up_match = 0; + up_bytes = 0; + low_match = 0; + low_bytes = 0; + n_fields = 0; + n_bytes = 0; + fold = 0; + path_arr = NULL; + rtr_info = NULL; + } }; /******************************************************//** diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index f478d3fa876..747ad676e33 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -538,6 +538,18 @@ struct btr_pcur_t{ /** old_rec_buf size if old_rec_buf is not NULL */ ulint buf_size; + btr_pcur_t() : + btr_cur(), latch_mode(0), old_stored(false), old_rec(NULL), + old_n_fields(0), rel_pos(btr_pcur_pos_t(0)), + block_when_stored(NULL), + modify_clock(0), withdraw_clock(0), + pos_state(BTR_PCUR_NOT_POSITIONED), + search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL), + old_rec_buf(NULL), buf_size(0) + { + btr_cur.init(); + } + /** Return the index of this persistent cursor */ dict_index_t* index() const { return(btr_cur.index); } }; diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index ace2e2f6ef1..741cb1dbca3 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -371,9 +371,8 @@ public: m_interrupted = true; } - /** Check whether trx is interrupted - @return true if trx is interrupted */ - bool check_interrupted(); + /** Check whether the operation has been interrupted */ + void check_interrupted(); /** Flush dirty pages. */ void flush(); @@ -395,7 +394,7 @@ private: fil_space_t* m_space; /** Trx instance */ - trx_t* const m_trx; + const trx_t* const m_trx; /** Performance schema accounting object, used by ALTER TABLE. If not NULL, then stage->begin_phase_flush() will be called initially, diff --git a/storage/innobase/include/dict0defrag_bg.h b/storage/innobase/include/dict0defrag_bg.h index 8d77a461dc9..ddef139853c 100644 --- a/storage/innobase/include/dict0defrag_bg.h +++ b/storage/innobase/include/dict0defrag_bg.h @@ -33,6 +33,25 @@ Created 25/08/2016 Jan Lindström #include "os0event.h" #include "os0thread.h" + +/** Indices whose defrag stats need to be saved to persistent storage.*/ +struct defrag_pool_item_t { + table_id_t table_id; + index_id_t index_id; +}; + +/** Allocator type, used by std::vector */ +typedef ut_allocator<defrag_pool_item_t> + defrag_pool_allocator_t; + +/** The multitude of tables to be defragmented- an STL vector */ +typedef std::vector<defrag_pool_item_t, defrag_pool_allocator_t> + defrag_pool_t; + +/** Pool where we store information on which tables are to be processed +by background defragmentation. */ +extern defrag_pool_t defrag_pool; + /*****************************************************************//** Initialize the defrag pool, called once during thread initialization. */ void diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 66b64f96128..3dcf290a276 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1862,14 +1862,6 @@ const char* dict_tf_to_row_format_string( /*=========================*/ ulint table_flag); /*!< in: row format setting */ -/****************************************************************//** -Return maximum size of the node pointer record. -@return maximum size of the record in bytes */ -ulint -dict_index_node_ptr_max_size( -/*=========================*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); /** encode number of columns and number of virtual columns in one 4 bytes value. We could do this because the number of columns in diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 6ed3b105da2..3e06def55b0 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -593,7 +593,7 @@ struct dict_col_t{ inline void detach(const dict_index_t& index); /** Data for instantly added columns */ - struct { + struct def_t { /** original default value of instantly added column */ const void* data; /** len of data, or UNIV_SQL_DEFAULT if unavailable */ @@ -771,6 +771,9 @@ struct dict_field_t{ column if smaller than DICT_ANTELOPE_MAX_INDEX_COL_LEN */ + /** Zero-initialize all fields */ + dict_field_t() : col(NULL), name(NULL), prefix_len(0), fixed_len(0) {} + /** Check whether two index fields are equivalent. @param[in] old the other index field @return whether the index fields are equivalent */ diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index 5dd53c46d1b..407e0221110 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -32,6 +32,9 @@ Created Jan 06, 2010 Vasil Dimov #include "dict0types.h" #include "trx0types.h" +#define TABLE_STATS_NAME "mysql/innodb_table_stats" +#define INDEX_STATS_NAME "mysql/innodb_index_stats" + enum dict_stats_upd_option_t { DICT_STATS_RECALC_PERSISTENT,/* (re) calculate the statistics using a precise and slow @@ -110,12 +113,21 @@ dict_stats_deinit( dict_table_t* table) /*!< in/out: table */ MY_ATTRIBUTE((nonnull)); +#ifdef WITH_WSREP +/** Update the table modification counter and if necessary, +schedule new estimates for table and index statistics to be calculated. +@param[in,out] table persistent or temporary table +@param[in] thd current session */ +void dict_stats_update_if_needed(dict_table_t* table, THD* thd) + MY_ATTRIBUTE((nonnull(1))); +#else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void -dict_stats_update_if_needed(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t* table) MY_ATTRIBUTE((nonnull)); +# define dict_stats_update_if_needed(t,thd) dict_stats_update_if_needed_func(t) +#endif /*********************************************************************//** Calculates new estimates for table and index statistics. The statistics diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 968fd1573c6..eb00239ca4e 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -327,6 +327,9 @@ struct fil_node_t { { return(handle != OS_FILE_CLOSED); } + + /** Close the file handle. */ + void close(); }; /** Value of fil_node_t::magic_n */ diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h index b5187ce2a41..2a2b25c36bd 100644 --- a/storage/innobase/include/fts0ast.h +++ b/storage/innobase/include/fts0ast.h @@ -1,6 +1,7 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, 2018, MariaDB Corporation. 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 @@ -296,6 +297,8 @@ struct fts_ast_node_t { fts_ast_node_t* next_alloc; /*!< For tracking allocations */ bool visited; /*!< whether this node is already processed */ + /** current transaction */ + const trx_t* trx; /* Used by plugin parser */ fts_ast_node_t* up_node; /*!< Direct up node */ bool go_up; /*!< Flag if go one level up */ diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index be2fe7e040b..068720c1947 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2016, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -561,6 +561,7 @@ fts_commit( MY_ATTRIBUTE((warn_unused_result)); /** FTS Query entry point. +@param[in,out] trx transaction @param[in] index fts index to search @param[in] flags FTS search mode @param[in] query_str FTS query @@ -569,6 +570,7 @@ fts_commit( @return DB_SUCCESS if successful otherwise error code */ dberr_t fts_query( + trx_t* trx, dict_index_t* index, uint flags, const byte* query_str, @@ -711,6 +713,12 @@ fts_drop_index_tables( dict_index_t* index) /*!< in: Index to drop */ MY_ATTRIBUTE((warn_unused_result)); +/** Add the table to add to the OPTIMIZER's list. +@param[in] table table to add */ +void +fts_optimize_add_table( + dict_table_t* table); + /******************************************************************//** Remove the table from the OPTIMIZER's list. We do wait for acknowledgement from the consumer of the message. */ diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index aef6e816461..d045c9d3c72 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -512,13 +512,6 @@ fts_get_table_id( MY_ATTRIBUTE((warn_unused_result)); /******************************************************************//** -Add the table to add to the OPTIMIZER's list. */ -void -fts_optimize_add_table( -/*===================*/ - dict_table_t* table); /*!< in: table to add */ - -/******************************************************************//** Construct the prefix name of an FTS table. @return own: table name, must be freed with ut_free() */ char* diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index e4b8947ac3a..0f6fe158264 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -806,69 +806,6 @@ lock_trx_has_expl_x_lock( MY_ATTRIBUTE((nonnull, warn_unused_result)); #endif /* UNIV_DEBUG */ -/** -Allocate cached locks for the transaction. -@param trx allocate cached record locks for this transaction */ -void -lock_trx_alloc_locks(trx_t* trx); - -/** Lock modes and types */ -/* @{ */ -#define LOCK_MODE_MASK 0xFUL /*!< mask used to extract mode from the - type_mode field in a lock */ -/** Lock types */ -/* @{ */ -#define LOCK_TABLE 16U /*!< table lock */ -#define LOCK_REC 32U /*!< record lock */ -#define LOCK_TYPE_MASK 0xF0UL /*!< mask used to extract lock type from the - type_mode field in a lock */ -#if LOCK_MODE_MASK & LOCK_TYPE_MASK -# error "LOCK_MODE_MASK & LOCK_TYPE_MASK" -#endif - -#define LOCK_WAIT 256U /*!< Waiting lock flag; when set, it - means that the lock has not yet been - granted, it is just waiting for its - turn in the wait queue */ -/* Precise modes */ -#define LOCK_ORDINARY 0 /*!< this flag denotes an ordinary - next-key lock in contrast to LOCK_GAP - or LOCK_REC_NOT_GAP */ -#define LOCK_GAP 512U /*!< when this bit is set, it means that the - lock holds only on the gap before the record; - for instance, an x-lock on the gap does not - give permission to modify the record on which - the bit is set; locks of this type are created - when records are removed from the index chain - of records */ -#define LOCK_REC_NOT_GAP 1024U /*!< this bit means that the lock is only on - the index record and does NOT block inserts - to the gap before the index record; this is - used in the case when we retrieve a record - with a unique key, and is also used in - locking plain SELECTs (not part of UPDATE - or DELETE) when the user has set the READ - COMMITTED isolation level */ -#define LOCK_INSERT_INTENTION 2048U/*!< this bit is set when we place a waiting - gap type record lock request in order to let - an insert of an index record to wait until - there are no conflicting locks by other - transactions on the gap; note that this flag - remains set when the waiting lock is granted, - or if the lock is inherited to a neighboring - record */ -#define LOCK_PREDICATE 8192U /*!< Predicate lock */ -#define LOCK_PRDT_PAGE 16384U /*!< Page lock */ - - -#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_MODE_MASK -# error -#endif -#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_TYPE_MASK -# error -#endif -/* @} */ - /** Lock operation struct */ struct lock_op_t{ dict_table_t* table; /*!< table to be locked */ diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index f5b2b51acfc..d9377e97d40 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -42,19 +42,6 @@ those functions in lock/ */ #define UINT32_MAX (4294967295U) #endif -/** A table lock */ -struct lock_table_t { - dict_table_t* table; /*!< database table in dictionary - cache */ - UT_LIST_NODE_T(lock_t) - locks; /*!< list of locks on the same - table */ - /** Print the table lock into the given output stream - @param[in,out] out the output stream - @return the given output stream. */ - std::ostream& print(std::ostream& out) const; -}; - /** Print the table lock into the given output stream @param[in,out] out the output stream @return the given output stream. */ @@ -77,131 +64,11 @@ operator<<(std::ostream& out, const lock_table_t& lock) return(lock.print(out)); } -/** Record lock for a page */ -struct lock_rec_t { - ib_uint32_t space; /*!< space id */ - ib_uint32_t page_no; /*!< page number */ - ib_uint32_t n_bits; /*!< number of bits in the lock - bitmap; NOTE: the lock bitmap is - placed immediately after the - lock struct */ - - /** Print the record lock into the given output stream - @param[in,out] out the output stream - @return the given output stream. */ - std::ostream& print(std::ostream& out) const; -}; - -/** Print the record lock into the given output stream -@param[in,out] out the output stream -@return the given output stream. */ -inline -std::ostream& lock_rec_t::print(std::ostream& out) const -{ - out << "[lock_rec_t: space=" << space << ", page_no=" << page_no - << ", n_bits=" << n_bits << "]"; - return(out); -} - -inline -std::ostream& -operator<<(std::ostream& out, const lock_rec_t& lock) -{ - return(lock.print(out)); -} - -/** Lock struct; protected by lock_sys.mutex */ -struct lock_t { - trx_t* trx; /*!< transaction owning the - lock */ - UT_LIST_NODE_T(lock_t) - trx_locks; /*!< list of the locks of the - transaction */ - - dict_index_t* index; /*!< index for a record lock */ - - lock_t* hash; /*!< hash chain node for a record - lock. The link node in a singly linked - list, used during hashing. */ - - /* Statistics for how long lock has been held and time - how long this lock had to be waited before it was granted */ - time_t requested_time; /*!< Lock request time */ - ulint wait_time; /*!< Time waited this lock or 0 */ - - union { - lock_table_t tab_lock;/*!< table lock */ - lock_rec_t rec_lock;/*!< record lock */ - } un_member; /*!< lock details */ - - ib_uint32_t type_mode; /*!< lock type, mode, LOCK_GAP or - LOCK_REC_NOT_GAP, - LOCK_INSERT_INTENTION, - wait flag, ORed */ - - /** Determine if the lock object is a record lock. - @return true if record lock, false otherwise. */ - bool is_record_lock() const - { - return(type() == LOCK_REC); - } - - bool is_waiting() const - { - return(type_mode & LOCK_WAIT); - } - - bool is_gap() const - { - return(type_mode & LOCK_GAP); - } - - bool is_record_not_gap() const - { - return(type_mode & LOCK_REC_NOT_GAP); - } - - bool is_insert_intention() const - { - return(type_mode & LOCK_INSERT_INTENTION); - } - - ulint type() const { - return(type_mode & LOCK_TYPE_MASK); - } - - enum lock_mode mode() const - { - return(static_cast<enum lock_mode>(type_mode & LOCK_MODE_MASK)); - } - - /** Print the lock object into the given output stream. - @param[in,out] out the output stream - @return the given output stream. */ - std::ostream& print(std::ostream& out) const; - - /** Convert the member 'type_mode' into a human readable string. - @return human readable string */ - std::string type_mode_string() const; - - const char* type_string() const - { - switch (type_mode & LOCK_TYPE_MASK) { - case LOCK_REC: - return("LOCK_REC"); - case LOCK_TABLE: - return("LOCK_TABLE"); - default: - ut_error; - } - } -}; - /** Convert the member 'type_mode' into a human readable string. @return human readable string */ inline std::string -lock_t::type_mode_string() const +ib_lock_t::type_mode_string() const { std::ostringstream sout; sout << type_string(); @@ -227,7 +94,7 @@ lock_t::type_mode_string() const inline std::ostream& -lock_t::print(std::ostream& out) const +ib_lock_t::print(std::ostream& out) const { out << "[lock_t: type_mode=" << type_mode << "(" << type_mode_string() << ")"; @@ -244,7 +111,7 @@ lock_t::print(std::ostream& out) const inline std::ostream& -operator<<(std::ostream& out, const lock_t& lock) +operator<<(std::ostream& out, const ib_lock_t& lock) { return(lock.print(out)); } diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic index 150a80b7be4..b5be9076644 100644 --- a/storage/innobase/include/lock0priv.ic +++ b/storage/innobase/include/lock0priv.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -388,17 +389,10 @@ lock_table_has( const dict_table_t* table, /*!< in: table */ lock_mode in_mode)/*!< in: lock mode */ { - if (trx->lock.table_locks.empty()) { - return(NULL); - } - - typedef lock_pool_t::const_reverse_iterator iterator; - - iterator end = trx->lock.table_locks.rend(); - /* Look for stronger locks the same trx already has on the table */ - for (iterator it = trx->lock.table_locks.rbegin(); it != end; ++it) { + for (lock_list::const_iterator it = trx->lock.table_locks.begin(), + end = trx->lock.table_locks.end(); it != end; ++it) { const lock_t* lock = *it; diff --git a/storage/innobase/include/lock0types.h b/storage/innobase/include/lock0types.h index 792a5f21acb..1aac5d20a59 100644 --- a/storage/innobase/include/lock0types.h +++ b/storage/innobase/include/lock0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -72,6 +73,195 @@ const char* lock_mode_string(enum lock_mode mode) } } -typedef UT_LIST_BASE_NODE_T(lock_t) trx_lock_list_t; +/** A table lock */ +struct lock_table_t { + dict_table_t* table; /*!< database table in dictionary + cache */ + UT_LIST_NODE_T(ib_lock_t) + locks; /*!< list of locks on the same + table */ + /** Print the table lock into the given output stream + @param[in,out] out the output stream + @return the given output stream. */ + std::ostream& print(std::ostream& out) const; +}; + +/** Record lock for a page */ +struct lock_rec_t { + ib_uint32_t space; /*!< space id */ + ib_uint32_t page_no; /*!< page number */ + ib_uint32_t n_bits; /*!< number of bits in the lock + bitmap; NOTE: the lock bitmap is + placed immediately after the + lock struct */ + + /** Print the record lock into the given output stream + @param[in,out] out the output stream + @return the given output stream. */ + std::ostream& print(std::ostream& out) const; +}; + +/** Print the record lock into the given output stream +@param[in,out] out the output stream +@return the given output stream. */ +inline +std::ostream& lock_rec_t::print(std::ostream& out) const +{ + out << "[lock_rec_t: space=" << space << ", page_no=" << page_no + << ", n_bits=" << n_bits << "]"; + return(out); +} + +inline +std::ostream& +operator<<(std::ostream& out, const lock_rec_t& lock) +{ + return(lock.print(out)); +} + +#define LOCK_MODE_MASK 0xFUL /*!< mask used to extract mode from the + type_mode field in a lock */ +/** Lock types */ +/* @{ */ +#define LOCK_TABLE 16U /*!< table lock */ +#define LOCK_REC 32U /*!< record lock */ +#define LOCK_TYPE_MASK 0xF0UL /*!< mask used to extract lock type from the + type_mode field in a lock */ +#if LOCK_MODE_MASK & LOCK_TYPE_MASK +# error "LOCK_MODE_MASK & LOCK_TYPE_MASK" +#endif + +#define LOCK_WAIT 256U /*!< Waiting lock flag; when set, it + means that the lock has not yet been + granted, it is just waiting for its + turn in the wait queue */ +/* Precise modes */ +#define LOCK_ORDINARY 0 /*!< this flag denotes an ordinary + next-key lock in contrast to LOCK_GAP + or LOCK_REC_NOT_GAP */ +#define LOCK_GAP 512U /*!< when this bit is set, it means that the + lock holds only on the gap before the record; + for instance, an x-lock on the gap does not + give permission to modify the record on which + the bit is set; locks of this type are created + when records are removed from the index chain + of records */ +#define LOCK_REC_NOT_GAP 1024U /*!< this bit means that the lock is only on + the index record and does NOT block inserts + to the gap before the index record; this is + used in the case when we retrieve a record + with a unique key, and is also used in + locking plain SELECTs (not part of UPDATE + or DELETE) when the user has set the READ + COMMITTED isolation level */ +#define LOCK_INSERT_INTENTION 2048U/*!< this bit is set when we place a waiting + gap type record lock request in order to let + an insert of an index record to wait until + there are no conflicting locks by other + transactions on the gap; note that this flag + remains set when the waiting lock is granted, + or if the lock is inherited to a neighboring + record */ +#define LOCK_PREDICATE 8192U /*!< Predicate lock */ +#define LOCK_PRDT_PAGE 16384U /*!< Page lock */ + + +#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_MODE_MASK +# error +#endif +#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_TYPE_MASK +# error +#endif +/* @} */ + +/** Lock struct; protected by lock_sys.mutex */ +struct ib_lock_t +{ + trx_t* trx; /*!< transaction owning the + lock */ + UT_LIST_NODE_T(ib_lock_t) + trx_locks; /*!< list of the locks of the + transaction */ + + dict_index_t* index; /*!< index for a record lock */ + + ib_lock_t* hash; /*!< hash chain node for a record + lock. The link node in a singly linked + list, used during hashing. */ + + /* Statistics for how long lock has been held and time + how long this lock had to be waited before it was granted */ + time_t requested_time; /*!< Lock request time */ + ulint wait_time; /*!< Time waited this lock or 0 */ + + union { + lock_table_t tab_lock;/*!< table lock */ + lock_rec_t rec_lock;/*!< record lock */ + } un_member; /*!< lock details */ + + ib_uint32_t type_mode; /*!< lock type, mode, LOCK_GAP or + LOCK_REC_NOT_GAP, + LOCK_INSERT_INTENTION, + wait flag, ORed */ + + /** Determine if the lock object is a record lock. + @return true if record lock, false otherwise. */ + bool is_record_lock() const + { + return(type() == LOCK_REC); + } + + bool is_waiting() const + { + return(type_mode & LOCK_WAIT); + } + + bool is_gap() const + { + return(type_mode & LOCK_GAP); + } + + bool is_record_not_gap() const + { + return(type_mode & LOCK_REC_NOT_GAP); + } + + bool is_insert_intention() const + { + return(type_mode & LOCK_INSERT_INTENTION); + } + + ulint type() const { + return(type_mode & LOCK_TYPE_MASK); + } + + enum lock_mode mode() const + { + return(static_cast<enum lock_mode>(type_mode & LOCK_MODE_MASK)); + } + + /** Print the lock object into the given output stream. + @param[in,out] out the output stream + @return the given output stream. */ + std::ostream& print(std::ostream& out) const; + + /** Convert the member 'type_mode' into a human readable string. + @return human readable string */ + std::string type_mode_string() const; + + const char* type_string() const + { + switch (type_mode & LOCK_TYPE_MASK) { + case LOCK_REC: + return("LOCK_REC"); + case LOCK_TABLE: + return("LOCK_TABLE"); + default: + ut_error; + } + } +}; + +typedef UT_LIST_BASE_NODE_T(ib_lock_t) trx_lock_list_t; #endif /* lock0types_h */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 6d528b1d88a..986b4dede97 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -492,14 +492,6 @@ or the MySQL version that created the redo log file. */ header */ #define LOG_FILE_HDR_SIZE (4 * OS_FILE_LOG_BLOCK_SIZE) -/** The state of a log group */ -enum log_group_state_t { - /** No corruption detected */ - LOG_GROUP_OK, - /** Corrupted */ - LOG_GROUP_CORRUPTED -}; - typedef ib_mutex_t LogSysMutex; typedef ib_mutex_t FlushOrderMutex; @@ -557,8 +549,6 @@ struct log_t{ ulint format; /** individual log file size in bytes, including the header */ lsn_t file_size; - /** corruption status */ - log_group_state_t state; /** lsn used to fix coordinates within the log group */ lsn_t lsn; /** the byte offset of the above lsn */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 15ad34ba9a5..eda991661c1 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -139,9 +139,21 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply); /** Moves the parsing buffer data left to the buffer start. */ void recv_sys_justify_left_parsing_buf(); -/** Backup function checks whether the space id belongs to -the skip table list given in the mariabackup option. */ -extern bool(*check_if_backup_includes)(ulint space_id); +/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +@param[in] space_id tablespace identifier +*/ +extern void(*log_optimized_ddl_op)(ulint space_id); + +/** Report an operation to create, delete, or rename a file during backup. +@param[in] space_id tablespace identifier +@param[in] flags tablespace flags (NULL if not create) +@param[in] name file name (not NUL-terminated) +@param[in] len length of name, in bytes +@param[in] new_name new file name (NULL if not rename) +@param[in] new_len length of new_name, in bytes (0 if NULL) */ +extern void (*log_file_op)(ulint space_id, const byte* flags, + const byte* name, ulint len, + const byte* new_name, ulint new_len); /** Block of log record data */ struct recv_data_t{ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 7d5c1c414bd..0c157cb87cf 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -61,13 +61,6 @@ savepoint. */ @return old mode */ #define mtr_set_log_mode(m, d) (m)->set_log_mode((d)) -/** Get the flush observer of a mini-transaction. -@return flush observer object */ -#define mtr_get_flush_observer(m) (m)->get_flush_observer() - -/** Set the flush observer of a mini-transaction. */ -#define mtr_set_flush_observer(m, d) (m)->set_flush_observer((d)) - /** Read 1 - 4 bytes from a file page buffered in the buffer pool. @return value read */ #define mtr_read_ulint(p, t, m) (m)->read_ulint((p), (t)) diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index 78908b998fe..d98dfa5ec07 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -328,6 +328,20 @@ page_cur_open_on_rnd_user_rec( /*==========================*/ buf_block_t* block, /*!< in: page */ page_cur_t* cursor);/*!< out: page cursor */ +/** Write a redo log record of inserting a record into an index page. +@param[in] insert_rec inserted record +@param[in] rec_size rec_get_size(insert_rec) +@param[in] cursor_rec predecessor of insert_rec +@param[in,out] index index tree +@param[in,out] mtr mini-transaction */ +void +page_cur_insert_rec_write_log( + const rec_t* insert_rec, + ulint rec_size, + const rec_t* cursor_rec, + dict_index_t* index, + mtr_t* mtr) + MY_ATTRIBUTE((nonnull)); /***********************************************************//** Parses a log record of a record insert on a page. @return end of log record or NULL */ diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index cc8b92e99b1..3ee993944e9 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -312,6 +312,31 @@ rec_set_status(rec_t* rec, byte bits) | bits; } +/** Get the length of added field count in a REC_STATUS_COLUMNS_ADDED record. +@param[in] n_add_field number of added fields, minus one +@return storage size of the field count, in bytes */ +inline unsigned rec_get_n_add_field_len(ulint n_add_field) +{ + ut_ad(n_add_field < REC_MAX_N_FIELDS); + return n_add_field < 0x80 ? 1 : 2; +} + +/** Set the added field count in a REC_STATUS_COLUMNS_ADDED record. +@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record +@param[in] n_add number of added fields, minus 1 +@return record header before the number of added fields */ +inline void rec_set_n_add_field(byte*& header, ulint n_add) +{ + ut_ad(n_add < REC_MAX_N_FIELDS); + + if (n_add < 0x80) { + *header-- = byte(n_add); + } else { + *header-- = byte(n_add) | 0x80; + *header-- = byte(n_add >> 7); + } +} + /******************************************************//** The following function is used to retrieve the info and status bits of a record. (Only compact records have status bits.) @@ -962,6 +987,7 @@ rec_get_converted_size_temp( @param[in] index index of that the record belongs to @param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets) @param[in] n_core number of core fields (index->n_core_fields) +@param[in] def_val default values for non-core fields @param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */ void rec_init_offsets_temp( @@ -969,6 +995,7 @@ rec_init_offsets_temp( const dict_index_t* index, ulint* offsets, ulint n_core, + const dict_col_t::def_t*def_val, rec_comp_status_t status = REC_STATUS_ORDINARY) MY_ATTRIBUTE((nonnull)); /** Determine the offset to each field in temporary file. diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h index 25204895f1a..3ae5d5bc175 100644 --- a/storage/innobase/include/row0ftsort.h +++ b/storage/innobase/include/row0ftsort.h @@ -122,6 +122,16 @@ struct fts_tokenize_ctx { dfield_t sort_field[FTS_NUM_FIELDS_SORT]; /*!< in: sort field */ fts_token_list_t fts_token_list; + + fts_tokenize_ctx() : + processed_len(0), init_pos(0), buf_used(0), + rows_added(), cached_stopword(NULL), sort_field(), + fts_token_list() + { + memset(rows_added, 0, sizeof rows_added); + memset(sort_field, 0, sizeof sort_field); + UT_LIST_INIT(fts_token_list, &row_fts_token_t::token_list); + } }; typedef struct fts_tokenize_ctx fts_tokenize_ctx_t; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 69374ab3fba..6af212d35ff 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -646,8 +646,11 @@ public: { mutex_enter(&element->mutex); lf_hash_search_unpin(pins); - if ((trx= element->trx)) - { + trx= element->trx; + if (!trx); + else if (UNIV_UNLIKELY(trx_id != trx->id)) + trx= NULL; + else { if (do_ref_count) trx->reference(); ut_d(validate_element(trx)); diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 76d4e9caba0..d6a8b8c771b 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -476,7 +476,9 @@ Check transaction state */ @param t transaction handle */ #define assert_trx_is_free(t) do { \ ut_ad(trx_state_eq((t), TRX_STATE_NOT_STARTED)); \ - ut_ad(!trx->has_logged()); \ + ut_ad(!(t)->id); \ + ut_ad(!(t)->has_logged()); \ + ut_ad(!(t)->is_referenced()); \ ut_ad(!(t)->read_view.is_open()); \ ut_ad((t)->lock.wait_thr == NULL); \ ut_ad(UT_LIST_GET_LEN((t)->lock.trx_locks) == 0); \ @@ -517,7 +519,7 @@ The transaction must have mysql_thd assigned. */ # define assert_trx_nonlocking_or_in_list(trx) ((void)0) #endif /* UNIV_DEBUG */ -typedef std::vector<ib_lock_t*, ut_allocator<ib_lock_t*> > lock_pool_t; +typedef std::vector<ib_lock_t*, ut_allocator<ib_lock_t*> > lock_list; /*******************************************************************//** Latching protocol for trx_lock_t::que_state. trx_lock_t::que_state @@ -579,13 +581,19 @@ struct trx_lock_t { only be modified by the thread that is serving the running transaction. */ - lock_pool_t rec_pool; /*!< Pre-allocated record locks */ + /** Pre-allocated record locks */ + struct { + ib_lock_t lock; byte pad[256]; + } rec_pool[8]; - lock_pool_t table_pool; /*!< Pre-allocated table locks */ + /** Pre-allocated table locks */ + ib_lock_t table_pool[8]; - ulint rec_cached; /*!< Next free rec lock in pool */ + /** Next available rec_pool[] entry */ + unsigned rec_cached; - ulint table_cached; /*!< Next free table lock in pool */ + /** Next available table_pool[] entry */ + unsigned table_cached; mem_heap_t* lock_heap; /*!< memory heap for trx_locks; protected by lock_sys.mutex */ @@ -595,7 +603,7 @@ struct trx_lock_t { and lock_sys.mutex; removals are protected by lock_sys.mutex */ - lock_pool_t table_locks; /*!< All table locks requested by this + lock_list table_locks; /*!< All table locks requested by this transaction, including AUTOINC locks */ bool cancel; /*!< true if the transaction is being diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index ffa4967b9de..bf1d245a65e 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 7 -#define INNODB_VERSION_BUGFIX 22 +#define INNODB_VERSION_BUGFIX 23 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index 6367b53dbe6..d3ea733a440 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -125,8 +125,7 @@ struct Pool { elem = NULL; } - m_lock_strategy.exit(); - +#if defined HAVE_valgrind || defined __SANITIZE_ADDRESS__ if (elem) { /* Unpoison the memory for AddressSanitizer */ MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); @@ -135,10 +134,11 @@ struct Pool { actually initialized; we checked that by UNIV_MEM_ASSERT_RW() in mem_free() below. */ UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); - return &elem->m_type; } +#endif - return NULL; + m_lock_strategy.exit(); + return elem ? &elem->m_type : NULL; } /** Add the object to the pool. @@ -151,8 +151,12 @@ struct Pool { elem = reinterpret_cast<Element*>(p - sizeof(*elem)); UNIV_MEM_ASSERT_RW(&elem->m_type, sizeof elem->m_type); - elem->m_pool->put(elem); + elem->m_pool->m_lock_strategy.enter(); + + elem->m_pool->putl(elem); MEM_NOACCESS(&elem->m_type, sizeof elem->m_type); + + elem->m_pool->m_lock_strategy.exit(); } protected: @@ -170,17 +174,13 @@ private: /** Release the object to the free pool @param elem element to free */ - void put(Element* elem) + void putl(Element* elem) { - m_lock_strategy.enter(); - ut_ad(elem >= m_start && elem < m_last); ut_ad(Factory::debug(&elem->m_type)); m_pqueue.push(elem); - - m_lock_strategy.exit(); } /** Initialise the elements. diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 4d93f2c449c..07ae85ced5a 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -59,18 +59,6 @@ ulong innodb_lock_schedule_algorithm; /** The value of innodb_deadlock_detect */ my_bool innobase_deadlock_detect; -/** Total number of cached record locks */ -static const ulint REC_LOCK_CACHE = 8; - -/** Maximum record lock size in bytes */ -static const ulint REC_LOCK_SIZE = sizeof(ib_lock_t) + 256; - -/** Total number of cached table locks */ -static const ulint TABLE_LOCK_CACHE = 8; - -/** Size in bytes, of the table lock instance */ -static const ulint TABLE_LOCK_SIZE = sizeof(ib_lock_t); - /*********************************************************************//** Checks if a waiting record lock request still has to wait in a queue. @return lock that is causing the wait */ @@ -1409,13 +1397,13 @@ lock_rec_create_low( } } - if (trx->lock.rec_cached >= trx->lock.rec_pool.size() - || sizeof *lock + n_bytes > REC_LOCK_SIZE) { + if (trx->lock.rec_cached >= UT_ARR_SIZE(trx->lock.rec_pool) + || sizeof *lock + n_bytes > sizeof *trx->lock.rec_pool) { lock = static_cast<lock_t*>( mem_heap_alloc(trx->lock.lock_heap, sizeof *lock + n_bytes)); } else { - lock = trx->lock.rec_pool[trx->lock.rec_cached++]; + lock = &trx->lock.rec_pool[trx->lock.rec_cached++].lock; } lock->trx = trx; @@ -1750,7 +1738,10 @@ lock_rec_enqueue_waiting( lock_prdt_set_prdt(lock, prdt); } - if (const trx_t* victim = + if ( +#ifdef UNIV_DEBUG + const trx_t* victim = +#endif DeadlockChecker::check_and_resolve(lock, trx)) { ut_ad(victim == trx); lock_reset_lock_and_trx_wait(lock); @@ -3517,8 +3508,9 @@ lock_table_create( ib_vector_push(trx->autoinc_locks, &lock); - } else if (trx->lock.table_cached < trx->lock.table_pool.size()) { - lock = trx->lock.table_pool[trx->lock.table_cached++]; + } else if (trx->lock.table_cached + < UT_ARR_SIZE(trx->lock.table_pool)) { + lock = &trx->lock.table_pool[trx->lock.table_cached++]; } else { lock = static_cast<lock_t*>( @@ -4370,24 +4362,15 @@ lock_trx_table_locks_remove( ut_ad(trx_mutex_own(trx)); } - typedef lock_pool_t::reverse_iterator iterator; - - iterator end = trx->lock.table_locks.rend(); - - for (iterator it = trx->lock.table_locks.rbegin(); it != end; ++it) { - + for (lock_list::iterator it = trx->lock.table_locks.begin(), + end = trx->lock.table_locks.end(); it != end; ++it) { const lock_t* lock = *it; - if (lock == NULL) { - continue; - } - - ut_a(trx == lock->trx); - ut_a(lock_get_type_low(lock) & LOCK_TABLE); - ut_a(lock->un_member.tab_lock.table != NULL); + ut_ad(!lock || trx == lock->trx); + ut_ad(!lock || lock_get_type_low(lock) & LOCK_TABLE); + ut_ad(!lock || lock->un_member.tab_lock.table); if (lock == lock_to_remove) { - *it = NULL; if (!trx->lock.cancel) { @@ -4804,11 +4787,8 @@ lock_trx_table_locks_find( trx_mutex_enter(trx); - typedef lock_pool_t::const_reverse_iterator iterator; - - iterator end = trx->lock.table_locks.rend(); - - for (iterator it = trx->lock.table_locks.rbegin(); it != end; ++it) { + for (lock_list::const_iterator it = trx->lock.table_locks.begin(), + end = trx->lock.table_locks.end(); it != end; ++it) { const lock_t* lock = *it; @@ -6334,6 +6314,9 @@ lock_trx_release_locks( /*--------------------------------------*/ trx_mutex_enter(trx); trx->state = TRX_STATE_COMMITTED_IN_MEMORY; + /* Ensure that rw_trx_hash_t::find() will no longer find + this transaction. */ + trx->id = 0; trx_mutex_exit(trx); /*--------------------------------------*/ @@ -6544,10 +6527,8 @@ lock_trx_has_sys_table_locks( lock_mutex_enter(); - typedef lock_pool_t::const_reverse_iterator iterator; - - iterator end = trx->lock.table_locks.rend(); - iterator it = trx->lock.table_locks.rbegin(); + const lock_list::const_iterator end = trx->lock.table_locks.end(); + lock_list::const_iterator it = trx->lock.table_locks.begin(); /* Find a valid mode. Note: ib_vector_size() can be 0. */ @@ -7099,33 +7080,6 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) return(victim_trx); } -/** -Allocate cached locks for the transaction. -@param trx allocate cached record locks for this transaction */ -void -lock_trx_alloc_locks(trx_t* trx) -{ - ulint sz = REC_LOCK_SIZE * REC_LOCK_CACHE; - byte* ptr = reinterpret_cast<byte*>(ut_malloc_nokey(sz)); - - /* We allocate one big chunk and then distribute it among - the rest of the elements. The allocated chunk pointer is always - at index 0. */ - - for (ulint i = 0; i < REC_LOCK_CACHE; ++i, ptr += REC_LOCK_SIZE) { - trx->lock.rec_pool.push_back( - reinterpret_cast<ib_lock_t*>(ptr)); - } - - sz = TABLE_LOCK_SIZE * TABLE_LOCK_CACHE; - ptr = reinterpret_cast<byte*>(ut_malloc_nokey(sz)); - - for (ulint i = 0; i < TABLE_LOCK_CACHE; ++i, ptr += TABLE_LOCK_SIZE) { - trx->lock.table_pool.push_back( - reinterpret_cast<ib_lock_t*>(ptr)); - } - -} /*************************************************************//** Updates the lock table when a page is split and merged to two pages. */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index c1efef231f6..08f4f72efbc 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -667,7 +667,6 @@ void log_t::files::create(ulint n_files) format= srv_encrypt_log ? LOG_HEADER_FORMAT_ENC_10_4 : LOG_HEADER_FORMAT_10_3; file_size= srv_log_file_size; - state= LOG_GROUP_OK; lsn= LOG_START_LSN; lsn_offset= LOG_FILE_HDR_SIZE; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1339e4c3745..1cbb102bfdd 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -169,9 +169,21 @@ typedef std::map< static recv_spaces_t recv_spaces; -/** Backup function checks whether the space id belongs to -the skip table list given in the mariabackup option. */ -bool(*check_if_backup_includes)(ulint space_id); +/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +@param[in] space_id tablespace identifier +*/ +void (*log_optimized_ddl_op)(ulint space_id); + +/** Report an operation to create, delete, or rename a file during backup. +@param[in] space_id tablespace identifier +@param[in] flags tablespace flags (NULL if not create) +@param[in] name file name (not NUL-terminated) +@param[in] len length of name, in bytes +@param[in] new_name new file name (NULL if not rename) +@param[in] new_len length of new_name, in bytes (0 if NULL) */ +void (*log_file_op)(ulint space_id, const byte* flags, + const byte* name, ulint len, + const byte* new_name, ulint new_len); /** Process a file name from a MLOG_FILE_* record. @param[in,out] name file name @@ -381,9 +393,13 @@ fil_name_parse( fil_name_process( reinterpret_cast<char*>(ptr), len, space_id, true); - - break; + /* fall through */ case MLOG_FILE_CREATE2: + if (log_file_op) { + log_file_op(space_id, + type == MLOG_FILE_CREATE2 ? ptr - 4 : NULL, + ptr, len, NULL, 0); + } break; case MLOG_FILE_RENAME2: if (corrupt) { @@ -424,6 +440,11 @@ fil_name_parse( reinterpret_cast<char*>(new_name), new_len, space_id, false); + if (log_file_op) { + log_file_op(space_id, NULL, + ptr, len, new_name, new_len); + } + if (!apply) { break; } @@ -719,6 +740,15 @@ fail: goto fail; } } + + ulint dl = log_block_get_data_len(buf); + if (dl < LOG_BLOCK_HDR_SIZE + || (dl != OS_FILE_LOG_BLOCK_SIZE + && dl > log_sys.trailer_offset())) { + recv_sys->found_corrupt_log = true; + end_lsn = *start_lsn; + break; + } } if (recv_sys->report(ut_time())) { @@ -837,8 +867,6 @@ recv_find_max_checkpoint_0(ulint* max_field) *max_field = field; max_no = checkpoint_no; - log_sys.log.state = LOG_GROUP_OK; - log_sys.log.lsn = mach_read_from_8( buf + LOG_CHECKPOINT_LSN); log_sys.log.lsn_offset = static_cast<ib_uint64_t>( @@ -933,8 +961,6 @@ recv_find_max_checkpoint(ulint* max_field) buf = log_sys.checkpoint_buf; - log_sys.log.state = LOG_GROUP_CORRUPTED; - log_header_read(0); /* Check the header page checksum. There was no checksum in the first redo log format (version 0). */ @@ -1002,7 +1028,6 @@ recv_find_max_checkpoint(ulint* max_field) if (checkpoint_no >= max_no) { *max_field = field; max_no = checkpoint_no; - log_sys.log.state = LOG_GROUP_OK; log_sys.log.lsn = mach_read_from_8( buf + LOG_CHECKPOINT_LSN); log_sys.log.lsn_offset = mach_read_from_8( @@ -1447,7 +1472,8 @@ parse_log: break; default: ptr = NULL; - ib::error() << "Incorrect log record type:" << type; + ib::error() << "Incorrect log record type " + << ib::hex(unsigned(type)); recv_sys->found_corrupt_log = true; } @@ -2133,7 +2159,8 @@ recv_parse_log_rec( case MLOG_MULTI_REC_END | MLOG_SINGLE_REC_FLAG: case MLOG_DUMMY_RECORD | MLOG_SINGLE_REC_FLAG: case MLOG_CHECKPOINT | MLOG_SINGLE_REC_FLAG: - ib::error() << "Incorrect log record type:" << *ptr; + ib::error() << "Incorrect log record type " + << ib::hex(unsigned(*ptr)); recv_sys->found_corrupt_log = true; return(0); } @@ -2152,7 +2179,6 @@ recv_parse_log_rec( *type, new_ptr, end_ptr, *space, *page_no, apply, NULL, NULL); if (UNIV_UNLIKELY(new_ptr == NULL)) { - return(0); } @@ -2204,30 +2230,30 @@ recv_report_corrupt_log( ib::error() << "############### CORRUPT LOG RECORD FOUND ##################"; + const ulint ptr_offset = ulint(ptr - recv_sys->buf); + ib::info() << "Log record type " << type << ", page " << space << ":" << page_no << ". Log parsing proceeded successfully up to " << recv_sys->recovered_lsn << ". Previous log record type " << recv_previous_parsed_rec_type << ", is multi " << recv_previous_parsed_rec_is_multi << " Recv offset " - << (ptr - recv_sys->buf) << ", prev " + << ptr_offset << ", prev " << recv_previous_parsed_rec_offset; ut_ad(ptr <= recv_sys->buf + recv_sys->len); const ulint limit = 100; - const ulint before - = std::min(recv_previous_parsed_rec_offset, limit); - const ulint after - = std::min(recv_sys->len - ulint(ptr - recv_sys->buf), limit); + const ulint prev_offset = std::min(recv_previous_parsed_rec_offset, + ptr_offset); + const ulint before = std::min(prev_offset, limit); + const ulint after = std::min(recv_sys->len - ptr_offset, limit); ib::info() << "Hex dump starting " << before << " bytes before and" " ending " << after << " bytes after the corrupted record:"; - ut_print_buf(stderr, - recv_sys->buf - + recv_previous_parsed_rec_offset - before, - ulint(ptr - recv_sys->buf) + before + after - - recv_previous_parsed_rec_offset); + const byte* start = recv_sys->buf + prev_offset - before; + + ut_print_buf(stderr, start, ulint(ptr - start) + after); putc('\n', stderr); if (!srv_force_recovery) { @@ -2298,13 +2324,8 @@ loop: len = recv_parse_log_rec(&type, ptr, end_ptr, &space, &page_no, apply, &body); - if (len == 0) { - return(false); - } - if (recv_sys->found_corrupt_log) { - recv_report_corrupt_log( - ptr, type, space, page_no); + recv_report_corrupt_log(ptr, type, space, page_no); return(true); } @@ -2312,6 +2333,10 @@ loop: return(true); } + if (len == 0) { + return(false); + } + new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len); if (new_recovered_lsn > recv_sys->scanned_lsn) { @@ -2399,11 +2424,8 @@ loop: /* fall through */ case MLOG_INDEX_LOAD: if (type == MLOG_INDEX_LOAD) { - if (check_if_backup_includes - && !check_if_backup_includes(space)) { - ut_ad(srv_operation - == SRV_OPERATION_BACKUP); - return true; + if (log_optimized_ddl_op) { + log_optimized_ddl_op(space); } } /* fall through */ @@ -2436,13 +2458,10 @@ loop: &type, ptr, end_ptr, &space, &page_no, false, &body); - if (len == 0) { - return(false); - } - if (recv_sys->found_corrupt_log || type == MLOG_CHECKPOINT - || (*ptr & MLOG_SINGLE_REC_FLAG)) { + || (ptr != end_ptr + && (*ptr & MLOG_SINGLE_REC_FLAG))) { recv_sys->found_corrupt_log = true; recv_report_corrupt_log( ptr, type, space, page_no); @@ -2453,6 +2472,10 @@ loop: return(true); } + if (len == 0) { + return(false); + } + recv_previous_parsed_rec_type = type; recv_previous_parsed_rec_offset = recv_sys->recovered_offset + total_len; diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc index b789e24f19c..6baf1f06bf9 100644 --- a/storage/innobase/mtr/mtr0log.cc +++ b/storage/innobase/mtr/mtr0log.cc @@ -98,7 +98,11 @@ mlog_parse_initial_log_record( } *type = mlog_id_t(*ptr & ~MLOG_SINGLE_REC_FLAG); - ut_ad(*type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(*type)); + if (UNIV_UNLIKELY(*type > MLOG_BIGGEST_TYPE + && !EXTRA_CHECK_MLOG_NUMBER(*type))) { + recv_sys->found_corrupt_log = true; + return NULL; + } ptr++; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index c6da047e8c5..208fe356fbe 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2496,30 +2496,15 @@ os_file_fsync_posix( os_thread_sleep(200000); break; - case EIO: - - ++failures; - ut_a(failures < 1000); - - if (!(failures % 100)) { - - ib::warn() - << "fsync(): " - << "An error occurred during " - << "synchronization," - << " retrying"; - } - - /* 0.2 sec */ - os_thread_sleep(200000); - break; - case EINTR: ++failures; ut_a(failures < 2000); break; + case EIO: + ib::error() << "fsync() returned EIO, aborting"; + /* fall through */ default: ut_error; break; @@ -3325,7 +3310,8 @@ os_file_get_status_posix( { int ret = stat(path, statinfo); - if (ret && (errno == ENOENT || errno == ENOTDIR)) { + if (ret && (errno == ENOENT || errno == ENOTDIR + || errno == ENAMETOOLONG)) { /* file does not exist */ return(DB_NOT_FOUND); @@ -4665,7 +4651,8 @@ os_file_get_status_win32( { int ret = _stat64(path, statinfo); - if (ret && (errno == ENOENT || errno == ENOTDIR)) { + if (ret && (errno == ENOENT || errno == ENOTDIR + || errno == ENAMETOOLONG)) { /* file does not exist */ return(DB_NOT_FOUND); diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 9effe74fa7c..36b9a135b10 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -824,18 +824,19 @@ page_cur_open_on_rnd_user_rec( } while (rnd--); } -/***********************************************************//** -Writes the log record of a record insert on a page. */ -static +/** Write a redo log record of inserting a record into an index page. +@param[in] insert_rec inserted record +@param[in] rec_size rec_get_size(insert_rec) +@param[in] cursor_rec predecessor of insert_rec +@param[in,out] index index tree +@param[in,out] mtr mini-transaction */ void page_cur_insert_rec_write_log( -/*==========================*/ - rec_t* insert_rec, /*!< in: inserted physical record */ - ulint rec_size, /*!< in: insert_rec size */ - rec_t* cursor_rec, /*!< in: record the - cursor is pointing to */ - dict_index_t* index, /*!< in: record descriptor */ - mtr_t* mtr) /*!< in: mini-transaction handle */ + const rec_t* insert_rec, + ulint rec_size, + const rec_t* cursor_rec, + dict_index_t* index, + mtr_t* mtr) { ulint cur_rec_size; ulint extra_size; @@ -2255,7 +2256,10 @@ page_cur_parse_delete_rec( offset = mach_read_from_2(ptr); ptr += 2; - ut_a(offset <= srv_page_size); + if (UNIV_UNLIKELY(offset >= srv_page_size)) { + recv_sys->found_corrupt_log = true; + return NULL; + } if (block) { page_t* page = buf_block_get_frame(block); diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 7d1a35d82e4..7a3aa44bc3f 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -237,15 +237,6 @@ rec_get_n_extern_new( return(n_extern); } -/** Get the length of added field count in a REC_STATUS_COLUMNS_ADDED record. -@param[in] n_add_field number of added fields, minus one -@return storage size of the field count, in bytes */ -static inline unsigned rec_get_n_add_field_len(ulint n_add_field) -{ - ut_ad(n_add_field < REC_MAX_N_FIELDS); - return n_add_field < 0x80 ? 1 : 2; -} - /** Get the added field count in a REC_STATUS_COLUMNS_ADDED record. @param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record @return number of added fields */ @@ -264,22 +255,6 @@ static inline unsigned rec_get_n_add_field(const byte*& header) return n_fields_add; } -/** Set the added field count in a REC_STATUS_COLUMNS_ADDED record. -@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record -@param[in] n_add number of added fields, minus 1 -@return record header before the number of added fields */ -static inline void rec_set_n_add_field(byte*& header, ulint n_add) -{ - ut_ad(n_add < REC_MAX_N_FIELDS); - - if (n_add < 0x80) { - *header-- = byte(n_add); - } else { - *header-- = byte(n_add) | 0x80; - *header-- = byte(n_add >> 7); - } -} - /** Format of a leaf-page ROW_FORMAT!=REDUNDANT record */ enum rec_leaf_format { /** Temporary file record */ @@ -299,6 +274,8 @@ This is a special case of rec_init_offsets() and rec_get_offsets_func(). @param[in] rec leaf-page record @param[in] index the index that the record belongs in @param[in] n_core number of core fields (index->n_core_fields) +@param[in] def_val default values for non-core fields, or + NULL to refer to index->fields[].col->def_val @param[in,out] offsets offsets, with valid rec_offs_n_fields(offsets) @param[in] format record format */ static inline @@ -308,6 +285,7 @@ rec_init_offsets_comp_ordinary( const dict_index_t* index, ulint* offsets, ulint n_core, + const dict_col_t::def_t*def_val, rec_leaf_format format) { ulint offs = 0; @@ -379,7 +357,19 @@ ordinary: ulint len; /* set default value flag */ - if (i >= n_fields) { + if (i < n_fields) { + } else if (def_val) { + const dict_col_t::def_t& d = def_val[i - n_core]; + if (!d.data) { + len = offs | REC_OFFS_SQL_NULL; + ut_ad(d.len == UNIV_SQL_NULL); + } else { + len = offs | REC_OFFS_DEFAULT; + any |= REC_OFFS_DEFAULT; + } + + goto resolved; + } else { ulint dlen; if (!index->instant_field_value(i, &dlen)) { len = offs | REC_OFFS_SQL_NULL; @@ -618,12 +608,14 @@ rec_init_offsets( ut_ad(leaf); rec_init_offsets_comp_ordinary(rec, index, offsets, index->n_core_fields, + NULL, REC_LEAF_COLUMNS_ADDED); return; case REC_STATUS_ORDINARY: ut_ad(leaf); rec_init_offsets_comp_ordinary(rec, index, offsets, index->n_core_fields, + NULL, REC_LEAF_ORDINARY); return; } @@ -1695,6 +1687,7 @@ rec_get_converted_size_temp( @param[in] index index of that the record belongs to @param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets) @param[in] n_core number of core fields (index->n_core_fields) +@param[in] def_val default values for non-core fields @param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */ void rec_init_offsets_temp( @@ -1702,6 +1695,7 @@ rec_init_offsets_temp( const dict_index_t* index, ulint* offsets, ulint n_core, + const dict_col_t::def_t*def_val, rec_comp_status_t status) { ut_ad(status == REC_STATUS_ORDINARY @@ -1710,7 +1704,7 @@ rec_init_offsets_temp( if it was emptied during an ALTER TABLE operation. */ ut_ad(index->n_core_fields == n_core || !index->is_instant()); ut_ad(index->n_core_fields >= n_core); - rec_init_offsets_comp_ordinary(rec, index, offsets, n_core, + rec_init_offsets_comp_ordinary(rec, index, offsets, n_core, def_val, status == REC_STATUS_COLUMNS_ADDED ? REC_LEAF_TEMP_COLUMNS_ADDED : REC_LEAF_TEMP); @@ -1729,7 +1723,8 @@ rec_init_offsets_temp( { ut_ad(!index->is_instant()); rec_init_offsets_comp_ordinary(rec, index, offsets, - index->n_core_fields, REC_LEAF_TEMP); + index->n_core_fields, NULL, + REC_LEAF_TEMP); } /** Convert a data tuple prefix to the temporary file format. diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 3ca93ba34b9..a351a1ae01b 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -805,7 +805,6 @@ DECLARE_THREAD(fts_parallel_tokenization)( merge_file = psort_info->merge_file; blob_heap = mem_heap_create(512); memset(&doc, 0, sizeof(doc)); - memset(&t_ctx, 0, sizeof(t_ctx)); memset(mycount, 0, FTS_NUM_AUX_INDEX * sizeof(int)); doc.charset = fts_index_get_charset( @@ -1687,12 +1686,10 @@ row_fts_merge_insert( ut_ad(aux_index->n_core_null_bytes == UT_BITS_IN_BYTES(aux_index->n_nullable)); - FlushObserver* observer; - observer = psort_info[0].psort_common->trx->flush_observer; - /* Create bulk load instance */ - ins_ctx.btr_bulk = UT_NEW_NOKEY(BtrBulk(aux_index, trx->id, observer)); - ins_ctx.btr_bulk->init(); + ins_ctx.btr_bulk = UT_NEW_NOKEY( + BtrBulk(aux_index, trx, psort_info[0].psort_common->trx + ->flush_observer)); /* Create tuple for insert */ ins_ctx.tuple = dtuple_create(heap, dict_index_get_n_fields(aux_index)); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 0357804f617..aab445cb197 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2015, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -113,19 +113,19 @@ struct row_index_t { struct row_import { row_import() UNIV_NOTHROW : - m_table(), - m_version(), - m_hostname(), - m_table_name(), - m_autoinc(), + m_table(NULL), + m_version(0), + m_hostname(NULL), + m_table_name(NULL), + m_autoinc(0), m_page_size(0, 0, false), - m_flags(), - m_n_cols(), - m_cols(), - m_col_names(), - m_n_indexes(), - m_indexes(), - m_missing(true) {} + m_flags(0), + m_n_cols(0), + m_cols(NULL), + m_col_names(NULL), + m_n_indexes(0), + m_indexes(NULL), + m_missing(true) { } ~row_import() UNIV_NOTHROW; @@ -1227,17 +1227,63 @@ row_import::match_schema( { /* Do some simple checks. */ - if ((m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR) { + if (ulint mismatch = (m_table->flags ^ m_flags) + & ~DICT_TF_MASK_DATA_DIR) { + const char* msg; + if (mismatch & DICT_TF_MASK_ZIP_SSIZE) { + if ((m_table->flags & DICT_TF_MASK_ZIP_SSIZE) + && (m_flags & DICT_TF_MASK_ZIP_SSIZE)) { + switch (m_flags & DICT_TF_MASK_ZIP_SSIZE) { + case 0U << DICT_TF_POS_ZIP_SSIZE: + goto uncompressed; + case 1U << DICT_TF_POS_ZIP_SSIZE: + msg = "ROW_FORMAT=COMPRESSED" + " KEY_BLOCK_SIZE=1"; + break; + case 2U << DICT_TF_POS_ZIP_SSIZE: + msg = "ROW_FORMAT=COMPRESSED" + " KEY_BLOCK_SIZE=2"; + break; + case 3U << DICT_TF_POS_ZIP_SSIZE: + msg = "ROW_FORMAT=COMPRESSED" + " KEY_BLOCK_SIZE=4"; + break; + case 4U << DICT_TF_POS_ZIP_SSIZE: + msg = "ROW_FORMAT=COMPRESSED" + " KEY_BLOCK_SIZE=8"; + break; + case 5U << DICT_TF_POS_ZIP_SSIZE: + msg = "ROW_FORMAT=COMPRESSED" + " KEY_BLOCK_SIZE=16"; + break; + default: + msg = "strange KEY_BLOCK_SIZE"; + } + } else if (m_flags & DICT_TF_MASK_ZIP_SSIZE) { + msg = "ROW_FORMAT=COMPRESSED"; + } else { + goto uncompressed; + } + } else { +uncompressed: + msg = (m_flags & DICT_TF_MASK_ATOMIC_BLOBS) + ? "ROW_FORMAT=DYNAMIC" + : (m_flags & DICT_TF_MASK_COMPACT) + ? "ROW_FORMAT=COMPACT" + : "ROW_FORMAT=REDUNDANT"; + } + ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, "Table flags don't match, server table has 0x%x" - " and the meta-data file has 0x" ULINTPFx, - m_table->flags, m_flags); + " and the meta-data file has 0x" ULINTPFx ";" + " .cfg file uses %s", + m_table->flags, m_flags, msg); return(DB_ERROR); } else if (m_table->n_cols != m_n_cols) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Number of columns don't match, table has %u" - " columns but the tablespace meta-data file has " + "Number of columns don't match, table has %u " + "columns but the tablespace meta-data file has " ULINTPF " columns", m_table->n_cols, m_n_cols); @@ -1686,7 +1732,6 @@ PageConverter::update_records( while (!m_rec_iter.end()) { rec_t* rec = m_rec_iter.current(); - ibool deleted = rec_get_deleted_flag(rec, comp); /* For the clustered index we have to adjust the BLOB @@ -2359,8 +2404,6 @@ row_import_cfg_read_index_fields( dict_field_t* field = index->m_fields; - memset(field, 0x0, sizeof(*field) * n_fields); - for (ulint i = 0; i < n_fields; ++i, ++field) { byte* ptr = row; @@ -2378,6 +2421,8 @@ row_import_cfg_read_index_fields( return(DB_IO_ERROR); } + new (field) dict_field_t(); + field->prefix_len = mach_read_from_4(ptr); ptr += sizeof(ib_uint32_t); @@ -3787,8 +3832,6 @@ row_import_for_mysql( row_import cfg; - memset(&cfg, 0x0, sizeof(cfg)); - err = row_import_read_cfg(table, trx->mysql_thd, cfg); /* Check if the table column definitions match the contents diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 37ae828d09d..c6ac98f1082 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1660,7 +1660,8 @@ row_ins_check_foreign_constraint( if (check_table == NULL || !check_table->is_readable() - || check_index == NULL) { + || check_index == NULL + || check_table->space->is_being_truncated) { if (!srv_read_only_mode && check_ref) { FILE* ef = dict_foreign_err_file; diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index db33910c6f2..a6e35744446 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -227,6 +227,8 @@ struct row_log_t { table could be emptied, so that table->is_instant() no longer holds, but all log records must be in the "instant" format. */ unsigned n_core_fields; + /** the default values of non-core fields when the operation started */ + dict_col_t::def_t* non_core_fields; bool allow_not_null; /*!< Whether the alter ignore is being used or if the sql mode is non-strict mode; if not, NULL values will not be converted to @@ -243,6 +245,14 @@ struct row_log_t { ut_ad(n_core_fields <= index->n_fields); return n_core_fields != index->n_fields; } + + const byte* instant_field_value(ulint n, ulint* len) const + { + ut_ad(n >= n_core_fields); + const dict_col_t::def_t& d= non_core_fields[n - n_core_fields]; + *len = d.len; + return static_cast<const byte*>(d.data); + } }; /** Create the file or online log if it does not exist. @@ -935,15 +945,16 @@ row_log_table_low( ulint mrec_size; ulint avail_size; const dict_index_t* new_index; + row_log_t* log = index->online_log; - new_index = dict_table_get_first_index(index->online_log->table); + new_index = dict_table_get_first_index(log->table); ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(new_index)); ut_ad(!dict_index_is_online_ddl(new_index)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); - ut_ad(rec_offs_size(offsets) <= sizeof index->online_log->tail.buf); + ut_ad(rec_offs_size(offsets) <= sizeof log->tail.buf); ut_ad(rw_lock_own_flagged( &index->lock, RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); @@ -970,7 +981,7 @@ row_log_table_low( if (index->online_status != ONLINE_INDEX_CREATION || (index->type & DICT_CORRUPT) || index->table->corrupted - || index->online_log->error != DB_SUCCESS) { + || log->error != DB_SUCCESS) { return; } @@ -987,14 +998,32 @@ row_log_table_low( const ulint omit_size = REC_N_NEW_EXTRA_BYTES; const ulint rec_extra_size = rec_offs_extra_size(offsets) - omit_size; - const bool is_instant = index->online_log->is_instant(index); + const bool is_instant = log->is_instant(index); extra_size = rec_extra_size + is_instant; + unsigned fake_extra_size = 0; + byte fake_extra_buf[2]; + if (is_instant && UNIV_UNLIKELY(!index->is_instant())) { + /* The source table was emptied after ALTER TABLE + started, and it was converted to non-instant format. + Because row_log_table_apply_op() expects to find + all records to be logged in the same way, we will + be unable to copy the rec_extra_size bytes from the + record header, but must convert them here. */ + unsigned n_add = index->n_fields - 1 - log->n_core_fields; + fake_extra_size = rec_get_n_add_field_len(n_add); + ut_ad(fake_extra_size == 1 || fake_extra_size == 2); + extra_size += fake_extra_size; + byte* fake_extra = fake_extra_buf + fake_extra_size - 1; + rec_set_n_add_field(fake_extra, n_add); + ut_ad(fake_extra + 1 == fake_extra_buf); + } + mrec_size = ROW_LOG_HEADER_SIZE + (extra_size >= 0x80) + rec_offs_size(offsets) - omit_size - + is_instant; + + is_instant + fake_extra_size; - if (insert || index->online_log->same_pk) { + if (insert || log->same_pk) { ut_ad(!old_pk); old_pk_extra_size = old_pk_size = 0; } else { @@ -1012,8 +1041,7 @@ row_log_table_low( mrec_size += 1/*old_pk_extra_size*/ + old_pk_size; } - if (byte* b = row_log_table_open(index->online_log, - mrec_size, &avail_size)) { + if (byte* b = row_log_table_open(log, mrec_size, &avail_size)) { if (insert) { *b++ = ROW_T_INSERT; } else { @@ -1038,20 +1066,23 @@ row_log_table_low( } if (is_instant) { - *b++ = rec_get_status(rec); + *b++ = fake_extra_size + ? REC_STATUS_COLUMNS_ADDED + : rec_get_status(rec); } else { ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY); } memcpy(b, rec - rec_extra_size - omit_size, rec_extra_size); b += rec_extra_size; + memcpy(b, fake_extra_buf, fake_extra_size); + b += fake_extra_size; ulint len; ulint trx_id_offs = rec_get_nth_field_offs( offsets, index->n_uniq, &len); ut_ad(len == DATA_TRX_ID_LEN); memcpy(b, rec, rec_offs_data_size(offsets)); - if (trx_read_trx_id(b + trx_id_offs) - < index->online_log->min_trx) { + if (trx_read_trx_id(b + trx_id_offs) < log->min_trx) { memcpy(b + trx_id_offs, reset_trx_id, sizeof reset_trx_id); } @@ -1133,7 +1164,6 @@ row_log_table_get_pk_col( field = rec_get_nth_field(rec, offsets, i, &len); if (len == UNIV_SQL_NULL) { - if (!log->allow_not_null) { return(DB_INVALID_NULL); } @@ -1142,6 +1172,9 @@ row_log_table_get_pk_col( field = static_cast<const byte*>( log->defaults->fields[n_default_cols].data); + if (!field) { + return(DB_INVALID_NULL); + } len = log->defaults->fields[i - DATA_N_SYS_COLS].len; } @@ -1576,7 +1609,7 @@ blob_done: } else { data = rec_get_nth_field(mrec, offsets, i, &len); if (len == UNIV_SQL_DEFAULT) { - data = index->instant_field_value(i, &len); + data = log->instant_field_value(i, &len); } dfield_set_data(dfield, data, len); } @@ -2416,7 +2449,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, - log->n_core_fields, + log->n_core_fields, log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -2497,6 +2530,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, log->n_core_fields, + log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -2598,6 +2632,7 @@ row_log_table_apply_op( rec_offs_set_n_fields(offsets, dup->index->n_fields); rec_init_offsets_temp(mrec, dup->index, offsets, log->n_core_fields, + log->non_core_fields, is_instant ? static_cast<rec_comp_status_t>( *(mrec - extra_size)) @@ -3174,6 +3209,18 @@ row_log_allocate( log->old_table = old_table; log->n_rows = 0; + if (table && index->is_instant()) { + const unsigned n = log->n_core_fields; + log->non_core_fields = UT_NEW_ARRAY_NOKEY( + dict_col_t::def_t, index->n_fields - n); + for (unsigned i = n; i < index->n_fields; i++) { + log->non_core_fields[i - n] + = index->fields[i].col->def_val; + } + } else { + log->non_core_fields = NULL; + } + dict_index_set_online_status(index, ONLINE_INDEX_CREATION); index->online_log = log; @@ -3206,6 +3253,7 @@ row_log_free( MONITOR_ATOMIC_DEC(MONITOR_ONLINE_CREATE_INDEX); UT_DELETE(log->blobs); + UT_DELETE_ARRAY(log->non_core_fields); row_log_block_free(log->tail); row_log_block_free(log->head); row_merge_file_destroy_low(log->fd); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index be3c081562e..ba8a7044baa 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2528,17 +2528,16 @@ write_buffers: if (clust_btr_bulk == NULL) { clust_btr_bulk = UT_NEW_NOKEY( BtrBulk(index[i], - trx->id, - observer)); - - clust_btr_bulk->init(); + trx, + observer/**/)); } else { clust_btr_bulk->latch(); } err = row_merge_insert_index_tuples( index[i], old_table, - OS_FILE_CLOSED, NULL, buf, clust_btr_bulk, + OS_FILE_CLOSED, NULL, buf, + clust_btr_bulk, table_total_rows, curr_progress, pct_cost, @@ -2643,13 +2642,13 @@ write_buffers: trx->error_key_num = i; goto all_done;); - BtrBulk btr_bulk(index[i], trx->id, + BtrBulk btr_bulk(index[i], trx, observer); - btr_bulk.init(); err = row_merge_insert_index_tuples( index[i], old_table, - OS_FILE_CLOSED, NULL, buf, &btr_bulk, + OS_FILE_CLOSED, NULL, buf, + &btr_bulk, table_total_rows, curr_progress, pct_cost, @@ -4673,11 +4672,15 @@ row_merge_build_indexes( we use bulk load to create all types of indexes except spatial index, for which redo logging is enabled. If we create only spatial indexes, we don't need to flush dirty pages at all. */ - bool need_flush_observer = (old_table != new_table); + bool need_flush_observer = bool(innodb_log_optimize_ddl); - for (i = 0; i < n_indexes; i++) { - if (!dict_index_is_spatial(indexes[i])) { - need_flush_observer = true; + if (need_flush_observer) { + need_flush_observer = old_table != new_table; + + for (i = 0; i < n_indexes; i++) { + if (!dict_index_is_spatial(indexes[i])) { + need_flush_observer = true; + } } } @@ -4921,9 +4924,8 @@ wait_again: os_thread_sleep(20000000);); /* 20 sec */ if (error == DB_SUCCESS) { - BtrBulk btr_bulk(sort_idx, trx->id, + BtrBulk btr_bulk(sort_idx, trx, flush_observer); - btr_bulk.init(); pct_cost = (COST_BUILD_INDEX_STATIC + (total_dynamic_cost * merge_files[i].offset / @@ -4976,14 +4978,16 @@ wait_again: ut_ad(sort_idx->online_status == ONLINE_INDEX_COMPLETE); } else { - ut_ad(need_flush_observer); + if (flush_observer) { + flush_observer->flush(); + row_merge_write_redo(indexes[i]); + } + if (global_system_variables.log_warnings > 2) { sql_print_information( "InnoDB: Online DDL : Applying" " log to index"); } - flush_observer->flush(); - row_merge_write_redo(indexes[i]); DEBUG_SYNC_C("row_log_apply_before"); error = row_log_apply(trx, sort_idx, table, stage); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 49ac2638ef8..a3c3d0eaaa6 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -72,6 +72,13 @@ Created 9/17/2000 Heikki Tuuri #include <deque> #include <vector> +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#include "wsrep.h" +#include "log.h" +#include "wsrep_mysqld.h" +#endif + /** Provide optional 4.x backwards compatibility for 5.0 and above */ ibool row_rollback_on_timeout = FALSE; @@ -1568,7 +1575,7 @@ error_exit: memcpy(prebuilt->row_id, node->sys_buf, DATA_ROW_ID_LEN); } - dict_stats_update_if_needed(table); + dict_stats_update_if_needed(table, trx->mysql_thd); trx->op_info = ""; if (blob_heap != NULL) { @@ -1952,7 +1959,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) } if (update_statistics) { - dict_stats_update_if_needed(prebuilt->table); + dict_stats_update_if_needed(prebuilt->table, trx->mysql_thd); } else { /* Always update the table modification counter. */ prebuilt->table->stat_modified_counter++; @@ -2195,7 +2202,7 @@ static dberr_t row_update_vers_insert(que_thr_t* thr, upd_node_t* node) case DB_SUCCESS: srv_stats.n_rows_inserted.inc( static_cast<size_t>(trx->id)); - dict_stats_update_if_needed(table); + dict_stats_update_if_needed(table, trx->mysql_thd); goto exit; } } @@ -2288,7 +2295,8 @@ row_update_cascade_for_mysql( } if (stats) { - dict_stats_update_if_needed(node->table); + dict_stats_update_if_needed(node->table, + trx->mysql_thd); } else { /* Always update the table modification counter. */ diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 79ce3057cd7..e2bbb5a3d5e 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1156,9 +1156,9 @@ row_purge_record_func( /*==================*/ purge_node_t* node, /*!< in: row purge node */ trx_undo_rec_t* undo_rec, /*!< in: record to purge */ -#ifdef UNIV_DEBUG +#if defined UNIV_DEBUG || defined WITH_WSREP const que_thr_t*thr, /*!< in: query thread */ -#endif /* UNIV_DEBUG */ +#endif /* UNIV_DEBUG || WITH_WSREP */ bool updated_extern) /*!< in: whether external columns were updated */ { @@ -1179,7 +1179,9 @@ row_purge_record_func( if (purged) { if (node->table->stat_initialized && srv_stats_include_delete_marked) { - dict_stats_update_if_needed(node->table); + dict_stats_update_if_needed( + node->table, + thr->graph->trx->mysql_thd); } MONITOR_INC(MONITOR_N_DEL_ROW_PURGE); } @@ -1214,13 +1216,13 @@ row_purge_record_func( return(purged); } -#ifdef UNIV_DEBUG +#if defined UNIV_DEBUG || defined WITH_WSREP # define row_purge_record(node,undo_rec,thr,updated_extern) \ row_purge_record_func(node,undo_rec,thr,updated_extern) -#else /* UNIV_DEBUG */ +#else /* UNIV_DEBUG || WITH_WSREP */ # define row_purge_record(node,undo_rec,thr,updated_extern) \ row_purge_record_func(node,undo_rec,updated_extern) -#endif /* UNIV_DEBUG */ +#endif /* UNIV_DEBUG || WITH_WSREP */ /***********************************************************//** Fetches an undo log record and does the purge for the recorded operation. diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index b68efbfa7be..c6a463c584b 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4973,6 +4973,13 @@ wrong_offs: if (!rec_get_deleted_flag(rec, comp)) { goto no_gap_lock; } + + /* At most one transaction can be active + for temporary table. */ + if (clust_index->table->is_temporary()) { + goto no_gap_lock; + } + if (index == clust_index) { trx_id_t trx_id = row_get_rec_trx_id( rec, index, offsets); diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index abd037e4a49..65170a10f57 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2013, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -1181,6 +1181,11 @@ row_truncate_complete( { bool is_file_per_table = dict_table_is_file_per_table(table); + /* Add the table back to FTS optimize background thread. */ + if (table->fts) { + fts_optimize_add_table(table); + } + row_mysql_unlock_data_dictionary(trx); DEBUG_SYNC_C("ib_trunc_table_trunc_completing"); @@ -1507,6 +1512,9 @@ row_truncate_update_system_tables( /* Reset the Doc ID in cache to 0 */ if (has_internal_doc_id && table->fts->cache != NULL) { + DBUG_EXECUTE_IF("ib_trunc_sleep_before_fts_cache_clear", + os_thread_sleep(10000000);); + table->fts->fts_status |= TABLE_DICT_LOCKED; fts_update_next_doc_id(trx, table, NULL, 0); fts_cache_clear(table->fts->cache); @@ -1754,6 +1762,10 @@ row_truncate_table_for_mysql( } if (!table->is_temporary()) { + if (table->fts) { + fts_optimize_remove_table(table); + } + trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index cbcb4eb8d1d..2067e957f3c 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -273,8 +273,6 @@ row_undo_ins_remove_sec_low( enum row_search_result search_result; const bool modify_leaf = mode == BTR_MODIFY_LEAF; - memset(&pcur, 0, sizeof(pcur)); - row_mtr_start(&mtr, index, !modify_leaf); if (modify_leaf) { @@ -631,7 +629,8 @@ row_undo_ins( already be holding dict_sys->mutex, which would be acquired when updating statistics. */ if (!dict_locked) { - dict_stats_update_if_needed(node->table); + dict_stats_update_if_needed( + node->table, node->trx->mysql_thd); } } } diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 64d771d7d94..90bce6c8be6 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1351,7 +1351,8 @@ rollback_clust: already be holding dict_sys->mutex, which would be acquired when updating statistics. */ if (update_statistics && !dict_locked) { - dict_stats_update_if_needed(node->table); + dict_stats_update_if_needed( + node->table, node->trx->mysql_thd); } else { node->table->stat_modified_counter++; } diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 1008e2d13fa..187fa2a0929 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -126,6 +126,8 @@ row_vers_impl_x_locked_low( DBUG_RETURN(0); } + ut_ad(!clust_index->table->is_temporary()); + trx_t* trx; if (trx_id == caller_trx->id) { diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index ab4814f3177..d5b0537c095 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -1042,86 +1042,52 @@ rw_lock_own( return(false); } -/** For collecting the debug information for a thread's rw-lock */ -typedef std::vector<rw_lock_debug_t*> Infos; - -/** Get the thread debug info -@param[in] infos The rw-lock mode owned by the threads -@param[in] lock rw-lock to check -@return the thread debug info or NULL if not found */ -void -rw_lock_get_debug_info(const rw_lock_t* lock, Infos* infos) -{ - rw_lock_debug_t* info = NULL; - - ut_ad(rw_lock_validate(lock)); - - rw_lock_debug_mutex_enter(); - - for (info = UT_LIST_GET_FIRST(lock->debug_list); - info != NULL; - info = UT_LIST_GET_NEXT(list, info)) { - - if (os_thread_eq(info->thread_id, os_thread_get_curr_id())) { - - infos->push_back(info); - } - } - - rw_lock_debug_mutex_exit(); -} - /** Checks if the thread has locked the rw-lock in the specified mode, with the pass value == 0. @param[in] lock rw-lock @param[in] flags specify lock types with OR of the rw_lock_flag_t values @return true if locked */ -bool -rw_lock_own_flagged( - const rw_lock_t* lock, - rw_lock_flags_t flags) +bool rw_lock_own_flagged(const rw_lock_t* lock, rw_lock_flags_t flags) { - Infos infos; - - rw_lock_get_debug_info(lock, &infos); - - Infos::const_iterator end = infos.end(); - - for (Infos::const_iterator it = infos.begin(); it != end; ++it) { + ut_ad(rw_lock_validate(lock)); - const rw_lock_debug_t* info = *it; + rw_lock_debug_mutex_enter(); - if (info->pass) { + for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list); + info != NULL; + info = UT_LIST_GET_NEXT(list, info)) { + if (!os_thread_eq(info->thread_id, os_thread_get_curr_id()) + || info->pass) { continue; } - ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id())); - switch (info->lock_type) { case RW_LOCK_S: - - if (flags & RW_LOCK_FLAG_S) { - return(true); + if (!(flags & RW_LOCK_FLAG_S)) { + continue; } break; case RW_LOCK_X: - - if (flags & RW_LOCK_FLAG_X) { - return(true); + if (!(flags & RW_LOCK_FLAG_X)) { + continue; } break; case RW_LOCK_SX: - - if (flags & RW_LOCK_FLAG_SX) { - return(true); + if (!(flags & RW_LOCK_FLAG_SX)) { + continue; } + break; } + + rw_lock_debug_mutex_exit(); + return true; } - return(false); + rw_lock_debug_mutex_exit(); + return false; } /***************************************************************//** @@ -1222,28 +1188,31 @@ rw_lock_t::locked_from() const the same thread can call X lock recursively. */ std::ostringstream msg; - Infos infos; + bool written = false; - rw_lock_get_debug_info(this, &infos); + ut_ad(rw_lock_validate(this)); - ulint i = 0; - Infos::const_iterator end = infos.end(); - - for (Infos::const_iterator it = infos.begin(); it != end; ++it, ++i) { - - const rw_lock_debug_t* info = *it; + rw_lock_debug_mutex_enter(); - ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id())); + for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list); + info != NULL; + info = UT_LIST_GET_NEXT(list, info)) { + if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())) { + continue; + } - if (i > 0) { + if (written) { msg << ", "; } + written = true; + msg << info->file_name << ":" << info->line; } - return(msg.str()); + rw_lock_debug_mutex_exit(); + return(msg.str()); } /** Print the rw-lock information. diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 81ad85dca7d..0e56af81ed4 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -545,9 +545,7 @@ trx_rseg_array_init() *trx_sys.recovered_binlog_filename = '\0'; trx_sys.recovered_binlog_offset = 0; #ifdef WITH_WSREP - memset(&trx_sys.recovered_wsrep_xid, 0, - sizeof trx_sys.recovered_wsrep_xid); - trx_sys.recovered_wsrep_xid.formatID = -1; + trx_sys.recovered_wsrep_xid.null(); #endif for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) { diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index c13ccdf53ed..30c19669cee 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -118,8 +118,6 @@ trx_init( /*=====*/ trx_t* trx) { - trx->id = 0; - trx->no = TRX_ID_MAX; trx->state = TRX_STATE_NOT_STARTED; @@ -197,11 +195,7 @@ struct TrxFactory { the constructors of the trx_t members. */ new(&trx->mod_tables) trx_mod_tables_t(); - new(&trx->lock.rec_pool) lock_pool_t(); - - new(&trx->lock.table_pool) lock_pool_t(); - - new(&trx->lock.table_locks) lock_pool_t(); + new(&trx->lock.table_locks) lock_list(); new(&trx->read_view) ReadView(); @@ -225,8 +219,6 @@ struct TrxFactory { &trx_named_savept_t::trx_savepoints); mutex_create(LATCH_ID_TRX, &trx->mutex); - - lock_trx_alloc_locks(trx); } /** Release resources held by the transaction object. @@ -256,27 +248,7 @@ struct TrxFactory { ut_ad(!trx->read_view.is_open()); - if (!trx->lock.rec_pool.empty()) { - - /* See lock_trx_alloc_locks() why we only free - the first element. */ - - ut_free(trx->lock.rec_pool[0]); - } - - if (!trx->lock.table_pool.empty()) { - - /* See lock_trx_alloc_locks() why we only free - the first element. */ - - ut_free(trx->lock.table_pool[0]); - } - - trx->lock.rec_pool.~lock_pool_t(); - - trx->lock.table_pool.~lock_pool_t(); - - trx->lock.table_locks.~lock_pool_t(); + trx->lock.table_locks.~lock_list(); trx->read_view.~ReadView(); } @@ -412,7 +384,12 @@ trx_t *trx_create() /* Should have been either just initialized or .clear()ed by trx_free(). */ - ut_a(trx->mod_tables.size() == 0); + ut_ad(trx->mod_tables.empty()); + ut_ad(trx->lock.table_locks.empty()); + ut_ad(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); + ut_ad(trx->lock.n_rec_locks == 0); + ut_ad(trx->lock.table_cached == 0); + ut_ad(trx->lock.rec_cached == 0); #ifdef WITH_WSREP trx->wsrep_event = NULL; @@ -955,8 +932,7 @@ trx_start_low( } #ifdef WITH_WSREP - memset(trx->xid, 0, sizeof(xid_t)); - trx->xid->formatID = -1; + trx->xid->null(); #endif /* WITH_WSREP */ /* The initial value for trx->no: TRX_ID_MAX is used in @@ -994,8 +970,6 @@ trx_start_low( trx_sys.register_rw(trx); } else { - trx->id = 0; - if (!trx_is_autocommit_non_locking(trx)) { /* If this is a read-only transaction that is writing @@ -1251,9 +1225,6 @@ trx_update_mod_tables_timestamp( /*============================*/ trx_t* trx) /*!< in: transaction */ { - - ut_ad(trx->id != 0); - /* consider using trx->start_time if calling time() is too expensive here */ time_t now = ut_time(); @@ -1326,7 +1297,10 @@ trx_commit_in_memory( trx_sys.deregister_rw(trx); } + /* trx->id will be cleared in lock_trx_release_locks(trx). */ + ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg || trx->id); lock_trx_release_locks(trx); + ut_ad(trx->id == 0); /* Remove the transaction from the list of active transactions now that it no longer holds any user locks. */ diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt index 5a7d4699386..c21eaf70536 100644 --- a/storage/mroonga/CMakeLists.txt +++ b/storage/mroonga/CMakeLists.txt @@ -361,7 +361,6 @@ else() MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-unused-parameter") MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-strict-aliasing") MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-deprecated") - MY_CHECK_AND_SET_COMPILER_FLAG("-fno-implicit-templates") if(("${MYSQL_VARIANT}" STREQUAL "MariaDB") OR ("${MYSQL_VARIANT}" STREQUAL "MySQL" AND ${MYSQL_VERSION} VERSION_LESS "5.7.0")) diff --git a/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp b/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp index b2e0e0444b8..9c56997d6d8 100644 --- a/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp +++ b/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp @@ -624,9 +624,10 @@ namespace mrn { long long int long_long_value; mrn_byte_order_network_to_host(&long_long_value, grn_key, grn_key_size); int max_bit = (grn_key_size * 8 - 1); - *((long long int *)mysql_key) = + long_long_value = long_long_value ^ (((long_long_value ^ (1LL << max_bit)) >> max_bit) | (1LL << max_bit)); + memcpy(mysql_key, &long_long_value, sizeof(long_long_value)); DBUG_VOID_RETURN; } diff --git a/storage/mroonga/vendor/groonga/config.h.cmake b/storage/mroonga/vendor/groonga/config.h.cmake index bfd0cbdc012..ec67c5eea23 100644 --- a/storage/mroonga/vendor/groonga/config.h.cmake +++ b/storage/mroonga/vendor/groonga/config.h.cmake @@ -107,6 +107,7 @@ #cmakedefine HAVE_SIGNAL_H #cmakedefine HAVE_SYS_MMAN_H #cmakedefine HAVE_SYS_PARAM_H +#cmakedefine HAVE_SYS_POLL_H #cmakedefine HAVE_SYS_RESOURCE_H #cmakedefine HAVE_SYS_SELECT_H #cmakedefine HAVE_SYS_SOCKET_H diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c index 44378cfae25..a3d838c327f 100644 --- a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c @@ -562,7 +562,7 @@ inline static grn_ts_bool grn_ts_op_not_equal_float(grn_ts_float lhs, grn_ts_float rhs) { /* To suppress warnings, "lhs != rhs" is not used. */ - return (lhs < rhs) || (lhs > rhs); + return !grn_ts_op_equal_float(lhs, rhs); } /* grn_ts_op_not_equal_time() returns lhs != rhs. */ diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index a98615e5781..557daf616c2 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. Copyright (c) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify @@ -1329,10 +1329,14 @@ int ha_myisam::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) if (file->s->base.auto_key) update_auto_increment_key(¶m, file, 1); if (optimize_done) + { + mysql_mutex_lock(&share->intern_lock); error = update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT | (local_testflag & T_STATISTICS ? UPDATE_STAT : 0)); + mysql_mutex_unlock(&share->intern_lock); + } info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_CONST); if (rows != file->state->records && ! (param.testflag & T_VERY_SILENT)) diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 3a3bd6f08da..c638dcbe3e8 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4475,6 +4475,10 @@ int update_state_info(HA_CHECK *param, MI_INFO *info,uint update) int error; uint r_locks=share->r_locks,w_locks=share->w_locks; share->r_locks= share->w_locks= share->tot_locks= 0; + + DBUG_EXECUTE_IF("simulate_incorrect_share_wlock_value", + DEBUG_SYNC_C("after_share_wlock_set_to_0");); + error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK); share->r_locks=r_locks; share->w_locks=w_locks; diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index d2c74cf9980..b348429fd3c 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2018, MariaDB Corporation This program is free software; you can redistribute it and/or modify @@ -236,6 +236,10 @@ int mi_lock_database(MI_INFO *info, int lock_type) info->invalidator=info->s->invalidator; share->w_locks++; share->tot_locks++; + + DBUG_EXECUTE_IF("simulate_incorrect_share_wlock_value", + DEBUG_SYNC_C("after_share_wlock_increment");); + info->s->in_use= list_add(info->s->in_use, &info->in_use); break; default: diff --git a/storage/oqgraph/CMakeLists.txt b/storage/oqgraph/CMakeLists.txt index 613a44807c7..638ac00dc01 100644 --- a/storage/oqgraph/CMakeLists.txt +++ b/storage/oqgraph/CMakeLists.txt @@ -58,7 +58,6 @@ IF(MSVC) ELSE(MSVC) # Fix lp bug 1221555 with -fpermissive, so that errors in gcc 4.7 become warnings for the time being STRING(REPLACE "-fno-exceptions" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -fno-strict-aliasing -fpermissive") ENDIF(MSVC) diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt index d37f7e8bf0f..e56c5b1033e 100644 --- a/storage/rocksdb/CMakeLists.txt +++ b/storage/rocksdb/CMakeLists.txt @@ -241,7 +241,7 @@ IF (ZSTD_FOUND) SET(WITH_ZSTD ON) ENDIF() -IF(GIT_EXECUTABLE) +IF(GIT_EXECUTABLE AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/rocksdb/.git) EXECUTE_PROCESS( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rocksdb diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake index 8f01024be63..d854bdaa03a 100644 --- a/storage/rocksdb/build_rocksdb.cmake +++ b/storage/rocksdb/build_rocksdb.cmake @@ -33,7 +33,7 @@ endif() # Optional compression libraries. -foreach(compression_lib LZ4 BZIP2 ZSTD snappy) +foreach(compression_lib LZ4 BZIP2 zstd snappy) FIND_PACKAGE(${compression_lib} QUIET) SET(WITH_ROCKSDB_${compression_lib} AUTO CACHE STRING @@ -76,7 +76,7 @@ if(ZSTD_FOUND AND (NOT WITH_ROCKSDB_ZSTD STREQUAL "OFF")) if (ZSTD_VALID) add_definitions(-DZSTD) include_directories(${ZSTD_INCLUDE_DIR}) - list(APPEND THIRDPARTY_LIBS ${ZSTD_LIBRARY}) + list(APPEND THIRDPARTY_LIBS ${ZSTD_LIBRARIES}) endif() endif() @@ -377,6 +377,30 @@ FOREACH(s ${ROCKSDB_SOURCES}) list(APPEND SOURCES ${ROCKSDB_SOURCE_DIR}/${s}) ENDFOREACH() +if(MSVC) + add_definitions(-DHAVE_SSE42 -DHAVE_PCLMUL) +else() + set(CMAKE_REQUIRED_FLAGS "-msse4.2 -mpclmul ${CXX11_FLAGS}") + + CHECK_CXX_SOURCE_COMPILES(" +#include <cstdint> +#include <nmmintrin.h> +#include <wmmintrin.h> +int main() { + volatile uint32_t x = _mm_crc32_u32(0, 0); + const auto a = _mm_set_epi64x(0, 0); + const auto b = _mm_set_epi64x(0, 0); + const auto c = _mm_clmulepi64_si128(a, b, 0x00); + auto d = _mm_cvtsi128_si64(c); +} +" HAVE_SSE42) + if(HAVE_SSE42) + set_source_files_properties(${ROCKSDB_SOURCE_DIR}/util/crc32c.cc + PROPERTIES COMPILE_FLAGS "-DHAVE_SSE42 -DHAVE_PCLMUL -msse4.2 -mpclmul") + endif() + unset(CMAKE_REQUIRED_FLAGS) +endif() + IF(CMAKE_VERSION VERSION_GREATER "2.8.10") STRING(TIMESTAMP GIT_DATE_TIME "%Y-%m-%d %H:%M:%S") ENDIF() @@ -390,4 +414,3 @@ target_link_libraries(rocksdblib ${THIRDPARTY_LIBS} ${SYSTEM_LIBS}) IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set_target_properties(rocksdblib PROPERTIES COMPILE_FLAGS "-fPIC -fno-builtin-memcmp -frtti") endif() - diff --git a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug-master.opt b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug-master.opt index 83ed8522e72..06917181cd6 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug-master.opt +++ b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug-master.opt @@ -1 +1 @@ ---binlog-format=row +--binlog-format=row --rocksdb-flush-log-at-trx-commit=1 diff --git a/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_errors.test b/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_errors.test index 1e349d0ff18..3f085269365 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_errors.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_errors.test @@ -60,6 +60,13 @@ SELECT * FROM t1; --source include/wait_until_count_sessions.inc +# Note: in MariaDB, session count will be decremented *before* +# myrocks::rocksdb_close_connection is called. This causes a race condition: +# we may grep the error log before bulk load is finalized. +# To prevent that, do a soft restart of the server (I wasnt able to find +# any other reliable way) +--source include/restart_mysqld_with_option.inc + --let SEARCH_FILE=$LOG2 --let SEARCH_PATTERN=RocksDB: Error [0-9]+ finalizing last SST file while disconnecting --source include/search_pattern_in_file.inc diff --git a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def index 3b9726986f0..d0cd1ce6407 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def +++ b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def @@ -76,4 +76,4 @@ information_schema: MDEV-14372: unstable testcase ## mysqlbinlog_gtid_skip_empty_trans_rocksdb : MariaRocks: requires GTIDs - +autoinc_debug: Fails with wrong results diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index f611d66496e..86332a741c6 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -3445,7 +3445,7 @@ int ha_sphinx::create ( const char * name, TABLE * table_arg, HA_CREATE_INFO * ) if ( table_arg->s->keys!=1 || table_arg->key_info[0].user_defined_key_parts!=1 || - strcasecmp ( table_arg->key_info[0].key_part[0].field->field_name.str, table->field[2]->field_name.str ) ) + strcasecmp ( table_arg->key_info[0].key_part[0].field->field_name.str, table_arg->field[2]->field_name.str ) ) { my_snprintf ( sError, sizeof(sError), "%s: there must be an index on '%s' column", name, table_arg->field[2]->field_name.str ); diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake index e1da095fc00..3413339628f 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake @@ -3,17 +3,11 @@ # We use it in MySQL to merge mysys,dbug,vio etc into mysqlclient FUNCTION(TOKU_GET_DEPENDEND_OS_LIBS target result) SET(deps ${${target}_LIB_DEPENDS}) - IF(deps) - FOREACH(lib ${deps}) - # Filter out keywords for used for debug vs optimized builds - IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized") - GET_TARGET_PROPERTY(lib_location ${lib} LOCATION) - IF(NOT lib_location) - SET(ret ${ret} ${lib}) - ENDIF() - ENDIF() - ENDFOREACH() - ENDIF() + FOREACH(lib ${deps}) + IF(TARGET ${lib}) + SET(ret ${ret} ${lib}) + ENDIF() + ENDFOREACH() SET(${result} ${ret} PARENT_SCOPE) ENDFUNCTION(TOKU_GET_DEPENDEND_OS_LIBS) diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake index 50d35ee4906..0a5b86a430f 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake @@ -79,14 +79,6 @@ set_cflags_if_supported( ) ## set_cflags_if_supported_named("-Weffc++" -Weffcpp) -if (CMAKE_CXX_FLAGS MATCHES -fno-implicit-templates) - # must append this because mysql sets -fno-implicit-templates and we need to override it - check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_IMPLICIT_TEMPLATES) - if (HAVE_CXX_IMPLICIT_TEMPLATES) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fimplicit-templates") - endif () -endif() - ## Clang has stricter POD checks. So, only enable this warning on our other builds (Linux + GCC) if (NOT CMAKE_CXX_COMPILER_ID MATCHES Clang) set_cflags_if_supported( diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 612fdbab38c..9be1ce43aab 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -218,11 +218,11 @@ static size_t my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)), static size_t my_case_bin(CHARSET_INFO *cs __attribute__((unused)), - char *src __attribute__((unused)), - size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) + const char *src, size_t srclen, + char *dst, size_t dstlen) { + DBUG_ASSERT(srclen <= dstlen); + memcpy(dst, src, srclen); return srclen; } diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 1af182db9aa..f4f7d041239 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -10028,8 +10028,8 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_ctype_mb, my_caseup_str_mb, my_casedn_str_mb, - my_caseup_mb_varlen, /* UPPER() can reduce length: Turkish DOTLESS i -> I */ - my_casedn_mb, /* LOWER() does not change length, use simple version*/ + my_caseup_mb, /* UPPER() can reduce length: Turkish DOTLESS i -> I */ + my_casedn_mb, /* LOWER() does not change length */ my_snprintf_8bit, my_long10_to_str_8bit, my_longlong10_to_str_8bit, diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 3fd481664fb..1fd80445180 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -71,81 +71,8 @@ get_case_info_for_ch(CHARSET_INFO *cs, uint page, uint offs) /* - For character sets which don't change octet length in case conversion. -*/ -size_t my_caseup_mb(CHARSET_INFO * cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) -{ - register uint32 l; - register char *srcend= src + srclen; - register const uchar *map= cs->to_upper; - - DBUG_ASSERT(cs->caseup_multiply == 1); - DBUG_ASSERT(src == dst && srclen == dstlen); - DBUG_ASSERT(cs->mbmaxlen == 2); - - while (src < srcend) - { - if ((l=my_ismbchar(cs, src, srcend))) - { - MY_UNICASE_CHARACTER *ch; - if ((ch= get_case_info_for_ch(cs, (uchar) src[0], (uchar) src[1]))) - { - *src++= ch->toupper >> 8; - *src++= ch->toupper & 0xFF; - } - else - src+= l; - } - else - { - *src=(char) map[(uchar) *src]; - src++; - } - } - return srclen; -} - - -size_t my_casedn_mb(CHARSET_INFO * cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) -{ - register uint32 l; - register char *srcend= src + srclen; - register const uchar *map=cs->to_lower; - - DBUG_ASSERT(cs->casedn_multiply == 1); - DBUG_ASSERT(src == dst && srclen == dstlen); - DBUG_ASSERT(cs->mbmaxlen == 2); - - while (src < srcend) - { - if ((l= my_ismbchar(cs, src, srcend))) - { - MY_UNICASE_CHARACTER *ch; - if ((ch= get_case_info_for_ch(cs, (uchar) src[0], (uchar) src[1]))) - { - *src++= ch->tolower >> 8; - *src++= ch->tolower & 0xFF; - } - else - src+= l; - } - else - { - *src= (char) map[(uchar)*src]; - src++; - } - } - return srclen; -} - - -/* - Case folding functions for character set - where case conversion can change string octet length. + Case folding functions for CJK character set. + Case conversion can optionally reduce string octet length. For example, in EUCKR, _euckr 0xA9A5 == "LATIN LETTER DOTLESS I" (Turkish letter) is upper-cased to to @@ -153,13 +80,14 @@ size_t my_casedn_mb(CHARSET_INFO * cs, char *src, size_t srclen, Length is reduced in this example from two bytes to one byte. */ static size_t -my_casefold_mb_varlen(CHARSET_INFO *cs, - char *src, size_t srclen, - char *dst, size_t dstlen __attribute__((unused)), - const uchar *map, - size_t is_upper) +my_casefold_mb(CHARSET_INFO *cs, + const char *src, size_t srclen, + char *dst, size_t dstlen __attribute__((unused)), + const uchar *map, + size_t is_upper) { - char *srcend= src + srclen, *dst0= dst; + const char *srcend= src + srclen; + char *dst0= dst; DBUG_ASSERT(cs->mbmaxlen == 2); @@ -193,22 +121,22 @@ my_casefold_mb_varlen(CHARSET_INFO *cs, size_t -my_casedn_mb_varlen(CHARSET_INFO * cs, char *src, size_t srclen, +my_casedn_mb(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { DBUG_ASSERT(dstlen >= srclen * cs->casedn_multiply); DBUG_ASSERT(src != dst || cs->casedn_multiply == 1); - return my_casefold_mb_varlen(cs, src, srclen, dst, dstlen, cs->to_lower, 0); + return my_casefold_mb(cs, src, srclen, dst, dstlen, cs->to_lower, 0); } size_t -my_caseup_mb_varlen(CHARSET_INFO * cs, char *src, size_t srclen, - char *dst, size_t dstlen) +my_caseup_mb(CHARSET_INFO * cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { DBUG_ASSERT(dstlen >= srclen * cs->caseup_multiply); DBUG_ASSERT(src != dst || cs->caseup_multiply == 1); - return my_casefold_mb_varlen(cs, src, srclen, dst, dstlen, cs->to_upper, 1); + return my_casefold_mb(cs, src, srclen, dst, dstlen, cs->to_upper, 1); } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 314438bcdf9..518f6f9842f 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -236,28 +236,26 @@ size_t my_casedn_str_8bit(CHARSET_INFO * cs,char *str) } -size_t my_caseup_8bit(CHARSET_INFO * cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +size_t my_caseup_8bit(CHARSET_INFO * cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { - char *end= src + srclen; + const char *end= src + srclen; register const uchar *map= cs->to_upper; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); for ( ; src != end ; src++) - *src= (char) map[(uchar) *src]; + *dst++= (char) map[(uchar) *src]; return srclen; } -size_t my_casedn_8bit(CHARSET_INFO * cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +size_t my_casedn_8bit(CHARSET_INFO * cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { - char *end= src + srclen; + const char *end= src + srclen; register const uchar *map=cs->to_lower; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); for ( ; src != end ; src++) - *src= (char) map[(uchar) *src]; + *dst++= (char) map[(uchar) *src]; return srclen; } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 42eeb68c871..7596b7f2168 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1359,25 +1359,26 @@ my_tosort_utf16(MY_UNICASE_INFO *uni_plane, my_wc_t *wc) static size_t -my_caseup_utf16(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +my_caseup_utf16(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc; my_charset_conv_wc_mb wc_mb= cs->cset->wc_mb; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && (res= mb_wc(cs, &wc, (uchar *) src, (uchar *) srcend)) > 0) { my_toupper_utf16(uni_plane, &wc); - if (res != wc_mb(cs, wc, (uchar *) src, (uchar *) srcend)) + if (res != wc_mb(cs, wc, (uchar *) dst, (uchar *) dstend)) break; src+= res; + dst+= res; } return srclen; } @@ -1416,25 +1417,26 @@ my_hash_sort_utf16(CHARSET_INFO *cs, const uchar *s, size_t slen, static size_t -my_casedn_utf16(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +my_casedn_utf16(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc; my_charset_conv_wc_mb wc_mb= cs->cset->wc_mb; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && (res= mb_wc(cs, &wc, (uchar *) src, (uchar *) srcend)) > 0) { my_tolower_utf16(uni_plane, &wc); - if (res != wc_mb(cs, wc, (uchar *) src, (uchar *) srcend)) + if (res != wc_mb(cs, wc, (uchar *) dst, (uchar *) dstend)) break; src+= res; + dst+= res; } return srclen; } @@ -2231,23 +2233,24 @@ my_lengthsp_utf32(CHARSET_INFO *cs __attribute__((unused)), static size_t -my_caseup_utf32(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +my_caseup_utf32(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && (res= my_utf32_uni(cs, &wc, (uchar *)src, (uchar*) srcend)) > 0) { my_toupper_utf32(uni_plane, &wc); - if (res != my_uni_utf32(cs, wc, (uchar*) src, (uchar*) srcend)) + if (res != my_uni_utf32(cs, wc, (uchar*) dst, (uchar*) dstend)) break; src+= res; + dst+= res; } return srclen; } @@ -2287,22 +2290,23 @@ my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen, static size_t -my_casedn_utf32(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +my_casedn_utf32(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((res= my_utf32_uni(cs, &wc, (uchar*) src, (uchar*) srcend)) > 0) { my_tolower_utf32(uni_plane,&wc); - if (res != my_uni_utf32(cs, wc, (uchar*) src, (uchar*) srcend)) + if (res != my_uni_utf32(cs, wc, (uchar*) dst, (uchar*) dstend)) break; src+= res; + dst+= res; } return srclen; } @@ -3081,23 +3085,24 @@ my_tosort_ucs2(MY_UNICASE_INFO *uni_plane, my_wc_t *wc) *wc= page[*wc & 0xFF].sort; } -static size_t my_caseup_ucs2(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +static size_t my_caseup_ucs2(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && (res= my_ucs2_uni(cs, &wc, (uchar *)src, (uchar*) srcend)) > 0) { my_toupper_ucs2(uni_plane, &wc); - if (res != my_uni_ucs2(cs, wc, (uchar*) src, (uchar*) srcend)) + if (res != my_uni_ucs2(cs, wc, (uchar*) dst, (uchar*) dstend)) break; src+= res; + dst+= res; } return srclen; } @@ -3131,23 +3136,24 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen, my_hash_sort_ucs2_nopad(cs, s, lengthsp, nr1, nr2); } -static size_t my_casedn_ucs2(CHARSET_INFO *cs, char *src, size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) +static size_t my_casedn_ucs2(CHARSET_INFO *cs, const char *src, size_t srclen, + char *dst, size_t dstlen) { my_wc_t wc; int res; - char *srcend= src + srclen; + const char *srcend= src + srclen; + char *dstend= dst + dstlen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; - DBUG_ASSERT(src == dst && srclen == dstlen); + DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && (res= my_ucs2_uni(cs, &wc, (uchar*) src, (uchar*) srcend)) > 0) { my_tolower_ucs2(uni_plane, &wc); - if (res != my_uni_ucs2(cs, wc, (uchar*) src, (uchar*) srcend)) + if (res != my_uni_ucs2(cs, wc, (uchar*) dst, (uchar*) dstend)) break; src+= res; + dst+= res; } return srclen; } diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 4c553d15526..2da603687ef 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -67161,12 +67161,12 @@ get_case_info_for_ch(CHARSET_INFO *cs, uint plane, uint page, uint offs) */ static size_t my_casefold_ujis(CHARSET_INFO *cs, - char *src, size_t srclen, + const char *src, size_t srclen, char *dst, size_t dstlen __attribute__((unused)), const uchar * const map, size_t is_upper) { - char *srcend= src + srclen, *dst0= dst; + const char *srcend= src + srclen, *dst0= dst; while (src < srcend) { @@ -67208,7 +67208,7 @@ my_casefold_ujis(CHARSET_INFO *cs, LOWER() */ size_t -my_casedn_ujis(CHARSET_INFO * cs, char *src, size_t srclen, +my_casedn_ujis(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { DBUG_ASSERT(dstlen >= srclen * cs->casedn_multiply); @@ -67221,7 +67221,7 @@ my_casedn_ujis(CHARSET_INFO * cs, char *src, size_t srclen, UPPER() */ size_t -my_caseup_ujis(CHARSET_INFO * cs, char *src, size_t srclen, +my_caseup_ujis(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { DBUG_ASSERT(dstlen >= srclen * cs->caseup_multiply); diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index cd6ddaaa196..c525ee97b65 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -5140,12 +5140,13 @@ my_toupper_utf8mb3(MY_UNICASE_INFO *uni_plane, my_wc_t *wc) } -static size_t my_caseup_utf8(CHARSET_INFO *cs, char *src, size_t srclen, +static size_t my_caseup_utf8(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) { my_wc_t wc; int srcres, dstres; - char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst; + const char *srcend= src + srclen; + char *dstend= dst + dstlen, *dst0= dst; MY_UNICASE_INFO *uni_plane= cs->caseinfo; DBUG_ASSERT(src != dst || cs->caseup_multiply == 1); @@ -5218,12 +5219,13 @@ static size_t my_caseup_str_utf8(CHARSET_INFO *cs, char *src) } -static size_t my_casedn_utf8(CHARSET_INFO *cs, char *src, size_t srclen, +static size_t my_casedn_utf8(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) { my_wc_t wc; int srcres, dstres; - char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst; + const char *srcend= src + srclen; + char *dstend= dst + dstlen, *dst0= dst; MY_UNICASE_INFO *uni_plane= cs->caseinfo; DBUG_ASSERT(src != dst || cs->casedn_multiply == 1); @@ -7567,12 +7569,13 @@ my_toupper_utf8mb4(MY_UNICASE_INFO *uni_plane, my_wc_t *wc) static size_t -my_caseup_utf8mb4(CHARSET_INFO *cs, char *src, size_t srclen, +my_caseup_utf8mb4(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) { my_wc_t wc; int srcres, dstres; - char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst; + const char *srcend= src + srclen; + char *dstend= dst + dstlen, *dst0= dst; MY_UNICASE_INFO *uni_plane= cs->caseinfo; DBUG_ASSERT(src != dst || cs->caseup_multiply == 1); @@ -7662,12 +7665,13 @@ my_caseup_str_utf8mb4(CHARSET_INFO *cs, char *src) static size_t my_casedn_utf8mb4(CHARSET_INFO *cs, - char *src, size_t srclen, + const char *src, size_t srclen, char *dst, size_t dstlen) { my_wc_t wc; int srcres, dstres; - char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst; + const char *srcend= src + srclen; + char *dstend= dst + dstlen, *dst0= dst; MY_UNICASE_INFO *uni_plane= cs->caseinfo; DBUG_ASSERT(src != dst || cs->casedn_multiply == 1); diff --git a/strings/json_lib.c b/strings/json_lib.c index 57ac3eb15b6..139bd98742f 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1643,6 +1643,8 @@ int json_escape(CHARSET_INFO *str_cs, return -1; } } + else /* c_len == 0, an illegal symbol. */ + return -1; } return (int)(json - json_start); diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index ef9fa5c2a22..8d43b6db428 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -17,7 +17,6 @@ Description=MariaDB @VERSION@ database server Documentation=man:mysqld(8) Documentation=https://mariadb.com/kb/en/library/systemd/ After=network.target -After=syslog.target [Install] WantedBy=multi-user.target diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index 465a0d94c62..a2f5cff0828 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -22,7 +22,6 @@ Description=MariaDB @VERSION@ database server (multi-instance) Documentation=man:mysqld(8) Documentation=https://mariadb.com/kb/en/library/systemd/ After=network.target -After=syslog.target ConditionPathExists=@sysconf2dir@/my%I.cnf diff --git a/support-files/mysqld_multi.server.sh b/support-files/mysqld_multi.server.sh index 75908a5db9d..f00c6a56af1 100644 --- a/support-files/mysqld_multi.server.sh +++ b/support-files/mysqld_multi.server.sh @@ -14,8 +14,23 @@ # Version 1.0 # -basedir=/usr/local/mysql -bindir=/usr/local/mysql/bin +### BEGIN INIT INFO +# Provides: mysqld_multi +# Required-Start: $local_fs $network $remote_fs +# Should-Start: ypbind nscd ldap ntpd xntpd +# Required-Stop: $local_fs $network $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start and stop multiple mysql database server daemon instances +# Description: Controls multiple MariaDB database server daemon instances +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=mysqld_multi +DESC=mysqld_multi + +basedir=/usr +bindir=/usr/bin if test -x $bindir/mysqld_multi then diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index d5dc3becba8..61bfe9e5568 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -123,11 +123,9 @@ ELSE() FILE(APPEND "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf" "\n}\n") SET(COPYING_RTF "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf") ENDIF() -GET_TARGET_PROPERTY(WIXCA_LOCATION wixca LOCATION) SET(CPACK_WIX_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/CPackWixConfig.cmake) -GET_TARGET_PROPERTY(upgrade_wizard_location mysql_upgrade_wizard LOCATION) -IF(NOT upgrade_wizard_location) +IF(NOT TARGET mysql_upgrade_wizard) SET(EXTRA_WIX_PREPROCESSOR_FLAGS "-dHaveUpgradeWizard=0") ENDIF() IF(WITH_INNOBASE_STORAGE_ENGINE) @@ -145,7 +143,6 @@ IF(WITH_THIRD_PARTY) ENDIF() ENDIF() -GET_TARGET_PROPERTY(LIBMYSQL_LOCATION libmysql LOCATION) FOREACH(third_party ${WITH_THIRD_PARTY}) SET(third_party_install_plugin ${CMAKE_CURRENT_SOURCE_DIR}/${third_party}.cmake) IF(NOT EXISTS ${third_party_install_plugin}) @@ -169,10 +166,6 @@ ENDIF() IF(NOT CPACK_WIX_UI) SET(CPACK_WIX_UI "MyWixUI_Mondo") ENDIF() -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/create_msi.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/create_msi.cmake - @ONLY) - IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(WixWin64 " Win64='yes'") @@ -188,17 +181,69 @@ ENDIF() ADD_CUSTOM_TARGET( MSI - COMMAND ${CMAKE_COMMAND} - ${CONFIG_PARAM} - -P ${CMAKE_CURRENT_BINARY_DIR}/create_msi.cmake + COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} + -DCANDLE_EXECUTABLE="${CANDLE_EXECUTABLE}" + -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}" + -DCMAKE_FULL_VER="${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" + -DCMAKE_SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P} + -DCOPYING_RTF="${COPYING_RTF}" + -DCPACK_WIX_CONFIG="${CPACK_WIX_CONFIG}" + -DCPACK_WIX_INCLUDE="${CPACK_WIX_INCLUDE}" + -DCPACK_WIX_PACKAGE_BASE_NAME="${CPACK_WIX_PACKAGE_BASE_NAME}" + -DCPACK_WIX_PACKAGE_NAME="${CPACK_WIX_PACKAGE_NAME}" + -DCPACK_WIX_UPGRADE_CODE="${CPACK_WIX_UPGRADE_CODE}" + -DEXTRA_WIX_PREPROCESSOR_FLAGS="${EXTRA_WIX_PREPROCESSOR_FLAGS}" + -DLIGHT_EXECUTABLE="${LIGHT_EXECUTABLE}" + -DMAJOR_VERSION="${MAJOR_VERSION}" + -DMANUFACTURER="${MANUFACTURER}" + -DMINOR_VERSION="${MINOR_VERSION}" + -DPATCH_VERSION="${PATCH_VERSION}" + -DSIGNCODE="${SIGNCODE}" + -DSIGNTOOL_EXECUTABLE="${SIGNTOOL_EXECUTABLE}" + -DSIGNTOOL_PARAMETERS="${SIGNTOOL_PARAMETERS}" + -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" + -DTHIRD_PARTY_DOWNLOAD_LOCATION="${THIRD_PARTY_DOWNLOAD_LOCATION}" + -DTHIRD_PARTY_FEATURE_CONDITION="${THIRD_PARTY_FEATURE_CONDITION}" + -DTINY_VERSION="${TINY_VERSION}" + -DTOP_BINDIR="${CMAKE_BINARY_DIR}" + -DVERSION="${VERSION}" + -DWITH_THIRD_PARTY="${WITH_THIRD_PARTY}" + -DWIXCA_LOCATION="$<TARGET_FILE:wixca>" + -P ${CMAKE_CURRENT_SOURCE_DIR}/create_msi.cmake ) ADD_DEPENDENCIES(MSI wixca) ADD_CUSTOM_TARGET( MSI_ESSENTIALS - COMMAND ${CMAKE_COMMAND} -DESSENTIALS=1 - ${CONFIG_PARAM} - -P ${CMAKE_CURRENT_BINARY_DIR}/create_msi.cmake + COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -DESSENTIALS=1 + -DCANDLE_EXECUTABLE="${CANDLE_EXECUTABLE}" + -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}" + -DCMAKE_FULL_VER="${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" + -DCMAKE_SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P} + -DCOPYING_RTF="${COPYING_RTF}" + -DCPACK_WIX_CONFIG="${CPACK_WIX_CONFIG}" + -DCPACK_WIX_INCLUDE="${CPACK_WIX_INCLUDE}" + -DCPACK_WIX_PACKAGE_BASE_NAME="${CPACK_WIX_PACKAGE_BASE_NAME}" + -DCPACK_WIX_PACKAGE_NAME="${CPACK_WIX_PACKAGE_NAME}" + -DCPACK_WIX_UPGRADE_CODE="${CPACK_WIX_UPGRADE_CODE}" + -DEXTRA_WIX_PREPROCESSOR_FLAGS="${EXTRA_WIX_PREPROCESSOR_FLAGS}" + -DLIGHT_EXECUTABLE="${LIGHT_EXECUTABLE}" + -DMAJOR_VERSION="${MAJOR_VERSION}" + -DMANUFACTURER="${MANUFACTURER}" + -DMINOR_VERSION="${MINOR_VERSION}" + -DPATCH_VERSION="${PATCH_VERSION}" + -DSIGNCODE="${SIGNCODE}" + -DSIGNTOOL_EXECUTABLE="${SIGNTOOL_EXECUTABLE}" + -DSIGNTOOL_PARAMETERS="${SIGNTOOL_PARAMETERS}" + -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" + -DTHIRD_PARTY_DOWNLOAD_LOCATION="${THIRD_PARTY_DOWNLOAD_LOCATION}" + -DTHIRD_PARTY_FEATURE_CONDITION="${THIRD_PARTY_FEATURE_CONDITION}" + -DTINY_VERSION="${TINY_VERSION}" + -DTOP_BINDIR="${CMAKE_BINARY_DIR}" + -DVERSION="${VERSION}" + -DWITH_THIRD_PARTY="${WITH_THIRD_PARTY}" + -DWIXCA_LOCATION="$<TARGET_FILE:wixca>" + -P ${CMAKE_CURRENT_SOURCE_DIR}/create_msi.cmake ) ADD_DEPENDENCIES(MSI_ESSENTIALS wixca) diff --git a/win/packaging/create_msi.cmake.in b/win/packaging/create_msi.cmake index c37f7ca9d1d..795baa32c8f 100644 --- a/win/packaging/create_msi.cmake.in +++ b/win/packaging/create_msi.cmake @@ -1,35 +1,3 @@ -SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@") -SET(CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@") -SET(CANDLE_EXECUTABLE "@CANDLE_EXECUTABLE@") -SET(LIGHT_EXECUTABLE "@LIGHT_EXECUTABLE@") -SET(CMAKE_COMMAND "@CMAKE_COMMAND@") -SET(CMAKE_CFG_INTDIR "@CMAKE_CFG_INTDIR@") -SET(VERSION "@VERSION@") -SET(MAJOR_VERSION "@MAJOR_VERSION@") -SET(MINOR_VERSION "@MINOR_VERSION@") -SET(PATCH_VERSION "@PATCH_VERSION@") -SET(TINY_VERSION "@TINY_VERSION@") -SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@) -SET(MANUFACTURER "@MANUFACTURER@") -SET(WIXCA_LOCATION "@WIXCA_LOCATION@") -SET(COPYING_RTF "@COPYING_RTF@") -SET(CPACK_WIX_CONFIG "@CPACK_WIX_CONFIG@") -SET(CPACK_WIX_INCLUDE "@CPACK_WIX_INCLUDE@") -SET(CPACK_WIX_UPGRADE_CODE "@CPACK_WIX_UPGRADE_CODE@") -SET(CPACK_WIX_PACKAGE_NAME "@CPACK_WIX_PACKAGE_NAME@") -SET(CPACK_WIX_PACKAGE_BASE_NAME "@CPACK_WIX_PACKAGE_BASE_NAME@") -SET(SIGNCODE "@SIGNCODE@") -SET(SIGNTOOL_EXECUTABLE "@SIGNTOOL_EXECUTABLE@") -SET(SIGNTOOL_PARAMETERS "@SIGNTOOL_PARAMETERS@") -SET(CMAKE_FULL_VER - "@CMAKE_MAJOR_VERSION@.@CMAKE_MINOR_VERSION@.@CMAKE_PATCH_VERSION@") -SET(EXTRA_WIX_PREPROCESSOR_FLAGS "@EXTRA_WIX_PREPROCESSOR_FLAGS@") -SET(WITH_THIRD_PARTY "@WITH_THIRD_PARTY@") -SET(THIRD_PARTY_DOWNLOAD_LOCATION "@THIRD_PARTY_DOWNLOAD_LOCATION@") -SET(THIRD_PARTY_FEATURE_CONDITION "@THIRD_PARTY_FEATURE_CONDITION@") -SET(LIBMYSQL_LOCATION "@LIBMYSQL_LOCATION@") - - MACRO(MAKE_WIX_IDENTIFIER str varname) STRING(REPLACE "/" "." ${varname} "${str}") STRING(REGEX REPLACE "[^a-zA-Z_0-9.]" "_" ${varname} "${${varname}}") @@ -45,19 +13,15 @@ MACRO(MAKE_WIX_IDENTIFIER str varname) ENDMACRO() SET($ENV{VS_UNICODE_OUTPUT} "") -IF(LIBMYSQL_LOCATION AND CMAKE_CFG_INTDIR) - # resolve libmysql full path - STRING(REPLACE "${CMAKE_CFG_INTDIR}" "${CMAKE_INSTALL_CONFIG_NAME}" LIBMYSQL_LOCATION "${LIBMYSQL_LOCATION}") -ENDIF() - + FOREACH(third_party ${WITH_THIRD_PARTY}) - INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/${third_party}.cmake) + INCLUDE(${SRCDIR}/${third_party}.cmake) # Check than above script produced ${third_party}.wxi and ${third_party}_feature.wxi FOREACH(outfile ${third_party}.wxi ${third_party}_feature.wxi) IF(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${outfile}) MESSAGE(FATAL_ERROR - "${CMAKE_CURRENT_SOURCE_DIR}/${third_party}.cmake did not produce " + "${SRCDIR}/${third_party}.cmake did not produce " "${CMAKE_CURRENT_BINARY_DIR}/${outfile}" ) ENDIF() @@ -79,7 +43,7 @@ ENDIF() SET(ENV{VS_UNICODE_OUTPUT}) -INCLUDE(${CMAKE_BINARY_DIR}/CPackConfig.cmake) +INCLUDE(${TOP_BINDIR}/CPackConfig.cmake) IF(CPACK_WIX_CONFIG) INCLUDE(${CPACK_WIX_CONFIG}) @@ -101,13 +65,13 @@ FOREACH(comp ${COMPONENTS_ALL}) SET(ENV{DESTDIR} testinstall/${comp}) EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -DCMAKE_INSTALL_COMPONENT=${comp} - -DCMAKE_INSTALL_PREFIX= -P ${CMAKE_BINARY_DIR}/cmake_install.cmake + -DCMAKE_INSTALL_PREFIX= -P ${TOP_BINDIR}/cmake_install.cmake OUTPUT_QUIET ) # Exclude empty install components SET(INCLUDE_THIS_COMPONENT 1) - SET(MANIFEST_FILENAME "${CMAKE_BINARY_DIR}/install_manifest_${comp}.txt") + SET(MANIFEST_FILENAME "${TOP_BINDIR}/install_manifest_${comp}.txt") IF(EXISTS ${MANIFEST_FILENAME}) FILE(READ ${MANIFEST_FILENAME} content) STRING(LENGTH "${content}" content_length) @@ -385,9 +349,9 @@ SET(CPACK_WIX_INCLUDES ENDFOREACH() -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mysql_server.wxs.in +CONFIGURE_FILE(${SRCDIR}/mysql_server.wxs.in ${CMAKE_CURRENT_BINARY_DIR}/mysql_server.wxs) -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/extra.wxs.in +CONFIGURE_FILE(${SRCDIR}/extra.wxs.in ${CMAKE_CURRENT_BINARY_DIR}/extra.wxs) SET(EXTRA_CANDLE_ARGS "$ENV{EXTRA_CANDLE_ARGS}") @@ -425,6 +389,7 @@ EXECUTE_PROCESS( ) IF(SIGNCODE) + SEPARATE_ARGUMENTS(SIGNTOOL_PARAMETERS WINDOWS_COMMAND "${SIGNTOOL_PARAMETERS}") EXECUTE_PROCESS( COMMAND ${SIGNTOOL_EXECUTABLE} sign ${SIGNTOOL_PARAMETERS} /d ${CPACK_PACKAGE_FILE_NAME}.msi @@ -432,6 +397,6 @@ IF(SIGNCODE) ) ENDIF() CONFIGURE_FILE(${CPACK_PACKAGE_FILE_NAME}.msi - ${CMAKE_BINARY_DIR}/${CPACK_PACKAGE_FILE_NAME}.msi + ${TOP_BINDIR}/${CPACK_PACKAGE_FILE_NAME}.msi COPYONLY) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 819bcc36ecb..a71ef982896 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -71,8 +71,8 @@ <!-- User interface dialogs --> - <WixVariable Id='WixUIBannerBmp' Value='@CMAKE_CURRENT_SOURCE_DIR@\WixUIBannerBmp.jpg' /> - <WixVariable Id='WixUIDialogBmp' Value='@CMAKE_CURRENT_SOURCE_DIR@\WixUIDialogBmp.jpg' /> + <WixVariable Id='WixUIBannerBmp' Value='@SRCDIR@\WixUIBannerBmp.jpg' /> + <WixVariable Id='WixUIDialogBmp' Value='@SRCDIR@\WixUIDialogBmp.jpg' /> <UI> <!-- Dialog on uninstall of the database --> diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index 569ae4d8ed5..6f325ca30af 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -13,11 +13,5 @@ IF(NOT EXISTS ${HEIDISQL_DOWNLOAD_DIR}/${HEIDISQL_ZIP}) ENDIF() SET(LIBMYSQLDLL_SOURCE ${HEIDISQL_DOWNLOAD_DIR}/libmysql.dll) -IF(CMAKE_SIZEOF_VOID_P EQUAL 4) - # Use our libmysql if it is 32 bit. - IF(LIBMYSQL_LOCATION) - SET(LIBMYSQLDLL_SOURCE "${LIBMYSQL_LOCATION}") - ENDIF() -ENDIF() -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/heidisql.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/heidisql.wxi) -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/heidisql_feature.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/heidisql_feature.wxi) +CONFIGURE_FILE(${SRCDIR}/heidisql.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/heidisql.wxi) +CONFIGURE_FILE(${SRCDIR}/heidisql_feature.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/heidisql_feature.wxi) diff --git a/win/upgrade_wizard/CMakeLists.txt b/win/upgrade_wizard/CMakeLists.txt index 81c9c0d572c..f4148ee98d2 100644 --- a/win/upgrade_wizard/CMakeLists.txt +++ b/win/upgrade_wizard/CMakeLists.txt @@ -46,9 +46,8 @@ SET_TARGET_PROPERTIES(mysql_upgrade_wizard PROPERTIES WIN32_EXECUTABLE 1) # to change service configuration. Due to a CMake bug http://www.vtk.org/Bug/view.php?id=11171 # it is not possible currenly to do it with linker flags. Work around is to use # manifest tool mt.exe and embed the manifest post-build. -GET_TARGET_PROPERTY(upgrade_wizard_location mysql_upgrade_wizard LOCATION) ADD_CUSTOM_COMMAND( TARGET mysql_upgrade_wizard POST_BUILD COMMAND mt.exe -manifest ${CMAKE_CURRENT_SOURCE_DIR}/upgrade_wizard.exe.manifest - "-outputresource:${upgrade_wizard_location};#1" + "-outputresource:$<TARGET_FILE:mysql_upgrade_wizard>;#1" ) |