diff options
author | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2010-07-05 12:35:24 +0300 |
---|---|---|
committer | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2010-07-05 12:35:24 +0300 |
commit | 22f4498cd6fe1484184bdb08f94d51c1ab88e45e (patch) | |
tree | cd0a9790c5861b1ff41c3763d6e4d83033c03ce3 | |
parent | 0a0d013aefa2823b1846ec904567a3fcb84c8432 (diff) | |
parent | 2ecadfc1f934d00180458d1ecfc8088b27d7ff8d (diff) | |
download | mariadb-git-22f4498cd6fe1484184bdb08f94d51c1ab88e45e.tar.gz |
merge
392 files changed, 8739 insertions, 3284 deletions
diff --git a/.bzrignore b/.bzrignore index 7733bd2aa7c..f5f678ca360 100644 --- a/.bzrignore +++ b/.bzrignore @@ -996,6 +996,8 @@ libmysqld/.deps/sql_crypt.Po libmysqld/.deps/sql_cursor.Po libmysqld/.deps/sql_db.Po libmysqld/.deps/sql_delete.Po +libmysqld/.deps/sql_truncate.Po +libmysqld/.deps/datadict.Po libmysqld/.deps/sql_derived.Po libmysqld/.deps/sql_do.Po libmysqld/.deps/sql_error.Po @@ -1172,6 +1174,8 @@ libmysqld/sql_cursor.cc libmysqld/sql_cursor.h libmysqld/sql_db.cc libmysqld/sql_delete.cc +libmysqld/sql_truncate.cc +libmysqld/datadict.cc libmysqld/sql_derived.cc libmysqld/sql_do.cc libmysqld/sql_error.cc @@ -2062,6 +2066,8 @@ sql/.deps/sql_crypt.Po sql/.deps/sql_cursor.Po sql/.deps/sql_db.Po sql/.deps/sql_delete.Po +sql/.deps/sql_truncate.Po +sql/.deps/datadict.Po sql/.deps/sql_derived.Po sql/.deps/sql_do.Po sql/.deps/sql_error.Po diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 0bc16f120e5..08ae4de2e23 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -90,22 +90,19 @@ SSL_LIBRARY=--with-ssl if [ "x$warning_mode" != "xpedantic" ]; then # Both C and C++ warnings - warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W" - warnings="$warnings -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare" - warnings="$warnings -Wwrite-strings -Wunused-function -Wunused-label -Wunused-value -Wunused-variable" + warnings="-Wall -Wextra -Wunused -Wwrite-strings" # For more warnings, uncomment the following line -# warnings="$global_warnings -Wshadow" +# warnings="$warnings -Wshadow" # C warnings - c_warnings="$warnings -Wunused-parameter" + c_warnings="$warnings" # C++ warnings - cxx_warnings="$warnings" + cxx_warnings="$warnings -Wno-unused-parameter" # cxx_warnings="$cxx_warnings -Woverloaded-virtual -Wsign-promo" - cxx_warnings="$cxx_warnings -Wreorder" cxx_warnings="$cxx_warnings -Wctor-dtor-privacy -Wnon-virtual-dtor" # Added unless --with-debug=full - debug_extra_cflags="-O0 -g3 -gdwarf-2" #1 -Wuninitialized" + debug_extra_cflags="-O0 -g3 -gdwarf-2" else warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" c_warnings="$warnings" @@ -122,7 +119,7 @@ fi # Override -DFORCE_INIT_OF_VARS from debug_cflags. It enables the macro # LINT_INIT(), which is only useful for silencing spurious warnings # of static analysis tools. We want LINT_INIT() to be a no-op in Valgrind. -valgrind_flags="-UFORCE_INIT_OF_VARS -DHAVE_purify " +valgrind_flags="-USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify " valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" valgrind_configs="--with-valgrind" # diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh index 2d7c0d2a2c2..c3803610e73 100755 --- a/BUILD/build_mccge.sh +++ b/BUILD/build_mccge.sh @@ -1010,7 +1010,7 @@ set_ccache_usage() set_valgrind_flags() { if test "x$valgrind_flag" = "xyes" ; then - loc_valgrind_flags="-UFORCE_INIT_OF_VARS -DHAVE_purify " + loc_valgrind_flags="-USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify " loc_valgrind_flags="$loc_valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" compiler_flags="$compiler_flags $loc_valgrind_flags" with_flags="$with_flags --with-valgrind" diff --git a/BUILD/check-cpu b/BUILD/check-cpu index eb001ee61ae..f9f5d423f4f 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -187,69 +187,76 @@ check_cpu () { cc=$CC fi - if test "x$compiler" = "x" ; then - cc_ver=`$cc --version | sed 1q` - cc_verno=`echo $cc_ver | sed -e 's/^.*(GCC)//g; s/[^0-9. ]//g; s/^ *//g; s/ .*//g'` + if test "x$core2" = "xyes" ; then + cpu_arg="core2" + fi + + if test "x$compiler" != "x" ; then + return 0 + fi + + # check if compiler is gcc and dump its version + cc_verno=`$cc -dumpversion 2>/dev/null` + if test "x$?" = "x0" ; then set -- `echo $cc_verno | tr '.' ' '` + cc_ver="GCC" cc_major=$1 cc_minor=$2 cc_patch=$3 cc_comp=`expr $cc_major '*' 100 '+' $cc_minor` - - case "$cc_ver--$cc_verno" in - *GCC*) - # different gcc backends (and versions) have different CPU flags - case `gcc -dumpmachine` in - i?86-* | x86_64-*) - if test "$cc_comp" -lt 304 ; then - check_cpu_cflags="-mcpu=${cpu_arg}" - elif test "$cc_comp" -ge 402 ; then - check_cpu_cflags="-mtune=native" - else - check_cpu_cflags="-mtune=${cpu_arg}" - fi - ;; - ppc-*) - check_cpu_cflags="-mcpu=${cpu_arg} -mtune=${cpu_arg}" - ;; - *) - check_cpu_cflags="" - return - ;; - esac - ;; - 2.95.*) - # GCC 2.95 doesn't expose its name in --version output - check_cpu_cflags="-m${cpu_arg}" - ;; - *) - check_cpu_cflags="" - return - ;; - esac - # now we check whether the compiler really understands the cpu type - touch __test.c - - while [ "$cpu_arg" ] ; do - printf "testing $cpu_arg ... " >&2 - - # compile check - eval "$cc -c $check_cpu_cflags __test.c" 2>/dev/null - if test "x$?" = "x0" ; then - echo ok >&2 - break; - fi + fi - echo failed >&2 + case "$cc_ver--$cc_verno" in + *GCC*) + # different gcc backends (and versions) have different CPU flags + case `gcc -dumpmachine` in + i?86-* | x86_64-*) + if test "$cc_comp" -lt 304 ; then + check_cpu_cflags="-mcpu=${cpu_arg}" + elif test "$cc_comp" -ge 402 ; then + check_cpu_cflags="-mtune=native" + else + check_cpu_cflags="-mtune=${cpu_arg}" + fi + ;; + ppc-*) + check_cpu_cflags="-mcpu=${cpu_arg} -mtune=${cpu_arg}" + ;; + *) + check_cpu_cflags="" + return + ;; + esac + ;; + 2.95.*) + # GCC 2.95 doesn't expose its name in --version output + check_cpu_cflags="-m${cpu_arg}" + ;; + *) check_cpu_cflags="" + return + ;; + esac + + # now we check whether the compiler really understands the cpu type + touch __test.c + + while [ "$cpu_arg" ] ; do + printf "testing $cpu_arg ... " >&2 + + # compile check + eval "$cc -c $check_cpu_cflags __test.c" 2>/dev/null + if test "x$?" = "x0" ; then + echo ok >&2 break; - done - rm __test.* - fi - if test "x$core2" = "xyes" ; then - cpu_arg="core2" - fi + fi + + echo failed >&2 + check_cpu_cflags="" + break; + done + rm __test.* return 0 } - + check_cpu diff --git a/CMakeLists.txt b/CMakeLists.txt index 536fae9f4b1..0131ac1b0a7 100755..100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,18 @@ SET(CUSTOM_C_FLAGS $ENV{CFLAGS}) OPTION(WITH_DEBUG "Use dbug/safemutex" OFF) OPTION(WITH_DEBUG_FULL "Use dbug and safemalloc/safemutex. Slow" OFF) +# Distinguish between community and non-community builds, with the +# default being a community build. This does not impact the feature +# set that will be compiled in; it's merely provided as a hint to +# custom packaging steps. +OPTION(COMMUNITY_BUILD "Set to true if this is a community build" ON) + +# Use a default manufacturer if no manufacturer was identified. +SET(MANUFACTURER_DOCSTRING + "Set the entity that appears as the manufacturer of packages that support a manufacturer field.") +IF(NOT DEFINED MANUFACTURER) + SET(MANUFACTURER "Built from Source" CACHE BOOL ${MANUFACTURER_DOCSTRING}) +ENDIF() # We choose to provide WITH_DEBUG as alias to standard CMAKE_BUILD_TYPE=Debug # which turns out to be not trivial, as this involves synchronization @@ -277,6 +289,7 @@ IF(WIN32) ELSE() SET(CPACK_GENERATOR "TGZ") ENDIF() +ADD_SUBDIRECTORY(packaging/WiX) INCLUDE(CPack) IF(UNIX) INSTALL(FILES Docs/mysql.info DESTINATION ${INSTALL_INFODIR} OPTIONAL) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index f4e223c9c72..d0bb8d43edd 100755..100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -33,7 +33,7 @@ IF(UNIX) TARGET_LINK_LIBRARIES(mysql ${READLINE_LIBRARY}) ENDIF(UNIX) -MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc) +MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test) SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS") TARGET_LINK_LIBRARIES(mysqltest mysqlclient regex) diff --git a/client/mysql.cc b/client/mysql.cc index 58ef51f3fff..e605d517d2c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -88,7 +88,6 @@ extern "C" { #endif #endif -#undef bcmp // Fix problem with new readline #if defined(__WIN__) #include <conio.h> #elif !defined(__NETWARE__) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 75b23ea9af7..95fe3904259 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5827,7 +5827,7 @@ int read_command(struct st_command** command_ptr) (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME|MY_ZEROFILL))) || insert_dynamic(&q_lines, (uchar*) &command)) - die(NullS); + die("Out of memory"); command->type= Q_UNKNOWN; read_command_buf[0]= 0; @@ -6326,7 +6326,7 @@ void init_win_path_patterns() } if (insert_dynamic(&patterns, (uchar*) &p)) - die(NullS); + die("Out of memory"); DBUG_PRINT("info", ("p: %s", p)); while (*p) @@ -9421,8 +9421,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count, for (i=1 ; i <= found_sets ; i++) { pos=from[found_set[i-1].table_offset]; - rep_str[i].found= !bcmp((const uchar*) pos, - (const uchar*) "\\^", 3) ? 2 : 1; + rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1; rep_str[i].replace_string=to_array[found_set[i-1].table_offset]; rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos); rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+ @@ -9550,8 +9549,8 @@ void copy_bits(REP_SET *to,REP_SET *from) int cmp_bits(REP_SET *set1,REP_SET *set2) { - return bcmp((uchar*) set1->bits,(uchar*) set2->bits, - sizeof(uint) * set1->size_of_bits); + return memcmp(set1->bits, set2->bits, + sizeof(uint) * set1->size_of_bits); } @@ -9620,17 +9619,15 @@ int find_found(FOUND_SET *found_set,uint table_offset, int found_offset) uint start_at_word(char * pos) { - return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) || - !bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0); + return (((!memcmp(pos, "\\b",2) && pos[2]) || + !memcmp(pos, "\\^", 2)) ? 1 : 0); } uint end_of_word(char * pos) { char * end=strend(pos); - return ((end > pos+2 && !bcmp((const uchar*) end-2, - (const uchar*) "\\b", 2)) || - (end >= pos+2 && !bcmp((const uchar*) end-2, - (const uchar*) "\\$",2))) ? 1 : 0; + return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) || + (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0; } /**************************************************************************** diff --git a/cmake/create_initial_db.cmake.in b/cmake/create_initial_db.cmake.in index 649d96a6627..881afe265ef 100644 --- a/cmake/create_initial_db.cmake.in +++ b/cmake/create_initial_db.cmake.in @@ -31,8 +31,7 @@ ENDIF() # Create bootstrapper SQL script FILE(WRITE bootstrap.sql "use mysql;\n" ) -FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql - fill_help_tables.sql) +FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql) FILE(STRINGS ${CMAKE_SOURCE_DIR}/scripts/${FILENAME} CONTENTS) FOREACH(STR ${CONTENTS}) IF(NOT STR MATCHES "@current_hostname") @@ -40,6 +39,8 @@ FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql ENDIF() ENDFOREACH() ENDFOREACH() +FILE(READ ${CMAKE_SOURCE_DIR}/scripts/fill_help_tables.sql CONTENTS) +FILE(APPEND bootstrap.sql ${CONTENTS}) FILE(REMOVE_RECURSE mysql) @@ -56,6 +57,7 @@ SET(BOOTSTRAP_COMMAND --lc-messages-dir=${CMAKE_CURRENT_BINARY_DIR}/share --basedir=. --datadir=. + --default-storage-engine=MyISAM --loose-skip-innodb --loose-skip-ndbcluster --max_allowed_packet=8M @@ -78,4 +80,4 @@ EXECUTE_PROCESS ( IF(NOT RESULT EQUAL 0) MESSAGE(FATAL_ERROR "Could not create initial database \n ${OUT} \n ${ERR}") ENDIF() -
\ No newline at end of file + diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index ade6cdb747f..ade6cdb747f 100755..100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index f049776b8f4..07aa4500188 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -35,15 +35,84 @@ MACRO (INSTALL_DEBUG_SYMBOLS targets) IF(CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}" pdb_location ${pdb_location}) ENDIF() - INSTALL(FILES ${pdb_location} DESTINATION ${INSTALL_LOCATION}) + IF(target STREQUAL "mysqld") + SET(comp Server) + ELSE() + SET(comp Debuginfo) + ENDIF() + INSTALL(FILES ${pdb_location} DESTINATION ${INSTALL_LOCATION} COMPONENT ${comp}) ENDFOREACH() ENDIF() ENDMACRO() +# Installs manpage for given file (either script or executable) +# +FUNCTION(INSTALL_MANPAGE file) + IF(NOT UNIX) + RETURN() + ENDIF() + GET_FILENAME_COMPONENT(file_name "${file}" NAME) + SET(GLOB_EXPR + ${CMAKE_SOURCE_DIR}/man/*${file}man.1* + ${CMAKE_SOURCE_DIR}/man/*${file}man.8* + ${CMAKE_BINARY_DIR}/man/*${file}man.1* + ${CMAKE_BINARY_DIR}/man/*${file}man.8* + ) + IF(MYSQL_DOC_DIR) + SET(GLOB_EXPR + ${MYSQL_DOC_DIR}/man/*${file}man.1* + ${MYSQL_DOC_DIR}/man/*${file}man.8* + ${MYSQL_DOC_DIR}/man/*${file}.1* + ${MYSQL_DOC_DIR}/man/*${file}.8* + ${GLOB_EXPR} + ) + ENDIF() + + FILE(GLOB_RECURSE MANPAGES ${GLOB_EXPR}) + IF(MANPAGES) + LIST(GET MANPAGES 0 MANPAGE) + STRING(REPLACE "${file}man.1" "${file}.1" MANPAGE "${MANPAGE}") + STRING(REPLACE "${file}man.8" "${file}.8" MANPAGE "${MANPAGE}") + IF(MANPAGE MATCHES "${file}.1") + SET(SECTION man1) + ELSE() + SET(SECTION man8) + ENDIF() + INSTALL(FILES "${MANPAGE}" DESTINATION "${INSTALL_MANDIR}/${SECTION}") + ENDIF() +ENDFUNCTION() + +FUNCTION(INSTALL_SCRIPT) + CMAKE_PARSE_ARGUMENTS(ARG + "DESTINATION;COMPONENT" + "" + ${ARGN} + ) + + SET(script ${ARG_DEFAULT_ARGS}) + IF(NOT ARG_DESTINATION) + SET(ARG_DESTINATION ${INSTALL_BINDIR}) + ENDIF() + IF(ARG_COMPONENT) + SET(COMP COMPONENT ${ARG_COMPONENT}) + ELSE() + SET(COMP) + ENDIF() + + INSTALL(FILES + ${script} + DESTINATION ${ARG_DESTINATION} + PERMISSIONS OWNER_READ OWNER_WRITE + OWNER_EXECUTE GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE ${COMP} + ) + INSTALL_MANPAGE(${script}) +ENDFUNCTION() + # Install symbolic link to CMake target. # the link is created in the same directory as target # and extension will be the same as for target file. -MACRO(INSTALL_SYMLINK linkname target destination) +MACRO(INSTALL_SYMLINK linkname target destination component) IF(UNIX) GET_TARGET_PROPERTY(location ${target} LOCATION) GET_FILENAME_COMPONENT(path ${location} PATH) @@ -68,7 +137,12 @@ IF(UNIX) STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}" output ${output}) ENDIF() - INSTALL(FILES ${output} DESTINATION ${destination}) + IF(component) + SET(COMP COMPONENT ${component}) + ELSE() + SET(COMP) + ENDIF() + INSTALL(FILES ${output} DESTINATION ${destination} ${COMP}) ENDIF() ENDMACRO() @@ -128,13 +202,11 @@ ENDMACRO() # Installs targets, also installs pdbs on Windows. # -# More stuff can be added later, e.g signing -# or pre-link custom targets (one example is creating -# version resource for windows executables) +# FUNCTION(MYSQL_INSTALL_TARGETS) CMAKE_PARSE_ARGUMENTS(ARG - "DESTINATION" + "DESTINATION;COMPONENT" "" ${ARGN} ) @@ -146,15 +218,24 @@ FUNCTION(MYSQL_INSTALL_TARGETS) MESSAGE(FATAL_ERROR "Need DESTINATION parameter for MYSQL_INSTALL_TARGETS") ENDIF() - # If signing is required, sign executables before installing + FOREACH(target ${TARGETS}) - IF(SIGNCODE AND SIGNCODE_ENABLED) + # If signing is required, sign executables before installing + IF(SIGNCODE AND SIGNCODE_ENABLED) SIGN_TARGET(${target}) ENDIF() + # For Windows, add version info to executables ADD_VERSION_INFO(${target}) + # Install man pages on Unix + IF(UNIX) + GET_TARGET_PROPERTY(target_location ${target} LOCATION) + INSTALL_MANPAGE(${target_location}) + ENDIF() ENDFOREACH() - - INSTALL(TARGETS ${TARGETS} DESTINATION ${ARG_DESTINATION}) + IF(ARG_COMPONENT) + SET(COMP COMPONENT ${ARG_COMPONENT}) + ENDIF() + INSTALL(TARGETS ${TARGETS} DESTINATION ${ARG_DESTINATION} ${COMP}) SET(INSTALL_LOCATION ${ARG_DESTINATION} ) INSTALL_DEBUG_SYMBOLS("${TARGETS}") SET(INSTALL_LOCATION) diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index 2263b146ed6..ba63df71428 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -214,7 +214,7 @@ ENDMACRO() #) MACRO(MERGE_LIBRARIES) CMAKE_PARSE_ARGUMENTS(ARG - "EXPORTS;OUTPUT_NAME" + "EXPORTS;OUTPUT_NAME;COMPONENT" "STATIC;SHARED;MODULE;NOINSTALL" ${ARGN} ) @@ -259,7 +259,10 @@ MACRO(MERGE_LIBRARIES) MESSAGE(FATAL_ERROR "Unknown library type") ENDIF() IF(NOT ARG_NOINSTALL) - MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}") + IF(ARG_COMPONENT) + SET(COMP COMPONENT ${ARG_COMPONENT}) + ENDIF() + MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}" ${COMP}) ENDIF() SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_INTERFACE_LIBRARIES "") ENDMACRO() diff --git a/cmake/mysql_add_executable.cmake b/cmake/mysql_add_executable.cmake index 2157d03e6d1..86301c2eec8 100644 --- a/cmake/mysql_add_executable.cmake +++ b/cmake/mysql_add_executable.cmake @@ -29,7 +29,7 @@ INCLUDE(cmake_parse_arguments) FUNCTION (MYSQL_ADD_EXECUTABLE)
# Pass-through arguments for ADD_EXECUTABLE
CMAKE_PARSE_ARGUMENTS(ARG
- "WIN32;MACOSX_BUNDLE;EXCLUDE_FROM_ALL;DESTINATION"
+ "WIN32;MACOSX_BUNDLE;EXCLUDE_FROM_ALL;DESTINATION;COMPONENT"
""
${ARGN}
)
@@ -43,7 +43,14 @@ FUNCTION (MYSQL_ADD_EXECUTABLE) IF(NOT ARG_EXCLUDE_FROM_ALL)
IF(NOT ARG_DESTINATION)
SET(ARG_DESTINATION ${INSTALL_BINDIR})
+ ENDIF() + IF(ARG_COMPONENT) + SET(COMP COMPONENT ${ARG_COMPONENT}) + ELSEIF(MYSQL_INSTALL_COMPONENT) + SET(COMP COMPONENT ${MYSQL_INSTALL_COMPONENT}) + ELSE() + SET(COMP COMPONENT Client) ENDIF()
- MYSQL_INSTALL_TARGETS(${target} DESTINATION ${ARG_DESTINATION})
+ MYSQL_INSTALL_TARGETS(${target} DESTINATION ${ARG_DESTINATION} ${COMP})
ENDIF()
-ENDFUNCTION()
\ No newline at end of file +ENDFUNCTION() diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index 68b6f2a6ddf..e07e3f54aa8 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -30,7 +30,6 @@ SET(HAVE_ASM_MSR_H CACHE INTERNAL "") SET(HAVE_BACKTRACE CACHE INTERNAL "") SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "") SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "") -SET(HAVE_BCMP CACHE INTERNAL "") SET(HAVE_BFILL CACHE INTERNAL "") SET(HAVE_BMOVE CACHE INTERNAL "") SET(HAVE_BSD_SIGNALS CACHE INTERNAL "") diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index d2998cfd795..6e6fe89e8b3 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -15,6 +15,8 @@ # Produce meaningful package name for the binary package # The logic is rather involved with special cases for different OSes +INCLUDE(CheckTypeSize) +CHECK_TYPE_SIZE("void *" SIZEOF_VOIDP) MACRO(GET_PACKAGE_FILE_NAME Var) IF(NOT VERSION) MESSAGE(FATAL_ERROR @@ -24,7 +26,8 @@ IF(NOT VERSION) SET(NEED_DASH_BETWEEN_PLATFORM_AND_MACHINE 1) SET(DEFAULT_PLATFORM ${CMAKE_SYSTEM_NAME}) SET(DEFAULT_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) - IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + MESSAGE("SIZEOF_VOIDP=${SIZEOF_VOIDP}") + IF(SIZEOF_VOIDP EQUAL 8) SET(64BIT 1) ENDIF() diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 896624996d3..94edfb8741a 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -173,7 +173,7 @@ MACRO(MYSQL_ADD_PLUGIN) SET_TARGET_PROPERTIES(${target} PROPERTIES OUTPUT_NAME "${ARG_MODULE_OUTPUT_NAME}") # Install dynamic library - MYSQL_INSTALL_TARGETS(${target} DESTINATION ${INSTALL_PLUGINDIR}) + MYSQL_INSTALL_TARGETS(${target} DESTINATION ${INSTALL_PLUGINDIR} COMPONENT Server) INSTALL_DEBUG_TARGET(${target} DESTINATION ${INSTALL_PLUGINDIR}/debug) ENDIF() ENDMACRO() diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index b101c26e241..d1f48888092 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -25,7 +25,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL) SET(SSL_LIBRARIES yassl taocrypt) SET(SSL_INCLUDE_DIRS ${INC_DIRS}) SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL) - SET(SSL_DEFINES"-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DYASSL_THREAD_SAFE") + SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DYASSL_THREAD_SAFE") CHANGE_SSL_SETTINGS("bundled") #Remove -fno-implicit-templates #(yassl sources cannot be compiled with it) diff --git a/cmd-line-utils/readline/Makefile.am b/cmd-line-utils/readline/Makefile.am index 40e74ccaf55..48d3af34412 100644 --- a/cmd-line-utils/readline/Makefile.am +++ b/cmd-line-utils/readline/Makefile.am @@ -31,4 +31,4 @@ noinst_HEADERS = readline.h chardefs.h keymaps.h \ EXTRA_DIST= emacs_keymap.c vi_keymap.c CMakeLists.txt -DEFS = -DMYSQL_CLIENT_NO_THREADS -DHAVE_CONFIG_H -DNO_KILL_INTR +DEFS = -DMYSQL_CLIENT_NO_THREADS -DHAVE_CONFIG_H -DNO_KILL_INTR -D_GNU_SOURCE=1 diff --git a/config.h.cmake b/config.h.cmake index c6c049814ba..2d877ed853f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -81,6 +81,8 @@ #cmakedefine HAVE_SYS_STREAM_H 1 #cmakedefine HAVE_SYS_TERMCAP_H 1 #cmakedefine HAVE_SYS_TIMEB_H 1 +#cmakedefine HAVE_SYS_TIMES_H 1 +#cmakedefine HAVE_SYS_TIME_H 1 #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_SYS_UN_H 1 #cmakedefine HAVE_SYS_VADVISE_H 1 @@ -88,6 +90,7 @@ #cmakedefine HAVE_TERMIOS_H 1 #cmakedefine HAVE_TERMIO_H 1 #cmakedefine HAVE_TERMCAP_H 1 +#cmakedefine HAVE_TIME_H 1 #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UTIME_H 1 #cmakedefine HAVE_VARARGS_H 1 @@ -122,7 +125,6 @@ #cmakedefine HAVE_AIOWAIT 1 #cmakedefine HAVE_ALARM 1 #cmakedefine HAVE_ALLOCA 1 -#cmakedefine HAVE_BCMP 1 #cmakedefine HAVE_BFILL 1 #cmakedefine HAVE_BMOVE 1 #cmakedefine HAVE_BZERO 1 @@ -261,6 +263,8 @@ #cmakedefine HAVE_TEMPNAM 1 #cmakedefine HAVE_THR_SETCONCURRENCY 1 #cmakedefine HAVE_THR_YIELD 1 +#cmakedefine HAVE_TIME 1 +#cmakedefine HAVE_TIMES 1 #cmakedefine HAVE_VALLOC 1 #define HAVE_VIO_READ_BUFF 1 #cmakedefine HAVE_VASPRINTF 1 @@ -295,11 +299,6 @@ /* Types we may use */ -#cmakedefine SIZEOF_CHAR @SIZEOF_CHAR@ -#if SIZEOF_CHAR -# define HAVE_CHAR 1 -#endif - #ifdef __APPLE__ /* Special handling required for OSX to support universal binaries that @@ -310,127 +309,71 @@ #else #define SIZEOF_LONG 4 #endif + #define SIZEOF_VOIDP SIZEOF_LONG #define SIZEOF_CHARP SIZEOF_LONG #define SIZEOF_SIZE_T SIZEOF_LONG #else - #cmakedefine SIZEOF_LONG @SIZEOF_LONG@ - #cmakedefine SIZEOF_CHARP @SIZEOF_CHARP@ - #cmakedefine SIZEOF_SIZE_T @SIZEOF_CHARP@ -#endif - -#if SIZEOF_LONG -# define HAVE_LONG 1 -#endif - - -#if SIZEOF_CHARP -#define HAVE_CHARP 1 -#define SIZEOF_VOIDP SIZEOF_CHARP +/* No indentation, to fetch the lines from verification scripts */ +#cmakedefine SIZEOF_LONG @SIZEOF_LONG@ +#cmakedefine SIZEOF_VOIDP @SIZEOF_VOIDP@ +#cmakedefine SIZEOF_CHARP @SIZEOF_CHARP@ +#cmakedefine SIZEOF_SIZE_T @SIZEOF_CHARP@ #endif +#cmakedefine SIZEOF_CHAR @SIZEOF_CHAR@ +#cmakedefine HAVE_CHAR 1 +#cmakedefine HAVE_LONG 1 +#cmakedefine HAVE_CHARP 1 #cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@ -#if SIZEOF_SHORT -# define HAVE_SHORT 1 -#endif - +#cmakedefine HAVE_SHORT 1 #cmakedefine SIZEOF_INT @SIZEOF_INT@ -#if SIZEOF_INT -# define HAVE_INT 1 -#endif - - +#cmakedefine HAVE_INT 1 #cmakedefine SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ -#if SIZEOF_LONG_LONG -# define HAVE_LONG_LONG 1 -#endif - +#cmakedefine HAVE_LONG_LONG 1 #cmakedefine SIZEOF_OFF_T @SIZEOF_OFF_T@ -#if SIZEOF_OFF_T -#define HAVE_OFF_T 1 -#endif - +#cmakedefine HAVE_OFF_T 1 #cmakedefine SIZEOF_SIGSET_T @SIZEOF_SIGSET_T@ -#if SIZEOF_SIGSET_T -#define HAVE_SIGSET_T 1 -#endif - -#if SIZEOF_SIZE_T -#define HAVE_SIZE_T 1 -#endif - +#cmakedefine HAVE_SIGSET_T 1 +#cmakedefine HAVE_SIZE_T 1 #cmakedefine SIZEOF_UCHAR @SIZEOF_UCHAR@ -#if SIZEOF_UCHAR -#define HAVE_UCHAR 1 -#endif - +#cmakedefine HAVE_UCHAR 1 #cmakedefine SIZEOF_UINT @SIZEOF_UINT@ -#if SIZEOF_UINT -#define HAVE_UINT 1 -#endif - +#cmakedefine HAVE_UINT 1 #cmakedefine SIZEOF_ULONG @SIZEOF_ULONG@ -#if SIZEOF_ULONG -#define HAVE_ULONG 1 -#endif - +#cmakedefine HAVE_ULONG 1 #cmakedefine SIZEOF_INT8 @SIZEOF_INT8@ -#if SIZEOF_INT8 -#define HAVE_INT8 1 -#endif +#cmakedefine HAVE_INT8 1 #cmakedefine SIZEOF_UINT8 @SIZEOF_UINT8@ -#if SIZEOF_UINT8 -#define HAVE_UINT8 1 -#endif - +#cmakedefine HAVE_UINT8 1 #cmakedefine SIZEOF_INT16 @SIZEOF_INT16@ -#if SIZEOF_INT16 -# define HAVE_INT16 1 -#endif +#cmakedefine HAVE_INT16 1 #cmakedefine SIZEOF_UINT16 @SIZEOF_UINT16@ -#if SIZEOF_UINT16 -#define HAVE_UINT16 1 -#endif - +#cmakedefine HAVE_UINT16 1 #cmakedefine SIZEOF_INT32 @SIZEOF_INT32@ -#if SIZEOF_INT32 -#define HAVE_INT32 1 -#endif +#cmakedefine HAVE_INT32 1 #cmakedefine SIZEOF_UINT32 @SIZEOF_UINT32@ -#if SIZEOF_UINT32 -#define HAVE_UINT32 1 -#endif +#cmakedefine HAVE_UINT32 1 #cmakedefine SIZEOF_U_INT32_T @SIZEOF_U_INT32_T@ -#if SIZEOF_U_INT32_T -#define HAVE_U_INT32_T 1 -#endif - +#cmakedefine HAVE_U_INT32_T 1 #cmakedefine SIZEOF_INT64 @SIZEOF_INT64@ -#if SIZEOF_INT64 -#define HAVE_INT64 1 -#endif +#cmakedefine HAVE_INT64 1 #cmakedefine SIZEOF_UINT64 @SIZEOF_UINT64@ -#if SIZEOF_UINT64 -#define HAVE_UINT64 1 -#endif +#cmakedefine HAVE_UINT64 1 +#cmakedefine SIZEOF_BOOL @SIZEOF_BOOL@ +#cmakedefine HAVE_BOOL 1 #cmakedefine SOCKET_SIZE_TYPE @SOCKET_SIZE_TYPE@ -#cmakedefine SIZEOF_BOOL @SIZEOF_BOOL@ -#if SIZEOF_BOOL -#define HAVE_BOOL 1 -#endif #cmakedefine HAVE_MBSTATE_T #define MAX_INDEXES 64 #cmakedefine QSORT_TYPE_IS_VOID 1 -#define RETQSORTTYPE void +#cmakedefine RETQSORTTYPE @RETQSORTTYPE@ #cmakedefine SIGNAL_RETURN_TYPE_IS_VOID 1 -#define RETSIGTYPE void -#if SIGNAL_RETURN_TYPE_IS_VOID -#define VOID_SIGHANDLER 1 -#endif +#cmakedefine RETSIGTYPE @RETSIGTYPE@ +#cmakedefine VOID_SIGHANDLER 1 #define STRUCT_RLIMIT struct rlimit #ifdef __APPLE__ @@ -547,7 +490,7 @@ #cmakedefine strtoull @strtoull@ #cmakedefine vsnprintf @vsnprintf@ #if (_MSC_VER > 1310) -#define HAVE_SETENV +# define HAVE_SETENV #define setenv(a,b,c) _putenv_s(a,b) #endif @@ -575,7 +518,7 @@ #cmakedefine FN_NO_CASE_SENSE 1 #cmakedefine HAVE_CHARSET_armscii8 1 -#cmakedefine HAVE_CHARSET_ascii +#cmakedefine HAVE_CHARSET_ascii 1 #cmakedefine HAVE_CHARSET_big5 1 #cmakedefine HAVE_CHARSET_cp1250 1 #cmakedefine HAVE_CHARSET_cp1251 1 @@ -637,7 +580,7 @@ #cmakedefine WITH_PERFSCHEMA_STORAGE_ENGINE 1 #cmakedefine WITH_NDBCLUSTER_STORAGE_ENGINE 1 #if (WITH_NDBCLUSTER_STORAGE_ENGINE) && !defined(EMBEDDED_LIBRARY) -#define HAVE_NDB_BINLOG 1 +# define HAVE_NDB_BINLOG 1 #endif #cmakedefine DEFAULT_MYSQL_HOME "@DEFAULT_MYSQL_HOME@" diff --git a/configure.cmake b/configure.cmake index 1727e2b2c10..ab3d706ee01 100644 --- a/configure.cmake +++ b/configure.cmake @@ -90,6 +90,21 @@ ENDIF(WITHOUT_DYNAMIC_PLUGINS) # Large files, common flag SET(_LARGEFILE_SOURCE 1) +# If finds the size of a type, set SIZEOF_<type> and HAVE_<type> +FUNCTION(MY_CHECK_TYPE_SIZE type defbase) + CHECK_TYPE_SIZE("${type}" SIZEOF_${defbase}) + IF(SIZEOF_${defbase}) + SET(HAVE_${defbase} 1 PARENT_SCOPE) + ENDIF() +ENDFUNCTION() + +# Same for structs, setting HAVE_STRUCT_<name> instead +FUNCTION(MY_CHECK_STRUCT_SIZE type defbase) + CHECK_TYPE_SIZE("struct ${type}" SIZEOF_${defbase}) + IF(SIZEOF_${defbase}) + SET(HAVE_STRUCT_${defbase} 1 PARENT_SCOPE) + ENDIF() +ENDFUNCTION() # Searches function in libraries # if function is found, sets output parameter result to the name of the library @@ -108,6 +123,7 @@ FUNCTION(MY_SEARCH_LIBS func libs result) CHECK_LIBRARY_EXISTS(${lib} ${func} "" HAVE_${func}_IN_${lib}) IF(HAVE_${func}_IN_${lib}) SET(${result} ${lib} PARENT_SCOPE) + SET(HAVE_${result} 1 PARENT_SCOPE) RETURN() ENDIF() ENDFOREACH() @@ -169,6 +185,7 @@ CHECK_INCLUDE_FILES (alloca.h HAVE_ALLOCA_H) CHECK_INCLUDE_FILES (aio.h HAVE_AIO_H) CHECK_INCLUDE_FILES (arpa/inet.h HAVE_ARPA_INET_H) CHECK_INCLUDE_FILES (crypt.h HAVE_CRYPT_H) +CHECK_INCLUDE_FILES (cxxabi.h HAVE_CXXABI_H) CHECK_INCLUDE_FILES (dirent.h HAVE_DIRENT_H) CHECK_INCLUDE_FILES (dlfcn.h HAVE_DLFCN_H) CHECK_INCLUDE_FILES (execinfo.h HAVE_EXECINFO_H) @@ -195,7 +212,6 @@ CHECK_INCLUDE_FILES (select.h HAVE_SELECT_H) CHECK_INCLUDE_FILES (semaphore.h HAVE_SEMAPHORE_H) CHECK_INCLUDE_FILES (sys/dir.h HAVE_SYS_DIR_H) CHECK_INCLUDE_FILES (sys/pte.h HAVE_SYS_PTE_H) -CHECK_INCLUDE_FILES (sys/ptem.h HAVE_SYS_PTEM_H) CHECK_INCLUDE_FILES (stddef.h HAVE_STDDEF_H) CHECK_INCLUDE_FILES (stdint.h HAVE_STDINT_H) CHECK_INCLUDE_FILES (stdlib.h HAVE_STDLIB_H) @@ -235,6 +251,13 @@ CHECK_INCLUDE_FILES (fnmatch.h HAVE_FNMATCH_H) CHECK_INCLUDE_FILES (stdarg.h HAVE_STDARG_H) CHECK_INCLUDE_FILES("stdlib.h;sys/un.h" HAVE_SYS_UN_H) +IF(HAVE_SYS_STREAM_H) + # Needs sys/stream.h on Solaris + CHECK_INCLUDE_FILES (sys/stream.h sys/ptem.h HAVE_SYS_PTEM_H) +ELSE() + CHECK_INCLUDE_FILES (sys/ptem.h HAVE_SYS_PTEM_H) +ENDIF() + # Figure out threading library # FIND_PACKAGE (Threads) @@ -250,7 +273,6 @@ CHECK_FUNCTION_EXISTS (backtrace HAVE_BACKTRACE) CHECK_FUNCTION_EXISTS (backtrace_symbols HAVE_BACKTRACE_SYMBOLS) CHECK_FUNCTION_EXISTS (backtrace_symbols_fd HAVE_BACKTRACE_SYMBOLS_FD) CHECK_FUNCTION_EXISTS (printstack HAVE_PRINTSTACK) -CHECK_FUNCTION_EXISTS (bcmp HAVE_BCMP) CHECK_FUNCTION_EXISTS (bfill HAVE_BFILL) CHECK_FUNCTION_EXISTS (bmove HAVE_BMOVE) CHECK_FUNCTION_EXISTS (bsearch HAVE_BSEARCH) @@ -458,14 +480,11 @@ set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_LARGEFILE_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS) SET(CMAKE_EXTRA_INCLUDE_FILES signal.h) -CHECK_TYPE_SIZE(sigset_t SIZEOF_SIGSET_T) -IF(SIZEOF_SIGSET_T) - SET(HAVE_SIGSET_T 1) -ENDIF() +MY_CHECK_TYPE_SIZE(sigset_t SIGSET_T) IF(NOT SIZEOF_SIGSET_T) SET(sigset_t int) ENDIF() -CHECK_TYPE_SIZE(mode_t SIZEOF_MODE_T) +MY_CHECK_TYPE_SIZE(mode_t MODE_T) IF(NOT SIZEOF_MODE_T) SET(mode_t int) ENDIF() @@ -478,43 +497,41 @@ ENDIF(HAVE_STDINT_H) IF(NOT APPLE) # Prevent some checks on OSX, they return ambigious results # on universal 32/64 bit binariess - CHECK_TYPE_SIZE("char *" SIZEOF_CHARP) - CHECK_TYPE_SIZE(long SIZEOF_LONG) - CHECK_TYPE_SIZE(size_t SIZEOF_SIZE_T) + MY_CHECK_TYPE_SIZE("void *" VOIDP) + MY_CHECK_TYPE_SIZE("char *" CHARP) + MY_CHECK_TYPE_SIZE(long LONG) + MY_CHECK_TYPE_SIZE(size_t SIZE_T) ENDIF() -CHECK_TYPE_SIZE(char SIZEOF_CHAR) -CHECK_TYPE_SIZE(short SIZEOF_SHORT) -CHECK_TYPE_SIZE(int SIZEOF_INT) -CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) +MY_CHECK_TYPE_SIZE(char CHAR) +MY_CHECK_TYPE_SIZE(short SHORT) +MY_CHECK_TYPE_SIZE(int INT) +MY_CHECK_TYPE_SIZE("long long" LONG_LONG) SET(CMAKE_EXTRA_INCLUDE_FILES stdio.h sys/types.h) -CHECK_TYPE_SIZE(off_t SIZEOF_OFF_T) -CHECK_TYPE_SIZE(uchar SIZEOF_UCHAR) -CHECK_TYPE_SIZE(uint SIZEOF_UINT) -CHECK_TYPE_SIZE(ulong SIZEOF_ULONG) -CHECK_TYPE_SIZE(int8 SIZEOF_INT8) -CHECK_TYPE_SIZE(uint8 SIZEOF_UINT8) -CHECK_TYPE_SIZE(int16 SIZEOF_INT16) -CHECK_TYPE_SIZE(uint16 SIZEOF_UINT16) -CHECK_TYPE_SIZE(int32 SIZEOF_INT32) -CHECK_TYPE_SIZE(uint32 SIZEOF_UINT32) -CHECK_TYPE_SIZE(u_int32_t SIZEOF_U_INT32_T) -CHECK_TYPE_SIZE(int64 SIZEOF_INT64) -CHECK_TYPE_SIZE(uint64 SIZEOF_UINT64) +MY_CHECK_TYPE_SIZE(off_t OFF_T) +MY_CHECK_TYPE_SIZE(uchar UCHAR) +MY_CHECK_TYPE_SIZE(uint UINT) +MY_CHECK_TYPE_SIZE(ulong ULONG) +MY_CHECK_TYPE_SIZE(int8 INT8) +MY_CHECK_TYPE_SIZE(uint8 UINT8) +MY_CHECK_TYPE_SIZE(int16 INT16) +MY_CHECK_TYPE_SIZE(uint16 UINT16) +MY_CHECK_TYPE_SIZE(int32 INT32) +MY_CHECK_TYPE_SIZE(uint32 UINT32) +MY_CHECK_TYPE_SIZE(u_int32_t U_INT32_T) +MY_CHECK_TYPE_SIZE(int64 INT64) +MY_CHECK_TYPE_SIZE(uint64 UINT64) SET (CMAKE_EXTRA_INCLUDE_FILES sys/types.h) -CHECK_TYPE_SIZE(bool SIZEOF_BOOL) +MY_CHECK_TYPE_SIZE(bool BOOL) SET(CMAKE_EXTRA_INCLUDE_FILES) IF(HAVE_SYS_SOCKET_H) SET(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) ENDIF(HAVE_SYS_SOCKET_H) -CHECK_TYPE_SIZE(socklen_t SIZEOF_SOCKLEN_T) +MY_CHECK_TYPE_SIZE(socklen_t SOCKLEN_T) SET(CMAKE_EXTRA_INCLUDE_FILES) IF(HAVE_IEEEFP_H) SET(CMAKE_EXTRA_INCLUDE_FILES ieeefp.h) - CHECK_TYPE_SIZE(fp_except SIZEOF_FP_EXCEPT) - IF(SIZEOF_FP_EXCEPT) - SET(HAVE_FP_EXCEPT TRUE) - ENDIF() + MY_CHECK_TYPE_SIZE(fp_except FP_EXCEPT) ENDIF() @@ -678,6 +695,7 @@ int main(int ac, char **av) {} " SIGNAL_RETURN_TYPE_IS_VOID) IF(SIGNAL_RETURN_TYPE_IS_VOID) SET(RETSIGTYPE void) + SET(VOID_SIGHANDLER 1) ELSE(SIGNAL_RETURN_TYPE_IS_VOID) SET(RETSIGTYPE int) ENDIF(SIGNAL_RETURN_TYPE_IS_VOID) @@ -777,7 +795,7 @@ ENDIF(NOT HAVE_POSIX_SIGNALS) # Assume regular sprintf SET(SPRINTFS_RETURNS_INT 1) -IF(CMAKE_COMPILER_IS_GNUXX) +IF(CMAKE_COMPILER_IS_GNUXX AND HAVE_CXXABI_H) CHECK_CXX_SOURCE_COMPILES(" #include <cxxabi.h> int main(int argc, char **argv) @@ -787,9 +805,6 @@ CHECK_CXX_SOURCE_COMPILES(" return 0; }" HAVE_ABI_CXA_DEMANGLE) -IF(HAVE_ABI_CXA_DEMANGLE) - SET(HAVE_CXXABI_H 1) -ENDIF() ENDIF() CHECK_C_SOURCE_COMPILES(" @@ -983,14 +998,8 @@ ELSEIF(WIN32) SET(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} winsock2.h ws2ipdef.h) ENDIF() -CHECK_TYPE_SIZE("struct sockaddr_in6" SIZEOF_SOCKADDR_IN6) -CHECK_TYPE_SIZE("struct in6_addr" SIZEOF_IN6_ADDR) -IF(SIZEOF_SOCKADDR_IN6) - SET(HAVE_STRUCT_SOCKADDR_IN6 1) -ENDIF() -IF(SIZEOF_IN6_ADDR) - SET(HAVE_STRUCT_IN6_ADDR 1) -ENDIF() +MY_CHECK_STRUCT_SIZE("sockaddr_in6" SOCKADDR_IN6) +MY_CHECK_STRUCT_SIZE("in6_addr" IN6_ADDR) IF(HAVE_STRUCT_SOCKADDR_IN6 OR HAVE_STRUCT_IN6_ADDR) SET(HAVE_IPV6 TRUE CACHE INTERNAL "") diff --git a/configure.in b/configure.in index 5de43fc7951..b07f172e758 100644 --- a/configure.in +++ b/configure.in @@ -27,7 +27,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.5.5-m3], [], [mysql]) +AC_INIT([MySQL Server], [5.5.6-m3], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM @@ -2342,7 +2342,7 @@ MYSQL_TYPE_QSORT AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF -AC_CHECK_FUNCS(alarm bcmp bfill bmove bsearch bzero \ +AC_CHECK_FUNCS(alarm bfill bmove bsearch bzero \ chsize cuserid fchmod fcntl \ fdatasync fesetround finite fpresetsticky fpsetmask fsync ftruncate \ getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \ diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt index 16e130fa28a..16e130fa28a 100755..100644 --- a/dbug/CMakeLists.txt +++ b/dbug/CMakeLists.txt diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 862635c25dc..27fc31cbdde 100755..100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -24,6 +24,8 @@ ${CMAKE_SOURCE_DIR}/storage/ndb/include/ndbapi ${CMAKE_SOURCE_DIR}/storage/ndb/include/portlib ${CMAKE_SOURCE_DIR}/storage/ndb/include/mgmapi) +# Default install component for the files is Server here +SET(MYSQL_INSTALL_COMPONENT Server) IF(NOT CMAKE_CROSSCOMPILING) ADD_EXECUTABLE(comp_err comp_err.c) diff --git a/extra/comp_err.c b/extra/comp_err.c index 53d8c18262b..4af17e3edf9 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -665,9 +665,9 @@ static struct message *find_message(struct errors *err, const char *lang, static ha_checksum checksum_format_specifier(const char* msg) { ha_checksum chksum= 0; - const char* p= msg; - const char* start= 0; - int num_format_specifiers= 0; + const uchar* p= (const uchar*) msg; + const uchar* start= NULL; + uint32 num_format_specifiers= 0; while (*p) { diff --git a/extra/replace.c b/extra/replace.c index 3f07183807c..4ae7989e5a7 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -648,7 +648,7 @@ static REPLACE *init_replace(char * *from, char * *to,uint count, for (i=1 ; i <= found_sets ; i++) { pos=from[found_set[i-1].table_offset]; - rep_str[i].found= (my_bool) (!bcmp(pos,"\\^",3) ? 2 : 1); + rep_str[i].found= (my_bool) (!memcmp(pos,"\\^",3) ? 2 : 1); rep_str[i].replace_string=to_array[found_set[i-1].table_offset]; rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos); rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+ @@ -776,8 +776,8 @@ static void copy_bits(REP_SET *to,REP_SET *from) static int cmp_bits(REP_SET *set1,REP_SET *set2) { - return bcmp((uchar*) set1->bits,(uchar*) set2->bits, - sizeof(uint) * set1->size_of_bits); + return memcmp(set1->bits, set2->bits, + sizeof(uint) * set1->size_of_bits); } @@ -849,14 +849,14 @@ static short find_found(FOUND_SET *found_set,uint table_offset, static uint start_at_word(char * pos) { - return (((!bcmp(pos,"\\b",2) && pos[2]) || !bcmp(pos,"\\^",2)) ? 1 : 0); + return (((!memcmp(pos,"\\b",2) && pos[2]) || !memcmp(pos,"\\^",2)) ? 1 : 0); } static uint end_of_word(char * pos) { char * end=strend(pos); - return ((end > pos+2 && !bcmp(end-2,"\\b",2)) || - (end >= pos+2 && !bcmp(end-2,"\\$",2))) ? + return ((end > pos+2 && !memcmp(end-2,"\\b",2)) || + (end >= pos+2 && !memcmp(end-2,"\\$",2))) ? 1 : 0; } diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt index 82d7e5b7581..82d7e5b7581 100755..100644 --- a/extra/yassl/CMakeLists.txt +++ b/extra/yassl/CMakeLists.txt diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp index 28d7f1b5693..b968ec1e6c3 100644 --- a/extra/yassl/src/crypto_wrapper.cpp +++ b/extra/yassl/src/crypto_wrapper.cpp @@ -953,8 +953,9 @@ x509* PemToDer(FILE* file, CertType type, EncryptedInfo* info) info->set = true; } } - fgets(line,sizeof(line), file); // get blank line - begin = ftell(file); + // get blank line + if (fgets(line, sizeof(line), file)) + begin = ftell(file); } } diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt index 2c43756b6f4..2c43756b6f4 100755..100644 --- a/extra/yassl/taocrypt/CMakeLists.txt +++ b/extra/yassl/taocrypt/CMakeLists.txt diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index 90d2c014b4c..94bbab7aea8 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -51,7 +51,7 @@ public: enum { BLOCK_SIZE = BLOWFISH_BLOCK_SIZE, ROUNDS = 16 }; Blowfish(CipherDir DIR, Mode MODE) - : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} + : Mode_BASE(BLOCK_SIZE, DIR, MODE), sbox_(pbox_ + ROUNDS + 2) {} #ifdef DO_BLOWFISH_ASM void Process(byte*, const byte*, word32); @@ -62,8 +62,8 @@ private: static const word32 p_init_[ROUNDS + 2]; static const word32 s_init_[4 * 256]; - word32 pbox_[ROUNDS + 2]; - word32 sbox_[4 * 256]; + word32 pbox_[ROUNDS + 2 + 4 * 256]; + word32* sbox_; void crypt_block(const word32 in[2], word32 out[2]) const; void AsmProcess(const byte* in, byte* out) const; diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index b59f61a1cde..9d12b253dd6 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -35,10 +35,7 @@ // Handler for pure virtual functions namespace __Crun { - static void pure_error(void) - { - assert("Pure virtual method called." == "Aborted"); - } + void pure_error(void); } // namespace __Crun #endif // __sun @@ -54,16 +51,7 @@ extern "C" { #else #include "kernelc.hpp" #endif - -/* Disallow inline __cxa_pure_virtual() */ -static int __cxa_pure_virtual() __attribute__((noinline, used)); -static int __cxa_pure_virtual() -{ - // oops, pure virtual called! - assert(!"Pure virtual method called. Aborted"); - return 0; -} - + int __cxa_pure_virtual () __attribute__ ((weak)); } // extern "C" #endif // __GNUC__ > 2 diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp index b2b42d3dcf0..63eff1d91fc 100644 --- a/extra/yassl/taocrypt/src/aes.cpp +++ b/extra/yassl/taocrypt/src/aes.cpp @@ -51,7 +51,7 @@ void AES::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } - else if (mode_ == CBC) + else if (mode_ == CBC) { if (dir_ == ENCRYPTION) while (blocks--) { r_[0] ^= *(word32*)in; @@ -78,6 +78,7 @@ void AES::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } + } } #endif // DO_AES_ASM diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index c221ce3d6cb..47a660d5c96 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -186,10 +186,10 @@ Integer AbstractGroup::CascadeScalarMultiply(const Element &x, struct WindowSlider { - WindowSlider(const Integer &exp, bool fastNegate, + WindowSlider(const Integer &expIn, bool fastNegateIn, unsigned int windowSizeIn=0) - : exp(exp), windowModulus(Integer::One()), windowSize(windowSizeIn), - windowBegin(0), fastNegate(fastNegate), firstTime(true), + : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), + windowBegin(0), fastNegate(fastNegateIn), firstTime(true), finished(false) { if (windowSize == 0) diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index 66ff4d829d7..2097b045278 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -53,7 +53,7 @@ void Blowfish::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } - else if (mode_ == CBC) + else if (mode_ == CBC) { if (dir_ == ENCRYPTION) while (blocks--) { r_[0] ^= *(word32*)in; @@ -78,6 +78,7 @@ void Blowfish::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } + } } #endif // DO_BLOWFISH_ASM diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 85733b88aa9..b054e98bef4 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -283,21 +283,23 @@ DWord() {} word GetHighHalfAsBorrow() const {return 0-halfs_.high;} private: + struct dword_struct + { + #ifdef LITTLE_ENDIAN_ORDER + word low; + word high; + #else + word high; + word low; + #endif + }; + union { #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE dword whole_; #endif - struct - { - #ifdef LITTLE_ENDIAN_ORDER - word low; - word high; - #else - word high; - word low; - #endif - } halfs_; + struct dword_struct halfs_; }; }; @@ -1214,20 +1216,24 @@ public: #define AS1(x) #x ";" #define AS2(x, y) #x ", " #y ";" #define AddPrologue \ + word res; \ __asm__ __volatile__ \ ( \ "push %%ebx;" /* save this manually, in case of -fPIC */ \ - "mov %2, %%ebx;" \ + "mov %3, %%ebx;" \ ".intel_syntax noprefix;" \ "push ebp;" #define AddEpilogue \ "pop ebp;" \ ".att_syntax prefix;" \ "pop %%ebx;" \ - : \ + "mov %%eax, %0;" \ + : "=g" (res) \ : "c" (C), "d" (A), "m" (B), "S" (N) \ : "%edi", "memory", "cc" \ - ); + ); \ + return res; + #define MulPrologue \ __asm__ __volatile__ \ ( \ diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 402645c93fd..11dd4dc6d66 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -84,12 +84,23 @@ namespace STL = STL_NAMESPACE; } -#if defined(__ICC) || defined(__INTEL_COMPILER) +#ifdef __sun + +// Handler for pure virtual functions +namespace __Crun { + void pure_error() { + assert(!"Aborted: pure virtual method called."); + } +} + +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) || (__GNUC__ > 2) extern "C" { int __cxa_pure_virtual() { - assert("Pure virtual method called." == "Aborted"); + assert(!"Aborted: pure virtual method called."); return 0; } @@ -166,14 +177,6 @@ word Crop(word value, unsigned int size) #ifdef TAOCRYPT_X86ASM_AVAILABLE -#ifndef _MSC_VER - static jmp_buf s_env; - static void SigIllHandler(int) - { - longjmp(s_env, 1); - } -#endif - bool HaveCpuId() { diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp index 84dd35f9191..71601c08162 100644 --- a/extra/yassl/taocrypt/src/twofish.cpp +++ b/extra/yassl/taocrypt/src/twofish.cpp @@ -54,7 +54,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } - else if (mode_ == CBC) + else if (mode_ == CBC) { if (dir_ == ENCRYPTION) while (blocks--) { r_[0] ^= *(word32*)in; @@ -82,6 +82,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } + } } #endif // DO_TWOFISH_ASM diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index c921f8f9c69..970ba5bf367 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -160,6 +160,11 @@ inline void err_sys(const char* msg) } +extern "C" { + static int PasswordCallBack(char*, int, int, void*); +} + + static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) { strncpy(passwd, "12345678", sz); diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index e2ef01b3b4c..c3922231047 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -57,7 +57,7 @@ SET(HEADERS ${HEADERS_GEN_CONFIGURE} ) -INSTALL(FILES ${HEADERS} DESTINATION ${INSTALL_INCLUDEDIR}) -INSTALL(DIRECTORY mysql/ DESTINATION ${INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h") +INSTALL(FILES ${HEADERS} DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT Development) +INSTALL(DIRECTORY mysql/ DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT Development FILES_MATCHING PATTERN "*.h" ) diff --git a/include/heap.h b/include/heap.h index 27aefb5beda..a585371e18f 100644 --- a/include/heap.h +++ b/include/heap.h @@ -184,12 +184,22 @@ typedef struct st_heap_info typedef struct st_heap_create_info { + HP_KEYDEF *keydef; + ulong max_records; + ulong min_records; uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; + uint keys; + uint reclength; ulonglong max_table_size; ulonglong auto_increment; my_bool with_auto_increment; my_bool internal_table; + /* + TRUE if heap_create should 'pin' the created share by setting + open_count to 1. Is only looked at if not internal_table. + */ + my_bool pin_share; } HP_CREATE_INFO; /* Prototypes for heap-functions */ @@ -197,6 +207,7 @@ typedef struct st_heap_create_info extern HP_INFO *heap_open(const char *name, int mode); extern HP_INFO *heap_open_from_share(HP_SHARE *share, int mode); extern HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode); +extern void heap_release_share(HP_SHARE *share, my_bool internal_table); extern int heap_close(HP_INFO *info); extern int heap_write(HP_INFO *info,const uchar *buff); extern int heap_update(HP_INFO *info,const uchar *old,const uchar *newdata); @@ -205,9 +216,9 @@ extern int heap_scan_init(HP_INFO *info); extern int heap_scan(register HP_INFO *info, uchar *record); extern int heap_delete(HP_INFO *info,const uchar *buff); extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); -extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, - uint reclength, ulong max_records, ulong min_records, - HP_CREATE_INFO *create_info, HP_SHARE **share); +extern int heap_create(const char *name, + HP_CREATE_INFO *create_info, HP_SHARE **share, + my_bool *created_new_share); extern int heap_delete_table(const char *name); extern void heap_drop_table(HP_INFO *info); extern int heap_extra(HP_INFO *info,enum ha_extra_function function); diff --git a/include/m_string.h b/include/m_string.h index 1a2a508edfb..2e443a87736 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -36,10 +36,6 @@ /* need by my_vsnprintf */ #include <stdarg.h> -#ifdef _AIX -#undef HAVE_BCMP -#endif - /* This is needed for the definitions of bzero... on solaris */ #if defined(HAVE_STRINGS_H) #include <strings.h> @@ -63,14 +59,10 @@ /* Unixware 7 */ #if !defined(HAVE_BFILL) # define bfill(A,B,C) memset((A),(C),(B)) -# define bmove_align(A,B,C) memcpy((A),(B),(C)) #endif -#if !defined(HAVE_BCMP) -# define bcopy(s, d, n) memcpy((d), (s), (n)) -# define bcmp(A,B,C) memcmp((A),(B),(C)) -# define bzero(A,B) memset((A),0,(B)) -# define bmove_align(A,B,C) memcpy((A),(B),(C)) +#if !defined(bzero) && !defined(HAVE_BZERO) +# define bzero(A,B) memset((A),0,(B)) #endif #if defined(__cplusplus) @@ -116,19 +108,6 @@ extern char NEAR _dig_vec_lower[]; extern void bfill(uchar *dst,size_t len,pchar fill); #endif -#if !defined(bzero) && !defined(HAVE_BZERO) -extern void bzero(uchar * dst,size_t len); -#endif - -#if !defined(bcmp) && !defined(HAVE_BCMP) -extern size_t bcmp(const uchar *s1,const uchar *s2,size_t len); -#endif -#ifdef HAVE_purify -extern size_t my_bcmp(const uchar *s1,const uchar *s2,size_t len); -#undef bcmp -#define bcmp(A,B,C) my_bcmp((A),(B),(C)) -#endif /* HAVE_purify */ - #ifndef bmove512 extern void bmove512(uchar *dst,const uchar *src,size_t len); #endif diff --git a/include/my_alarm.h b/include/my_alarm.h index dd2d5642f5f..fa396cf02f9 100644 --- a/include/my_alarm.h +++ b/include/my_alarm.h @@ -36,14 +36,14 @@ extern ulong my_time_to_wait_for_lock; #define ALARM_END (void) signal(SIGALRM,alarm_signal); \ (void) alarm(alarm_old); #define ALARM_TEST my_have_got_alarm -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY #define ALARM_REINIT (void) alarm(MY_HOW_OFTEN_TO_ALARM); \ (void) signal(SIGALRM,my_set_alarm_variable);\ my_have_got_alarm=0; #else #define ALARM_REINIT (void) alarm((uint) MY_HOW_OFTEN_TO_ALARM); \ my_have_got_alarm=0; -#endif /* DONT_REMEMBER_SIGNAL */ +#endif /* SIGNAL_HANDLER_RESET_ON_DELIVERY */ #else #define ALARM_VARIABLES long alarm_pos=0,alarm_end_pos=MY_HOW_OFTEN_TO_WRITE-1 #define ALARM_INIT diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 314dac983b0..0caf2da12d0 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -159,22 +159,6 @@ static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) #define bitmap_set_all(MAP) \ (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP)))) -/** - check, set and clear a bit of interest of an integer. - - If the bit is out of range @retval -1. Otherwise - bit_is_set @return 0 or 1 reflecting the bit is set or not; - bit_do_set @return 1 (bit is set 1) - bit_do_clear @return 0 (bit is cleared to 0) -*/ - -#define bit_is_set(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ - (((I) & (ULL(1) << (B))) == 0 ? 0 : 1) : -1) -#define bit_do_set(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ - ((I) |= (ULL(1) << (B)), 1) : -1) -#define bit_do_clear(I,B) (sizeof(I) * CHAR_BIT > (B) ? \ - ((I) &= ~(ULL(1) << (B)), 0) : -1) - #ifdef __cplusplus } #endif diff --git a/include/my_global.h b/include/my_global.h index 7b9c34cd724..d23bbbde576 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -627,26 +627,34 @@ extern "C" int madvise(void *addr, size_t len, int behav); #endif /* Does the system remember a signal handler after a signal ? */ -#ifndef HAVE_BSD_SIGNALS -#define DONT_REMEMBER_SIGNAL +#if !defined(HAVE_BSD_SIGNALS) && !defined(HAVE_SIGACTION) +#define SIGNAL_HANDLER_RESET_ON_DELIVERY #endif -#if defined(_lint) || defined(FORCE_INIT_OF_VARS) -#define LINT_INIT(var) var=0 /* No uninitialize-warning */ +/* + Deprecated workaround for false-positive uninitialized variables + warnings. Those should be silenced using tool-specific heuristics. + + Enabled by default for g++ due to the bug referenced below. +*/ +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || \ + (defined(__GNUC__) && defined(__cplusplus)) +#define LINT_INIT(var) var= 0 #else #define LINT_INIT(var) #endif -/* +/* Suppress uninitialized variable warning without generating code. The _cplusplus is a temporary workaround for C++ code pending a fix - for a g++ bug (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34772). + for a g++ bug (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34772). */ -#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(__cplusplus) || \ - !defined(__GNUC__) +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || \ + defined(__cplusplus) || !defined(__GNUC__) #define UNINIT_VAR(x) x= 0 #else +/* GCC specific self-initialization which inhibits the warning. */ #define UNINIT_VAR(x) x= x #endif @@ -670,7 +678,6 @@ typedef unsigned short ushort; #define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0) #define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0) #define test_all_bits(a,b) (((a) & (b)) == (b)) -#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) #define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) /* Define some general constants */ diff --git a/include/myisam.h b/include/myisam.h index d590a29c1b3..7547f6b475e 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -55,8 +55,6 @@ extern "C" { #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ #define MI_NAME_IEXT ".MYI" #define MI_NAME_DEXT ".MYD" -/* Max extra space to use when sorting keys */ -#define MI_MAX_TEMP_LENGTH 2*1024L*1024L*1024L /* Possible values for myisam_block_size (must be power of 2) */ #define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ diff --git a/include/thr_lock.h b/include/thr_lock.h index 1f4072ca0c5..37dc37f8017 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -54,12 +54,6 @@ enum thr_lock_type { TL_IGNORE=-1, */ TL_WRITE_ALLOW_WRITE, /* - Write lock, but allow other threads to read. - Used by ALTER TABLE in MySQL to allow readers - to use the table until ALTER TABLE is finished. - */ - TL_WRITE_ALLOW_READ, - /* WRITE lock used by concurrent insert. Will allow READ, if one could use concurrent insert on table. */ diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index cd23f825b9e..2ae09c1707a 100755..100644 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -152,7 +152,7 @@ SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES}) # Merge several convenience libraries into one big mysqlclient # and link them together into shared library. -MERGE_LIBRARIES(mysqlclient STATIC ${LIBS}) +MERGE_LIBRARIES(mysqlclient STATIC ${LIBS} COMPONENT Development) # Visual Studio users need debug static library for debug projects IF(MSVC) @@ -171,11 +171,11 @@ IF(UNIX) SET(${OUTNAME} ${LIBNAME}${EXTENSION}${DOT_VERSION}) ENDIF() ENDMACRO() - INSTALL_SYMLINK(${CMAKE_STATIC_LIBRARY_PREFIX}mysqlclient_r.a mysqlclient ${INSTALL_LIBDIR}) + INSTALL_SYMLINK(${CMAKE_STATIC_LIBRARY_PREFIX}mysqlclient_r.a mysqlclient ${INSTALL_LIBDIR} COMPONENT SharedLibraries) ENDIF() IF(NOT DISABLE_SHARED) - MERGE_LIBRARIES(libmysql SHARED ${LIBS} EXPORTS ${CLIENT_API_FUNCTIONS}) + MERGE_LIBRARIES(libmysql SHARED ${LIBS} EXPORTS ${CLIENT_API_FUNCTIONS} COMPONENT SharedLibraries) IF(UNIX) # libtool compatability IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR APPLE) @@ -209,7 +209,7 @@ IF(NOT DISABLE_SHARED) "${CMAKE_SHARED_LIBRARY_SUFFIX}" "" linkname) - INSTALL_SYMLINK(${linkname} libmysql ${INSTALL_LIBDIR}) + INSTALL_SYMLINK(${linkname} libmysql ${INSTALL_LIBDIR} COMPONENT SharedLibraries) SET(OS_SHARED_LIB_SYMLINKS "${SHARED_LIB_MAJOR_VERSION}" "${OS_SHARED_LIB_VERSION}") LIST(REMOVE_DUPLICATES OS_SHARED_LIB_SYMLINKS) FOREACH(ver ${OS_SHARED_LIB_SYMLINKS}) @@ -218,7 +218,7 @@ IF(NOT DISABLE_SHARED) "${CMAKE_SHARED_LIBRARY_SUFFIX}" "${ver}" linkname) - INSTALL_SYMLINK(${linkname} libmysql ${INSTALL_LIBDIR}) + INSTALL_SYMLINK(${linkname} libmysql ${INSTALL_LIBDIR} COMPONENT SharedLibraries) ENDFOREACH() ENDIF() ENDIF() diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 71a4fd867bd..7db0c7066a6 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -38,7 +38,7 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \ strmake.lo strend.lo \ strnlen.lo strfill.lo is_prefix.lo \ int2str.lo str2int.lo strinstr.lo strcont.lo \ - strcend.lo bcmp.lo ctype-latin1.lo \ + strcend.lo ctype-latin1.lo \ bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \ strtoull.lo strtoll.lo llstr.lo my_vsnprintf.lo \ ctype.lo ctype-simple.lo ctype-bin.lo ctype-mb.lo \ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 901fa1f0c4c..f2ad085405f 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -318,7 +318,7 @@ sig_handler my_pipe_sig_handler(int sig __attribute__((unused))) { DBUG_PRINT("info",("Hit by signal %d",sig)); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY (void) signal(SIGPIPE, my_pipe_sig_handler); #endif } @@ -2127,7 +2127,12 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) stmt->insert_id= mysql->insert_id; if (res) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2338,7 +2343,12 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) buff, sizeof(buff), (uchar*) 0, 0, 1, stmt)) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); return 1; } if ((*mysql->methods->read_rows_from_cursor)(stmt)) @@ -3025,7 +3035,12 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, buff, sizeof(buff), (uchar*) data, length, 1, stmt)) { - set_stmt_errmsg(stmt, &mysql->net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } } @@ -4440,7 +4455,12 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), (uchar*) 0, 0, 1, stmt)) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } } diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index fa5088f288b..6f553ef9c11 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -63,7 +63,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/sql_class.cc ../sql/sql_crypt.cc ../sql/sql_cursor.cc ../sql/sql_db.cc ../sql/sql_delete.cc ../sql/sql_derived.cc ../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.cc - ../sql/sql_help.cc ../sql/sql_insert.cc + ../sql/sql_help.cc ../sql/sql_insert.cc ../sql/datadict.cc + ../sql/sql_truncate.cc ../sql/sql_lex.cc ../sql/keycaches.cc ../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc ../sql/sql_binlog.cc ../sql/sql_manager.cc ../sql/sql_map.cc @@ -124,7 +125,7 @@ FOREACH(LIB ${LIBS}) ENDFOREACH() MERGE_LIBRARIES(mysqlserver STATIC ${EMBEDDED_LIBS} - OUTPUT_NAME ${MYSQLSERVER_OUTPUT_NAME}) + OUTPUT_NAME ${MYSQLSERVER_OUTPUT_NAME} COMPONENT Embedded) # Visual Studio users need debug static library IF(MSVC) @@ -137,5 +138,6 @@ IF(UNIX) ENDIF() IF(MSVC AND NOT DISABLE_SHARED) - MERGE_LIBRARIES(libmysqld SHARED ${LIBS} EXPORTS ${CLIENT_API_FUNCTIONS}) + MERGE_LIBRARIES(libmysqld SHARED ${LIBS} EXPORTS ${CLIENT_API_FUNCTIONS} + COMPONENT Embedded) ENDIF() diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 5ff23be42ba..3519c6e2541 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -63,7 +63,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ protocol.cc net_serv.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ sql_load.cc discover.cc sql_locale.cc \ - sql_profile.cc \ + sql_profile.cc sql_truncate.cc datadict.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index e727122293c..b36a97759d2 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -634,7 +634,6 @@ void *create_embedded_thd(int client_flag) thd->variables.option_bits |= OPTION_BIG_SELECTS; thd->proc_info=0; // Remove 'login' thd->command=COM_SLEEP; - thd->version=refresh_version; thd->set_time(); thd->init_for_queries(); thd->client_capabilities= client_flag; diff --git a/mysql-test/CMakeLists.txt b/mysql-test/CMakeLists.txt index b309db292da..9745699b61d 100644 --- a/mysql-test/CMakeLists.txt +++ b/mysql-test/CMakeLists.txt @@ -16,6 +16,7 @@ INSTALL( DIRECTORY . DESTINATION ${INSTALL_MYSQLTESTDIR} + COMPONENT Test PATTERN "var/" EXCLUDE PATTERN "lib/My/SafeProcess" EXCLUDE PATTERN "lib/t*" EXCLUDE diff --git a/mysql-test/extra/binlog_tests/binlog_truncate.test b/mysql-test/extra/binlog_tests/binlog_truncate.test index dce33b3cef0..24cf363f780 100644 --- a/mysql-test/extra/binlog_tests/binlog_truncate.test +++ b/mysql-test/extra/binlog_tests/binlog_truncate.test @@ -25,3 +25,44 @@ TRUNCATE TABLE t2; source include/show_binlog_events.inc; DROP TABLE t1,t2; + +--echo # +--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +--echo # + +eval CREATE TABLE t1 (a INT) ENGINE=$engine; +eval CREATE TABLE t2 (a INT) ENGINE=$engine; +INSERT INTO t1 VALUES (1),(2); + +let $binlog_start = query_get_value("SHOW MASTER STATUS", Position, 1); +if (`select length('$before_truncate') > 0`) { + eval $before_truncate; +} + +--echo # Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; + +connect (truncate,localhost,root,,); +--echo # Connection: truncate +send TRUNCATE TABLE t1; + +connection default; +--echo # Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COMMIT; + +connection truncate; +--echo # Connection: truncate +--echo # Reaping TRUNCATE TABLE +--reap +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; + +connection default; +--echo # Connection: default + +source include/show_binlog_events.inc; +disconnect truncate; +DROP TABLE t1,t2; diff --git a/mysql-test/include/check_concurrent_insert.inc b/mysql-test/include/check_concurrent_insert.inc index 6a9ada65562..f4bec3c9cdb 100644 --- a/mysql-test/include/check_concurrent_insert.inc +++ b/mysql-test/include/check_concurrent_insert.inc @@ -10,9 +10,9 @@ # $con_aux2 Name of the second auxiliary connection to be used by this # script. # $statement Statement to be checked. -# $restore_table Table which might be modified affected by statement to be -# checked and thus needs backing up before its execution -# and restoring after it (can be empty). +# $restore_table Table which might be modified by statement to be checked +# and thus needs backing up before its execution and +# restoring after it (can be empty). # # EXAMPLE # lock_sync.test @@ -25,7 +25,7 @@ set debug_sync= "RESET"; if (`SELECT '$restore_table' <> ''`) { ---eval create table t_backup select * from $restore_table; +--eval create temporary table t_backup select * from $restore_table; } connection $con_aux1; @@ -34,19 +34,19 @@ set debug_sync='after_lock_tables_takes_lock SIGNAL parked WAIT_FOR go'; connection $con_aux2; set debug_sync='now WAIT_FOR parked'; ---send_eval insert into $table values (0); +--send_eval insert into $table (i) values (0); --enable_result_log --enable_query_log connection default; # Wait until concurrent insert is successfully executed while # statement being checked has its tables locked. -# We use wait_condition.inc instead of simply executing +# We use wait_condition.inc instead of simply reaping # concurrent insert here in order to avoid deadlocks if test -# fails and timing out instead. +# fails and to time out gracefully instead. let $wait_condition= select count(*) = 0 from information_schema.processlist - where info = "insert into $table values (0)"; + where info = "insert into $table (i) values (0)"; --source include/wait_condition.inc --disable_result_log @@ -86,7 +86,7 @@ if (`SELECT '$restore_table' <> ''`) { --eval truncate table $restore_table; --eval insert into $restore_table select * from t_backup; -drop table t_backup; +drop temporary table t_backup; } # Clean-up. Reset DEBUG_SYNC facility after use. diff --git a/mysql-test/include/check_no_concurrent_insert.inc b/mysql-test/include/check_no_concurrent_insert.inc index 278ffeffb1e..57772dddefc 100644 --- a/mysql-test/include/check_no_concurrent_insert.inc +++ b/mysql-test/include/check_no_concurrent_insert.inc @@ -10,9 +10,9 @@ # $con_aux2 Name of the second auxiliary connection to be used by this # script. # $statement Statement to be checked. -# $restore_table Table which might be modified affected by statement to be -# checked and thus needs backing up before its execution -# and restoring after it (can be empty). +# $restore_table Table which might be modified by statement to be checked +# and thus needs backing up before its execution and +# restoring after it (can be empty). # # EXAMPLE # lock_sync.test @@ -25,7 +25,7 @@ set debug_sync= "RESET"; if (`SELECT '$restore_table' <> ''`) { ---eval create table t_backup select * from $restore_table; +--eval create temporary table t_backup select * from $restore_table; } connection $con_aux1; @@ -34,7 +34,7 @@ set debug_sync='after_lock_tables_takes_lock SIGNAL parked WAIT_FOR go'; connection $con_aux2; set debug_sync='now WAIT_FOR parked'; ---send_eval insert into $table values (0); +--send_eval insert into $table (i) values (0); --enable_result_log --enable_query_log @@ -43,7 +43,7 @@ connection default; # of our statement. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Table lock" and info = "insert into $table values (0)"; + where state = "Table lock" and info = "insert into $table (i) values (0)"; --source include/wait_condition.inc --disable_result_log @@ -71,7 +71,7 @@ if (`SELECT '$restore_table' <> ''`) { --eval truncate table $restore_table; --eval insert into $restore_table select * from t_backup; -drop table t_backup; +drop temporary table t_backup; } # Clean-up. Reset DEBUG_SYNC facility after use. diff --git a/mysql-test/include/check_no_row_lock.inc b/mysql-test/include/check_no_row_lock.inc index 958161b9b7f..c08e7f35b10 100644 --- a/mysql-test/include/check_no_row_lock.inc +++ b/mysql-test/include/check_no_row_lock.inc @@ -29,9 +29,9 @@ connection default; # Wait until statement is successfully executed while # all rows in table are X-locked. This means that it # does not acquire any row locks. -# We use wait_condition.inc instead of simply executing +# We use wait_condition.inc instead of simply reaping # statement here in order to avoid deadlocks if test -# fails and timing out instead. +# fails and to time out gracefully instead. let $wait_condition= select count(*) = 0 from information_schema.processlist where info = "$statement"; diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc index ad42615511a..d6216f3fe1e 100644 --- a/mysql-test/include/diff_tables.inc +++ b/mysql-test/include/diff_tables.inc @@ -65,17 +65,13 @@ let $_diff_table=$diff_table_2; let $_diff_i=2; while ($_diff_i) { - # Parse out any leading "master:" or "slave:" from the table - # specification and connect the appropriate server. - let $_diff_conn_master=`SELECT SUBSTR('$_diff_table', 1, 7) = 'master:'`; - if ($_diff_conn_master) { - let $_diff_table=`SELECT SUBSTR('$_diff_table', 8)`; - connection master; - } - let $_diff_conn_slave=`SELECT SUBSTR('$_diff_table', 1, 6) = 'slave:'`; - if ($_diff_conn_slave) { - let $_diff_table=`SELECT SUBSTR('$_diff_table', 7)`; - connection slave; + # Parse out any leading "master:" or "slave:" from the table specification +# and connect the appropriate server. + let $_pos= `SELECT LOCATE(':', '$_diff_table')`; + let $_diff_conn=`SELECT SUBSTR('$_diff_table', 1, $_pos-1)`; + if (`SELECT 'XX$_diff_conn' <> 'XX'`) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', $_pos+1)`; + connection $_diff_conn; } # Sanity-check the input. diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 66648aaf1bf..fe6abe13892 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1351,6 +1351,13 @@ connection con1; SELECT * FROM t1; ROLLBACK; +--echo # Switch to connection con2 +connection con2; +ROLLBACK; + +--echo # Switch to connection con1 +connection con1; + --echo # 2. test for serialized update: CREATE TABLE t2 (a INT); @@ -1435,6 +1442,7 @@ connection con2; --reap SELECT * FROM t1; +--enable_abort_on_error connection default; disconnect con1; disconnect con2; @@ -1556,3 +1564,36 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1) DROP TABLE t1; --echo End of 5.1 tests + +--echo # +--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +--echo # +--echo # Check that a TRUNCATE TABLE statement, needing an exclusive meta +--echo # data lock, waits for a shared metadata lock owned by a concurrent +--echo # transaction. +--echo # + +eval CREATE TABLE t1 (a INT) ENGINE=$engine_type; +INSERT INTO t1 VALUES (1),(2),(3); +BEGIN; +SELECT * FROM t1 ORDER BY a; +--echo # Connection con1 +connect (con1, localhost, root,,); +--send TRUNCATE TABLE t1; +--echo # Connection default +connection default; +let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist + WHERE state='Waiting for table' AND info='TRUNCATE TABLE t1'; +--source include/wait_condition.inc +SELECT * FROM t1 ORDER BY a; +ROLLBACK; +--echo # Connection con1 +connection con1; +--echo # Reaping TRUNCATE TABLE +--reap +SELECT * FROM t1; +--echo # Disconnect con1 +disconnect con1; +--echo # Connection default +connection default; +DROP TABLE t1; diff --git a/mysql-test/include/parser_bug21114.inc b/mysql-test/include/parser_bug21114.inc index eb709d5cc03..eb709d5cc03 100755..100644 --- a/mysql-test/include/parser_bug21114.inc +++ b/mysql-test/include/parser_bug21114.inc diff --git a/mysql-test/include/rpl_diff_tables.inc b/mysql-test/include/rpl_diff_tables.inc new file mode 100644 index 00000000000..c3a45578a79 --- /dev/null +++ b/mysql-test/include/rpl_diff_tables.inc @@ -0,0 +1,35 @@ +# ############################################################################# +# Check whether the given table is consistent between different master and +# slaves +# +# Usage: +# --let $diff_table= test.t1 +# --let $diff_server_list= master, slave, slave2 +# --source include/rpl_diff_tables.inc +# ############################################################################# + +if (`SELECT "XX$diff_table" = "XX"`) +{ + --die diff_table is null. +} + +--let $_servers= master, slave +if (`SELECT "XX$diff_server_list" <> "XX"`) +{ + --let $_servers= $diff_server_list +} + +--let $_master= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` +--let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_master') + 2))` +connection $_master; +while (`SELECT "XX$_servers" <> "XX"`) +{ + --let $_slave= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` + --let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_slave') + 2))` + + --sync_slave_with_master $_slave + --let $diff_table_1= $_master:$diff_table + --let $diff_table_2= $_slave:$diff_table + --source include/diff_tables.inc + connection $_slave; +} diff --git a/mysql-test/include/show_msg.inc b/mysql-test/include/show_msg.inc index 659dce14686..659dce14686 100755..100644 --- a/mysql-test/include/show_msg.inc +++ b/mysql-test/include/show_msg.inc diff --git a/mysql-test/include/show_msg80.inc b/mysql-test/include/show_msg80.inc index 42fb35edbcc..42fb35edbcc 100755..100644 --- a/mysql-test/include/show_msg80.inc +++ b/mysql-test/include/show_msg80.inc diff --git a/mysql-test/lib/My/Handles.pm b/mysql-test/lib/My/Handles.pm index 66ee22b403f..66ee22b403f 100755..100644 --- a/mysql-test/lib/My/Handles.pm +++ b/mysql-test/lib/My/Handles.pm diff --git a/mysql-test/lib/My/SafeProcess/CMakeLists.txt b/mysql-test/lib/My/SafeProcess/CMakeLists.txt index 893e6d896be..f79c2d450b9 100644 --- a/mysql-test/lib/My/SafeProcess/CMakeLists.txt +++ b/mysql-test/lib/My/SafeProcess/CMakeLists.txt @@ -13,15 +13,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +SET(INSTALL_ARGS + DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess" + COMPONENT Test +) + IF (WIN32) - ADD_EXECUTABLE(my_safe_process safe_process_win.cc) - ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc) + MYSQL_ADD_EXECUTABLE(my_safe_process safe_process_win.cc ${INSTALL_ARGS}) + MYSQL_ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc ${INSTALL_ARGS}) ELSE() - ADD_EXECUTABLE(my_safe_process safe_process.cc) + MYSQL_ADD_EXECUTABLE(my_safe_process safe_process.cc ${INSTALL_ARGS}) ENDIF() -INSTALL(TARGETS my_safe_process DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess") +INSTALL(TARGETS my_safe_process DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess" COMPONENT Test) IF(WIN32) - INSTALL(TARGETS my_safe_kill DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess") + INSTALL(TARGETS my_safe_kill DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess" COMPONENT Test) ENDIF() -INSTALL(FILES safe_process.pl Base.pm DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess") +INSTALL(FILES safe_process.pl Base.pm DESTINATION "${INSTALL_MYSQLTESTDIR}/lib/My/SafeProcess" COMPONENT Test) diff --git a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc index f72b851d0b6..f72b851d0b6 100755..100644 --- a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc index 50c433b9b39..1c778362975 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process.cc @@ -159,7 +159,7 @@ int main(int argc, char* const argv[] ) signal(SIGCHLD, handle_signal); signal(SIGABRT, handle_abort); - sprintf(safe_process_name, "safe_process[%d]", own_pid); + sprintf(safe_process_name, "safe_process[%ld]", (long) own_pid); message("Started"); diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 8fffede0b62..8fffede0b62 100755..100644 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 4039825be55..29626e38396 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -41,6 +41,12 @@ our $opt_with_ndbcluster_only; our $defaults_file; our $defaults_extra_file; our $quick_collect; +# Set to 1 if you want the tests to override +# default storage engine settings, and use MyISAM +# as default. (temporary option used in connection +# with the change of default storage engine to InnoDB) +our $default_myisam= 1; + sub collect_option { my ($opt, $value)= @_; @@ -591,6 +597,9 @@ sub optimize_cases { my $default_engine= mtr_match_prefix($opt, "--default-storage-engine="); + # Allow use of uppercase, convert to all lower case + $default_engine =~ tr/A-Z/a-z/; + if (defined $default_engine){ #print " $tinfo->{name}\n"; @@ -948,10 +957,12 @@ sub collect_one_test_case { return $tinfo unless $do_innodb_plugin; } } - else + elsif ($default_myisam) { - push(@{$tinfo->{'master_opt'}}, "--loose-skip-innodb"); - push(@{$tinfo->{'slave_opt'}}, "--loose-skip-innodb"); + # This is a temporary fix to allow non-innodb tests to run even if + # the default storage engine is innodb. + push(@{$tinfo->{'master_opt'}}, "--default-storage-engine=MyISAM"); + push(@{$tinfo->{'slave_opt'}}, "--default-storage-engine=MyISAM"); } if ( $tinfo->{'need_binlog'} ) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 23a92828e2a..acb5fa3ed0f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -944,6 +944,7 @@ sub command_line_setup { 'timestamp' => \&report_option, 'timediff' => \&report_option, 'max-connections=i' => \$opt_max_connections, + 'default-myisam!' => \&collect_option, 'help|h' => \$opt_usage, 'list-options' => \$opt_list_options, @@ -2843,7 +2844,6 @@ sub mysql_install_db { mtr_add_arg($args, "--bootstrap"); mtr_add_arg($args, "--basedir=%s", $install_basedir); mtr_add_arg($args, "--datadir=%s", $install_datadir); - mtr_add_arg($args, "--loose-innodb=OFF"); mtr_add_arg($args, "--loose-skip-falcon"); mtr_add_arg($args, "--loose-skip-ndbcluster"); mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/"); @@ -5560,7 +5560,9 @@ Misc options timediff With --timestamp, also print time passed since *previous* test started max-connections=N Max number of open connection to server in mysqltest - + default-myisam Set default storage engine to MyISAM for non-innodb + tests. This is needed after switching default storage + engine to InnoDB. HERE exit(1); diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 88f38a13b4a..685e1e5ba4b 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12749,6 +12749,14 @@ ERROR HY000: Can't find file: 't1' (errno: 2) DROP TABLE t1; ERROR 42S02: Unknown table 't1' # +# Ensure that TRUNCATE fails for non-empty archive tables. +# +CREATE TABLE t1 (a INT) ENGINE=ARCHIVE; +INSERT INTO t1 VALUES (1); +TRUNCATE TABLE t1; +ERROR HY000: Table storage engine for 't1' doesn't have this option +DROP TABLE t1; +# # BUG#46565 - repair of partition fail for archive engine # # Installing corrupted table files for t1. diff --git a/mysql-test/r/bug46080.result b/mysql-test/r/bug46080.result index 44f6bba8db6..44f6bba8db6 100755..100644 --- a/mysql-test/r/bug46080.result +++ b/mysql-test/r/bug46080.result diff --git a/mysql-test/r/bug46760.result b/mysql-test/r/bug46760.result index 413df050b10..46b8c23b95c 100644 --- a/mysql-test/r/bug46760.result +++ b/mysql-test/r/bug46760.result @@ -25,7 +25,7 @@ DROP TABLE t1; # MySQL Bug#39200: optimize table does not recognize # ROW_FORMAT=COMPRESSED # -CREATE TABLE t1 (a INT) ROW_FORMAT=compressed; +CREATE TABLE t1 (a INT) ROW_FORMAT=compressed, ENGINE=MyISAM; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/commit.result b/mysql-test/r/commit.result new file mode 100644 index 00000000000..8620d2077c6 --- /dev/null +++ b/mysql-test/r/commit.result @@ -0,0 +1,272 @@ +# +# Bug#20837 Apparent change of isolation level +# during transaction +# +# Bug#53343 completion_type=1, COMMIT/ROLLBACK +# AND CHAIN don't preserve the isolation +# level +connection default; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; +START TRANSACTION; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +ERROR 25001: Transaction isolation level can't be changed while a transaction is in progress +COMMIT; +SET @@autocommit=0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT @@tx_isolation; +@@tx_isolation +REPEATABLE-READ +Should be REPEATABLE READ +SELECT * FROM t1; +s1 +1 +2 +SELECT @@tx_isolation; +@@tx_isolation +REPEATABLE-READ +Should be REPEATABLE READ +INSERT INTO t1 VALUES (-1); +SELECT @@tx_isolation; +@@tx_isolation +REPEATABLE-READ +Should be REPEATABLE READ +COMMIT; +START TRANSACTION; +SELECT * FROM t1; +s1 +1 +2 +-1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1000); +COMMIT; +connection default +We should not be able to read the '1000' +SELECT * FROM t1; +s1 +1 +2 +-1 +COMMIT; +Now, the '1000' should appear. +START TRANSACTION; +SELECT * FROM t1; +s1 +1 +2 +-1 +1000 +COMMIT; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +connection default +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; +connection default +SELECT COUNT(*) FROM t1 WHERE s1 = 1001; +COUNT(*) +1 +Should be 1 +COMMIT AND CHAIN; +connection con1 +INSERT INTO t1 VALUES (1002); +COMMIT; +connection default +SELECT COUNT(*) FROM t1 WHERE s1 = 1002; +COUNT(*) +1 +Should be 1 +COMMIT; +SELECT * FROM t1; +s1 +1 +2 +-1 +1000 +1001 +1002 +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; +connection default +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; +connection default +SELECT COUNT(*) FROM t1 WHERE s1 = 1001; +COUNT(*) +1 +Should be 1 +ROLLBACK AND CHAIN; +connection con1 +INSERT INTO t1 VALUES (1002); +COMMIT; +connection default +SELECT COUNT(*) FROM t1 WHERE s1 = 1002; +COUNT(*) +1 +Should be 1 +COMMIT; +SELECT * FROM t1; +s1 +1 +2 +-1 +1001 +1002 +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; +SET @@completion_type=1; +connection default +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +Should see 1001 +COMMIT AND NO CHAIN; +default transaction is now in REPEATABLE READ +connection con1 +INSERT INTO t1 VALUES (1002); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +1002 +Should see 1001 and 1002 +connection con1 +INSERT INTO t1 VALUES (1003); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +1002 +Should see 1001 and 1002, but NOT 1003 +COMMIT; +SELECT * FROM t1; +s1 +1 +2 +-1 +1001 +1002 +1003 +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT AND NO CHAIN; +SET @@completion_type=0; +COMMIT; +connection default +SET @@completion_type=1; +COMMIT AND NO CHAIN; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +Should see 1001 +ROLLBACK AND NO CHAIN; +default transaction is now in REPEATABLE READ +connection con1 +INSERT INTO t1 VALUES (1002); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +1002 +Should see 1001 and 1002 +connection con1 +INSERT INTO t1 VALUES (1003); +COMMIT; +connection default +SELECT * FROM t1 WHERE s1 >= 1000; +s1 +1001 +1002 +Should see 1001 and 1002, but NOT 1003 +COMMIT; +SELECT * FROM t1; +s1 +1 +2 +-1 +1001 +1002 +1003 +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT AND NO CHAIN; +SET @@completion_type=0; +COMMIT; +connection default +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +START TRANSACTION; +SELECT * FROM t1; +s1 +1 +2 +-1 +connection con1 +INSERT INTO t1 VALUES (1000); +COMMIT; +connection default +SELECT * FROM t1; +s1 +1 +2 +-1 +Should get same result as above (i.e should not read '1000') +COMMIT; +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; +SET @@completion_type=1; +COMMIT AND NO CHAIN; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES (1000); +SELECT * FROM t1; +s1 +1000 +Should read '1000' +connection con1 +INSERT INTO t1 VALUES (1001); +COMMIT; +connection default +SELECT * FROM t1; +s1 +1000 +Should only read the '1000' as this transaction is now in REP READ +COMMIT AND NO CHAIN; +SET @@completion_type=0; +COMMIT AND NO CHAIN; +SET @autocommit=1; +COMMIT; +DROP TABLE t1; +# +# End of test cases for Bug#20837 +# diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e37f9d580ba..fce775c5952 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -99,6 +99,14 @@ create table t1 (`` int); ERROR 42000: Incorrect column name '' create table t1 (i int, index `` (i)); ERROR 42000: Incorrect index name '' +create table t1 (i int); +lock tables t1 read; +create table t2 (j int); +ERROR HY000: Table 't2' was not locked with LOCK TABLES +create temporary table t2 (j int); +drop temporary table t2; +unlock tables; +drop table t1; create table t1 (a int auto_increment not null primary key, B CHAR(20)); insert into t1 (b) values ("hello"),("my"),("world"); create table t2 (key (b)) select * from t1; @@ -377,6 +385,17 @@ ERROR 42S01: Table 't3' already exists drop table t1, t2, t3; drop table t3; drop database mysqltest; +create table t1 (i int); +create table t2 (j int); +lock tables t1 read; +create table t3 like t1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +create temporary table t3 like t1; +drop temporary table t3; +create temporary table t3 like t2; +ERROR HY000: Table 't2' was not locked with LOCK TABLES +unlock tables; +drop tables t1, t2; SET SESSION storage_engine="heap"; SELECT @@storage_engine; @@storage_engine @@ -2033,3 +2052,39 @@ ID 3 DROP TABLE t1; DROP TEMPORARY TABLE t2; +# +# Bug #22909 "Using CREATE ... LIKE is possible to create field +# with invalid default value" +# +# Altough original bug report suggests to use older version of MySQL +# for producing .FRM with invalid defaults we use sql_mode to achieve +# the same effect. +drop tables if exists t1, t2; +# Attempt to create table with invalid default should fail in normal mode +create table t1 (dt datetime default '2008-02-31 00:00:00'); +ERROR 42000: Invalid default value for 'dt' +set @old_mode= @@sql_mode; +set @@sql_mode='ALLOW_INVALID_DATES'; +# The same should be possible in relaxed mode +create table t1 (dt datetime default '2008-02-31 00:00:00'); +set @@sql_mode= @old_mode; +# In normal mode attempt to create copy of table with invalid +# default should fail +create table t2 like t1; +ERROR 42000: Invalid default value for 'dt' +set @@sql_mode='ALLOW_INVALID_DATES'; +# But should work in relaxed mode +create table t2 like t1; +# Check that table definitions match +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dt` datetime DEFAULT '2008-02-31 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `dt` datetime DEFAULT '2008-02-31 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +set @@sql_mode= @old_mode; +drop tables t1, t2; diff --git a/mysql-test/r/ctype_eucjpms.result b/mysql-test/r/ctype_eucjpms.result index bd25b1beed4..bd25b1beed4 100755..100644 --- a/mysql-test/r/ctype_eucjpms.result +++ b/mysql-test/r/ctype_eucjpms.result diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index 17ec2b09a0a..f1712a650b1 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -157,3 +157,13 @@ Error 1051 Unknown table 't1' # -- # -- End of Bug#37431. # -- +# +# Bug#54282 Crash in MDL_context::upgrade_shared_lock_to_exclusive +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT); +LOCK TABLE t1 WRITE; +DROP TABLE t1, t1; +ERROR 42000: Not unique table/alias: 't1' +UNLOCK TABLES; +DROP TABLE t1; diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result index fc58687cc86..b6b79cb596b 100644 --- a/mysql-test/r/error_simulation.result +++ b/mysql-test/r/error_simulation.result @@ -48,5 +48,40 @@ Got one of the listed errors SET SESSION debug=DEFAULT; DROP TABLE t1; # +# Bug#41660: Sort-index_merge for non-first join table may require +# O(#scans) memory +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); +CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b)); +INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C; +INSERT INTO t2 VALUES (1, 1, 'data'); +# the example query uses LEFT JOIN only for the sake of being able to +# demonstrate the issue with a very small dataset. (left outer join +# disables the use of join buffering, so we get the second table +# re-scanned for every record in the outer table. if we used inner join, +# we would need to have thousands of records and/or more columns in both +# tables so that the join buffer is filled and re-scans are triggered). +SET SESSION debug = '+d,only_one_Unique_may_be_created'; +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +id select_type table type possible_keys key key_len ref rows Extra +x x x x x x x x x +x x x x x x x x x Using sort_union(a,b); Using where +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +a a b filler +0 1 1 data +1 1 1 data +2 1 1 data +3 1 1 data +4 1 1 data +5 1 1 data +6 1 1 data +7 1 1 data +8 1 1 data +9 1 1 data +SET SESSION debug = DEFAULT; +DROP TABLE t1, t2; +# # End of 5.1 tests # diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index ffdacc43735..fdeec2755ca 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -750,4 +750,24 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables DROP TABLE t1; # +# Bug#54477: Crash on IN / CASE with NULL arguments +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT 1 IN (NULL, a) FROM t1; +1 IN (NULL, a) +1 +NULL +SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP; +a IN (a, a) +1 +1 +NULL +SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP; +CASE a WHEN a THEN a END +1 +2 +NULL +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result index 8d0f34f3bda..552ff564a89 100644 --- a/mysql-test/r/func_like.result +++ b/mysql-test/r/func_like.result @@ -169,3 +169,17 @@ select 'andre%' like 'andreÊ%' escape 'Ê'; select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'; _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê' 1 +End of 4.1 tests +# +# Bug #54575: crash when joining tables with unique set column +# +CREATE TABLE t1(a SET('a') NOT NULL, UNIQUE KEY(a)); +CREATE TABLE t2(b INT PRIMARY KEY); +INSERT INTO t1 VALUES (); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +INSERT INTO t2 VALUES (1), (2), (3); +SELECT 1 FROM t2 JOIN t1 ON 1 LIKE a GROUP BY a; +1 +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 86fa9d76864..2d5751843e8 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1681,6 +1681,16 @@ COUNT(*) DROP USER nonpriv; DROP TABLE db1.t1; DROP DATABASE db1; + +Bug#54422 query with = 'variables' + +CREATE TABLE variables(f1 INT); +SELECT COLUMN_DEFAULT, TABLE_NAME +FROM INFORMATION_SCHEMA.COLUMNS +WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = 'variables'; +COLUMN_DEFAULT TABLE_NAME +NULL variables +DROP TABLE variables; End of 5.1 tests. # # Additional test for WL#3726 "DDL locking for all metadata objects" diff --git a/mysql-test/r/innodb_mysql_lock2.result b/mysql-test/r/innodb_mysql_lock2.result index aed704e6b3e..17dd747de6f 100644 --- a/mysql-test/r/innodb_mysql_lock2.result +++ b/mysql-test/r/innodb_mysql_lock2.result @@ -178,8 +178,7 @@ end| # 1.1 Simple SELECT statement. # # No locks are necessary as this statement won't be written -# to the binary log and thanks to how MyISAM works SELECT -# will see version of the table prior to concurrent insert. +# to the binary log and InnoDB supports snapshots. Success: 'select * from t1' doesn't take row locks on 't1'. # # 1.2 Multi-UPDATE statement. @@ -484,7 +483,7 @@ Success: 'insert into t2 values (f13((select i+10 from t1 where i=1)))' takes sh # row locks on the data it reads. Success: 'call p2(@a)' doesn't take row locks on 't1'. # -# 5.2 Function that modifes data and uses CALL, +# 5.2 Function that modifies data and uses CALL, # which reads a table through SELECT. # # Since a call to such function is written to the binary @@ -562,3 +561,68 @@ drop view v1, v2; drop procedure p1; drop procedure p2; drop table t1, t2, t3, t4, t5; +# +# Test for bug#51263 "Deadlock between transactional SELECT +# and ALTER TABLE ... REBUILD PARTITION". +# +drop table if exists t1, t2; +create table t1 (i int auto_increment not null primary key) engine=innodb; +create table t2 (i int) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5); +begin; +# Acquire SR metadata lock on t1 and LOCK_S row-locks on its rows. +insert into t2 select count(*) from t1; +# Switching to connection 'con1'. +# Sending: +alter table t1 add column j int; +# Switching to connection 'default'. +# Wait until ALTER is blocked because it tries to upgrade SNW +# metadata lock to X lock. +# It should not be blocked during copying data to new version of +# table as it acquires LOCK_S locks on rows of old version, which +# are compatible with locks acquired by connection 'con1'. +# The below statement will deadlock because it will try to acquire +# SW lock on t1, which will conflict with ALTER's SNW lock. And +# ALTER will be waiting for this connection to release its SR lock. +# This deadlock should be detected by an MDL subsystem and this +# statement should be aborted with an appropriate error. +insert into t1 values (6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +# Unblock ALTER TABLE. +commit; +# Switching to connection 'con1'. +# Reaping ALTER TABLE. +# Switching to connection 'default'. +# +# Now test for scenario in which bug was reported originally. +# +drop tables t1, t2; +create table t1 (i int auto_increment not null primary key) engine=innodb +partition by hash (i) partitions 4; +create table t2 (i int) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5); +begin; +# Acquire SR metadata lock on t1. +select * from t1; +i +1 +2 +3 +4 +5 +# Switching to connection 'con1'. +# Sending: +alter table t1 rebuild partition p0; +# Switching to connection 'default'. +# Wait until ALTER is blocked because of active SR lock. +# The below statement should succeed as transaction +# has SR metadata lock on t1 and only going to read +# rows from it. +insert into t2 select count(*) from t1; +# Unblock ALTER TABLE. +commit; +# Switching to connection 'con1'. +# Reaping ALTER TABLE. +# Switching to connection 'default'. +# Clean-up. +drop tables t1, t2; diff --git a/mysql-test/r/lock_sync.result b/mysql-test/r/lock_sync.result index e6265f1cb5e..3682f0df26a 100644 --- a/mysql-test/r/lock_sync.result +++ b/mysql-test/r/lock_sync.result @@ -511,7 +511,7 @@ Success: 'insert into t2 values (f13((select i+10 from t1 where i=1)))' doesn't # strong locks on the data it reads. Success: 'call p2(@a)' allows concurrent inserts into 't1'. # -# 5.2 Function that modifes data and uses CALL, +# 5.2 Function that modifies data and uses CALL, # which reads a table through SELECT. # # Since a call to such function is written to the binary diff --git a/mysql-test/r/lowercase_mixed_tmpdir_innodb.result b/mysql-test/r/lowercase_mixed_tmpdir_innodb.result index a478b49cfda..a478b49cfda 100755..100644 --- a/mysql-test/r/lowercase_mixed_tmpdir_innodb.result +++ b/mysql-test/r/lowercase_mixed_tmpdir_innodb.result diff --git a/mysql-test/r/mdl_sync.result b/mysql-test/r/mdl_sync.result index b78b8dadc77..67d778211dd 100644 --- a/mysql-test/r/mdl_sync.result +++ b/mysql-test/r/mdl_sync.result @@ -330,9 +330,9 @@ select column_name from information_schema.columns where table_schema='test' and table_name='t1'; column_name c1 -select count(*) from t1; -count(*) -4 +# Disable result log to make test robust against +# effects of concurrent insert. +select * from t1; insert into t1 values (1); # Check that SNW lock is not compatible with SW lock. # Again we use ALTER TABLE which fails after opening @@ -1765,6 +1765,7 @@ drop tables t1, t2; # locking subsystem. # drop tables if exists t0, t1, t2, t3, t4, t5; +set debug_sync= 'RESET'; create table t1 (i int); create table t2 (j int); create table t3 (k int); @@ -1943,6 +1944,98 @@ commit; # Reap ALTER TABLE ... RENAME. drop table t2; # +# Test that in situation when MDL subsystem detects a deadlock +# but it turns out that it can be resolved by backing-off locks +# acquired by one of participating transactions (which is +# possible when one of transactions consists only of currently +# executed statement, e.g. in autocommit mode) no error is +# reported. +# +create table t1 (i int); +create table t2 (j int); +# Ensure that the below SELECT stops once it has acquired metadata +# lock on table 't2'. +set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; +# Sending: +select * from t2, t1; +# +# Switching to connection 'deadlock_con1'. +# Wait till SELECT acquires MDL on 't2' and starts waiting for signal. +set debug_sync= 'now WAIT_FOR locked'; +# Sending: +lock tables t1 write, t2 write; +# +# Switching to connection 'deadlock_con2'. +# Wait until LOCK TABLES acquires SNRW lock on 't1' and is blocked +# while trying to acquire SNRW lock on 't1'. +# Resume SELECT execution, this should eventually unblock LOCK TABLES. +set debug_sync= 'now SIGNAL finish'; +# +# Switching to connection 'deadlock_con1'. +# Reaping LOCK TABLES. +unlock tables; +# +# Switching to connection 'default'. +# Reaping SELECT. It succeed and not report ER_LOCK_DEADLOCK error. +j i +drop tables t1, t2; +# +# Test coverage for situation in which a race has happened +# during deadlock detection process which led to unwarranted +# ER_LOCK_DEADLOCK error. +# +create table t1 (i int); +# Ensure that ALTER waits once it has acquired SNW lock. +set debug_sync='after_open_table_mdl_shared SIGNAL parked1 WAIT_FOR go1'; +# Sending: +alter table t1 add column j int; +# +# Switching to connection 'deadlock_con1'. +# Wait till ALTER acquires SNW lock and stops. +set debug_sync='now WAIT_FOR parked1'; +# Ensure that INSERT is paused once it detects that there is +# a conflicting metadata lock so it has to wait, but before +# deadlock detection is run. +set debug_sync='mdl_acquire_lock_wait SIGNAL parked2 WAIT_FOR go2'; +# Sending: +insert into t1 values (); +# +# Switching to connection 'deadlock_con2'. +# Wait till INSERT is paused. +set debug_sync='now WAIT_FOR parked2'; +# Resume ALTER execution. Eventually it will release its +# metadata lock and INSERT's request for SW lock will be +# satisified. +set debug_sync='now SIGNAL go1'; +# +# Switching to connection 'default'. +# Reaping ALTER TABLE. +# Add a new request for SNW lock to waiting graph. +# Sending: +alter table t1 drop column j; +# +# Switching to connection 'deadlock_con2'. +# Wait until ALTER is blocked. +# Resume INSERT so it can start deadlock detection. +# +# At this point there is a discrepancy between the fact that INSERT's +# SW lock is already satisfied, but INSERT's connection is still +# marked as waiting for it. Looking for a loop in waiters graph +# without additional checks has detected a deadlock (INSERT waits +# for SW lock; which is not granted because of pending SNW lock from +# ALTER; which waits for active SW lock from INSERT). Since requests +# for SW and SNW locks have same weight ALTER was selected as a victim +# and ended with ER_LOCK_DEADLOCK error. +set debug_sync='now SIGNAL go2'; +# +# Switching to connection 'deadlock_con1'. +# Reaping INSERT. +# +# Switching to connection 'default'. +# Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK. +drop table t1; +set debug_sync= 'RESET'; +# # Test for bug #46748 "Assertion in MDL_context::wait_for_locks() # on INSERT + CREATE TRIGGER". # @@ -2175,7 +2268,7 @@ alter table t1 add column e int, rename to t2;; # # Switching to connection 'default'. set debug_sync='now WAIT_FOR alter_table_locked'; -set debug_sync='before_open_table_wait_refresh SIGNAL alter_go'; +set debug_sync='mdl_acquire_lock_wait SIGNAL alter_go'; # The below statement should get ER_LOCK_DEADLOCK error # (i.e. it should not allow ALTER to proceed, and then # fail due to 't1' changing its name to 't2'). @@ -2382,6 +2475,45 @@ commit; set debug_sync= 'RESET'; drop table t1; # +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +# Ensure that a acquired lock is not given up due to a conflict. +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); +# Connection: con1 +SET debug_sync='lock_table_for_truncate SIGNAL parked_truncate WAIT_FOR go_truncate'; +TRUNCATE TABLE t1; +# Connection: default +SET debug_sync='now WAIT_FOR parked_truncate'; +# Connection: con2 +SET debug_sync='after_open_table_ignore_flush SIGNAL parked_show WAIT_FOR go_show'; +SHOW FIELDS FROM t1; +# Connection: default +SET debug_sync='now WAIT_FOR parked_show'; +# Connection: con3 +SET debug_sync='after_flush_unlock SIGNAL parked_flush WAIT_FOR go_flush'; +FLUSH TABLES t1; +# Connection: default +SET debug_sync='now WAIT_FOR parked_flush'; +SET debug_sync='now SIGNAL go_truncate'; +# Connection: con1 +# Reaping... +# Connection: default +SET debug_sync= 'now SIGNAL go_show'; +# Connection: con2 (SHOW FIELDS FROM t1) +# Reaping... +Field Type Null Key Default Extra +a int(11) YES NULL +# Connection: default +SET debug_sync= 'now SIGNAL go_flush'; +# Connection: con3 (FLUSH TABLES t1) +# Reaping... +# Connection: default +SET debug_sync= 'RESET'; +DROP TABLE t1; +# # Bug#52856 concurrent show columns or show full columns causes a crash!!! # CREATE TABLE t1(a CHAR(255)); diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index e46d8e75ab1..8f7ebb06c06 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2699,4 +2699,23 @@ LOCK TABLE m1 WRITE; ALTER TABLE m1 ADD INDEX (c1); UNLOCK TABLES; DROP TABLE m1, t1; +# +# Test for bug #37371 "CREATE TABLE LIKE merge loses UNION parameter" +# +drop tables if exists t1, m1, m2; +create table t1 (i int) engine=myisam; +create table m1 (i int) engine=mrg_myisam union=(t1) insert_method=first; +create table m2 like m1; +# Table definitions should match +show create table m1; +Table Create Table +m1 CREATE TABLE `m1` ( + `i` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`) +show create table m2; +Table Create Table +m2 CREATE TABLE `m2` ( + `i` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`) +drop tables m1, m2, t1; End of 6.0 tests diff --git a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result index 5f1a25324ed..533f35c1113 100644 --- a/mysql-test/r/mysqld--help-notwin.result +++ b/mysql-test/r/mysqld--help-notwin.result @@ -746,7 +746,7 @@ connect-timeout 10 console FALSE date-format %Y-%m-%d datetime-format %Y-%m-%d %H:%i:%s -default-storage-engine MyISAM +default-storage-engine InnoDB default-time-zone (No default value) default-week-format 0 delay-key-write ON diff --git a/mysql-test/r/mysqld--help-win.result b/mysql-test/r/mysqld--help-win.result index 5d517f06add..9b6b0f53b01 100644 --- a/mysql-test/r/mysqld--help-win.result +++ b/mysql-test/r/mysqld--help-win.result @@ -750,7 +750,7 @@ connect-timeout 10 console FALSE date-format %Y-%m-%d datetime-format %Y-%m-%d %H:%i:%s -default-storage-engine MyISAM +default-storage-engine InnoDB default-time-zone (No default value) default-week-format 0 delay-key-write ON diff --git a/mysql-test/r/parser_not_embedded.result b/mysql-test/r/parser_not_embedded.result index 140b13c9864..5a5ae9f8178 100644 --- a/mysql-test/r/parser_not_embedded.result +++ b/mysql-test/r/parser_not_embedded.result @@ -47,3 +47,48 @@ +----------+--------+ | 4 | 4 | +----------+--------+ +# Bug#46527 "COMMIT AND CHAIN RELEASE does not make sense" +# +COMMIT AND CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +COMMIT AND NO CHAIN RELEASE; +COMMIT RELEASE; +COMMIT CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN RELEASE' at line 1 +COMMIT NO CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN RELEASE' at line 1 +COMMIT AND NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +COMMIT AND RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +COMMIT NO RELEASE; +COMMIT CHAIN NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN NO RELEASE' at line 1 +COMMIT NO CHAIN NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN NO RELEASE' at line 1 +COMMIT AND RELEASE CHAIN; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE CHAIN' at line 1 +COMMIT AND NO CHAIN NO RELEASE; +ROLLBACK AND CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +ROLLBACK AND NO CHAIN RELEASE; +ROLLBACK RELEASE; +ROLLBACK CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN RELEASE' at line 1 +ROLLBACK NO CHAIN RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN RELEASE' at line 1 +ROLLBACK AND NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +ROLLBACK AND RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE' at line 1 +ROLLBACK NO RELEASE; +ROLLBACK CHAIN NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN NO RELEASE' at line 1 +ROLLBACK NO CHAIN NO RELEASE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAIN NO RELEASE' at line 1 +ROLLBACK AND RELEASE CHAIN; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RELEASE CHAIN' at line 1 +ROLLBACK AND NO CHAIN NO RELEASE; +# +# End of 5.5 tests +# diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 2df8b19e00c..8ae16238a18 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -266,12 +266,12 @@ engine = x partition by key (a); Warnings: Warning 1286 Unknown storage engine 'x' -Warning 1266 Using storage engine MyISAM for table 't1' +Warning 1266 Using storage engine InnoDB for table 't1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (a) */ drop table t1; create table t1 (a int) diff --git a/mysql-test/r/partition_innodb_semi_consistent.result b/mysql-test/r/partition_innodb_semi_consistent.result index 48a1bb3d258..1ff7ffba6db 100644 --- a/mysql-test/r/partition_innodb_semi_consistent.result +++ b/mysql-test/r/partition_innodb_semi_consistent.result @@ -18,6 +18,7 @@ set autocommit=0; update t1 set a=10 where a=5; ERROR HY000: Lock wait timeout exceeded; try restarting transaction commit; +commit; set session transaction isolation level read committed; update t1 set a=10 where a=5; select * from t1 where a=2 for update; @@ -64,6 +65,7 @@ a b # Switch to connection con2 UPDATE t1 SET b = 21 WHERE a = 1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ROLLBACK; # Switch to connection con1 SELECT * FROM t1; a b @@ -99,6 +101,7 @@ a b SELECT * FROM t1; a b 1 init+con1+con2 +COMMIT; # Switch to connection con1 # 3. test for updated key column: TRUNCATE t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 16f6657ceeb..0e75ebd57ec 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -695,11 +695,11 @@ REPEATABLE-READ set transaction isolation level read committed; execute stmt; @@tx_isolation -READ-COMMITTED +REPEATABLE-READ set transaction isolation level serializable; execute stmt; @@tx_isolation -SERIALIZABLE +REPEATABLE-READ set @@tx_isolation=default; execute stmt; @@tx_isolation diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result index 1257a668cce..edf05d0c5d3 100644 --- a/mysql-test/r/rename.result +++ b/mysql-test/r/rename.result @@ -55,14 +55,15 @@ t2 t4 drop table t2, t4; End of 4.1 tests +# +# Bug#14959: "ALTER TABLE isn't able to rename a view" +# Bug#53976: "ALTER TABLE RENAME is allowed on views +# (not documented, broken)" +# create table t1(f1 int); create view v1 as select * from t1; alter table v1 rename to v2; -alter table v1 rename to v2; -ERROR 42S02: Table 'test.v1' doesn't exist -rename table v2 to v1; -rename table v2 to v1; -ERROR 42S01: Table 'v1' already exists +ERROR HY000: 'test.v1' is not BASE TABLE drop view v1; drop table t1; End of 5.0 tests diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e594e87694f..a61e5077c2b 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4856,4 +4856,19 @@ a b c SELECT * FROM t1 WHERE 102 < c; a b c DROP TABLE t1; +# +# Bug #54459: Assertion failed: param.sort_length, +# file .\filesort.cc, line 149 (part II) +# +CREATE TABLE t1(a ENUM('') NOT NULL); +INSERT INTO t1 VALUES (), (), (); +EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +1 +1 +1 +1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/sp_sync.result b/mysql-test/r/sp_sync.result index a16babaef67..174b3c60745 100644 --- a/mysql-test/r/sp_sync.result +++ b/mysql-test/r/sp_sync.result @@ -59,30 +59,31 @@ SET DEBUG_SYNC= 'RESET'; # # Bug #48246 assert in close_thread_table # +CREATE TABLE t0 (b INTEGER); CREATE TABLE t1 (a INTEGER); CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1; -CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1; +CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1, t0; +INSERT INTO t0 VALUES(1); INSERT INTO t1 VALUES(1), (2); # Connection 2 CALL p1(); COUNT(f1(a)) 2 -# Connection default -SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called'; -# Sending: -CREATE TABLE t1 (a INTEGER); -# Connection 2 -SET DEBUG_SYNC= 'now WAIT_FOR locked'; -SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created'; -# This call used to cause an assertion. MDL locking conflict will -# cause back-off and retry. A variable indicating if a prelocking list -# exists, used to be not reset properly causing an eventual assert. +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked_t1 WAIT_FOR go_for_t0'; +# This call used to cause an assertion. MDL deadlock with upcoming +# LOCK TABLES statement will cause back-off and retry. +# A variable indicating if a prelocking list exists, used to be not +# reset properly causing an eventual assert. # Sending: CALL p1(); # Connection default -# Reaping: CREATE TABLE t1 (a INTEGER) -ERROR 42S01: Table 't1' already exists -SET DEBUG_SYNC= 'now SIGNAL created'; +SET DEBUG_SYNC= 'now WAIT_FOR locked_t1'; +# Issue LOCK TABLES statement which will enter in MDL deadlock +# with CALL statement and as result will cause it to perform +# back-off and retry. +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL go_for_t0'; +LOCK TABLES t0 WRITE, t1 WRITE; +UNLOCK TABLES; # Connection 2 # Reaping: CALL p1() COUNT(f1(a)) @@ -90,5 +91,5 @@ COUNT(f1(a)) # Connection default DROP PROCEDURE p1; DROP FUNCTION f1; -DROP TABLE t1; +DROP TABLES t0, t1; SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index e3aa87876ed..72d63e47d9a 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4988,3 +4988,20 @@ t1_id total_amount DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; +# +# Bug #52711: Segfault when doing EXPLAIN SELECT with +# union...order by (select... where...) +# +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +# Should not crash +EXPLAIN +SELECT * FROM t2 UNION SELECT * FROM t2 +ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +# Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 +ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +DROP TABLE t1,t2; +End of 5.1 tests diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index 8f237c81e75..773075f9dae 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -99,7 +99,7 @@ LOCK TABLE t1 WRITE; SELECT * FROM v1; ERROR HY000: Table 'v1' was not locked with LOCK TABLES TRUNCATE v1; -ERROR 42S02: Table 'test.v1' doesn't exist +ERROR HY000: Table 'v1' was not locked with LOCK TABLES SELECT * FROM v1; ERROR HY000: Table 'v1' was not locked with LOCK TABLES UNLOCK TABLES; @@ -107,7 +107,7 @@ LOCK TABLE t1 WRITE, t2 WRITE; SELECT * FROM v1; ERROR HY000: Table 'v1' was not locked with LOCK TABLES TRUNCATE v1; -ERROR 42S02: Table 'test.v1' doesn't exist +ERROR HY000: Table 'v1' was not locked with LOCK TABLES SELECT * FROM v1; ERROR HY000: Table 'v1' was not locked with LOCK TABLES UNLOCK TABLES; @@ -117,7 +117,7 @@ c1 1 3 TRUNCATE v1; -ERROR 42S02: Table 'test.v1' doesn't exist +ERROR HY000: Table 'v1' was not locked with LOCK TABLES SELECT * FROM v1; c1 1 @@ -129,7 +129,7 @@ c1 1 3 TRUNCATE v1; -ERROR 42S02: Table 'test.v1' doesn't exist +ERROR HY000: Table 'v1' was not locked with LOCK TABLES SELECT * FROM v1; c1 1 diff --git a/mysql-test/r/truncate_coverage.result b/mysql-test/r/truncate_coverage.result index 7a5021f55e2..a7a4b9c70f4 100644 --- a/mysql-test/r/truncate_coverage.result +++ b/mysql-test/r/truncate_coverage.result @@ -18,13 +18,15 @@ TRUNCATE TABLE t1; SET DEBUG_SYNC='now WAIT_FOR waiting'; KILL QUERY @id; # +# connection default +ERROR 70100: Query execution was interrupted +UNLOCK TABLES; +# # connection con1 # Release shared metadata lock by closing HANDLER. HANDLER t1 CLOSE; # # connection default -ERROR 70100: Query execution was interrupted -UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; CREATE TABLE t1 (c1 INT); @@ -64,10 +66,15 @@ TRUNCATE TABLE t1; # connection con1 SET DEBUG_SYNC='now WAIT_FOR waiting'; KILL QUERY @id; -COMMIT; # # connection default ERROR 70100: Query execution was interrupted +# +# connection con1 +# Release SW lock by committing transaction. +COMMIT; +# +# connection default UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 95d2827c1a6..e1c1d6f4128 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3954,6 +3954,7 @@ drop procedure p; CREATE TABLE t1 (a INT); CREATE VIEW v1 AS SELECT a FROM t1; ALTER TABLE v1; +ERROR HY000: 'test.v1' is not BASE TABLE DROP VIEW v1; DROP TABLE t1; # diff --git a/mysql-test/suite/binlog/r/binlog_innodb.result b/mysql-test/suite/binlog/r/binlog_innodb.result index 5f90dd5d3dd..dc170361026 100644 --- a/mysql-test/suite/binlog/r/binlog_innodb.result +++ b/mysql-test/suite/binlog/r/binlog_innodb.result @@ -2,65 +2,65 @@ SET BINLOG_FORMAT=MIXED; RESET MASTER; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=INNODB; INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6); -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = a * a WHERE a > 3; COMMIT; SET BINLOG_FORMAT=STATEMENT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t1 SET b = 1*a WHERE a > 1; ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED. COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 2; ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED. COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; SET BINLOG_FORMAT=MIXED; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t1 SET b = 1*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 2; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; SET BINLOG_FORMAT=ROW; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t1 SET b = 1*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 2; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; show binlog events from <binlog_start>; diff --git a/mysql-test/suite/binlog/r/binlog_stm_ctype_cp932.result b/mysql-test/suite/binlog/r/binlog_stm_ctype_cp932.result index 43108222866..43108222866 100755..100644 --- a/mysql-test/suite/binlog/r/binlog_stm_ctype_cp932.result +++ b/mysql-test/suite/binlog/r/binlog_stm_ctype_cp932.result diff --git a/mysql-test/suite/binlog/r/binlog_truncate_innodb.result b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result index ab237898a74..8beeeb1a428 100644 --- a/mysql-test/suite/binlog/r/binlog_truncate_innodb.result +++ b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result @@ -1,3 +1,6 @@ +SET @old_binlog_format=@@binlog_format; +SET BINLOG_FORMAT=ROW; +RESET MASTER; CREATE TABLE t1 (a INT) ENGINE=InnoDB; CREATE TABLE t2 (a INT) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3); @@ -9,6 +12,45 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +# Even though the isolation level might be permissive, truncate +# table follows a stricter isolation as its locking is based on +# (exclusive) metadata locks. CREATE TABLE t1 (a INT) ENGINE=InnoDB; CREATE TABLE t2 (a INT) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3); @@ -22,6 +64,43 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; CREATE TABLE t1 (a INT) ENGINE=InnoDB; CREATE TABLE t2 (a INT) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3); @@ -35,6 +114,196 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +TRUNCATE TABLE t2; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +TRUNCATE TABLE t2; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +SET BINLOG_FORMAT=STATEMENT; +RESET MASTER; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +TRUNCATE TABLE t2; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +# Truncate is not supported for SBR if the isolation level is +# READ UNCOMMITTED or READ COMMITTED. These specific isolation +# levels are tested elsewhere. CREATE TABLE t1 (a INT) ENGINE=InnoDB; CREATE TABLE t2 (a INT) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3); @@ -48,6 +317,41 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; CREATE TABLE t1 (a INT) ENGINE=InnoDB; CREATE TABLE t2 (a INT) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3); @@ -61,3 +365,39 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +SET BINLOG_FORMAT=@old_binlog_format; diff --git a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result index 9f01c015178..1f5b206fd6f 100644 --- a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result @@ -1,3 +1,5 @@ +SET @old_binlog_format=@@binlog_format; +SET BINLOG_FORMAT=ROW; RESET MASTER; CREATE TABLE t1 (a INT) ENGINE=MyISAM; CREATE TABLE t2 (a INT) ENGINE=MyISAM; @@ -10,3 +12,91 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +SET BINLOG_FORMAT=STATEMENT; +RESET MASTER; +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3); +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +# Connection: default +BEGIN; +INSERT INTO t2 SELECT * FROM t1; +# Connection: truncate +TRUNCATE TABLE t1; +# Connection: default +INSERT INTO t2 SELECT * FROM t1; +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +COMMIT; +# Connection: truncate +# Reaping TRUNCATE TABLE +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +4 +# Connection: default +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +DROP TABLE t1,t2; +SET BINLOG_FORMAT=@old_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_innodb.test b/mysql-test/suite/binlog/t/binlog_innodb.test index 482e787a724..8191b72d5a9 100644 --- a/mysql-test/suite/binlog/t/binlog_innodb.test +++ b/mysql-test/suite/binlog/t/binlog_innodb.test @@ -8,14 +8,14 @@ RESET MASTER; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=INNODB; INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6); -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; # Should be logged as statement UPDATE t1 SET b = 2*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; # Should be logged as rows UPDATE t1 SET b = a * a WHERE a > 3; COMMIT; @@ -25,69 +25,69 @@ COMMIT; SET BINLOG_FORMAT=STATEMENT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE; UPDATE t1 SET b = 1*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE; UPDATE t1 SET b = 2*a WHERE a > 2; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; SET BINLOG_FORMAT=MIXED; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t1 SET b = 1*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 2; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; SET BINLOG_FORMAT=ROW; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t1 SET b = 1*a WHERE a > 1; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; UPDATE t1 SET b = 2*a WHERE a > 2; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; UPDATE t1 SET b = 3*a WHERE a > 3; COMMIT; -BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; UPDATE t1 SET b = 4*a WHERE a > 4; COMMIT; diff --git a/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt index f8e46a44854..099f07e5d4e 100644 --- a/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt +++ b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt @@ -1 +1 @@ ---max_binlog_size=4096 +--max_binlog_size=4096 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt index e76299453d3..9655b180fbd 100644 --- a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt +++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--innodb_lock_wait_timeout=2 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt index f8e46a44854..099f07e5d4e 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt +++ b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt @@ -1 +1 @@ ---max_binlog_size=4096 +--max_binlog_size=4096 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt index 5d0037fdc97..5c4f0b5c198 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 --binlog-direct-non-transactional-updates=FALSE +--innodb_lock_wait_timeout=2 --binlog-direct-non-transactional-updates=FALSE --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test index be0918a43f0..56dd5bda505 100644 --- a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test @@ -1,20 +1,18 @@ source include/have_log_bin.inc; source include/have_innodb.inc; -# It is necessary to reset the master since otherwise the binlog test -# might show the wrong binary log. The default for SHOW BINLOG EVENTS -# is to show the first binary log, not the current one (which is -# actually a better idea). +let $engine = InnoDB; + +SET @old_binlog_format=@@binlog_format; +SET BINLOG_FORMAT=ROW; RESET MASTER; -let $engine = InnoDB; source extra/binlog_tests/binlog_truncate.test; -# Under transaction isolation level READ UNCOMMITTED and READ -# COMMITTED, InnoDB does not permit statement-based replication of -# row-deleting statement. In these cases, TRUNCATE TABLE should still -# be replicated as a statement. +--echo # Even though the isolation level might be permissive, truncate +--echo # table follows a stricter isolation as its locking is based on +--echo # (exclusive) metadata locks. let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; source extra/binlog_tests/binlog_truncate.test; @@ -27,3 +25,20 @@ source extra/binlog_tests/binlog_truncate.test; let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; source extra/binlog_tests/binlog_truncate.test; + +SET BINLOG_FORMAT=STATEMENT; +RESET MASTER; + +source extra/binlog_tests/binlog_truncate.test; + +--echo # Truncate is not supported for SBR if the isolation level is +--echo # READ UNCOMMITTED or READ COMMITTED. These specific isolation +--echo # levels are tested elsewhere. + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +source extra/binlog_tests/binlog_truncate.test; + +SET BINLOG_FORMAT=@old_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test index e0e4673e876..fc28bd7c7e2 100644 --- a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test @@ -1,11 +1,17 @@ source include/have_log_bin.inc; -# It is necessary to reset the master since otherwise the binlog test -# might show the wrong binary log. The default for SHOW BINLOG EVENTS -# is to show the first binary log, not the current one (which is -# actually a better idea). +SET @old_binlog_format=@@binlog_format; +let $engine = MyISAM; + +SET BINLOG_FORMAT=ROW; +RESET MASTER; + +source extra/binlog_tests/binlog_truncate.test; + +SET BINLOG_FORMAT=STATEMENT; RESET MASTER; -let $engine = MyISAM; source extra/binlog_tests/binlog_truncate.test; + +SET BINLOG_FORMAT=@old_binlog_format; diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def index b6086edb2f0..35ecf52decf 100644 --- a/mysql-test/suite/binlog/t/disabled.def +++ b/mysql-test/suite/binlog/t/disabled.def @@ -9,6 +9,7 @@ # Do not use any TAB characters for whitespace. # ############################################################################## + binlog_truncate_innodb : BUG#42643 2009-02-06 mats Changes to InnoDB requires to complete fix for BUG#36763 binlog_unsafe : BUG#50312 2010-01-13 lsoares Warnings for unsafe sub-statement not returned to client binlog_spurious_ddl_errors : BUG#54195 2010-06-03 alik binlog_spurious_ddl_errors.test fails, thus disabled diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result index b4bce0b0d1b..86a61773a31 100644 --- a/mysql-test/suite/funcs_1/r/innodb_views.result +++ b/mysql-test/suite/funcs_1/r/innodb_views.result @@ -3521,6 +3521,7 @@ RENAME TABLE v1 TO v2; RENAME VIEW v2 TO v1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VIEW v2 TO v1' at line 1 ALTER TABLE v2 RENAME AS v1; +ERROR HY000: 'test.v2' is not BASE TABLE ALTER VIEW v1 RENAME AS v2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RENAME AS v2' at line 1 DROP TABLE IF EXISTS t1, t2 ; diff --git a/mysql-test/suite/funcs_1/r/is_engines_innodb.result b/mysql-test/suite/funcs_1/r/is_engines_innodb.result index 5713b417cd1..57e53b60bbd 100644 --- a/mysql-test/suite/funcs_1/r/is_engines_innodb.result +++ b/mysql-test/suite/funcs_1/r/is_engines_innodb.result @@ -1,7 +1,7 @@ SELECT * FROM information_schema.engines WHERE ENGINE = 'InnoDB'; ENGINE InnoDB -SUPPORT YES +SUPPORT DEFAULT COMMENT Supports transactions, row-level locking, and foreign keys TRANSACTIONS YES XA YES diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index 2f7342088f8..7ed23c3a5c1 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -3522,6 +3522,7 @@ RENAME TABLE v1 TO v2; RENAME VIEW v2 TO v1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VIEW v2 TO v1' at line 1 ALTER TABLE v2 RENAME AS v1; +ERROR HY000: 'test.v2' is not BASE TABLE ALTER VIEW v1 RENAME AS v2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RENAME AS v2' at line 1 DROP TABLE IF EXISTS t1, t2 ; diff --git a/mysql-test/suite/funcs_1/r/myisam_views.result b/mysql-test/suite/funcs_1/r/myisam_views.result index b77ea8a4bd9..ca4dba9f337 100644 --- a/mysql-test/suite/funcs_1/r/myisam_views.result +++ b/mysql-test/suite/funcs_1/r/myisam_views.result @@ -4024,6 +4024,7 @@ RENAME TABLE v1 TO v2; RENAME VIEW v2 TO v1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VIEW v2 TO v1' at line 1 ALTER TABLE v2 RENAME AS v1; +ERROR HY000: 'test.v2' is not BASE TABLE ALTER VIEW v1 RENAME AS v2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RENAME AS v2' at line 1 DROP TABLE IF EXISTS t1, t2 ; diff --git a/mysql-test/suite/funcs_1/r/ndb_views.result b/mysql-test/suite/funcs_1/r/ndb_views.result index 10cb7613f47..6c5a10845a0 100644 --- a/mysql-test/suite/funcs_1/r/ndb_views.result +++ b/mysql-test/suite/funcs_1/r/ndb_views.result @@ -3521,6 +3521,7 @@ RENAME TABLE v1 TO v2; RENAME VIEW v2 TO v1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VIEW v2 TO v1' at line 1 ALTER TABLE v2 RENAME AS v1; +ERROR HY000: 'test.v2' is not BASE TABLE ALTER VIEW v1 RENAME AS v2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RENAME AS v2' at line 1 DROP TABLE IF EXISTS t1, t2 ; diff --git a/mysql-test/suite/funcs_1/views/func_view.inc b/mysql-test/suite/funcs_1/views/func_view.inc index 4aed5845a84..660efde8927 100644 --- a/mysql-test/suite/funcs_1/views/func_view.inc +++ b/mysql-test/suite/funcs_1/views/func_view.inc @@ -171,7 +171,7 @@ CREATE TABLE t1_selects disable_result ENUM('Yes','No') NOT NULL default 'No', PRIMARY KEY(id), UNIQUE (my_select) -); +) ENGINE=MyISAM; # MODES to be checked CREATE TABLE t1_modes @@ -180,7 +180,7 @@ CREATE TABLE t1_modes my_mode VARCHAR(200) NOT NULL, PRIMARY KEY(id), UNIQUE (my_mode) -); +) ENGINE=MyISAM; --enable_query_log # The table to be used in the FROM parts of the SELECTs diff --git a/mysql-test/suite/funcs_1/views/views_master.inc b/mysql-test/suite/funcs_1/views/views_master.inc index 4f8439efc3a..906f1f03b3b 100644 --- a/mysql-test/suite/funcs_1/views/views_master.inc +++ b/mysql-test/suite/funcs_1/views/views_master.inc @@ -298,7 +298,7 @@ RENAME TABLE v1 TO v2; # RENAME VIEW is not available even when we try it via rename table. --error ER_PARSE_ERROR RENAME VIEW v2 TO v1; -#--error ER_WRONG_OBJECT +--error ER_WRONG_OBJECT ALTER TABLE v2 RENAME AS v1; --error ER_PARSE_ERROR ALTER VIEW v1 RENAME AS v2; diff --git a/mysql-test/suite/ibmdb2i/include/have_i54.inc b/mysql-test/suite/ibmdb2i/include/have_i54.inc index 7054e196153..7054e196153 100755..100644 --- a/mysql-test/suite/ibmdb2i/include/have_i54.inc +++ b/mysql-test/suite/ibmdb2i/include/have_i54.inc diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result index 8276b401073..8276b401073 100755..100644 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result index 311e800e1b0..311e800e1b0 100755..100644 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test index ea29b5abcd4..ea29b5abcd4 100755..100644 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test index da69b5d9148..da69b5d9148 100755..100644 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test diff --git a/mysql-test/r/innodb-autoinc-optimize.result b/mysql-test/suite/innodb/r/innodb-autoinc-optimize.result index c6da43555b2..c6da43555b2 100644 --- a/mysql-test/r/innodb-autoinc-optimize.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc-optimize.result diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index 5d67a06b80f..1aeca2c226a 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -918,9 +918,9 @@ ERROR HY000: Too big row alter table t1 row_format=compact; create index t1u on t1 (u(1)); drop table t1; -set global innodb_file_per_table=0; -set global innodb_file_format=Antelope; -set global innodb_file_format_check=Antelope; +set global innodb_file_per_table=1; +set global innodb_file_format=Barracuda; +set global innodb_file_format_max=Barracuda; SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; CREATE TABLE t1( diff --git a/mysql-test/suite/innodb/r/innodb-semi-consistent.result b/mysql-test/suite/innodb/r/innodb-semi-consistent.result index ca0e362ef80..989cb818cec 100644 --- a/mysql-test/suite/innodb/r/innodb-semi-consistent.result +++ b/mysql-test/suite/innodb/r/innodb-semi-consistent.result @@ -13,6 +13,7 @@ set autocommit=0; update t1 set a=10 where a=5; ERROR HY000: Lock wait timeout exceeded; try restarting transaction commit; +commit; set session transaction isolation level read committed; update t1 set a=10 where a=5; select * from t1 where a=2 for update; diff --git a/mysql-test/r/innodb-ucs2.result b/mysql-test/suite/innodb/r/innodb-ucs2.result index b6bff7d5f42..b6bff7d5f42 100644 --- a/mysql-test/r/innodb-ucs2.result +++ b/mysql-test/suite/innodb/r/innodb-ucs2.result diff --git a/mysql-test/suite/innodb/r/innodb-zip.result b/mysql-test/suite/innodb/r/innodb-zip.result index bcd3849238f..da2be2bb07d 100644 --- a/mysql-test/suite/innodb/r/innodb-zip.result +++ b/mysql-test/suite/innodb/r/innodb-zip.result @@ -1,3 +1,4 @@ +set session innodb_strict_mode=0; set global innodb_file_per_table=off; set global innodb_file_format=`0`; create table t0(a int primary key) engine=innodb row_format=compressed; @@ -393,29 +394,29 @@ table_schema table_name row_format test t8 Compact test t9 Redundant drop table t8, t9; -set global innodb_file_per_table=0; -set global innodb_file_format=Antelope; +set global innodb_file_per_table=1; +set global innodb_file_format=Barracuda; set global innodb_file_per_table=on; set global innodb_file_format=`Barracuda`; -set global innodb_file_format_check=`Antelope`; +set global innodb_file_format_max=`Antelope`; create table normal_table ( c1 int ) engine = innodb; -select @@innodb_file_format_check; -@@innodb_file_format_check +select @@innodb_file_format_max; +@@innodb_file_format_max Antelope create table zip_table ( c1 int ) engine = innodb key_block_size = 8; -select @@innodb_file_format_check; -@@innodb_file_format_check +select @@innodb_file_format_max; +@@innodb_file_format_max Barracuda -set global innodb_file_format_check=`Antelope`; -select @@innodb_file_format_check; -@@innodb_file_format_check +set global innodb_file_format_max=`Antelope`; +select @@innodb_file_format_max; +@@innodb_file_format_max Antelope show table status; -select @@innodb_file_format_check; -@@innodb_file_format_check +select @@innodb_file_format_max; +@@innodb_file_format_max Barracuda drop table normal_table, zip_table; diff --git a/mysql-test/r/innodb_autoinc_lock_mode_zero.result b/mysql-test/suite/innodb/r/innodb_autoinc_lock_mode_zero.result index 3d016684338..3d016684338 100644 --- a/mysql-test/r/innodb_autoinc_lock_mode_zero.result +++ b/mysql-test/suite/innodb/r/innodb_autoinc_lock_mode_zero.result diff --git a/mysql-test/r/innodb_bug30919.result b/mysql-test/suite/innodb/r/innodb_bug30919.result index 42aa4ff302b..42aa4ff302b 100644 --- a/mysql-test/r/innodb_bug30919.result +++ b/mysql-test/suite/innodb/r/innodb_bug30919.result diff --git a/mysql-test/suite/innodb/r/innodb_bug38231.result b/mysql-test/suite/innodb/r/innodb_bug38231.result index 41a40542b84..195775f74c8 100644 --- a/mysql-test/suite/innodb/r/innodb_bug38231.result +++ b/mysql-test/suite/innodb/r/innodb_bug38231.result @@ -1,11 +1 @@ SET storage_engine=InnoDB; -INSERT INTO bug38231_2 VALUES (1), (10), (300); -SET autocommit=0; -SELECT * FROM bug38231_2 FOR UPDATE; -a -1 -10 -300 -TRUNCATE TABLE bug38231_2; -COMMIT; -DROP TABLE bug38231_2; diff --git a/mysql-test/r/innodb_bug42419.result b/mysql-test/suite/innodb/r/innodb_bug42419.result index f304bb634cb..f304bb634cb 100644 --- a/mysql-test/r/innodb_bug42419.result +++ b/mysql-test/suite/innodb/r/innodb_bug42419.result diff --git a/mysql-test/suite/innodb/r/innodb_bug47167.result b/mysql-test/suite/innodb/r/innodb_bug47167.result index cf8cb0c0d7b..656a4846a52 100644 --- a/mysql-test/suite/innodb/r/innodb_bug47167.result +++ b/mysql-test/suite/innodb/r/innodb_bug47167.result @@ -1,24 +1,24 @@ -set @old_innodb_file_format_check=@@innodb_file_format_check; -select @old_innodb_file_format_check; -@old_innodb_file_format_check +set @old_innodb_file_format_max=@@innodb_file_format_max; +select @old_innodb_file_format_max; +@old_innodb_file_format_max Antelope -set global innodb_file_format_check = Barracuda; -select @@innodb_file_format_check; -@@innodb_file_format_check +set global innodb_file_format_max = Barracuda; +select @@innodb_file_format_max; +@@innodb_file_format_max Barracuda -set global innodb_file_format_check = DEFAULT; -select @@innodb_file_format_check; -@@innodb_file_format_check -Barracuda -set global innodb_file_format_check = @old_innodb_file_format_check; -select @@innodb_file_format_check; -@@innodb_file_format_check +set global innodb_file_format_max = DEFAULT; +select @@innodb_file_format_max; +@@innodb_file_format_max +Antelope +set global innodb_file_format_max = @old_innodb_file_format_max; +select @@innodb_file_format_max; +@@innodb_file_format_max Antelope -set global innodb_file_format_check = cheetah; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'cheetah' -set global innodb_file_format_check = Bear; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'Bear' -set global innodb_file_format_check = on; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'ON' -set global innodb_file_format_check = off; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'off' +set global innodb_file_format_max = cheetah; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'cheetah' +set global innodb_file_format_max = Bear; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'Bear' +set global innodb_file_format_max = on; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'ON' +set global innodb_file_format_max = off; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'off' diff --git a/mysql-test/suite/innodb/r/innodb_bug52745.result b/mysql-test/suite/innodb/r/innodb_bug52745.result index 254c6525257..16dd356997e 100644 --- a/mysql-test/suite/innodb/r/innodb_bug52745.result +++ b/mysql-test/suite/innodb/r/innodb_bug52745.result @@ -125,6 +125,6 @@ Warning 1264 Out of range value for column 'col78' at row 1 Warning 1265 Data truncated for column 'col79' at row 1 Warning 1264 Out of range value for column 'col84' at row 1 DROP TABLE bug52745; -SET GLOBAL innodb_file_format=Antelope; -SET GLOBAL innodb_file_format_check=Antelope; -SET GLOBAL innodb_file_per_table=0; +SET GLOBAL innodb_file_format=Barracuda; +SET GLOBAL innodb_file_format_max=Antelope; +SET GLOBAL innodb_file_per_table=1; diff --git a/mysql-test/suite/innodb/r/innodb_bug53591.result b/mysql-test/suite/innodb/r/innodb_bug53591.result index 1f05b6d2a57..8573fb60718 100644 --- a/mysql-test/suite/innodb/r/innodb_bug53591.result +++ b/mysql-test/suite/innodb/r/innodb_bug53591.result @@ -11,6 +11,6 @@ Error 139 Too big row Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs Error 1030 Got error 139 from storage engine DROP TABLE bug53591; -SET GLOBAL innodb_file_format=Antelope; -SET GLOBAL innodb_file_format_check=Antelope; -SET GLOBAL innodb_file_per_table=0; +SET GLOBAL innodb_file_format=Barracuda; +SET GLOBAL innodb_file_format_max=Antelope; +SET GLOBAL innodb_file_per_table=1; diff --git a/mysql-test/suite/innodb/r/innodb_file_format.result b/mysql-test/suite/innodb/r/innodb_file_format.result index 6a573d8658e..447e13f0d60 100644 --- a/mysql-test/suite/innodb/r/innodb_file_format.result +++ b/mysql-test/suite/innodb/r/innodb_file_format.result @@ -1,8 +1,11 @@ select @@innodb_file_format; @@innodb_file_format -Antelope +Barracuda select @@innodb_file_format_check; @@innodb_file_format_check +1 +select @@innodb_file_format_max; +@@innodb_file_format_max Antelope set global innodb_file_format=antelope; set global innodb_file_format=barracuda; @@ -14,30 +17,34 @@ Barracuda set global innodb_file_format=default; select @@innodb_file_format; @@innodb_file_format -Antelope +Barracuda set global innodb_file_format=on; ERROR 42000: Variable 'innodb_file_format' can't be set to the value of 'ON' set global innodb_file_format=off; ERROR 42000: Variable 'innodb_file_format' can't be set to the value of 'off' select @@innodb_file_format; @@innodb_file_format -Antelope -set global innodb_file_format_check=antelope; -set global innodb_file_format_check=barracuda; -set global innodb_file_format_check=cheetah; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'cheetah' -select @@innodb_file_format_check; -@@innodb_file_format_check Barracuda -set global innodb_file_format_check=default; -select @@innodb_file_format_check; -@@innodb_file_format_check +set global innodb_file_format_max=antelope; +set global innodb_file_format_max=barracuda; +set global innodb_file_format_max=cheetah; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'cheetah' +select @@innodb_file_format_max; +@@innodb_file_format_max Barracuda +set global innodb_file_format_max=default; +select @@innodb_file_format_max; +@@innodb_file_format_max +Antelope set global innodb_file_format=on; ERROR 42000: Variable 'innodb_file_format' can't be set to the value of 'ON' set global innodb_file_format=off; ERROR 42000: Variable 'innodb_file_format' can't be set to the value of 'off' -select @@innodb_file_format_check; -@@innodb_file_format_check -Barracuda -set global innodb_file_format_check=antelope; +select @@innodb_file_format_max; +@@innodb_file_format_max +Antelope +set global innodb_file_format_max=antelope; +set global innodb_file_format_check=off; +ERROR HY000: Variable 'innodb_file_format_check' is a read only variable +SET GLOBAL innodb_file_format=Barracuda; +SET GLOBAL innodb_file_format_max=Antelope; diff --git a/mysql-test/r/innodb_gis.result b/mysql-test/suite/innodb/r/innodb_gis.result index 0ce1ebe56ad..0ce1ebe56ad 100644 --- a/mysql-test/r/innodb_gis.result +++ b/mysql-test/suite/innodb/r/innodb_gis.result diff --git a/mysql-test/suite/innodb/r/innodb_information_schema.result b/mysql-test/suite/innodb/r/innodb_information_schema.result index ad8729804df..1737dab2ff0 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema.result @@ -63,4 +63,4 @@ RUNNING 4 0 0 7 1 0 REPEATABLE READ 1 1 trx_isolation_level trx_unique_checks trx_foreign_key_checks SERIALIZABLE 0 0 trx_state trx_isolation_level trx_last_foreign_key_error -RUNNING SERIALIZABLE `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c02`) REFERENCES `t1` (`c01`) +RUNNING REPEATABLE READ `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c02`) REFERENCES `t1` (`c01`) diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result index bd8760b8f79..bd8760b8f79 100644 --- a/mysql-test/r/innodb_lock_wait_timeout_1.result +++ b/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index acbb1fedf4b..b418b62ec90 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -1590,6 +1590,9 @@ SELECT * FROM t1; a b 1 12 ROLLBACK; +# Switch to connection con2 +ROLLBACK; +# Switch to connection con1 # 2. test for serialized update: CREATE TABLE t2 (a INT); TRUNCATE t1; @@ -1764,6 +1767,37 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DERIVED t1 index c3,c2 c2 14 NULL 5 DROP TABLE t1; End of 5.1 tests +# +# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +# +# Check that a TRUNCATE TABLE statement, needing an exclusive meta +# data lock, waits for a shared metadata lock owned by a concurrent +# transaction. +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); +BEGIN; +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +# Connection con1 +TRUNCATE TABLE t1;; +# Connection default +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +ROLLBACK; +# Connection con1 +# Reaping TRUNCATE TABLE +SELECT * FROM t1; +a +# Disconnect con1 +# Connection default +DROP TABLE t1; drop table if exists t1, t2, t3; create table t1(a int); insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); @@ -2414,6 +2448,18 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where DROP TABLE t1,t2; # +# Bug#38999 valgrind warnings for update statement in function compare_record() +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); +SELECT * FROM t1 WHERE a = 2; +a +2 +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; +DROP TABLE t1,t2; +# # Bug #53830: !table || (!table->read_set || bitmap_is_set(table->read_set, field_index)) # CREATE TABLE t1 (a INT, b INT, c INT, d INT, @@ -2460,6 +2506,38 @@ AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge PRIMARY,idx1,idx2 idx2,idx1,PRIMARY 7,60,4 NULL 1 Using intersect(idx2,idx1,PRIMARY); Using where DROP TABLE t1; +# +# Bug#51431 Wrong sort order after import of dump file +# +CREATE TABLE t1 ( +f1 INT(11) NOT NULL, +f2 int(11) NOT NULL, +f3 int(11) NOT NULL, +f4 tinyint(1) NOT NULL, +PRIMARY KEY (f1), +UNIQUE KEY (f2, f3), +KEY (f4) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,1,991,1), (2,1,992,1), (3,1,993,1), (4,1,994,1), (5,1,995,1), +(6,1,996,1), (7,1,997,1), (8,1,998,1), (10,1,999,1), (11,1,9910,1), +(16,1,9911,1), (17,1,9912,1), (18,1,9913,1), (19,1,9914,1), (20,1,9915,1), +(21,1,9916,1), (22,1,9917,1), (23,1,9918,1), (24,1,9919,1), (25,1,9920,1), +(26,1,9921,1), (27,1,9922,1); +FLUSH TABLES; +SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +f1 f2 f3 f4 +27 1 9922 1 +26 1 9921 1 +25 1 9920 1 +24 1 9919 1 +23 1 9918 1 +EXPLAIN SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where +DROP TABLE t1; End of 5.1 tests # # Test for bug #39932 "create table fails if column for FK is in different diff --git a/mysql-test/r/innodb_mysql_rbk.result b/mysql-test/suite/innodb/r/innodb_mysql_rbk.result index 21ac4295325..21ac4295325 100644 --- a/mysql-test/r/innodb_mysql_rbk.result +++ b/mysql-test/suite/innodb/r/innodb_mysql_rbk.result diff --git a/mysql-test/r/innodb_notembedded.result b/mysql-test/suite/innodb/r/innodb_notembedded.result index af332aba38a..af332aba38a 100644 --- a/mysql-test/r/innodb_notembedded.result +++ b/mysql-test/suite/innodb/r/innodb_notembedded.result diff --git a/mysql-test/r/innodb_timeout_rollback.result b/mysql-test/suite/innodb/r/innodb_timeout_rollback.result index e2da6ba8af7..e2da6ba8af7 100644 --- a/mysql-test/r/innodb_timeout_rollback.result +++ b/mysql-test/suite/innodb/r/innodb_timeout_rollback.result diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def index da04138fd0a..888298bbb09 100644 --- a/mysql-test/suite/innodb/t/disabled.def +++ b/mysql-test/suite/innodb/t/disabled.def @@ -9,4 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -innodb_multi_update: Bug #38999 2010-05-05 mmakela Valgrind warnings diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-44030-master.opt b/mysql-test/suite/innodb/t/innodb-autoinc-44030-master.opt new file mode 100644 index 00000000000..303ec1be1d0 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-autoinc-44030-master.opt @@ -0,0 +1,3 @@ +--default-storage-engine=MyISAM +--innodb-strict-mode=0 +--innodb-file-per-table=0 diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-44030.test b/mysql-test/suite/innodb/t/innodb-autoinc-44030.test index 17c836004a1..790646fe13b 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc-44030.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc-44030.test @@ -2,7 +2,7 @@ # embedded server ignores 'delayed', so skip this -- source include/not_embedded.inc -let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; +let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; --disable_warnings drop table if exists t1; @@ -40,4 +40,4 @@ DROP TABLE t1; # -- disable_query_log -eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; +eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-master.opt b/mysql-test/suite/innodb/t/innodb-autoinc-master.opt new file mode 100644 index 00000000000..303ec1be1d0 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-autoinc-master.opt @@ -0,0 +1,3 @@ +--default-storage-engine=MyISAM +--innodb-strict-mode=0 +--innodb-file-per-table=0 diff --git a/mysql-test/t/innodb-autoinc-optimize.test b/mysql-test/suite/innodb/t/innodb-autoinc-optimize.test index 0f0cb57f92f..0f0cb57f92f 100644 --- a/mysql-test/t/innodb-autoinc-optimize.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc-optimize.test diff --git a/mysql-test/suite/innodb/t/innodb-autoinc.test b/mysql-test/suite/innodb/t/innodb-autoinc.test index c1cae16153e..a8e853baef7 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc.test @@ -2,7 +2,7 @@ # embedded server ignores 'delayed', so skip this -- source include/not_embedded.inc -let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; +let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; --disable_warnings drop table if exists t1; @@ -671,4 +671,4 @@ DROP TABLE t1; # -- disable_query_log -eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; +eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test index f7cf3050704..05d1d37c422 100644 --- a/mysql-test/suite/innodb/t/innodb-index.test +++ b/mysql-test/suite/innodb/t/innodb-index.test @@ -2,7 +2,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; +let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); @@ -403,7 +403,7 @@ create index t1u on t1 (u(1)); drop table t1; eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; -eval set global innodb_file_format_check=$format; +eval set global innodb_file_format_max=$format; # # Test to check whether CREATE INDEX handles implicit foreign key @@ -550,4 +550,4 @@ DROP TABLE t1; # -- disable_query_log -eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; +eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; diff --git a/mysql-test/suite/innodb/t/innodb-master.opt b/mysql-test/suite/innodb/t/innodb-master.opt index 4901efb416c..8b247193a4e 100644 --- a/mysql-test/suite/innodb/t/innodb-master.opt +++ b/mysql-test/suite/innodb/t/innodb-master.opt @@ -1 +1,4 @@ --binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--default-storage-engine=MyISAM +--innodb-strict-mode=0 +--innodb-file-per-table=0 diff --git a/mysql-test/suite/innodb/t/innodb-semi-consistent.test b/mysql-test/suite/innodb/t/innodb-semi-consistent.test index 61ad7815ca9..28bf532ff1f 100644 --- a/mysql-test/suite/innodb/t/innodb-semi-consistent.test +++ b/mysql-test/suite/innodb/t/innodb-semi-consistent.test @@ -23,6 +23,7 @@ set session transaction isolation level repeatable read; set autocommit=0; -- error ER_LOCK_WAIT_TIMEOUT update t1 set a=10 where a=5; +commit; connection a; commit; connection b; diff --git a/mysql-test/suite/innodb/t/innodb-system-table-view-master.opt b/mysql-test/suite/innodb/t/innodb-system-table-view-master.opt new file mode 100644 index 00000000000..303ec1be1d0 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-system-table-view-master.opt @@ -0,0 +1,3 @@ +--default-storage-engine=MyISAM +--innodb-strict-mode=0 +--innodb-file-per-table=0 diff --git a/mysql-test/t/innodb-ucs2.test b/mysql-test/suite/innodb/t/innodb-ucs2.test index 7b91ef37d3f..7b91ef37d3f 100644 --- a/mysql-test/t/innodb-ucs2.test +++ b/mysql-test/suite/innodb/t/innodb-ucs2.test diff --git a/mysql-test/suite/innodb/t/innodb-use-sys-malloc-master.opt b/mysql-test/suite/innodb/t/innodb-use-sys-malloc-master.opt index acf3b8729ed..041b063645b 100644 --- a/mysql-test/suite/innodb/t/innodb-use-sys-malloc-master.opt +++ b/mysql-test/suite/innodb/t/innodb-use-sys-malloc-master.opt @@ -1 +1,3 @@ ---innodb-use-sys-malloc=true +--default-storage-engine=MyISAM +--loose-innodb-use-sys-malloc=true +--loose-innodb-use-sys-malloc=true diff --git a/mysql-test/suite/innodb/t/innodb-zip.test b/mysql-test/suite/innodb/t/innodb-zip.test index 8ba83517b44..8e00a8b019b 100644 --- a/mysql-test/suite/innodb/t/innodb-zip.test +++ b/mysql-test/suite/innodb/t/innodb-zip.test @@ -2,10 +2,13 @@ let $per_table=`select @@innodb_file_per_table`; let $format=`select @@innodb_file_format`; -let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; +let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; +let $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`; + +set session innodb_strict_mode=0; set global innodb_file_per_table=off; set global innodb_file_format=`0`; - + create table t0(a int primary key) engine=innodb row_format=compressed; create table t00(a int primary key) engine=innodb key_block_size=4 row_format=compressed; @@ -316,21 +319,21 @@ eval set global innodb_file_format=$format; -- disable_info set global innodb_file_per_table=on; set global innodb_file_format=`Barracuda`; -set global innodb_file_format_check=`Antelope`; +set global innodb_file_format_max=`Antelope`; create table normal_table ( c1 int ) engine = innodb; -select @@innodb_file_format_check; +select @@innodb_file_format_max; create table zip_table ( c1 int ) engine = innodb key_block_size = 8; -select @@innodb_file_format_check; -set global innodb_file_format_check=`Antelope`; -select @@innodb_file_format_check; +select @@innodb_file_format_max; +set global innodb_file_format_max=`Antelope`; +select @@innodb_file_format_max; -- disable_result_log show table status; -- enable_result_log -select @@innodb_file_format_check; +select @@innodb_file_format_max; drop table normal_table, zip_table; -- disable_result_log @@ -341,4 +344,5 @@ drop table normal_table, zip_table; -- disable_query_log eval set global innodb_file_format=$format; eval set global innodb_file_per_table=$per_table; -eval set global innodb_file_format_check=$innodb_file_format_check_orig; +eval set global innodb_file_format_max=$innodb_file_format_max_orig; +eval set session innodb_strict_mode=$innodb_strict_mode_orig; diff --git a/mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt index fad0da2ac2e..fad0da2ac2e 100644 --- a/mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt +++ b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt diff --git a/mysql-test/t/innodb_autoinc_lock_mode_zero.test b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero.test index 96f748673c0..96f748673c0 100644 --- a/mysql-test/t/innodb_autoinc_lock_mode_zero.test +++ b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero.test diff --git a/mysql-test/t/innodb_bug30919-master.opt b/mysql-test/suite/innodb/t/innodb_bug30919-master.opt index 8636d2d8734..8636d2d8734 100644 --- a/mysql-test/t/innodb_bug30919-master.opt +++ b/mysql-test/suite/innodb/t/innodb_bug30919-master.opt diff --git a/mysql-test/t/innodb_bug30919.test b/mysql-test/suite/innodb/t/innodb_bug30919.test index 56b2c7bc03d..56b2c7bc03d 100644 --- a/mysql-test/t/innodb_bug30919.test +++ b/mysql-test/suite/innodb/t/innodb_bug30919.test diff --git a/mysql-test/suite/innodb/t/innodb_bug36172.test b/mysql-test/suite/innodb/t/innodb_bug36172.test index c6c4e6fae47..6f5dd7629ff 100644 --- a/mysql-test/suite/innodb/t/innodb_bug36172.test +++ b/mysql-test/suite/innodb/t/innodb_bug36172.test @@ -15,7 +15,7 @@ SET storage_engine=InnoDB; -- disable_result_log let $file_format=`select @@innodb_file_format`; -let $file_format_check=`select @@innodb_file_format_check`; +let $file_format_max=`select @@innodb_file_format_max`; let $file_per_table=`select @@innodb_file_per_table`; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=on; @@ -28,5 +28,5 @@ INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.90 CHECK TABLE table0 EXTENDED; DROP TABLE table0; EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_format_max=$file_format_max; EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb_bug38231.test b/mysql-test/suite/innodb/t/innodb_bug38231.test index a0a10bbd100..0d4262b4473 100644 --- a/mysql-test/suite/innodb/t/innodb_bug38231.test +++ b/mysql-test/suite/innodb/t/innodb_bug38231.test @@ -71,30 +71,7 @@ UNLOCK TABLES; DROP TABLE bug38231_1; -# test that TRUNCATE works with row-level locks - -DROP TABLE IF EXISTS bug38231_2; -CREATE TABLE bug38231_2 (a INT); - -- enable_query_log -- enable_result_log -INSERT INTO bug38231_2 VALUES (1), (10), (300); - --- connect (con4,localhost,root,,) - --- connection con4 -SET autocommit=0; -SELECT * FROM bug38231_2 FOR UPDATE; - -- connection default -TRUNCATE TABLE bug38231_2; - --- connection con4 -COMMIT; - --- connection default - --- disconnect con4 - -DROP TABLE bug38231_2; diff --git a/mysql-test/t/innodb_bug42419.test b/mysql-test/suite/innodb/t/innodb_bug42419.test index 93c4764252a..93c4764252a 100644 --- a/mysql-test/t/innodb_bug42419.test +++ b/mysql-test/suite/innodb/t/innodb_bug42419.test diff --git a/mysql-test/suite/innodb/t/innodb_bug47167.test b/mysql-test/suite/innodb/t/innodb_bug47167.test index 9b8bff0292f..8fcd129cf94 100644 --- a/mysql-test/suite/innodb/t/innodb_bug47167.test +++ b/mysql-test/suite/innodb/t/innodb_bug47167.test @@ -1,45 +1,45 @@ -# This is the unit test for bug *47167. -# It tests setting the global variable -# "innodb_file_format_check" with a -# user-Defined Variable. +# This is the unit test for bug #47167. +# It tests setting the global variable "innodb_file_format_max" ( +# originally "innodb_file_format_check") with a user-Defined Variable. +--source include/not_embedded.inc --source include/have_innodb.inc -# Save the value (Antelope) in 'innodb_file_format_check' to -# 'old_innodb_file_format_check' -set @old_innodb_file_format_check=@@innodb_file_format_check; +# Save the value (Antelope) in 'innodb_file_format_max' to +# 'old_innodb_file_format_max' +set @old_innodb_file_format_max=@@innodb_file_format_max; -# @old_innodb_file_format_check shall have the value of 'Antelope' -select @old_innodb_file_format_check; +# @old_innodb_file_format_max shall have the value of 'Antelope' +select @old_innodb_file_format_max; -# Reset the value in 'innodb_file_format_check' to 'Barracuda' -set global innodb_file_format_check = Barracuda; +# Reset the value in 'innodb_file_format_max' to 'Barracuda' +set global innodb_file_format_max = Barracuda; -select @@innodb_file_format_check; +select @@innodb_file_format_max; -# Set 'innodb_file_format_check' to its default value, which +# Set 'innodb_file_format_max' to its default value, which # is the latest file format supported in the current release. -set global innodb_file_format_check = DEFAULT; +set global innodb_file_format_max = DEFAULT; -select @@innodb_file_format_check; +select @@innodb_file_format_max; -# Put the saved value back to 'innodb_file_format_check' -set global innodb_file_format_check = @old_innodb_file_format_check; +# Put the saved value back to 'innodb_file_format_max' +set global innodb_file_format_max = @old_innodb_file_format_max; -# Check whether 'innodb_file_format_check' get its original value. -select @@innodb_file_format_check; +# Check whether 'innodb_file_format_max' get its original value. +select @@innodb_file_format_max; # Following are negative tests, all should fail. --disable_warnings --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check = cheetah; +set global innodb_file_format_max = cheetah; --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check = Bear; +set global innodb_file_format_max = Bear; --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check = on; +set global innodb_file_format_max = on; --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check = off; +set global innodb_file_format_max = off; --enable_warnings diff --git a/mysql-test/suite/innodb/t/innodb_bug52745.test b/mysql-test/suite/innodb/t/innodb_bug52745.test index d2de869648b..686ca705ab7 100644 --- a/mysql-test/suite/innodb/t/innodb_bug52745.test +++ b/mysql-test/suite/innodb/t/innodb_bug52745.test @@ -1,7 +1,7 @@ -- source include/have_innodb.inc let $file_format=`select @@innodb_file_format`; -let $file_format_check=`select @@innodb_file_format_check`; +let $file_format_max=`select @@innodb_file_format_max`; let $file_per_table=`select @@innodb_file_per_table`; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=on; @@ -105,5 +105,5 @@ SHOW WARNINGS; DROP TABLE bug52745; EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_format_max=$file_format_max; EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb_bug53591.test b/mysql-test/suite/innodb/t/innodb_bug53591.test index 58a7596dff9..e0e568034d8 100644 --- a/mysql-test/suite/innodb/t/innodb_bug53591.test +++ b/mysql-test/suite/innodb/t/innodb_bug53591.test @@ -1,7 +1,7 @@ -- source include/have_innodb.inc let $file_format=`select @@innodb_file_format`; -let $file_format_check=`select @@innodb_file_format_check`; +let $file_format_max=`select @@innodb_file_format_max`; let $file_per_table=`select @@innodb_file_per_table`; SET GLOBAL innodb_file_format='Barracuda'; @@ -18,5 +18,5 @@ SHOW WARNINGS; DROP TABLE bug53591; EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_format_max=$file_format_max; EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb_file_format.test b/mysql-test/suite/innodb/t/innodb_file_format.test index 5d094cb9dba..aa411258da0 100644 --- a/mysql-test/suite/innodb/t/innodb_file_format.test +++ b/mysql-test/suite/innodb/t/innodb_file_format.test @@ -1,7 +1,12 @@ +-- source include/not_embedded.inc -- source include/have_innodb.inc +let $innodb_file_format_orig=`select @@innodb_file_format`; +let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; + select @@innodb_file_format; select @@innodb_file_format_check; +select @@innodb_file_format_max; set global innodb_file_format=antelope; set global innodb_file_format=barracuda; --error ER_WRONG_VALUE_FOR_VAR @@ -14,16 +19,24 @@ set global innodb_file_format=on; --error ER_WRONG_VALUE_FOR_VAR set global innodb_file_format=off; select @@innodb_file_format; -set global innodb_file_format_check=antelope; -set global innodb_file_format_check=barracuda; +set global innodb_file_format_max=antelope; +set global innodb_file_format_max=barracuda; --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check=cheetah; -select @@innodb_file_format_check; -set global innodb_file_format_check=default; -select @@innodb_file_format_check; +set global innodb_file_format_max=cheetah; +select @@innodb_file_format_max; +set global innodb_file_format_max=default; +select @@innodb_file_format_max; --error ER_WRONG_VALUE_FOR_VAR set global innodb_file_format=on; --error ER_WRONG_VALUE_FOR_VAR set global innodb_file_format=off; -select @@innodb_file_format_check; -set global innodb_file_format_check=antelope; +select @@innodb_file_format_max; +set global innodb_file_format_max=antelope; + +# innodb_file_format_check is read only variable, can be +# set as server startup parameter +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +set global innodb_file_format_check=off; + +eval SET GLOBAL innodb_file_format=$innodb_file_format_orig; +eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; diff --git a/mysql-test/t/innodb_gis.test b/mysql-test/suite/innodb/t/innodb_gis.test index 1adb14ea482..1adb14ea482 100644 --- a/mysql-test/t/innodb_gis.test +++ b/mysql-test/suite/innodb/t/innodb_gis.test diff --git a/mysql-test/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt index 462f8fbe828..462f8fbe828 100644 --- a/mysql-test/t/innodb_lock_wait_timeout_1-master.opt +++ b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test index fcbf2b1cfc7..fcbf2b1cfc7 100644 --- a/mysql-test/t/innodb_lock_wait_timeout_1.test +++ b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test diff --git a/mysql-test/suite/innodb/t/innodb_mysql-master.opt b/mysql-test/suite/innodb/t/innodb_mysql-master.opt new file mode 100644 index 00000000000..c46f5079568 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_mysql-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=2 --default-storage-engine=MyISAM diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index 2abcf48d686..fcd54075ecc 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -649,6 +649,19 @@ EXPLAIN SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0 DROP TABLE t1,t2; +--echo # +--echo # Bug#38999 valgrind warnings for update statement in function compare_record() +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); + +SELECT * FROM t1 WHERE a = 2; +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; + +DROP TABLE t1,t2; --echo # --echo # Bug #53830: !table || (!table->read_set || bitmap_is_set(table->read_set, field_index)) @@ -694,6 +707,36 @@ AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; DROP TABLE t1; +--echo # +--echo # Bug#51431 Wrong sort order after import of dump file +--echo # + +CREATE TABLE t1 ( + f1 INT(11) NOT NULL, + f2 int(11) NOT NULL, + f3 int(11) NOT NULL, + f4 tinyint(1) NOT NULL, + PRIMARY KEY (f1), + UNIQUE KEY (f2, f3), + KEY (f4) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES +(1,1,991,1), (2,1,992,1), (3,1,993,1), (4,1,994,1), (5,1,995,1), +(6,1,996,1), (7,1,997,1), (8,1,998,1), (10,1,999,1), (11,1,9910,1), +(16,1,9911,1), (17,1,9912,1), (18,1,9913,1), (19,1,9914,1), (20,1,9915,1), +(21,1,9916,1), (22,1,9917,1), (23,1,9918,1), (24,1,9919,1), (25,1,9920,1), +(26,1,9921,1), (27,1,9922,1); + +FLUSH TABLES; + +SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +EXPLAIN SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql_rbk-master.opt b/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt index 0e400f9c36b..0e400f9c36b 100644 --- a/mysql-test/t/innodb_mysql_rbk-master.opt +++ b/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt diff --git a/mysql-test/t/innodb_mysql_rbk.test b/mysql-test/suite/innodb/t/innodb_mysql_rbk.test index d2368c81f95..d2368c81f95 100644 --- a/mysql-test/t/innodb_mysql_rbk.test +++ b/mysql-test/suite/innodb/t/innodb_mysql_rbk.test diff --git a/mysql-test/t/innodb_notembedded.test b/mysql-test/suite/innodb/t/innodb_notembedded.test index c74dc931505..c74dc931505 100644 --- a/mysql-test/t/innodb_notembedded.test +++ b/mysql-test/suite/innodb/t/innodb_notembedded.test diff --git a/mysql-test/t/innodb_timeout_rollback-master.opt b/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt index 50921bb4df0..50921bb4df0 100644 --- a/mysql-test/t/innodb_timeout_rollback-master.opt +++ b/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt diff --git a/mysql-test/t/innodb_timeout_rollback.test b/mysql-test/suite/innodb/t/innodb_timeout_rollback.test index 99890971064..99890971064 100644 --- a/mysql-test/t/innodb_timeout_rollback.test +++ b/mysql-test/suite/innodb/t/innodb_timeout_rollback.test diff --git a/mysql-test/suite/parts/r/partition_alter3_innodb.result b/mysql-test/suite/parts/r/partition_alter3_innodb.result index cb104d4be54..dc6008842a3 100644 --- a/mysql-test/suite/parts/r/partition_alter3_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter3_innodb.result @@ -57,6 +57,7 @@ t1 CREATE TABLE `t1` ( `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 t1.frm +t1.ibd EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 20 Using where @@ -78,6 +79,7 @@ t1 CREATE TABLE `t1` ( `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -96,6 +98,7 @@ t1 CREATE TABLE `t1` ( `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (DAYOFYEAR(f_date)) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -112,6 +115,7 @@ t1 CREATE TABLE `t1` ( `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -137,6 +141,9 @@ t1 CREATE TABLE `t1` ( (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -161,6 +168,10 @@ t1 CREATE TABLE `t1` ( PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -186,6 +197,14 @@ t1 CREATE TABLE `t1` ( PARTITION p5 ENGINE = InnoDB, PARTITION p6 ENGINE = InnoDB, PARTITION p7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#p6.ibd +t1#P#p7.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -222,6 +241,13 @@ t1 CREATE TABLE `t1` ( PARTITION p4 ENGINE = InnoDB, PARTITION p5 ENGINE = InnoDB, PARTITION p6 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#p6.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -244,6 +270,12 @@ t1 CREATE TABLE `t1` ( PARTITION part2 ENGINE = InnoDB, PARTITION p4 ENGINE = InnoDB, PARTITION p5 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -265,6 +297,11 @@ t1 CREATE TABLE `t1` ( PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB, PARTITION p4 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -285,6 +322,10 @@ t1 CREATE TABLE `t1` ( PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -304,6 +345,9 @@ t1 CREATE TABLE `t1` ( (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -322,6 +366,8 @@ t1 CREATE TABLE `t1` ( /*!50100 PARTITION BY HASH (YEAR(f_date)) (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -339,6 +385,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) (PARTITION p0 ENGINE = InnoDB) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; @@ -359,6 +406,7 @@ t1 CREATE TABLE `t1` ( `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 t1.frm +t1.ibd EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 20 Using where @@ -398,6 +446,7 @@ t1 CREATE TABLE `t1` ( `f_charbig` varchar(1000) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 t1.frm +t1.ibd EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 20 Using where @@ -420,6 +469,7 @@ t1 CREATE TABLE `t1` ( `f_charbig` varchar(1000) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (f_int1) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -448,6 +498,9 @@ t1 CREATE TABLE `t1` ( (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -472,6 +525,10 @@ t1 CREATE TABLE `t1` ( PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -500,6 +557,14 @@ t1 CREATE TABLE `t1` ( PARTITION p5 ENGINE = InnoDB, PARTITION p6 ENGINE = InnoDB, PARTITION p7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#p6.ibd +t1#P#p7.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -534,6 +599,13 @@ t1 CREATE TABLE `t1` ( PARTITION p4 ENGINE = InnoDB, PARTITION p5 ENGINE = InnoDB, PARTITION p6 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#p6.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -559,6 +631,12 @@ t1 CREATE TABLE `t1` ( PARTITION part2 ENGINE = InnoDB, PARTITION p4 ENGINE = InnoDB, PARTITION p5 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#p5.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -583,6 +661,11 @@ t1 CREATE TABLE `t1` ( PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB, PARTITION p4 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#p4.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -606,6 +689,10 @@ t1 CREATE TABLE `t1` ( PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB, PARTITION part2 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -628,6 +715,9 @@ t1 CREATE TABLE `t1` ( (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB, PARTITION part7 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd +t1#P#part7.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -649,6 +739,8 @@ t1 CREATE TABLE `t1` ( /*!50100 PARTITION BY KEY (f_int1) (PARTITION p0 ENGINE = InnoDB, PARTITION part1 ENGINE = InnoDB) */ +t1#P#p0.ibd +t1#P#part1.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -669,6 +761,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (f_int1) (PARTITION p0 ENGINE = InnoDB) */ +t1#P#p0.ibd t1.frm t1.par EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; @@ -692,6 +785,7 @@ t1 CREATE TABLE `t1` ( `f_charbig` varchar(1000) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 t1.frm +t1.ibd EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 20 Using where diff --git a/mysql-test/suite/parts/r/partition_basic_innodb.result b/mysql-test/suite/parts/r/partition_basic_innodb.result index 21c5d70e6e3..c6a89e970b3 100644 --- a/mysql-test/suite/parts/r/partition_basic_innodb.result +++ b/mysql-test/suite/parts/r/partition_basic_innodb.result @@ -77,6 +77,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -532,6 +534,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -1002,6 +1009,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -1468,6 +1483,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -1930,6 +1951,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -2405,6 +2434,14 @@ SUBPARTITION BY KEY (f_int1) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -2882,6 +2919,14 @@ SUBPARTITION BY HASH (f_int1 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -3345,6 +3390,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -3802,6 +3856,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -4257,6 +4313,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -4727,6 +4788,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -5193,6 +5262,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -5655,6 +5730,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -6128,6 +6211,14 @@ SUBPARTITION BY KEY (f_int2) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -6601,6 +6692,14 @@ SUBPARTITION BY HASH (f_int2 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -7064,6 +7163,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -7527,6 +7635,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -8019,6 +8129,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -8526,6 +8641,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -9029,6 +9152,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -9528,6 +9657,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -10040,6 +10177,14 @@ SUBPARTITION BY KEY (f_int1) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -10554,6 +10699,14 @@ SUBPARTITION BY HASH (f_int1 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -11054,6 +11207,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -11547,6 +11709,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -12039,6 +12203,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -12546,6 +12715,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -13049,6 +13226,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -13548,6 +13731,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -14060,6 +14251,14 @@ SUBPARTITION BY KEY (f_int1) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -14574,6 +14773,14 @@ SUBPARTITION BY HASH (f_int1 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -15074,6 +15281,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -15567,6 +15783,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -16075,6 +16293,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -16598,6 +16821,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -17117,6 +17348,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -17632,6 +17869,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -18160,6 +18405,14 @@ SUBPARTITION BY KEY (f_int1) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -18690,6 +18943,14 @@ SUBPARTITION BY HASH (f_int1 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -19206,6 +19467,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -19720,6 +19990,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -20212,6 +20484,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -20719,6 +20996,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -21222,6 +21507,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -21721,6 +22012,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -22231,6 +22530,14 @@ SUBPARTITION BY KEY (f_int2) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -22741,6 +23048,14 @@ SUBPARTITION BY HASH (f_int2 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -23241,6 +23556,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -23734,6 +24058,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -24226,6 +24552,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -24733,6 +25064,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -25236,6 +25575,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -25735,6 +26080,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -26245,6 +26598,14 @@ SUBPARTITION BY KEY (f_int2) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -26755,6 +27116,14 @@ SUBPARTITION BY HASH (f_int2 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -27255,6 +27624,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par @@ -27748,6 +28126,8 @@ t1 CREATE TABLE `t1` ( PARTITIONS 2 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd t1.frm t1.par @@ -28256,6 +28636,11 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ unified filelist +t1#P#p0.ibd +t1#P#p1.ibd +t1#P#p2.ibd +t1#P#p3.ibd +t1#P#p4.ibd t1.frm t1.par @@ -28779,6 +29164,14 @@ t1 CREATE TABLE `t1` ( PARTITION part3 VALUES IN (3) ENGINE = InnoDB) */ unified filelist +t1#P#part0.ibd +t1#P#part1.ibd +t1#P#part2.ibd +t1#P#part3.ibd +t1#P#part_1.ibd +t1#P#part_2.ibd +t1#P#part_3.ibd +t1#P#part_N.ibd t1.frm t1.par @@ -29298,6 +29691,12 @@ t1 CREATE TABLE `t1` ( PARTITION partf VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta.ibd +t1#P#partb.ibd +t1#P#partc.ibd +t1#P#partd.ibd +t1#P#parte.ibd +t1#P#partf.ibd t1.frm t1.par @@ -29813,6 +30212,14 @@ SUBPARTITIONS 2 PARTITION partd VALUES LESS THAN (2147483646) ENGINE = InnoDB) */ unified filelist +t1#P#parta#SP#partasp0.ibd +t1#P#parta#SP#partasp1.ibd +t1#P#partb#SP#partbsp0.ibd +t1#P#partb#SP#partbsp1.ibd +t1#P#partc#SP#partcsp0.ibd +t1#P#partc#SP#partcsp1.ibd +t1#P#partd#SP#partdsp0.ibd +t1#P#partd#SP#partdsp1.ibd t1.frm t1.par @@ -30339,6 +30746,14 @@ SUBPARTITION BY KEY (f_int2) SUBPARTITION subpart42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#subpart11.ibd +t1#P#part1#SP#subpart12.ibd +t1#P#part2#SP#subpart21.ibd +t1#P#part2#SP#subpart22.ibd +t1#P#part3#SP#subpart31.ibd +t1#P#part3#SP#subpart32.ibd +t1#P#part4#SP#subpart41.ibd +t1#P#part4#SP#subpart42.ibd t1.frm t1.par @@ -30865,6 +31280,14 @@ SUBPARTITION BY HASH (f_int2 + 1) SUBPARTITION sp42 ENGINE = InnoDB)) */ unified filelist +t1#P#part1#SP#sp11.ibd +t1#P#part1#SP#sp12.ibd +t1#P#part2#SP#sp21.ibd +t1#P#part2#SP#sp22.ibd +t1#P#part3#SP#sp31.ibd +t1#P#part3#SP#sp32.ibd +t1#P#part4#SP#sp41.ibd +t1#P#part4#SP#sp42.ibd t1.frm t1.par @@ -31381,6 +31804,15 @@ SUBPARTITIONS 3 PARTITION part3 VALUES IN (NULL) ENGINE = InnoDB) */ unified filelist +t1#P#part1#SP#part1sp0.ibd +t1#P#part1#SP#part1sp1.ibd +t1#P#part1#SP#part1sp2.ibd +t1#P#part2#SP#part2sp0.ibd +t1#P#part2#SP#part2sp1.ibd +t1#P#part2#SP#part2sp2.ibd +t1#P#part3#SP#part3sp0.ibd +t1#P#part3#SP#part3sp1.ibd +t1#P#part3#SP#part3sp2.ibd t1.frm t1.par diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result index 73dc1178a54..55256894743 100644 --- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result +++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result @@ -25,7 +25,7 @@ wait/synch/rwlock/sql/LOCK_system_variables_hash YES YES wait/synch/rwlock/sql/LOCK_sys_init_connect YES YES wait/synch/rwlock/sql/LOCK_sys_init_slave YES YES wait/synch/rwlock/sql/LOGGER::LOCK_logger YES YES -wait/synch/rwlock/sql/MDL_context::waiting_for_lock YES YES +wait/synch/rwlock/sql/MDL_context::LOCK_waiting_for YES YES wait/synch/rwlock/sql/MDL_lock::rwlock YES YES wait/synch/rwlock/sql/Query_cache_query::lock YES YES wait/synch/rwlock/sql/THR_LOCK_servers YES YES diff --git a/mysql-test/suite/perfschema/t/no_threads-master.opt b/mysql-test/suite/perfschema/t/no_threads-master.opt index b15ab02821d..0dfb498094a 100644 --- a/mysql-test/suite/perfschema/t/no_threads-master.opt +++ b/mysql-test/suite/perfschema/t/no_threads-master.opt @@ -1 +1 @@ ---one-thread --thread-handling=no-threads --loose-performance-schema-max-thread_instances=10 +--one-thread --thread-handling=no-threads --loose-performance-schema-max-thread_instances=10 --default-storage-engine=MyISAM --skip-innodb diff --git a/mysql-test/suite/rpl/r/rpl_current_user.result b/mysql-test/suite/rpl/r/rpl_current_user.result new file mode 100644 index 00000000000..69c20078531 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_current_user.result @@ -0,0 +1,205 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); + +# On slave2 +# Connect slave2 to slave +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=SLAVE_MYPORT;, +MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; +START SLAVE; + +# [On master] +DROP VIEW IF EXISTS v_user; +DROP VIEW IF EXISTS v_tables_priv; +DROP VIEW IF EXISTS v_procs_priv; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS my_grant; +DROP PROCEDURE IF EXISTS my_revoke; +DROP FUNCTION IF EXISTS my_user; +DROP EVENT IF EXISTS e1; +CREATE TABLE t1(c1 char(100)); +CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; +CREATE PROCEDURE p1() SELECT 1; +# bug48321_1-01234 has the max length(16) of user. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; + +# Make sure the max lengths of user and host +# the user name is too lengh +GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; +ERROR HY000: String '01234567890123456' is too long for user name (should be no longer than 16) +# the host name is too lengh +GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; +ERROR HY000: String '0123456789012345678901234567890123456789012345678901234567890' is too long for host name (should be no longer than 60) + +# User 'bug48321_1-01234' connects to master by conn1 +# [On conn1] +# Verify 'REVOKE ALL' statement +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'GRANT ... ON TABLE ...' statement +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'GRANT ... ON PROCEDURE...' statement +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'GRANT ... ON *.* ...' statement +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'REVOKE ... ON TABLE ...' statement +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'REVOKE ... ON PROCEDURE...' statement +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'REVOKE ... ON *.* ...' statement +REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'GRANT ...' statement in the procedure +CREATE PROCEDURE my_grant() +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +call my_grant; +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'REVOKE ... ON TABLE ...' statement in the procedure +CREATE PROCEDURE my_revoke() +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +call my_revoke; +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'RENAME USER ...' statement +RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'DROP USER ...' statement +GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; +DROP USER CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'ALTER EVENT...' statement +CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; +# Explicitly assign CURRENT_USER() to definer +ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; +Comparing tables master:test.v_event and slave:test.v_event +Comparing tables master:test.v_event and slave2:test.v_event + +# Session user will be set as definer, if the statement does not assign +# a definer +ALTER EVENT e1 ENABLE; +Comparing tables master:test.v_event and slave:test.v_event +Comparing tables master:test.v_event and slave2:test.v_event + +# Verify that this patch does not affect the calling of CURRENT_USER() +# in the other statements +# [On master] +INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +SELECT * FROM t1; +c1 +root@localhost +1234 +# [On slave] +SELECT * FROM t1; +c1 +@ +1234 +# [On slave2] +SELECT * FROM t1; +c1 +@ +1234 +# [On master] +UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +SELECT * FROM t1; +c1 +root@localhost +root@localhost +# [On slave] +SELECT * FROM t1; +c1 +@ +@ +# [On slave2] +SELECT * FROM t1; +c1 +@ +@ +# [On master] +DELETE FROM t1 WHERE c1=CURRENT_USER(); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +SELECT * FROM t1; +c1 +# [On slave] +SELECT * FROM t1; +c1 +# [On slave2] +SELECT * FROM t1; +c1 +# [On master] +CREATE TABLE t2(c1 char(100)); +CREATE FUNCTION my_user() RETURNS VARCHAR(64) +SQL SECURITY INVOKER +BEGIN +INSERT INTO t2 VALUES(CURRENT_USER()); +RETURN CURRENT_USER(); +END | +INSERT INTO t1 VALUES(my_user()); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +SELECT * FROM t1; +c1 +root@localhost +SELECT * FROM t2; +c1 +root@localhost +# [On slave] +SELECT * FROM t1; +c1 +@ +SELECT * FROM t2; +c1 +@ +# [On slave2] +SELECT * FROM t1; +c1 +@ +SELECT * FROM t2; +c1 +@ + +# END +DROP TABLE t1, t2; +DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; +DROP PROCEDURE p1; +DROP PROCEDURE my_grant; +DROP PROCEDURE my_revoke; +DROP FUNCTION my_user; +DROP EVENT e1; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index dd0a2d89d54..daef153cdef 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -750,7 +750,7 @@ test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test_rpl e2 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) diff --git a/mysql-test/suite/rpl/r/rpl_row_loaddata_concurrent.result b/mysql-test/suite/rpl/r/rpl_row_loaddata_concurrent.result index abeb92a7d21..cb095ad561e 100644 --- a/mysql-test/suite/rpl/r/rpl_row_loaddata_concurrent.result +++ b/mysql-test/suite/rpl/r/rpl_row_loaddata_concurrent.result @@ -7,11 +7,11 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT +master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT +master-bin.000001 # Xid # # COMMIT /* XID */ DROP TABLE t1; stop slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; diff --git a/mysql-test/suite/rpl/r/rpl_slave_skip.result b/mysql-test/suite/rpl/r/rpl_slave_skip.result index d6513d838c3..5feba69b64d 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_skip.result +++ b/mysql-test/suite/rpl/r/rpl_slave_skip.result @@ -8,15 +8,15 @@ start slave; STOP SLAVE; **** On Master **** SET SESSION BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b INT); -CREATE TABLE t2 (c INT, d INT); +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1),(2,4),(3,9); INSERT INTO t2 VALUES (1,1),(2,8),(3,27); UPDATE t1,t2 SET b = d, d = b * 2 WHERE a = c; show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT) -master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (c INT, d INT) +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM +master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 0af76e93ab4..42f7a9c7ed8 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -1215,18 +1215,23 @@ lock table t2 write; # Sending 'insert into t1 (a) values (f1())'... insert into t1 (a) values (f1()); # Waitng for 'insert into t1 ...' to get blocked on table lock... -# Sending 'drop function f1'. It will abort the table lock wait. -drop function f1; +# Sending 'drop function f1'. It will wait till insert finishes. +drop function f1;; # --> connection default +# Check that 'drop function f1' gets blocked. # Now let's let 'insert' go through... unlock tables; -# --> connection con1 +# --> connection master # Reaping 'insert into t1 (a) values (f1())'... -ERROR 42000: FUNCTION test.f1 does not exist +# --> connection master1 +# Reaping 'drop function f1' +# --> connection master select * from t1; a +1 select * from t1; a +1 drop table t1, t2; drop function f1; ERROR 42000: FUNCTION test.f1 does not exist diff --git a/mysql-test/suite/rpl/r/rpl_stm_innodb.result b/mysql-test/suite/rpl/r/rpl_stm_innodb.result index 825238c66fe..f99457faaf0 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_stm_innodb.result @@ -66,7 +66,7 @@ SHOW CREATE TABLE mysqltest1.tmp2; Table Create Table tmp2 CREATE TEMPORARY TABLE `tmp2` ( `a` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ######### Must return no rows here ######### SELECT COUNT(*) FROM mysqltest1.t1; COUNT(*) diff --git a/mysql-test/suite/rpl/r/rpl_stm_loaddata_concurrent.result b/mysql-test/suite/rpl/r/rpl_stm_loaddata_concurrent.result index e204d67181a..417da0e2237 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_loaddata_concurrent.result +++ b/mysql-test/suite/rpl/r/rpl_stm_loaddata_concurrent.result @@ -1,10 +1,10 @@ RESET MASTER; -CREATE TABLE t1 (c1 char(50)); +CREATE TABLE t1 (c1 char(50)) ENGINE=MyISAM; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`c1`) ;file_id=# diff --git a/mysql-test/suite/rpl/t/rpl_current_user.cnf b/mysql-test/suite/rpl/t/rpl_current_user.cnf new file mode 100644 index 00000000000..999ee727a88 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.cnf @@ -0,0 +1,9 @@ +!include ../my.cnf + +[mysqld.3] +server-id=3 +log-bin=slave-bin + +[ENV] +SLAVE_MYPORT1= @mysqld.3.port +SLAVE_MYSOCK1= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_current_user.test b/mysql-test/suite/rpl/t/rpl_current_user.test new file mode 100644 index 00000000000..79816ef6c95 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.test @@ -0,0 +1,239 @@ +############################################################################## +# BUG#48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER, +# REVOKE, GRANT, ALTER EVENT +# +# Calling CURRENT_USER() results into inconsistency between slave and master, +# as the slave SQL thread has different user with common users. +# +# After the patch for bug#48321, session's user will be written into query log +# event if CURRENT_USER() is called in 'DROP/RENAME USER', 'REVOKE', 'GRANT', +# 'ALTER EVENT'. +# +############################################################################## +source include/master-slave.inc; +source include/have_binlog_format_statement.inc; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); + +--echo +--echo # On slave2 +connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT1,); +connection slave2; + +--echo # Connect slave2 to slave +--replace_result $SLAVE_MYPORT SLAVE_MYPORT; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, + MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; +START SLAVE; +source include/wait_for_slave_to_start.inc; + +--echo +--echo # [On master] +connection master; +--disable_warnings +DROP VIEW IF EXISTS v_user; +DROP VIEW IF EXISTS v_tables_priv; +DROP VIEW IF EXISTS v_procs_priv; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS my_grant; +DROP PROCEDURE IF EXISTS my_revoke; +DROP FUNCTION IF EXISTS my_user; +DROP EVENT IF EXISTS e1; +--enable_warnings +CREATE TABLE t1(c1 char(100)); +CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; +CREATE PROCEDURE p1() SELECT 1; +--echo # bug48321_1-01234 has the max length(16) of user. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; + +--echo +--echo # Make sure the max lengths of user and host +--echo # the user name is too lengh +--error 1470 +GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; +--echo # the host name is too lengh +--error 1470 +GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; + +--echo +--echo # User 'bug48321_1-01234' connects to master by conn1 +connect (conn1, 127.0.0.1, 'bug48321_1-01234'@'localhost',,); +connection conn1; +--echo # [On conn1] +--echo # Verify 'REVOKE ALL' statement +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); +let $diff_table= test.v_user; +let $diff_server_list= master, slave, slave2; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON TABLE ...' statement +connection conn1; +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON PROCEDURE...' statement +connection conn1; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); +let $diff_table= test.v_procs_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON *.* ...' statement +connection conn1; +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement +connection conn1; +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON PROCEDURE...' statement +connection conn1; +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); +let $diff_table= test.v_procs_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON *.* ...' statement +connection conn1; +REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); +let $diff_table= test.v_user; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ...' statement in the procedure +connection conn1; +CREATE PROCEDURE my_grant() + GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +call my_grant; +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement in the procedure +connection conn1; +CREATE PROCEDURE my_revoke() + REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +call my_revoke; +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'RENAME USER ...' statement +connection conn1; +RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; +let $diff_table= test.v_user; +source include/rpl_diff_tables.inc; + +disconnect conn1; + +--echo +--echo # Verify 'DROP USER ...' statement +connection master; +GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; +connect (conn1, 127.0.0.1, 'bug48321_2'@'localhost',,); +connection conn1; +DROP USER CURRENT_USER(); +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'ALTER EVENT...' statement +connection master; +CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; + +--echo # Explicitly assign CURRENT_USER() to definer +ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; +let $diff_table= test.v_event; +source include/rpl_diff_tables.inc; + +connection master; +--echo +--echo # Session user will be set as definer, if the statement does not assign +--echo # a definer +ALTER EVENT e1 ENABLE; +sync_slave_with_master; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify that this patch does not affect the calling of CURRENT_USER() +--echo # in the other statements +connection master; +--echo # [On master] +INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +--echo # [On slave2] +sync_slave_with_master slave2; +SELECT * FROM t1; + +connection master; +--echo # [On master] +UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; + +connection master; +--echo # [On master] +DELETE FROM t1 WHERE c1=CURRENT_USER(); +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; + +connection master; +--echo # [On master] +CREATE TABLE t2(c1 char(100)); + +DELIMITER |; +CREATE FUNCTION my_user() RETURNS VARCHAR(64) + SQL SECURITY INVOKER +BEGIN + INSERT INTO t2 VALUES(CURRENT_USER()); + RETURN CURRENT_USER(); +END | +DELIMITER ;| + +INSERT INTO t1 VALUES(my_user()); +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; +SELECT * FROM t2; + +--echo +--echo # END +connection master; +DROP TABLE t1, t2; +DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; +DROP PROCEDURE p1; +DROP PROCEDURE my_grant; +DROP PROCEDURE my_revoke; +DROP FUNCTION my_user; +DROP EVENT e1; +sync_slave_with_master; +sync_slave_with_master slave2; +source include/master-slave-end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt index de86b63f230..bd7728134c7 100644 --- a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt +++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt @@ -1,2 +1,2 @@ ---binlog_ignore_db=test_ignore +--binlog_ignore_db=test_ignore --default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size-master.opt b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size-master.opt index 45631525481..eb56e5c0a09 100644 --- a/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size-master.opt +++ b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size-master.opt @@ -1 +1 @@ ---binlog_cache_size=4096 --max_binlog_cache_size=7680 +--binlog_cache_size=4096 --max_binlog_cache_size=7680 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt index e0d075c3fbd..773ec62bef2 100644 --- a/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt +++ b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt @@ -1 +1,2 @@ --skip-external-locking +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_slave_skip.test b/mysql-test/suite/rpl/t/rpl_slave_skip.test index fc0936cea09..66762d4dad0 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_skip.test +++ b/mysql-test/suite/rpl/t/rpl_slave_skip.test @@ -17,8 +17,8 @@ STOP SLAVE; connection master; SET SESSION BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b INT); -CREATE TABLE t2 (c INT, d INT); +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1),(2,4),(3,9); INSERT INTO t2 VALUES (1,1),(2,8),(3,27); let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1); diff --git a/mysql-test/suite/rpl/t/rpl_sp.test b/mysql-test/suite/rpl/t/rpl_sp.test index 8ca4ff51eda..8510f387111 100644 --- a/mysql-test/suite/rpl/t/rpl_sp.test +++ b/mysql-test/suite/rpl/t/rpl_sp.test @@ -657,17 +657,25 @@ connection master1; let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='insert into t1 (a) values (f1())'; --source include/wait_condition.inc ---echo # Sending 'drop function f1'. It will abort the table lock wait. -drop function f1; +--echo # Sending 'drop function f1'. It will wait till insert finishes. +--send drop function f1; --echo # --> connection default connection default; +--echo # Check that 'drop function f1' gets blocked. +let $wait_condition=select count(*)=1 from information_schema.processlist +where state='Waiting for table' and info='drop function f1'; +--source include/wait_condition.inc --echo # Now let's let 'insert' go through... unlock tables; ---echo # --> connection con1 +--echo # --> connection master connection master; --echo # Reaping 'insert into t1 (a) values (f1())'... ---error ER_SP_DOES_NOT_EXIST --reap +--echo # --> connection master1 +connection master1; +--echo # Reaping 'drop function f1' +--reap +--echo # --> connection master connection master; select * from t1; sync_slave_with_master; diff --git a/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test index 2ea95a63fb5..7add76c0ef5 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test +++ b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test @@ -4,7 +4,7 @@ RESET MASTER; let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); -CREATE TABLE t1 (c1 char(50)); +CREATE TABLE t1 (c1 char(50)) ENGINE=MyISAM; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; -- source include/show_binlog_events.inc diff --git a/mysql-test/suite/rpl/t/rpl_sync-master.opt b/mysql-test/suite/rpl/t/rpl_sync-master.opt new file mode 100644 index 00000000000..ad327ce0454 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sync-master.opt @@ -0,0 +1,2 @@ +--default-storage-engine=MyISAM +--innodb-file-per-table=0 diff --git a/mysql-test/suite/rpl/t/rpl_sync-slave.opt b/mysql-test/suite/rpl/t/rpl_sync-slave.opt index 972f9ef8af9..7d6147ed59a 100644 --- a/mysql-test/suite/rpl/t/rpl_sync-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_sync-slave.opt @@ -1 +1 @@ ---sync-relay-log-info=1 --relay-log-recovery=1 --innodb_file_format_check='ON' +--sync-relay-log-info=1 --relay-log-recovery=1 --innodb_file_format_check='ON' --default-storage-engine=MyISAM --innodb-file-per-table=0 diff --git a/mysql-test/suite/rpl/t/rpl_temp_temporary-master.opt b/mysql-test/suite/rpl/t/rpl_temp_temporary-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temp_temporary-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 0f741ff930a..7f6dca3eb7b 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -10,5 +10,7 @@ There should be *no* long test name listed below: select variable_name as `There should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; There should be *no* variables listed below: +INNODB_FILE_FORMAT_MAX +INNODB_FILE_FORMAT_MAX drop table t1; drop table t2; diff --git a/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result b/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result index 541c0b6b328..c2acc7ab5ac 100644 --- a/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result +++ b/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result @@ -1,22 +1,22 @@ SET @start_global_value = @@global.default_storage_engine; SELECT @start_global_value; @start_global_value -MyISAM +InnoDB SET @start_session_value = @@session.default_storage_engine; SELECT @start_session_value; @start_session_value -MyISAM +InnoDB '#--------------------FN_DYNVARS_005_01-------------------------#' SET @@global.default_storage_engine = INNODB; SET @@global.default_storage_engine = DEFAULT; SELECT @@global.default_storage_engine; @@global.default_storage_engine -MyISAM +InnoDB SET @@session.default_storage_engine = INNODB; SET @@session.default_storage_engine = DEFAULT; SELECT @@session.default_storage_engine; @@session.default_storage_engine -MyISAM +InnoDB '#--------------------FN_DYNVARS_005_02-------------------------#' SET @@global.default_storage_engine = MYISAM; SELECT @@global.default_storage_engine; @@ -110,8 +110,8 @@ SET @@default_storage_engine = @start_global_value; SET @@global.default_storage_engine = @start_global_value; SELECT @@global.default_storage_engine; @@global.default_storage_engine -MyISAM +InnoDB SET @@session.default_storage_engine = @start_session_value; SELECT @@session.default_storage_engine; @@session.default_storage_engine -MyISAM +InnoDB diff --git a/mysql-test/suite/sys_vars/r/innodb_file_format_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_format_basic.result index 58e009ea705..41369038cf6 100644 --- a/mysql-test/suite/sys_vars/r/innodb_file_format_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_file_format_basic.result @@ -1,28 +1,28 @@ SET @start_global_value = @@global.innodb_file_format; SELECT @start_global_value; @start_global_value -Antelope +Barracuda Valid values are 'Antelope' and 'Barracuda' select @@global.innodb_file_format in ('Antelope', 'Barracuda'); @@global.innodb_file_format in ('Antelope', 'Barracuda') 1 select @@global.innodb_file_format; @@global.innodb_file_format -Antelope +Barracuda select @@session.innodb_file_format; ERROR HY000: Variable 'innodb_file_format' is a GLOBAL variable show global variables like 'innodb_file_format'; Variable_name Value -innodb_file_format Antelope +innodb_file_format Barracuda show session variables like 'innodb_file_format'; Variable_name Value -innodb_file_format Antelope +innodb_file_format Barracuda select * from information_schema.global_variables where variable_name='innodb_file_format'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT Antelope +INNODB_FILE_FORMAT Barracuda select * from information_schema.session_variables where variable_name='innodb_file_format'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT Antelope +INNODB_FILE_FORMAT Barracuda set global innodb_file_format='Antelope'; select @@global.innodb_file_format; @@global.innodb_file_format @@ -56,4 +56,4 @@ ERROR 42000: Variable 'innodb_file_format' can't be set to the value of 'Salmon' SET @@global.innodb_file_format = @start_global_value; SELECT @@global.innodb_file_format; @@global.innodb_file_format -Antelope +Barracuda diff --git a/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result index 29be30cf096..c59e1b802f4 100644 --- a/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result @@ -1,59 +1,59 @@ -SET @start_global_value = @@global.innodb_file_format_check; +SET @start_global_value = @@global.innodb_file_format_max; SELECT @start_global_value; @start_global_value Antelope Valid values are 'Antelope' and 'Barracuda' -select @@global.innodb_file_format_check in ('Antelope', 'Barracuda'); -@@global.innodb_file_format_check in ('Antelope', 'Barracuda') +select @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); +@@global.innodb_file_format_max in ('Antelope', 'Barracuda') 1 -select @@global.innodb_file_format_check; -@@global.innodb_file_format_check +select @@global.innodb_file_format_max; +@@global.innodb_file_format_max Antelope -select @@session.innodb_file_format_check; -ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable -show global variables like 'innodb_file_format_check'; +select @@session.innodb_file_format_max; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable +show global variables like 'innodb_file_format_max'; Variable_name Value -innodb_file_format_check Antelope -show session variables like 'innodb_file_format_check'; +innodb_file_format_max Antelope +show session variables like 'innodb_file_format_max'; Variable_name Value -innodb_file_format_check Antelope -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; +innodb_file_format_max Antelope +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Antelope -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; +INNODB_FILE_FORMAT_MAX Antelope +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Antelope -set global innodb_file_format_check='Antelope'; -select @@global.innodb_file_format_check; -@@global.innodb_file_format_check +INNODB_FILE_FORMAT_MAX Antelope +set global innodb_file_format_max='Antelope'; +select @@global.innodb_file_format_max; +@@global.innodb_file_format_max Antelope -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Antelope -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; +INNODB_FILE_FORMAT_MAX Antelope +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Antelope -set @@global.innodb_file_format_check='Barracuda'; -select @@global.innodb_file_format_check; -@@global.innodb_file_format_check +INNODB_FILE_FORMAT_MAX Antelope +set @@global.innodb_file_format_max='Barracuda'; +select @@global.innodb_file_format_max; +@@global.innodb_file_format_max Barracuda -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Barracuda -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; +INNODB_FILE_FORMAT_MAX Barracuda +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_CHECK Barracuda -set session innodb_file_format_check='Salmon'; -ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable and should be set with SET GLOBAL -set @@session.innodb_file_format_check='Salmon'; -ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable and should be set with SET GLOBAL -set global innodb_file_format_check=1.1; -ERROR 42000: Incorrect argument type to variable 'innodb_file_format_check' -set global innodb_file_format_check=1e1; -ERROR 42000: Incorrect argument type to variable 'innodb_file_format_check' -set global innodb_file_format_check='Salmon'; -ERROR 42000: Variable 'innodb_file_format_check' can't be set to the value of 'Salmon' -SET @@global.innodb_file_format_check = @start_global_value; -SELECT @@global.innodb_file_format_check; -@@global.innodb_file_format_check +INNODB_FILE_FORMAT_MAX Barracuda +set session innodb_file_format_max='Salmon'; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL +set @@session.innodb_file_format_max='Salmon'; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL +set global innodb_file_format_max=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' +set global innodb_file_format_max=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' +set global innodb_file_format_max='Salmon'; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'Salmon' +SET @@global.innodb_file_format_max = @start_global_value; +SELECT @@global.innodb_file_format_max; +@@global.innodb_file_format_max Antelope diff --git a/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result b/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result index 200f9166215..5e55faa99c9 100644 --- a/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result @@ -1,32 +1,32 @@ SET @start_global_value = @@global.innodb_strict_mode; SELECT @start_global_value; @start_global_value -0 +1 Valid values are 'ON' and 'OFF' select @@global.innodb_strict_mode in (0, 1); @@global.innodb_strict_mode in (0, 1) 1 select @@global.innodb_strict_mode; @@global.innodb_strict_mode -0 +1 select @@session.innodb_strict_mode in (0, 1); @@session.innodb_strict_mode in (0, 1) 1 select @@session.innodb_strict_mode; @@session.innodb_strict_mode -0 +1 show global variables like 'innodb_strict_mode'; Variable_name Value -innodb_strict_mode OFF +innodb_strict_mode ON show session variables like 'innodb_strict_mode'; Variable_name Value -innodb_strict_mode OFF +innodb_strict_mode ON select * from information_schema.global_variables where variable_name='innodb_strict_mode'; VARIABLE_NAME VARIABLE_VALUE -INNODB_STRICT_MODE OFF +INNODB_STRICT_MODE ON select * from information_schema.session_variables where variable_name='innodb_strict_mode'; VARIABLE_NAME VARIABLE_VALUE -INNODB_STRICT_MODE OFF +INNODB_STRICT_MODE ON set global innodb_strict_mode='OFF'; set session innodb_strict_mode='OFF'; select @@global.innodb_strict_mode; @@ -117,4 +117,4 @@ INNODB_STRICT_MODE ON SET @@global.innodb_strict_mode = @start_global_value; SELECT @@global.innodb_strict_mode; @@global.innodb_strict_mode -0 +1 diff --git a/mysql-test/suite/sys_vars/r/storage_engine_basic.result b/mysql-test/suite/sys_vars/r/storage_engine_basic.result index 5e80f1343b7..6f10ec475a0 100644 --- a/mysql-test/suite/sys_vars/r/storage_engine_basic.result +++ b/mysql-test/suite/sys_vars/r/storage_engine_basic.result @@ -1,22 +1,22 @@ SET @start_global_value = @@global.storage_engine; SELECT @start_global_value; @start_global_value -MyISAM +InnoDB SET @start_session_value = @@session.storage_engine; SELECT @start_session_value; @start_session_value -MyISAM +InnoDB '#--------------------FN_DYNVARS_005_01-------------------------#' SET @@global.storage_engine = INNODB; SET @@global.storage_engine = DEFAULT; SELECT @@global.storage_engine; @@global.storage_engine -MyISAM +InnoDB SET @@session.storage_engine = INNODB; SET @@session.storage_engine = DEFAULT; SELECT @@session.storage_engine; @@session.storage_engine -MyISAM +InnoDB '#--------------------FN_DYNVARS_005_02-------------------------#' SET @@global.storage_engine = MYISAM; SELECT @@global.storage_engine; @@ -110,8 +110,8 @@ SET @@storage_engine = @start_global_value; SET @@global.storage_engine = @start_global_value; SELECT @@global.storage_engine; @@global.storage_engine -MyISAM +InnoDB SET @@session.storage_engine = @start_session_value; SELECT @@session.storage_engine; @@session.storage_engine -MyISAM +InnoDB diff --git a/mysql-test/suite/sys_vars/t/default_storage_engine_basic.test b/mysql-test/suite/sys_vars/t/default_storage_engine_basic.test index 17f2d2cc852..f47453eb234 100644 --- a/mysql-test/suite/sys_vars/t/default_storage_engine_basic.test +++ b/mysql-test/suite/sys_vars/t/default_storage_engine_basic.test @@ -15,6 +15,7 @@ # # ######################################################################## +--source include/not_embedded.inc --source include/have_innodb.inc --source include/load_sysvars.inc diff --git a/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test b/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test index 4c60957561c..cbf25af2442 100644 --- a/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test @@ -2,54 +2,54 @@ # 2010-01-25 - Added # - +--source include/not_embedded.inc --source include/have_innodb.inc -SET @start_global_value = @@global.innodb_file_format_check; +SET @start_global_value = @@global.innodb_file_format_max; SELECT @start_global_value; # # exists as global only # --echo Valid values are 'Antelope' and 'Barracuda' -select @@global.innodb_file_format_check in ('Antelope', 'Barracuda'); -select @@global.innodb_file_format_check; +select @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); +select @@global.innodb_file_format_max; --error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.innodb_file_format_check; -show global variables like 'innodb_file_format_check'; -show session variables like 'innodb_file_format_check'; -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; +select @@session.innodb_file_format_max; +show global variables like 'innodb_file_format_max'; +show session variables like 'innodb_file_format_max'; +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; # # show that it's writable # -set global innodb_file_format_check='Antelope'; -select @@global.innodb_file_format_check; -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; -set @@global.innodb_file_format_check='Barracuda'; -select @@global.innodb_file_format_check; -select * from information_schema.global_variables where variable_name='innodb_file_format_check'; -select * from information_schema.session_variables where variable_name='innodb_file_format_check'; +set global innodb_file_format_max='Antelope'; +select @@global.innodb_file_format_max; +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; +set @@global.innodb_file_format_max='Barracuda'; +select @@global.innodb_file_format_max; +select * from information_schema.global_variables where variable_name='innodb_file_format_max'; +select * from information_schema.session_variables where variable_name='innodb_file_format_max'; --error ER_GLOBAL_VARIABLE -set session innodb_file_format_check='Salmon'; +set session innodb_file_format_max='Salmon'; --error ER_GLOBAL_VARIABLE -set @@session.innodb_file_format_check='Salmon'; +set @@session.innodb_file_format_max='Salmon'; # # incorrect types # --error ER_WRONG_TYPE_FOR_VAR -set global innodb_file_format_check=1.1; +set global innodb_file_format_max=1.1; --error ER_WRONG_TYPE_FOR_VAR -set global innodb_file_format_check=1e1; +set global innodb_file_format_max=1e1; --error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_check='Salmon'; +set global innodb_file_format_max='Salmon'; # # Cleanup # -SET @@global.innodb_file_format_check = @start_global_value; -SELECT @@global.innodb_file_format_check; +SET @@global.innodb_file_format_max = @start_global_value; +SELECT @@global.innodb_file_format_max; diff --git a/mysql-test/suite/sys_vars/t/storage_engine_basic.test b/mysql-test/suite/sys_vars/t/storage_engine_basic.test index 7ec071e6414..49e8a52efea 100644 --- a/mysql-test/suite/sys_vars/t/storage_engine_basic.test +++ b/mysql-test/suite/sys_vars/t/storage_engine_basic.test @@ -21,6 +21,7 @@ # # ######################################################################## +--source include/not_embedded.inc --source include/have_innodb.inc --source include/load_sysvars.inc diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 5b61176b0f6..a3665e5f455 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1670,6 +1670,15 @@ SELECT * FROM t1; --error ER_BAD_TABLE_ERROR DROP TABLE t1; +--echo # +--echo # Ensure that TRUNCATE fails for non-empty archive tables. +--echo # +CREATE TABLE t1 (a INT) ENGINE=ARCHIVE; +INSERT INTO t1 VALUES (1); +--error ER_ILLEGAL_HA +TRUNCATE TABLE t1; +DROP TABLE t1; + --echo # --echo # BUG#46565 - repair of partition fail for archive engine diff --git a/mysql-test/t/bootstrap-master.opt b/mysql-test/t/bootstrap-master.opt new file mode 100644 index 00000000000..31a799e4d9b --- /dev/null +++ b/mysql-test/t/bootstrap-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM --skip-innodb diff --git a/mysql-test/t/bootstrap.test b/mysql-test/t/bootstrap.test index db89269b35d..e98afb81ff1 100644 --- a/mysql-test/t/bootstrap.test +++ b/mysql-test/t/bootstrap.test @@ -8,8 +8,7 @@ drop table if exists t1; # Add the datadir to the bootstrap command let $MYSQLD_DATADIR= `select @@datadir`; -let $MYSQLD_BOOTSTRAP_CMD= $MYSQLD_BOOTSTRAP_CMD --datadir=$MYSQLD_DATADIR; - +let $MYSQLD_BOOTSTRAP_CMD= $MYSQLD_BOOTSTRAP_CMD --datadir=$MYSQLD_DATADIR --default-storage-engine=MyISAM --skip-innodb; # # Check that --bootstrap reads from stdin # @@ -20,7 +19,6 @@ EOF --exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 drop table t1; remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql; - # # Check that --bootstrap of file with SQL error returns error # diff --git a/mysql-test/t/bug46760.test b/mysql-test/t/bug46760.test index f55edbbfa42..e7f57549250 100644 --- a/mysql-test/t/bug46760.test +++ b/mysql-test/t/bug46760.test @@ -29,7 +29,7 @@ DROP TABLE t1; --echo # ROW_FORMAT=COMPRESSED --echo # -CREATE TABLE t1 (a INT) ROW_FORMAT=compressed; +CREATE TABLE t1 (a INT) ROW_FORMAT=compressed, ENGINE=MyISAM; SHOW CREATE TABLE t1; OPTIMIZE TABLE t1; SHOW CREATE TABLE t1; diff --git a/mysql-test/t/commit.test b/mysql-test/t/commit.test new file mode 100644 index 00000000000..261867bd5cc --- /dev/null +++ b/mysql-test/t/commit.test @@ -0,0 +1,350 @@ +--source include/have_innodb.inc + +connect (con1,localhost,root,,); + +--echo # +--echo # Bug#20837 Apparent change of isolation level +--echo # during transaction +--echo # +--echo # Bug#53343 completion_type=1, COMMIT/ROLLBACK +--echo # AND CHAIN don't preserve the isolation +--echo # level +# +# A set of test cases that verifies operation of +# transaction isolation level and chaining is +# provided + +# init +--echo connection default; +connection default; + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +CREATE TABLE t1 (s1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; + +# +# Verify that SET TRANS ISO LEVEL is not allowed +# inside a transaction +# +START TRANSACTION; +--error ER_CANT_CHANGE_TX_ISOLATION +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +COMMIT; + +# +# Verify consistent output from +# SELECT @@tx_isolation (Bug#20837) +# +# The transaction will be in READ UNCOMMITTED mode, +# but SELECT @@tx_isolation should report the session +# value, which is REPEATABLE READ +# +SET @@autocommit=0; +COMMIT; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +START TRANSACTION; +SELECT @@tx_isolation; +--echo Should be REPEATABLE READ +SELECT * FROM t1; +SELECT @@tx_isolation; +--echo Should be REPEATABLE READ +INSERT INTO t1 VALUES (-1); +SELECT @@tx_isolation; +--echo Should be REPEATABLE READ +COMMIT; + +# +# Verify that a change in the session variable +# does not affect the currently started +# transaction +# +START TRANSACTION; +SELECT * FROM t1; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; + +--echo connection con1 +connection con1; +START TRANSACTION; +INSERT INTO t1 VALUES (1000); +COMMIT; + +--echo connection default +connection default; +--echo We should not be able to read the '1000' +SELECT * FROM t1; +COMMIT; + +--echo Now, the '1000' should appear. +START TRANSACTION; +SELECT * FROM t1; +COMMIT; + +# restore the session value +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; + +# +# A set of test cases for verification that +# isolation level during chaining works. MySQL +# has three variants of chaining, i.e +# COMMIT AND CHAIN, ROLLBACK AND CHAIN, and +# the use of @completion_type +# + +# +# Verify isolation level with COMMIT AND CHAIN +# +# COMMIT AND CHAIN causes a new transaction to +# begin as soon as the current ends, and the new +# transaction will have the same tran. iso. level +# as the first. +# +--echo connection default +connection default; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; + +--echo connection con1 +connection con1; +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; + +--echo connection default +connection default; +SELECT COUNT(*) FROM t1 WHERE s1 = 1001; +--echo Should be 1 +COMMIT AND CHAIN; + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1002); +COMMIT; + +--echo connection default +connection default; +SELECT COUNT(*) FROM t1 WHERE s1 = 1002; +--echo Should be 1 +COMMIT; +SELECT * FROM t1; +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; + +# +# Verify isolation level with ROLLBACK AND CHAIN +# +--echo connection default +connection default; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; + +--echo connection con1 +connection con1; +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; + +--echo connection default +connection default; +SELECT COUNT(*) FROM t1 WHERE s1 = 1001; +--echo Should be 1 +ROLLBACK AND CHAIN; + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1002); +COMMIT; + +--echo connection default +connection default; +SELECT COUNT(*) FROM t1 WHERE s1 = 1002; +--echo Should be 1 +COMMIT; +SELECT * FROM t1; +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; + +# +# Verify isolation level with @completion_type=1. +# (A @@completion_type value of 1 is equivalentl to +# explicitly adding "AND CHAIN" to COMMIT or ROLLBACK) +# + +# +# Verify that COMMIT AND NO CHAIN overrides the value +# of @@completion_type +# +SET @@completion_type=1; + +--echo connection default +connection default; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; + +--echo connection con1 +connection con1; +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 +COMMIT AND NO CHAIN; +--echo default transaction is now in REPEATABLE READ + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1002); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 and 1002 + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1003); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 and 1002, but NOT 1003 +COMMIT; + +SELECT * FROM t1; +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT AND NO CHAIN; +SET @@completion_type=0; +COMMIT; + +# +# Verify that ROLLBACK AND NO CHAIN overrides the value +# of @@completion_type +# +--echo connection default +connection default; +SET @@completion_type=1; +COMMIT AND NO CHAIN; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; + +--echo connection con1 +connection con1; +START TRANSACTION; +INSERT INTO t1 VALUES (1001); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 +ROLLBACK AND NO CHAIN; +--echo default transaction is now in REPEATABLE READ + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1002); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 and 1002 + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1003); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1 WHERE s1 >= 1000; +--echo Should see 1001 and 1002, but NOT 1003 + +COMMIT; +SELECT * FROM t1; +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT AND NO CHAIN; +SET @@completion_type=0; +COMMIT; + +# +# Verify that in the sequence: +# SET TRANSACTION ISOLATION LEVEL +# SET SESSION ISOLATION LEVEL +# +# SET SESSION ISOLATION LEVEL has precedence over +# SET TRANSACTION. (Note that this is _not_ +# in accordance with ISO 9075.) +# +--echo connection default +connection default; + +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +START TRANSACTION; +SELECT * FROM t1; + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1000); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1; +--echo Should get same result as above (i.e should not read '1000') +COMMIT; + +DELETE FROM t1 WHERE s1 >= 1000; +COMMIT; + + +# +# Verify that a transaction ended with an +# implicit commit (i.e a DDL statement), the +# @@completetion_type setting is ignored, and +# the next transaction's isolation level is +# the session level. +# +SET @@completion_type=1; +COMMIT AND NO CHAIN; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES (1000); +SELECT * FROM t1; +--echo Should read '1000' + +--echo connection con1 +connection con1; +INSERT INTO t1 VALUES (1001); +COMMIT; + +--echo connection default +connection default; +SELECT * FROM t1; +--echo Should only read the '1000' as this transaction is now in REP READ +COMMIT AND NO CHAIN; + +SET @@completion_type=0; +COMMIT AND NO CHAIN; + + +# +# Cleanup +# +SET @autocommit=1; +COMMIT; + +disconnect con1; + +DROP TABLE t1; + +--echo # +--echo # End of test cases for Bug#20837 +--echo # diff --git a/mysql-test/t/crash_commit_before-master.opt b/mysql-test/t/crash_commit_before-master.opt index a745693594e..cd2ae9b1455 100644 --- a/mysql-test/t/crash_commit_before-master.opt +++ b/mysql-test/t/crash_commit_before-master.opt @@ -1,2 +1,3 @@ --skip-stack-trace --skip-core-file - +--default-storage-engine=MyISAM +--innodb-file-per-table=0 diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 383ba98ae6d..887ae4da404 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -102,6 +102,22 @@ create table t1 (`` int); create table t1 (i int, index `` (i)); # +# CREATE TABLE under LOCK TABLES +# +# We don't allow creation of non-temporary tables under LOCK TABLES +# as following meta-data locking protocol in this case can lead to +# deadlock. +create table t1 (i int); +lock tables t1 read; +--error ER_TABLE_NOT_LOCKED +create table t2 (j int); +# OTOH creating of temporary table should be OK +create temporary table t2 (j int); +drop temporary table t2; +unlock tables; +drop table t1; + +# # Test of CREATE ... SELECT with indexes # @@ -315,6 +331,26 @@ drop table t3; drop database mysqltest; # +# CREATE TABLE LIKE under LOCK TABLES +# +# Similarly to ordinary CREATE TABLE we don't allow creation of +# non-temporary tables under LOCK TABLES. Also we require source +# table to be locked. +create table t1 (i int); +create table t2 (j int); +lock tables t1 read; +--error ER_TABLE_NOT_LOCKED +create table t3 like t1; +# OTOH creating of temporary table should be OK +create temporary table t3 like t1; +drop temporary table t3; +# Source table should be locked +--error ER_TABLE_NOT_LOCKED +create temporary table t3 like t2; +unlock tables; +drop tables t1, t2; + +# # Test default table type # SET SESSION storage_engine="heap"; @@ -1731,3 +1767,34 @@ DROP TABLE t1; DROP TEMPORARY TABLE t2; + +--echo # +--echo # Bug #22909 "Using CREATE ... LIKE is possible to create field +--echo # with invalid default value" +--echo # +--echo # Altough original bug report suggests to use older version of MySQL +--echo # for producing .FRM with invalid defaults we use sql_mode to achieve +--echo # the same effect. +--disable_warnings +drop tables if exists t1, t2; +--enable_warnings +--echo # Attempt to create table with invalid default should fail in normal mode +--error ER_INVALID_DEFAULT +create table t1 (dt datetime default '2008-02-31 00:00:00'); +set @old_mode= @@sql_mode; +set @@sql_mode='ALLOW_INVALID_DATES'; +--echo # The same should be possible in relaxed mode +create table t1 (dt datetime default '2008-02-31 00:00:00'); +set @@sql_mode= @old_mode; +--echo # In normal mode attempt to create copy of table with invalid +--echo # default should fail +--error ER_INVALID_DEFAULT +create table t2 like t1; +set @@sql_mode='ALLOW_INVALID_DATES'; +--echo # But should work in relaxed mode +create table t2 like t1; +--echo # Check that table definitions match +show create table t1; +show create table t2; +set @@sql_mode= @old_mode; +drop tables t1, t2; diff --git a/mysql-test/t/ctype_utf8-master.opt b/mysql-test/t/ctype_utf8-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/ctype_utf8-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/ctype_utf8mb4-master.opt b/mysql-test/t/ctype_utf8mb4-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/ctype_utf8mb4-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/ctype_utf8mb4_innodb-master.opt b/mysql-test/t/ctype_utf8mb4_innodb-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/ctype_utf8mb4_innodb-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test index 5ef4a28b202..b5ca0817b6f 100644 --- a/mysql-test/t/drop.test +++ b/mysql-test/t/drop.test @@ -256,3 +256,20 @@ SHOW WARNINGS; --echo # -- --echo # -- End of Bug#37431. --echo # -- + + +--echo # +--echo # Bug#54282 Crash in MDL_context::upgrade_shared_lock_to_exclusive +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT); +LOCK TABLE t1 WRITE; +--error ER_NONUNIQ_TABLE +DROP TABLE t1, t1; + +UNLOCK TABLES; +DROP TABLE t1; diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test index 7a48a2e3231..f6edacfaa29 100644 --- a/mysql-test/t/error_simulation.test +++ b/mysql-test/t/error_simulation.test @@ -45,7 +45,6 @@ SHOW CREATE TABLE t1; SELECT * FROM t1; DROP TABLE t1; - --echo # --echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string --echo # @@ -60,6 +59,36 @@ SET SESSION debug=DEFAULT; DROP TABLE t1; +-- echo # +-- echo # Bug#41660: Sort-index_merge for non-first join table may require +-- echo # O(#scans) memory +-- echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); + +CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b)); +INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C; +INSERT INTO t2 VALUES (1, 1, 'data'); + +--echo # the example query uses LEFT JOIN only for the sake of being able to +--echo # demonstrate the issue with a very small dataset. (left outer join +--echo # disables the use of join buffering, so we get the second table +--echo # re-scanned for every record in the outer table. if we used inner join, +--echo # we would need to have thousands of records and/or more columns in both +--echo # tables so that the join buffer is filled and re-scans are triggered). + +SET SESSION debug = '+d,only_one_Unique_may_be_created'; + +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); + +SET SESSION debug = DEFAULT; + +DROP TABLE t1, t2; + --echo # --echo # End of 5.1 tests --echo # diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 61ae812d874..6efeb2866e6 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -540,5 +540,20 @@ EXPLAIN SELECT * FROM t1 WHERE c_char IN (NULL, NULL); DROP TABLE t1; --echo # +--echo # Bug#54477: Crash on IN / CASE with NULL arguments +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +SELECT 1 IN (NULL, a) FROM t1; + +SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP; + +DROP TABLE t1; + +--echo # --echo End of 5.1 tests diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test index 741ea5533da..1204d04d9a0 100644 --- a/mysql-test/t/func_like.test +++ b/mysql-test/t/func_like.test @@ -112,5 +112,19 @@ select 'andre%' like 'andreÊ%' escape 'Ê'; # select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'; -# -# End of 4.1 tests + +--echo End of 4.1 tests + + +--echo # +--echo # Bug #54575: crash when joining tables with unique set column +--echo # +CREATE TABLE t1(a SET('a') NOT NULL, UNIQUE KEY(a)); +CREATE TABLE t2(b INT PRIMARY KEY); +INSERT INTO t1 VALUES (); +INSERT INTO t2 VALUES (1), (2), (3); +SELECT 1 FROM t2 JOIN t1 ON 1 LIKE a GROUP BY a; +DROP TABLE t1, t2; + + +--echo End of 5.1 tests diff --git a/mysql-test/t/implicit_commit-master.opt b/mysql-test/t/implicit_commit-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/implicit_commit-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 456cacf2fe1..b7bc662864e 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1416,6 +1416,15 @@ DROP USER nonpriv; DROP TABLE db1.t1; DROP DATABASE db1; +--echo +--echo Bug#54422 query with = 'variables' +--echo + +CREATE TABLE variables(f1 INT); +SELECT COLUMN_DEFAULT, TABLE_NAME +FROM INFORMATION_SCHEMA.COLUMNS +WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = 'variables'; +DROP TABLE variables; --echo End of 5.1 tests. diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/t/innodb_mysql-master.opt deleted file mode 100644 index 205c733455d..00000000000 --- a/mysql-test/t/innodb_mysql-master.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-lock-wait-timeout=2 diff --git a/mysql-test/t/innodb_mysql_lock2.test b/mysql-test/t/innodb_mysql_lock2.test index 5111d56225a..048d712183f 100644 --- a/mysql-test/t/innodb_mysql_lock2.test +++ b/mysql-test/t/innodb_mysql_lock2.test @@ -3,7 +3,12 @@ # This test requires statement/mixed mode binary logging. # Row-based mode puts weaker serializability requirements # so weaker locks are acquired for it. +# Also in ROW mode LOCK_S row locks won't be acquired for DML +# and test for bug#51263 won't trigger execution path on which +# this bug was encountered. --source include/have_binlog_format_mixed_or_statement.inc +# Original test case for bug#51263 needs partitioning. +--source include/have_partition.inc # Save the initial number of concurrent sessions. --source include/count_sessions.inc @@ -199,8 +204,7 @@ let $table= t1; --echo # 1.1 Simple SELECT statement. --echo # --echo # No locks are necessary as this statement won't be written ---echo # to the binary log and thanks to how MyISAM works SELECT ---echo # will see version of the table prior to concurrent insert. +--echo # to the binary log and InnoDB supports snapshots. let $statement= select * from t1; --source include/check_no_row_lock.inc @@ -654,7 +658,7 @@ let $statement= call p2(@a); --source include/check_no_row_lock.inc --echo # ---echo # 5.2 Function that modifes data and uses CALL, +--echo # 5.2 Function that modifies data and uses CALL, --echo # which reads a table through SELECT. --echo # --echo # Since a call to such function is written to the binary @@ -760,6 +764,104 @@ drop procedure p2; drop table t1, t2, t3, t4, t5; disconnect con1; + +--echo # +--echo # Test for bug#51263 "Deadlock between transactional SELECT +--echo # and ALTER TABLE ... REBUILD PARTITION". +--echo # +connect (con1,localhost,root,,test,,); +connection default; +--disable_warnings +drop table if exists t1, t2; +--enable_warnings +create table t1 (i int auto_increment not null primary key) engine=innodb; +create table t2 (i int) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5); + +begin; +--echo # Acquire SR metadata lock on t1 and LOCK_S row-locks on its rows. +insert into t2 select count(*) from t1; + +--echo # Switching to connection 'con1'. +connection con1; +--echo # Sending: +--send alter table t1 add column j int + +--echo # Switching to connection 'default'. +connection default; +--echo # Wait until ALTER is blocked because it tries to upgrade SNW +--echo # metadata lock to X lock. +--echo # It should not be blocked during copying data to new version of +--echo # table as it acquires LOCK_S locks on rows of old version, which +--echo # are compatible with locks acquired by connection 'con1'. +let $wait_condition= + select count(*) = 1 from information_schema.processlist where state = + "Waiting for table" and info = "alter table t1 add column j int"; +--source include/wait_condition.inc + +--echo # The below statement will deadlock because it will try to acquire +--echo # SW lock on t1, which will conflict with ALTER's SNW lock. And +--echo # ALTER will be waiting for this connection to release its SR lock. +--echo # This deadlock should be detected by an MDL subsystem and this +--echo # statement should be aborted with an appropriate error. +--error ER_LOCK_DEADLOCK +insert into t1 values (6); +--echo # Unblock ALTER TABLE. +commit; + +--echo # Switching to connection 'con1'. +connection con1; +--echo # Reaping ALTER TABLE. +--reap + +--echo # Switching to connection 'default'. +connection default; + +--echo # +--echo # Now test for scenario in which bug was reported originally. +--echo # +drop tables t1, t2; +create table t1 (i int auto_increment not null primary key) engine=innodb + partition by hash (i) partitions 4; +create table t2 (i int) engine=innodb; +insert into t1 values (1), (2), (3), (4), (5); + +begin; +--echo # Acquire SR metadata lock on t1. +select * from t1; + +--echo # Switching to connection 'con1'. +connection con1; +--echo # Sending: +--send alter table t1 rebuild partition p0 + +--echo # Switching to connection 'default'. +connection default; +--echo # Wait until ALTER is blocked because of active SR lock. +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = "alter table t1 rebuild partition p0"; +--source include/wait_condition.inc + +--echo # The below statement should succeed as transaction +--echo # has SR metadata lock on t1 and only going to read +--echo # rows from it. +insert into t2 select count(*) from t1; +--echo # Unblock ALTER TABLE. +commit; + +--echo # Switching to connection 'con1'. +connection con1; +--echo # Reaping ALTER TABLE. +--reap + +--echo # Switching to connection 'default'. +connection default; +disconnect con1; +--echo # Clean-up. +drop tables t1, t2; + + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/lock_sync-master.opt b/mysql-test/t/lock_sync-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/lock_sync-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/lock_sync.test b/mysql-test/t/lock_sync.test index 921ce991652..2f35da9d1ee 100644 --- a/mysql-test/t/lock_sync.test +++ b/mysql-test/t/lock_sync.test @@ -716,7 +716,7 @@ let $restore_table= ; --source include/check_concurrent_insert.inc --echo # ---echo # 5.2 Function that modifes data and uses CALL, +--echo # 5.2 Function that modifies data and uses CALL, --echo # which reads a table through SELECT. --echo # --echo # Since a call to such function is written to the binary diff --git a/mysql-test/t/mdl_sync-master.opt b/mysql-test/t/mdl_sync-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/mdl_sync-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/mdl_sync.test b/mysql-test/t/mdl_sync.test index 0b4b9af5bc6..19f9b396087 100644 --- a/mysql-test/t/mdl_sync.test +++ b/mysql-test/t/mdl_sync.test @@ -462,7 +462,11 @@ handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; -select count(*) from t1; +--echo # Disable result log to make test robust against +--echo # effects of concurrent insert. +--disable_result_log +select * from t1; +--enable_result_log insert into t1 values (1); --echo # Check that SNW lock is not compatible with SW lock. --echo # Again we use ALTER TABLE which fails after opening @@ -2407,6 +2411,7 @@ drop tables t1, t2; --disable_warnings drop tables if exists t0, t1, t2, t3, t4, t5; --enable_warnings +set debug_sync= 'RESET'; connect(deadlock_con1,localhost,root,,); connect(deadlock_con2,localhost,root,,); @@ -2696,6 +2701,136 @@ connection default; drop table t2; +--echo # +--echo # Test that in situation when MDL subsystem detects a deadlock +--echo # but it turns out that it can be resolved by backing-off locks +--echo # acquired by one of participating transactions (which is +--echo # possible when one of transactions consists only of currently +--echo # executed statement, e.g. in autocommit mode) no error is +--echo # reported. +--echo # +create table t1 (i int); +create table t2 (j int); +--echo # Ensure that the below SELECT stops once it has acquired metadata +--echo # lock on table 't2'. +set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; +--echo # Sending: +--send select * from t2, t1 + +--echo # +--echo # Switching to connection 'deadlock_con1'. +connection deadlock_con1; +--echo # Wait till SELECT acquires MDL on 't2' and starts waiting for signal. +set debug_sync= 'now WAIT_FOR locked'; +--echo # Sending: +--send lock tables t1 write, t2 write + +--echo # +--echo # Switching to connection 'deadlock_con2'. +connection deadlock_con2; +--echo # Wait until LOCK TABLES acquires SNRW lock on 't1' and is blocked +--echo # while trying to acquire SNRW lock on 't1'. +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = "lock tables t1 write, t2 write"; +--source include/wait_condition.inc +--echo # Resume SELECT execution, this should eventually unblock LOCK TABLES. +set debug_sync= 'now SIGNAL finish'; + +--echo # +--echo # Switching to connection 'deadlock_con1'. +connection deadlock_con1; +--echo # Reaping LOCK TABLES. +--reap +unlock tables; + +--echo # +--echo # Switching to connection 'default'. +connection default; +--echo # Reaping SELECT. It succeed and not report ER_LOCK_DEADLOCK error. +--reap + +drop tables t1, t2; + +--echo # +--echo # Test coverage for situation in which a race has happened +--echo # during deadlock detection process which led to unwarranted +--echo # ER_LOCK_DEADLOCK error. +--echo # +create table t1 (i int); + +--echo # Ensure that ALTER waits once it has acquired SNW lock. +set debug_sync='after_open_table_mdl_shared SIGNAL parked1 WAIT_FOR go1'; +--echo # Sending: +--send alter table t1 add column j int + +--echo # +--echo # Switching to connection 'deadlock_con1'. +connection deadlock_con1; +--echo # Wait till ALTER acquires SNW lock and stops. +set debug_sync='now WAIT_FOR parked1'; +--echo # Ensure that INSERT is paused once it detects that there is +--echo # a conflicting metadata lock so it has to wait, but before +--echo # deadlock detection is run. +set debug_sync='mdl_acquire_lock_wait SIGNAL parked2 WAIT_FOR go2'; +--echo # Sending: +--send insert into t1 values () + +--echo # +--echo # Switching to connection 'deadlock_con2'. +connection deadlock_con2; +--echo # Wait till INSERT is paused. +set debug_sync='now WAIT_FOR parked2'; +--echo # Resume ALTER execution. Eventually it will release its +--echo # metadata lock and INSERT's request for SW lock will be +--echo # satisified. +set debug_sync='now SIGNAL go1'; + +--echo # +--echo # Switching to connection 'default'. +connection default; +--echo # Reaping ALTER TABLE. +--reap +--echo # Add a new request for SNW lock to waiting graph. +--echo # Sending: +--send alter table t1 drop column j + +--echo # +--echo # Switching to connection 'deadlock_con2'. +connection deadlock_con2; +--echo # Wait until ALTER is blocked. +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = "alter table t1 drop column j"; +--source include/wait_condition.inc +--echo # Resume INSERT so it can start deadlock detection. +--echo # +--echo # At this point there is a discrepancy between the fact that INSERT's +--echo # SW lock is already satisfied, but INSERT's connection is still +--echo # marked as waiting for it. Looking for a loop in waiters graph +--echo # without additional checks has detected a deadlock (INSERT waits +--echo # for SW lock; which is not granted because of pending SNW lock from +--echo # ALTER; which waits for active SW lock from INSERT). Since requests +--echo # for SW and SNW locks have same weight ALTER was selected as a victim +--echo # and ended with ER_LOCK_DEADLOCK error. +set debug_sync='now SIGNAL go2'; + +--echo # +--echo # Switching to connection 'deadlock_con1'. +connection deadlock_con1; +--echo # Reaping INSERT. +--reap + +--echo # +--echo # Switching to connection 'default'. +connection default; +--echo # Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK. +--reap + +drop table t1; + +set debug_sync= 'RESET'; + disconnect deadlock_con1; disconnect deadlock_con2; disconnect deadlock_con3; @@ -3093,7 +3228,7 @@ set debug_sync='after_lock_tables_takes_lock SIGNAL alter_table_locked WAIT_FOR --echo # Switching to connection 'default'. connection default; set debug_sync='now WAIT_FOR alter_table_locked'; -set debug_sync='before_open_table_wait_refresh SIGNAL alter_go'; +set debug_sync='mdl_acquire_lock_wait SIGNAL alter_go'; --echo # The below statement should get ER_LOCK_DEADLOCK error --echo # (i.e. it should not allow ALTER to proceed, and then --echo # fail due to 't1' changing its name to 't2'). @@ -3469,6 +3604,86 @@ set debug_sync= 'RESET'; drop table t1; --echo # +--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE +--echo # +--echo # Ensure that a acquired lock is not given up due to a conflict. +--echo # + +connect (con1,localhost,root,,test,,); +connect (con2,localhost,root,,test,,); +connect (con3,localhost,root,,test,,); + +connection default; + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); + +--echo # Connection: con1 +connection con1; +SET debug_sync='lock_table_for_truncate SIGNAL parked_truncate WAIT_FOR go_truncate'; +send TRUNCATE TABLE t1; + +connection default; +--echo # Connection: default +SET debug_sync='now WAIT_FOR parked_truncate'; + +connection con2; +--echo # Connection: con2 +SET debug_sync='after_open_table_ignore_flush SIGNAL parked_show WAIT_FOR go_show'; +send SHOW FIELDS FROM t1; + +connection default; +--echo # Connection: default +SET debug_sync='now WAIT_FOR parked_show'; + +connection con3; +--echo # Connection: con3 +SET debug_sync='after_flush_unlock SIGNAL parked_flush WAIT_FOR go_flush'; +send FLUSH TABLES t1; + +connection default; +--echo # Connection: default +SET debug_sync='now WAIT_FOR parked_flush'; +SET debug_sync='now SIGNAL go_truncate'; + +connection con1; +--echo # Connection: con1 +--echo # Reaping... +reap; + +connection default; +--echo # Connection: default +SET debug_sync= 'now SIGNAL go_show'; + +connection con2; +--echo # Connection: con2 (SHOW FIELDS FROM t1) +--echo # Reaping... +reap; + +connection default; +--echo # Connection: default +SET debug_sync= 'now SIGNAL go_flush'; + +connection con3; +--echo # Connection: con3 (FLUSH TABLES t1) +--echo # Reaping... +reap; + +disconnect con1; +disconnect con2; +disconnect con3; + +connection default; +--echo # Connection: default +SET debug_sync= 'RESET'; +DROP TABLE t1; + + +--echo # --echo # Bug#52856 concurrent show columns or show full columns causes a crash!!! --echo # CREATE TABLE t1(a CHAR(255)); diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index a9d98da0403..29c0eae1df6 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -2187,5 +2187,20 @@ UNLOCK TABLES; DROP TABLE m1, t1; +--echo # +--echo # Test for bug #37371 "CREATE TABLE LIKE merge loses UNION parameter" +--echo # +--disable_warnings +drop tables if exists t1, m1, m2; +--enable_warnings +create table t1 (i int) engine=myisam; +create table m1 (i int) engine=mrg_myisam union=(t1) insert_method=first; +create table m2 like m1; +--echo # Table definitions should match +show create table m1; +show create table m2; +drop tables m1, m2, t1; + + --echo End of 6.0 tests diff --git a/mysql-test/t/mysql_delimiter_19799.sql b/mysql-test/t/mysql_delimiter_19799.sql index 2a3d4378492..2a3d4378492 100755..100644 --- a/mysql-test/t/mysql_delimiter_19799.sql +++ b/mysql-test/t/mysql_delimiter_19799.sql diff --git a/mysql-test/t/mysqldump-max-master.opt b/mysql-test/t/mysqldump-max-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/mysqldump-max-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index e6c9c8b423f..d477843b22b 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -732,3 +732,4 @@ DROP TABLE t1, t2, t3; --echo # --echo # End of 5.1 tests --echo # + diff --git a/mysql-test/t/parser_not_embedded.test b/mysql-test/t/parser_not_embedded.test index 8ebeb9a8301..22e9ae5a140 100644 --- a/mysql-test/t/parser_not_embedded.test +++ b/mysql-test/t/parser_not_embedded.test @@ -24,3 +24,78 @@ EOF --exec $MYSQL --comment --force --table test <$MYSQLTEST_VARDIR/tmp/bug39559.sql --remove_file $MYSQLTEST_VARDIR/tmp/bug39559.sql +--echo # Bug#46527 "COMMIT AND CHAIN RELEASE does not make sense" +--echo # +--error ER_PARSE_ERROR +COMMIT AND CHAIN RELEASE; + +COMMIT AND NO CHAIN RELEASE; +disconnect default; +connect(default, localhost, root,,); + +COMMIT RELEASE; +disconnect default; +connect(default, localhost, root,,); + +--error ER_PARSE_ERROR +COMMIT CHAIN RELEASE; + +--error ER_PARSE_ERROR +COMMIT NO CHAIN RELEASE; + +--error ER_PARSE_ERROR +COMMIT AND NO RELEASE; +--error ER_PARSE_ERROR +COMMIT AND RELEASE; + +COMMIT NO RELEASE; +--error ER_PARSE_ERROR +COMMIT CHAIN NO RELEASE; +--error ER_PARSE_ERROR +COMMIT NO CHAIN NO RELEASE; + +--error ER_PARSE_ERROR +COMMIT AND RELEASE CHAIN; + +COMMIT AND NO CHAIN NO RELEASE; + +--error ER_PARSE_ERROR +ROLLBACK AND CHAIN RELEASE; + +ROLLBACK AND NO CHAIN RELEASE; +disconnect default; +connect(default, localhost, root,,); + +ROLLBACK RELEASE; +disconnect default; +connect(default, localhost, root,,); + +--error ER_PARSE_ERROR +ROLLBACK CHAIN RELEASE; + +--error ER_PARSE_ERROR +ROLLBACK NO CHAIN RELEASE; +disconnect default; +connect(default, localhost, root,,); + +--error ER_PARSE_ERROR +ROLLBACK AND NO RELEASE; + +--error ER_PARSE_ERROR +ROLLBACK AND RELEASE; + +ROLLBACK NO RELEASE; + +--error ER_PARSE_ERROR +ROLLBACK CHAIN NO RELEASE; + +--error ER_PARSE_ERROR +ROLLBACK NO CHAIN NO RELEASE; +--error ER_PARSE_ERROR +ROLLBACK AND RELEASE CHAIN; + +ROLLBACK AND NO CHAIN NO RELEASE; + +--echo # +--echo # End of 5.5 tests +--echo # diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 6400017dfb7..ccca4df9882 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -1,3 +1,4 @@ +--source include/not_embedded.inc --source include/have_partition.inc --source include/have_innodb.inc diff --git a/mysql-test/t/partition_innodb_semi_consistent-master.opt b/mysql-test/t/partition_innodb_semi_consistent-master.opt index e76299453d3..9655b180fbd 100644 --- a/mysql-test/t/partition_innodb_semi_consistent-master.opt +++ b/mysql-test/t/partition_innodb_semi_consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--innodb_lock_wait_timeout=2 --default-storage-engine=MyISAM diff --git a/mysql-test/t/partition_innodb_semi_consistent.test b/mysql-test/t/partition_innodb_semi_consistent.test index 294521a45d5..7f6b3d48c63 100644 --- a/mysql-test/t/partition_innodb_semi_consistent.test +++ b/mysql-test/t/partition_innodb_semi_consistent.test @@ -31,6 +31,7 @@ set session transaction isolation level repeatable read; set autocommit=0; -- error ER_LOCK_WAIT_TIMEOUT update t1 set a=10 where a=5; +commit; connection a; #DELETE FROM t1 WHERE a=5; commit; @@ -101,6 +102,7 @@ connection con2; --error ER_LOCK_WAIT_TIMEOUT UPDATE t1 SET b = 21 WHERE a = 1; --disable_info +ROLLBACK; --echo # Switch to connection con1 connection con1; @@ -150,6 +152,7 @@ SELECT * FROM t1; connection con2; --reap SELECT * FROM t1; +COMMIT; --echo # Switch to connection con1 connection con1; diff --git a/mysql-test/t/ps_3innodb-master.opt b/mysql-test/t/ps_3innodb-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/ps_3innodb-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 5aa1a51a90f..bb90cbafd74 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -79,17 +79,15 @@ connection default; --echo End of 4.1 tests -# -# Bug#14959: ALTER TABLE isn't able to rename a view -# +--echo # +--echo # Bug#14959: "ALTER TABLE isn't able to rename a view" +--echo # Bug#53976: "ALTER TABLE RENAME is allowed on views +--echo # (not documented, broken)" +--echo # create table t1(f1 int); create view v1 as select * from t1; +--error ER_WRONG_OBJECT alter table v1 rename to v2; ---error ER_NO_SUCH_TABLE -alter table v1 rename to v2; -rename table v2 to v1; ---error ER_TABLE_EXISTS_ERROR -rename table v2 to v1; drop view v1; drop table t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 1e53461f665..463b3f39baa 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4117,4 +4117,15 @@ SELECT * FROM t1 WHERE 102 < c; DROP TABLE t1; +--echo # +--echo # Bug #54459: Assertion failed: param.sort_length, +--echo # file .\filesort.cc, line 149 (part II) +--echo # +CREATE TABLE t1(a ENUM('') NOT NULL); +INSERT INTO t1 VALUES (), (), (); +EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/mysql-test/t/sp_sync.test b/mysql-test/t/sp_sync.test index 391298b604a..431db463b67 100644 --- a/mysql-test/t/sp_sync.test +++ b/mysql-test/t/sp_sync.test @@ -108,38 +108,35 @@ disconnect con3; --echo # Bug #48246 assert in close_thread_table --echo # +CREATE TABLE t0 (b INTEGER); CREATE TABLE t1 (a INTEGER); CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1; -CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1; +CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1, t0; +INSERT INTO t0 VALUES(1); INSERT INTO t1 VALUES(1), (2); --echo # Connection 2 connect (con2, localhost, root); CALL p1(); ---echo # Connection default -connection default; -SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called'; ---echo # Sending: ---send CREATE TABLE t1 (a INTEGER) - ---echo # Connection 2 -connection con2; -SET DEBUG_SYNC= 'now WAIT_FOR locked'; -SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created'; ---echo # This call used to cause an assertion. MDL locking conflict will ---echo # cause back-off and retry. A variable indicating if a prelocking list ---echo # exists, used to be not reset properly causing an eventual assert. +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked_t1 WAIT_FOR go_for_t0'; +--echo # This call used to cause an assertion. MDL deadlock with upcoming +--echo # LOCK TABLES statement will cause back-off and retry. +--echo # A variable indicating if a prelocking list exists, used to be not +--echo # reset properly causing an eventual assert. --echo # Sending: --send CALL p1() --echo # Connection default connection default; ---echo # Reaping: CREATE TABLE t1 (a INTEGER) ---error ER_TABLE_EXISTS_ERROR ---reap -SET DEBUG_SYNC= 'now SIGNAL created'; +SET DEBUG_SYNC= 'now WAIT_FOR locked_t1'; +--echo # Issue LOCK TABLES statement which will enter in MDL deadlock +--echo # with CALL statement and as result will cause it to perform +--echo # back-off and retry. +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL go_for_t0'; +LOCK TABLES t0 WRITE, t1 WRITE; +UNLOCK TABLES; --echo # Connection 2 connection con2; @@ -151,7 +148,7 @@ connection default; disconnect con2; DROP PROCEDURE p1; DROP FUNCTION f1; -DROP TABLE t1; +DROP TABLES t0, t1; SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/t/strict-master.opt b/mysql-test/t/strict-master.opt new file mode 100644 index 00000000000..96f0ce3f36c --- /dev/null +++ b/mysql-test/t/strict-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 06aaf5dfb7f..2e442e7f897 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3921,3 +3921,28 @@ GROUP BY DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; + + +--echo # +--echo # Bug #52711: Segfault when doing EXPLAIN SELECT with +--echo # union...order by (select... where...) +--echo # + +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); + +--echo # Should not crash +--disable_result_log +EXPLAIN +SELECT * FROM t2 UNION SELECT * FROM t2 + ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); + +--echo # Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 + ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +DROP TABLE t1,t2; +--enable_result_log + +--echo End of 5.1 tests diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test index cdfa448f78a..c7a066cc203 100644 --- a/mysql-test/t/truncate.test +++ b/mysql-test/t/truncate.test @@ -102,7 +102,7 @@ SELECT * FROM v1; LOCK TABLE t1 WRITE; --error ER_TABLE_NOT_LOCKED SELECT * FROM v1; ---error ER_NO_SUCH_TABLE +--error ER_TABLE_NOT_LOCKED TRUNCATE v1; --error ER_TABLE_NOT_LOCKED SELECT * FROM v1; @@ -111,7 +111,7 @@ UNLOCK TABLES; LOCK TABLE t1 WRITE, t2 WRITE; --error ER_TABLE_NOT_LOCKED SELECT * FROM v1; ---error ER_NO_SUCH_TABLE +--error ER_TABLE_NOT_LOCKED TRUNCATE v1; --error ER_TABLE_NOT_LOCKED SELECT * FROM v1; @@ -119,14 +119,14 @@ UNLOCK TABLES; # LOCK TABLE v1 WRITE; SELECT * FROM v1; ---error ER_NO_SUCH_TABLE +--error ER_TABLE_NOT_LOCKED TRUNCATE v1; SELECT * FROM v1; UNLOCK TABLES; # LOCK TABLE t1 WRITE, t2 WRITE, v1 WRITE; SELECT * FROM v1; ---error ER_NO_SUCH_TABLE +--error ER_TABLE_NOT_LOCKED TRUNCATE v1; SELECT * FROM v1; UNLOCK TABLES; diff --git a/mysql-test/t/truncate_coverage.test b/mysql-test/t/truncate_coverage.test index b7c08b03c8b..c9c4bd90ca4 100644 --- a/mysql-test/t/truncate_coverage.test +++ b/mysql-test/t/truncate_coverage.test @@ -55,6 +55,12 @@ let $invisible_assignment_in_select = `SELECT @id := $ID`; KILL QUERY @id; --disconnect con2 --echo # +--echo # connection default +--connection default +--error ER_QUERY_INTERRUPTED +reap; +UNLOCK TABLES; +--echo # --echo # connection con1 --connection con1 --echo # Release shared metadata lock by closing HANDLER. @@ -63,9 +69,6 @@ HANDLER t1 CLOSE; --echo # --echo # connection default --connection default ---error ER_QUERY_INTERRUPTED -reap; -UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; ######## @@ -151,13 +154,20 @@ send TRUNCATE TABLE t1; SET DEBUG_SYNC='now WAIT_FOR waiting'; let $invisible_assignment_in_select = `SELECT @id := $ID`; KILL QUERY @id; -COMMIT; ---disconnect con1 --echo # --echo # connection default --connection default --error ER_QUERY_INTERRUPTED reap; +--echo # +--echo # connection con1 +--connection con1 +--echo # Release SW lock by committing transaction. +COMMIT; +--disconnect con1 +--echo # +--echo # connection default +--connection default UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4ef8b1898ae..c0564a82b23 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3902,6 +3902,7 @@ drop procedure p; --echo # CREATE TABLE t1 (a INT); CREATE VIEW v1 AS SELECT a FROM t1; +--error ER_WRONG_OBJECT ALTER TABLE v1; DROP VIEW v1; DROP TABLE t1; diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index b7d31948d23..b7d31948d23 100755..100644 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 4c93f5ffd57..0ea65ce8e4b 100755..100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -66,3 +66,7 @@ ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY} ${LIBNSL} ${LIBM} ${LIBRT}) DTRACE_INSTRUMENT(mysys) + +ADD_EXECUTABLE(thr_lock thr_lock.c) +TARGET_LINK_LIBRARIES(thr_lock mysys) +SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN") diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c index 07851ab6e92..9350babc176 100644 --- a/mysys/mf_loadpath.c +++ b/mysys/mf_loadpath.c @@ -42,7 +42,7 @@ char * my_load_path(char * to, const char *path, if (is_cur) is_cur=2; /* Remove current dir */ if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0))) - (void) strncat(buff, path+is_cur, FN_REFLEN); + (void) strncat(buff, path+is_cur, FN_REFLEN-1); else (void) strnmov(buff, path, FN_REFLEN); /* Return org file name */ } diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 4f7cd90e8aa..86fd61537e7 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -52,7 +52,7 @@ void pack_dirname(char * to, const char *from) buff_length= strlen(buff); d_length= (size_t) (start-to); if ((start == to || - (buff_length == d_length && !bcmp(buff,start,d_length))) && + (buff_length == d_length && !memcmp(buff,start,d_length))) && *start != FN_LIBCHAR && *start) { /* Put current dir before */ bchange((uchar*) to, d_length, (uchar*) buff, buff_length, strlen(to)+1); @@ -70,7 +70,7 @@ void pack_dirname(char * to, const char *from) } if (length > 1 && length < d_length) { /* test if /xx/yy -> ~/yy */ - if (bcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) + if (memcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) { to[0]=FN_HOMELIB; /* Filename begins with ~ */ (void) strmov_overlapp(to+1,to+length); @@ -80,7 +80,7 @@ void pack_dirname(char * to, const char *from) { /* Test if cwd is ~/... */ if (length > 1 && length < buff_length) { - if (bcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) + if (memcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) { buff[0]=FN_HOMELIB; (void) strmov_overlapp(buff+1,buff+length); @@ -166,7 +166,7 @@ size_t cleanup_dirname(register char *to, const char *from) *pos = FN_LIBCHAR; if (*pos == FN_LIBCHAR) { - if ((size_t) (pos-start) > length && bcmp(pos-length,parent,length) == 0) + if ((size_t) (pos-start) > length && memcmp(pos-length,parent,length) == 0) { /* If .../../; skip prev */ pos-=length; if (pos != start) @@ -197,7 +197,7 @@ size_t cleanup_dirname(register char *to, const char *from) end_parentdir=pos; while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */ pos--; - if (pos[1] == FN_HOMELIB || bcmp(pos,parent,length) == 0) + if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0) { /* Don't remove ~user/ */ pos=strmov(end_parentdir+1,parent); *pos=FN_LIBCHAR; @@ -206,7 +206,7 @@ size_t cleanup_dirname(register char *to, const char *from) } } else if ((size_t) (pos-start) == length-1 && - !bcmp(start,parent+1,length-1)) + !memcmp(start,parent+1,length-1)) start=pos; /* Starts with "../" */ else if (pos-start > 0 && pos[-1] == FN_LIBCHAR) { diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 91370bd3727..fc5d1dba217 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -508,10 +508,8 @@ uint bitmap_get_first_set(const MY_BITMAP *map) if (*byte_ptr & (1 << k)) return (i*32) + (j*8) + k; } - DBUG_ASSERT(0); } } - DBUG_ASSERT(0); } } return MY_BIT_NONE; @@ -534,7 +532,7 @@ uint bitmap_get_first(const MY_BITMAP *map) { byte_ptr= (uchar*)data_ptr; for (j=0; ; j++, byte_ptr++) - { + { if (*byte_ptr != 0xFF) { for (k=0; ; k++) @@ -542,10 +540,8 @@ uint bitmap_get_first(const MY_BITMAP *map) if (!(*byte_ptr & (1 << k))) return (i*32) + (j*8) + k; } - DBUG_ASSERT(0); } } - DBUG_ASSERT(0); } } return MY_BIT_NONE; diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index c6a7af58f57..bfbe205be39 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -47,7 +47,7 @@ my_bool my_gethwaddr(uchar *to) uchar *buf, *next, *end, *addr; struct if_msghdr *ifm; struct sockaddr_dl *sdl; - int i, res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; + int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) goto err; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 1e94dd2d761..30f4888cd98 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -28,7 +28,7 @@ typedef void (*init_func_p)(const struct my_option *option, void *variable, static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; -static int findopt(char *, uint, const struct my_option **, char **); +static int findopt(char *, uint, const struct my_option **, const char **); my_bool getopt_compare_strings(const char *, const char *, uint); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *, const struct my_option *, int *); @@ -113,8 +113,8 @@ int handle_options(int *argc, char ***argv, uint opt_found, argvpos= 0, length; my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose; - char **pos, **pos_end, *optend, *UNINIT_VAR(prev_found), - *opt_str, key_name[FN_REFLEN]; + char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN]; + const char *UNINIT_VAR(prev_found); const struct my_option *optp; void *value; int error, i; @@ -185,7 +185,6 @@ int handle_options(int *argc, char ***argv, Find first the right option. Return error in case of an ambiguous, or unknown option */ - LINT_INIT(prev_found); optp= longopts; if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) { @@ -696,10 +695,10 @@ ret: static int findopt(char *optpat, uint length, const struct my_option **opt_res, - char **ffname) + const char **ffname) { uint count; - struct my_option *opt= (struct my_option *) *opt_res; + const struct my_option *opt= *opt_res; for (count= 0; opt->name; opt++) { @@ -710,8 +709,9 @@ static int findopt(char *optpat, uint length, return 1; if (!count) { + /* We only need to know one prev */ count= 1; - *ffname= (char *) opt->name; /* We only need to know one prev */ + *ffname= opt->name; } else if (strcmp(*ffname, opt->name)) { diff --git a/mysys/my_handler.c b/mysys/my_handler.c index 3f8af553db6..48d100f2d3f 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -269,7 +269,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a+=a_length; b+=b_length; - break; } break; case HA_KEYTYPE_INT8: diff --git a/mysys/my_init.c b/mysys/my_init.c index f27f3f7b3e8..5bda2cb03ac 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -93,10 +93,6 @@ my_bool my_basic_init(void) my_umask_dir= (int) (atoi_octal(str) | 0700); #endif - /* $HOME is needed early to parse configuration files located in ~/ */ - if ((home_dir= getenv("HOME")) != 0) - home_dir= intern_filename(home_dir_buff, home_dir); - init_glob_errs(); instrumented_stdin.m_file= stdin; @@ -122,6 +118,10 @@ my_bool my_basic_init(void) return 1; #endif + /* $HOME is needed early to parse configuration files located in ~/ */ + if ((home_dir= getenv("HOME")) != 0) + home_dir= intern_filename(home_dir_buff, home_dir); + return 0; } diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 6d0f7e5dd53..8407657efb7 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -163,7 +163,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); } DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", - (long)sf_malloc_max_memory,lineno, filename)); + (long) sf_malloc_max_memory, lineno, filename)); DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_SET("-d,simulate_out_of_memory");); if (MyFlags & MY_FAE) diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 8ee89cfb55d..c6f9480b791 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -306,7 +306,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #if defined(MAIN) && !defined(__bsdi__) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ #endif return; @@ -325,7 +325,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #endif process_alarm_part2(sig); #ifndef USE_ALARM_THREAD -#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) +#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND) my_sigset(THR_SERVER_ALARM,process_alarm); #endif mysql_mutex_unlock(&LOCK_alarm); @@ -523,12 +523,12 @@ void thr_alarm_info(ALARM_INFO *info) */ -static sig_handler thread_alarm(int sig) +static sig_handler thread_alarm(int sig __attribute__((unused))) { #ifdef MAIN printf("thread_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,thread_alarm); /* int. thread system calls */ #endif } @@ -797,7 +797,7 @@ static sig_handler print_signal_warning(int sig) { printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); fflush(stdout); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif if (sig == SIGALRM) diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 43db0470735..9d10ba1fb01 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -29,7 +29,6 @@ TL_READ_WITH_SHARED_LOCKS TL_READ_HIGH_PRIORITY # High priority read TL_READ_NO_INSERT # Read without concurrent inserts TL_WRITE_ALLOW_WRITE # Write lock that allows other writers -TL_WRITE_ALLOW_READ # Write lock, but allow reading TL_WRITE_CONCURRENT_INSERT # Insert that can be mixed when selects TL_WRITE_DELAYED # Used by delayed insert @@ -41,7 +40,7 @@ TL_WRITE_ONLY # High priority write Locks are prioritized according to: -WRITE_ALLOW_WRITE, WRITE_ALLOW_READ, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, +WRITE_ALLOW_WRITE, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, WRITE_LOW_PRIORITY, READ, WRITE, READ_HIGH_PRIORITY and WRITE_ONLY Locks in the same privilege level are scheduled in first-in-first-out order. @@ -64,9 +63,8 @@ get_status: In MyISAM this stores the number of rows and size of the datafile for concurrent reads. -The lock algorithm allows one to have one TL_WRITE_ALLOW_READ, -TL_WRITE_CONCURRENT_INSERT or one TL_WRITE_DELAYED lock at the same time as -multiple read locks. +The lock algorithm allows one to have one TL_WRITE_CONCURRENT_INSERT or +one TL_WRITE_DELAYED lock at the same time as multiple read locks. */ @@ -124,8 +122,7 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, { THR_LOCK_DATA *data,**prev; uint count=0; - THR_LOCK_OWNER *first_owner; - LINT_INIT(first_owner); + THR_LOCK_OWNER *UNINIT_VAR(first_owner); prev= &list->data; if (list->data) @@ -238,7 +235,6 @@ static void check_locks(THR_LOCK *lock, const char *where, (((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT || lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) && !lock->read_no_write_count) || - lock->write_wait.data->type == TL_WRITE_ALLOW_READ || (lock->write_wait.data->type == TL_WRITE_DELAYED && !lock->read.data))) { @@ -543,14 +539,14 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, Request /------- H|++++ WRITE_ALLOW_WRITE - e|++++ WRITE_ALLOW_READ - l|+++- WRITE_CONCURRENT_INSERT - d|++++ WRITE_DELAYED - |||| + e|+++- WRITE_CONCURRENT_INSERT + l|++++ WRITE_DELAYED + d |||| |||\= READ_NO_INSERT ||\ = READ_HIGH_PRIORITY |\ = READ_WITH_SHARED_LOCKS \ = READ + + = Request can be satisified. - = Request cannot be satisified. @@ -620,14 +616,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end; } - /* - if there is a TL_WRITE_ALLOW_READ lock, we have to wait for a lock - (TL_WRITE_ALLOW_READ is used for ALTER TABLE in MySQL) - */ - if ((!lock->write.data || - lock->write.data->type != TL_WRITE_ALLOW_READ) && - !have_specific_lock(lock->write_wait.data,TL_WRITE_ALLOW_READ) && - (lock->write.data || lock->read.data)) + if (lock->write.data || lock->read.data) { /* Add delayed write lock to write_wait queue, and return at once */ (*lock->write_wait.last)=data; @@ -680,8 +669,6 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, it is OK to grant new lock without additional checks in such situation. **) The exceptions are situations when: - - old lock type is TL_WRITE_ALLOW_READ and new lock type is - TL_WRITE_ALLOW_WRITE - when old lock type is TL_WRITE_DELAYED But these should never happen within MySQL. Therefore it is OK to allow acquiring write lock on the table if @@ -695,9 +682,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, ((lock_type <= lock->write.data->type || (lock_type == TL_WRITE && lock->write.data->type == TL_WRITE_LOW_PRIORITY)) && - ! ((lock_type < TL_WRITE_ALLOW_READ && - lock->write.data->type == TL_WRITE_ALLOW_READ) || - lock->write.data->type == TL_WRITE_DELAYED))); + lock->write.data->type != TL_WRITE_DELAYED)); if ((lock_type == TL_WRITE_ALLOW_WRITE && ! lock->write_wait.data && @@ -1265,10 +1250,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) occurs also other waiters, both readers and writers can be allowed to start. The previous lock is often TL_WRITE_ONLY but can also be - TL_WRITE and TL_WRITE_ALLOW_READ. The normal downgrade variants are - TL_WRITE_ONLY => TL_WRITE_ALLOW_READ After a short exclusive lock - TL_WRITE_ALLOW_READ => TL_WRITE_ALLOW_WRITE After discovering that the - operation didn't need such a high lock. + TL_WRITE. The normal downgrade variants are: TL_WRITE_ONLY => TL_WRITE after a short exclusive lock while holding a write table lock TL_WRITE_ONLY => TL_WRITE_ALLOW_WRITE After a short exclusive lock after @@ -1289,11 +1271,6 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, #ifndef DBUG_OFF enum thr_lock_type old_lock_type= in_data->type; #endif -#ifdef TO_BE_REMOVED - THR_LOCK_DATA *data, *next; - bool start_writers= FALSE; - bool start_readers= FALSE; -#endif DBUG_ENTER("thr_downgrade_write_only_lock"); mysql_mutex_lock(&lock->mutex); @@ -1302,165 +1279,6 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, in_data->type= new_lock_type; check_locks(lock,"after downgrading lock",0); -#if TO_BE_REMOVED - switch (old_lock_type) - { - case TL_WRITE_ONLY: - case TL_WRITE: - case TL_WRITE_LOW_PRIORITY: - /* - Previous lock was exclusive we are now ready to start up most waiting - threads. - */ - switch (new_lock_type) - { - case TL_WRITE_ALLOW_READ: - /* Still cannot start WRITE operations. Can only start readers. */ - start_readers= TRUE; - break; - case TL_WRITE: - case TL_WRITE_LOW_PRIORITY: - /* - Still cannot start anything, but new requests are no longer - aborted. - */ - break; - case TL_WRITE_ALLOW_WRITE: - /* - We can start both writers and readers. - */ - start_writers= TRUE; - start_readers= TRUE; - break; - case TL_WRITE_CONCURRENT_INSERT: - case TL_WRITE_DELAYED: - /* - This routine is not designed for those. Lock will be downgraded - but no start of waiters will occur. This is not the optimal but - should be a correct behaviour. - */ - break; - default: - DBUG_ASSERT(0); - } - break; - case TL_WRITE_DELAYED: - case TL_WRITE_CONCURRENT_INSERT: - /* - This routine is not designed for those. Lock will be downgraded - but no start of waiters will occur. This is not the optimal but - should be a correct behaviour. - */ - break; - case TL_WRITE_ALLOW_READ: - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); - /* - Previously writers were not allowed to start, now it is ok to - start them again. Readers are already allowed so no reason to - handle them. - */ - start_writers= TRUE; - break; - default: - DBUG_ASSERT(0); - break; - } - if (start_writers) - { - /* - At this time the only active writer can be ourselves. Thus we need - not worry about that there are other concurrent write operations - active on the table. Thus we only need to worry about starting - waiting operations. - We also only come here with TL_WRITE_ALLOW_WRITE as the new - lock type, thus we can start other writers also of the same type. - If we find a lock at exclusive level >= TL_WRITE_LOW_PRIORITY we - don't start any more operations that would be mean those operations - will have to wait for things started afterwards. - */ - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); - for (data=lock->write_wait.data; data ; data= next) - { - /* - All WRITE requests compatible with new lock type are also - started - */ - next= data->next; - if (start_writers && data->type == new_lock_type) - { - mysql_cond_t *cond= data->cond; - /* - It is ok to start this waiter. - Move from being first in wait queue to be last in write queue. - */ - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->write_wait.last= data->prev; - data->prev= lock->write.last; - lock->write.last= &data->next; - data->next= 0; - check_locks(lock, "Started write lock after downgrade",0); - data->cond= 0; - mysql_cond_signal(cond); - } - else - { - /* - We found an incompatible lock, we won't start any more write - requests to avoid letting writers pass other writers in the - queue. - */ - start_writers= FALSE; - if (data->type >= TL_WRITE_LOW_PRIORITY) - { - /* - We have an exclusive writer in the queue so we won't start - readers either. - */ - start_readers= FALSE; - } - } - } - } - if (start_readers) - { - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE || - new_lock_type == TL_WRITE_ALLOW_READ); - /* - When we come here we know that the write locks are - TL_WRITE_ALLOW_WRITE or TL_WRITE_ALLOW_READ. This means that reads - are ok - */ - for (data=lock->read_wait.data; data ; data=next) - { - next= data->next; - /* - All reads are ok to start now except TL_READ_NO_INSERT when - write lock is TL_WRITE_ALLOW_READ. - */ - if (new_lock_type != TL_WRITE_ALLOW_READ || - data->type != TL_READ_NO_INSERT) - { - mysql_cond_t *cond= data->cond; - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->read_wait.last= data->prev; - data->prev= lock->read.last; - lock->read.last= &data->next; - data->next= 0; - - if (data->type == TL_READ_NO_INSERT) - lock->read_no_write_count++; - check_locks(lock, "Started read lock after downgrade",0); - data->cond= 0; - mysql_cond_signal(cond); - } - } - } - check_locks(lock,"after starting waiters after downgrading lock",0); -#endif mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -1646,15 +1464,14 @@ struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_REA struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}}; struct st_test test_10[] ={{4,TL_WRITE}}; struct st_test test_11[] = {{0,TL_WRITE_LOW_PRIORITY},{1,TL_WRITE_LOW_PRIORITY},{2,TL_WRITE_LOW_PRIORITY},{3,TL_WRITE_LOW_PRIORITY}}; /* Many writes */ -struct st_test test_12[] = {{0,TL_WRITE_ALLOW_READ},{1,TL_WRITE_ALLOW_READ},{2,TL_WRITE_ALLOW_READ},{3,TL_WRITE_ALLOW_READ}}; /* Many writes */ -struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; -struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; -struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; -struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; +struct st_test test_12[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; +struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; +struct st_test test_14[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; +struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6, test_7,test_8,test_9,test_10,test_11,test_12, - test_13,test_14,test_15,test_16}; + test_13,test_14,test_15}; int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), sizeof(test_1)/sizeof(struct st_test), sizeof(test_2)/sizeof(struct st_test), @@ -1670,8 +1487,7 @@ int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), sizeof(test_12)/sizeof(struct st_test), sizeof(test_13)/sizeof(struct st_test), sizeof(test_14)/sizeof(struct st_test), - sizeof(test_15)/sizeof(struct st_test), - sizeof(test_16)/sizeof(struct st_test) + sizeof(test_15)/sizeof(struct st_test) }; @@ -1681,6 +1497,7 @@ static uint thread_count; static ulong sum=0; #define MAX_LOCK_COUNT 8 +#define TEST_TIMEOUT 100000 /* The following functions is for WRITE_CONCURRENT_INSERT */ @@ -1727,7 +1544,7 @@ static void *test_thread(void *arg) multi_locks[i]= &data[i]; data[i].type= tests[param][i].lock_type; } - thr_multi_lock(multi_locks, lock_counts[param], &owner); + thr_multi_lock(multi_locks, lock_counts[param], &owner, TEST_TIMEOUT); mysql_mutex_lock(&LOCK_thread_count); { int tmp=rand() & 7; /* Do something from 0-2 sec */ diff --git a/packaging/WiX/AdminBackground.jpg b/packaging/WiX/AdminBackground.jpg Binary files differnew file mode 100644 index 00000000000..847dc6cdbed --- /dev/null +++ b/packaging/WiX/AdminBackground.jpg diff --git a/packaging/WiX/AdminHeader.jpg b/packaging/WiX/AdminHeader.jpg Binary files differnew file mode 100644 index 00000000000..6e2e33d404f --- /dev/null +++ b/packaging/WiX/AdminHeader.jpg diff --git a/packaging/WiX/CMakeLists.txt b/packaging/WiX/CMakeLists.txt new file mode 100644 index 00000000000..8a6a4ae4c41 --- /dev/null +++ b/packaging/WiX/CMakeLists.txt @@ -0,0 +1,112 @@ +# Copyright 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +IF(NOT WIN32) + RETURN() +ENDIF() + +FIND_PATH(WIX_DIR heat.exe + $ENV{WIX_DIR}/bin + $ENV{ProgramFiles}/wix/bin + "$ENV{ProgramFiles}/Windows Installer XML v3/bin" + "$ENV{ProgramFiles}/Windows Installer XML v3.5/bin" +) + +IF(NOT WIX_DIR) + IF(NOT _WIX_DIR_CHECKED) + SET(_WIX_DIR_CHECKED 1 CACHE INTERNAL "") + MESSAGE(STATUS "Cannot find wix 3, installer project will not be generated") + ENDIF() + RETURN() +ENDIF() + +ADD_SUBDIRECTORY(ca) + +# extra.wxs.in needs DATADIR_MYSQL_FILES and DATADIR_PERFORMANCE_SCHEMA_FILES, i.e +# Wix-compatible file lists for ${builddir}\sql\data\{mysql,performance_schema} + +FOREACH(dir mysql performance_schema) + FILE(GLOB files ${CMAKE_BINARY_DIR}/sql/data/${dir}/*) + SET(filelist) + FOREACH(f ${files}) + FILE(TO_NATIVE_PATH "${f}" file_native_path) + GET_FILENAME_COMPONENT(file_name "${f}" NAME) + SET(filelist +"${filelist} +<File Id='${file_name}' Source='${file_native_path}'/>") + ENDFOREACH() + STRING(TOUPPER ${dir} DIR_UPPER) + SET(DATADIR_${DIR_UPPER}_FILES "${filelist}") +ENDFOREACH() + + +FIND_PROGRAM(HEAT_EXECUTABLE heat ${WIX_DIR}) +FIND_PROGRAM(CANDLE_EXECUTABLE candle ${WIX_DIR}) +FIND_PROGRAM(LIGHT_EXECUTABLE light ${WIX_DIR}) + +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'") +ELSE() + SET(WixWin64) +ENDIF() +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/extra.wxs.in + ${CMAKE_CURRENT_BINARY_DIR}/extra.wxs) + +IF(CMAKE_GENERATOR MATCHES "Visual Studio") + SET(CONFIG_PARAM "-DCMAKE_INSTALL_CONFIG_NAME=${CMAKE_CFG_INTDIR}") +ENDIF() + +# WiX wants the license text as rtf; if there is no rtf license, +# we create a fake one from the plain text COPYING file. +IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.rtf") + MESSAGE("copying COPYING.rtf") + FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.rtf" CONTENTS) + FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf" "${CONTENTS}") +ELSE() + MESSAGE("creating COPYING.rtf") + FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/../../COPYING" CONTENTS) + STRING(REGEX REPLACE "\n" "\\\\par\n" CONTENTS "${CONTENTS}") + STRING(REGEX REPLACE "\t" "\\\\tab" CONTENTS "${CONTENTS}") + FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf" "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0\\fnil\\fcharset0 Courier New;}}\\viewkind4\\uc1\\pard\\lang1031\\f0\\fs15") + FILE(APPEND "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf" "${CONTENTS}") + FILE(APPEND "${CMAKE_CURRENT_BINARY_DIR}/COPYING.rtf" "\n}\n") +ENDIF() + +ADD_CUSTOM_TARGET( + MSI + COMMAND set VS_UNICODE_OUTPUT= + COMMAND ${CMAKE_COMMAND} + -DCPACK_WIX_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/CPackWixConfig.cmake + -DCPACK_WIX_INCLUDE=${CMAKE_CURRENT_BINARY_DIR}/extra.wxs + ${CONFIG_PARAM} + -P ${CMAKE_CURRENT_BINARY_DIR}/create_msi.cmake +) +ADD_DEPENDENCIES(MSI wixca) + +ADD_CUSTOM_TARGET( + MSI_ESSENTIALS + COMMAND set VS_UNICODE_OUTPUT= + COMMAND ${CMAKE_COMMAND} -DESSENTIALS=1 + -DCPACK_WIX_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/CPackWixConfig.cmake + -DCPACK_WIX_INCLUDE=${CMAKE_CURRENT_BINARY_DIR}/extra.wxs + ${CONFIG_PARAM} + -P ${CMAKE_CURRENT_BINARY_DIR}/create_msi.cmake +) +ADD_DEPENDENCIES(MSI wixca) + diff --git a/packaging/WiX/CPackWixConfig.cmake b/packaging/WiX/CPackWixConfig.cmake new file mode 100644 index 00000000000..9577574bbaf --- /dev/null +++ b/packaging/WiX/CPackWixConfig.cmake @@ -0,0 +1,95 @@ +
+IF(ESSENTIALS)
+ MESSAGE("Essentials!")
+ SET(CPACK_COMPONENTS_USED "Server;Client;DataFiles")
+ SET(CPACK_WIX_UI "WixUI_InstallDir")
+ MATH(EXPR bits ${CMAKE_SIZEOF_VOID_P}*8)
+ SET(CPACK_PACKAGE_FILE_NAME "mysql-essentials-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH}-win${bits}")
+ELSE()
+ SET(CPACK_COMPONENTS_USED
+ "Server;Client;DataFiles;Development;SharedLibraries;Embedded;Debuginfo;Documentation;IniFiles;Readme;Server_Scripts")
+ENDIF()
+
+
+# Some components like Embedded are optional
+# We will build MSI without embedded if it was not selected for build
+#(need to modify CPACK_COMPONENTS_ALL for that)
+SET(CPACK_ALL)
+FOREACH(comp1 ${CPACK_COMPONENTS_USED})
+ SET(found)
+ FOREACH(comp2 ${CPACK_COMPONENTS_ALL})
+ IF(comp1 STREQUAL comp2)
+ SET(found 1)
+ BREAK()
+ ENDIF()
+ ENDFOREACH()
+ IF(found)
+ SET(CPACK_ALL ${CPACK_ALL} ${comp1})
+ ENDIF()
+ENDFOREACH()
+SET(CPACK_COMPONENTS_ALL ${CPACK_ALL})
+
+# Always install (hidden), includes Readme files
+SET(CPACK_COMPONENT_GROUP_ALWAYSINSTALL_HIDDEN 1)
+SET(CPACK_COMPONENT_README_GROUP "AlwaysInstall")
+
+# Feature MySQL Server
+SET(CPACK_COMPONENT_GROUP_MYSQLSERVER_DISPLAY_NAME "MySQL Server")
+SET(CPACK_COMPONENT_GROUP_MYSQLSERVER_EXPANDED "1")
+SET(CPACK_COMPONENT_GROUP_MYSQLSERVER_DESCRIPTION "Install MySQL Server")
+ # Subfeature "Server" (hidden)
+ SET(CPACK_COMPONENT_SERVER_GROUP "MySQLServer")
+ SET(CPACK_COMPONENT_SERVER_HIDDEN 1)
+ # Subfeature "Client"
+ SET(CPACK_COMPONENT_CLIENT_GROUP "MySQLServer")
+ SET(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client Programs")
+ SET(CPACK_COMPONENT_CLIENT_DESCRIPTION
+ "Various helpful (commandline) tools including the mysql command line client" )
+
+ #Subfeature "Data Files"
+ SET(CPACK_COMPONENT_DATAFILES_GROUP "MySQLServer")
+ SET(CPACK_COMPONENT_DATAFILES_DISPLAY_NAME "Server data files")
+ SET(CPACK_COMPONENT_DATAFILES_DESCRIPTION "Server data files" )
+
+
+#Feature "Devel"
+SET(CPACK_COMPONENT_GROUP_DEVEL_DISPLAY_NAME "Development Components")
+SET(CPACK_COMPONENT_GROUP_DEVEL_DESCRIPTION "Installs C/C++ header files and libraries")
+ #Subfeature "Development"
+ SET(CPACK_COMPONENT_DEVELOPMENT_GROUP "Devel")
+ SET(CPACK_COMPONENT_DEVELOPMENT_HIDDEN 1)
+
+ #Subfeature "Shared libraries"
+ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "Devel")
+ SET(CPACK_COMPONENT_SHAREDLIBRARIES_DISPLAY_NAME "Client C API library (shared)")
+ SET(CPACK_COMPONENT_SHAREDLIBRARIES_DESCRIPTION "Installs shared client library")
+
+ #Subfeature "Embedded"
+ SET(CPACK_COMPONENT_EMBEDDED_GROUP "Devel")
+ SET(CPACK_COMPONENT_EMBEDDED_DISPLAY_NAME "Embedded server library")
+ SET(CPACK_COMPONENT_EMBEDDED_DESCRIPTION "Installs embedded server library")
+ SET(CPACK_COMPONENT_EMBEDDED_WIX_LEVEL 2)
+
+#Feature Debug Symbols
+SET(CPACK_COMPONENT_GROUP_DEBUGSYMBOLS_DISPLAY_NAME "Debug Symbols")
+SET(CPACK_COMPONENT_GROUP_DEBUGSYMBOLS_DESCRIPTION "Installs Debug Symbols")
+SET(CPACK_COMPONENT_GROUP_DEBUGSYMBOLS_WIX_LEVEL 2)
+ SET(CPACK_COMPONENT_DEBUGINFO_GROUP "DebugSymbols")
+ SET(CPACK_COMPONENT_DEBUGINFO_HIDDEN 1)
+
+#Feature Documentation
+SET(CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "Documentation")
+SET(CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION "Installs documentation")
+SET(CPACK_COMPONENT_DOCUMENTATION_WIX_LEVEL 2)
+
+#Feature tests
+SET(CPACK_COMPONENT_TEST_DISPLAY_NAME "Tests")
+SET(CPACK_COMPONENT_TEST_DESCRIPTION "Installs unittests (requires Perl to run)")
+SET(CPACK_COMPONENT_TEST_WIX_LEVEL 2)
+
+
+#Feature Misc (hidden, installs only if everything is installed)
+SET(CPACK_COMPONENT_GROUP_MISC_HIDDEN 1)
+SET(CPACK_COMPONENT_GROUP_MISC_WIX_LEVEL 100)
+ SET(CPACK_COMPONENT_INIFILES_GROUP "Misc")
+ SET(CPACK_COMPONENT_SERVER_SCRIPTS_GROUP "Misc")
diff --git a/packaging/WiX/MySQLServer.ico b/packaging/WiX/MySQLServer.ico Binary files differnew file mode 100644 index 00000000000..a471afcda95 --- /dev/null +++ b/packaging/WiX/MySQLServer.ico diff --git a/packaging/WiX/ca/CMakeLists.txt b/packaging/WiX/ca/CMakeLists.txt new file mode 100644 index 00000000000..c74b51284c7 --- /dev/null +++ b/packaging/WiX/ca/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/inc) +LINK_DIRECTORIES(${WIX_DIR}/../SDK/lib) + +SET(WIXCA_SOURCES CustomAction.cpp CustomAction.rc CustomAction.def) + +IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + LINK_LIBRARIES(wcautil_x64 dutil_x64 msi version) +ELSE() + LINK_LIBRARIES(wcautil dutil msi version) +ENDIF() + +ADD_LIBRARY(wixca SHARED ${WIXCA_SOURCES}) diff --git a/packaging/WiX/ca/CustomAction.cpp b/packaging/WiX/ca/CustomAction.cpp new file mode 100644 index 00000000000..806535bc79a --- /dev/null +++ b/packaging/WiX/ca/CustomAction.cpp @@ -0,0 +1,188 @@ +/* Copyright 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef UNICODE +#define UNICODE +#endif + +#include <windows.h> +#include <winreg.h> +#include <msi.h> +#include <msiquery.h> +#include <wcautil.h> +#include <string.h> +#include <strsafe.h> + +/* + * Search the registry for a service whose ImagePath starts + * with our install directory. Stop and remove it if requested. + */ +static TCHAR last_service_name[128]; +int remove_service(TCHAR *installdir, int check_only) { + HKEY hKey; + int done = 0; + + if(wcslen(installdir) < 3) { + WcaLog(LOGMSG_STANDARD, "INSTALLDIR is suspiciously short, better not do anything."); + return 0; + } + + if(check_only == 0) { + WcaLog(LOGMSG_STANDARD, "Determining number of matching services..."); + int servicecount = remove_service(installdir, 1); + if(servicecount <= 0) { + WcaLog(LOGMSG_STANDARD, "No services found, not removing anything."); + return 0; + } else if(servicecount == 1) { + TCHAR buf[256]; + swprintf_s(buf, sizeof(buf), TEXT("There is a service called '%ls' set up to run from this installation. Do you wish me to stop and remove that service?"), last_service_name); + int rc = MessageBox(NULL, buf, TEXT("Removing MySQL Server"), MB_ICONQUESTION|MB_YESNOCANCEL|MB_SYSTEMMODAL); + if(rc == IDCANCEL) return -1; + if(rc != IDYES) return 0; + } else if(servicecount > 0) { + TCHAR buf[256]; + swprintf_s(buf, sizeof(buf), TEXT("There appear to be %d services set up to run from this installation. Do you wish me to stop and remove those services?"), servicecount); + int rc = MessageBox(NULL, buf, TEXT("Removing MySQL Server"), MB_ICONQUESTION|MB_YESNOCANCEL|MB_SYSTEMMODAL); + if(rc == IDCANCEL) return -1; + if(rc != IDYES) return 0; + } + } + + if(check_only == -1) check_only = 0; + + WcaLog(LOGMSG_STANDARD, "Looking for service..."); + WcaLog(LOGMSG_STANDARD, "INSTALLDIR = %ls", installdir); + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\services"), 0, KEY_READ, &hKey)==ERROR_SUCCESS) { + DWORD index = 0; + TCHAR keyname[1024]; + DWORD keylen = sizeof(keyname); + FILETIME t; + /* Go through all services in the registry */ + while(RegEnumKeyExW(hKey, index, keyname, &keylen, NULL, NULL, NULL, &t) == ERROR_SUCCESS) { + HKEY hServiceKey = 0; + TCHAR path[1024]; + DWORD pathlen = sizeof(path)-1; + if (RegOpenKeyExW(hKey, keyname, NULL, KEY_READ, &hServiceKey) == ERROR_SUCCESS) { + /* Look at the ImagePath value of each service */ + if (RegQueryValueExW(hServiceKey, TEXT("ImagePath"), NULL, NULL, (LPBYTE)path, &pathlen) == ERROR_SUCCESS) { + path[pathlen] = 0; + TCHAR *p = path; + if(p[0] == '"') p += 1; + /* See if it is similar to our install directory */ + if(wcsncmp(p, installdir, wcslen(installdir)) == 0) { + WcaLog(LOGMSG_STANDARD, "Found service '%ls' with ImagePath '%ls'.", keyname, path); + swprintf_s(last_service_name, sizeof(last_service_name), TEXT("%ls"), keyname); + /* If we are supposed to stop and remove the service... */ + if(!check_only) { + WcaLog(LOGMSG_STANDARD, "Trying to stop the service."); + SC_HANDLE hSCM = NULL; + hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if(hSCM != NULL) { + SC_HANDLE hService = NULL; + hService = OpenService(hSCM, keyname, SERVICE_STOP|SERVICE_QUERY_STATUS|DELETE); + if(hService != NULL) { + WcaLog(LOGMSG_STANDARD, "Waiting for the service to stop..."); + SERVICE_STATUS status; + /* Attempt to stop the service */ + if(ControlService(hService, SERVICE_CONTROL_STOP, &status)) { + /* Now wait until it's stopped */ + while("it's one big, mean and cruel world out there") { + if(!QueryServiceStatus(hService, &status)) break; + if(status.dwCurrentState == SERVICE_STOPPED) break; + Sleep(1000); + } + WcaLog(LOGMSG_STANDARD, "Stopped the service."); + } + /* Mark the service for deletion */ + DeleteService(hService); + CloseServiceHandle(hService); + } + CloseServiceHandle(hSCM); + } + } + done++; + } + } + RegCloseKey(hServiceKey); + } + index++; + keylen = sizeof(keyname)-1; + } + RegCloseKey(hKey); + } else { + WcaLog(LOGMSG_STANDARD, "Can't seem to go through the list of installed services in the registry."); + } + return done; +} + +UINT wrap(MSIHANDLE hInstall, char *name, int check_only) { + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, name); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized."); + + TCHAR INSTALLDIR[1024]; + DWORD INSTALLDIR_size = sizeof(INSTALLDIR); + if(MsiGetPropertyW(hInstall, TEXT("CustomActionData"), INSTALLDIR, &INSTALLDIR_size) == ERROR_SUCCESS) { + int rc = remove_service(INSTALLDIR, check_only); + if(rc < 0) { + er = ERROR_CANCELLED; + } + } else { + er = ERROR_CANT_ACCESS_FILE; + } + +LExit: + return WcaFinalize(er); +} + +UINT __stdcall RemoveServiceNoninteractive(MSIHANDLE hInstall) +{ + return wrap(hInstall, "RemoveServiceNoninteractive", -1); +} + +UINT __stdcall RemoveService(MSIHANDLE hInstall) +{ + return wrap(hInstall, "RemoveService", 0); +} + +UINT __stdcall TestService(MSIHANDLE hInstall) +{ + return wrap(hInstall, "TestService", 1); +} + +/* DllMain - Initialize and cleanup WiX custom action utils */ +extern "C" BOOL WINAPI DllMain( + __in HINSTANCE hInst, + __in ULONG ulReason, + __in LPVOID + ) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + break; + } + + return TRUE; +} diff --git a/packaging/WiX/ca/CustomAction.def b/packaging/WiX/ca/CustomAction.def new file mode 100644 index 00000000000..5f5e6630013 --- /dev/null +++ b/packaging/WiX/ca/CustomAction.def @@ -0,0 +1,8 @@ +LIBRARY "wixca" +VERSION 1.0 + +EXPORTS + +RemoveService +RemoveServiceNoninteractive +TestService diff --git a/packaging/WiX/ca/CustomAction.rc b/packaging/WiX/ca/CustomAction.rc new file mode 100644 index 00000000000..3f37126ee77 --- /dev/null +++ b/packaging/WiX/ca/CustomAction.rc @@ -0,0 +1,18 @@ +#include "afxres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN +END + diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in new file mode 100644 index 00000000000..ff18009fd0c --- /dev/null +++ b/packaging/WiX/create_msi.cmake.in @@ -0,0 +1,311 @@ +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(MAJOR_VERSION "@MAJOR_VERSION@")
+SET(MINOR_VERSION "@MINOR_VERSION@")
+SET(PATCH "@PATCH@")
+SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@)
+SET(MANUFACTURER "@MANUFACTURER@")
+
+IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ SET(Win64 " Win64='yes'")
+ SET(Platform x64)
+ SET(PlatformProgramFilesFolder ProgramFiles64Folder)
+ELSE()
+ SET(Platform x86)
+ SET(PlatformProgramFilesFolder ProgramFilesFolder)
+ SET(Win64)
+ENDIF()
+
+SET(ENV{VS_UNICODE_OUTPUT})
+
+INCLUDE(${CMAKE_BINARY_DIR}/CPackConfig.cmake)
+
+IF(CPACK_WIX_CONFIG)
+ INCLUDE(${CPACK_WIX_CONFIG})
+ENDIF()
+
+IF(NOT CPACK_WIX_UI)
+ SET(CPACK_WIX_UI "WixUI_Mondo")
+ENDIF()
+
+SET(WIX_FEATURES)
+FOREACH(comp ${CPACK_COMPONENTS_ALL})
+ STRING(TOUPPER "${comp}" comp_upper)
+ IF(NOT CPACK_COMPONENT_${comp_upper}_GROUP)
+ SET(WIX_FEATURE_${comp_upper}_COMPONENTS "${comp}")
+ SET(CPACK_COMPONENT_${comp_upper}_HIDDEN 1)
+ SET(CPACK_COMPONENT_GROUP_${comp_upper}_DISPLAY_NAME ${CPACK_COMPONENT_${comp_upper}_DISPLAY_NAME})
+ SET(CPACK_COMPONENT_GROUP_${comp_upper}_DESCRIPTION ${CPACK_COMPONENT_${comp_upper}_DESCRIPTION})
+ SET(CPACK_COMPONENT_GROUP_${comp_upper}_WIX_LEVEL ${CPACK_COMPONENT_${comp_upper}_WIX_LEVEL})
+ SET(WIX_FEATURES ${WIX_FEATURES} WIX_FEATURE_${comp_upper})
+ ELSE()
+ SET(FEATURE_NAME WIX_FEATURE_${CPACK_COMPONENT_${comp_upper}_GROUP})
+ SET(WIX_FEATURES ${WIX_FEATURES} ${FEATURE_NAME})
+ LIST(APPEND ${FEATURE_NAME}_COMPONENTS ${comp})
+ ENDIF()
+ENDFOREACH()
+
+LIST(REMOVE_DUPLICATES WIX_FEATURES)
+
+SET(CPACK_WIX_FEATURES)
+
+FOREACH(f ${WIX_FEATURES})
+ STRING(TOUPPER "${f}" f_upper)
+ STRING(REPLACE "WIX_FEATURE_" "" f_upper ${f_upper})
+ IF (CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME)
+ SET(TITLE ${CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME})
+ ELSE()
+ SET(TITLE CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME)
+ ENDIF()
+
+ IF (CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION)
+ SET(DESCRIPTION ${CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION})
+ ELSE()
+ SET(DESCRIPTION CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION)
+ ENDIF()
+ IF(CPACK_COMPONENT_${f_upper}_WIX_LEVEL)
+ SET(Level ${CPACK_COMPONENT_${f_upper}_WIX_LEVEL})
+ ELSE()
+ SET(Level 1)
+ ENDIF()
+ IF(CPACK_COMPONENT_GROUP_${f_upper}_HIDDEN)
+ SET(DISPLAY "Display='hidden'")
+ SET(TITLE ${f_upper})
+ SET(DESCRIPTION ${f_upper})
+ ELSE()
+ SET(DISPLAY)
+ IF(CPACK_COMPONENT_GROUP_${f_upper}_EXPANDED)
+ SET(DISPLAY "Display='expand'")
+ ENDIF()
+ IF (CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME)
+ SET(TITLE ${CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME})
+ ELSE()
+ SET(TITLE CPACK_COMPONENT_GROUP_${f_upper}_DISPLAY_NAME)
+ ENDIF()
+ IF (CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION)
+ SET(DESCRIPTION ${CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION})
+ ELSE()
+ SET(DESCRIPTION CPACK_COMPONENT_GROUP_${f_upper}_DESCRIPTION)
+ ENDIF()
+ ENDIF()
+
+ SET(CPACK_WIX_FEATURES
+ "${CPACK_WIX_FEATURES}
+ <Feature Id='${f_upper}'
+ Title='${TITLE}'
+ Description='${DESCRIPTION}'
+ ConfigurableDirectory='INSTALLDIR'
+ Level='${Level}' ${DISPLAY} >"
+ )
+ FOREACH(c ${${f}_COMPONENTS})
+ STRING(TOUPPER "${c}" c_upper)
+ IF (CPACK_COMPONENT_${c_upper}_DISPLAY_NAME)
+ SET(TITLE ${CPACK_COMPONENT_${c_upper}_DISPLAY_NAME})
+ ELSE()
+ SET(TITLE CPACK_COMPONENT_${c_upper}_DISPLAY_NAME)
+ ENDIF()
+
+ IF (CPACK_COMPONENT_${c_upper}_DESCRIPTION)
+ SET(DESCRIPTION ${CPACK_COMPONENT_${c_upper}_DESCRIPTION})
+ ELSE()
+ SET(DESCRIPTION CPACK_COMPONENT_${c_upper}_DESCRIPTION)
+ ENDIF()
+ IF(CPACK_COMPONENT_${c_upper}_WIX_LEVEL)
+ SET(Level ${CPACK_COMPONENT_${c_upper}_WIX_LEVEL})
+ ELSE()
+ SET(Level 1)
+ ENDIF()
+ IF(CPACK_COMPONENT_${c_upper}_HIDDEN)
+ SET(CPACK_WIX_FEATURES
+ "${CPACK_WIX_FEATURES}
+ <ComponentGroupRef Id='componentgroup.${c}'/>")
+ ELSE()
+ SET(CPACK_WIX_FEATURES
+ "${CPACK_WIX_FEATURES}
+ <Feature Id='${c}'
+ Title='${TITLE}'
+ Description='${DESCRIPTION}'
+ ConfigurableDirectory='INSTALLDIR'
+ Level='${Level}'>
+ <ComponentGroupRef Id='componentgroup.${c}'/>
+ </Feature>")
+ ENDIF()
+
+ ENDFOREACH()
+ SET(CPACK_WIX_FEATURES
+ "${CPACK_WIX_FEATURES}
+ </Feature>
+ ")
+ENDFOREACH()
+
+
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mysql_server.wxs.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mysql_server.wxs)
+
+
+IF(CMAKE_INSTALL_CONFIG_NAME)
+ SET(CONFIG_PARAM "-DCMAKE_INSTALL_CONFIG_NAME=${CMAKE_INSTALL_CONFIG_NAME}")
+ENDIF()
+
+FOREACH(comp ${CPACK_COMPONENTS_ALL})
+ SET(ENV{DESTDIR} testinstall/${comp})
+ SET(DIRS ${DIRS} testinstall/${comp})
+ EXECUTE_PROCESS(
+ COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -DCMAKE_INSTALL_COMPONENT=${comp}
+ -DCMAKE_INSTALL_PREFIX= -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
+ OUTPUT_QUIET
+ )
+ENDFOREACH()
+
+MACRO(GENERATE_GUID VarName)
+ EXECUTE_PROCESS(COMMAND uuidgen -c
+ OUTPUT_VARIABLE ${VarName}
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ENDMACRO()
+
+SET(INC_VAR 0)
+MACRO(MAKE_WIX_IDENTIFIER str varname)
+ STRING(REPLACE "/" "." ${varname} "${str}")
+ STRING(REGEX REPLACE "[^a-zA-Z_0-9.]" "_" ${varname} "${${varname}}")
+ STRING(LENGTH "${${varname}}" len)
+ # Identifier should be smaller than 72 character
+ # We have to cut down the length to 70 chars, since we add 2 char prefix
+ # pretty often
+ IF(len GREATER 70)
+ STRING(SUBSTRING "${${varname}}" 0 67 shortstr)
+ MATH(EXPR INC_VAR ${INC_VAR}+1)
+ SET(${varname} "${shortstr}${INC_VAR}")
+ ENDIF()
+ENDMACRO()
+
+
+FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root)
+ FILE(GLOB all_files ${dir}/*)
+ IF(NOT all_files)
+ RETURN()
+ ENDIF()
+ FILE(RELATIVE_PATH dir_rel ${topdir} ${dir})
+ IF(dir_rel)
+ MAKE_DIRECTORY(${dir_root}/${dir_rel})
+ MAKE_WIX_IDENTIFIER("${dir_rel}" id)
+ SET(DirectoryRefId "D.${id}")
+ ELSE()
+ SET(DirectoryRefId "INSTALLDIR")
+ ENDIF()
+ FILE(APPEND ${file} "<DirectoryRef Id='${DirectoryRefId}'>\n")
+
+ SET(NONEXEFILES)
+ FOREACH(f ${all_files})
+ IF(NOT IS_DIRECTORY ${f})
+ FILE(RELATIVE_PATH rel ${topdir} ${f})
+ MAKE_WIX_IDENTIFIER("${rel}" id)
+ FILE(TO_NATIVE_PATH ${f} f_native)
+ GET_FILENAME_COMPONENT(f_ext "${f}" EXT)
+ # According to MSDN each DLL or EXE should be in the own component
+ IF(f_ext MATCHES ".exe" OR f_ext MATCHES ".dll")
+
+ FILE(APPEND ${file} " <Component Id='C.${id}' Guid='*' ${Win64}>\n")
+ FILE(APPEND ${file} " <File Id='F.${id}' KeyPath='yes' Source='${f_native}'/>\n")
+ FILE(APPEND ${file} " </Component>\n")
+ FILE(APPEND ${file_comp} " <ComponentRef Id='C.${id}'/>\n")
+ ELSE()
+ SET(NONEXEFILES "${NONEXEFILES}\n<File Id='F.${id}' Source='${f_native}'/>" )
+ ENDIF()
+ ENDIF()
+ ENDFOREACH()
+ FILE(APPEND ${file} "</DirectoryRef>\n")
+ IF(NONEXEFILES)
+ GENERATE_GUID(guid)
+ SET(ComponentId "C._files_${COMP_NAME}.${DirectoryRefId}")
+ FILE(APPEND ${file}
+ "<DirectoryRef Id='${DirectoryRefId}'>\n<Component Guid='${guid}' Id='${ComponentId}' ${Win64}>${NONEXEFILES}\n</Component></DirectoryRef>\n")
+ FILE(APPEND ${file_comp} " <ComponentRef Id='${ComponentId}'/>\n")
+ ENDIF()
+ FOREACH(f ${all_files})
+ IF(IS_DIRECTORY ${f})
+ TRAVERSE_FILES(${f} ${topdir} ${file} ${file_comp} ${dir_root})
+ ENDIF()
+ ENDFOREACH()
+ENDFUNCTION()
+
+FUNCTION(TRAVERSE_DIRECTORIES dir topdir file prefix)
+ FILE(RELATIVE_PATH rel ${topdir} ${dir})
+ IF(rel AND IS_DIRECTORY "${f}")
+ MAKE_WIX_IDENTIFIER("${rel}" id)
+ GET_FILENAME_COMPONENT(name ${dir} NAME)
+ FILE(APPEND ${file} "${prefix}<Directory Id='D.${id}' Name='${name}'>\n")
+ ENDIF()
+ FILE(GLOB all_files ${dir}/*)
+ FOREACH(f ${all_files})
+ IF(IS_DIRECTORY ${f})
+ TRAVERSE_DIRECTORIES(${f} ${topdir} ${file} "${prefix} ")
+ ENDIF()
+ ENDFOREACH()
+ IF(rel AND IS_DIRECTORY "${f}")
+ FILE(APPEND ${file} "${prefix}</Directory>\n")
+ ENDIF()
+ENDFUNCTION()
+
+SET(CPACK_WIX_COMPONENTS)
+SET(CPACK_WIX_COMPONENT_GROUPS)
+GET_FILENAME_COMPONENT(abs . ABSOLUTE)
+FOREACH(d ${DIRS})
+ GET_FILENAME_COMPONENT(d ${d} ABSOLUTE)
+ GET_FILENAME_COMPONENT(d_name ${d} NAME)
+ FILE(WRITE ${abs}/${d_name}_component_group.wxs "<ComponentGroup Id='componentgroup.${d_name}'>")
+ SET(COMP_NAME ${d_name})
+ TRAVERSE_FILES(${d} ${d} ${abs}/${d_name}.wxs ${abs}/${d_name}_component_group.wxs "${abs}/dirs")
+ FILE(APPEND ${abs}/${d_name}_component_group.wxs "</ComponentGroup>")
+ FILE(READ ${d_name}.wxs WIX_TMP)
+ SET(CPACK_WIX_COMPONENTS "${CPACK_WIX_COMPONENTS}\n${WIX_TMP}")
+ FILE(REMOVE ${d_name}.wxs)
+ FILE(READ ${d_name}_component_group.wxs WIX_TMP)
+
+ SET(CPACK_WIX_COMPONENT_GROUPS "${CPACK_WIX_COMPONENT_GROUPS}\n${WIX_TMP}")
+ FILE(REMOVE ${d_name}_component_group.wxs)
+ENDFOREACH()
+
+FILE(WRITE directories.wxs "<DirectoryRef Id='INSTALLDIR'>\n")
+TRAVERSE_DIRECTORIES(${abs}/dirs ${abs}/dirs directories.wxs "")
+FILE(APPEND directories.wxs "</DirectoryRef>\n")
+
+FILE(READ directories.wxs CPACK_WIX_DIRECTORIES)
+FILE(REMOVE directories.wxs)
+
+
+FOREACH(src ${CPACK_WIX_INCLUDE})
+SET(CPACK_WIX_INCLUDES
+"${CPACK_WIX_INCLUDES}
+ <?include ${src}?>"
+)
+ENDFOREACH()
+
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mysql_server.wxs.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mysql_server.wxs)
+
+SET(EXTRA_CANDLE_ARGS)
+IF("$ENV{EXTRA_CANDLE_ARGS}")
+ SET(EXTRA_CANDLE_ARGS "$ENV{EXTRA_CANDLE_ARGS}")
+ENDIF()
+
+SET(EXTRA_LIGHT_ARGS)
+IF("$ENV{EXTRA_LIGHT_ARGS}")
+ SET(EXTRA_LIGHT_ARGS "$ENV{EXTRA_LIGHT_ARGS}")
+ENDIF()
+
+FILE(REMOVE mysql_server.wixobj)
+EXECUTE_PROCESS(
+ COMMAND ${CANDLE_EXECUTABLE} -ext WixUtilExtension mysql_server.wxs ${EXTRA_CANDLE_ARGS}
+)
+EXECUTE_PROCESS(
+ COMMAND ${LIGHT_EXECUTABLE} -ext WixUIExtension -ext WixUtilExtension
+ mysql_server.wixobj -out ${CPACK_PACKAGE_FILE_NAME}.msi
+ ${EXTRA_LIGHT_ARGS}
+)
+
diff --git a/packaging/WiX/extra.wxs.in b/packaging/WiX/extra.wxs.in new file mode 100644 index 00000000000..b6c42136129 --- /dev/null +++ b/packaging/WiX/extra.wxs.in @@ -0,0 +1,60 @@ +<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"
+ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
+
+ <!-- Datafiles that installation will copy to CommonAppData (initial database)
+ They are declared Permanent and NeverOverwrite since it is user data -->
+ <DirectoryRef Id='TARGETDIR'>
+ <Directory Id="CommonAppDataFolder">
+ <Directory Id="datadir.mysql" Name="MySQL">
+ <Directory Id="datadir.mysql.mysqlserver"
+ Name="MySQL Server @MAJOR_VERSION@.@MINOR_VERSION@">
+ <Directory Id="DATADIR" Name=".">
+ <Component Id="component.datadir" Guid="d3491319-5dbc-4477-95f3-4f809ef1dd2d">
+ <CreateFolder>
+ <util:PermissionEx User="[LogonUser]" GenericAll="yes" />
+ </CreateFolder>
+ </Component>
+ <Directory Id="datadir.mysql.mysqlserver.data" Name="data">
+ <Directory Id="datadir.mysql.mysqlserver.data.mysql" Name="mysql">
+ <Component Id="component.datadir.mysql"
+ Guid="19ec0f1f-1a7f-424e-a788-b09346c0a709"
+ Permanent="yes" NeverOverwrite="yes">
+ <CreateFolder>
+ <util:PermissionEx User="[LogonUser]" GenericAll="yes" />
+ </CreateFolder>
+ @DATADIR_MYSQL_FILES@
+ </Component>
+ </Directory>
+ <Directory Id="datadir.mysql.mysqlserver.data.performance_schema"
+ Name="performance_schema">
+ <Component Id="component.datadir.performance_schema"
+ Guid="af2a6776-2655-431f-a748-9e9f4645acc3"
+ Permanent="yes" NeverOverwrite="yes">
+ <CreateFolder>
+ <util:PermissionEx User="[LogonUser]" GenericAll="yes" />
+ </CreateFolder>
+ @DATADIR_PERFORMANCE_SCHEMA_FILES@
+ </Component>
+ </Directory>
+ <Directory Id="datadir.mysql.mysqlserver.data.test" Name="test">
+ <Component Id="component.datadir.test" Guid="52fa9f0a-fcd1-420a-b2ac-95a8f70ad20a">
+ <CreateFolder/>
+ </Component>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+ </DirectoryRef>
+
+ <Feature Id="UserEditableDatafiles" Level='1' Display='hidden' ConfigurableDirectory="DATADIR">
+ <ComponentRef Id="component.datadir"/>
+ <ComponentRef Id="component.datadir.mysql"/>
+ <ComponentRef Id="component.datadir.performance_schema"/>
+ <ComponentRef Id="component.datadir.test"/>
+ </Feature>
+</Include>
+
+
+
diff --git a/packaging/WiX/mysql_server.wxs.in b/packaging/WiX/mysql_server.wxs.in new file mode 100644 index 00000000000..8b20644e58d --- /dev/null +++ b/packaging/WiX/mysql_server.wxs.in @@ -0,0 +1,114 @@ +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
+ <Product
+ Id="*"
+ UpgradeCode="49EB7A6A-1CEF-4A1E-9E89-B9A4993963E3"
+ Name="MySQL Server @MAJOR_VERSION@.@MINOR_VERSION@"
+ Version="@MAJOR_VERSION@.@MINOR_VERSION@.@PATCH@"
+ Language="1033"
+ Manufacturer="@MANUFACTURER@">
+
+ <Package Id='*'
+ Keywords='Installer'
+ Description="MySQL Database Server"
+ Manufacturer='@MANUFACTURER@'
+ InstallerVersion='200'
+ Languages='1033'
+ Compressed='yes'
+ SummaryCodepage='1252'
+ Platform='@Platform@'/>
+
+ <Media Id='1' Cabinet='product.cab' EmbedCab='yes' />
+
+ <!-- Upgrade -->
+ <Upgrade Id="49EB7A6A-1CEF-4A1E-9E89-B9A4993963E3">
+ <UpgradeVersion
+ Minimum="@MAJOR_VERSION@.@MINOR_VERSION@.0"
+ IncludeMinimum="yes"
+ Maximum="@MAJOR_VERSION@.@MINOR_VERSION@.@PATCH@"
+ Property="OLDERVERSIONBEINGUPGRADED" />
+ <UpgradeVersion
+ Minimum="@MAJOR_VERSION@.@MINOR_VERSION@.@PATCH@"
+ OnlyDetect="yes"
+ Property="NEWERVERSIONDETECTED" />
+ </Upgrade>
+ <Condition Message="A later version of [ProductName] is already installed. Setup will now exit.">
+ NOT NEWERVERSIONDETECTED OR Installed
+ </Condition>
+ <InstallExecuteSequence>
+ <RemoveExistingProducts After="InstallInitialize"/>
+ </InstallExecuteSequence>
+
+
+ <!-- UI -->
+ <Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"></Property>
+ <UIRef Id="@CPACK_WIX_UI@" />
+ <UIRef Id="WixUI_ErrorProgressText" />
+ <WixVariable
+ Id="WixUIBannerBmp"
+ Value="@CMAKE_CURRENT_SOURCE_DIR@/AdminHeader.jpg" />
+ <WixVariable
+ Id="WixUIDialogBmp"
+ Value="@CMAKE_CURRENT_SOURCE_DIR@/AdminBackground.jpg" />
+ <Icon
+ Id="icon.ico"
+ SourceFile="@CMAKE_CURRENT_SOURCE_DIR@/MySQLServer.ico"/>
+ <Property
+ Id="ARPPRODUCTICON"
+ Value="icon.ico" />
+
+ <!-- License -->
+ <WixVariable
+ Id="WixUILicenseRtf"
+ Value="@CMAKE_CURRENT_BINARY_DIR@/COPYING.rtf"/>
+
+ <!-- How to remove the service on uninstall -->
+ <Binary Id='wixca.dll' SourceFile='@CMAKE_CURRENT_BINARY_DIR@/ca/RelWithDebInfo/wixca.dll' />
+ <CustomAction Id="UnregisterProperty" Property="UnregisterService" Value="[INSTALLDIR]" Return="check" />
+ <CustomAction Id="UnregisterPropertySilent" Property="UnregisterServiceSilently" Value="[INSTALLDIR]" Return="check" />
+ <CustomAction Id="UnregisterService"
+ BinaryKey="wixca.dll"
+ DllEntry="RemoveService"
+ Execute="deferred"
+ Impersonate="no"
+ Return="check" />
+ <CustomAction Id="UnregisterServiceSilently"
+ BinaryKey="wixca.dll"
+ DllEntry="RemoveServiceNoninteractive"
+ Execute="deferred"
+ Impersonate="no"
+ Return="check" />
+ <InstallExecuteSequence>
+ <Custom Action="UnregisterProperty" After="InstallInitialize">Installed And Not UPGRADINGPRODUCTCODE</Custom>
+ <Custom Action="UnregisterPropertySilent" After="InstallInitialize">Installed And Not UPGRADINGPRODUCTCODE</Custom>
+ <Custom Action="UnregisterService" After="UnregisterProperty">Installed And Not UPGRADINGPRODUCTCODE And UILevel>2</Custom>
+ <Custom Action="UnregisterServiceSilently" After="UnregisterPropertySilent">Installed And Not UPGRADINGPRODUCTCODE And UILevel<=2</Custom>
+ </InstallExecuteSequence>
+
+ <!-- Installation root-->
+ <Directory Id='TARGETDIR' Name='SourceDir'>
+ <Directory Id='@PlatformProgramFilesFolder@'>
+ <Directory Id='directory.MySQL' Name='MySQL'>
+ <Directory Id='INSTALLDIR' Name='MySQL Server @MAJOR_VERSION@.@MINOR_VERSION@'>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <!-- CPACK_WIX_FEATURES -->
+ @CPACK_WIX_FEATURES@
+
+ <!-- CPACK_WIX_DIRECTORIES -->
+ @CPACK_WIX_DIRECTORIES@
+
+ <!--CPACK_WIX_COMPONENTS-->
+ @CPACK_WIX_COMPONENTS@
+
+ <!--CPACK_WIX_COMPONENTS_GROUPS -->
+ @CPACK_WIX_COMPONENT_GROUPS@
+
+ <!--CPACK_WIX_INCLUDES -->
+ @CPACK_WIX_INCLUDES@
+ </Product>
+
+</Wix>
\ No newline at end of file diff --git a/plugin/audit_null/CMakeLists.txt b/plugin/audit_null/CMakeLists.txt index 4e27ae7e0d9..4baa1da35fe 100644 --- a/plugin/audit_null/CMakeLists.txt +++ b/plugin/audit_null/CMakeLists.txt @@ -13,4 +13,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -MYSQL_ADD_PLUGIN(audit_null audit_null.c MODULE_ONLY) +MYSQL_ADD_PLUGIN(audit_null audit_null.c + MODULE_ONLY MODULE_OUTPUT_NAME "adt_null") diff --git a/plugin/daemon_example/CMakeLists.txt b/plugin/daemon_example/CMakeLists.txt index 1c21d57b326..de4310b0244 100644 --- a/plugin/daemon_example/CMakeLists.txt +++ b/plugin/daemon_example/CMakeLists.txt @@ -13,4 +13,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -MYSQL_ADD_PLUGIN(daemon_example daemon_example.cc MODULE_ONLY) +MYSQL_ADD_PLUGIN(daemon_example daemon_example.cc + MODULE_ONLY MODULE_OUTPUT_NAME "libdaemon_example") diff --git a/regex/CMakeLists.txt b/regex/CMakeLists.txt index 02132eefaad..02132eefaad 100755..100644 --- a/regex/CMakeLists.txt +++ b/regex/CMakeLists.txt diff --git a/regex/regcomp.c b/regex/regcomp.c index b203d4941e1..8280fbfd6c8 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -690,7 +690,6 @@ register cset *cs; case '-': SETERROR(REG_ERANGE); return; /* NOTE RETURN */ - break; default: c = '\0'; break; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index fc55a2923f2..84472c3a5c3 100755..100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -77,7 +77,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql ${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_data_timezone.sql ${FIX_PRIVILEGES_SQL} - DESTINATION ${INSTALL_MYSQLSHAREDIR} + DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server ) # TCMalloc hacks @@ -175,12 +175,10 @@ ELSE() SET(EXT ".pl") ENDIF() -INSTALL(FILES +INSTALL_SCRIPT( "${CMAKE_CURRENT_BINARY_DIR}/mysql_install_db${EXT}" DESTINATION ${DEST} - PERMISSIONS OWNER_READ OWNER_WRITE - OWNER_EXECUTE GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE + COMPONENT Server ) @@ -255,6 +253,7 @@ IF(MSVC) ENDIF() SET(NON_THREADED_LIBS ${CLIENT_LIBS}) +SET(mysql_config_COMPONENT COMPONENT Development) IF(WIN32) # On Windows, some .sh and some .pl.in files are configured @@ -268,31 +267,22 @@ IF(WIN32) mysqlhotcopy) FOREACH(file ${PLIN_FILES}) + IF(NOT ${file}_COMPONENT) + SET(${file}_COMPONENT Server_Scripts) + ENDIF() CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file}.pl.in ${CMAKE_CURRENT_BINARY_DIR}/${file}.pl ESCAPE_QUOTES @ONLY) - - INSTALL(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${file}.pl - DESTINATION scripts - PERMISSIONS OWNER_READ OWNER_WRITE - OWNER_EXECUTE GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE - ) + INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/${file}.pl COMPONENT ${${file}_COMPONENT}) ENDFOREACH() FOREACH(file ${SH_FILES}) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.pl ESCAPE_QUOTES @ONLY) - INSTALL(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${file}.pl - DESTINATION scripts - PERMISSIONS OWNER_READ OWNER_WRITE - OWNER_EXECUTE GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE - ) + INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/${file}.pl COMPONENT ${${file}_COMPONENT}) ENDFOREACH() ELSE() # On Unix, most of the files end up in the bin directory + SET(mysql_config_COMPONENT COMPONENT Development) SET(BIN_SCRIPTS msql2mysql mysql_config @@ -321,13 +311,14 @@ ELSE() MESSAGE(FATAL_ERROR "Can not find ${file}.sh or ${file} in " "${CMAKE_CURRENT_SOURCE_DIR}" ) ENDIF() - INSTALL(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${file} - DESTINATION ${INSTALL_BINDIR} - PERMISSIONS OWNER_READ OWNER_WRITE - OWNER_EXECUTE GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE - ) + IF(NOT ${file}_COMPONENT) + SET(${file}_COMPONENT Server) + ENDIF() + INSTALL_SCRIPT( + ${CMAKE_CURRENT_BINARY_DIR}/${file} + DESTINATION ${INSTALL_BINDIR} + COMPONENT ${${file}_COMPONENT} + ) ENDFOREACH() ENDIF() @@ -342,7 +333,8 @@ IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_FLAGS MATCHES "-static") ERROR_QUIET ) IF(${RESULT} EQUAL 0 AND EXISTS ${LIBGCC_LOCATION}) - INSTALL(FILES "${LIBGCC_LOCATION}" DESTINATION ${INSTALL_LIBDIR}) + INSTALL(FILES "${LIBGCC_LOCATION}" DESTINATION ${INSTALL_LIBDIR} + COMPONENT Development) ENDIF() ENDIF() diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 5d7f0760b82..562732e7387 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -704,7 +704,7 @@ fi cmd="`mysqld_ld_preload_text`$NOHUP_NICENESS" -plugin_dir="${PLUGIN_DIR:-$MY_BASEDIR_VERSION/lib/plugin}${PLUGIN_VARIANT}" +plugin_dir="${PLUGIN_DIR:-$MY_BASEDIR_VERSION/lib/mysql/plugin}${PLUGIN_VARIANT}" for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \ "--datadir=$DATADIR" "--plugin-dir=$plugin_dir" "$USER_OPTION" diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index a0e157b7806..ca5738f116e 100755..100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -75,7 +75,7 @@ SET (SQL_SOURCE sql_connect.cc scheduler.cc sql_profile.cc event_parse_data.cc sql_signal.cc rpl_handler.cc mdl.cc - transaction.cc sys_vars.cc + transaction.cc sys_vars.cc sql_truncate.cc datadict.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE}) @@ -97,7 +97,7 @@ ELSE() SET(MYSQLD_SOURCE main.cc ${DTRACE_PROBES_ALL}) ENDIF() -MYSQL_ADD_EXECUTABLE(mysqld ${MYSQLD_SOURCE} DESTINATION ${INSTALL_SBINDIR}) +MYSQL_ADD_EXECUTABLE(mysqld ${MYSQLD_SOURCE} DESTINATION ${INSTALL_SBINDIR} COMPONENT Server) IF(NOT WITHOUT_DYNAMIC_PLUGINS) SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE) @@ -252,7 +252,7 @@ IF(INSTALL_LAYOUT STREQUAL "STANDALONE") # Avoid completely empty directories and install dummy file instead. SET(DUMMY_FILE ${CMAKE_CURRENT_BINARY_DIR}/.empty ) FILE(WRITE ${DUMMY_FILE} "") -INSTALL(FILES ${DUMMY_FILE} DESTINATION data/test) +INSTALL(FILES ${DUMMY_FILE} DESTINATION data/test COMPONENT DataFiles) # Install initial database on windows IF(NOT CMAKE_CROSSCOMPILING) @@ -280,7 +280,7 @@ IF(WIN32 AND MYSQLD_EXECUTABLE) ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/data/mysql/user.frm ) - INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data DESTINATION . + INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data DESTINATION . COMPONENT DataFiles PATTERN "bootstrap.sql" EXCLUDE) ELSE() # Not windows or cross compiling, just install an empty directory diff --git a/sql/Makefile.am b/sql/Makefile.am index f57d1f3bc34..0616893a014 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -39,7 +39,9 @@ DTRACEFILES = filesort.o \ sql_connect.o \ sql_cursor.o \ sql_delete.o \ + sql_truncate.o \ sql_insert.o \ + datadict.o \ sql_parse.o \ sql_prepare.o \ sql_select.o \ @@ -56,7 +58,9 @@ DTRACEFILES_DEPEND = filesort.o \ sql_connect.o \ sql_cursor.o \ sql_delete.o \ + sql_truncate.o \ sql_insert.o \ + datadict.o \ sql_parse.o \ sql_prepare.o \ sql_select.o \ @@ -121,7 +125,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ sql_audit.h \ contributors.h sql_servers.h sql_signal.h records.h \ sql_prepare.h rpl_handler.h replication.h mdl.h \ - sql_plist.h transaction.h sys_vars.h + sql_plist.h transaction.h sys_vars.h sql_truncate.h \ + datadict.h mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ @@ -136,10 +141,10 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_connect.cc scheduler.cc sql_parse.cc \ keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \ sql_base.cc table.cc sql_select.cc sql_insert.cc \ - sql_profile.cc \ + datadict.cc sql_profile.cc \ sql_prepare.cc sql_error.cc sql_locale.cc \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \ - procedure.cc sql_test.cc \ + procedure.cc sql_test.cc sql_truncate.cc \ log.cc init.cc derror.cc sql_acl.cc \ unireg.cc des_key_file.cc \ log_event.cc rpl_record.cc \ diff --git a/sql/datadict.cc b/sql/datadict.cc new file mode 100644 index 00000000000..33c3b6bc700 --- /dev/null +++ b/sql/datadict.cc @@ -0,0 +1,161 @@ +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "datadict.h" +#include "sql_priv.h" +#include "sql_class.h" +#include "sql_table.h" + + +/** + Check type of .frm if we are not going to parse it. + + @param path path to FRM file + + @retval FRMTYPE_ERROR error + @retval FRMTYPE_TABLE table + @retval FRMTYPE_VIEW view +*/ + +frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) +{ + File file; + uchar header[10]; //"TYPE=VIEW\n" it is 10 characters + size_t error; + DBUG_ENTER("dd_frm_type"); + + *dbt= DB_TYPE_UNKNOWN; + + if ((file= mysql_file_open(key_file_frm, path, O_RDONLY | O_SHARE, MYF(0))) < 0) + DBUG_RETURN(FRMTYPE_ERROR); + error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)); + mysql_file_close(file, MYF(MY_WME)); + + if (error) + DBUG_RETURN(FRMTYPE_ERROR); + if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header))) + DBUG_RETURN(FRMTYPE_VIEW); + + /* + This is just a check for DB_TYPE. We'll return default unknown type + if the following test is true (arg #3). This should not have effect + on return value from this function (default FRMTYPE_TABLE) + */ + if (header[0] != (uchar) 254 || header[1] != 1 || + (header[2] != FRM_VER && header[2] != FRM_VER+1 && + (header[2] < FRM_VER+3 || header[2] > FRM_VER+4))) + DBUG_RETURN(FRMTYPE_TABLE); + + *dbt= (enum legacy_db_type) (uint) *(header + 3); + + /* Probably a table. */ + DBUG_RETURN(FRMTYPE_TABLE); +} + + +/** + Given a table name, check if the storage engine for the + table referred by this name supports an option 'flag'. + Return an error if the table does not exist or is not a + base table. + + @pre Any metadata lock on the table. + + @param[in] thd The current session. + @param[in] db Table schema. + @param[in] table_name Table database. + @param[in] flag The option to check. + @param[out] yes_no The result. Undefined if error. +*/ + +bool dd_check_storage_engine_flag(THD *thd, + const char *db, const char *table_name, + uint32 flag, bool *yes_no) +{ + char path[FN_REFLEN + 1]; + enum legacy_db_type db_type; + handlerton *table_type; + LEX_STRING db_name = {(char *) db, strlen(db)}; + + if (check_db_name(&db_name)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); + return TRUE; + } + + if (check_table_name(table_name, strlen(table_name), FALSE)) + { + my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name); + return TRUE; + } + + /* There should be at least some lock on the table. */ + DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, + table_name, MDL_SHARED)); + + (void) build_table_filename(path, sizeof(path) - 1, db, + table_name, reg_ext, 0); + + dd_frm_type(thd, path, &db_type); + + /* Type is unknown if the object is not found or is not a table. */ + if (db_type == DB_TYPE_UNKNOWN) + { + my_error(ER_NO_SUCH_TABLE, MYF(0), db, table_name); + return TRUE; + } + + table_type= ha_resolve_by_legacy_type(thd, db_type); + *yes_no= ha_check_storage_engine_flag(table_type, flag); + + return FALSE; +} + + +/* + Regenerate a metadata locked table. + + @param thd Thread context. + @param db Name of the database to which the table belongs to. + @param name Table name. + + @retval FALSE Success. + @retval TRUE Error. +*/ + +bool dd_recreate_table(THD *thd, const char *db, const char *table_name) +{ + bool error= TRUE; + HA_CREATE_INFO create_info; + char path[FN_REFLEN + 1]; + DBUG_ENTER("dd_recreate_table"); + + /* There should be a exclusive metadata lock on the table. */ + DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, + MDL_EXCLUSIVE)); + + memset(&create_info, 0, sizeof(create_info)); + + /* Create a path to the table, but without a extension. */ + build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0); + + /* Attempt to reconstruct the table. */ + mysql_mutex_lock(&LOCK_open); + error= ha_create_table(thd, path, db, table_name, &create_info, TRUE); + mysql_mutex_unlock(&LOCK_open); + + DBUG_RETURN(error); +} + diff --git a/sql/datadict.h b/sql/datadict.h new file mode 100644 index 00000000000..05b5a9bba4b --- /dev/null +++ b/sql/datadict.h @@ -0,0 +1,40 @@ +#ifndef DATADICT_INCLUDED +#define DATADICT_INCLUDED +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "handler.h" + +/* + Data dictionary API. +*/ + +enum frm_type_enum +{ + FRMTYPE_ERROR= 0, + FRMTYPE_TABLE, + FRMTYPE_VIEW +}; + + +frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt); + +bool dd_check_storage_engine_flag(THD *thd, + const char *db, const char *table_name, + uint32 flag, + bool *yes_no); +bool dd_recreate_table(THD *thd, const char *db, const char *table_name); + +#endif // DATADICT_INCLUDED diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 33b9a1cafda..c646642dbba 100755..100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -203,7 +203,6 @@ pre_init_event_thread(THD* thd) */ thd->proc_info= "Initialized"; - thd->version= refresh_version; thd->set_time(); /* Do not use user-supplied timeout value for system threads. */ diff --git a/sql/examples/CMakeLists.txt b/sql/examples/CMakeLists.txt index 1a22e9a3efd..1a22e9a3efd 100755..100644 --- a/sql/examples/CMakeLists.txt +++ b/sql/examples/CMakeLists.txt diff --git a/sql/field.cc b/sql/field.cc index bfaaf10b141..fa258ce9479 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8280,7 +8280,13 @@ int Field_set::store(longlong nr, bool unsigned_val) { ASSERT_COLUMN_MARKED_FOR_WRITE; int error= 0; - ulonglong max_nr= set_bits(ulonglong, typelib->count); + ulonglong max_nr; + + if (sizeof(ulonglong)*8 <= typelib->count) + max_nr= ULONGLONG_MAX; + else + max_nr= (ULL(1) << typelib->count) - 1; + if ((ulonglong) nr > max_nr) { nr&= max_nr; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 9f003174d2e..68b98c79a50 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -7408,9 +7408,10 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, DBUG_PRINT("info", ("Remove table %s/%s", db, file_name_str)); // Delete the table and all related files TABLE_LIST table_list; - bzero((char*) &table_list,sizeof(table_list)); - table_list.db= (char*) db; - table_list.alias= table_list.table_name= (char*)file_name_str; + table_list.init_one_table(db, strlen(db), file_name_str, + strlen(file_name_str), file_name_str, + TL_WRITE); + table_list.mdl_request.set_type(MDL_EXCLUSIVE); (void)mysql_rm_table_part2(thd, &table_list, FALSE, /* if_exists */ FALSE, /* drop_temporary */ @@ -9509,7 +9510,6 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) if (thd->store_globals()) goto ndb_util_thread_fail; thd->init_for_queries(); - thd->version=refresh_version; thd->main_security_ctx.host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index a61f5b4feea..ab046164485 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3679,7 +3679,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) thd->init_for_queries(); thd->command= COM_DAEMON; thd->system_thread= SYSTEM_THREAD_NDBCLUSTER_BINLOG; - thd->version= refresh_version; thd->main_security_ctx.host_or_ip= ""; thd->client_capabilities= 0; my_net_init(&thd->net, 0); @@ -3966,9 +3965,9 @@ restart: !ndb_binlog_running)) break; /* Shutting down server */ - if (ndb_binlog_index && ndb_binlog_index->s->version < refresh_version) + if (ndb_binlog_index && ndb_binlog_index->s->needs_reopen()) { - if (ndb_binlog_index->s->version < refresh_version) + if (ndb_binlog_index->s->needs_reopen()) { close_thread_tables(thd); ndb_binlog_index= 0; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a6f106be3be..3fb5a30b560 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1308,7 +1308,7 @@ int ha_partition::prepare_new_partition(TABLE *tbl, assumes that external_lock() is last call that may fail here. Otherwise see description for cleanup_new_partition(). */ - if ((error= file->ha_external_lock(ha_thd(), m_lock_type))) + if ((error= file->ha_external_lock(ha_thd(), F_WRLCK))) goto error_external_lock; DBUG_PRINT("info", ("partition %s external locked", part_name)); diff --git a/sql/handler.cc b/sql/handler.cc index 11f684a8010..587490dd708 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1302,7 +1302,6 @@ int ha_commit_one_phase(THD *thd, bool all) if (thd->transaction.changed_tables) query_cache.invalidate(thd->transaction.changed_tables); #endif - thd->variables.tx_isolation=thd->session_tx_isolation; } } /* Free resources and perform other cleanup even for 'empty' transactions. */ @@ -1379,8 +1378,6 @@ int ha_rollback_trans(THD *thd, bool all) if (is_real_trans && thd->transaction_rollback_request && thd->transaction.xid_state.xa_state != XA_NOTR) thd->transaction.xid_state.rm_error= thd->stmt_da->sql_errno(); - if (all) - thd->variables.tx_isolation=thd->session_tx_isolation; } /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) diff --git a/sql/item.cc b/sql/item.cc index 05363f41d07..13b4aa96c76 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4400,8 +4400,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) context->first_name_resolution_table, context->last_name_resolution_table, reference, REPORT_ALL_ERRORS, - !any_privileges && - TRUE, TRUE); + !any_privileges, TRUE); } return -1; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3c871bc0663..d31799d7e60 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2777,6 +2777,8 @@ Item *Item_func_case::find_item(String *str) /* Compare every WHEN argument with it and return the first match */ for (uint i=0 ; i < ncases ; i+=2) { + if (args[i]->real_item()->type() == NULL_ITEM) + continue; cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); DBUG_ASSERT(cmp_type != ROW_RESULT); DBUG_ASSERT(cmp_items[(uint)cmp_type]); @@ -4007,9 +4009,17 @@ longlong Item_func_in::val_int() return (longlong) (!null_value && tmp != negated); } + if ((null_value= args[0]->real_item()->type() == NULL_ITEM)) + return 0; + have_null= 0; for (uint i= 1 ; i < arg_count ; i++) { + if (args[i]->real_item()->type() == NULL_ITEM) + { + have_null= TRUE; + continue; + } Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); in_item= cmp_items[(uint)cmp_type]; DBUG_ASSERT(in_item); @@ -4571,13 +4581,14 @@ Item_func::optimize_type Item_func_like::select_optimize() const if (args[1]->const_item()) { String* res2= args[1]->val_str((String *)&cmp.value2); + const char *ptr2; - if (!res2) + if (!res2 || !(ptr2= res2->ptr())) return OPTIMIZE_NONE; - if (*res2->ptr() != wild_many) + if (*ptr2 != wild_many) { - if (args[0]->result_type() != STRING_RESULT || *res2->ptr() != wild_one) + if (args[0]->result_type() != STRING_RESULT || *ptr2 != wild_one) return OPTIMIZE_OP; } } diff --git a/sql/item_create.cc b/sql/item_create.cc index 5f30a10d1e0..672e59986d5 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5131,8 +5131,6 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, CHARSET_INFO *cs) { Item *UNINIT_VAR(res); - ulong len; - uint dec; switch (cast_type) { case ITEM_CAST_BINARY: @@ -5155,11 +5153,10 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, break; case ITEM_CAST_DECIMAL: { - if (c_len == NULL) - { - len= 0; - } - else + ulong len= 0; + uint dec= 0; + + if (c_len) { ulong decoded_size; errno= 0; @@ -5173,11 +5170,7 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, len= decoded_size; } - if (c_dec == NULL) - { - dec= 0; - } - else + if (c_dec) { ulong decoded_size; errno= 0; @@ -5213,12 +5206,9 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, } case ITEM_CAST_CHAR: { + int len= -1; CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection); - if (c_len == NULL) - { - len= LL(-1); - } - else + if (c_len) { ulong decoded_size; errno= 0; @@ -5228,7 +5218,7 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type, my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH); return NULL; } - len= decoded_size; + len= (int) decoded_size; } res= new (thd->mem_root) Item_char_typecast(a, len, real_cs); break; diff --git a/sql/lock.cc b/sql/lock.cc index 3f13f15454a..52d97a2422b 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -415,7 +415,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) THR_LOCK_DATA **lock=sql_lock->locks; for (i=found=0 ; i < sql_lock->lock_count ; i++) { - if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ) + if (sql_lock->locks[i]->type > TL_WRITE_ALLOW_WRITE) { swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]); lock++; @@ -435,7 +435,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) for (i=found=0 ; i < sql_lock->table_count ; i++) { DBUG_ASSERT(sql_lock->table[i]->lock_position == i); - if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ) + if ((uint) sql_lock->table[i]->reginfo.lock_type > TL_WRITE_ALLOW_WRITE) { swap_variables(TABLE *, *table, sql_lock->table[i]); table++; @@ -866,6 +866,8 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, before calling it. Also it cannot be called while holding LOCK_open mutex. Both these invariants are enforced by asserts in MDL_context::acquire_locks(). + @note Initialization of MDL_request members of TABLE_LIST elements + is a responsibility of the caller. @retval FALSE Success. @retval TRUE Failure (OOM or thread was killed). @@ -880,12 +882,7 @@ bool lock_table_names(THD *thd, TABLE_LIST *table_list) global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE); for (lock_table= table_list; lock_table; lock_table= lock_table->next_local) - { - lock_table->mdl_request.init(MDL_key::TABLE, - lock_table->db, lock_table->table_name, - MDL_EXCLUSIVE); mdl_requests.push_front(&lock_table->mdl_request); - } mdl_requests.push_front(&global_request); @@ -1301,7 +1298,8 @@ wait_if_global_read_lock(THD *thd, bool abort_on_refresh, old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock, "Waiting for release of readlock"); while (must_wait && ! thd->killed && - (!abort_on_refresh || thd->version == refresh_version)) + (!abort_on_refresh || !thd->open_tables || + thd->open_tables->s->version == refresh_version)) { DBUG_PRINT("signal", ("Waiting for COND_global_read_lock")); mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); diff --git a/sql/lock.h b/sql/lock.h index f7c19913675..84c7bce0679 100644 --- a/sql/lock.h +++ b/sql/lock.h @@ -15,33 +15,32 @@ typedef struct st_mysql_lock MYSQL_LOCK; #define MYSQL_OPEN_TEMPORARY_ONLY 0x0004 #define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008 #define MYSQL_LOCK_LOG_TABLE 0x0010 -#define MYSQL_OPEN_TAKE_UPGRADABLE_MDL 0x0020 /** Do not try to acquire a metadata lock on the table: we already have one. */ -#define MYSQL_OPEN_HAS_MDL_LOCK 0x0040 +#define MYSQL_OPEN_HAS_MDL_LOCK 0x0020 /** If in locked tables mode, ignore the locked tables and get a new instance of the table. */ -#define MYSQL_OPEN_GET_NEW_TABLE 0x0080 +#define MYSQL_OPEN_GET_NEW_TABLE 0x0040 /** Don't look up the table in the list of temporary tables. */ -#define MYSQL_OPEN_SKIP_TEMPORARY 0x0100 +#define MYSQL_OPEN_SKIP_TEMPORARY 0x0080 /** Fail instead of waiting when conficting metadata lock is discovered. */ -#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0200 +#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100 /** Open tables using MDL_SHARED lock instead of one specified in parser. */ -#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0400 +#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0200 /** Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified in parser. */ -#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0800 +#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0400 /** When opening or locking the table, use the maximum timeout (LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value. */ -#define MYSQL_LOCK_IGNORE_TIMEOUT 0x1000 +#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800 /** Please refer to the internals manual. */ #define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\ diff --git a/sql/log.cc b/sql/log.cc index fd17e04b212..cbf6d2589b0 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -370,8 +370,8 @@ bool LOGGER::is_log_table_enabled(uint log_table_type) /* Check if a given table is opened log table */ -int check_if_log_table(uint db_len, const char *db, uint table_name_len, - const char *table_name, uint check_if_opened) +int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, + const char *table_name, bool check_if_opened) { if (db_len == 5 && !(lower_case_table_names ? @@ -2044,7 +2044,7 @@ static int find_uniq_filename(char *name) file_info= dir_info->dir_entry; for (i= dir_info->number_off_files ; i-- ; file_info++) { - if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 && + if (memcmp(file_info->name, start, length) == 0 && test_if_number(file_info->name+length, &number,0)) { set_if_bigger(max_found,(ulong) number); diff --git a/sql/log.h b/sql/log.h index cd3faace598..d264f62fb64 100644 --- a/sql/log.h +++ b/sql/log.h @@ -490,8 +490,8 @@ public: }; -int check_if_log_table(uint db_len, const char *db, uint table_name_len, - const char *table_name, uint check_if_opened); +int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, + const char *table_name, bool check_if_opened); class Log_to_csv_event_handler: public Log_event_handler { diff --git a/sql/log_event.cc b/sql/log_event.cc index 7778ee18f5c..6a24760ef86 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2323,6 +2323,53 @@ bool Query_log_event::write(IO_CACHE* file) start+= 4; } + if (thd && thd->is_current_user_used()) + { + LEX_STRING user; + LEX_STRING host; + memset(&user, 0, sizeof(user)); + memset(&host, 0, sizeof(host)); + + if (thd->slave_thread && thd->has_invoker()) + { + /* user will be null, if master is older than this patch */ + user= thd->get_invoker_user(); + host= thd->get_invoker_host(); + } + else if (thd->security_ctx->priv_user) + { + Security_context *ctx= thd->security_ctx; + + user.length= strlen(ctx->priv_user); + user.str= ctx->priv_user; + if (ctx->priv_host[0] != '\0') + { + host.str= ctx->priv_host; + host.length= strlen(ctx->priv_host); + } + } + + if (user.length > 0) + { + *start++= Q_INVOKER; + + /* + Store user length and user. The max length of use is 16, so 1 byte is + enough to store the user's length. + */ + *start++= (uchar)user.length; + memcpy(start, user.str, user.length); + start+= user.length; + + /* + Store host length and host. The max length of host is 60, so 1 byte is + enough to store the host's length. + */ + *start++= (uchar)host.length; + memcpy(start, host.str, host.length); + start+= host.length; + } + } /* NOTE: When adding new status vars, please don't forget to update the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function @@ -2652,6 +2699,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, bool catalog_nz= 1; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); + memset(&user, 0, sizeof(user)); + memset(&host, 0, sizeof(host)); common_header_len= description_event->common_header_len; post_header_len= description_event->post_header_len[event_type-1]; DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d", @@ -2806,6 +2855,20 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, data_written= master_data_written= uint4korr(pos); pos+= 4; break; + case Q_INVOKER: + { + CHECK_SPACE(pos, end, 1); + user.length= *pos++; + CHECK_SPACE(pos, end, user.length); + user.str= my_strndup((const char *)pos, user.length, MYF(0)); + pos+= user.length; + + CHECK_SPACE(pos, end, 1); + host.length= *pos++; + CHECK_SPACE(pos, end, host.length); + host.str= my_strndup((const char *)pos, host.length, MYF(0)); + pos+= host.length; + } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -2982,7 +3045,7 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (likely(charset_inited) && (unlikely(!print_event_info->charset_inited || - bcmp((uchar*) print_event_info->charset, (uchar*) charset, 6)))) + memcmp(print_event_info->charset, charset, 6)))) { CHARSET_INFO *cs_info= get_charset(uint2korr(charset), MYF(MY_WME)); if (cs_info) @@ -3005,8 +3068,8 @@ void Query_log_event::print_query_header(IO_CACHE* file, } if (time_zone_len) { - if (bcmp((uchar*) print_event_info->time_zone_str, - (uchar*) time_zone_str, time_zone_len+1)) + if (memcmp(print_event_info->time_zone_str, + time_zone_str, time_zone_len+1)) { my_b_printf(file,"SET @@session.time_zone='%s'%s\n", time_zone_str, print_event_info->delimiter); @@ -3252,7 +3315,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, thd->variables.collation_database= thd->db_charset; thd->table_map_for_update= (table_map)table_map_for_update; - + thd->set_invoker(&user, &host); /* Execute the query (note that we bypass dispatch_command()) */ Parser_state parser_state; if (!parser_state.init(thd, thd->query(), thd->query_length())) @@ -8654,7 +8717,7 @@ Rows_log_event::write_row(const Relay_log_info *const rli, TABLE *table= m_table; // pointer to event's table int error; - int keynum; + int UNINIT_VAR(keynum); auto_afree_ptr<char> key(NULL); /* fill table->record[0] with default values */ @@ -8848,19 +8911,19 @@ Rows_log_event::write_row(const Relay_log_info *const rli, #endif -int +int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); - + if (error && !thd->is_error()) { DBUG_ASSERT(0); my_error(ER_UNKNOWN_ERROR, MYF(0)); } - - return error; + + return error; } #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ diff --git a/sql/log_event.h b/sql/log_event.h index bd95c74b6c5..688bc3a9aa6 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -270,7 +270,8 @@ struct sql_ex_info 1 + 2 /* type, lc_time_names_number */ + \ 1 + 2 /* type, charset_database_number */ + \ 1 + 8 /* type, table_map_for_update */ + \ - 1 + 4 /* type, master_data_written */) + 1 + 4 /* type, master_data_written */ + \ + 1 + 16 + 1 + 60/* type, user_len, user, host_len, host */) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ @@ -339,6 +340,8 @@ struct sql_ex_info #define Q_MASTER_DATA_WRITTEN_CODE 10 +#define Q_INVOKER 11 + /* Intvar event post-header */ /* Intvar event data */ @@ -1610,6 +1613,8 @@ protected: */ class Query_log_event: public Log_event { + LEX_STRING user; + LEX_STRING host; protected: Log_event::Byte* data_buf; public: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index d9b48cd134e..dd333b246e0 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -418,7 +418,7 @@ copy_extra_record_fields(TABLE *table, DBUG_ASSERT(master_reclength <= table->s->reclength); if (master_reclength < table->s->reclength) - bmove_align(table->record[0] + master_reclength, + memcpy(table->record[0] + master_reclength, table->record[1] + master_reclength, table->s->reclength - master_reclength); @@ -697,7 +697,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key) rnd_pos() returns the record in table->record[0], so we have to move it to table->record[1]. */ - bmove_align(table->record[1], table->record[0], table->s->reclength); + memcpy(table->record[1], table->record[0], table->s->reclength); DBUG_RETURN(error); } @@ -1190,7 +1190,7 @@ int Update_rows_log_event_old::do_exec_row(TABLE *table) overwriting the default values that where put there by the unpack_row() function. */ - bmove_align(table->record[0], m_after_image, table->s->reclength); + memcpy(table->record[0], m_after_image, table->s->reclength); copy_extra_record_fields(table, m_master_reclength, m_width); /* diff --git a/sql/mdl.cc b/sql/mdl.cc index ddf518fbb1c..184b3c6051d 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -21,28 +21,28 @@ #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; -static PSI_mutex_key key_MDL_context_signal_mutex; +static PSI_mutex_key key_MDL_wait_LOCK_wait_status; static PSI_mutex_info all_mdl_mutexes[]= { { &key_MDL_map_mutex, "MDL_map::mutex", PSI_FLAG_GLOBAL}, - { &key_MDL_context_signal_mutex, "MDL_context::signal", 0} + { &key_MDL_wait_LOCK_wait_status, "MDL_wait::LOCK_wait_status", 0} }; static PSI_rwlock_key key_MDL_lock_rwlock; -static PSI_rwlock_key key_MDL_context_waiting_for_rwlock; +static PSI_rwlock_key key_MDL_context_LOCK_waiting_for; static PSI_rwlock_info all_mdl_rwlocks[]= { { &key_MDL_lock_rwlock, "MDL_lock::rwlock", 0}, - { &key_MDL_context_waiting_for_rwlock, "MDL_context::waiting_for_lock", 0} + { &key_MDL_context_LOCK_waiting_for, "MDL_context::LOCK_waiting_for", 0} }; -static PSI_cond_key key_MDL_context_signal_cond; +static PSI_cond_key key_MDL_wait_COND_wait_status; static PSI_cond_info all_mdl_conds[]= { - { &key_MDL_context_signal_cond, "MDL_context::signal", 0} + { &key_MDL_wait_COND_wait_status, "MDL_context::COND_wait_status", 0} }; /** @@ -105,23 +105,46 @@ enum enum_deadlock_weight }; - /** A context of the recursive traversal through all contexts in all sessions in search for deadlock. */ -class Deadlock_detection_context +class Deadlock_detection_visitor { public: - Deadlock_detection_context(MDL_context *start_arg) - : start(start_arg), - victim(NULL), - current_search_depth(0) - { } - MDL_context *start; - MDL_context *victim; - uint current_search_depth; + Deadlock_detection_visitor(MDL_context *start_node_arg) + : m_start_node(start_node_arg), + m_victim(NULL), + m_current_search_depth(0) + {} + bool enter_node(MDL_context * /* unused */); + void leave_node(MDL_context * /* unused */); + + bool inspect_edge(MDL_context *dest); + + MDL_context *get_victim() const { return m_victim; } + + /** + Change the deadlock victim to a new one if it has lower deadlock + weight. + */ + MDL_context *opt_change_victim_to(MDL_context *new_victim); +private: + /** + The context which has initiated the search. There + can be multiple searches happening in parallel at the same time. + */ + MDL_context *m_start_node; + /** If a deadlock is found, the context that identifies the victim. */ + MDL_context *m_victim; + /** Set to the 0 at start. Increased whenever + we descend into another MDL context (aka traverse to the next + wait-for graph node). When MAX_SEARCH_DEPTH is reached, we + assume that a deadlock is found, even if we have not found a + loop. + */ + uint m_current_search_depth; /** Maximum depth for deadlock searches. After this depth is achieved we will unconditionally declare that there is a @@ -140,6 +163,74 @@ public: /** + Enter a node of a wait-for graph. After + a node is entered, inspect_edge() will be called + for all wait-for destinations of this node. Then + leave_node() will be called. + We call "enter_node()" for all nodes we inspect, + including the starting node. + + @retval TRUE Maximum search depth exceeded. + @retval FALSE OK. +*/ + +bool Deadlock_detection_visitor::enter_node(MDL_context * /* unused */) +{ + if (++m_current_search_depth >= MAX_SEARCH_DEPTH) + return TRUE; + return FALSE; +} + + +/** + Done inspecting this node. Decrease the search + depth. Clear the node for debug safety. +*/ + +void Deadlock_detection_visitor::leave_node(MDL_context * /* unused */) +{ + --m_current_search_depth; +} + + +/** + Inspect a wait-for graph edge from one MDL context to another. + + @retval TRUE A loop is found. + @retval FALSE No loop is found. +*/ + +bool Deadlock_detection_visitor::inspect_edge(MDL_context *node) +{ + return node == m_start_node; +} + + +/** + Change the deadlock victim to a new one if it has lower deadlock + weight. + + @retval new_victim Victim is not changed. + @retval !new_victim New victim became the current. +*/ + +MDL_context * +Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim) +{ + if (m_victim == NULL || + m_victim->get_deadlock_weight() >= new_victim->get_deadlock_weight()) + { + /* Swap victims, unlock the old one. */ + MDL_context *tmp= m_victim; + m_victim= new_victim; + return tmp; + } + /* No change, unlock the current context. */ + return new_victim; +} + + +/** Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps and compatibility matrices. */ @@ -168,7 +259,9 @@ public: typedef I_P_List<MDL_ticket, I_P_List_adapter<MDL_ticket, &MDL_ticket::next_in_lock, - &MDL_ticket::prev_in_lock> > + &MDL_ticket::prev_in_lock>, + I_P_List_null_counter, + I_P_List_fast_push_back<MDL_ticket> > List; operator const List &() const { return m_list; } Ticket_list() :m_bitmap(0) {} @@ -254,25 +347,12 @@ public: } } - /** - Wake up contexts which are waiting to acquire lock on the object and - which may succeed now, when we released some lock on it or removed - some pending request from its waiters list (the latter can happen, - for example, when context trying to acquire exclusive on the object - lock is killed). - */ - void wake_up_waiters() - { - MDL_lock::Ticket_iterator it(m_waiting); - MDL_ticket *awake_ticket; + void reschedule_waiters(); - while ((awake_ticket= it++)) - awake_ticket->get_ctx()->awake(MDL_context::NORMAL_WAKE_UP); - } void remove_ticket(Ticket_list MDL_lock::*queue, MDL_ticket *ticket); bool find_deadlock(MDL_ticket *waiting_ticket, - Deadlock_detection_context *deadlock_ctx); + Deadlock_detection_visitor *dvisitor); /** List of granted tickets for this lock. */ Ticket_list m_granted; @@ -408,7 +488,7 @@ mdl_locks_key(const uchar *record, size_t *length, statement, the design capitalizes on that to later save on look ups in the table definition cache. This leads to reduced contention overall and on LOCK_open in particular. - Please see the description of MDL_context::acquire_shared_lock() + Please see the description of MDL_context::acquire_lock() for details. */ @@ -635,13 +715,9 @@ MDL_context::MDL_context() :m_trans_sentinel(NULL), m_thd(NULL), m_needs_thr_lock_abort(FALSE), - m_waiting_for(NULL), - m_deadlock_weight(0), - m_signal(NO_WAKE_UP) + m_waiting_for(NULL) { - mysql_prlock_init(key_MDL_context_waiting_for_rwlock, &m_waiting_for_lock); - mysql_mutex_init(key_MDL_context_signal_mutex, &m_signal_lock, NULL); - mysql_cond_init(key_MDL_context_signal_mutex, &m_signal_cond, NULL); + mysql_prlock_init(key_MDL_context_LOCK_waiting_for, &m_LOCK_waiting_for); } @@ -661,9 +737,7 @@ void MDL_context::destroy() { DBUG_ASSERT(m_tickets.is_empty()); - mysql_prlock_destroy(&m_waiting_for_lock); - mysql_mutex_destroy(&m_signal_lock); - mysql_cond_destroy(&m_signal_cond); + mysql_prlock_destroy(&m_LOCK_waiting_for); } @@ -750,13 +824,6 @@ MDL_request::create(MDL_key::enum_mdl_namespace mdl_namespace, const char *db, } -uint MDL_request::get_deadlock_weight() const -{ - return key.mdl_namespace() == MDL_key::GLOBAL || - type > MDL_SHARED_NO_WRITE ? - MDL_DEADLOCK_WEIGHT_DDL : MDL_DEADLOCK_WEIGHT_DML; -} - /** Auxiliary functions needed for creation/destruction of MDL_lock objects. @@ -805,6 +872,21 @@ void MDL_ticket::destroy(MDL_ticket *ticket) /** + Return the 'weight' of this ticket for the + victim selection algorithm. Requests with + lower weight are preferred to requests + with higher weight when choosing a victim. +*/ + +uint MDL_ticket::get_deadlock_weight() const +{ + return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL || + m_type > MDL_SHARED_NO_WRITE ? + MDL_DEADLOCK_WEIGHT_DDL : MDL_DEADLOCK_WEIGHT_DML); +} + + +/** Helper functions and macros to be used for killable waiting in metadata locking subsystem. @@ -865,27 +947,120 @@ static inline void mdl_exit_cond(THD *thd, } -MDL_context::mdl_signal_type MDL_context::timed_wait(struct timespec - *abs_timeout) +/** Construct an empty wait slot. */ + +MDL_wait::MDL_wait() + :m_wait_status(EMPTY) +{ + mysql_mutex_init(key_MDL_wait_LOCK_wait_status, &m_LOCK_wait_status, NULL); + mysql_cond_init(key_MDL_wait_COND_wait_status, &m_COND_wait_status, NULL); +} + + +/** Destroy system resources. */ + +MDL_wait::~MDL_wait() +{ + mysql_mutex_destroy(&m_LOCK_wait_status); + mysql_cond_destroy(&m_COND_wait_status); +} + + +/** + Set the status unless it's already set. Return FALSE if set, + TRUE otherwise. +*/ + +bool MDL_wait::set_status(enum_wait_status status_arg) +{ + bool was_occupied= TRUE; + mysql_mutex_lock(&m_LOCK_wait_status); + if (m_wait_status == EMPTY) + { + was_occupied= FALSE; + m_wait_status= status_arg; + mysql_cond_signal(&m_COND_wait_status); + } + mysql_mutex_unlock(&m_LOCK_wait_status); + return was_occupied; +} + + +/** Query the current value of the wait slot. */ + +MDL_wait::enum_wait_status MDL_wait::get_status() +{ + enum_wait_status result; + mysql_mutex_lock(&m_LOCK_wait_status); + result= m_wait_status; + mysql_mutex_unlock(&m_LOCK_wait_status); + return result; +} + + +/** Clear the current value of the wait slot. */ + +void MDL_wait::reset_status() +{ + mysql_mutex_lock(&m_LOCK_wait_status); + m_wait_status= EMPTY; + mysql_mutex_unlock(&m_LOCK_wait_status); +} + + +/** + Wait for the status to be assigned to this wait slot. + + @param abs_timeout Absolute time after which waiting should stop. + @param set_status_on_tiemout TRUE - If in case of timeout waiting + context should close the wait slot by + sending TIMEOUT to itself. + FALSE - Otherwise. + + @returns Signal posted. +*/ + +MDL_wait::enum_wait_status +MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, + bool set_status_on_timeout) { const char *old_msg; - mdl_signal_type result; + enum_wait_status result; st_my_thread_var *mysys_var= my_thread_var; int wait_result= 0; - mysql_mutex_lock(&m_signal_lock); + mysql_mutex_lock(&m_LOCK_wait_status); - old_msg= MDL_ENTER_COND(m_thd, mysys_var, &m_signal_cond, &m_signal_lock); + old_msg= MDL_ENTER_COND(thd, mysys_var, &m_COND_wait_status, + &m_LOCK_wait_status); - while (!m_signal && !mysys_var->abort && + while (!m_wait_status && !mysys_var->abort && wait_result != ETIMEDOUT && wait_result != ETIME) - wait_result= mysql_cond_timedwait(&m_signal_cond, &m_signal_lock, + wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status, abs_timeout); - result= (m_signal != NO_WAKE_UP || mysys_var->abort) ? - m_signal : TIMEOUT_WAKE_UP; + if (m_wait_status == EMPTY) + { + /* + Wait has ended not due to a status being set from another + thread but due to this connection/statement being killed or a + time out. + To avoid races, which may occur if another thread sets + GRANTED status before the code which calls this method + processes the abort/timeout, we assign the status under + protection of the m_LOCK_wait_status, within the critical + section. An exception is when set_status_on_timeout is + false, which means that the caller intends to restart the + wait. + */ + if (mysys_var->abort) + m_wait_status= KILLED; + else if (set_status_on_timeout) + m_wait_status= TIMEOUT; + } + result= m_wait_status; - MDL_EXIT_COND(m_thd, mysys_var, &m_signal_lock, old_msg); + MDL_EXIT_COND(thd, mysys_var, &m_LOCK_wait_status, old_msg); return result; } @@ -925,7 +1100,11 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) called by other threads. */ DBUG_ASSERT(ticket->get_lock()); - m_list.push_front(ticket); + /* + Add ticket to the *back* of the queue to ensure fairness + among requests with the same priority. + */ + m_list.push_back(ticket); m_bitmap|= MDL_BIT(ticket->get_type()); } @@ -953,6 +1132,75 @@ void MDL_lock::Ticket_list::remove_ticket(MDL_ticket *ticket) /** + Determine waiting contexts which requests for the lock can be + satisfied, grant lock to them and wake them up. + + @note Together with MDL_lock::add_ticket() this method implements + fair scheduling among requests with the same priority. + It tries to grant lock from the head of waiters list, while + add_ticket() adds new requests to the back of this list. + +*/ + +void MDL_lock::reschedule_waiters() +{ + MDL_lock::Ticket_iterator it(m_waiting); + MDL_ticket *ticket; + + /* + Find the first (and hence the oldest) waiting request which + can be satisfied (taking into account priority). Grant lock to it. + Repeat the process for the remainder of waiters. + Note we don't need to re-start iteration from the head of the + list after satisfying the first suitable request as in our case + all compatible types of requests have the same priority. + + TODO/FIXME: We should: + - Either switch to scheduling without priorities + which will allow to stop iteration through the + list of waiters once we found the first ticket + which can't be satisfied + - Or implement some check using bitmaps which will + allow to stop iteration in cases when, e.g., we + grant SNRW lock and there are no pending S or + SH locks. + */ + while ((ticket= it++)) + { + if (can_grant_lock(ticket->get_type(), ticket->get_ctx())) + { + if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED)) + { + /* + Satisfy the found request by updating lock structures. + It is OK to do so even after waking up the waiter since any + session which tries to get any information about the state of + this lock has to acquire MDL_lock::m_rwlock first and thus, + when manages to do so, already sees an updated state of the + MDL_lock object. + */ + m_waiting.remove_ticket(ticket); + m_granted.add_ticket(ticket); + + /* If we are granting an X lock, release the cached object. */ + if (ticket->get_type() == MDL_EXCLUSIVE && cached_object) + (*cached_object_release_hook)(cached_object); + cached_object= NULL; + } + /* + If we could not update the wait slot of the waiter, + it can be due to fact that its connection/statement was + killed or it has timed out (i.e. the slot is not empty). + Since in all such cases the waiter assumes that the lock was + not been granted, we should keep the request in the waiting + queue and look for another request to reschedule. + */ + } + } +} + + +/** Compatibility (or rather "incompatibility") matrices for global metadata lock. Arrays of bitmaps which elements specify which granted/waiting locks are incompatible with type of lock being requested. @@ -1159,9 +1407,19 @@ void MDL_lock::remove_ticket(Ticket_list MDL_lock::*list, MDL_ticket *ticket) { /* There can be some contexts waiting to acquire a lock - which now might be able to do it. Wake them up! + which now might be able to do it. Grant the lock to + them and wake them up! + + We always try to reschedule locks, since there is no easy way + (i.e. by looking at the bitmaps) to find out whether it is + required or not. + In a general case, even when the queue's bitmap is not changed + after removal of the ticket, there is a chance that some request + can be satisfied (due to the fact that a granted request + reflected in the bitmap might belong to the same context as a + pending request). */ - wake_up_waiters(); + reschedule_waiters(); mysql_prlock_unlock(&m_rwlock); } } @@ -1262,29 +1520,6 @@ MDL_context::find_ticket(MDL_request *mdl_request, /** - Acquire one lock with waiting for conflicting locks to go away if needed. - - @note This is an internal method which should not be used outside of MDL - subsystem as in most cases simply waiting for conflicting locks to - go away will lead to deadlock. - - @param mdl_request [in/out] Lock request object for lock to be acquired - - @param lock_wait_timeout [in] Seconds to wait before timeout. - - @retval FALSE Success. MDL_request::ticket points to the ticket - for the lock. - @retval TRUE Failure (Out of resources or waiting is aborted), -*/ - -bool -MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout) -{ - return acquire_lock_impl(mdl_request, lock_wait_timeout); -} - - -/** Try to acquire one lock. Unlike exclusive locks, shared locks are acquired one by @@ -1306,15 +1541,55 @@ MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout) @retval FALSE Success. The lock may have not been acquired. Check the ticket, if it's NULL, a conflicting lock - exists and another attempt should be made after releasing - all current locks and waiting for conflicting lock go - away (using MDL_context::wait_for_lock()). + exists. @retval TRUE Out of resources, an error has been reported. */ bool MDL_context::try_acquire_lock(MDL_request *mdl_request) { + MDL_ticket *ticket; + + if (try_acquire_lock_impl(mdl_request, &ticket)) + return TRUE; + + if (! mdl_request->ticket) + { + /* + Our attempt to acquire lock without waiting has failed. + Let us release resources which were acquired in the process. + We can't get here if we allocated a new lock object so there + is no need to release it. + */ + DBUG_ASSERT(! ticket->m_lock->is_empty()); + mysql_prlock_unlock(&ticket->m_lock->m_rwlock); + MDL_ticket::destroy(ticket); + } + + return FALSE; +} + + +/** + Auxiliary method for acquiring lock without waiting. + + @param mdl_request [in/out] Lock request object for lock to be acquired + @param out_ticket [out] Ticket for the request in case when lock + has not been acquired. + + @retval FALSE Success. The lock may have not been acquired. + Check MDL_request::ticket, if it's NULL, a conflicting + lock exists. In this case "out_ticket" out parameter + points to ticket which was constructed for the request. + MDL_ticket::m_lock points to the corresponding MDL_lock + object and MDL_lock::m_rwlock write-locked. + @retval TRUE Out of resources, an error has been reported. +*/ + +bool +MDL_context::try_acquire_lock_impl(MDL_request *mdl_request, + MDL_ticket **out_ticket) +{ MDL_lock *lock; MDL_key *key= &mdl_request->key; MDL_ticket *ticket; @@ -1374,10 +1649,16 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request) return TRUE; } + ticket->m_lock= lock; + if (lock->can_grant_lock(mdl_request->type, this)) { - ticket->m_lock= lock; lock->m_granted.add_ticket(ticket); + + if (mdl_request->type == MDL_EXCLUSIVE && lock->cached_object) + (*lock->cached_object_release_hook)(lock->cached_object); + lock->cached_object= NULL; + mysql_prlock_unlock(&lock->m_rwlock); m_tickets.push_front(ticket); @@ -1385,12 +1666,7 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request) mdl_request->ticket= ticket; } else - { - /* We can't get here if we allocated a new lock. */ - DBUG_ASSERT(! lock->is_empty()); - mysql_prlock_unlock(&lock->m_rwlock); - MDL_ticket::destroy(ticket); - } + *out_ticket= ticket; return FALSE; } @@ -1468,121 +1744,125 @@ void notify_shared_lock(THD *thd, MDL_ticket *conflicting_ticket) /** - Auxiliary method for acquiring an exclusive lock. - - @param mdl_request Request for the lock to be acqured. + Acquire one lock with waiting for conflicting locks to go away if needed. - @param lock_wait_timeout Seconds to wait before timeout. + @param mdl_request [in/out] Lock request object for lock to be acquired - @note Should not be used outside of MDL subsystem. Instead one - should call acquire_lock() or acquire_locks() - methods which ensure that conditions for deadlock-free - lock acquisition are fulfilled. + @param lock_wait_timeout [in] Seconds to wait before timeout. - @retval FALSE Success - @retval TRUE Failure + @retval FALSE Success. MDL_request::ticket points to the ticket + for the lock. + @retval TRUE Failure (Out of resources or waiting is aborted), */ -bool MDL_context::acquire_lock_impl(MDL_request *mdl_request, - ulong lock_wait_timeout) +bool +MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout) { MDL_lock *lock; MDL_ticket *ticket; - bool not_used; - st_my_thread_var *mysys_var= my_thread_var; - MDL_key *key= &mdl_request->key; struct timespec abs_timeout; - struct timespec abs_shortwait; + MDL_wait::enum_wait_status wait_status; + /* Do some work outside the critical section. */ set_timespec(abs_timeout, lock_wait_timeout); - mysql_mutex_assert_not_owner(&LOCK_open); - - DBUG_ASSERT(mdl_request->ticket == NULL); - /* Don't take chances in production. */ - mdl_request->ticket= NULL; + if (try_acquire_lock_impl(mdl_request, &ticket)) + return TRUE; - /* - Check whether the context already holds an exclusive lock on the object, - and if so, grant the request. - */ - if ((ticket= find_ticket(mdl_request, ¬_used))) + if (mdl_request->ticket) { - DBUG_ASSERT(ticket->m_lock); - mdl_request->ticket= ticket; + /* + We have managed to acquire lock without waiting. + MDL_lock, MDL_context and MDL_request were updated + accordingly, so we can simply return success. + */ return FALSE; } - DBUG_ASSERT(mdl_request->type < MDL_SHARED_NO_WRITE || - is_lock_owner(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE)); - - /* Early allocation: ticket will be needed in any case. */ - if (!(ticket= MDL_ticket::create(this, mdl_request->type))) - return TRUE; + /* + Our attempt to acquire lock without waiting has failed. + As a result of this attempt we got MDL_ticket with m_lock + member pointing to the corresponding MDL_lock object which + has MDL_lock::m_rwlock write-locked. + */ + lock= ticket->m_lock; - /* The below call implicitly locks MDL_lock::m_rwlock on success. */ - if (!(lock= mdl_locks.find_or_insert(key))) - { - MDL_ticket::destroy(ticket); - return TRUE; - } + lock->m_waiting.add_ticket(ticket); - ticket->m_lock= lock; + /* + Once we added a pending ticket to the waiting queue, + we must ensure that our wait slot is empty, so + that our lock request can be scheduled. Do that in the + critical section formed by the acquired write lock on MDL_lock. + */ + m_wait.reset_status(); - lock->m_waiting.add_ticket(ticket); + if (ticket->is_upgradable_or_exclusive()) + lock->notify_shared_locks(this); - while (!lock->can_grant_lock(mdl_request->type, this)) - { - wait_reset(); + mysql_prlock_unlock(&lock->m_rwlock); - if (ticket->is_upgradable_or_exclusive()) - lock->notify_shared_locks(this); + will_wait_for(ticket); - mysql_prlock_unlock(&lock->m_rwlock); + /* There is a shared or exclusive lock on the object. */ + DEBUG_SYNC(m_thd, "mdl_acquire_lock_wait"); - set_deadlock_weight(mdl_request->get_deadlock_weight()); - will_wait_for(ticket); + find_deadlock(); - /* There is a shared or exclusive lock on the object. */ - DEBUG_SYNC(m_thd, "mdl_acquire_lock_wait"); + if (ticket->is_upgradable_or_exclusive()) + { + struct timespec abs_shortwait; + set_timespec(abs_shortwait, 1); + wait_status= MDL_wait::EMPTY; - bool is_deadlock= find_deadlock(); - bool is_timeout= FALSE; - if (!is_deadlock) + while (cmp_timespec(abs_shortwait, abs_timeout) <= 0) { + /* abs_timeout is far away. Wait a short while and notify locks. */ + wait_status= m_wait.timed_wait(m_thd, &abs_shortwait, FALSE); + + if (wait_status != MDL_wait::EMPTY) + break; + + mysql_prlock_wrlock(&lock->m_rwlock); + lock->notify_shared_locks(this); + mysql_prlock_unlock(&lock->m_rwlock); set_timespec(abs_shortwait, 1); - bool timeout_is_near= cmp_timespec(abs_shortwait, abs_timeout) > 0; - mdl_signal_type wait_result= - timed_wait(timeout_is_near ? &abs_timeout : &abs_shortwait); - - if (timeout_is_near && wait_result == TIMEOUT_WAKE_UP) - is_timeout= TRUE; - else if (wait_result == VICTIM_WAKE_UP) - is_deadlock= TRUE; } + if (wait_status == MDL_wait::EMPTY) + wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE); + } + else + wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE); - stop_waiting(); + done_waiting_for(); - if (mysys_var->abort || is_deadlock || is_timeout) + if (wait_status != MDL_wait::GRANTED) + { + lock->remove_ticket(&MDL_lock::m_waiting, ticket); + MDL_ticket::destroy(ticket); + switch (wait_status) { - lock->remove_ticket(&MDL_lock::m_waiting, ticket); - MDL_ticket::destroy(ticket); - if (is_deadlock) - my_error(ER_LOCK_DEADLOCK, MYF(0)); - else if (is_timeout) - my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); - return TRUE; + case MDL_wait::VICTIM: + my_error(ER_LOCK_DEADLOCK, MYF(0)); + break; + case MDL_wait::TIMEOUT: + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); + break; + case MDL_wait::KILLED: + break; + default: + DBUG_ASSERT(0); + break; } - mysql_prlock_wrlock(&lock->m_rwlock); + return TRUE; } - lock->m_waiting.remove_ticket(ticket); - lock->m_granted.add_ticket(ticket); - - if (ticket->get_type() == MDL_EXCLUSIVE && lock->cached_object) - (*lock->cached_object_release_hook)(lock->cached_object); - lock->cached_object= NULL; - - mysql_prlock_unlock(&lock->m_rwlock); + /* + We have been granted our request. + State of MDL_lock object is already being appropriately updated by a + concurrent thread (@sa MDL_lock:reschedule_waiters()). + So all we need to do is to update MDL_context and MDL_request objects. + */ + DBUG_ASSERT(wait_status == MDL_wait::GRANTED); m_tickets.push_front(ticket); @@ -1652,7 +1932,7 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests, for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++) { - if (acquire_lock_impl(*p_req, lock_wait_timeout)) + if (acquire_lock(*p_req, lock_wait_timeout)) goto err; } my_free(sort_buf, MYF(0)); @@ -1689,9 +1969,8 @@ err: shared mode). @note There can be only one upgrader for a lock or we will have deadlock. - This invariant is ensured by code outside of metadata subsystem usually - by obtaining some sort of exclusive table-level lock (e.g. TL_WRITE, - TL_WRITE_ALLOW_READ) before performing upgrade of metadata lock. + This invariant is ensured by the fact that upgradeable locks SNW + and SNRW are not compatible with each other and themselves. @retval FALSE Success @retval TRUE Failure (thread was killed) @@ -1721,7 +2000,7 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket, mdl_xlock_request.init(&mdl_ticket->m_lock->key, MDL_EXCLUSIVE); - if (acquire_lock_impl(&mdl_xlock_request, lock_wait_timeout)) + if (acquire_lock(&mdl_xlock_request, lock_wait_timeout)) DBUG_RETURN(TRUE); is_new_ticket= ! has_lock(mdl_svp, mdl_xlock_request.ticket); @@ -1752,251 +2031,231 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket, bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket, - Deadlock_detection_context *deadlock_ctx) + Deadlock_detection_visitor *dvisitor) { MDL_ticket *ticket; - bool result= FALSE; + MDL_context *src_ctx= waiting_ticket->get_ctx(); + bool result= TRUE; mysql_prlock_rdlock(&m_rwlock); + /* Must be initialized after taking a read lock. */ Ticket_iterator granted_it(m_granted); Ticket_iterator waiting_it(m_waiting); + /* + MDL_lock's waiting and granted queues and MDL_context::m_waiting_for + member are updated by different threads when the lock is granted + (see MDL_context::acquire_lock() and MDL_lock::reschedule_waiters()). + As a result, here we may encounter a situation when MDL_lock data + already reflects the fact that the lock was granted but + m_waiting_for member has not been updated yet. + + For example, imagine that: + + thread1: Owns SNW lock on table t1. + thread2: Attempts to acquire SW lock on t1, + but sees an active SNW lock. + Thus adds the ticket to the waiting queue and + sets m_waiting_for to point to the ticket. + thread1: Releases SNW lock, updates MDL_lock object to + grant SW lock to thread2 (moves the ticket for + SW from waiting to the active queue). + Attempts to acquire a new SNW lock on t1, + sees an active SW lock (since it is present in the + active queue), adds ticket for SNW lock to the waiting + queue, sets m_waiting_for to point to this ticket. + + At this point deadlock detection algorithm run by thread1 will see that: + - Thread1 waits for SNW lock on t1 (since m_waiting_for is set). + - SNW lock is not granted, because it conflicts with active SW lock + owned by thread 2 (since ticket for SW is present in granted queue). + - Thread2 waits for SW lock (since its m_waiting_for has not been + updated yet!). + - SW lock is not granted because there is pending SNW lock from thread1. + Therefore deadlock should exist [sic!]. + + To avoid detection of such false deadlocks we need to check the "actual" + status of the ticket being waited for, before analyzing its blockers. + We do this by checking the wait status of the context which is waiting + for it. To avoid races this has to be done under protection of + MDL_lock::m_rwlock lock. + */ + if (src_ctx->m_wait.get_status() != MDL_wait::EMPTY) + { + result= FALSE; + goto end; + } + + /* + To avoid visiting nodes which were already marked as victims of + deadlock detection (or whose requests were already satisfied) we + enter the node only after peeking at its wait status. + This is necessary to avoid active waiting in a situation + when previous searches for a deadlock already selected the + node we're about to enter as a victim (see the comment + in MDL_context::find_deadlock() for explanation why several searches + can be performed for the same wait). + There is no guarantee that the node isn't chosen a victim while we + are visiting it but this is OK: in the worst case we might do some + extra work and one more context might be chosen as a victim. + */ + if (dvisitor->enter_node(src_ctx)) + goto end; + + /* + We do a breadth-first search first -- that is, inspect all + edges of the current node, and only then follow up to the next + node. In workloads that involve wait-for graph loops this + has proven to be a more efficient strategy [citation missing]. + */ while ((ticket= granted_it++)) { - if (ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && - ticket->get_ctx() != waiting_ticket->get_ctx() && - ticket->get_ctx() == deadlock_ctx->start) + /* Filter out edges that point to the same node. */ + if (ticket->get_ctx() != src_ctx && + ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && + dvisitor->inspect_edge(ticket->get_ctx())) { - result= TRUE; - goto end; + goto end_leave_node; } } while ((ticket= waiting_it++)) { - if (ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && - ticket->get_ctx() != waiting_ticket->get_ctx() && - ticket->get_ctx() == deadlock_ctx->start) + /* Filter out edges that point to the same node. */ + if (ticket->get_ctx() != src_ctx && + ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && + dvisitor->inspect_edge(ticket->get_ctx())) { - result= TRUE; - goto end; + goto end_leave_node; } } + /* Recurse and inspect all adjacent nodes. */ granted_it.rewind(); while ((ticket= granted_it++)) { - if (ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && - ticket->get_ctx() != waiting_ticket->get_ctx() && - ticket->get_ctx()->find_deadlock(deadlock_ctx)) + if (ticket->get_ctx() != src_ctx && + ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && + ticket->get_ctx()->find_deadlock(dvisitor)) { - result= TRUE; - goto end; + goto end_leave_node; } } waiting_it.rewind(); while ((ticket= waiting_it++)) { - if (ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && - ticket->get_ctx() != waiting_ticket->get_ctx() && - ticket->get_ctx()->find_deadlock(deadlock_ctx)) + if (ticket->get_ctx() != src_ctx && + ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && + ticket->get_ctx()->find_deadlock(dvisitor)) { - result= TRUE; - goto end; + goto end_leave_node; } } + result= FALSE; + +end_leave_node: + dvisitor->leave_node(src_ctx); + end: mysql_prlock_unlock(&m_rwlock); return result; } -bool MDL_context::find_deadlock(Deadlock_detection_context *deadlock_ctx) +/** + Recursively traverse the wait-for graph of MDL contexts + in search for deadlocks. + + @retval TRUE A deadlock is found. A victim is remembered + by the visitor. + @retval FALSE +*/ + +bool MDL_context::find_deadlock(Deadlock_detection_visitor *dvisitor) { + MDL_context *m_unlock_ctx= this; bool result= FALSE; - mysql_prlock_rdlock(&m_waiting_for_lock); + mysql_prlock_rdlock(&m_LOCK_waiting_for); if (m_waiting_for) { - /* - QQ: should we rather be checking for NO_WAKE_UP ? - - We want to do check signal only when m_waiting_for is set - to avoid reading left-overs from previous kills. - */ - if (peek_signal() != VICTIM_WAKE_UP) - { - - if (++deadlock_ctx->current_search_depth > - deadlock_ctx->MAX_SEARCH_DEPTH) - result= TRUE; - else - result= m_waiting_for->m_lock->find_deadlock(m_waiting_for, - deadlock_ctx); - --deadlock_ctx->current_search_depth; - } - } - - if (result) - { - if (! deadlock_ctx->victim) - deadlock_ctx->victim= this; - else if (deadlock_ctx->victim->m_deadlock_weight >= m_deadlock_weight) - { - mysql_prlock_unlock(&deadlock_ctx->victim->m_waiting_for_lock); - deadlock_ctx->victim= this; - } - else - mysql_prlock_unlock(&m_waiting_for_lock); + result= m_waiting_for->m_lock->find_deadlock(m_waiting_for, dvisitor); + if (result) + m_unlock_ctx= dvisitor->opt_change_victim_to(this); } - else - mysql_prlock_unlock(&m_waiting_for_lock); + /* + We may recurse into the same MDL_context more than once + in case this is not the starting node. Make sure we release the + read lock as it's been taken, except for 1 read lock for + the deadlock victim. + */ + if (m_unlock_ctx) + mysql_prlock_unlock(&m_unlock_ctx->m_LOCK_waiting_for); return result; } -bool MDL_context::find_deadlock() -{ - while (1) - { - /* - The fact that we use fresh instance of deadlock_ctx for each - search performed by find_deadlock() below is important, code - responsible for victim selection relies on this. - */ - Deadlock_detection_context deadlock_ctx(this); - - if (! find_deadlock(&deadlock_ctx)) - { - /* No deadlocks are found! */ - break; - } - - if (deadlock_ctx.victim != this) - { - deadlock_ctx.victim->awake(VICTIM_WAKE_UP); - mysql_prlock_unlock(&deadlock_ctx.victim->m_waiting_for_lock); - /* - After adding new arc to waiting graph we found that it participates - in some loop (i.e. there is a deadlock). We decided to destroy this - loop by removing some arc other than newly added. Since this doesn't - guarantee that all loops created by addition of this arc are - destroyed we have to repeat search. - */ - continue; - } - else - { - DBUG_ASSERT(&deadlock_ctx.victim->m_waiting_for_lock == &m_waiting_for_lock); - mysql_prlock_unlock(&deadlock_ctx.victim->m_waiting_for_lock); - return TRUE; - } - } - return FALSE; -} - - /** - Wait until there will be no locks that conflict with lock requests - in the given list. - - This is a part of the locking protocol and must be used by the - acquirer of shared locks after a back-off. - - Does not acquire the locks! + Try to find a deadlock. This function produces no errors. - @param lock_wait_timeout Seconds to wait before timeout. + @note If during deadlock resolution context which performs deadlock + detection is chosen as a victim it will be informed about the + fact by setting VICTIM status to its wait slot. - @retval FALSE Success. One can try to obtain metadata locks. - @retval TRUE Failure (thread was killed or deadlock is possible). + @retval TRUE A deadlock is found. + @retval FALSE No deadlock found. */ -bool -MDL_context::wait_for_lock(MDL_request *mdl_request, ulong lock_wait_timeout) +void MDL_context::find_deadlock() { - MDL_lock *lock; - st_my_thread_var *mysys_var= my_thread_var; - struct timespec abs_timeout; - set_timespec(abs_timeout, lock_wait_timeout); - - mysql_mutex_assert_not_owner(&LOCK_open); - - DBUG_ASSERT(mdl_request->ticket == NULL); - - while (TRUE) + while (1) { /* - We have to check if there are some HANDLERs open by this thread - which conflict with some pending exclusive locks. Otherwise we - might have a deadlock in situations when we are waiting for - pending writer to go away, which in its turn waits for HANDLER - open by our thread. - - TODO: investigate situations in which we need to broadcast on - COND_mdl because of above scenario. + The fact that we use fresh instance of dvisitor for each + search performed by find_deadlock() below is important, + the code responsible for victim selection relies on this. */ - mysql_ha_flush(m_thd); - - MDL_key *key= &mdl_request->key; - - /* The below call implicitly locks MDL_lock::m_rwlock on success. */ - if (! (lock= mdl_locks.find(key))) - return FALSE; - - if (lock->can_grant_lock(mdl_request->type, this)) - { - mysql_prlock_unlock(&lock->m_rwlock); - return FALSE; - } + Deadlock_detection_visitor dvisitor(this); + MDL_context *victim; - MDL_ticket *pending_ticket; - if (! (pending_ticket= MDL_ticket::create(this, mdl_request->type))) + if (! find_deadlock(&dvisitor)) { - mysql_prlock_unlock(&lock->m_rwlock); - return TRUE; - } - - pending_ticket->m_lock= lock; - - lock->m_waiting.add_ticket(pending_ticket); - - wait_reset(); - mysql_prlock_unlock(&lock->m_rwlock); - - set_deadlock_weight(MDL_DEADLOCK_WEIGHT_DML); - will_wait_for(pending_ticket); - - bool is_deadlock= find_deadlock(); - bool is_timeout= FALSE; - if (!is_deadlock) - { - mdl_signal_type wait_result= timed_wait(&abs_timeout); - if (wait_result == TIMEOUT_WAKE_UP) - is_timeout= TRUE; - else if (wait_result == VICTIM_WAKE_UP) - is_deadlock= TRUE; + /* No deadlocks are found! */ + break; } - stop_waiting(); + victim= dvisitor.get_victim(); - lock->remove_ticket(&MDL_lock::m_waiting, pending_ticket); - MDL_ticket::destroy(pending_ticket); + /* + Failure to change status of the victim is OK as it means + that the victim has received some other message and is + about to stop its waiting/to break deadlock loop. + Even when the initiator of the deadlock search is + chosen the victim, we need to set the respective wait + result in order to "close" it for any attempt to + schedule the request. + This is needed to avoid a possible race during + cleanup in case when the lock request on which the + context was waiting is concurrently satisfied. + */ + (void) victim->m_wait.set_status(MDL_wait::VICTIM); + mysql_prlock_unlock(&victim->m_LOCK_waiting_for); - if (mysys_var->abort || is_deadlock || is_timeout) - { - if (is_deadlock) - my_error(ER_LOCK_DEADLOCK, MYF(0)); - else if (is_timeout) - my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); - return TRUE; - } + if (victim == this) + break; + /* + After adding a new edge to the waiting graph we found that it + creates a loop (i.e. there is a deadlock). We decided to destroy + this loop by removing an edge, but not the one that we added. + Since this doesn't guarantee that all loops created by addition + of the new edge are destroyed, we have to repeat the search. + */ } - return TRUE; } @@ -2125,7 +2384,7 @@ void MDL_ticket::downgrade_exclusive_lock(enum_mdl_type type) m_lock->m_granted.remove_ticket(this); m_type= type; m_lock->m_granted.add_ticket(this); - m_lock->wake_up_waiters(); + m_lock->reschedule_waiters(); mysql_prlock_unlock(&m_lock->m_rwlock); } @@ -2330,7 +2589,6 @@ void MDL_context::move_ticket_after_trans_sentinel(MDL_ticket *mdl_ticket) if (m_trans_sentinel == NULL) { m_trans_sentinel= mdl_ticket; - /* sic: linear from the number of transactional tickets acquired so-far! */ m_tickets.push_back(mdl_ticket); } else diff --git a/sql/mdl.h b/sql/mdl.h index 89a679be264..43d88c143c0 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -34,7 +34,7 @@ class THD; class MDL_context; class MDL_lock; class MDL_ticket; -class Deadlock_detection_context; +class Deadlock_detection_visitor; /** Type of metadata lock request. @@ -308,6 +308,10 @@ public: MDL_key key; public: + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () + { return alloc_root(mem_root, size); } + static void operator delete(void *ptr, MEM_ROOT *mem_root) {} + void init(MDL_key::enum_mdl_namespace namespace_arg, const char *db_arg, const char *name_arg, enum_mdl_type mdl_type_arg); @@ -318,8 +322,6 @@ public: DBUG_ASSERT(ticket == NULL); type= type_arg; } - uint get_deadlock_weight() const; - static MDL_request *create(MDL_key::enum_mdl_namespace mdl_namespace, const char *db, const char *name, enum_mdl_type mdl_type, MEM_ROOT *root); @@ -413,6 +415,8 @@ public: bool is_incompatible_when_granted(enum_mdl_type type) const; bool is_incompatible_when_waiting(enum_mdl_type type) const; + /* A helper used to determine which lock request should be aborted. */ + uint get_deadlock_weight() const; private: friend class MDL_context; @@ -443,6 +447,37 @@ private: }; +/** + A reliable way to wait on an MDL lock. +*/ + +class MDL_wait +{ +public: + MDL_wait(); + ~MDL_wait(); + + enum enum_wait_status { EMPTY = 0, GRANTED, VICTIM, TIMEOUT, KILLED }; + + bool set_status(enum_wait_status result_arg); + enum_wait_status get_status(); + void reset_status(); + enum_wait_status timed_wait(THD *thd, struct timespec *abs_timeout, + bool signal_timeout); +private: + /** + Condvar which is used for waiting until this context's pending + request can be satisfied or this thread has to perform actions + to resolve a potential deadlock (we subscribe to such + notification by adding a ticket corresponding to the request + to an appropriate queue of waiters). + */ + mysql_mutex_t m_LOCK_wait_status; + mysql_cond_t m_COND_wait_status; + enum_wait_status m_wait_status; +}; + + typedef I_P_List<MDL_request, I_P_List_adapter<MDL_request, &MDL_request::next_in_list, &MDL_request::prev_in_list>, @@ -460,16 +495,13 @@ public: typedef I_P_List<MDL_ticket, I_P_List_adapter<MDL_ticket, &MDL_ticket::next_in_context, - &MDL_ticket::prev_in_context> > + &MDL_ticket::prev_in_context>, + I_P_List_null_counter, + I_P_List_fast_push_back<MDL_ticket> > Ticket_list; typedef Ticket_list::Iterator Ticket_iterator; - enum mdl_signal_type { NO_WAKE_UP = 0, - NORMAL_WAKE_UP, - VICTIM_WAKE_UP, - TIMEOUT_WAKE_UP }; - MDL_context(); void destroy(); @@ -481,8 +513,6 @@ public: bool clone_ticket(MDL_request *mdl_request); - bool wait_for_lock(MDL_request *mdl_request, ulong lock_wait_timeout); - void release_all_locks_for_name(MDL_ticket *ticket); void release_lock(MDL_ticket *ticket); @@ -524,17 +554,17 @@ public: inline THD *get_thd() const { return m_thd; } + /** @pre Only valid if we started waiting for lock. */ + inline uint get_deadlock_weight() const + { return m_waiting_for->get_deadlock_weight(); } /** - Wake up context which is waiting for a change of MDL_lock state. - */ - void awake(mdl_signal_type signal) - { - mysql_mutex_lock(&m_signal_lock); - m_signal= signal; - mysql_cond_signal(&m_signal_cond); - mysql_mutex_unlock(&m_signal_lock); - } + Post signal to the context (and wake it up if necessary). + @retval FALSE - Success, signal was posted. + @retval TRUE - Failure, signal was not posted since context + already has received some signal or closed + signal slot. + */ void init(THD *thd_arg) { m_thd= thd_arg; } void set_needs_thr_lock_abort(bool needs_thr_lock_abort) @@ -554,7 +584,13 @@ public: return m_needs_thr_lock_abort; } - bool find_deadlock(Deadlock_detection_context *deadlock_ctx); + bool find_deadlock(Deadlock_detection_visitor *dvisitor); +public: + /** + If our request for a lock is scheduled, or aborted by the deadlock + detector, the result is recorded in this class. + */ + MDL_wait m_wait; private: /** All MDL tickets acquired by this connection. @@ -636,71 +672,38 @@ private: important as deadlock detector won't work correctly otherwise. @sa Comment for MDL_lock::m_rwlock. */ - mysql_prlock_t m_waiting_for_lock; - MDL_ticket *m_waiting_for; - uint m_deadlock_weight; + mysql_prlock_t m_LOCK_waiting_for; /** - Condvar which is used for waiting until this context's pending - request can be satisfied or this thread has to perform actions - to resolve a potential deadlock (we subscribe to such - notification by adding a ticket corresponding to the request - to an appropriate queue of waiters). - */ - mysql_mutex_t m_signal_lock; - mysql_cond_t m_signal_cond; - mdl_signal_type m_signal; - + Tell the deadlock detector what lock this session is waiting for. + In principle, this is redundant, as information can be found + by inspecting waiting queues, but we'd very much like it to be + readily available to the wait-for graph iterator. + */ + MDL_ticket *m_waiting_for; private: MDL_ticket *find_ticket(MDL_request *mdl_req, bool *is_transactional); void release_locks_stored_before(MDL_ticket *sentinel); - bool acquire_lock_impl(MDL_request *mdl_request, ulong lock_wait_timeout); + bool try_acquire_lock_impl(MDL_request *mdl_request, + MDL_ticket **out_ticket); - bool find_deadlock(); + void find_deadlock(); + /** Inform the deadlock detector there is an edge in the wait-for graph. */ void will_wait_for(MDL_ticket *pending_ticket) { - mysql_prlock_wrlock(&m_waiting_for_lock); + mysql_prlock_wrlock(&m_LOCK_waiting_for); m_waiting_for= pending_ticket; - mysql_prlock_unlock(&m_waiting_for_lock); + mysql_prlock_unlock(&m_LOCK_waiting_for); } - void set_deadlock_weight(uint weight) + /** Remove the wait-for edge from the graph after we're done waiting. */ + void done_waiting_for() { - /* - m_deadlock_weight should not be modified while m_waiting_for is - non-NULL as in this case this context might participate in deadlock - and so m_deadlock_weight can be accessed from other threads. - */ - DBUG_ASSERT(m_waiting_for == NULL); - m_deadlock_weight= weight; - } - - void stop_waiting() - { - mysql_prlock_wrlock(&m_waiting_for_lock); + mysql_prlock_wrlock(&m_LOCK_waiting_for); m_waiting_for= NULL; - mysql_prlock_unlock(&m_waiting_for_lock); + mysql_prlock_unlock(&m_LOCK_waiting_for); } - - void wait_reset() - { - mysql_mutex_lock(&m_signal_lock); - m_signal= NO_WAKE_UP; - mysql_mutex_unlock(&m_signal_lock); - } - - mdl_signal_type timed_wait(struct timespec *abs_timeout); - - mdl_signal_type peek_signal() - { - mdl_signal_type result; - mysql_mutex_lock(&m_signal_lock); - result= m_signal; - mysql_mutex_unlock(&m_signal_lock); - return result; - } - private: MDL_context(const MDL_context &rhs); /* not implemented */ MDL_context &operator=(MDL_context &rhs); /* not implemented */ @@ -717,7 +720,6 @@ void mdl_destroy(); extern bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, bool needs_thr_lock_abort); -extern void mysql_ha_flush(THD *thd); extern "C" const char *set_thd_proc_info(void *thd_arg, const char *info, const char *calling_function, const char *calling_file, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7968d637223..d1bf387cc5f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1388,7 +1388,7 @@ extern "C" sig_handler print_signal_warning(int sig) { if (global_system_variables.log_warnings) sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id()); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif #if !defined(__WIN__) && !defined(__NETWARE__) @@ -2649,7 +2649,6 @@ extern "C" sig_handler handle_segfault(int sig) { time_t curr_time; struct tm tm; - THD *thd=current_thd; /* Strictly speaking, one needs a mutex here @@ -2709,13 +2708,15 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n", #endif /* HAVE_LINUXTHREADS */ #ifdef HAVE_STACKTRACE + THD *thd=current_thd; + if (!(test_flags & TEST_NO_STACKTRACE)) { - fprintf(stderr,"thd: 0x%lx\n",(long) thd); - fprintf(stderr,"\ -Attempting backtrace. You can use the following information to find out\n\ -where mysqld died. If you see no messages after this, something went\n\ -terribly wrong...\n"); + fprintf(stderr, "thd: 0x%lx\n",(long) thd); + fprintf(stderr, "Attempting backtrace. You can use the following " + "information to find out\nwhere mysqld died. If " + "you see no messages after this, something went\n" + "terribly wrong...\n"); my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL, my_thread_stack_size); } @@ -3435,8 +3436,16 @@ static int init_common_variables() compiler error in the Sun Studio 12 compiler. As a work-around we set the def_value member to 0 in my_long_options and initialize it to the correct value here. + + From MySQL 5.5 onwards, the default storage engine is InnoDB + (except in the embedded server, where the default continues to + be MyISAM) */ +#ifdef EMBEDDED_LIBRARY default_storage_engine= const_cast<char *>("MyISAM"); +#else + default_storage_engine= const_cast<char *>("InnoDB"); +#endif /* Add server status variables to the dynamic list of diff --git a/sql/opt_range.cc b/sql/opt_range.cc index b0ffbe6a7c2..6df8cf2c2a9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1227,7 +1227,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param, TABLE *table) - :pk_quick_select(NULL), thd(thd_param) + :unique(NULL), pk_quick_select(NULL), thd(thd_param) { DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT"); index= MAX_KEY; @@ -1269,6 +1269,7 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT() List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects); QUICK_RANGE_SELECT* quick; DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT"); + delete unique; quick_it.rewind(); while ((quick= quick_it++)) quick->file= NULL; @@ -8342,7 +8343,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it(quick_selects); QUICK_RANGE_SELECT* cur_quick; int result; - Unique *unique; handler *file= head->file; DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge"); @@ -8361,9 +8361,22 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (cur_quick->init() || cur_quick->reset()) DBUG_RETURN(1); - unique= new Unique(refpos_order_cmp, (void *)file, - file->ref_length, - thd->variables.sortbuff_size); + if (unique == NULL) + { + DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique", abort(); ); + DBUG_EXECUTE_IF("only_one_Unique_may_be_created", + DBUG_SET("+d,index_merge_may_not_create_a_Unique"); ); + + unique= new Unique(refpos_order_cmp, (void *)file, + file->ref_length, + thd->variables.sortbuff_size); + } + else + unique->reset(); + + DBUG_ASSERT(file->ref_length == unique->get_size()); + DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size()); + if (!unique) DBUG_RETURN(1); for (;;) @@ -8378,10 +8391,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (cur_quick->file->inited != handler::NONE) cur_quick->file->ha_index_end(); if (cur_quick->init() || cur_quick->reset()) - { - delete unique; DBUG_RETURN(1); - } } if (result) @@ -8389,17 +8399,13 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (result != HA_ERR_END_OF_FILE) { cur_quick->range_end(); - delete unique; DBUG_RETURN(result); } break; } if (thd->killed) - { - delete unique; DBUG_RETURN(1); - } /* skip row if it will be retrieved by clustered PK scan */ if (pk_quick_select && pk_quick_select->row_in_ranges()) @@ -8408,10 +8414,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() cur_quick->file->position(cur_quick->record); result= unique->unique_add((char*)cur_quick->file->ref); if (result) - { - delete unique; DBUG_RETURN(1); - } } /* @@ -8420,7 +8423,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() sequence. */ result= unique->get(head); - delete unique; doing_pk_scan= FALSE; /* index_merge currently doesn't support "using index" at all */ head->set_keyread(FALSE); @@ -10496,7 +10498,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, ha_rows records_arg, uint key_infix_len_arg, uchar *key_infix_arg, MEM_ROOT *parent_alloc, bool is_index_scan_arg) - :join(join_arg), index_info(index_info_arg), + :file(table->file), join(join_arg), index_info(index_info_arg), group_prefix_len(group_prefix_len_arg), group_key_parts(group_key_parts_arg), have_min(have_min_arg), have_max(have_max_arg), have_agg_distinct(have_agg_distinct_arg), @@ -10506,7 +10508,6 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, is_index_scan(is_index_scan_arg) { head= table; - file= head->file; index= use_index; record= head->record[0]; tmp_record= head->record[1]; diff --git a/sql/opt_range.h b/sql/opt_range.h index 72f2eb4b51d..b15833a00e2 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -514,6 +514,7 @@ public: class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I { + Unique *unique; public: QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table); ~QUICK_INDEX_MERGE_SELECT(); @@ -697,7 +698,7 @@ private: class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I { private: - handler *file; /* The handler used to get data. */ + handler * const file; /* The handler used to get data. */ JOIN *join; /* Descriptor of the current query */ KEY *index_info; /* The index chosen for data access */ uchar *record; /* Buffer where the next record is returned. */ diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index cddf798aac0..81366d55fc6 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -102,7 +102,6 @@ static int init_failsafe_rpl_thread(THD* thd) thd->mem_root->free= thd->mem_root->used= 0; thd_proc_info(thd, "Thread initialized"); - thd->version=refresh_version; thd->set_time(); DBUG_RETURN(0); } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 8f070c51410..c1139599241 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1138,8 +1138,7 @@ bool Relay_log_info::cached_charset_compare(char *charset) const { DBUG_ENTER("Relay_log_info::cached_charset_compare"); - if (bcmp((uchar*) cached_charset, (uchar*) charset, - sizeof(cached_charset))) + if (memcmp(cached_charset, charset, sizeof(cached_charset))) { memcpy(const_cast<char*>(cached_charset), charset, sizeof(cached_charset)); DBUG_RETURN(1); diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 0675e9b51ad..7479e58fd98 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -517,10 +517,12 @@ void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_ bool is_conversion_ok(int order, Relay_log_info *rli) { DBUG_ENTER("is_conversion_ok"); - bool allow_non_lossy= - bit_is_set(slave_type_conversions_options, SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY); - bool allow_lossy= - bit_is_set(slave_type_conversions_options, SLAVE_TYPE_CONVERSIONS_ALL_LOSSY); + bool allow_non_lossy, allow_lossy; + + allow_non_lossy = slave_type_conversions_options & + (ULL(1) << SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY); + allow_lossy= slave_type_conversions_options & + (ULL(1) << SLAVE_TYPE_CONVERSIONS_ALL_LOSSY); DBUG_PRINT("enter", ("order: %d, flags:%s%s", order, allow_non_lossy ? " ALL_NON_LOSSY" : "", diff --git a/sql/share/CMakeLists.txt b/sql/share/CMakeLists.txt index 1868200f038..14de851aaa2 100644 --- a/sql/share/CMakeLists.txt +++ b/sql/share/CMakeLists.txt @@ -45,10 +45,10 @@ SET(files FOREACH (dir ${dirs}) INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} - DESTINATION ${INSTALL_MYSQLSHAREDIR}) + DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) ENDFOREACH() -INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/charsets DESTINATION ${INSTALL_MYSQLSHAREDIR} +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/charsets DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server PATTERN "languages.html" EXCLUDE ) -INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR}) +INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server) diff --git a/sql/slave.cc b/sql/slave.cc index 6ebdea4a42a..ba77eb482b6 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2055,7 +2055,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) thd_proc_info(thd, "Waiting for the next event in relay log"); else thd_proc_info(thd, "Waiting for master update"); - thd->version=refresh_version; thd->set_time(); /* Do not use user-supplied timeout value for system threads. */ thd->variables.lock_wait_timeout= LONG_TIMEOUT; @@ -2296,7 +2295,7 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu", FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->variables.option_bits, OPTION_BEGIN), - rli->last_event_start_time)); + (ulong) rli->last_event_start_time)); /* Execute the event to change the database and update the binary @@ -3126,8 +3125,8 @@ pthread_handler_t handle_slave_sql(void *arg) char llbuff[22],llbuff1[22]; char saved_log_name[FN_REFLEN]; char saved_master_log_name[FN_REFLEN]; - my_off_t saved_log_pos; - my_off_t saved_master_log_pos; + my_off_t UNINIT_VAR(saved_log_pos); + my_off_t UNINIT_VAR(saved_master_log_pos); my_off_t saved_skip= 0; Relay_log_info* rli = &((Master_info*)arg)->rli; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 1e708bcb083..f75acf11984 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -4028,6 +4028,11 @@ sp_head::add_used_tables_to_table_list(THD *thd, table->prelocking_placeholder= 1; table->belong_to_view= belong_to_view; table->trg_event_map= stab->trg_event_map; + /* + Since we don't allow DDL on base tables in prelocked mode it + is safe to infer the type of metadata lock from the type of + table lock. + */ table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name, table->lock_type >= TL_WRITE_ALLOW_WRITE ? MDL_SHARED_WRITE : MDL_SHARED_READ); @@ -4057,8 +4062,9 @@ sp_head::add_used_tables_to_table_list(THD *thd, TABLE_LIST * sp_add_to_query_tables(THD *thd, LEX *lex, - const char *db, const char *name, - thr_lock_type locktype) + const char *db, const char *name, + thr_lock_type locktype, + enum_mdl_type mdl_type) { TABLE_LIST *table; @@ -4073,8 +4079,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex, table->select_lex= lex->current_select; table->cacheable_table= 1; table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name, - table->lock_type >= TL_WRITE_ALLOW_WRITE ? - MDL_SHARED_WRITE : MDL_SHARED_READ); + mdl_type); lex->add_to_query_tables(table); return table; diff --git a/sql/sp_head.h b/sql/sp_head.h index 539a2da5f8c..9796c49fdfb 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1342,7 +1342,9 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc, TABLE_LIST * sp_add_to_query_tables(THD *thd, LEX *lex, const char *db, const char *name, - thr_lock_type locktype); + thr_lock_type locktype, + enum_mdl_type mdl_type); + Item * sp_prepare_func_item(THD* thd, Item **it_addr); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ec25e4cb68b..8c241d8d7ba 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -210,6 +210,7 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); +static inline void get_grantor(THD *thd, char* grantor); /* Convert scrambled password to binary form, according to scramble type, @@ -2755,6 +2756,20 @@ end: DBUG_RETURN(result); } +static inline void get_grantor(THD *thd, char *grantor) +{ + const char *user= thd->security_ctx->user; + const char *host= thd->security_ctx->host_or_ip; + +#if defined(HAVE_REPLICATION) + if (thd->slave_thread && thd->has_invoker()) + { + user= thd->get_invoker_user().str; + host= thd->get_invoker_host().str; + } +#endif + strxmov(grantor, user, "@", host, NullS); +} static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, TABLE *table, const LEX_USER &combo, @@ -2769,9 +2784,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); - strxmov(grantor, thd->security_ctx->user, "@", - thd->security_ctx->host_or_ip, NullS); - + get_grantor(thd, grantor); /* The following should always succeed as new users are created before this function is called! @@ -2901,9 +2914,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } - strxmov(grantor, thd->security_ctx->user, "@", - thd->security_ctx->host_or_ip, NullS); - + get_grantor(thd, grantor); /* New users are created before this function is called. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 325f054db02..47aebc37241 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -16,18 +16,18 @@ /* Basic functions needed by many modules */ +#include "sql_base.h" // setup_table_map #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" #include "unireg.h" #include "debug_sync.h" -#include "sql_base.h" // setup_table_map #include "lock.h" // broadcast_refresh, mysql_lock_remove, // mysql_unlock_tables, // mysql_lock_have_duplicate #include "sql_show.h" // append_identifier #include "strfunc.h" // find_type #include "parse_file.h" // sql_parse_prepare, File_parser -#include "sql_view.h" // mysql_frm_type, mysql_make_view, VIEW_ANY_ACL +#include "sql_view.h" // mysql_make_view, VIEW_ANY_ACL #include "sql_parse.h" // check_table_access #include "sql_insert.h" // kill_delayed_threads #include "sql_acl.h" // *_ACL, check_grant_all_columns, @@ -52,6 +52,7 @@ #include <hash.h> #include "rpl_filter.h" #include "sql_table.h" // build_table_filename +#include "datadict.h" // dd_frm_type() #ifdef __WIN__ #include <io.h> #endif @@ -438,6 +439,9 @@ static void table_def_unuse_table(TABLE *table) { DBUG_ASSERT(table->in_use); + /* We shouldn't put the table to 'unused' list if the share is old. */ + DBUG_ASSERT(! table->s->needs_reopen()); + table->in_use= 0; /* Remove table from the list of tables used in this share. */ table->s->used_tables.remove(table); @@ -558,7 +562,9 @@ found: DBUG_RETURN(0); } - if (!share->ref_count++ && share->prev) + ++share->ref_count; + + if (share->ref_count == 1 && share->prev) { /* Share was not used before and it was in the old_unused_share list @@ -685,7 +691,6 @@ static TABLE_SHARE void release_table_share(TABLE_SHARE *share) { - bool to_be_deleted= 0; DBUG_ENTER("release_table_share"); DBUG_PRINT("enter", ("share: 0x%lx table: %s.%s ref_count: %u version: %lu", @@ -697,9 +702,8 @@ void release_table_share(TABLE_SHARE *share) DBUG_ASSERT(share->ref_count); if (!--share->ref_count) { - if (share->version != refresh_version || - table_def_shutdown_in_progress) - to_be_deleted=1; + if (share->needs_reopen() || table_def_shutdown_in_progress) + my_hash_delete(&table_def_cache, (uchar*) share); else { /* Link share last in used_table_share list */ @@ -711,15 +715,14 @@ void release_table_share(TABLE_SHARE *share) end_of_unused_share.prev= &share->next; share->next= &end_of_unused_share; - to_be_deleted= (table_def_cache.records > table_def_size); + if (table_def_cache.records > table_def_size) + { + /* Delete the least used share to preserve LRU order. */ + my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share); + } } } - if (to_be_deleted) - { - DBUG_PRINT("info", ("Deleting share")); - my_hash_delete(&table_def_cache, (uchar*) share); - } DBUG_VOID_RETURN; } @@ -834,7 +837,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) I_P_List_iterator<TABLE, TABLE_share> it(share->used_tables); while (it++) ++(*start_list)->in_use; - (*start_list)->locked= (share->version == 0) ? 1 : 0; + (*start_list)->locked= 0; /* Obsolete. */ start_list= &(*start_list)->next; *start_list=0; } @@ -1023,6 +1026,9 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, TABLE_LIST *tables_to_reopen= (tables ? tables : thd->locked_tables_list.locked_tables()); + /* Close open HANLER instances to avoid self-deadlock. */ + mysql_ha_flush_tables(thd, tables_to_reopen); + for (TABLE_LIST *table_list= tables_to_reopen; table_list; table_list= table_list->next_global) { @@ -1050,7 +1056,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, { found= FALSE; /* - To avoid self and other kinds of deadlock we have to flush open HANDLERs. + To a self-deadlock or deadlocks with other FLUSH threads + waiting on our open HANDLERs, we have to flush them. */ mysql_ha_flush(thd); DEBUG_SYNC(thd, "after_flush_unlock"); @@ -1065,7 +1072,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, { TABLE_SHARE *share=(TABLE_SHARE*) my_hash_element(&table_def_cache, idx); - if (share->version != refresh_version) + if (share->needs_reopen()) { found= TRUE; break; @@ -1077,7 +1084,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, for (TABLE_LIST *table= tables; table; table= table->next_local) { TABLE_SHARE *share= get_cached_table_share(table->db, table->table_name); - if (share && share->version != refresh_version) + if (share && share->needs_reopen()) { found= TRUE; break; @@ -1295,29 +1302,21 @@ static void close_open_tables(THD *thd) mysql_mutex_assert_not_owner(&LOCK_open); - mysql_mutex_lock(&LOCK_open); - DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); while (thd->open_tables) found_old_table|= close_thread_table(thd, &thd->open_tables); - /* Free tables to hold down open files */ - while (table_cache_count > table_cache_size && unused_tables) - free_cache_entry(unused_tables); if (found_old_table) { /* Tell threads waiting for refresh that something has happened */ broadcast_refresh(); } - - mysql_mutex_unlock(&LOCK_open); } /** - Close all open instances of the table but keep the MDL lock, - if any. + Close all open instances of the table but keep the MDL lock. Works both under LOCK TABLES and in the normal mode. Removes all closed instances of the table from the table cache. @@ -1331,6 +1330,8 @@ static void close_open_tables(THD *thd) In that case the documented behaviour is to implicitly remove the table from LOCK TABLES list. + + @pre Must be called with an X MDL lock on the table. */ void @@ -1339,17 +1340,12 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, { char key[MAX_DBKEY_LENGTH]; uint key_length= share->table_cache_key.length; + const char *db= key; + const char *table_name= db + share->db.length + 1; memcpy(key, share->table_cache_key.str, key_length); mysql_mutex_assert_not_owner(&LOCK_open); - /* - We need to hold LOCK_open while changing the open_tables - list, since another thread may work on it. - @sa mysql_notify_thread_having_shared_lock() - */ - mysql_mutex_lock(&LOCK_open); - for (TABLE **prev= &thd->open_tables; *prev; ) { TABLE *table= *prev; @@ -1357,10 +1353,9 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, if (table->s->table_cache_key.length == key_length && !memcmp(table->s->table_cache_key.str, key, key_length)) { - /* Inform handler that table will be dropped after close */ - if (table->db_stat) - table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); - + thd->locked_tables_list.unlink_from_list(thd, + table->pos_in_locked_tables, + remove_from_locked_tables); /* Does nothing if the table is not locked. This allows one to use this function after a table @@ -1368,12 +1363,9 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, */ mysql_lock_remove(thd, thd->lock, table); - thd->locked_tables_list.unlink_from_list(thd, - table->pos_in_locked_tables, - remove_from_locked_tables); - - /* Make sure the table is removed from the cache */ - table->s->version= 0; + /* Inform handler that table will be dropped after close */ + if (table->db_stat) /* Not true for partitioned tables. */ + table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); close_thread_table(thd, prev); } else @@ -1382,9 +1374,15 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, prev= &table->next; } } - /* We have been removing tables from the table cache. */ - broadcast_refresh(); + /* Remove the table share from the cache. */ + mysql_mutex_lock(&LOCK_open); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table_name); mysql_mutex_unlock(&LOCK_open); + /* + There could be a FLUSH thread waiting + on the table to go away. Wake it up. + */ + broadcast_refresh(); } @@ -1583,30 +1581,43 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) DBUG_ENTER("close_thread_table"); DBUG_ASSERT(table->key_read == 0); DBUG_ASSERT(!table->file || table->file->inited == handler::NONE); - mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); + + table->mdl_ticket= NULL; + mysql_mutex_lock(&thd->LOCK_thd_data); *table_ptr=table->next; + mysql_mutex_unlock(&thd->LOCK_thd_data); - table->mdl_ticket= NULL; - if (table->s->needs_reopen() || - thd->version != refresh_version || table->needs_reopen() || + if (! table->needs_reopen()) + { + /* Avoid having MERGE tables with attached children in unused_tables. */ + table->file->extra(HA_EXTRA_DETACH_CHILDREN); + /* Free memory and reset for next loop. */ + free_field_buffers_larger_than(table, MAX_TDC_BLOB_SIZE); + table->file->ha_reset(); + } + + mysql_mutex_lock(&LOCK_open); + + if (table->s->needs_reopen() || table->needs_reopen() || table_def_shutdown_in_progress) { free_cache_entry(table); - found_old_table=1; + found_old_table= 1; } else { - /* Avoid to have MERGE tables with attached children in unused_tables. */ DBUG_ASSERT(table->file); - table->file->extra(HA_EXTRA_DETACH_CHILDREN); - - /* Free memory and reset for next loop */ - free_field_buffers_larger_than(table,MAX_TDC_BLOB_SIZE); - - table->file->ha_reset(); table_def_unuse_table(table); + /* + We free the least used table, not the subject table, + to keep the LRU order. + */ + if (table_cache_count > table_cache_size) + free_cache_entry(unused_tables); } + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(found_old_table); } @@ -2227,14 +2238,15 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name, DBUG_ASSERT(table == thd->open_tables); handlerton *table_type= table->s->db_type(); - /* Ensure the table is removed from the cache. */ - table->s->version= 0; - mysql_mutex_lock(&LOCK_open); table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); close_thread_table(thd, &thd->open_tables); - quick_rm_table(table_type, db_name, table_name, 0); + /* Remove the table share from the table cache. */ + mysql_mutex_lock(&LOCK_open); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db_name, table_name); mysql_mutex_unlock(&LOCK_open); + /* Remove the table from the storage engine and rm the .frm. */ + quick_rm_table(table_type, db_name, table_name, 0); } DBUG_VOID_RETURN; } @@ -2294,7 +2306,7 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond) @param[out] exists Out parameter which is set to TRUE if table exists and to FALSE otherwise. - @note This function assumes that caller owns LOCK_open mutex. + @note This function acquires LOCK_open internally. It also assumes that the fact that there are no exclusive metadata locks on the table was checked beforehand. @@ -2302,28 +2314,30 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond) of engines (e.g. it was created on another node of NDB cluster) this function will fetch and create proper .FRM file for it. - @retval TRUE Some error occured + @retval TRUE Some error occurred @retval FALSE No error. 'exists' out parameter set accordingly. */ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists) { char path[FN_REFLEN + 1]; - int rc; + int rc= 0; DBUG_ENTER("check_if_table_exists"); - mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); *exists= TRUE; + mysql_mutex_lock(&LOCK_open); + if (get_cached_table_share(table->db, table->table_name)) - DBUG_RETURN(FALSE); + goto end; build_table_filename(path, sizeof(path) - 1, table->db, table->table_name, reg_ext, 0); if (!access(path, F_OK)) - DBUG_RETURN(FALSE); + goto end; /* .FRM file doesn't exist. Check if some engine can provide it. */ @@ -2333,19 +2347,17 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists) { /* Table does not exists in engines as well. */ *exists= FALSE; - DBUG_RETURN(FALSE); - } - else if (!rc) - { - /* Table exists in some engine and .FRM for it was created. */ - DBUG_RETURN(FALSE); + rc= 0; } - else /* (rc > 0) */ + else if (rc) { my_printf_error(ER_UNKNOWN_ERROR, "Failed to open '%-.64s', error while " "unpacking from engine", MYF(0), table->table_name); - DBUG_RETURN(TRUE); } + +end: + mysql_mutex_unlock(&LOCK_open); + DBUG_RETURN(test(rc)); } @@ -2364,82 +2376,192 @@ void table_share_release_hook(void *share) /** - A helper function that acquires an MDL lock for a table - being opened. + An error handler which converts, if possible, ER_LOCK_DEADLOCK error + that can occur when we are trying to acquire a metadata lock to + a request for back-off and re-start of open_tables() process. */ -static bool -open_table_get_mdl_lock(THD *thd, TABLE_LIST *table_list, - MDL_request *mdl_request, - Open_table_context *ot_ctx, - uint flags) +class MDL_deadlock_handler : public Internal_error_handler +{ +public: + MDL_deadlock_handler(Open_table_context *ot_ctx_arg) + : m_ot_ctx(ot_ctx_arg), m_is_active(FALSE) + {} + + virtual ~MDL_deadlock_handler() {} + + virtual bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + MYSQL_ERROR::enum_warning_level level, + const char* msg, + MYSQL_ERROR ** cond_hdl); + +private: + /** Open table context to be used for back-off request. */ + Open_table_context *m_ot_ctx; + /** + Indicates that we are already in the process of handling + ER_LOCK_DEADLOCK error. Allows to re-emit the error from + the error handler without falling into infinite recursion. + */ + bool m_is_active; +}; + + +bool MDL_deadlock_handler::handle_condition(THD *, + uint sql_errno, + const char*, + MYSQL_ERROR::enum_warning_level, + const char*, + MYSQL_ERROR ** cond_hdl) { - if (table_list->lock_strategy) + *cond_hdl= NULL; + if (! m_is_active && sql_errno == ER_LOCK_DEADLOCK) { - MDL_request_list mdl_requests; - MDL_request *global_request; + /* Disable the handler to avoid infinite recursion. */ + m_is_active= TRUE; + (void) m_ot_ctx->request_backoff_action(Open_table_context::OT_MDL_CONFLICT, + NULL); + m_is_active= FALSE; /* - In case of CREATE TABLE .. If NOT EXISTS .. SELECT, the table - may not yet exist. Let's acquire an exclusive lock for that - case. If later it turns out the table existsed, we will - downgrade the lock to shared. Note that, according to the - locking protocol, all exclusive locks must be acquired before - shared locks. This invariant is preserved here and is also - enforced by asserts in metadata locking subsystem. + If the above back-off request failed, a new instance of + ER_LOCK_DEADLOCK error was emitted. Thus the current + instance of error condition can be treated as handled. */ + return TRUE; + } + return FALSE; +} - mdl_request->set_type(MDL_EXCLUSIVE); - DBUG_ASSERT(! thd->mdl_context.has_locks() || - thd->handler_tables_hash.records || - thd->global_read_lock.is_acquired()); - - if (!(global_request= ot_ctx->get_global_mdl_request(thd))) - return 1; - mdl_requests.push_front(mdl_request); - mdl_requests.push_front(global_request); +/** + Try to acquire an MDL lock for a table being opened. + + @param[in,out] thd Session context, to report errors. + @param[out] ot_ctx Open table context, to hold the back off + state. If we failed to acquire a lock + due to a lock conflict, we add the + failed request to the open table context. + @param[in,out] mdl_request A request for an MDL lock. + If we managed to acquire a ticket + (no errors or lock conflicts occurred), + contains a reference to it on + return. However, is not modified if MDL + lock type- modifying flags were provided. + @param[in] flags flags MYSQL_OPEN_FORCE_SHARED_MDL, + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL or + MYSQL_OPEN_FAIL_ON_MDL_CONFLICT + @sa open_table(). + @param[out] mdl_ticket Only modified if there was no error. + If we managed to acquire an MDL + lock, contains a reference to the + ticket, otherwise is set to NULL. + + @retval TRUE An error occurred. + @retval FALSE No error, but perhaps a lock conflict, check mdl_ticket. +*/ - if (thd->mdl_context.acquire_locks(&mdl_requests, ot_ctx->get_timeout())) - return 1; - } - else +static bool +open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx, + MDL_request *mdl_request, + uint flags, + MDL_ticket **mdl_ticket) +{ + if (flags & (MYSQL_OPEN_FORCE_SHARED_MDL | + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)) { - if (flags & MYSQL_OPEN_FORCE_SHARED_MDL) - { - /* - While executing PREPARE for prepared statement we override - type-of-operation aware type of shared metadata lock which - was set in the parser with simple shared metadata lock. - This is necessary to allow concurrent execution of PREPARE - and LOCK TABLES WRITE statement which locks one of the tables - used in the statement being prepared. - */ - DBUG_ASSERT(!(flags & (MYSQL_OPEN_TAKE_UPGRADABLE_MDL | - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))); + /* + MYSQL_OPEN_FORCE_SHARED_MDL flag means that we are executing + PREPARE for a prepared statement and want to override + the type-of-operation aware metadata lock which was set + in the parser/during view opening with a simple shared + metadata lock. + This is necessary to allow concurrent execution of PREPARE + and LOCK TABLES WRITE statement against the same table. + + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL flag means that we open + the table in order to get information about it for one of I_S + queries and also want to override the type-of-operation aware + shared metadata lock which was set earlier (e.g. during view + opening) with a high-priority shared metadata lock. + This is necessary to avoid unnecessary waiting and extra + ER_WARN_I_S_SKIPPED_TABLE warnings when accessing I_S tables. + + These two flags are mutually exclusive. + */ + DBUG_ASSERT(!(flags & MYSQL_OPEN_FORCE_SHARED_MDL) || + !(flags & MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)); - mdl_request->set_type(MDL_SHARED); - } - else if (flags & MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) - { - DBUG_ASSERT(!(flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL)); - mdl_request->set_type(MDL_SHARED_HIGH_PRIO); - } + mdl_request= new (thd->mem_root) MDL_request(mdl_request); + if (mdl_request == NULL) + return TRUE; - ot_ctx->add_request(mdl_request); + mdl_request->set_type((flags & MYSQL_OPEN_FORCE_SHARED_MDL) ? + MDL_SHARED : MDL_SHARED_HIGH_PRIO); + } - if (thd->mdl_context.try_acquire_lock(mdl_request)) - return 1; + ot_ctx->add_request(mdl_request); + if (flags & MYSQL_OPEN_FAIL_ON_MDL_CONFLICT) + { + /* + When table is being open in order to get data for I_S table, + we might have some tables not only open but also locked (e.g. when + this happens under LOCK TABLES or in a stored function). + As a result by waiting on a conflicting metadata lock to go away + we may create a deadlock which won't entirely belong to the + MDL subsystem and thus won't be detectable by this subsystem's + deadlock detector. + To avoid such situation we skip the trouble-making table if + there is a conflicting lock. + */ + if (thd->mdl_context.try_acquire_lock(mdl_request)) + return TRUE; if (mdl_request->ticket == NULL) { - if (flags & MYSQL_OPEN_FAIL_ON_MDL_CONFLICT) - my_error(ER_WARN_I_S_SKIPPED_TABLE, MYF(0), table_list->db, table_list->table_name); - else - ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_MDL_LOCK); - return 1; + my_error(ER_WARN_I_S_SKIPPED_TABLE, MYF(0), + mdl_request->key.db_name(), mdl_request->key.name()); + return TRUE; } } - return 0; + else + { + /* + We are doing a normal table open. Let us try to acquire a metadata + lock on the table. If there is a conflicting lock, acquire_lock() + will wait for it to go away. Sometimes this waiting may lead to a + deadlock, with the following results: + 1) If a deadlock is entirely within MDL subsystem, it is + detected by the deadlock detector of this subsystem. + ER_LOCK_DEADLOCK error is produced. Then, the error handler + that is installed prior to the call to acquire_lock() attempts + to request a back-off and retry. Upon success, ER_LOCK_DEADLOCK + error is suppressed, otherwise propagated up the calling stack. + 2) Otherwise, a deadlock may occur when the wait-for graph + includes edges not visible to the MDL deadlock detector. + One such example is a wait on an InnoDB row lock, e.g. when: + conn C1 gets SR MDL lock on t1 with SELECT * FROM t1 + conn C2 gets a row lock on t2 with SELECT * FROM t2 FOR UPDATE + conn C3 gets in and waits on C1 with DROP TABLE t0, t1 + conn C2 continues and blocks on C3 with SELECT * FROM t0 + conn C1 deadlocks by waiting on C2 by issuing SELECT * FROM + t2 LOCK IN SHARE MODE. + Such circular waits are currently only resolved by timeouts, + e.g. @@innodb_lock_wait_timeout or @@lock_wait_timeout. + */ + MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); + + thd->push_internal_handler(&mdl_deadlock_handler); + bool result= thd->mdl_context.acquire_lock(mdl_request, + ot_ctx->get_timeout()); + thd->pop_internal_handler(); + + if (result && !ot_ctx->can_recover_from_failed_open()) + return TRUE; + } + *mdl_ticket= mdl_request->ticket; + return FALSE; } @@ -2474,11 +2596,9 @@ open_table_get_mdl_lock(THD *thd, TABLE_LIST *table_list, is never opened. In both cases, metadata locks are always taken according to the lock strategy. - This function will take a exclusive metadata lock on the table if - TABLE_LIST::lock_strategy is EXCLUSIVE_DOWNGRADABLE_MDL or EXCLUSIVE_MDL. - If the lock strategy is EXCLUSIVE_DOWNGRADABLE_MDL and opening the table - is successful, the exclusive metadata lock is downgraded to a shared - lock. + If the lock strategy is OTLS_DOWNGRADE_IF_EXISTS and opening the table + is successful, the exclusive metadata lock acquired by the caller + is downgraded to a shared lock. RETURN TRUE Open failed. "action" parameter may contain type of action @@ -2490,13 +2610,13 @@ open_table_get_mdl_lock(THD *thd, TABLE_LIST *table_list, bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, - Open_table_context *ot_ctx, uint flags) + Open_table_context *ot_ctx) { reg1 TABLE *table; char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; - MDL_request *mdl_request; + uint flags= ot_ctx->get_flags(); MDL_ticket *mdl_ticket; int error; TABLE_SHARE *share; @@ -2532,9 +2652,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (thd->global_read_lock.wait_if_global_read_lock(thd, 1, 1)) DBUG_RETURN(TRUE); - if (thd->version != refresh_version) + if (thd->open_tables && thd->open_tables->s->version != refresh_version) { - (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC); + (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC, + NULL); DBUG_RETURN(TRUE); } } @@ -2678,7 +2799,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, during prelocking process (in this case in theory we still should hold shared metadata lock on it). */ - if (mysql_frm_type(thd, path, ¬_used) == FRMTYPE_VIEW) + if (dd_frm_type(thd, path, ¬_used) == FRMTYPE_VIEW) { if (!tdc_open_view(thd, table_list, alias, key, key_length, mem_root, 0)) @@ -2707,66 +2828,45 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, This is the normal use case. */ - mdl_request= &table_list->mdl_request; if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK)) { - if (open_table_get_mdl_lock(thd, table_list, mdl_request, ot_ctx, flags)) + if (open_table_get_mdl_lock(thd, ot_ctx, &table_list->mdl_request, + flags, &mdl_ticket) || + mdl_ticket == NULL) { DEBUG_SYNC(thd, "before_open_table_wait_refresh"); DBUG_RETURN(TRUE); } DEBUG_SYNC(thd, "after_open_table_mdl_shared"); } - - /* - Grab reference to the granted MDL lock ticket. Must be done after - open_table_get_mdl_lock as the lock on the table might have been - acquired previously (MYSQL_OPEN_HAS_MDL_LOCK). - */ - mdl_ticket= mdl_request->ticket; + else + { + /* + Grab reference to the MDL lock ticket that was acquired + by the caller. + */ + mdl_ticket= table_list->mdl_request.ticket; + } hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); - mysql_mutex_lock(&LOCK_open); - /* - If it's the first table from a list of tables used in a query, - remember refresh_version (the version of open_cache state). - If the version changes while we're opening the remaining tables, - we will have to back off, close all the tables opened-so-far, - and try to reopen them. - Note: refresh_version is currently changed only during FLUSH TABLES. - */ - if (!thd->open_tables) - thd->version=refresh_version; - else if ((thd->version != refresh_version) && - ! (flags & MYSQL_OPEN_IGNORE_FLUSH)) - { - /* Someone did a refresh while thread was opening tables */ - mysql_mutex_unlock(&LOCK_open); - (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC); - DBUG_RETURN(TRUE); - } if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS) { bool exists; if (check_if_table_exists(thd, table_list, &exists)) - goto err_unlock2; + DBUG_RETURN(TRUE); if (!exists) - { - mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(FALSE); - } + /* Table exists. Let us try to open it. */ } else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB) - { - mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(FALSE); - } + mysql_mutex_lock(&LOCK_open); #ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL if (!(share= (TABLE_SHARE *) mdl_ticket->get_cached_object())) #endif @@ -2788,7 +2888,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, my_error(ER_WRONG_MRG_TABLE, MYF(0)); goto err_unlock; } - + /* This table is a view. Validate its metadata version: in particular, that it was a view when the statement was prepared. @@ -2802,26 +2902,15 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (open_new_frm(thd, share, alias, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), - READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | - (flags & OPEN_VIEW_NO_PARSE), thd->open_options, + READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, + thd->open_options, 0, table_list, mem_root)) goto err_unlock; /* TODO: Don't free this */ release_table_share(share); - if (flags & OPEN_VIEW_NO_PARSE) - { - /* - VIEW not really opened, only frm were read. - Set 1 as a flag here - */ - table_list->view= (LEX*)1; - } - else - { - DBUG_ASSERT(table_list->view); - } + DBUG_ASSERT(table_list->view); mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(FALSE); @@ -2868,7 +2957,15 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } #endif - if (share->version != refresh_version) + + /* + If the version changes while we're opening the tables, + we have to back off, close all the tables opened-so-far, + and try to reopen them. Note: refresh_version is currently + changed only during FLUSH TABLES. + */ + if (share->needs_reopen() || + (thd->open_tables && thd->open_tables->s->version != share->version)) { if (!(flags & MYSQL_OPEN_IGNORE_FLUSH)) { @@ -2884,11 +2981,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ release_table_share(share); mysql_mutex_unlock(&LOCK_open); - (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC); + (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC, + NULL); DBUG_RETURN(TRUE); } - /* Force close at once after usage */ - thd->version= share->version; } if (!share->free_tables.is_empty()) @@ -2904,9 +3000,11 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, while (table_cache_count > table_cache_size && unused_tables) free_cache_entry(unused_tables); + mysql_mutex_unlock(&LOCK_open); + /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) - goto err_unlock; + goto err_lock; error= open_table_from_share(thd, share, alias, (uint) (HA_OPEN_KEYFILE | @@ -2922,26 +3020,23 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, my_free(table, MYF(0)); if (error == 7) - { - share->version= 0; - (void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER); - } + (void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER, + table_list); else if (share->crashed) - { - share->version= 0; - (void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR); - } + (void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR, + table_list); - goto err_unlock; + goto err_lock; } if (open_table_entry_fini(thd, share, table)) { closefrm(table, 0); my_free((uchar*)table, MYF(0)); - goto err_unlock; + goto err_lock; } + mysql_mutex_lock(&LOCK_open); /* Add table to the share's used tables list. */ table_def_add_used_table(thd, table); } @@ -2953,14 +3048,14 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table exists now we should downgrade our exclusive metadata lock on this table to SW metadata lock. */ - if (table_list->lock_strategy == TABLE_LIST::EXCLUSIVE_DOWNGRADABLE_MDL && + if (table_list->lock_strategy == TABLE_LIST::OTLS_DOWNGRADE_IF_EXISTS && !(flags & MYSQL_OPEN_HAS_MDL_LOCK)) mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_WRITE); table->mdl_ticket= mdl_ticket; - table->next=thd->open_tables; /* Link into simple list */ - thd->open_tables=table; + table->next= thd->open_tables; /* Link into simple list */ + thd->set_open_tables(table); table->reginfo.lock_type=TL_READ; /* Assume read */ @@ -3003,6 +3098,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->file->extra(HA_EXTRA_DETACH_CHILDREN); DBUG_RETURN(FALSE); +err_lock: + mysql_mutex_lock(&LOCK_open); err_unlock: release_table_share(share); err_unlock2: @@ -3300,7 +3397,6 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) */ if (reopen_count) { - mysql_mutex_lock(&LOCK_open); while (reopen_count--) { /* @@ -3317,7 +3413,6 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) close_thread_table(thd, &thd->open_tables); } broadcast_refresh(); - mysql_mutex_unlock(&LOCK_open); } /* Exclude all closed tables from the LOCK TABLES list. */ for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= @@ -3351,7 +3446,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) bool Locked_tables_list::reopen_tables(THD *thd) { - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); size_t reopen_count= 0; MYSQL_LOCK *lock; MYSQL_LOCK *merged_lock; @@ -3363,8 +3458,7 @@ Locked_tables_list::reopen_tables(THD *thd) continue; /* Links into thd->open_tables upon success */ - if (open_table(thd, table_list, thd->mem_root, &ot_ctx_unused, - MYSQL_OPEN_REOPEN)) + if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) { unlink_all_closed_tables(thd, 0, reopen_count); return TRUE; @@ -3719,7 +3813,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list) TABLE_SHARE *share; TABLE *entry; int not_used; - bool result= FALSE; + bool result= TRUE; my_hash_value_type hash_value; cache_key_length= create_table_def_key(thd, cache_key, table_list, 0); @@ -3734,20 +3828,19 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list) cache_key_length, OPEN_VIEW, ¬_used, hash_value))) - { - mysql_mutex_unlock(&LOCK_open); - return TRUE; - } + goto end_unlock; if (share->is_view) - goto end_with_lock_open; + { + release_table_share(share); + goto end_unlock; + } if (!(entry= (TABLE*)my_malloc(sizeof(TABLE), MYF(MY_WME)))) { - result= TRUE; - goto end_with_lock_open; + release_table_share(share); + goto end_unlock; } - share->version= 0; mysql_mutex_unlock(&LOCK_open); if (open_table_from_share(thd, share, table_list->alias, @@ -3766,19 +3859,21 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list) share->table_name.str); if (entry->file) closefrm(entry, 0); - result= TRUE; } else { thd->clear_error(); // Clear error message closefrm(entry, 0); + result= FALSE; } my_free(entry, MYF(0)); mysql_mutex_lock(&LOCK_open); - -end_with_lock_open: release_table_share(share); + /* Remove the repaired share from the table cache. */ + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, + table_list->db, table_list->table_name); +end_unlock: mysql_mutex_unlock(&LOCK_open); return result; } @@ -3786,14 +3881,17 @@ end_with_lock_open: /** Open_table_context */ -Open_table_context::Open_table_context(THD *thd, ulong timeout) - :m_action(OT_NO_ACTION), +Open_table_context::Open_table_context(THD *thd, uint flags) + :m_failed_table(NULL), m_start_of_statement_svp(thd->mdl_context.mdl_savepoint()), + m_global_mdl_request(NULL), + m_timeout(flags & MYSQL_LOCK_IGNORE_TIMEOUT ? + LONG_TIMEOUT : thd->variables.lock_wait_timeout), + m_flags(flags), + m_action(OT_NO_ACTION), m_has_locks((thd->in_multi_stmt_transaction_mode() && thd->mdl_context.has_locks()) || - thd->mdl_context.trans_sentinel()), - m_global_mdl_request(NULL), - m_timeout(timeout) + thd->mdl_context.trans_sentinel()) {} @@ -3807,10 +3905,8 @@ MDL_request *Open_table_context::get_global_mdl_request(THD *thd) { if (! m_global_mdl_request) { - char *buff; - if ((buff= (char*)thd->alloc(sizeof(MDL_request)))) + if ((m_global_mdl_request= new (thd->mem_root) MDL_request())) { - m_global_mdl_request= new (buff) MDL_request(); m_global_mdl_request->init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE); } @@ -3829,30 +3925,51 @@ MDL_request *Open_table_context::get_global_mdl_request(THD *thd) bool Open_table_context:: -request_backoff_action(enum_open_table_action action_arg) +request_backoff_action(enum_open_table_action action_arg, + TABLE_LIST *table) { /* - We are inside a transaction that already holds locks and have - met a broken table or a table which needs re-discovery. - Performing any recovery action requires acquiring an exclusive - metadata lock on this table. Doing that with locks breaks the - metadata locking protocol and might lead to deadlocks, - so we report an error. - - However, if we have only met a conflicting lock or an old - TABLE version, and just need to wait for the conflict to - disappear/old version to go away, allow waiting. - While waiting, we use a simple empiric to detect - deadlocks: we never wait on someone who's waiting too. - Waiting will be done after releasing metadata locks acquired - by this statement. + A back off action may be one of the three kinds: + + * We met a broken table that needs repair, or a table that + is not present on this MySQL server and needs re-discovery. + To perform the action, we need an exclusive metadata lock on + the table. Acquiring an X lock while holding other shared + locks is very deadlock-prone. If this is a multi- statement + transaction that holds metadata locks for completed + statements, we don't do it, and report an error instead. + * Our attempt to acquire an MDL lock lead to a deadlock, + detected by the MDL deadlock detector. The current + session was chosen a victim. If this is a multi-statement + transaction that holds metadata locks for completed statements, + restarting locking for the current statement may lead + to a livelock. Thus, again, if m_has_locks is set, + we report an error. Otherwise, when there are no metadata + locks other than which belong to this statement, we can + try to recover from error by releasing all locks and + restarting the pre-locking. + * Finally, we could have met a TABLE_SHARE with old version. + Again, if this is a first statement in a transaction we can + close all tables, release all metadata locks and wait for + the old version to go away. Otherwise, waiting with MDL locks + may lead to criss-cross wait between this connection and a + connection that has an open table and waits on a metadata lock, + i.e. to a deadlock. + Since there is no way to detect such a deadlock, we prevent + it by reporting an error. */ - if (m_has_locks && action_arg != OT_WAIT_MDL_LOCK) + if (m_has_locks) { my_error(ER_LOCK_DEADLOCK, MYF(0)); return TRUE; } m_action= action_arg; + /* + If auto-repair or discovery are requested, a pointer to table + list element must be provided. + */ + DBUG_ASSERT((m_action != OT_DISCOVER && m_action != OT_REPAIR) || table); + m_failed_table= table; return FALSE; } @@ -3861,10 +3978,6 @@ request_backoff_action(enum_open_table_action action_arg) Recover from failed attempt of open table by performing requested action. @param thd Thread context - @param mdl_request MDL_request of the object that caused the problem. - @param table Optional (can be NULL). Used only if action is OT_REPAIR. - In that case a TABLE_LIST for the table to be repaired. - @todo: It's unnecessary and should be removed. @pre This function should be called only with "action" != OT_NO_ACTION and after having called @sa close_tables_for_reopen(). @@ -3875,8 +3988,7 @@ request_backoff_action(enum_open_table_action action_arg) bool Open_table_context:: -recover_from_failed_open(THD *thd, MDL_request *mdl_request, - TABLE_LIST *table) +recover_from_failed_open(THD *thd) { bool result= FALSE; /* @@ -3887,8 +3999,7 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, /* Execute the action. */ switch (m_action) { - case OT_WAIT_MDL_LOCK: - result= thd->mdl_context.wait_for_lock(mdl_request, get_timeout()); + case OT_MDL_CONFLICT: break; case OT_WAIT_TDC: result= tdc_wait_for_old_versions(thd, &m_mdl_requests, get_timeout()); @@ -3897,7 +4008,7 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, case OT_DISCOVER: { MDL_request mdl_global_request; - MDL_request mdl_xlock_request(mdl_request); + MDL_request mdl_xlock_request(&m_failed_table->mdl_request); MDL_request_list mdl_requests; mdl_global_request.init(MDL_key::GLOBAL, "", "", @@ -3911,14 +4022,11 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, thd->mdl_context.acquire_locks(&mdl_requests, get_timeout()))) break; - DBUG_ASSERT(mdl_request->key.mdl_namespace() == MDL_key::TABLE); mysql_mutex_lock(&LOCK_open); - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, - mdl_request->key.db_name(), - mdl_request->key.name()); - ha_create_table_from_engine(thd, - mdl_request->key.db_name(), - mdl_request->key.name()); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, m_failed_table->db, + m_failed_table->table_name); + ha_create_table_from_engine(thd, m_failed_table->db, + m_failed_table->table_name); mysql_mutex_unlock(&LOCK_open); thd->warning_info->clear_warning_info(thd->query_id); @@ -3929,7 +4037,7 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, case OT_REPAIR: { MDL_request mdl_global_request; - MDL_request mdl_xlock_request(mdl_request); + MDL_request mdl_xlock_request(&m_failed_table->mdl_request); MDL_request_list mdl_requests; mdl_global_request.init(MDL_key::GLOBAL, "", "", @@ -3943,14 +4051,12 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, thd->mdl_context.acquire_locks(&mdl_requests, get_timeout()))) break; - DBUG_ASSERT(mdl_request->key.mdl_namespace() == MDL_key::TABLE); mysql_mutex_lock(&LOCK_open); - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, - mdl_request->key.db_name(), - mdl_request->key.name()); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, m_failed_table->db, + m_failed_table->table_name); mysql_mutex_unlock(&LOCK_open); - result= auto_repair_table(thd, table); + result= auto_repair_table(thd, m_failed_table); thd->mdl_context.release_transactional_locks(); break; } @@ -3959,6 +4065,12 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, } /* Remove all old requests, they will be re-added. */ m_mdl_requests.empty(); + /* + Reset the pointers to conflicting MDL request and the + TABLE_LIST element, set when we need auto-discovery or repair, + for safety. + */ + m_failed_table= NULL; /* Prepare for possible another back-off. */ m_action= OT_NO_ACTION; return result; @@ -4081,15 +4193,25 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, */ DBUG_ASSERT(rt->mdl_request.type == MDL_SHARED); - if (thd->mdl_context.try_acquire_lock(&rt->mdl_request)) - DBUG_RETURN(TRUE); + /* + Waiting for a conflicting metadata lock to go away may + lead to a deadlock, detected by MDL subsystem. + If possible, we try to resolve such deadlocks by releasing all + metadata locks and restarting the pre-locking process. + To prevent the error from polluting the diagnostics area + in case of successful resolution, install a special error + handler for ER_LOCK_DEADLOCK error. + */ + MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); - if (rt->mdl_request.ticket == NULL) - { - /* A lock conflict. Someone's trying to modify SP metadata. */ - ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_MDL_LOCK); + thd->push_internal_handler(&mdl_deadlock_handler); + bool result= thd->mdl_context.acquire_lock(&rt->mdl_request, + ot_ctx->get_timeout()); + thd->pop_internal_handler(); + + if (result) DBUG_RETURN(TRUE); - } + DEBUG_SYNC(thd, "after_shared_lock_pname"); /* Ensures the routine is up-to-date and cached, if exists. */ @@ -4234,12 +4356,14 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, */ if (tables->view) { + MDL_ticket *mdl_ticket; /* We still need to take a MDL lock on the merged view to protect it from concurrent changes. */ - if (!open_table_get_mdl_lock(thd, tables, &tables->mdl_request, - ot_ctx, flags)) + if (!open_table_get_mdl_lock(thd, ot_ctx, &tables->mdl_request, + flags, &mdl_ticket) && + mdl_ticket != NULL) goto process_view_routines; /* Fall-through to return error. */ } @@ -4268,12 +4392,12 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, */ Prelock_error_handler prelock_handler; thd->push_internal_handler(& prelock_handler); - error= open_table(thd, tables, new_frm_mem, ot_ctx, flags); + error= open_table(thd, tables, new_frm_mem, ot_ctx); thd->pop_internal_handler(); safe_to_ignore_table= prelock_handler.safely_trapped_errors(); } else - error= open_table(thd, tables, new_frm_mem, ot_ctx, flags); + error= open_table(thd, tables, new_frm_mem, ot_ctx); free_root(new_frm_mem, MYF(MY_KEEP_PREALLOC)); @@ -4429,6 +4553,8 @@ end: should be acquired. @param tables_end End of list of tables. @param ot_ctx Context of open_tables() operation. + @param flags Bitmap of flags to modify how the tables will be + open, see open_table() description for details. @retval FALSE Success. @retval TRUE Failure (e.g. connection was killed) @@ -4437,31 +4563,30 @@ end: static bool open_tables_acquire_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, TABLE_LIST *tables_end, - Open_table_context *ot_ctx) + Open_table_context *ot_ctx, + uint flags) { MDL_request_list mdl_requests; TABLE_LIST *table; DBUG_ASSERT(!thd->locked_tables_mode); - DEBUG_SYNC(thd, "open_tables_acquire_upgradable_mdl"); for (table= tables_start; table && table != tables_end; table= table->next_global) { - if (table->lock_type >= TL_WRITE_ALLOW_WRITE && + if (table->mdl_request.type >= MDL_SHARED_NO_WRITE && !(table->open_type == OT_TEMPORARY_ONLY || + (flags & MYSQL_OPEN_TEMPORARY_ONLY) || (table->open_type != OT_BASE_ONLY && + ! (flags & MYSQL_OPEN_SKIP_TEMPORARY) && find_temporary_table(thd, table)))) - { - table->mdl_request.set_type(table->lock_type > TL_WRITE_ALLOW_READ ? - MDL_SHARED_NO_READ_WRITE : - MDL_SHARED_NO_WRITE); mdl_requests.push_front(&table->mdl_request); - } } if (! mdl_requests.is_empty()) { + DEBUG_SYNC(thd, "open_tables_acquire_upgradable_mdl"); + MDL_request *global_request= ot_ctx->get_global_mdl_request(thd); if (global_request == NULL) @@ -4475,11 +4600,8 @@ open_tables_acquire_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, for (table= tables_start; table && table != tables_end; table= table->next_global) { - if (table->lock_type >= TL_WRITE_ALLOW_WRITE) - { + if (table->mdl_request.type >= MDL_SHARED_NO_WRITE) table->mdl_request.ticket= NULL; - table->mdl_request.set_type(MDL_SHARED_WRITE); - } } return FALSE; @@ -4495,6 +4617,8 @@ open_tables_acquire_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, @param tables_start Start of list of tables on which upgradable locks should be searched for. @param tables_end End of list of tables. + @param flags Bitmap of flags to modify how the tables will be + open, see open_table() description for details. @retval FALSE Success. @retval TRUE Failure (e.g. connection was killed) @@ -4502,7 +4626,7 @@ open_tables_acquire_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, static bool open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, - TABLE_LIST *tables_end) + TABLE_LIST *tables_end, uint flags) { TABLE_LIST *table; @@ -4511,9 +4635,11 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, for (table= tables_start; table && table != tables_end; table= table->next_global) { - if (table->lock_type >= TL_WRITE_ALLOW_WRITE && + if (table->mdl_request.type >= MDL_SHARED_NO_WRITE && !(table->open_type == OT_TEMPORARY_ONLY || + (flags & MYSQL_OPEN_TEMPORARY_ONLY) || (table->open_type != OT_BASE_ONLY && + ! (flags & MYSQL_OPEN_SKIP_TEMPORARY) && find_temporary_table(thd, table)))) { /* @@ -4525,8 +4651,14 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start, lock, all other instances of TABLE for the same table will have the same ticket. - Note that find_table_for_mdl_upgrade() will report an error if a - ticket is not found. + Note that this works OK even for CREATE TABLE statements which + request X type of metadata lock. This is because under LOCK TABLES + such statements don't create the table but only check if it exists + or, in most complex case, only insert into it. + Thus SNRW lock should be enough. + + Note that find_table_for_mdl_upgrade() will report an error if + no suitable ticket is found. */ if (!find_table_for_mdl_upgrade(thd->open_tables, table->db, table->table_name, FALSE)) @@ -4580,26 +4712,13 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, TABLE_LIST **table_to_open; Sroutine_hash_entry **sroutine_to_open; TABLE_LIST *tables; - Open_table_context ot_ctx(thd, (flags & MYSQL_LOCK_IGNORE_TIMEOUT) ? - LONG_TIMEOUT : thd->variables.lock_wait_timeout); + Open_table_context ot_ctx(thd, flags); bool error= FALSE; MEM_ROOT new_frm_mem; bool has_prelocking_list; DBUG_ENTER("open_tables"); /* - Close HANDLER tables which are marked for flush or against which there - are pending exclusive metadata locks. Note that we do this not to avoid - deadlocks (calls to mysql_ha_flush() in mdl_wait_for_locks() and - tdc_wait_for_old_version() are enough for this) but in order to have - a point during statement execution at which such HANDLERs are closed - even if they don't create problems for current thread (i.e. to avoid - having DDL blocked by HANDLERs opened for long time). - */ - if (thd->handler_tables_hash.records) - mysql_ha_flush(thd); - - /* temporary mem_root for new .frm parsing. TODO: variables for size */ @@ -4607,6 +4726,17 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, thd->current_tablenr= 0; restart: + /* + Close HANDLER tables which are marked for flush or against which there + are pending exclusive metadata locks. This is needed both in order to + avoid deadlocks and to have a point during statement execution at + which such HANDLERs are closed even if they don't create problems for + the current session (i.e. to avoid having a DDL blocked by HANDLERs + opened for a long time). + */ + if (thd->handler_tables_hash.records) + mysql_ha_flush(thd); + has_prelocking_list= thd->lex->requires_prelocking(); table_to_open= start; sroutine_to_open= (Sroutine_hash_entry**) &thd->lex->sroutines_list.first; @@ -4618,21 +4748,19 @@ restart: (in non-LOCK TABLES mode) we might have to acquire upgradable semi-exclusive metadata locks (SNW or SNRW) on some of the tables to be opened. - So we acquire all such locks at once here as doing this in one + When executing CREATE TABLE .. If NOT EXISTS .. SELECT, the + table may not yet exist, in which case we acquire an exclusive + lock. + We acquire all such locks at once here as doing this in one by one fashion may lead to deadlocks or starvation. Later when we will be opening corresponding table pre-acquired metadata lock will be reused (thanks to the fact that in recursive case metadata locks are acquired without waiting). */ - if (flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) + if (! (flags & (MYSQL_OPEN_HAS_MDL_LOCK | + MYSQL_OPEN_FORCE_SHARED_MDL | + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))) { - /* - open_tables_acquire_upgradable_mdl() does not currenly handle - these two flags. At this point, that does not matter as they - are not used together with MYSQL_OPEN_TAKE_UPGRADABLE_MDL. - */ - DBUG_ASSERT(!(flags & (MYSQL_OPEN_SKIP_TEMPORARY | - MYSQL_OPEN_TEMPORARY_ONLY))); if (thd->locked_tables_mode) { /* @@ -4640,7 +4768,8 @@ restart: need to check if appropriate locks were pre-acquired. */ if (open_tables_check_upgradable_mdl(thd, *start, - thd->lex->first_not_own_table())) + thd->lex->first_not_own_table(), + flags)) { error= TRUE; goto err; @@ -4648,7 +4777,7 @@ restart: } else if (open_tables_acquire_upgradable_mdl(thd, *start, thd->lex->first_not_own_table(), - &ot_ctx)) + &ot_ctx, flags)) { error= TRUE; goto err; @@ -4694,7 +4823,6 @@ restart: have failed to open since closing tables can trigger removal of elements from the table list (if MERGE tables are involved), */ - TABLE_LIST *failed_table= *table_to_open; close_tables_for_reopen(thd, start, ot_ctx.start_of_statement_svp()); /* @@ -4702,8 +4830,7 @@ restart: TABLE_LIST element. Altough currently this assumption is valid it may change in future. */ - if (ot_ctx.recover_from_failed_open(thd, &failed_table->mdl_request, - failed_table)) + if (ot_ctx.recover_from_failed_open(thd)) goto err; error= FALSE; @@ -4747,7 +4874,7 @@ restart: { close_tables_for_reopen(thd, start, ot_ctx.start_of_statement_svp()); - if (ot_ctx.recover_from_failed_open(thd, &rt->mdl_request, NULL)) + if (ot_ctx.recover_from_failed_open(thd)) goto err; error= FALSE; @@ -5054,8 +5181,8 @@ static bool check_lock_and_start_stmt(THD *thd, else lock_type= table_list->lock_type; - if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && - (int) table_list->table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) + if ((int) lock_type > (int) TL_WRITE_ALLOW_WRITE && + (int) table_list->table->reginfo.lock_type <= (int) TL_WRITE_ALLOW_WRITE) { my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias); DBUG_RETURN(1); @@ -5156,8 +5283,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, uint lock_flags) { TABLE *table; - Open_table_context ot_ctx(thd, (lock_flags & MYSQL_LOCK_IGNORE_TIMEOUT) ? - LONG_TIMEOUT : thd->variables.lock_wait_timeout); + Open_table_context ot_ctx(thd, lock_flags); bool error; DBUG_ENTER("open_ltable"); @@ -5169,7 +5295,10 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, /* open_ltable can be used only for BASIC TABLEs */ table_list->required_type= FRMTYPE_TABLE; - while ((error= open_table(thd, table_list, thd->mem_root, &ot_ctx, lock_flags)) && + /* This function can't properly handle requests for such metadata locks. */ + DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_NO_WRITE); + + while ((error= open_table(thd, table_list, thd->mem_root, &ot_ctx)) && ot_ctx.can_recover_from_failed_open()) { /* @@ -5179,8 +5308,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, */ thd->mdl_context.rollback_to_savepoint(ot_ctx.start_of_statement_svp()); table_list->mdl_request.ticket= 0; - if (ot_ctx.recover_from_failed_open(thd, &table_list->mdl_request, - table_list)) + if (ot_ctx.recover_from_failed_open(thd)) break; } @@ -5554,15 +5682,6 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, /* We have to cleanup translation tables of views. */ tmp->cleanup_items(); } - /* - Metadata lock requests for tables from extended part of prelocking set - are part of list of requests to be waited for in Open_table_context. - So to satisfy assumptions in MDL_context::wait_for_locks(), which will - performs the waiting, we have to reset MDL_request::ticket values for - them as well. - */ - for (tmp= first_not_own_table; tmp; tmp= tmp->next_global) - tmp->mdl_request.ticket= NULL; close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(start_of_statement_svp); } @@ -8425,15 +8544,15 @@ my_bool mysql_rm_tmp_tables(void) (file->name[1] == '.' && !file->name[2]))) continue; - if (!bcmp((uchar*) file->name, (uchar*) tmp_file_prefix, - tmp_file_prefix_length)) + if (!memcmp(file->name, tmp_file_prefix, + tmp_file_prefix_length)) { char *ext= fn_ext(file->name); uint ext_len= strlen(ext); uint filePath_len= my_snprintf(filePath, sizeof(filePath), "%s%c%s", tmpdir, FN_LIBCHAR, file->name); - if (!bcmp((uchar*) reg_ext, (uchar*) ext, ext_len)) + if (!memcmp(reg_ext, ext, ext_len)) { handler *handler_file= 0; /* We should cut file extention before deleting of table */ @@ -8478,7 +8597,7 @@ my_bool mysql_rm_tmp_tables(void) all not used tables. */ -void flush_tables() +void tdc_flush_unused_tables() { mysql_mutex_lock(&LOCK_open); while (unused_tables) @@ -8529,10 +8648,10 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, mysql_mutex_unlock(&in_use->mysys_var->mutex); signalled= TRUE; } - mysql_mutex_lock(&LOCK_open); if (needs_thr_lock_abort) { + mysql_mutex_lock(&in_use->LOCK_thd_data); for (TABLE *thd_table= in_use->open_tables; thd_table ; thd_table= thd_table->next) @@ -8543,10 +8662,11 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, and do not remove such instances from the THD::open_tables for some time, during which other thread can see those instances (e.g. see partitioning code). - */ + */ if (!thd_table->needs_reopen()) signalled|= mysql_lock_abort_for_thread(thd, thd_table); } + mysql_mutex_unlock(&in_use->LOCK_thd_data); } /* Wake up threads waiting in tdc_wait_for_old_versions(). @@ -8559,7 +8679,6 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, a multi-statement transaction. */ broadcast_refresh(); - mysql_mutex_unlock(&LOCK_open); return signalled; } @@ -8668,8 +8787,12 @@ tdc_wait_for_old_versions(THD *thd, MDL_request_list *mdl_requests, while (!thd->killed) { /* - Here we have situation as in mdl_wait_for_locks() we need to - get rid of offending HANDLERs to avoid deadlock. + We have to get rid of HANDLERs which are open by this thread + and have old TABLE versions. Otherwise we might get a deadlock + in situation when we are waiting for an old TABLE object which + corresponds to a HANDLER open by another session. And this + other session waits for our HANDLER object to get closed. + TODO: We should also investigate in which situations we have to broadcast on COND_refresh because of this. */ @@ -8686,7 +8809,7 @@ tdc_wait_for_old_versions(THD *thd, MDL_request_list *mdl_requests, if ((share= get_cached_table_share(mdl_request->key.db_name(), mdl_request->key.name())) && - share->version != refresh_version) + share->needs_reopen()) break; } if (!mdl_request) diff --git a/sql/sql_base.h b/sql/sql_base.h index 0fe70e4bc9d..20a068e27d7 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -89,7 +89,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, uint lock_flags); bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, - Open_table_context *ot_ctx, uint flags); + Open_table_context *ot_ctx); bool name_lock_locked_table(THD *thd, TABLE_LIST *tables); bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in); TABLE *table_cache_insert_placeholder(THD *thd, const char *key, @@ -233,7 +233,6 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db, const char *table_name); void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table); void remove_db_from_cache(const char *db); -void flush_tables(); bool is_equal(const LEX_STRING *a, const LEX_STRING *b); /* Functions to work with system tables. */ @@ -263,10 +262,12 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias, char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags); +void tdc_flush_unused_tables(); TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db, const char *table_name, bool no_error); void mark_tmp_table_for_reuse(TABLE *table); +bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); extern uint table_cache_count; extern TABLE *unused_tables; @@ -322,6 +323,7 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table, db_name, table_name); } + inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, List<Item> &item, enum_mark_columns mark_used_columns, @@ -336,6 +338,89 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, return res; } +/** + An abstract class for a strategy specifying how the prelocking + algorithm should extend the prelocking set while processing + already existing elements in the set. +*/ + +class Prelocking_strategy +{ +public: + virtual ~Prelocking_strategy() { } + + virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, + Sroutine_hash_entry *rt, sp_head *sp, + bool *need_prelocking) = 0; + virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking) = 0; + virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking)= 0; +}; + + +/** + A Strategy for prelocking algorithm suitable for DML statements. + + Ensures that all tables used by all statement's SF/SP/triggers and + required for foreign key checks are prelocked and SF/SPs used are + cached. +*/ + +class DML_prelocking_strategy : public Prelocking_strategy +{ +public: + virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, + Sroutine_hash_entry *rt, sp_head *sp, + bool *need_prelocking); + virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking); + virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking); +}; + + +/** + A strategy for prelocking algorithm to be used for LOCK TABLES + statement. +*/ + +class Lock_tables_prelocking_strategy : public DML_prelocking_strategy +{ + virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking); +}; + + +/** + Strategy for prelocking algorithm to be used for ALTER TABLE statements. + + Unlike DML or LOCK TABLES strategy, it doesn't + prelock triggers, views or stored routines, since they are not + used during ALTER. +*/ + +class Alter_table_prelocking_strategy : public Prelocking_strategy +{ +public: + + Alter_table_prelocking_strategy(Alter_info *alter_info) + : m_alter_info(alter_info) + {} + + virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, + Sroutine_hash_entry *rt, sp_head *sp, + bool *need_prelocking); + virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking); + virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list, bool *need_prelocking); + +private: + Alter_info *m_alter_info; +}; + + inline bool open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags) { @@ -355,4 +440,85 @@ inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, &prelocking_strategy); } + +/** + A context of open_tables() function, used to recover + from a failed open_table() or open_routine() attempt. +*/ + +class Open_table_context +{ +public: + enum enum_open_table_action + { + OT_NO_ACTION= 0, + OT_MDL_CONFLICT, + OT_WAIT_TDC, + OT_DISCOVER, + OT_REPAIR + }; + Open_table_context(THD *thd, uint flags); + + bool recover_from_failed_open(THD *thd); + bool request_backoff_action(enum_open_table_action action_arg, + TABLE_LIST *table); + + void add_request(MDL_request *request) + { m_mdl_requests.push_front(request); } + + bool can_recover_from_failed_open() const + { return m_action != OT_NO_ACTION; } + + /** + When doing a back-off, we close all tables acquired by this + statement. Return an MDL savepoint taken at the beginning of + the statement, so that we can rollback to it before waiting on + locks. + */ + MDL_ticket *start_of_statement_svp() const + { + return m_start_of_statement_svp; + } + + MDL_request *get_global_mdl_request(THD *thd); + + inline ulong get_timeout() const + { + return m_timeout; + } + + uint get_flags() const { return m_flags; } +private: + /** List of requests for all locks taken so far. Used for waiting on locks. */ + MDL_request_list m_mdl_requests; + /** + For OT_DISCOVER and OT_REPAIR actions, the table list element for + the table which definition should be re-discovered or which + should be repaired. + */ + TABLE_LIST *m_failed_table; + MDL_ticket *m_start_of_statement_svp; + /** + Request object for global intention exclusive lock which is acquired during + opening tables for statements which take upgradable shared metadata locks. + */ + MDL_request *m_global_mdl_request; + /** + Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system + tables or to the "lock_wait_timeout" system variable for regular tables. + */ + ulong m_timeout; + /* open_table() flags. */ + uint m_flags; + /** Back off action. */ + enum enum_open_table_action m_action; + /** + Whether we had any locks when this context was created. + If we did, they are from the previous statement of a transaction, + and we can't safely do back-off (and release them). + */ + bool m_has_locks; +}; + + #endif /* SQL_BASE_INCLUDED */ diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index 80a4712dd69..8d00c984d14 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -22,6 +22,7 @@ #ifndef SQL_BITMAP_INCLUDED #define SQL_BITMAP_INCLUDED +#include <my_sys.h> #include <my_bitmap.h> template <uint default_width> class Bitmap diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8c147421363..f41007aedfb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -353,7 +353,7 @@ int thd_sql_command(const THD *thd) extern "C" int thd_tx_isolation(const THD *thd) { - return (int) thd->variables.tx_isolation; + return (int) thd->tx_isolation; } extern "C" @@ -592,7 +592,7 @@ THD::THD() *scramble= '\0'; /* Call to init() below requires fully initialized Open_tables_state. */ - init_open_tables_state(this, refresh_version); + reset_open_tables_state(this); init(); #if defined(ENABLED_PROFILING) @@ -626,6 +626,9 @@ THD::THD() thr_lock_owner_init(&main_lock_id, &lock_info); m_internal_handler= NULL; + current_user_used= FALSE; + memset(&invoker_user, 0, sizeof(invoker_user)); + memset(&invoker_host, 0, sizeof(invoker_host)); } @@ -960,7 +963,7 @@ void THD::init(void) update_lock_default= (variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE); - session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; + tx_isolation= (enum_tx_isolation) variables.tx_isolation; update_charset(); reset_current_stmt_binlog_format_row(); bzero((char *) &status_var, sizeof(status_var)); @@ -1341,6 +1344,7 @@ void THD::cleanup_after_query() where= THD::DEFAULT_WHERE; /* reset table map for multi-table update */ table_map_for_update= 0; + clean_current_user_used(); } @@ -3401,6 +3405,22 @@ void THD::leave_locked_tables_mode() mysql_ha_move_tickets_after_trans_sentinel(this); } +void THD::get_definer(LEX_USER *definer) +{ + set_current_user_used(); +#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) + if (slave_thread && has_invoker()) + { + definer->user = invoker_user; + definer->host= invoker_host; + definer->password.str= NULL; + definer->password.length= 0; + } + else +#endif + get_default_definer(this, definer); +} + /** Mark transaction to rollback and mark error as fatal to a sub-statement. diff --git a/sql/sql_class.h b/sql/sql_class.h index 25b136bc4ca..269c2418ec8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -472,6 +472,7 @@ typedef struct system_variables my_bool sysdate_is_now; double long_query_time_double; + } SV; @@ -1006,7 +1007,6 @@ public: of the main statement is called. */ enum enum_locked_tables_mode locked_tables_mode; - ulong version; uint current_tablenr; enum enum_flags { @@ -1025,15 +1025,6 @@ public: */ Open_tables_state() : state_flags(0U) { } - /** - Prepare Open_tables_state instance for operations dealing with tables. - */ - void init_open_tables_state(THD *thd, ulong version_arg) - { - reset_open_tables_state(thd); - version= version_arg; - } - void set_open_tables_state(Open_tables_state *state) { *this= *state; @@ -1229,162 +1220,6 @@ private: /** - An abstract class for a strategy specifying how the prelocking - algorithm should extend the prelocking set while processing - already existing elements in the set. -*/ - -class Prelocking_strategy -{ -public: - virtual ~Prelocking_strategy() { } - - virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, - Sroutine_hash_entry *rt, sp_head *sp, - bool *need_prelocking) = 0; - virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking) = 0; - virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking)= 0; -}; - - -/** - A Strategy for prelocking algorithm suitable for DML statements. - - Ensures that all tables used by all statement's SF/SP/triggers and - required for foreign key checks are prelocked and SF/SPs used are - cached. -*/ - -class DML_prelocking_strategy : public Prelocking_strategy -{ -public: - virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, - Sroutine_hash_entry *rt, sp_head *sp, - bool *need_prelocking); - virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking); - virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking); -}; - - -/** - A strategy for prelocking algorithm to be used for LOCK TABLES - statement. -*/ - -class Lock_tables_prelocking_strategy : public DML_prelocking_strategy -{ - virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking); -}; - - -/** - Strategy for prelocking algorithm to be used for ALTER TABLE statements. - - Unlike DML or LOCK TABLES strategy, it doesn't - prelock triggers, views or stored routines, since they are not - used during ALTER. -*/ - -class Alter_table_prelocking_strategy : public Prelocking_strategy -{ -public: - - Alter_table_prelocking_strategy(Alter_info *alter_info) - : m_alter_info(alter_info) - {} - - virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx, - Sroutine_hash_entry *rt, sp_head *sp, - bool *need_prelocking); - virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking); - virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *table_list, bool *need_prelocking); - -private: - Alter_info *m_alter_info; -}; - - -/** - A context of open_tables() function, used to recover - from a failed open_table() or open_routine() attempt. - - Implemented in sql_base.cc. -*/ - -class Open_table_context -{ -public: - enum enum_open_table_action - { - OT_NO_ACTION= 0, - OT_WAIT_MDL_LOCK, - OT_WAIT_TDC, - OT_DISCOVER, - OT_REPAIR - }; - Open_table_context(THD *thd, ulong timeout); - - bool recover_from_failed_open(THD *thd, MDL_request *mdl_request, - TABLE_LIST *table); - bool request_backoff_action(enum_open_table_action action_arg); - - void add_request(MDL_request *request) - { m_mdl_requests.push_front(request); } - - bool can_recover_from_failed_open() const - { return m_action != OT_NO_ACTION; } - - /** - When doing a back-off, we close all tables acquired by this - statement. Return an MDL savepoint taken at the beginning of - the statement, so that we can rollback to it before waiting on - locks. - */ - MDL_ticket *start_of_statement_svp() const - { - return m_start_of_statement_svp; - } - - MDL_request *get_global_mdl_request(THD *thd); - - inline ulong get_timeout() const - { - return m_timeout; - } - -private: - /** List of requests for all locks taken so far. Used for waiting on locks. */ - MDL_request_list m_mdl_requests; - /** Back off action. */ - enum enum_open_table_action m_action; - MDL_ticket *m_start_of_statement_svp; - /** - Whether we had any locks when this context was created. - If we did, they are from the previous statement of a transaction, - and we can't safely do back-off (and release them). - */ - bool m_has_locks; - /** - Request object for global intention exclusive lock which is acquired during - opening tables for statements which take upgradable shared metadata locks. - */ - MDL_request *m_global_mdl_request; - /** - Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system - tables or to the "lock_wait_timeout" system variable for regular tables. - */ - uint m_timeout; -}; - - -/** Tables that were locked with LOCK TABLES statement. Encapsulates a list of TABLE_LIST instances for tables @@ -2097,8 +1932,31 @@ public: uint server_status,open_options; enum enum_thread_type system_thread; uint select_number; //number of select (used for EXPLAIN) - /* variables.transaction_isolation is reset to this after each commit */ - enum_tx_isolation session_tx_isolation; + /* + Current or next transaction isolation level. + When a connection is established, the value is taken from + @@session.tx_isolation (default transaction isolation for + the session), which is in turn taken from @@global.tx_isolation + (the global value). + If there is no transaction started, this variable + holds the value of the next transaction's isolation level. + When a transaction starts, the value stored in this variable + becomes "actual". + At transaction commit or rollback, we assign this variable + again from @@session.tx_isolation. + The only statement that can otherwise change the value + of this variable is SET TRANSACTION ISOLATION LEVEL. + Its purpose is to effect the isolation level of the next + transaction in this session. When this statement is executed, + the value in this variable is changed. However, since + this statement is only allowed when there is no active + transaction, this assignment (naturally) only affects the + upcoming transaction. + At the end of the current active transaction the value is + be reset again from @@session.tx_isolation, as described + above. + */ + enum_tx_isolation tx_isolation; enum_check_fields count_cuted_fields; DYNAMIC_ARRAY user_var_events; /* For user variables replication */ @@ -2843,6 +2701,12 @@ public: void set_query_and_id(char *query_arg, uint32 query_length_arg, query_id_t new_query_id); void set_query_id(query_id_t new_query_id); + void set_open_tables(TABLE *open_tables_arg) + { + mysql_mutex_lock(&LOCK_thd_data); + open_tables= open_tables_arg; + mysql_mutex_unlock(&LOCK_thd_data); + } void enter_locked_tables_mode(enum_locked_tables_mode mode_arg) { DBUG_ASSERT(locked_tables_mode == LTM_NONE); @@ -2852,6 +2716,18 @@ public: } void leave_locked_tables_mode(); int decide_logging_format(TABLE_LIST *tables); + void set_current_user_used() { current_user_used= TRUE; } + bool is_current_user_used() { return current_user_used; } + void clean_current_user_used() { current_user_used= FALSE; } + void get_definer(LEX_USER *definer); + void set_invoker(const LEX_STRING *user, const LEX_STRING *host) + { + invoker_user= *user; + invoker_host= *host; + } + LEX_STRING get_invoker_user() { return invoker_user; } + LEX_STRING get_invoker_host() { return invoker_host; } + bool has_invoker() { return invoker_user.length > 0; } private: /** The current internal error handler for this thread, or NULL. */ @@ -2874,6 +2750,25 @@ private: MEM_ROOT main_mem_root; Warning_info main_warning_info; Diagnostics_area main_da; + + /** + It will be set TURE if CURRENT_USER() is called in account management + statements or default definer is set in CREATE/ALTER SP, SF, Event, + TRIGGER or VIEW statements. + + Current user will be binlogged into Query_log_event if current_user_used + is TRUE; It will be stored into invoker_host and invoker_user by SQL thread. + */ + bool current_user_used; + + /** + It points to the invoker in the Query_log_event. + SQL thread use it as the default definer in CREATE/ALTER SP, SF, Event, + TRIGGER or VIEW statements or current user in account management + statements if it is not NULL. + */ + LEX_STRING invoker_user; + LEX_STRING invoker_host; }; @@ -3428,6 +3323,9 @@ public: void reset(); bool walk(tree_walk_action action, void *walk_action_arg); + uint get_size() const { return size; } + ulonglong get_max_in_memory_size() const { return max_in_memory_size; } + friend int unique_write_to_file(uchar* key, element_count count, Unique *unique); friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique); }; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7b0ef3eb226..35ba39afd81 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1085,7 +1085,6 @@ static void prepare_new_connection_state(THD* thd) embedded server library. TODO: refactor this to avoid code duplication there */ - thd->version= refresh_version; thd->proc_info= 0; thd->command= COM_SLEEP; thd->set_time(); diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 59bf0764ada..ca724ec262f 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -357,7 +357,7 @@ void Sensitive_cursor::reset_thd(THD *thd) { thd->derived_tables= 0; - thd->open_tables= 0; + thd->set_open_tables(NULL); thd->lock= 0; thd->free_list= 0; thd->change_list.empty(); @@ -436,7 +436,7 @@ Sensitive_cursor::fetch(ulong num_rows) thd->lock == 0); thd->derived_tables= derived_tables; - thd->open_tables= open_tables; + thd->set_open_tables(open_tables); thd->lock= lock; thd->set_query_id(query_id); change_list.move_elements_to(&thd->change_list); @@ -519,14 +519,14 @@ Sensitive_cursor::close() TABLE *tmp_derived_tables= thd->derived_tables; MYSQL_LOCK *tmp_lock= thd->lock; - thd->open_tables= open_tables; + thd->set_open_tables(open_tables); thd->derived_tables= derived_tables; thd->lock= lock; /* Is expected to at least close tables and empty thd->change_list */ stmt_arena->cleanup_stmt(); - thd->open_tables= tmp_derived_tables; + thd->set_open_tables(tmp_derived_tables); thd->derived_tables= tmp_derived_tables; thd->lock= tmp_lock; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 15fdd842e34..2e48475f298 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1203,6 +1203,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, table_list->alias= table_list->table_name; // If lower_case_table_names=2 table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix); + table_list->mdl_request.init(MDL_key::TABLE, table_list->db, + table_list->table_name, MDL_EXCLUSIVE); /* Link into list */ (*tot_list_next)= table_list; tot_list_next= &table_list->next_local; @@ -1918,9 +1920,11 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0); if (!old_ident || !new_ident || !sl->add_table_to_list(thd, old_ident, NULL, - TL_OPTION_UPDATING, TL_IGNORE) || + TL_OPTION_UPDATING, TL_IGNORE, + MDL_EXCLUSIVE) || !sl->add_table_to_list(thd, new_ident, NULL, - TL_OPTION_UPDATING, TL_IGNORE)) + TL_OPTION_UPDATING, TL_IGNORE, + MDL_EXCLUSIVE)) { error= 1; my_dirend(dirp); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d71d5c56980..c4a773fee9c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -14,7 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* - Delete of records and truncate of tables. + Delete of records tables. Multi-table deletes were introduced by Monty and Sinisa */ @@ -47,8 +47,7 @@ */ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_I_List<ORDER> *order, ha_rows limit, ulonglong options, - bool reset_auto_increment) + SQL_I_List<ORDER> *order, ha_rows limit, ulonglong options) { bool will_batch; int error, loc_error; @@ -59,17 +58,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, bool transactional_table, safe_update, const_cond; bool const_cond_result; ha_rows deleted= 0; - bool triggers_applicable; uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; THD::killed_state killed_status= THD::NOT_KILLED; + THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE; DBUG_ENTER("mysql_delete"); - bool save_binlog_row_based; - - THD::enum_binlog_query_type query_type= - thd->lex->sql_command == SQLCOM_TRUNCATE ? - THD::STMT_QUERY_TYPE : - THD::ROW_QUERY_TYPE; if (open_and_lock_tables(thd, table_list, TRUE, 0)) DBUG_RETURN(TRUE); @@ -129,25 +122,20 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, any side-effects (because of triggers), so we can use optimized handler::delete_all_rows() method. - We implement fast TRUNCATE for InnoDB even if triggers are - present. TRUNCATE ignores triggers. - We can use delete_all_rows() if and only if: - We allow new functions (not using option --skip-new), and are not in safe mode (not using option --safe-mode) - There is no limit clause - The condition is constant - If there is a condition, then it it produces a non-zero value - - If the current command is DELETE FROM with no where clause - (i.e., not TRUNCATE) then: - - We should not be binlogging this statement row-based, and + - If the current command is DELETE FROM with no where clause, then: + - We should not be binlogging this statement in row-based, and - there should be no delete triggers associated with the table. */ if (!using_limit && const_cond_result && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && - (thd->lex->sql_command == SQLCOM_TRUNCATE || (!thd->is_current_stmt_binlog_format_row() && - !(table->triggers && table->triggers->has_delete_triggers())))) + !(table->triggers && table->triggers->has_delete_triggers()))) { /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -160,16 +148,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, query in row format, so we have to log it in statement format. */ query_type= THD::STMT_QUERY_TYPE; - error= -1; // ok + error= -1; deleted= maybe_deleted; - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); goto cleanup; } if (error != HA_ERR_WRONG_COMMAND) { table->file->print_error(error,MYF(0)); error=0; - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); goto cleanup; } /* Handler didn't support fast delete; Delete rows one by one */ @@ -212,11 +198,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (thd->is_error()) DBUG_RETURN(TRUE); my_ok(thd, 0); - /* - We don't need to call reset_auto_increment in this case, because - mysql_truncate always gives a NULL conds argument, hence we never - get here. - */ DBUG_RETURN(0); // Nothing to delete } @@ -287,12 +268,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, init_ftfuncs(thd, select_lex, 1); thd_proc_info(thd, "updating"); - /* NOTE: TRUNCATE must not invoke triggers. */ - - triggers_applicable= table->triggers && - thd->lex->sql_command != SQLCOM_TRUNCATE; - - if (triggers_applicable && + if (table->triggers && table->triggers->has_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER)) { @@ -310,11 +286,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->mark_columns_needed_for_delete(); - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - if (thd->lex->sql_command == SQLCOM_TRUNCATE && - thd->is_current_stmt_binlog_format_row()) - thd->clear_current_stmt_binlog_format_row(); - while (!(error=info.read_record(&info)) && !thd->killed && ! thd->is_error()) { @@ -323,7 +294,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (!(select && select->skip_record())&& ! thd->is_error() ) { - if (triggers_applicable && + if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) { @@ -334,7 +305,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (!(error= table->file->ha_delete_row(table->record[0]))) { deleted++; - if (triggers_applicable && + if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) { @@ -379,21 +350,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_NORMAL); - if (reset_auto_increment && (error < 0)) - { - /* - We're really doing a truncate and need to reset the table's - auto-increment counter. - */ - int error2= table->file->ha_reset_auto_increment(0); - - if (error2 && (error2 != HA_ERR_WRONG_COMMAND)) - { - table->file->print_error(error2, MYF(0)); - error= 1; - } - } - cleanup: /* Invalidate the table in the query cache if something changed. This must @@ -414,34 +370,24 @@ cleanup: /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { - if (mysql_bin_log.is_open() && - !(thd->lex->sql_command == SQLCOM_TRUNCATE && - thd->is_current_stmt_binlog_format_row() && - find_temporary_table(thd, table_list))) + if (mysql_bin_log.is_open()) { - bool const is_trans= - thd->lex->sql_command == SQLCOM_TRUNCATE ? - FALSE : - transactional_table; - int errcode= 0; if (error < 0) thd->clear_error(); else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); - + /* [binlog]: If 'handler::delete_all_rows()' was called and the storage engine does not inject the rows itself, we replicate statement-based; otherwise, 'ha_delete_row()' was used to delete specific rows which we might log row-based. - - Note that TRUNCATE TABLE is not transactional and should - therefore be treated as a DDL. */ int log_result= thd->binlog_query(query_type, thd->query(), thd->query_length(), - is_trans, FALSE, FALSE, errcode); + transactional_table, FALSE, FALSE, + errcode); if (log_result) { @@ -449,18 +395,12 @@ cleanup: } } } - if (save_binlog_row_based) - thd->set_current_stmt_binlog_format_row(); DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); if (error < 0 || (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error)) { - /* - If a TRUNCATE TABLE was issued, the number of rows should be reported as - zero since the exact number is unknown. - */ - my_ok(thd, reset_auto_increment ? 0 : deleted); + my_ok(thd, deleted); DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } DBUG_RETURN(error >= 0 || thd->is_error()); @@ -1062,227 +1002,3 @@ bool multi_delete::send_eof() return 0; } - -/*************************************************************************** - TRUNCATE TABLE -****************************************************************************/ - -/* - Row-by-row truncation if the engine does not support table recreation. - Probably a InnoDB table. -*/ - -static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list) -{ - bool error; - DBUG_ENTER("mysql_truncate_by_delete"); - table_list->lock_type= TL_WRITE; - table_list->mdl_request.set_type(MDL_SHARED_WRITE); - mysql_init_select(thd->lex); - /* Delete all rows from table */ - error= mysql_delete(thd, table_list, NULL, NULL, HA_POS_ERROR, LL(0), TRUE); - /* - All effects of a TRUNCATE TABLE operation are rolled back if a row by row - deletion fails. Otherwise, operation is automatically committed at the end. - */ - if (error) - { - DBUG_ASSERT(thd->stmt_da->is_error()); - trans_rollback_stmt(thd); - trans_rollback(thd); - } - DBUG_RETURN(error); -} - - -/* - Optimize delete of all rows by doing a full generate of the table - This will work even if the .ISM and .ISD tables are destroyed - - dont_send_ok should be set if: - - We should always wants to generate the table (even if the table type - normally can't safely do this. - - We don't want an ok to be sent to the end user. - - We don't want to log the truncate command - - If we want to keep exclusive metadata lock on the table (obtained by - caller) on exit without errors. -*/ - -bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) -{ - HA_CREATE_INFO create_info; - char path[FN_REFLEN + 1]; - TABLE *table; - bool error= TRUE; - uint path_length; - /* - Is set if we're under LOCK TABLES, and used - to downgrade the exclusive lock after the - table was truncated. - */ - MDL_ticket *mdl_ticket= NULL; - bool has_mdl_lock= FALSE; - bool is_temporary_table= false; - DBUG_ENTER("mysql_truncate"); - - bzero((char*) &create_info,sizeof(create_info)); - - /* Remove tables from the HANDLER's hash. */ - mysql_ha_rm_tables(thd, table_list); - - /* If it is a temporary table, close and regenerate it */ - if (!dont_send_ok && (table= find_temporary_table(thd, table_list))) - { - is_temporary_table= true; - handlerton *table_type= table->s->db_type(); - TABLE_SHARE *share= table->s; - /* Note that a temporary table cannot be partitioned */ - if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)) - goto trunc_by_del; - - table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK); - - close_temporary_table(thd, table, 0, 0); // Don't free share - ha_create_table(thd, share->normalized_path.str, - share->db.str, share->table_name.str, &create_info, 1); - // We don't need to call invalidate() because this table is not in cache - if ((error= (int) !(open_temporary_table(thd, share->path.str, - share->db.str, - share->table_name.str, 1)))) - (void) rm_temporary_table(table_type, path); - else - thd->thread_specific_used= TRUE; - - free_table_share(share); - my_free((char*) table,MYF(0)); - /* - If we return here we will not have logged the truncation to the bin log - and we will not my_ok() to the client. - */ - goto end; - } - - path_length= build_table_filename(path, sizeof(path) - 1, table_list->db, - table_list->table_name, reg_ext, 0); - - if (!dont_send_ok) - { - enum legacy_db_type table_type; - /* - FIXME: Code of TRUNCATE breaks the meta-data - locking protocol since it tries to find out the table storage - engine and therefore accesses table in some way without holding - any kind of meta-data lock. - */ - mysql_frm_type(thd, path, &table_type); - if (table_type == DB_TYPE_UNKNOWN) - { - my_error(ER_NO_SUCH_TABLE, MYF(0), - table_list->db, table_list->table_name); - DBUG_RETURN(TRUE); - } -#ifdef WITH_PARTITION_STORAGE_ENGINE - /* - TODO: Add support for TRUNCATE PARTITION for NDB and other engines - supporting native partitioning - */ - if (table_type != DB_TYPE_PARTITION_DB && - thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION) - { - my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); - DBUG_RETURN(TRUE); - } -#endif - if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, - table_type), - HTON_CAN_RECREATE) || - thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION) - goto trunc_by_del; - - - if (thd->locked_tables_mode) - { - if (!(table= find_table_for_mdl_upgrade(thd->open_tables, table_list->db, - table_list->table_name, FALSE))) - DBUG_RETURN(TRUE); - mdl_ticket= table->mdl_ticket; - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) - goto end; - close_all_tables_for_name(thd, table->s, FALSE); - } - else - { - MDL_request mdl_global_request, mdl_request; - MDL_request_list mdl_requests; - /* - Even though we could use the previous execution branch - here just as well, we must not try to open the table: - MySQL manual documents that TRUNCATE can be used to - repair a damaged table, i.e. a table that can not be - fully "opened". In particular MySQL manual says: - - As long as the table format file tbl_name.frm is valid, - the table can be re-created as an empty table with TRUNCATE - TABLE, even if the data or index files have become corrupted. - */ - - mdl_global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE); - mdl_request.init(MDL_key::TABLE, table_list->db, table_list->table_name, - MDL_EXCLUSIVE); - mdl_requests.push_front(&mdl_request); - mdl_requests.push_front(&mdl_global_request); - - if (thd->mdl_context.acquire_locks(&mdl_requests, - thd->variables.lock_wait_timeout)) - DBUG_RETURN(TRUE); - - has_mdl_lock= TRUE; - mysql_mutex_lock(&LOCK_open); - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db, - table_list->table_name); - mysql_mutex_unlock(&LOCK_open); - } - } - - /* - Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this - crashes, replacement works. *(path + path_length - reg_ext_length)= - '\0'; - */ - path[path_length - reg_ext_length] = 0; - mysql_mutex_lock(&LOCK_open); - error= ha_create_table(thd, path, table_list->db, table_list->table_name, - &create_info, 1); - mysql_mutex_unlock(&LOCK_open); - query_cache_invalidate3(thd, table_list, 0); - -end: - if (!dont_send_ok) - { - if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd)) - thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); - /* - Even if we failed to reopen some tables, - the operation itself succeeded, write the binlog. - */ - if (!error) - { - /* In RBR, the statement is not binlogged if the table is temporary. */ - if (!is_temporary_table || !thd->is_current_stmt_binlog_format_row()) - error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - if (!error) - my_ok(thd); // This should return record count - } - if (has_mdl_lock) - thd->mdl_context.release_transactional_locks(); - if (mdl_ticket) - mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE); - } - - DBUG_PRINT("exit", ("error: %d", error)); - DBUG_RETURN(error); - -trunc_by_del: - error= mysql_truncate_by_delete(thd, table_list); - DBUG_RETURN(error); -} diff --git a/sql/sql_delete.h b/sql/sql_delete.h index 0e09120f557..264991c220b 100644 --- a/sql/sql_delete.h +++ b/sql/sql_delete.h @@ -27,8 +27,6 @@ template <typename T> class SQL_I_List; int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_I_List<ORDER> *order, ha_rows rows, ulonglong options, - bool reset_auto_increment); -bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok); + SQL_I_List<ORDER> *order, ha_rows rows, ulonglong options); #endif /* SQL_DELETE_INCLUDED */ diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index b9cc0ef477d..d6f2a472e05 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -131,13 +131,11 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) /* Non temporary table. */ tables->table->file->ha_index_or_rnd_end(); tables->table->open_by_handler= 0; - mysql_mutex_lock(&LOCK_open); if (close_thread_table(thd, &tables->table)) { /* Tell threads waiting for refresh that something has happened */ broadcast_refresh(); } - mysql_mutex_unlock(&LOCK_open); thd->mdl_context.release_lock(tables->mdl_request.ticket); } else if (tables->table) @@ -278,7 +276,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) See open_table() back-off comments for more details. */ backup_open_tables= thd->open_tables; - thd->open_tables= NULL; + thd->set_open_tables(NULL); mdl_savepoint= thd->mdl_context.mdl_savepoint(); /* @@ -312,7 +310,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) if (error) { close_thread_tables(thd); - thd->open_tables= backup_open_tables; + thd->set_open_tables(backup_open_tables); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); if (!reopen) my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); @@ -325,7 +323,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(TRUE); } - thd->open_tables= backup_open_tables; + thd->set_open_tables(backup_open_tables); if (hash_tables->mdl_request.ticket) { thd->mdl_context. @@ -559,7 +557,7 @@ retry: mysql_lock_tables() needs thd->open_tables to be set correctly to be able to handle aborts properly. */ - thd->open_tables= hash_tables->table; + thd->set_open_tables(hash_tables->table); sql_handler_lock_error.init(); @@ -575,7 +573,7 @@ retry: */ DBUG_ASSERT(hash_tables->table == thd->open_tables); /* Restore previous context. */ - thd->open_tables= backup_open_tables; + thd->set_open_tables(backup_open_tables); if (sql_handler_lock_error.need_reopen()) { @@ -853,6 +851,35 @@ void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables) /** + Close cursors of matching tables from the HANDLER's hash table. + + @param thd Thread identifier. + @param tables The list of tables to flush. +*/ + +void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables) +{ + DBUG_ENTER("mysql_ha_flush_tables"); + + for (TABLE_LIST *table_list= all_tables; table_list; + table_list= table_list->next_global) + { + TABLE_LIST *hash_tables= mysql_ha_find(thd, table_list); + /* Close all aliases of the same table. */ + while (hash_tables) + { + TABLE_LIST *next_local= hash_tables->next_local; + if (hash_tables->table) + mysql_ha_close_table(thd, hash_tables); + hash_tables= next_local; + } + } + + DBUG_VOID_RETURN; +} + + +/** Flush (close and mark for re-open) all tables that should be should be reopen. diff --git a/sql/sql_handler.h b/sql/sql_handler.h index 8666d5a8d7b..c5da3c4d468 100644 --- a/sql/sql_handler.h +++ b/sql/sql_handler.h @@ -28,6 +28,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); void mysql_ha_flush(THD *thd); +void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables); void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables); void mysql_ha_cleanup(THD *thd); void mysql_ha_move_tickets_after_trans_sentinel(THD *thd); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d40f0dcb410..24a418f8f25 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1814,7 +1814,6 @@ public: thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user; thd.security_ctx->host=(char*) my_localhost; thd.current_tablenr=0; - thd.version=refresh_version; thd.command=COM_DELAYED_INSERT; thd.lex->current_select= 0; // for my_message_sql thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() @@ -3608,13 +3607,12 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); /* Here we open the destination table, on which we already have an exclusive metadata lock. */ - if (open_table(thd, create_table, thd->mem_root, - &ot_ctx_unused, MYSQL_OPEN_REOPEN)) + if (open_table(thd, create_table, thd->mem_root, &ot_ctx)) { mysql_mutex_lock(&LOCK_open); quick_rm_table(create_info->db_type, create_table->db, @@ -3627,9 +3625,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } else { - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); - if (open_table(thd, create_table, thd->mem_root, &ot_ctx_unused, - MYSQL_OPEN_TEMPORARY_ONLY)) + Open_table_context ot_ctx(thd, MYSQL_OPEN_TEMPORARY_ONLY); + if (open_table(thd, create_table, thd->mem_root, &ot_ctx)) { /* This shouldn't happen as creation of temporary table should make diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 16b4c727689..5f8b1148dcb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -443,8 +443,11 @@ void lex_end(LEX *lex) DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); /* release used plugins */ - plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, - lex->plugins.elements); + if (lex->plugins.elements) /* No function call and no mutex if no plugins. */ + { + plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, + lex->plugins.elements); + } reset_dynamic(&lex->plugins); DBUG_VOID_RETURN; @@ -1986,6 +1989,7 @@ TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table, LEX_STRING *alias, ulong table_join_options, thr_lock_type flags, + enum_mdl_type mdl_type, List<Index_hint> *hints, LEX_STRING *option) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 985edd42496..05af1237be8 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -502,6 +502,7 @@ public: LEX_STRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, + enum_mdl_type mdl_type= MDL_SHARED_READ, List<Index_hint> *hints= 0, LEX_STRING *option= 0); virtual void set_lock_for_tables(thr_lock_type lock_type) {} @@ -799,6 +800,7 @@ public: LEX_STRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, + enum_mdl_type mdl_type= MDL_SHARED_READ, List<Index_hint> *hints= 0, LEX_STRING *option= 0); TABLE_LIST* get_table_list(); @@ -1989,7 +1991,7 @@ struct LEX: public Query_tables_list bool autocommit; bool verbose, no_write_to_binlog; - bool tx_chain, tx_release; + enum enum_yes_no_unknown tx_chain, tx_release; /* Special JOIN::prepare mode: changing of query is prohibited. When creating a view, we need to just check its syntax omitting @@ -2266,6 +2268,7 @@ public: yacc_yyvs= NULL; m_set_signal_info.clear(); m_lock_type= TL_READ_DEFAULT; + m_mdl_type= MDL_SHARED_READ; } ~Yacc_state(); @@ -2277,6 +2280,7 @@ public: void reset_before_substatement() { m_lock_type= TL_READ_DEFAULT; + m_mdl_type= MDL_SHARED_READ; } /** @@ -2316,6 +2320,12 @@ public: */ thr_lock_type m_lock_type; + /** + The type of requested metadata lock for tables added to + the statement table list. + */ + enum_mdl_type m_mdl_type; + /* TODO: move more attributes from the LEX structure here. */ diff --git a/sql/sql_list.h b/sql/sql_list.h index d57534b0999..5b63e80ae94 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -85,7 +85,7 @@ public: SQL_I_List() { empty(); } - SQL_I_List(const SQL_I_List &tmp) + SQL_I_List(const SQL_I_List &tmp) : Sql_alloc() { elements= tmp.elements; first= tmp.first; diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index e9c9402a89a..2189b1e124f 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -108,7 +108,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) if (error == ETIMEDOUT || error == ETIME) { - flush_tables(); + tdc_flush_unused_tables(); error = 0; reset_flush_time = TRUE; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bdee13372d5..c3daf3b9520 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -49,6 +49,7 @@ // mysql_recreate_table, // mysql_backup_table, // mysql_restore_table +#include "sql_truncate.h" // mysql_truncate_table #include "sql_connect.h" // check_user, // decrease_user_connections, // thd_init_client_charset, check_mqh, @@ -264,7 +265,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS | CF_PROTECT_AGAINST_GRL; sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | - CF_AUTO_COMMIT_TRANS; + CF_AUTO_COMMIT_TRANS | CF_PROTECT_AGAINST_GRL; sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL | @@ -496,7 +497,6 @@ static void handle_bootstrap_impl(THD *thd) #endif /* EMBEDDED_LIBRARY */ thd_proc_info(thd, 0); - thd->version=refresh_version; thd->security_ctx->priv_user= thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); thd->security_ctx->priv_host[0]=0; @@ -1674,7 +1674,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, /* 'parent_lex' is used in init_query() so it must be before it. */ schema_select_lex->parent_lex= lex; schema_select_lex->init_query(); - if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ)) + if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ, + MDL_SHARED_READ)) DBUG_RETURN(1); lex->query_tables_last= query_tables_last; break; @@ -2612,7 +2613,7 @@ case SQLCOM_PREPARE: /* Set strategies: reset default or 'prepared' values. */ create_table->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; - create_table->lock_strategy= TABLE_LIST::EXCLUSIVE_DOWNGRADABLE_MDL; + create_table->lock_strategy= TABLE_LIST::OTLS_DOWNGRADE_IF_EXISTS; /* Close any open handlers for the table @@ -3350,9 +3351,8 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE)) - goto error; - res= mysql_truncate(thd, first_table, 0); + if (! (res= mysql_truncate_table(thd, first_table))) + my_ok(thd); break; case SQLCOM_DELETE: { @@ -3365,8 +3365,7 @@ end_with_restore_list: MYSQL_DELETE_START(thd->query()); res = mysql_delete(thd, all_tables, select_lex->where, &select_lex->order_list, - unit->select_limit_cnt, select_lex->options, - FALSE); + unit->select_limit_cnt, select_lex->options); MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func()); break; } @@ -3572,16 +3571,13 @@ end_with_restore_list: thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE)) goto error; - init_mdl_requests(all_tables); - thd->variables.option_bits|= OPTION_TABLE_LOCK; thd->in_lock_tables=1; { Lock_tables_prelocking_strategy lock_tables_prelocking_strategy; - res= (open_and_lock_tables(thd, all_tables, FALSE, - MYSQL_OPEN_TAKE_UPGRADABLE_MDL, + res= (open_and_lock_tables(thd, all_tables, FALSE, 0, &lock_tables_prelocking_strategy) || thd->locked_tables_list.init_locked_tables(thd)); } @@ -4103,33 +4099,65 @@ end_with_restore_list: my_ok(thd); break; case SQLCOM_COMMIT: + { DBUG_ASSERT(thd->lock == NULL || thd->locked_tables_mode == LTM_LOCK_TABLES); + bool tx_chain= (lex->tx_chain == TVL_YES || + (thd->variables.completion_type == 1 && + lex->tx_chain != TVL_NO)); + bool tx_release= (lex->tx_release == TVL_YES || + (thd->variables.completion_type == 2 && + lex->tx_release != TVL_NO)); if (trans_commit(thd)) goto error; thd->mdl_context.release_transactional_locks(); /* Begin transaction with the same isolation level. */ - if (lex->tx_chain && trans_begin(thd)) + if (tx_chain) + { + if (trans_begin(thd)) goto error; + } + else + { + /* Reset the isolation level if no chaining transaction. */ + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + } /* Disconnect the current client connection. */ - if (lex->tx_release) + if (tx_release) thd->killed= THD::KILL_CONNECTION; my_ok(thd); break; + } case SQLCOM_ROLLBACK: + { DBUG_ASSERT(thd->lock == NULL || thd->locked_tables_mode == LTM_LOCK_TABLES); + bool tx_chain= (lex->tx_chain == TVL_YES || + (thd->variables.completion_type == 1 && + lex->tx_chain != TVL_NO)); + bool tx_release= (lex->tx_release == TVL_YES || + (thd->variables.completion_type == 2 && + lex->tx_release != TVL_NO)); if (trans_rollback(thd)) goto error; thd->mdl_context.release_transactional_locks(); /* Begin transaction with the same isolation level. */ - if (lex->tx_chain && trans_begin(thd)) - goto error; + if (tx_chain) + { + if (trans_begin(thd)) + goto error; + } + else + { + /* Reset the isolation level if no chaining transaction. */ + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + } /* Disconnect the current client connection. */ - if (lex->tx_release) + if (tx_release) thd->killed= THD::KILL_CONNECTION; my_ok(thd); break; + } case SQLCOM_RELEASE_SAVEPOINT: if (trans_release_savepoint(thd, lex->ident)) goto error; @@ -4632,12 +4660,22 @@ create_sp_error: if (trans_xa_commit(thd)) goto error; thd->mdl_context.release_transactional_locks(); + /* + We've just done a commit, reset transaction + isolation level to the session default. + */ + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; my_ok(thd); break; case SQLCOM_XA_ROLLBACK: if (trans_xa_rollback(thd)) goto error; thd->mdl_context.release_transactional_locks(); + /* + We've just done a rollback, reset transaction + isolation level to the session default. + */ + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; my_ok(thd); break; case SQLCOM_XA_RECOVER: @@ -6087,6 +6125,7 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc) - TL_OPTION_FORCE_INDEX : Force usage of index - TL_OPTION_ALIAS : an alias in multi table DELETE @param lock_type How table should be locked + @param mdl_type Type of metadata lock to acquire on the table. @param use_index List of indexed used in USE INDEX @param ignore_index List of indexed used in IGNORE INDEX @@ -6101,6 +6140,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, LEX_STRING *alias, ulong table_options, thr_lock_type lock_type, + enum_mdl_type mdl_type, List<Index_hint> *index_hints_arg, LEX_STRING *option) { @@ -6248,9 +6288,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->next_name_resolution_table= NULL; /* Link table in global list (all used tables) */ lex->add_to_query_tables(ptr); - ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, - (ptr->lock_type >= TL_WRITE_ALLOW_WRITE) ? - MDL_SHARED_WRITE : MDL_SHARED_READ); + ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type); DBUG_RETURN(ptr); } @@ -7620,7 +7658,7 @@ LEX_USER *create_default_definer(THD *thd) if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) return 0; - get_default_definer(thd, definer); + thd->get_definer(definer); return definer; } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index de0a3035e9a..df76df72e09 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -130,11 +130,6 @@ bool check_simple_select(); Item *negate_expression(THD *thd, Item *expr); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); -bool begin_trans(THD *thd); -bool end_active_trans(THD *thd); -int end_trans(THD *thd, enum enum_mysql_completiontype completion); - - /* Variables */ extern const char* any_db; diff --git a/sql/sql_plist.h b/sql/sql_plist.h index eb239a63467..db85266be15 100644 --- a/sql/sql_plist.h +++ b/sql/sql_plist.h @@ -18,8 +18,10 @@ #include <my_global.h> -template <typename T, typename B, typename C> class I_P_List_iterator; +template <typename T, typename B, typename C, typename I> +class I_P_List_iterator; class I_P_List_null_counter; +template <typename T> class I_P_List_no_push_back; /** @@ -52,12 +54,19 @@ class I_P_List_null_counter; should be done. Instance of this class is also used as a place where information about number of list elements is stored. @sa I_P_List_null_counter, I_P_List_counter + @param I Policy class specifying whether I_P_List should support + efficient push_back() operation. Instance of this class + is used as place where we store information to support + this operation. + @sa I_P_List_no_push_back, I_P_List_fast_push_back. */ -template <typename T, typename B, typename C = I_P_List_null_counter> -class I_P_List : public C +template <typename T, typename B, + typename C = I_P_List_null_counter, + typename I = I_P_List_no_push_back<T> > +class I_P_List : public C, public I { - T *first; + T *m_first; /* Do not prohibit copying of I_P_List object to simplify their usage in @@ -65,31 +74,27 @@ class I_P_List : public C is a bad idea. */ public: - I_P_List() : first(NULL) { }; - inline void empty() { first= NULL; C::reset(); } - inline bool is_empty() const { return (first == NULL); } + I_P_List() : I(&m_first), m_first(NULL) {}; + inline void empty() { m_first= NULL; C::reset(); I::set_last(&m_first); } + inline bool is_empty() const { return (m_first == NULL); } inline void push_front(T* a) { - *B::next_ptr(a)= first; - if (first) - *B::prev_ptr(first)= B::next_ptr(a); - first= a; - *B::prev_ptr(a)= &first; + *B::next_ptr(a)= m_first; + if (m_first) + *B::prev_ptr(m_first)= B::next_ptr(a); + else + I::set_last(B::next_ptr(a)); + m_first= a; + *B::prev_ptr(a)= &m_first; C::inc(); } inline void push_back(T *a) { - insert_after(back(), a); - } - inline T *back() - { - T *t= front(); - if (t) - { - while (*B::next_ptr(t)) - t= *B::next_ptr(t); - } - return t; + T **last= I::get_last(); + *B::next_ptr(a)= *last; + *last= a; + *B::prev_ptr(a)= last; + I::set_last(B::next_ptr(a)); } inline void insert_after(T *pos, T *a) { @@ -105,6 +110,8 @@ public: T *old_next= *B::next_ptr(a); *B::prev_ptr(old_next)= B::next_ptr(a); } + else + I::set_last(B::next_ptr(a)); } } inline void remove(T *a) @@ -112,24 +119,31 @@ public: T *next= *B::next_ptr(a); if (next) *B::prev_ptr(next)= *B::prev_ptr(a); + else + I::set_last(*B::prev_ptr(a)); **B::prev_ptr(a)= next; C::dec(); } - inline T* front() { return first; } - inline const T *front() const { return first; } + inline T* front() { return m_first; } + inline const T *front() const { return m_first; } void swap(I_P_List<T, B, C> &rhs) { - swap_variables(T *, first, rhs.first); - if (first) - *B::prev_ptr(first)= &first; - if (rhs.first) - *B::prev_ptr(rhs.first)= &rhs.first; + swap_variables(T *, m_first, rhs.m_first); + I::swap(rhs); + if (m_first) + *B::prev_ptr(m_first)= &m_first; + else + I::set_last(&m_first); + if (rhs.m_first) + *B::prev_ptr(rhs.m_first)= &rhs.m_first; + else + I::set_last(&rhs.m_first); C::swap(rhs); } #ifndef _lint - friend class I_P_List_iterator<T, B, C>; + friend class I_P_List_iterator<T, B, C, I>; #endif - typedef I_P_List_iterator<T, B, C> Iterator; + typedef I_P_List_iterator<T, B, C, I> Iterator; }; @@ -137,18 +151,22 @@ public: Iterator for I_P_List. */ -template <typename T, typename B, typename C = I_P_List_null_counter> +template <typename T, typename B, + typename C = I_P_List_null_counter, + typename I = I_P_List_no_push_back<T> > class I_P_List_iterator { - const I_P_List<T, B, C> *list; + const I_P_List<T, B, C, I> *list; T *current; public: - I_P_List_iterator(const I_P_List<T, B, C> &a) : list(&a), current(a.first) {} - I_P_List_iterator(const I_P_List<T, B, C> &a, T* current_arg) : list(&a), current(current_arg) {} - inline void init(const I_P_List<T, B, C> &a) + I_P_List_iterator(const I_P_List<T, B, C, I> &a) + : list(&a), current(a.m_first) {} + I_P_List_iterator(const I_P_List<T, B, C, I> &a, T* current_arg) + : list(&a), current(current_arg) {} + inline void init(const I_P_List<T, B, C, I> &a) { list= &a; - current= a.first; + current= a.m_first; } inline T* operator++(int) { @@ -164,7 +182,7 @@ public: } inline void rewind() { - current= list->first; + current= list->m_first; } }; @@ -203,4 +221,40 @@ public: uint elements() const { return m_counter; } }; + +/** + A null insertion policy class for I_P_List to be used + in cases when push_back() operation is not necessary. +*/ + +template <typename T> class I_P_List_no_push_back +{ +protected: + I_P_List_no_push_back(T **a) {}; + void set_last(T **a) {} + /* + T** get_last() const method is intentionally left unimplemented + in order to prohibit usage of push_back() method in lists which + use this policy. + */ + void swap(I_P_List_no_push_back<T> &rhs) {} +}; + + +/** + An insertion policy class for I_P_List which can + be used when fast push_back() operation is required. +*/ + +template <typename T> class I_P_List_fast_push_back +{ + T **m_last; +protected: + I_P_List_fast_push_back(T **a) : m_last(a) { }; + void set_last(T **a) { m_last= a; } + T** get_last() const { return m_last; } + void swap(I_P_List_fast_push_back<T> &rhs) + { swap_variables(T**, m_last, rhs.m_last); } +}; + #endif diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index c87da592210..97c480ea0bd 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -261,11 +261,6 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); -#ifdef EMBEDDED_LIBRARY -/* declared in sql_base.cc */ -extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); -#endif /* EMBEDDED_LIBRARY */ - static void report_error(int where_to, uint error, ...) { va_list args; @@ -1475,10 +1470,8 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) When building an embedded library, if the mysql.plugin table does not exist, we silently ignore the missing table */ - mysql_mutex_lock(&LOCK_open); if (check_if_table_exists(new_thd, &tables, &table_exists)) table_exists= FALSE; - mysql_mutex_unlock(&LOCK_open); if (!table_exists) goto end; #endif /* EMBEDDED_LIBRARY */ @@ -1519,7 +1512,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) if (error > 0) sql_print_error(ER(ER_GET_ERRNO), my_errno); end_read_record(&read_record_info); - new_thd->version--; // Force close to free memory + table->m_needs_reopen= TRUE; // Force close to free memory end: close_thread_tables(new_thd); /* Remember that we don't have a THD */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 296fcf301d3..089e751900e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -791,6 +791,19 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, } #ifndef EMBEDDED_LIBRARY + +/** + Check whether this parameter data type is compatible with long data. + Used to detect whether a long data stream has been supplied to a + incompatible data type. +*/ +inline bool is_param_long_data_type(Item_param *param) +{ + return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) && + (param->param_type <= MYSQL_TYPE_STRING)); +} + + /** Routines to assign parameters from data supplied by the client. @@ -860,6 +873,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (!is_param_long_data_type(param)) + DBUG_RETURN(1); res= param->query_val_str(&str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -898,6 +919,14 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (is_param_long_data_type(param)) + DBUG_RETURN(1); if (param->convert_str_value(stmt->thd)) DBUG_RETURN(1); /* out of memory */ } @@ -1690,7 +1719,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt) for the prepare phase. */ create_table->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; - create_table->lock_strategy= TABLE_LIST::SHARED_MDL; + create_table->lock_strategy= TABLE_LIST::OTLS_NONE; if (select_lex->item_list.elements) { diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 8601b10b9bf..604890ffbe5 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -211,6 +211,11 @@ enum enum_var_type class sys_var; +enum enum_yes_no_unknown +{ + TVL_YES, TVL_NO, TVL_UNKNOWN +}; + #ifdef MYSQL_SERVER #endif /* MYSQL_SERVER */ diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index ea95b59b0c2..130a99a374f 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -29,6 +29,7 @@ // start_waiting_global_read_lock #include "sql_base.h" // tdc_remove_table #include "sql_handler.h" // mysql_ha_rm_tables +#include "datadict.h" static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error); @@ -283,7 +284,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, build_table_filename(name, sizeof(name) - 1, ren_table->db, old_alias, reg_ext, 0); - frm_type= mysql_frm_type(thd, name, &table_type); + frm_type= dd_frm_type(thd, name, &table_type); switch (frm_type) { case FRMTYPE_TABLE: diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 787f9dcae2c..5f994c09d6d 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -257,8 +257,7 @@ bool log_in_use(const char* log_name) if ((linfo = tmp->current_linfo)) { mysql_mutex_lock(&linfo->lock); - result = !bcmp((uchar*) log_name, (uchar*) linfo->log_file_name, - log_name_len); + result = !memcmp(log_name, linfo->log_file_name, log_name_len); mysql_mutex_unlock(&linfo->lock); if (result) break; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 992fa8f6212..8860cafc55f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -586,13 +586,21 @@ JOIN::prepare(Item ***rref_pointer_array, { Item *item= *ord->item; /* - Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields - there. Such fields don't contain any data to sort. + Disregard sort order if there's only + zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or + zero length NOT NULL string functions there. + Such tuples don't contain any data to sort. */ if (!real_order && - (item->type() != Item::FIELD_ITEM || - ((Item_field *) item)->field->maybe_null() || - ((Item_field *) item)->field->sort_length())) + /* Not a zero length NOT NULL field */ + ((item->type() != Item::FIELD_ITEM || + ((Item_field *) item)->field->maybe_null() || + ((Item_field *) item)->field->sort_length()) && + /* AND not a zero length NOT NULL string function. */ + (item->type() != Item::FUNC_ITEM || + item->maybe_null || + item->result_type() != STRING_RESULT || + item->max_length))) real_order= TRUE; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) @@ -7350,7 +7358,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { - if (order->item[0]->with_subselect) + if (order->item[0]->with_subselect && + !(join->select_lex->options & SELECT_DESCRIBE)) order->item[0]->val_str(&order->item[0]->str_value); DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; // skip const item @@ -13615,6 +13624,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, uint nr; key_map keys; uint best_key_parts= 0; + uint saved_best_key_parts= 0; int best_key_direction= 0; ha_rows best_records= 0; double read_time; @@ -13775,6 +13785,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, { best_key= nr; best_key_parts= keyinfo->key_parts; + saved_best_key_parts= used_key_parts; best_records= quick_records; is_best_covering= is_covering; best_key_direction= direction; @@ -13861,8 +13872,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ } } - used_key_parts= best_key_parts; order_direction= best_key_direction; + /* + saved_best_key_parts is actual number of used keyparts found by the + test_if_order_by_key function. It could differ from keyinfo->key_parts, + thus we have to restore it in case of desc order as it affects + QUICK_SELECT_DESC behaviour. + */ + used_key_parts= (order_direction == -1) ? + saved_best_key_parts : best_key_parts; } else DBUG_RETURN(0); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 99073ced693..5f2b975a94d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -18,7 +18,6 @@ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "debug_sync.h" #include "unireg.h" #include "sql_acl.h" // fill_schema_*_privileges #include "sql_select.h" // For select_describe @@ -28,7 +27,6 @@ // primary_key_name, // build_table_filename #include "repl_failsafe.h" -#include "sql_view.h" // mysql_frm_type #include "sql_parse.h" // check_access, check_table_access #include "sql_partition.h" // partition_element #include "sql_db.h" // check_db_dir_existence, load_db_opt_by_name @@ -50,8 +48,9 @@ #include "event_data_objects.h" #endif #include <my_dir.h> -#include "debug_sync.h" #include "lock.h" // MYSQL_OPEN_IGNORE_FLUSH +#include "debug_sync.h" +#include "datadict.h" // dd_frm_type() #define STR_OR_NIL(S) ((S) ? (S) : "<nil>") @@ -2366,7 +2365,7 @@ int make_table_list(THD *thd, SELECT_LEX *sel, Table_ident *table_ident; table_ident= new Table_ident(thd, *db_name, *table_name, 1); sel->init_query(); - if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ)) + if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, MDL_SHARED_READ)) return 1; return 0; } @@ -2858,7 +2857,9 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex, { if (with_i_schema) { - if (find_schema_table(thd, lookup_field_vals->table_value.str)) + ST_SCHEMA_TABLE *schema_table= + find_schema_table(thd, lookup_field_vals->table_value.str); + if (schema_table && !schema_table->hidden) { if (table_names->push_back(&lookup_field_vals->table_value)) return 1; @@ -2966,6 +2967,9 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, (can_deadlock ? MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0))); lex->sql_command= save_sql_command; + + DEBUG_SYNC(thd, "after_open_table_ignore_flush"); + /* get_all_tables() returns 1 on failure and 0 on success thus return only these and not the result code of ::process_table() @@ -3025,7 +3029,7 @@ static int fill_schema_table_names(THD *thd, TABLE *table, char path[FN_REFLEN + 1]; (void) build_table_filename(path, sizeof(path) - 1, db_name->str, table_name->str, reg_ext, 0); - switch (mysql_frm_type(thd, path, ¬_used)) { + switch (dd_frm_type(thd, path, ¬_used)) { case FRMTYPE_ERROR: table->field[3]->store(STRING_WITH_LEN("ERROR"), system_charset_info); @@ -3133,15 +3137,27 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table, bool error; table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name, MDL_SHARED_HIGH_PRIO); - while (!(error= - thd->mdl_context.try_acquire_lock(&table->mdl_request)) && - !table->mdl_request.ticket && !can_deadlock) + + if (can_deadlock) { - if ((error= - thd->mdl_context.wait_for_lock(&table->mdl_request, - thd->variables.lock_wait_timeout))) - break; + /* + When .FRM is being open in order to get data for an I_S table, + we might have some tables not only open but also locked. + E.g. this happens when a SHOW or I_S statement is run + under LOCK TABLES or inside a stored function. + By waiting for the conflicting metadata lock to go away we + might create a deadlock which won't entirely belong to the + MDL subsystem and thus won't be detectable by this subsystem's + deadlock detector. To avoid such situation, when there are + other locked tables, we prefer not to wait on a conflicting + lock. + */ + error= thd->mdl_context.try_acquire_lock(&table->mdl_request); } + else + error= thd->mdl_context.acquire_lock(&table->mdl_request, + thd->variables.lock_wait_timeout); + return error; } @@ -6568,7 +6584,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, strlen(schema_table->table_name), 0); if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0), - 0, 0, TL_READ)) + 0, 0, TL_READ, MDL_SHARED_READ)) { DBUG_RETURN(1); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dce23d1c09c..902e7fa7b5f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -27,8 +27,8 @@ // start_waiting_global_read_lock, // unlock_table_names, mysql_unlock_tables #include "strfunc.h" // find_type2, find_set -#include "sql_view.h" // mysql_frm_type, view_checksum, mysql_frm_type -#include "sql_delete.h" // mysql_truncate +#include "sql_view.h" // view_checksum +#include "sql_truncate.h" // regenerate_locked_table #include "sql_partition.h" // mem_alloc_error, // generate_partition_syntax, // partition_info @@ -52,6 +52,7 @@ #include "sql_show.h" #include "transaction.h" #include "keycaches.h" +#include "datadict.h" // dd_frm_type() #ifdef __WIN__ #include <io.h> @@ -84,19 +85,6 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, HA_CREATE_INFO *create_info, Alter_info *alter_info); -#ifndef DBUG_OFF - -/* Wait until we get a 'mysql_kill' signal */ - -static void wait_for_kill_signal(THD *thd) -{ - while (thd->killed == 0) - sleep(1); - // Reset signal and continue as if nothing happend - thd->killed= THD::NOT_KILLED; -} -#endif - /** @brief Helper function for explain_filename @@ -2125,7 +2113,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ((access(path, F_OK) && ha_create_table_from_engine(thd, db, alias)) || (!drop_view && - mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE))) + dd_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE))) { // Table was not found on disk and table can't be created from engine if (if_exists) @@ -2145,7 +2133,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ if (frm_db_type == DB_TYPE_UNKNOWN) { - mysql_frm_type(thd, path, &frm_db_type); + dd_frm_type(thd, path, &frm_db_type); DBUG_PRINT("info", ("frm_db_type %d from %s", frm_db_type, path)); } table_type= ha_resolve_by_legacy_type(thd, frm_db_type); @@ -4454,10 +4442,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, char from[FN_REFLEN],tmp[FN_REFLEN+32]; const char **ext; MY_STAT stat_info; - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_OPEN_HAS_MDL_LOCK | + MYSQL_LOCK_IGNORE_TIMEOUT)); DBUG_ENTER("prepare_for_repair"); - uint reopen_for_repair_flags= (MYSQL_OPEN_IGNORE_FLUSH | - MYSQL_OPEN_HAS_MDL_LOCK); if (!(check_opt->sql_flags & TT_USEFRM)) DBUG_RETURN(0); @@ -4586,12 +4574,18 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, "Failed renaming data file"); goto end; } - if (mysql_truncate(thd, table_list, 1)) + if (dd_recreate_table(thd, table_list->db, table_list->table_name)) { error= send_check_errmsg(thd, table_list, "repair", "Failed generating table from .frm file"); goto end; } + /* + 'FALSE' for 'using_transactions' means don't postpone + invalidation till the end of a transaction, but do it + immediately. + */ + query_cache_invalidate3(thd, table_list, FALSE); if (mysql_file_rename(key_file_misc, tmp, from, MYF(MY_WME))) { error= send_check_errmsg(thd, table_list, "repair", @@ -4606,8 +4600,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Now we should be able to open the partially repaired table to finish the repair in the handler later on. */ - if (open_table(thd, table_list, thd->mem_root, - &ot_ctx_unused, reopen_for_repair_flags)) + if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) { error= send_check_errmsg(thd, table_list, "repair", "Failed to open partially repaired table"); @@ -4685,6 +4678,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, strxmov(table_name, db, ".", table->table_name, NullS); thd->open_options|= extra_open_options; table->lock_type= lock_type; + /* + To make code safe for re-execution we need to reset type of MDL + request as code below may change it. + To allow concurrent execution of read-only operations we acquire + weak metadata lock for them. + */ + table->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ? + MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ); /* open only one table from local list of command */ { TABLE_LIST *save_next_global, *save_next_local; @@ -4706,8 +4707,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (view_operator_func == NULL) table->required_type=FRMTYPE_TABLE; - open_error= open_and_lock_tables(thd, table, TRUE, - MYSQL_OPEN_TAKE_UPGRADABLE_MDL); + open_error= open_and_lock_tables(thd, table, TRUE, 0); thd->no_warnings_for_error= 0; table->next_global= save_next_global; table->next_local= save_next_local; @@ -4864,18 +4864,30 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, /* purecov: end */ } - /* Close all instances of the table to allow repair to rename files */ - if (lock_type == TL_WRITE && table->table->s->version) + /* + Close all instances of the table to allow MyISAM "repair" + to rename files. + @todo: This code does not close all instances of the table. + It only closes instances in other connections, but if this + connection has LOCK TABLE t1 a READ, t1 b WRITE, + both t1 instances will be kept open. + There is no need to execute this branch for InnoDB, which does + repair by recreate. There is no need to do it for OPTIMIZE, + which doesn't move files around. + Hence, this code should be moved to prepare_for_repair(), + and executed only for MyISAM engine. + */ + if (lock_type == TL_WRITE && !table->table->s->tmp_table) { if (wait_while_table_is_used(thd, table->table, HA_EXTRA_PREPARE_FOR_RENAME)) goto err; - DBUG_EXECUTE_IF("wait_in_mysql_admin_table", - wait_for_kill_signal(thd); - if (thd->killed) - goto err;); /* Flush entries in the query cache involving this table. */ query_cache_invalidate3(thd, table->table, 0); + /* + XXX: hack: switch off open_for_modify to skip the + flush that is made later in the execution flow. + */ open_for_modify= 0; } @@ -5053,6 +5065,7 @@ send_result_message: /* Clear the ticket released in close_thread_tables(). */ table->mdl_request.ticket= NULL; DEBUG_SYNC(thd, "ha_admin_open_ltable"); + table->mdl_request.set_type(MDL_SHARED_WRITE); if ((table->table= open_ltable(thd, table, lock_type, 0))) { result_code= table->table->file->ha_analyze(thd, check_opt); @@ -5134,20 +5147,21 @@ send_result_message: } if (table->table) { - if (fatal_error) - table->table->s->version=0; // Force close of table - else if (open_for_modify) + if (table->table->s->tmp_table) { - if (table->table->s->tmp_table) + if (open_for_modify) table->table->file->info(HA_STATUS_CONST); - else - { - TABLE_LIST *save_next_global= table->next_global; - table->next_global= 0; - close_cached_tables(thd, table, FALSE, FALSE); - table->next_global= save_next_global; - } - /* May be something modified consequently we have to invalidate cache */ + } + else if (open_for_modify || fatal_error) + { + mysql_mutex_lock(&LOCK_open); + tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, + table->db, table->table_name); + mysql_mutex_unlock(&LOCK_open); + /* + May be something modified. Consequently, we have to + invalidate the query cache. + */ query_cache_invalidate3(thd, table->table, 0); } } @@ -5388,7 +5402,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, char buf[2048]; String query(buf, sizeof(buf), system_charset_info); query.length(0); // Have to zero it since constructor doesn't - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); /* The condition avoids a crash as described in BUG#48506. Other @@ -5403,8 +5417,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, to work. The table will be closed by close_thread_table() at the end of this branch. */ - if (open_table(thd, table, thd->mem_root, &ot_ctx_unused, - MYSQL_OPEN_REOPEN)) + if (open_table(thd, table, thd->mem_root, &ot_ctx)) goto err; int result __attribute__((unused))= @@ -5416,14 +5429,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, goto err; DBUG_ASSERT(thd->open_tables == table->table); - mysql_mutex_lock(&LOCK_open); /* When opening the table, we ignored the locked tables (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table without risking to close some locked table. */ close_thread_table(thd, &thd->open_tables); - mysql_mutex_unlock(&LOCK_open); } } else // Case 1 @@ -5490,6 +5501,7 @@ mysql_discard_or_import_tablespace(THD *thd, not complain when we lock the table */ thd->tablespace_op= TRUE; + table_list->mdl_request.set_type(MDL_SHARED_WRITE); if (!(table=open_ltable(thd, table_list, TL_WRITE, 0))) { thd->tablespace_op=FALSE; @@ -6467,8 +6479,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, char reg_path[FN_REFLEN+1]; ha_rows copied,deleted; handlerton *old_db_type, *new_db_type, *save_old_db_type; - legacy_db_type table_type; - frm_type_enum frm_type; enum_alter_table_change_level need_copy_table= ALTER_TABLE_METADATA_ONLY; #ifdef WITH_PARTITION_STORAGE_ENGINE uint fast_alter_partition= 0; @@ -6548,85 +6558,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Conditionally writes to binlog. */ DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, alter_info->tablespace_op)); - strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, - "/", table_name, reg_ext, NullS); - (void) unpack_filename(new_name_buff, new_name_buff); - /* - If this is just a rename of a view, short cut to the - following scenario: 1) lock LOCK_open 2) do a RENAME - 2) unlock LOCK_open. - This is a copy-paste added to make sure - ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled - as an independent branch in mysql_execute_command. The need - for a copy-paste arose because the main code flow of ALTER TABLE - ... RENAME tries to use open_ltable, which does not work for views - (open_ltable was never modified to merge table lists of child tables - into the main table list, like open_tables does). - This code is wrong and will be removed, please do not copy. - */ - frm_type= mysql_frm_type(thd, new_name_buff, &table_type); - /* Rename a view */ - /* Sic: there is a race here */ - if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME)) - { - /* - The following branch handles "ALTER VIEW v1 /no arguments/;" - This feature is not documented one. - However, before "OPTIMIZE TABLE t1;" was implemented, - ALTER TABLE with no alter_specifications was used to force-rebuild - the table. That's why this grammar is allowed. That's why we ignore - it for views. So just do nothing in such a case. - */ - if (!new_name) - { - my_ok(thd); - DBUG_RETURN(FALSE); - } - - /* - Avoid problems with a rename on a table that we have locked or - if the user is trying to to do this in a transcation context - */ - - if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) - { - my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); - DBUG_RETURN(TRUE); - } - - if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE)) - DBUG_RETURN(TRUE); - if (lock_table_names(thd, table_list)) - { - error= 1; - goto view_err; - } - - mysql_mutex_lock(&LOCK_open); - - if (!do_rename(thd, table_list, new_db, new_name, new_name, 1)) - { - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query(), thd->query_length(), - FALSE, TRUE, FALSE, 0); - if ((error= mysql_bin_log.write(&qinfo))) - goto view_err_unlock; - } - my_ok(thd); - } - -view_err_unlock: - mysql_mutex_unlock(&LOCK_open); - unlock_table_names(thd); - -view_err: - thd->global_read_lock.start_waiting_global_read_lock(thd); - DBUG_RETURN(error); - } - /* Code below can handle only base tables so ensure that we won't open a view. @@ -6637,8 +6568,7 @@ view_err: Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info); - error= open_and_lock_tables(thd, table_list, FALSE, - MYSQL_OPEN_TAKE_UPGRADABLE_MDL, + error= open_and_lock_tables(thd, table_list, FALSE, 0, &alter_prelocking_strategy); if (error) @@ -7241,14 +7171,14 @@ view_err: { if (table->s->tmp_table) { - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_LOCK_IGNORE_TIMEOUT)); TABLE_LIST tbl; bzero((void*) &tbl, sizeof(tbl)); tbl.db= new_db; tbl.table_name= tbl.alias= tmp_name; /* Table is in thd->temporary_tables */ - (void) open_table(thd, &tbl, thd->mem_root, &ot_ctx_unused, - MYSQL_OPEN_IGNORE_FLUSH); + (void) open_table(thd, &tbl, thd->mem_root, &ot_ctx); new_table= tbl.table; } else @@ -7527,7 +7457,7 @@ view_err: To do this we need to obtain a handler object for it. NO need to tamper with MERGE tables. The real open is done later. */ - Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); TABLE *t_table; if (new_name != table_name || new_db != db) { @@ -7547,8 +7477,7 @@ view_err: */ table_list->mdl_request.ticket= mdl_ticket; } - if (open_table(thd, table_list, thd->mem_root, - &ot_ctx_unused, MYSQL_OPEN_REOPEN)) + if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) { goto err_with_mdl; } @@ -7559,9 +7488,7 @@ view_err: create_info); DBUG_ASSERT(thd->open_tables == t_table); - mysql_mutex_lock(&LOCK_open); close_thread_table(thd, &thd->open_tables); - mysql_mutex_unlock(&LOCK_open); table_list->table= 0; if (error) @@ -7940,6 +7867,10 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list) table_list->table= NULL; /* Same applies to MDL ticket. */ table_list->mdl_request.ticket= NULL; + /* Set lock type which is appropriate for ALTER TABLE. */ + table_list->lock_type= TL_READ_NO_INSERT; + /* Same applies to MDL request. */ + table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE); bzero((char*) &create_info, sizeof(create_info)); create_info.row_type=ROW_TYPE_NOT_USED; diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 43d203e6498..48fd5f9dff8 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -45,7 +45,6 @@ static const char *lock_descriptions[] = /* TL_READ_HIGH_PRIORITY */ "High priority read lock", /* TL_READ_NO_INSERT */ "Read lock without concurrent inserts", /* TL_WRITE_ALLOW_WRITE */ "Write lock that allows other writers", - /* TL_WRITE_ALLOW_READ */ "Write lock, but allow reading", /* TL_WRITE_CONCURRENT_INSERT */ "Concurrent insert lock", /* TL_WRITE_DELAYED */ "Lock used by delayed insert", /* TL_WRITE_DEFAULT */ NULL, diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index c3266b5cbe2..2f084c369b6 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -489,8 +489,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) else { tables->table= open_n_lock_single_table(thd, tables, - TL_WRITE_ALLOW_READ, - MYSQL_OPEN_TAKE_UPGRADABLE_MDL); + TL_READ_NO_INSERT, 0); if (! tables->table) goto end; tables->table->use_all_columns(); @@ -1666,7 +1665,8 @@ bool add_table_for_trigger(THD *thd, DBUG_RETURN(TRUE); *table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str, - tbl_name.str, TL_IGNORE); + tbl_name.str, TL_IGNORE, + MDL_SHARED_NO_WRITE); DBUG_RETURN(*table ? FALSE : TRUE); } diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc new file mode 100644 index 00000000000..901ab8e987d --- /dev/null +++ b/sql/sql_truncate.cc @@ -0,0 +1,485 @@ +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "sql_truncate.h" +#include "sql_priv.h" +#include "transaction.h" +#include "debug_sync.h" +#include "records.h" // READ_RECORD +#include "table.h" // TABLE +#include "sql_class.h" // THD +#include "sql_base.h" // open_and_lock_tables +#include "sql_table.h" // write_bin_log +#include "sql_handler.h" // mysql_ha_rm_tables +#include "datadict.h" // dd_recreate_table() +#include "lock.h" // MYSQL_OPEN_TEMPORARY_ONLY + + +/* + Delete all rows of a locked table. + + @param thd Thread context. + @param table_list Table list element for the table. + @param rows_deleted Whether rows might have been deleted. + + @retval FALSE Success. + @retval TRUE Error. +*/ + +static bool +delete_all_rows(THD *thd, TABLE *table) +{ + int error; + READ_RECORD info; + bool is_bulk_delete; + bool some_rows_deleted= FALSE; + bool save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + DBUG_ENTER("delete_all_rows"); + + /* Replication of truncate table must be statement based. */ + thd->clear_current_stmt_binlog_format_row(); + + /* + Update handler statistics (e.g. table->file->stats.records). + Might be used by the storage engine to aggregate information + necessary to allow deletion. Currently, this seems to be + meaningful only to the archive storage engine, which uses + the info method to set the number of records. Although + archive does not support deletion, it becomes necessary in + order to return a error if the table is not empty. + */ + error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + if (error && error != HA_ERR_WRONG_COMMAND) + { + table->file->print_error(error, MYF(0)); + goto end; + } + + /* + Attempt to delete all rows in the table. + If it is unsupported, switch to row by row deletion. + */ + if (! (error= table->file->ha_delete_all_rows())) + goto end; + + if (error != HA_ERR_WRONG_COMMAND) + { + /* + If a transactional engine fails in the middle of deletion, + we expect it to be able to roll it back. Some reasons + for the engine to fail would be media failure or corrupted + data dictionary (i.e. in case of a partitioned table). We + have sufficiently strong metadata locks to rule out any + potential deadlocks. + + If a non-transactional engine fails here (that would + not be MyISAM, since MyISAM does TRUNCATE by recreate), + and binlog is on, replication breaks, since nothing gets + written to the binary log. (XXX: is this a bug?) + */ + table->file->print_error(error, MYF(0)); + goto end; + } + + /* + A workaround for Bug#53696 "Performance schema engine violates the + PSEA API by calling my_error()". + */ + if (thd->is_error()) + goto end; + + /* Handler didn't support fast delete. Delete rows one by one. */ + + init_read_record(&info, thd, table, NULL, TRUE, TRUE, FALSE); + + /* + Start bulk delete. If the engine does not support it, go on, + it's not an error. + */ + is_bulk_delete= ! table->file->start_bulk_delete(); + + table->mark_columns_needed_for_delete(); + + while (!(error= info.read_record(&info)) && !thd->killed) + { + if ((error= table->file->ha_delete_row(table->record[0]))) + { + table->file->print_error(error, MYF(0)); + break; + } + + some_rows_deleted= TRUE; + } + + /* HA_ERR_END_OF_FILE */ + if (error == -1) + error= 0; + + /* Close down the bulk delete. */ + if (is_bulk_delete) + { + int bulk_delete_error= table->file->end_bulk_delete(); + if (bulk_delete_error && !error) + { + table->file->print_error(bulk_delete_error, MYF(0)); + error= bulk_delete_error; + } + } + + end_read_record(&info); + + /* + Regardless of the error status, the query must be written to the + binary log if rows of the table is non-transactional. + */ + if (some_rows_deleted && !table->file->has_transactions()) + { + thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction.all.modified_non_trans_table= TRUE; + } + + if (error || thd->killed) + goto end; + + /* Truncate resets the auto-increment counter. */ + error= table->file->ha_reset_auto_increment(0); + if (error) + { + if (error != HA_ERR_WRONG_COMMAND) + table->file->print_error(error, MYF(0)); + else + error= 0; + } + +end: + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); + + DBUG_RETURN(error); +} + + +/* + Close and recreate a temporary table. In case of success, + write truncate statement into the binary log if in statement + mode. + + @param thd Thread context. + @param table The temporary table. + + @retval FALSE Success. + @retval TRUE Error. +*/ + +static bool recreate_temporary_table(THD *thd, TABLE *table) +{ + bool error= TRUE; + TABLE_SHARE *share= table->s; + HA_CREATE_INFO create_info; + handlerton *table_type= table->s->db_type(); + DBUG_ENTER("recreate_temporary_table"); + + memset(&create_info, 0, sizeof(create_info)); + + table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK); + + /* Don't free share. */ + close_temporary_table(thd, table, FALSE, FALSE); + + /* + We must use share->normalized_path.str since for temporary tables it + differs from what dd_recreate_table() would generate based + on table and schema names. + */ + ha_create_table(thd, share->normalized_path.str, share->db.str, + share->table_name.str, &create_info, 1); + + if (open_temporary_table(thd, share->path.str, share->db.str, + share->table_name.str, 1)) + { + error= FALSE; + thd->thread_specific_used= TRUE; + } + else + rm_temporary_table(table_type, share->path.str); + + free_table_share(share); + my_free(table, MYF(0)); + + DBUG_RETURN(error); +} + + +/* + Handle opening and locking if a base table for truncate. + + @param[in] thd Thread context. + @param[in] table_ref Table list element for the table to + be truncated. + @param[out] hton_can_recreate Set to TRUE if table can be dropped + and recreated. + @param[out] ticket_downgrade Set if a lock must be downgraded after + truncate is done. + + @retval FALSE Success. + @retval TRUE Error. +*/ + +static bool open_and_lock_table_for_truncate(THD *thd, TABLE_LIST *table_ref, + bool *hton_can_recreate, + MDL_ticket **ticket_downgrade) +{ + TABLE *table= NULL; + MDL_ticket *mdl_ticket= NULL; + DBUG_ENTER("open_and_lock_table_for_truncate"); + + /* + Before doing anything else, acquire a metadata lock on the table, + or ensure we have one. We don't use open_and_lock_tables() + right away because we want to be able to truncate (and recreate) + corrupted tables, those that we can't fully open. + + MySQL manual documents that TRUNCATE can be used to repair a + damaged table, i.e. a table that can not be fully "opened". + In particular MySQL manual says: As long as the table format + file tbl_name.frm is valid, the table can be re-created as + an empty table with TRUNCATE TABLE, even if the data or index + files have become corrupted. + */ + if (thd->locked_tables_mode) + { + if (!(table= find_table_for_mdl_upgrade(thd->open_tables, table_ref->db, + table_ref->table_name, FALSE))) + DBUG_RETURN(TRUE); + + *hton_can_recreate= ha_check_storage_engine_flag(table->s->db_type(), + HTON_CAN_RECREATE); + } + else + { + /* + Even though we could use the previous execution branch here just as + well, we must not try to open the table: + */ + MDL_request mdl_global_request, mdl_request; + MDL_request_list mdl_requests; + + mdl_global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE); + mdl_request.init(MDL_key::TABLE, table_ref->db, table_ref->table_name, + MDL_SHARED_NO_READ_WRITE); + mdl_requests.push_front(&mdl_request); + mdl_requests.push_front(&mdl_global_request); + + if (thd->mdl_context.acquire_locks(&mdl_requests, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(TRUE); + + mdl_ticket= mdl_request.ticket; + + if (dd_check_storage_engine_flag(thd, table_ref->db, table_ref->table_name, + HTON_CAN_RECREATE, hton_can_recreate)) + DBUG_RETURN(TRUE); + } + + DEBUG_SYNC(thd, "lock_table_for_truncate"); + + if (*hton_can_recreate) + { + /* + Acquire an exclusive lock. The storage engine can recreate the + table only if there are no references to it from anywhere, i.e. + no cached TABLE in the table cache. To remove the table from the + cache we need an exclusive lock. + */ + if (thd->locked_tables_mode) + { + if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + DBUG_RETURN(TRUE); + *ticket_downgrade= table->mdl_ticket; + close_all_tables_for_name(thd, table->s, FALSE); + } + else + { + ulong timeout= thd->variables.lock_wait_timeout; + if (thd->mdl_context.upgrade_shared_lock_to_exclusive(mdl_ticket, timeout)) + DBUG_RETURN(TRUE); + mysql_mutex_lock(&LOCK_open); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_ref->db, + table_ref->table_name); + mysql_mutex_unlock(&LOCK_open); + } + } + else + { + /* + Can't recreate, we must mechanically delete all rows in + the table. Our metadata lock guarantees that no transaction + is reading or writing into the table. Yet, to open a write + cursor we need a thr_lock lock. Use open_and_lock_tables() + to do the necessary job. + */ + + /* Allow to open base tables only. */ + table_ref->required_type= FRMTYPE_TABLE; + /* We don't need to load triggers. */ + DBUG_ASSERT(table_ref->trg_event_map == 0); + /* Work around partition parser rules using alter table's. */ + if (thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION) + { + table_ref->lock_type= TL_WRITE; + table_ref->mdl_request.set_type(MDL_SHARED_WRITE); + } + /* Ensure proper lock types (e.g. from the parser). */ + DBUG_ASSERT(table_ref->lock_type == TL_WRITE); + DBUG_ASSERT(table_ref->mdl_request.type == MDL_SHARED_WRITE); + + /* + Open the table as it will handle some required preparations. + Ignore pending FLUSH TABLES since we don't want to release + the MDL lock taken above and otherwise there is no way to + wait for FLUSH TABLES in deadlock-free fashion. + */ + if (open_and_lock_tables(thd, table_ref, FALSE, + MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_OPEN_SKIP_TEMPORARY)) + DBUG_RETURN(TRUE); + } + + DBUG_RETURN(FALSE); +} + + +/* + Optimized delete of all rows by doing a full generate of the table. + + @remark Will work even if the .MYI and .MYD files are destroyed. + In other words, it works as long as the .FRM is intact and + the engine supports re-create. + + @param thd Thread context. + @param table_ref Table list element for the table to be truncated. + + @retval FALSE Success. + @retval TRUE Error. +*/ + +bool mysql_truncate_table(THD *thd, TABLE_LIST *table_ref) +{ + TABLE *table; + bool error= TRUE, binlog_stmt; + MDL_ticket *mdl_ticket= NULL; + DBUG_ENTER("mysql_truncate_table"); + + /* Remove tables from the HANDLER's hash. */ + mysql_ha_rm_tables(thd, table_ref); + + /* If it is a temporary table, no need to take locks. */ + if ((table= find_temporary_table(thd, table_ref))) + { + /* In RBR, the statement is not binlogged if the table is temporary. */ + binlog_stmt= !thd->is_current_stmt_binlog_format_row(); + + /* Note that a temporary table cannot be partitioned. */ + if (ha_check_storage_engine_flag(table->s->db_type(), HTON_CAN_RECREATE)) + { + if ((error= recreate_temporary_table(thd, table))) + binlog_stmt= FALSE; /* No need to binlog failed truncate-by-recreate. */ + + DBUG_ASSERT(! thd->transaction.stmt.modified_non_trans_table); + } + else + { + /* + The engine does not support truncate-by-recreate. Open the + table and delete all rows. In such a manner this can in fact + open several tables if it's a temporary MyISAMMRG table. + */ + if (open_and_lock_tables(thd, table_ref, FALSE, + MYSQL_OPEN_TEMPORARY_ONLY)) + DBUG_RETURN(TRUE); + + error= delete_all_rows(thd, table_ref->table); + } + + /* + No need to invalidate the query cache, queries with temporary + tables are not in the cache. No need to write to the binary + log a failed row-by-row delete even if under RBR as the table + might not exist on the slave. + */ + } + else /* It's not a temporary table. */ + { + bool hton_can_recreate; + + if (open_and_lock_table_for_truncate(thd, table_ref, + &hton_can_recreate, &mdl_ticket)) + DBUG_RETURN(TRUE); + + if (hton_can_recreate) + { + /* + The storage engine can truncate the table by creating an + empty table with the same structure. + */ + error= dd_recreate_table(thd, table_ref->db, table_ref->table_name); + + if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd)) + thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); + + /* No need to binlog a failed truncate-by-recreate. */ + binlog_stmt= !error; + } + else + { + error= delete_all_rows(thd, table_ref->table); + + /* + Regardless of the error status, the query must be written to the + binary log if rows of a non-transactional table were deleted. + */ + binlog_stmt= !error || thd->transaction.stmt.modified_non_trans_table; + } + + query_cache_invalidate3(thd, table_ref, FALSE); + } + + /* DDL is logged in statement format, regardless of binlog format. */ + if (binlog_stmt) + error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); + + /* + All effects of a TRUNCATE TABLE operation are rolled back if a row + by row deletion fails. Otherwise, it is automatically committed at + the end. + */ + if (error) + { + trans_rollback_stmt(thd); + trans_rollback(thd); + } + + /* + A locked table ticket was upgraded to a exclusive lock. After the + the query has been written to the binary log, downgrade the lock + to a shared one. + */ + if (mdl_ticket) + mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE); + + DBUG_PRINT("exit", ("error: %d", error)); + DBUG_RETURN(test(error)); +} + diff --git a/sql/sql_truncate.h b/sql/sql_truncate.h new file mode 100644 index 00000000000..11c07c7187c --- /dev/null +++ b/sql/sql_truncate.h @@ -0,0 +1,23 @@ +#ifndef SQL_TRUNCATE_INCLUDED +#define SQL_TRUNCATE_INCLUDED +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +class THD; +struct TABLE_LIST; + +bool mysql_truncate_table(THD *thd, TABLE_LIST *table_ref); + +#endif diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 9ec17a67533..3d197303fb1 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -248,7 +248,7 @@ void udf_init() if (error > 0) sql_print_error("Got unknown error: %d", my_errno); end_read_record(&read_record_info); - new_thd->version--; // Force close to free memory + table->m_needs_reopen= TRUE; // Force close to free memory end: close_thread_tables(new_thd); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8cb4df36cd5..69abe70e863 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -32,6 +32,7 @@ #include "sp.h" #include "sp_head.h" #include "sp_cache.h" +#include "datadict.h" // dd_frm_type() #define MD5_BUFF_LENGTH 33 @@ -433,7 +434,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_strategy= TABLE_LIST::OPEN_STUB; - view->lock_strategy= TABLE_LIST::EXCLUSIVE_MDL; + view->lock_strategy= TABLE_LIST::OTLS_NONE; view->open_type= OT_BASE_ONLY; if (open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) @@ -1663,7 +1664,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) view->db, view->table_name, reg_ext, 0); if (access(path, F_OK) || - FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, ¬_used))) + FRMTYPE_VIEW != (type= dd_frm_type(thd, path, ¬_used))) { char name[FN_REFLEN]; my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); @@ -1742,54 +1743,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) /* - Check type of .frm if we are not going to parse it - - SYNOPSIS - mysql_frm_type() - path path to file - - RETURN - FRMTYPE_ERROR error - FRMTYPE_TABLE table - FRMTYPE_VIEW view -*/ - -frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) -{ - File file; - uchar header[10]; //"TYPE=VIEW\n" it is 10 characters - size_t error; - DBUG_ENTER("mysql_frm_type"); - - *dbt= DB_TYPE_UNKNOWN; - - if ((file= mysql_file_open(key_file_frm, - path, O_RDONLY | O_SHARE, MYF(0))) < 0) - DBUG_RETURN(FRMTYPE_ERROR); - error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)); - mysql_file_close(file, MYF(MY_WME)); - - if (error) - DBUG_RETURN(FRMTYPE_ERROR); - if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header))) - DBUG_RETURN(FRMTYPE_VIEW); - - /* - This is just a check for DB_TYPE. We'll return default unknown type - if the following test is true (arg #3). This should not have effect - on return value from this function (default FRMTYPE_TABLE) - */ - if (header[0] != (uchar) 254 || header[1] != 1 || - (header[2] != FRM_VER && header[2] != FRM_VER+1 && - (header[2] < FRM_VER+3 || header[2] > FRM_VER+4))) - DBUG_RETURN(FRMTYPE_TABLE); - - *dbt= (enum legacy_db_type) (uint) *(header + 3); - DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table -} - - -/* check of key (primary or unique) presence in updatable view SYNOPSIS diff --git a/sql/sql_view.h b/sql/sql_view.h index 7d06abb9068..c15ecffccb8 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -43,8 +43,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view); bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view); -frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt); - int view_checksum(THD *thd, TABLE_LIST *view); extern TYPELIB updatable_views_with_limit_typelib; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2d5f7df6009..1c673f4ca42 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -696,7 +696,8 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table) lex->sql_command= SQLCOM_CREATE_INDEX; if (!lex->current_select->add_table_to_list(lex->thd, table, NULL, TL_OPTION_UPDATING, - TL_WRITE_ALLOW_READ)) + TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) return TRUE; lex->alter_info.reset(); lex->alter_info.flags= ALTER_ADD_INDEX; @@ -765,6 +766,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, enum index_hint_type index_hint; enum enum_filetype filetype; enum Foreign_key::fk_option m_fk_option; + enum enum_yes_no_unknown m_yes_no_unk; Diag_condition_item_name diag_condition_item_name; } @@ -1432,12 +1434,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); table_option opt_if_not_exists opt_no_write_to_binlog opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option - start_transaction_opts opt_chain opt_release + start_transaction_opts union_opt select_derived_init option_type2 opt_natural_language_mode opt_query_expansion opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt +%type <m_yes_no_unk> + opt_chain opt_release + %type <m_fk_option> delete_option @@ -2022,7 +2027,7 @@ create: lex->sql_command= SQLCOM_CREATE_TABLE; if (!lex->select_lex.add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, - TL_WRITE)) + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; lex->alter_info.reset(); lex->col_list.empty(); @@ -4212,7 +4217,8 @@ create2: lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE; src_table= lex->select_lex.add_table_to_list(thd, $2, NULL, 0, - TL_READ); + TL_READ, + MDL_SHARED_READ); if (! src_table) MYSQL_YYABORT; /* CREATE TABLE ... LIKE is not allowed for views. */ @@ -4226,7 +4232,8 @@ create2: lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE; src_table= lex->select_lex.add_table_to_list(thd, $3, NULL, 0, - TL_READ); + TL_READ, + MDL_SHARED_READ); if (! src_table) MYSQL_YYABORT; /* CREATE TABLE ... LIKE is not allowed for views. */ @@ -6153,7 +6160,8 @@ alter: lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING, - TL_WRITE_ALLOW_READ)) + TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; lex->col_list.empty(); lex->select_lex.init_order(); @@ -6845,6 +6853,8 @@ checksum: { LEX *lex=Lex; lex->sql_command = SQLCOM_CHECKSUM; + /* Will be overriden during execution. */ + YYPS->m_lock_type= TL_UNLOCK; } table_list opt_checksum_type {} @@ -6864,6 +6874,8 @@ repair: lex->no_write_to_binlog= $2; lex->check_opt.init(); lex->alter_info.reset(); + /* Will be overriden during execution. */ + YYPS->m_lock_type= TL_UNLOCK; } table_list opt_mi_repair_type {} @@ -6893,6 +6905,8 @@ analyze: lex->no_write_to_binlog= $2; lex->check_opt.init(); lex->alter_info.reset(); + /* Will be overriden during execution. */ + YYPS->m_lock_type= TL_UNLOCK; } table_list {} @@ -6919,6 +6933,8 @@ check: lex->sql_command = SQLCOM_CHECK; lex->check_opt.init(); lex->alter_info.reset(); + /* Will be overriden during execution. */ + YYPS->m_lock_type= TL_UNLOCK; } table_list opt_mi_check_type {} @@ -6951,6 +6967,8 @@ optimize: lex->no_write_to_binlog= $2; lex->check_opt.init(); lex->alter_info.reset(); + /* Will be overriden during execution. */ + YYPS->m_lock_type= TL_UNLOCK; } table_list {} @@ -6999,9 +7017,9 @@ table_to_table: LEX *lex=Lex; SELECT_LEX *sl= lex->current_select; if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING, - TL_IGNORE) || + TL_IGNORE, MDL_EXCLUSIVE) || !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING, - TL_IGNORE)) + TL_IGNORE, MDL_EXCLUSIVE)) MYSQL_YYABORT; } ; @@ -7032,7 +7050,8 @@ keycache_list: assign_to_keycache: table_ident cache_keys_spec { - if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ, + if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ, + MDL_SHARED_READ, Select->pop_index_hints())) MYSQL_YYABORT; } @@ -7042,6 +7061,7 @@ assign_to_keycache_parts: table_ident adm_partition cache_keys_spec { if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ, + MDL_SHARED_READ, Select->pop_index_hints())) MYSQL_YYABORT; } @@ -7077,6 +7097,7 @@ preload_keys: table_ident cache_keys_spec opt_ignore_leaves { if (!Select->add_table_to_list(YYTHD, $1, NULL, $3, TL_READ, + MDL_SHARED_READ, Select->pop_index_hints())) MYSQL_YYABORT; } @@ -7086,6 +7107,7 @@ preload_keys_parts: table_ident adm_partition cache_keys_spec opt_ignore_leaves { if (!Select->add_table_to_list(YYTHD, $1, NULL, $4, TL_READ, + MDL_SHARED_READ, Select->pop_index_hints())) MYSQL_YYABORT; } @@ -9217,6 +9239,7 @@ table_factor: if (!($$= Select->add_table_to_list(YYTHD, $2, $3, Select->get_table_join_options(), YYPS->m_lock_type, + YYPS->m_mdl_type, Select->pop_index_hints()))) MYSQL_YYABORT; Select->add_joined_table($$); @@ -9288,7 +9311,7 @@ table_factor: MYSQL_YYABORT; if (!($$= sel->add_table_to_list(lex->thd, new Table_ident(unit), $5, 0, - TL_READ))) + TL_READ, MDL_SHARED_READ))) MYSQL_YYABORT; sel->add_joined_table($$); @@ -10123,13 +10146,17 @@ do: */ drop: - DROP opt_temporary table_or_tables if_exists table_list opt_restrict + DROP opt_temporary table_or_tables if_exists { LEX *lex=Lex; lex->sql_command = SQLCOM_DROP_TABLE; lex->drop_temporary= $2; lex->drop_if_exists= $4; + YYPS->m_lock_type= TL_UNLOCK; + YYPS->m_mdl_type= MDL_EXCLUSIVE; } + table_list opt_restrict + {} | DROP INDEX_SYM ident ON table_ident {} { LEX *lex=Lex; @@ -10142,7 +10169,8 @@ drop: lex->alter_info.drop_list.push_back(ad); if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL, TL_OPTION_UPDATING, - TL_WRITE_ALLOW_READ)) + TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; } | DROP DATABASE if_exists ident @@ -10212,12 +10240,16 @@ drop: { Lex->sql_command = SQLCOM_DROP_USER; } - | DROP VIEW_SYM if_exists table_list opt_restrict + | DROP VIEW_SYM if_exists { LEX *lex= Lex; lex->sql_command= SQLCOM_DROP_VIEW; lex->drop_if_exists= $3; + YYPS->m_lock_type= TL_UNLOCK; + YYPS->m_mdl_type= MDL_EXCLUSIVE; } + table_list opt_restrict + {} | DROP EVENT_SYM if_exists sp_name { Lex->drop_if_exists= $3; @@ -10258,7 +10290,10 @@ table_list: table_name: table_ident { - if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING)) + if (!Select->add_table_to_list(YYTHD, $1, NULL, + TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -10273,7 +10308,8 @@ table_alias_ref: { if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - YYPS->m_lock_type)) + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -10555,6 +10591,8 @@ delete: lex->sql_command= SQLCOM_DELETE; mysql_init_select(lex); YYPS->m_lock_type= TL_WRITE_DEFAULT; + YYPS->m_mdl_type= MDL_SHARED_WRITE; + lex->ignore= 0; lex->select_lex.init_order(); } @@ -10565,9 +10603,11 @@ single_multi: FROM table_ident { if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING, - YYPS->m_lock_type)) + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; YYPS->m_lock_type= TL_READ_DEFAULT; + YYPS->m_mdl_type= MDL_SHARED_READ; } where_clause opt_order_clause delete_limit_clause {} @@ -10575,6 +10615,7 @@ single_multi: { mysql_init_multi_delete(Lex); YYPS->m_lock_type= TL_READ_DEFAULT; + YYPS->m_mdl_type= MDL_SHARED_READ; } FROM join_table_list where_clause { @@ -10585,6 +10626,7 @@ single_multi: { mysql_init_multi_delete(Lex); YYPS->m_lock_type= TL_READ_DEFAULT; + YYPS->m_mdl_type= MDL_SHARED_READ; } USING join_table_list where_clause { @@ -10608,7 +10650,8 @@ table_wild_one: ti, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - YYPS->m_lock_type)) + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } | ident '.' ident opt_wild @@ -10620,7 +10663,8 @@ table_wild_one: ti, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - YYPS->m_lock_type)) + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -10642,7 +10686,7 @@ opt_delete_option: ; truncate: - TRUNCATE_SYM opt_table_sym table_name + TRUNCATE_SYM opt_table_sym { LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; @@ -10650,7 +10694,11 @@ truncate: lex->select_lex.options= 0; lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; lex->select_lex.init_order(); + YYPS->m_lock_type= TL_WRITE; + YYPS->m_mdl_type= MDL_SHARED_WRITE; } + table_name + {} ; opt_table_sym: @@ -11134,7 +11182,15 @@ flush: flush_options: table_or_tables - { Lex->type|= REFRESH_TABLES; } + { + Lex->type|= REFRESH_TABLES; + /* + Set type of metadata and table locks for + FLUSH TABLES table_list WITH READ LOCK. + */ + YYPS->m_lock_type= TL_READ_NO_INSERT; + YYPS->m_mdl_type= MDL_EXCLUSIVE; + } opt_table_list {} opt_with_read_lock {} | flush_options_list @@ -11298,7 +11354,7 @@ load: { LEX *lex=Lex; if (!Select->add_table_to_list(YYTHD, $12, NULL, TL_OPTION_UPDATING, - $4)) + $4, MDL_SHARED_WRITE)) MYSQL_YYABORT; lex->field_list.empty(); lex->update_list.empty(); @@ -13004,10 +13060,14 @@ table_lock: table_ident opt_table_alias lock_option { thr_lock_type lock_type= (thr_lock_type) $3; - if (!Select->add_table_to_list(YYTHD, $1, $2, 0, lock_type)) + bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE); + if (!Select->add_table_to_list(YYTHD, $1, $2, 0, lock_type, + (lock_for_write ? + MDL_SHARED_NO_READ_WRITE : + MDL_SHARED_READ))) MYSQL_YYABORT; /* If table is to be write locked, protect from a impending GRL. */ - if (lock_type >= TL_WRITE_ALLOW_WRITE) + if (lock_for_write) Lex->protect_against_global_read_lock= TRUE; } ; @@ -13543,16 +13603,16 @@ opt_work: opt_chain: /* empty */ - { $$= (YYTHD->variables.completion_type == 1); } - | AND_SYM NO_SYM CHAIN_SYM { $$=0; } - | AND_SYM CHAIN_SYM { $$=1; } + { $$= TVL_UNKNOWN; } + | AND_SYM NO_SYM CHAIN_SYM { $$= TVL_NO; } + | AND_SYM CHAIN_SYM { $$= TVL_YES; } ; opt_release: /* empty */ - { $$= (YYTHD->variables.completion_type == 2); } - | RELEASE_SYM { $$=1; } - | NO_SYM RELEASE_SYM { $$=0; } + { $$= TVL_UNKNOWN; } + | RELEASE_SYM { $$= TVL_YES; } + | NO_SYM RELEASE_SYM { $$= TVL_NO; } ; opt_savepoint: @@ -13565,7 +13625,9 @@ commit: { LEX *lex=Lex; lex->sql_command= SQLCOM_COMMIT; - lex->tx_chain= $3; + /* Don't allow AND CHAIN RELEASE. */ + MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES); + lex->tx_chain= $3; lex->tx_release= $4; } ; @@ -13575,7 +13637,9 @@ rollback: { LEX *lex=Lex; lex->sql_command= SQLCOM_ROLLBACK; - lex->tx_chain= $3; + /* Don't allow AND CHAIN RELEASE. */ + MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES); + lex->tx_chain= $3; lex->tx_release= $4; } | ROLLBACK_SYM opt_work @@ -13762,6 +13826,7 @@ query_expression_option: if (check_simple_select()) MYSQL_YYABORT; YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; + YYPS->m_mdl_type= MDL_SHARED_READ; Select->options|= SELECT_HIGH_PRIORITY; } | DISTINCT { Select->options|= SELECT_DISTINCT; } @@ -13891,7 +13956,10 @@ view_tail: LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; /* first table in list is target VIEW name */ - if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING)) + if (!lex->select_lex.add_table_to_list(thd, $3, NULL, + TL_OPTION_UPDATING, + TL_IGNORE, + MDL_EXCLUSIVE)) MYSQL_YYABORT; } view_list_opt AS view_select @@ -14031,7 +14099,8 @@ trigger_tail: if (!lex->select_lex.add_table_to_list(YYTHD, $9, (LEX_STRING*) 0, TL_OPTION_UPDATING, - TL_IGNORE)) + TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; } ; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 856f4c6f771..7eb9a72273b 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2029,24 +2029,38 @@ static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var) return FALSE; } -/* - If one doesn't use the SESSION modifier, the isolation level - is only active for the next command. -*/ -static bool fix_tx_isolation(sys_var *self, THD *thd, enum_var_type type) + +bool Sys_var_tx_isolation::session_update(THD *thd, set_var *var) { - if (type == OPT_SESSION) - thd->session_tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation; - return false; + if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var)) + return TRUE; + if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction()) + { + /* + Update the isolation level of the next transaction. + I.e. if one did: + COMMIT; + SET SESSION ISOLATION LEVEL ... + BEGIN; <-- this transaction has the new isolation + Note, that in case of: + COMMIT; + SET TRANSACTION ISOLATION LEVEL ... + SET SESSION ISOLATION LEVEL ... + BEGIN; <-- the session isolation level is used, not the + result of SET TRANSACTION statement. + */ + thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value; + } + return FALSE; } + // NO_CMD_LINE - different name of the option -static Sys_var_enum Sys_tx_isolation( +static Sys_var_tx_isolation Sys_tx_isolation( "tx_isolation", "Default transaction isolation level", SESSION_VAR(tx_isolation), NO_CMD_LINE, tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation), - ON_UPDATE(fix_tx_isolation)); + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation)); static Sys_var_ulonglong Sys_tmp_table_size( "tmp_table_size", diff --git a/sql/sys_vars.h b/sql/sys_vars.h index c4855ef4fd3..fbc48573487 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -1599,6 +1599,22 @@ public: { return type != STRING_RESULT; } }; + +class Sys_var_tx_isolation: public Sys_var_enum +{ +public: + Sys_var_tx_isolation(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], uint def_val, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func) + :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, + values, def_val, lock, binlog_status_arg, on_check_func) + {} + virtual bool session_update(THD *thd, set_var *var); +}; + /**************************************************************************** Used templates ****************************************************************************/ diff --git a/sql/table.cc b/sql/table.cc index 3143db78520..dbd657bee67 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2770,9 +2770,10 @@ bool check_db_name(LEX_STRING *org_name) returns 1 on error */ -bool check_table_name(const char *name, uint length, bool check_for_path_chars) +bool check_table_name(const char *name, size_t length, bool check_for_path_chars) { - uint name_length= 0; // name length in symbols + // name length in symbols + size_t name_length= 0; const char *end= name+length; if (!length || length > NAME_LEN) return 1; @@ -2805,18 +2806,19 @@ bool check_table_name(const char *name, uint length, bool check_for_path_chars) name_length++; } #if defined(USE_MB) && defined(USE_MB_IDENT) - return (last_char_is_space || name_length > NAME_CHAR_LEN) ; + return last_char_is_space || (name_length > NAME_CHAR_LEN); #else - return 0; + return FALSE; #endif } bool check_column_name(const char *name) { - uint name_length= 0; // name length in symbols + // name length in symbols + size_t name_length= 0; bool last_char_is_space= TRUE; - + while (*name) { #if defined(USE_MB) && defined(USE_MB_IDENT) @@ -2841,7 +2843,7 @@ bool check_column_name(const char *name) name_length++; } /* Error if empty or too long column name */ - return last_char_is_space || (uint) name_length > NAME_CHAR_LEN; + return last_char_is_space || (name_length > NAME_CHAR_LEN); } @@ -4676,13 +4678,6 @@ void TABLE_LIST::reinit_before_use(THD *thd) parent_embedding->nested_join->join_list.head() == embedded); mdl_request.ticket= NULL; - /* - Since we manipulate with the metadata lock type in open_table(), - we need to reset it to the parser default, to restore things back - to first-execution state. - */ - mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ? - MDL_SHARED_WRITE : MDL_SHARED_READ); } /* diff --git a/sql/table.h b/sql/table.h index cef547ae830..08b9a6e0a01 100644 --- a/sql/table.h +++ b/sql/table.h @@ -20,6 +20,7 @@ #include "sql_plist.h" #include "sql_list.h" /* Sql_alloc */ #include "mdl.h" +#include "datadict.h" #ifndef MYSQL_CLIENT @@ -305,14 +306,6 @@ enum tmp_table_type NO_TMP_TABLE, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE, INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE }; - -enum frm_type_enum -{ - FRMTYPE_ERROR= 0, - FRMTYPE_TABLE, - FRMTYPE_VIEW -}; - enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; typedef struct st_filesort_info @@ -580,9 +573,7 @@ struct TABLE_SHARE key_map keys_for_keyread; ha_rows min_rows, max_rows; /* create information */ ulong avg_row_length; /* create information */ - ulong raid_chunksize; ulong version, mysql_version; - ulong timestamp_offset; /* Set to offset+1 of record */ ulong reclength; /* Recordlength */ plugin_ref db_plugin; /* storage engine plugin */ @@ -593,11 +584,8 @@ struct TABLE_SHARE } enum row_type row_type; /* How rows are stored */ enum tmp_table_type tmp_table; - enum enum_ha_unused unused1; - enum enum_ha_unused unused2; uint ref_count; /* How many TABLE objects uses this */ - uint open_count; /* Number of tables in open list */ uint blob_ptr_size; /* 4 or 8 */ uint key_block_size; /* create key_block_size, if used */ uint null_bytes, last_null_bit_pos; @@ -613,7 +601,6 @@ struct TABLE_SHARE uint db_create_options; /* Create options from database */ uint db_options_in_use; /* Options in use */ uint db_record_offset; /* if HA_REC_IN_SEQ */ - uint raid_type, raid_chunks; uint rowid_field_offset; /* Field_nr +1 to rowid field */ /* Index of auto-updated TIMESTAMP field in field array */ uint primary_key; @@ -747,7 +734,7 @@ struct TABLE_SHARE /* Must all TABLEs be reopened? */ - inline bool needs_reopen() + inline bool needs_reopen() const { return version != refresh_version; } @@ -1600,20 +1587,21 @@ struct TABLE_LIST OPEN_STUB } open_strategy; /** - Indicates the locking strategy for the object being opened: - whether the associated metadata lock is shared or exclusive. + Indicates the locking strategy for the object being opened. */ enum { - /* Take a shared metadata lock before the object is opened. */ - SHARED_MDL= 0, /* - Take a exclusive metadata lock before the object is opened. - If opening is successful, downgrade to a shared lock. + Take metadata lock specified by 'mdl_request' member before + the object is opened. Do nothing after that. + */ + OTLS_NONE= 0, + /* + Take (exclusive) metadata lock specified by 'mdl_request' member + before object is opened. If opening is successful, downgrade to + a shared lock. */ - EXCLUSIVE_DOWNGRADABLE_MDL, - /* Take a exclusive metadata lock before the object is opened. */ - EXCLUSIVE_MDL + OTLS_DOWNGRADE_IF_EXISTS } lock_strategy; /* For transactional locking. */ int lock_timeout; /* NOWAIT or WAIT [X] */ @@ -2039,7 +2027,7 @@ void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); bool check_and_convert_db_name(LEX_STRING *db, bool preserve_lettercase); bool check_db_name(LEX_STRING *db); bool check_column_name(const char *name); -bool check_table_name(const char *name, uint length, bool check_for_path_chars); +bool check_table_name(const char *name, size_t length, bool check_for_path_chars); int rename_file_ext(const char * from,const char * to,const char * ext); char *get_field(MEM_ROOT *mem, Field *field); bool get_field(MEM_ROOT *mem, Field *field, class String *res); diff --git a/sql/transaction.cc b/sql/transaction.cc index 5047de1ccdc..78551d6fcf7 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -96,7 +96,18 @@ bool trans_begin(THD *thd, uint flags) DBUG_ASSERT(!thd->locked_tables_mode); - if (trans_commit_implicit(thd)) + if (thd->in_multi_stmt_transaction_mode() || + (thd->variables.option_bits & OPTION_TABLE_LOCK)) + { + thd->variables.option_bits&= ~OPTION_TABLE_LOCK; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + res= test(ha_commit_trans(thd, TRUE)); + } + + thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); + thd->transaction.all.modified_non_trans_table= FALSE; + + if (res) DBUG_RETURN(TRUE); /* @@ -182,6 +193,14 @@ bool trans_commit_implicit(THD *thd) thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; + /* + Upon implicit commit, reset the current transaction + isolation level. We do not care about + @@session.completion_type since it's documented + to not have any effect on implicit commit. + */ + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + DBUG_RETURN(res); } @@ -234,7 +253,11 @@ bool trans_commit_stmt(THD *thd) DBUG_ENTER("trans_commit_stmt"); int res= FALSE; if (thd->transaction.stmt.ha_list) + { res= ha_commit_trans(thd, FALSE); + if (! thd->in_active_multi_stmt_transaction()) + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + } if (res) /* @@ -265,6 +288,8 @@ bool trans_rollback_stmt(THD *thd) ha_rollback_trans(thd, FALSE); if (thd->transaction_rollback_request && !thd->in_sub_stmt) ha_rollback_trans(thd, TRUE); + if (! thd->in_active_multi_stmt_transaction()) + thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; } RUN_HOOK(transaction, after_rollback, (thd, FALSE)); diff --git a/sql/tztime.cc b/sql/tztime.cc index b23456b5465..79f3b83553e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1692,7 +1692,11 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) } for (TABLE_LIST *tl= tz_tables; tl; tl= tl->next_global) + { tl->table->use_all_columns(); + /* Force close at the end of the function to free memory. */ + tl->table->m_needs_reopen= TRUE; + } /* Now we are going to load leap seconds descriptions that are shared @@ -1781,7 +1785,6 @@ end_with_setting_default_tz: end_with_close: if (time_zone_tables_exist) { - thd->version--; /* Force close to free memory */ close_thread_tables(thd); thd->mdl_context.release_transactional_locks(); } diff --git a/sql/udf_example.c b/sql/udf_example.c index fa1b44178ac..284689d329f 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -146,7 +146,9 @@ typedef long long longlong; #ifdef HAVE_DLOPEN +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) static pthread_mutex_t LOCK_hostname; +#endif /* These must be right or mysqld will not find the symbol! */ diff --git a/sql/unireg.h b/sql/unireg.h index dbbeea077a9..b897c887c89 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -77,8 +77,8 @@ typedef struct st_ha_create_information HA_CREATE_INFO; #define SPECIAL_LOG_QUERIES_NOT_USING_INDEXES 4096 /* Obsolete */ /* Extern defines */ -#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->s->reclength) -#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->s->reclength) +#define store_record(A,B) memcpy((A)->B,(A)->record[0],(size_t) (A)->s->reclength) +#define restore_record(A,B) memcpy((A)->record[0],(A)->B,(size_t) (A)->s->reclength) #define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->s->reclength) #define empty_record(A) { \ restore_record((A),s->default_values); \ diff --git a/storage/heap/CMakeLists.txt b/storage/heap/CMakeLists.txt index 32359759abc..2c0b65b0cc4 100755..100644 --- a/storage/heap/CMakeLists.txt +++ b/storage/heap/CMakeLists.txt @@ -23,3 +23,9 @@ SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c) MYSQL_ADD_PLUGIN(heap ${HEAP_SOURCES} STORAGE_ENGINE MANDATORY RECOMPILE_FOR_EMBEDDED) + +ADD_EXECUTABLE(hp_test1 hp_test1.c) +TARGET_LINK_LIBRARIES(hp_test1 mysys heap dbug strings) + +ADD_EXECUTABLE(hp_test2 hp_test2.c) +TARGET_LINK_LIBRARIES(hp_test2 mysys heap dbug strings) diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index 3abffc7087f..541650bd5e8 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -29,6 +29,10 @@ static handler *heap_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); +static int +heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table, + HP_CREATE_INFO *hp_create_info); + int heap_panic(handlerton *hton, ha_panic_function flag) { @@ -96,43 +100,48 @@ const char **ha_heap::bas_ext() const int ha_heap::open(const char *name, int mode, uint test_if_locked) { - if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || - (!(file= heap_open(name, mode)) && my_errno == ENOENT)) + internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE); + if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT)) { - HA_CREATE_INFO create_info; - internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE); - bzero(&create_info, sizeof(create_info)); + HP_CREATE_INFO create_info; + my_bool created_new_share; + int rc; file= 0; - if (!create(name, table, &create_info)) + if (heap_prepare_hp_create_info(table, internal_table, &create_info)) + goto end; + create_info.pin_share= TRUE; + + rc= heap_create(name, &create_info, &internal_share, &created_new_share); + my_free((uchar*) create_info.keydef, MYF(0)); + if (rc) + goto end; + + implicit_emptied= test(created_new_share); + if (internal_table) + file= heap_open_from_share(internal_share, mode); + else + file= heap_open_from_share_and_register(internal_share, mode); + + if (!file) { - file= internal_table ? - heap_open_from_share(internal_share, mode) : - heap_open_from_share_and_register(internal_share, mode); - if (!file) - { - /* Couldn't open table; Remove the newly created table */ - mysql_mutex_lock(&THR_LOCK_heap); - hp_free(internal_share); - mysql_mutex_unlock(&THR_LOCK_heap); - } - implicit_emptied= 1; + heap_release_share(internal_share, internal_table); + goto end; } } + ref_length= sizeof(HEAP_PTR); - if (file) - { - /* Initialize variables for the opened table */ - set_keys_for_scanning(); - /* - We cannot run update_key_stats() here because we do not have a - lock on the table. The 'records' count might just be changed - temporarily at this moment and we might get wrong statistics (Bug - #10178). Instead we request for update. This will be done in - ha_heap::info(), which is always called before key statistics are - used. + /* Initialize variables for the opened table */ + set_keys_for_scanning(); + /* + We cannot run update_key_stats() here because we do not have a + lock on the table. The 'records' count might just be changed + temporarily at this moment and we might get wrong statistics (Bug + #10178). Instead we request for update. This will be done in + ha_heap::info(), which is always called before key statistics are + used. */ - key_stat_version= file->s->key_stat_version-1; - } + key_stat_version= file->s->key_stat_version-1; +end: return (file ? 0 : 1); } @@ -624,18 +633,20 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, } -int ha_heap::create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) +static int +heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table, + HP_CREATE_INFO *hp_create_info) { uint key, parts, mem_per_row= 0, keys= table_arg->s->keys; uint auto_key= 0, auto_key_type= 0; ha_rows max_rows; HP_KEYDEF *keydef; HA_KEYSEG *seg; - int error; TABLE_SHARE *share= table_arg->s; bool found_real_auto_increment= 0; + bzero(hp_create_info, sizeof(*hp_create_info)); + for (key= parts= 0; key < keys; key++) parts+= table_arg->key_info[key].key_parts; @@ -715,29 +726,45 @@ int ha_heap::create(const char *name, TABLE *table_arg, } } mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); - max_rows = (ha_rows) (table_arg->in_use->variables.max_heap_table_size / - (ulonglong) mem_per_row); if (table_arg->found_next_number_field) { keydef[share->next_number_index].flag|= HA_AUTO_KEY; found_real_auto_increment= share->next_number_key_offset == 0; } + hp_create_info->auto_key= auto_key; + hp_create_info->auto_key_type= auto_key_type; + hp_create_info->max_table_size=current_thd->variables.max_heap_table_size; + hp_create_info->with_auto_increment= found_real_auto_increment; + hp_create_info->internal_table= internal_table; + + max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row); + if (share->max_rows && share->max_rows < max_rows) + max_rows= share->max_rows; + + hp_create_info->max_records= (ulong) max_rows; + hp_create_info->min_records= (ulong) share->min_rows; + hp_create_info->keys= share->keys; + hp_create_info->reclength= share->reclength; + hp_create_info->keydef= keydef; + return 0; +} + + +int ha_heap::create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info) +{ + int error; + my_bool created; HP_CREATE_INFO hp_create_info; - hp_create_info.auto_key= auto_key; - hp_create_info.auto_key_type= auto_key_type; + + error= heap_prepare_hp_create_info(table_arg, internal_table, + &hp_create_info); + if (error) + return error; hp_create_info.auto_increment= (create_info->auto_increment_value ? create_info->auto_increment_value - 1 : 0); - hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; - hp_create_info.with_auto_increment= found_real_auto_increment; - hp_create_info.internal_table= internal_table; - max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row); - error= heap_create(name, - keys, keydef, share->reclength, - (ulong) ((share->max_rows < max_rows && - share->max_rows) ? - share->max_rows : max_rows), - (ulong) share->min_rows, &hp_create_info, &internal_share); - my_free((uchar*) keydef, MYF(0)); + error= heap_create(name, &hp_create_info, &internal_share, &created); + my_free((uchar*) hp_create_info.keydef, MYF(0)); DBUG_ASSERT(file == 0); return (error); } diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c index 85e632e5aad..cf0f5d5ba6d 100644 --- a/storage/heap/hp_create.c +++ b/storage/heap/hp_create.c @@ -21,24 +21,30 @@ static void init_block(HP_BLOCK *block,uint reclength,ulong min_records, /* Create a heap table */ -int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, - uint reclength, ulong max_records, ulong min_records, - HP_CREATE_INFO *create_info, HP_SHARE **res) +int heap_create(const char *name, HP_CREATE_INFO *create_info, + HP_SHARE **res, my_bool *created_new_share) { uint i, j, key_segs, max_length, length; HP_SHARE *share= 0; HA_KEYSEG *keyseg; + HP_KEYDEF *keydef= create_info->keydef; + uint reclength= create_info->reclength; + uint keys= create_info->keys; + ulong min_records= create_info->min_records; + ulong max_records= create_info->max_records; DBUG_ENTER("heap_create"); if (!create_info->internal_table) { mysql_mutex_lock(&THR_LOCK_heap); - if ((share= hp_find_named_heap(name)) && share->open_count == 0) + share= hp_find_named_heap(name); + if (share && share->open_count == 0) { hp_free(share); share= 0; } - } + } + *created_new_share= (share == NULL); if (!share) { @@ -200,7 +206,11 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, share->delete_on_close= 1; } if (!create_info->internal_table) + { + if (create_info->pin_share) + ++share->open_count; mysql_mutex_unlock(&THR_LOCK_heap); + } *res= share; DBUG_RETURN(0); diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c index aaaa0fe833f..f56df42aab3 100644 --- a/storage/heap/hp_hash.c +++ b/storage/heap/hp_hash.c @@ -577,7 +577,7 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const uchar *rec1, const uchar *rec2, } else { - if (bcmp(rec1+seg->start,rec2+seg->start,seg->length)) + if (memcmp(rec1+seg->start,rec2+seg->start,seg->length)) return 1; } } @@ -660,7 +660,7 @@ int hp_key_cmp(HP_KEYDEF *keydef, const uchar *rec, const uchar *key) } else { - if (bcmp(rec+seg->start,key,seg->length)) + if (memcmp(rec+seg->start,key,seg->length)) return 1; } } diff --git a/storage/heap/hp_open.c b/storage/heap/hp_open.c index feafa5d5cf1..ef2ce15f9b3 100644 --- a/storage/heap/hp_open.c +++ b/storage/heap/hp_open.c @@ -74,12 +74,33 @@ HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode) { info->open_list.data= (void*) info; heap_open_list= list_add(heap_open_list,&info->open_list); + /* Unpin the share, it is now pinned by the file. */ + share->open_count--; } mysql_mutex_unlock(&THR_LOCK_heap); DBUG_RETURN(info); } +/** + Dereference a HEAP share and free it if it's not referenced. + We don't check open_count for internal tables since they + are always thread-local, i.e. referenced by a single thread. +*/ +void heap_release_share(HP_SHARE *share, my_bool internal_table) +{ + /* Couldn't open table; Remove the newly created table */ + if (internal_table) + hp_free(share); + else + { + mysql_mutex_lock(&THR_LOCK_heap); + if (--share->open_count == 0) + hp_free(share); + mysql_mutex_unlock(&THR_LOCK_heap); + } +} + /* Open heap table based on name diff --git a/storage/heap/hp_test1.c b/storage/heap/hp_test1.c index 911e3a285a2..535db60e237 100644 --- a/storage/heap/hp_test1.c +++ b/storage/heap/hp_test1.c @@ -38,6 +38,7 @@ int main(int argc, char **argv) HA_KEYSEG keyseg[4]; HP_CREATE_INFO hp_create_info; HP_SHARE *tmp_share; + my_bool unused; MY_INIT(argv[0]); filename= "test1"; @@ -45,6 +46,11 @@ int main(int argc, char **argv) bzero(&hp_create_info, sizeof(hp_create_info)); hp_create_info.max_table_size= 1024L*1024L; + hp_create_info.keys= 1; + hp_create_info.keydef= keyinfo; + hp_create_info.reclength= 30; + hp_create_info.max_records= (ulong) flag*100000L; + hp_create_info.min_records= 10UL; keyinfo[0].keysegs=1; keyinfo[0].seg=keyseg; @@ -55,13 +61,12 @@ int main(int argc, char **argv) keyinfo[0].seg[0].charset= &my_charset_latin1; keyinfo[0].seg[0].null_bit= 0; keyinfo[0].flag = HA_NOSAME; - + deleted=0; bzero((uchar*) flags,sizeof(flags)); printf("- Creating heap-file\n"); - if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000L,10L, - &hp_create_info, &tmp_share) || + if (heap_create(filename, &hp_create_info, &tmp_share, &unused) || !(file= heap_open(filename, 2))) goto err; printf("- Writing records:s\n"); diff --git a/storage/heap/hp_test2.c b/storage/heap/hp_test2.c index 8216c7360b4..1571fc98402 100644 --- a/storage/heap/hp_test2.c +++ b/storage/heap/hp_test2.c @@ -15,16 +15,6 @@ /* Test av isam-databas: stor test */ -#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */ -#define USE_MY_FUNC -#endif -#ifdef DBUG_OFF -#undef DBUG_OFF -#endif -#ifndef SAFEMALLOC -#define SAFEMALLOC -#endif - #include "heapdef.h" /* Because of hp_find_block */ #include <signal.h> @@ -65,15 +55,21 @@ int main(int argc, char *argv[]) HEAP_PTR UNINIT_VAR(position); HP_CREATE_INFO hp_create_info; CHARSET_INFO *cs= &my_charset_latin1; + my_bool unused; MY_INIT(argv[0]); /* init my_sys library & pthreads */ filename= "test2"; filename2= "test2_2"; file=file2=0; get_options(argc,argv); - + bzero(&hp_create_info, sizeof(hp_create_info)); hp_create_info.max_table_size= 1024L*1024L; + hp_create_info.keys= keys; + hp_create_info.keydef= keyinfo; + hp_create_info.reclength= reclength; + hp_create_info.max_records= (ulong) flag*100000L; + hp_create_info.min_records= (ulong) recant/2; write_count=update=opt_delete=0; key_check=0; @@ -125,8 +121,7 @@ int main(int argc, char *argv[]) bzero((char*) key3,sizeof(key3)); printf("- Creating heap-file\n"); - if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L, - (ulong) recant/2, &hp_create_info, &tmp_share) || + if (heap_create(filename, &hp_create_info, &tmp_share, &unused) || !(file= heap_open(filename, 2))) goto err; signal(SIGINT,endprog); @@ -406,7 +401,7 @@ int main(int argc, char *argv[]) bmove(record2,record,reclength); if (heap_rsame(file,record,-1) || heap_rsame(file,record2,2)) goto err; - if (bcmp(record2,record,reclength)) + if (memcmp(record2,record,reclength)) { puts("heap_rsame didn't find right record"); goto end; @@ -415,7 +410,7 @@ int main(int argc, char *argv[]) puts("- Test of read through position"); if (heap_rrnd(file,record,position)) goto err; - if (bcmp(record3,record,reclength)) + if (memcmp(record3,record,reclength)) { puts("heap_frnd didn't find right record"); goto end; @@ -563,8 +558,10 @@ int main(int argc, char *argv[]) heap_close(file2); printf("- Creating output heap-file 2\n"); - if (heap_create(filename2, 1, keyinfo, reclength, 0L, 0L, &hp_create_info, - &tmp_share) || + hp_create_info.keys= 1; + hp_create_info.max_records= 0; + hp_create_info.min_records= 0; + if (heap_create(filename2, &hp_create_info, &tmp_share, &unused) || !(file2= heap_open_from_share_and_register(tmp_share, 2))) goto err; diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 6aec52032f3..90246aaa99d 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -272,6 +272,7 @@ ELSEIF (MYSQL_VERSION_ID LESS "50137") ELSE() # New plugin support, cross-platform , base name for shared module is "ha_innodb" MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE + DEFAULT MODULE_OUTPUT_NAME ha_innodb LINK_LIBRARIES ${ZLIB_LIBRARY}) ENDIF() diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index ae228732270..4b6b0a82486 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -2957,7 +2957,7 @@ wait_until_unfixed: block->page.buf_fix_count = 1; buf_block_set_io_fix(block, BUF_IO_READ); - rw_lock_x_lock(&block->lock); + rw_lock_x_lock_func(&block->lock, 0, file, line); UNIV_MEM_INVALID(bpage, sizeof *bpage); diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index b061fe696c1..6bf2c1d9d81 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -1694,6 +1694,7 @@ err_exit: /* Try to open the tablespace */ if (!fil_open_single_table_tablespace( TRUE, table->space, + table->flags == DICT_TF_COMPACT ? 0 : table->flags & ~(~0 << DICT_TF_BITS), name)) { /* We failed to find a sensible tablespace file */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index cbed05f0a5e..c392033b7a7 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -149,10 +149,10 @@ static char* innobase_log_group_home_dir = NULL; static char* innobase_file_format_name = NULL; static char* innobase_change_buffering = NULL; -/* Note: This variable can be set to on/off and any of the supported -file formats in the configuration file, but can only be set to any -of the supported file formats during runtime. */ -static char* innobase_file_format_check = NULL; +/* The highest file format being used in the database. The value can be +set by user, however, it will be adjusted to the newer file format if +a table of such format is created/opened. */ +static char* innobase_file_format_max = NULL; static char* innobase_file_flush_method = NULL; @@ -160,6 +160,7 @@ static char* innobase_file_flush_method = NULL; values */ static ulong innobase_fast_shutdown = 1; +static my_bool innobase_file_format_check = TRUE; #ifdef UNIV_LOG_ARCHIVE static my_bool innobase_log_archive = FALSE; static char* innobase_log_arch_dir = NULL; @@ -171,6 +172,7 @@ static my_bool innobase_rollback_on_timeout = FALSE; static my_bool innobase_create_status_file = FALSE; static my_bool innobase_stats_on_metadata = TRUE; + static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; @@ -366,22 +368,13 @@ innobase_file_format_name_lookup( name */ /************************************************************//** Validate the file format check config parameters, as a side effect it -sets the srv_check_file_format_at_startup variable. -@return true if one of "on" or "off" */ -static -bool -innobase_file_format_check_on_off( -/*==============================*/ - const char* format_check); /*!< in: parameter value */ -/************************************************************//** -Validate the file format check config parameters, as a side effect it -sets the srv_check_file_format_at_startup variable. +sets the srv_max_file_format_at_startup variable. @return the format_id if valid config value, otherwise, return -1 */ static int innobase_file_format_validate_and_set( -/*================================*/ - const char* format_check); /*!< in: parameter value */ +/*==================================*/ + const char* format_max); /*!< in: parameter value */ /****************************************************************//** Return alter table flags supported in an InnoDB database. */ static @@ -436,7 +429,7 @@ static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG, static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG, "Use strict mode when evaluating create options.", - NULL, NULL, FALSE); + NULL, NULL, TRUE); static MYSQL_THDVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG, "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.", @@ -2264,32 +2257,35 @@ mem_free_and_error: innobase_file_format_name is used in the MySQL set variable interface and so can't be const. */ - innobase_file_format_name = + innobase_file_format_name = (char*) trx_sys_file_format_id_to_name(format_id); - /* Process innobase_file_format_check variable */ - ut_a(innobase_file_format_check != NULL); + /* Check innobase_file_format_check variable */ + if (!innobase_file_format_check) { - /* As a side effect it will set srv_check_file_format_at_startup - on valid input. First we check for "on"/"off". */ - if (!innobase_file_format_check_on_off(innobase_file_format_check)) { + /* Set the value to disable checking. */ + srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX + 1; - /* Did the user specify a format name that we support ? - As a side effect it will update the variable - srv_check_file_format_at_startup */ - if (innobase_file_format_validate_and_set( - innobase_file_format_check) < 0) { + } else { - sql_print_error("InnoDB: invalid " - "innodb_file_format_check value: " - "should be either 'on' or 'off' or " - "any value up to %s or its " - "equivalent numeric id", - trx_sys_file_format_id_to_name( - DICT_TF_FORMAT_MAX)); + /* Set the value to the lowest supported format. */ + srv_max_file_format_at_startup = DICT_TF_FORMAT_MIN; + } - goto mem_free_and_error; - } + /* Did the user specify a format name that we support? + As a side effect it will update the variable + srv_max_file_format_at_startup */ + if (innobase_file_format_validate_and_set( + innobase_file_format_max) < 0) { + + sql_print_error("InnoDB: invalid " + "innodb_file_format_max value: " + "should be any value up to %s or its " + "equivalent numeric id", + trx_sys_file_format_id_to_name( + DICT_TF_FORMAT_MAX)); + + goto mem_free_and_error; } if (innobase_change_buffering) { @@ -2451,7 +2447,7 @@ innobase_change_buffering_inited_ok: #endif /* MYSQL_DYNAMIC_PLUGIN */ /* Get the current high water mark format. */ - innobase_file_format_check = (char*) trx_sys_file_format_max_get(); + innobase_file_format_max = (char*) trx_sys_file_format_max_get(); DBUG_RETURN(FALSE); error: @@ -3836,7 +3832,7 @@ retry: space, if this table has higher file format setting. */ trx_sys_file_format_max_upgrade( - (const char**) &innobase_file_format_check, + (const char**) &innobase_file_format_max, dict_table_get_format(prebuilt->table)); } @@ -6979,7 +6975,7 @@ ha_innobase::create( space, if this table has higher file format setting. */ trx_sys_file_format_max_upgrade( - (const char**) &innobase_file_format_check, + (const char**) &innobase_file_format_max, dict_table_get_format(innobase_table)); } @@ -7630,8 +7626,7 @@ innobase_get_mysql_key_number_for_index( /* If index does not belong to the table of share structure. Search index->table instead */ - if (index->table != ib_table - && innobase_strcasecmp(index->table->name, share->table_name)) { + if (index->table != ib_table) { i = 0; ind = dict_table_get_first_index(index->table); @@ -10369,49 +10364,21 @@ innobase_file_format_name_lookup( } /************************************************************//** -Validate the file format check value, is it one of "on" or "off", -as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if config value one of "on" or "off" */ -static -bool -innobase_file_format_check_on_off( -/*==============================*/ - const char* format_check) /*!< in: parameter value */ -{ - bool ret = true; - - if (!innobase_strcasecmp(format_check, "off")) { - - /* Set the value to disable checking. */ - srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1; - - } else if (!innobase_strcasecmp(format_check, "on")) { - - /* Set the value to the lowest supported format. */ - srv_check_file_format_at_startup = DICT_TF_FORMAT_51; - } else { - ret = FALSE; - } - - return(ret); -} - -/************************************************************//** Validate the file format check config parameters, as a side effect it -sets the srv_check_file_format_at_startup variable. +sets the srv_max_file_format_at_startup variable. @return the format_id if valid config value, otherwise, return -1 */ static int innobase_file_format_validate_and_set( -/*================================*/ - const char* format_check) /*!< in: parameter value */ +/*==================================*/ + const char* format_max) /*!< in: parameter value */ { uint format_id; - format_id = innobase_file_format_name_lookup(format_check); + format_id = innobase_file_format_name_lookup(format_max); if (format_id < DICT_TF_FORMAT_MAX + 1) { - srv_check_file_format_at_startup = format_id; + srv_max_file_format_at_startup = format_id; return((int) format_id); } else { @@ -10499,15 +10466,14 @@ innodb_file_format_name_update( *static_cast<const char**>(var_ptr) = trx_sys_file_format_id_to_name(srv_file_format); } - /*************************************************************//** -Check if valid argument to innodb_file_format_check. This -function is registered as a callback with MySQL. +Check if valid argument to innodb_file_format_max. This function +is registered as a callback with MySQL. @return 0 for valid file format */ static int -innodb_file_format_check_validate( -/*==============================*/ +innodb_file_format_max_validate( +/*============================*/ THD* thd, /*!< in: thread handle */ struct st_mysql_sys_var* var, /*!< in: pointer to system variable */ @@ -10527,39 +10493,27 @@ innodb_file_format_check_validate( if (file_format_input != NULL) { - /* Check if user set on/off, we want to print a suitable - message if they did so. */ - - if (innobase_file_format_check_on_off(file_format_input)) { - push_warning_printf(thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "InnoDB: invalid innodb_file_format_check " - "value; on/off can only be set at startup or " - "in the configuration file"); - } else { - format_id = innobase_file_format_validate_and_set( - file_format_input); + format_id = innobase_file_format_validate_and_set( + file_format_input); - if (format_id >= 0) { - /* Save a pointer to the name in the - 'file_format_name_map' constant array. */ - *static_cast<const char**>(save) = - trx_sys_file_format_id_to_name( - (uint)format_id); + if (format_id >= 0) { + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast<const char**>(save) = + trx_sys_file_format_id_to_name( + (uint)format_id); - return(0); + return(0); - } else { - push_warning_printf(thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "InnoDB: invalid innodb_file_format_check " - "value; can be any format up to %s " - "or its equivalent numeric id", - trx_sys_file_format_id_to_name( - DICT_TF_FORMAT_MAX)); - } + } else { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: invalid innodb_file_format_max " + "value; can be any format up to %s " + "or equivalent id of %d", + trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX), + DICT_TF_FORMAT_MAX); } } @@ -10568,12 +10522,12 @@ innodb_file_format_check_validate( } /****************************************************************//** -Update the system variable innodb_file_format_check using the "saved" +Update the system variable innodb_file_format_max using the "saved" value. This function is registered as a callback with MySQL. */ static void -innodb_file_format_check_update( -/*============================*/ +innodb_file_format_max_update( +/*==========================*/ THD* thd, /*!< in: thread handle */ struct st_mysql_sys_var* var, /*!< in: pointer to system variable */ @@ -10875,23 +10829,34 @@ static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown, static MYSQL_SYSVAR_BOOL(file_per_table, srv_file_per_table, PLUGIN_VAR_NOCMDARG, "Stores each InnoDB table to an .ibd file in the database dir.", - NULL, NULL, FALSE); + NULL, NULL, TRUE); static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name, PLUGIN_VAR_RQCMDARG, "File format to use for new tables in .ibd files.", innodb_file_format_name_validate, - innodb_file_format_name_update, "Antelope"); + innodb_file_format_name_update, "Barracuda"); + +/* "innobase_file_format_check" decides whether we would continue +booting the server if the file format stamped on the system +table space exceeds the maximum file format supported +by the server. Can be set during server startup at command +line or configure file, and a read only variable after +server startup */ +static MYSQL_SYSVAR_BOOL(file_format_check, innobase_file_format_check, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Whether to perform system file format check.", + NULL, NULL, TRUE); /* If a new file format is introduced, the file format name needs to be updated accordingly. Please refer to file_format_name_map[] defined in trx0sys.c for the next file format name. */ -static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check, +static MYSQL_SYSVAR_STR(file_format_max, innobase_file_format_max, PLUGIN_VAR_OPCMDARG, "The highest file format in the tablespace.", - innodb_file_format_check_validate, - innodb_file_format_check_update, "Barracuda"); + innodb_file_format_max_validate, + innodb_file_format_max_update, "Antelope"); static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, @@ -11139,6 +11104,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(file_per_table), MYSQL_SYSVAR(file_format), MYSQL_SYSVAR(file_format_check), + MYSQL_SYSVAR(file_format_max), MYSQL_SYSVAR(flush_log_at_trx_commit), MYSQL_SYSVAR(flush_method), MYSQL_SYSVAR(force_recovery), diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index f93b2f8c8a3..57e5b5394ee 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -88,6 +88,10 @@ combination of types */ new BLOB treatment */ /** Maximum supported file format */ #define DICT_TF_FORMAT_MAX DICT_TF_FORMAT_ZIP + +/** Minimum supported file format */ +#define DICT_TF_FORMAT_MIN DICT_TF_FORMAT_51 + /* @} */ #define DICT_TF_BITS 6 /*!< number of flag bits */ #if (1 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT)) <= DICT_TF_FORMAT_MAX diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 98e127d41e2..18f7c07c3c6 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -101,7 +101,7 @@ extern ulint srv_file_format; /** Whether to check file format during startup. A value of DICT_TF_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to set it to the highest format we support. */ -extern ulint srv_check_file_format_at_startup; +extern ulint srv_max_file_format_at_startup; /** Place locks to records only i.e. do not use next-key locking except on duplicate key checking and foreign key checking */ extern ibool srv_locks_unsafe_for_binlog; diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index a5bf361661b..2861235a995 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2678,6 +2678,12 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } + /* init null bytes with default values as they might be + left uninitialized in some cases and these uninited bytes + might be copied into mysql record buffer that leads to + valgrind warnings */ + memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); + for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index b1f3a543b07..6354689105a 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -127,7 +127,7 @@ UNIV_INTERN ulint srv_file_format = 0; /** Whether to check file format during startup. A value of DICT_TF_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to set it to the highest format we support. */ -UNIV_INTERN ulint srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX; +UNIV_INTERN ulint srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX; #if DICT_TF_FORMAT_51 # error "DICT_TF_FORMAT_51 must be 0!" @@ -2371,30 +2371,6 @@ loop: OS_THREAD_DUMMY_RETURN; } -/******************************************************************//** -Increment the server activity count. */ -UNIV_INLINE -void -srv_inc_activity_count_low(void) -/*============================*/ -{ - mutex_enter(&kernel_mutex); - - ++srv_activity_count; - - mutex_exit(&kernel_mutex); -} - -/******************************************************************//** -Increment the server activity count. */ -UNIV_INTERN -void -srv_inc_activity_count(void) -/*========================*/ -{ - srv_inc_activity_count_low(); -} - /**********************************************************************//** Check whether any background thread is active. @return FALSE if all are are suspended or have exited. */ @@ -2431,9 +2407,7 @@ void srv_active_wake_master_thread(void) /*===============================*/ { - ut_ad(!mutex_own(&kernel_mutex)); - - srv_inc_activity_count_low(); + srv_activity_count++; if (srv_n_threads_active[SRV_MASTER] == 0) { diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 1b96a2f4708..4a0ecc5154f 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -1590,7 +1590,7 @@ innobase_start_or_create_for_mysql(void) consistent state, this is REQUIRED for the recovery process to work. */ err = trx_sys_file_format_max_check( - srv_check_file_format_at_startup); + srv_max_file_format_at_startup); if (err != DB_SUCCESS) { return(err); diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 9c531e64662..e2f0ff6d532 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -135,7 +135,7 @@ UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key; #ifndef UNIV_HOTBACKUP /** This is used to track the maximum file format id known to InnoDB. It's -updated via SET GLOBAL innodb_file_format_check = 'x' or when we open +updated via SET GLOBAL innodb_file_format_max = 'x' or when we open or create a table. */ static file_format_t file_format_max; @@ -1160,7 +1160,7 @@ trx_sys_file_format_max_check( if (format_id == ULINT_UNDEFINED) { /* Format ID was not set. Set it to minimum possible value. */ - format_id = DICT_TF_FORMAT_51; + format_id = DICT_TF_FORMAT_MIN; } ut_print_timestamp(stderr); @@ -1240,7 +1240,7 @@ trx_sys_file_format_tag_init(void) /* If format_id is not set then set it to the minimum. */ if (format_id == ULINT_UNDEFINED) { - trx_sys_file_format_max_set(DICT_TF_FORMAT_51, NULL); + trx_sys_file_format_max_set(DICT_TF_FORMAT_MIN, NULL); } } @@ -1296,7 +1296,7 @@ trx_sys_file_format_init(void) /* We don't need a mutex here, as this function should only be called once at start up. */ - file_format_max.id = DICT_TF_FORMAT_51; + file_format_max.id = DICT_TF_FORMAT_MIN; file_format_max.name = trx_sys_file_format_id_to_name( file_format_max.id); diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt index b057a62a6dd..b057a62a6dd 100755..100644 --- a/storage/myisam/CMakeLists.txt +++ b/storage/myisam/CMakeLists.txt diff --git a/storage/myisam/mi_dbug.c b/storage/myisam/mi_dbug.c index 45882eda6af..e450e81cecb 100644 --- a/storage/myisam/mi_dbug.c +++ b/storage/myisam/mi_dbug.c @@ -164,7 +164,19 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, } /* print_key */ -#ifdef EXTRA_DEBUG +#ifdef EXTRA_DEBUG +/** + Check if the named table is in the open list. + + @param[in] name table path as in MYISAM_SHARE::unique_file_name + @param[in] where verbal description of caller + + @retval TRUE table is in open list + @retval FALSE table is not in open list + + @note This function takes THR_LOCK_myisam. Do not call it when + this mutex is locked by this thread already. +*/ my_bool check_table_is_closed(const char *name, const char *where) { @@ -173,6 +185,7 @@ my_bool check_table_is_closed(const char *name, const char *where) DBUG_ENTER("check_table_is_closed"); (void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32); + mysql_mutex_lock(&THR_LOCK_myisam); for (pos=myisam_open_list ; pos ; pos=pos->next) { MI_INFO *info=(MI_INFO*) pos->data; @@ -181,12 +194,14 @@ my_bool check_table_is_closed(const char *name, const char *where) { if (share->last_version) { + mysql_mutex_unlock(&THR_LOCK_myisam); fprintf(stderr,"Warning: Table: %s is open on %s\n", name,where); DBUG_PRINT("warning",("Table: %s is open on %s", name,where)); DBUG_RETURN(1); } } } + mysql_mutex_unlock(&THR_LOCK_myisam); DBUG_RETURN(0); } #endif /* EXTRA_DEBUG */ diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index c7ebf9ae220..24456e3d8fa 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -84,7 +84,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff, test(!(nextflag & SEARCH_SAVE_BUFF))))) goto err; - DBUG_DUMP("page",(uchar*) buff,mi_getint(buff)); + DBUG_DUMP("page", buff, mi_getint(buff)); flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, &keypos,lastkey, &last_key); @@ -819,7 +819,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_PRINT("error", ("Found too long null packed key: %u of %u at 0x%lx", length, keyseg->length, (long) *page_pos)); - DBUG_DUMP("key",(uchar*) *page_pos,16); + DBUG_DUMP("key", *page_pos, 16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; return 0; @@ -876,7 +876,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, { DBUG_PRINT("error",("Found too long packed key: %u of %u at 0x%lx", length, keyseg->length, (long) *page_pos)); - DBUG_DUMP("key",(uchar*) *page_pos,16); + DBUG_DUMP("key", *page_pos, 16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; return 0; /* Error */ @@ -948,7 +948,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_PRINT("error", ("Found too long binary packed key: %u of %u at 0x%lx", length, keyinfo->maxlength, (long) *page_pos)); - DBUG_DUMP("key",(uchar*) *page_pos,16); + DBUG_DUMP("key", *page_pos, 16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); /* Wrong key */ diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c index 63525b08820..31e20754314 100644 --- a/storage/myisam/mi_test2.c +++ b/storage/myisam/mi_test2.c @@ -415,7 +415,7 @@ int main(int argc, char *argv[]) } ant=0; while (mi_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; + memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys) { printf("prev: Found: %d records of %d\n",ant,dupp_keys); @@ -453,7 +453,7 @@ int main(int argc, char *argv[]) goto end; } if (mi_rlast(file,read_record2,0) || - bcmp(read_record2,read_record3,reclength)) + memcmp(read_record2,read_record3,reclength)) { printf("Can't find last record\n"); DBUG_DUMP("record2",(uchar*) read_record2,reclength); @@ -468,7 +468,7 @@ int main(int argc, char *argv[]) printf("prev: I found: %d records of %d\n",ant,write_count); goto end; } - if (bcmp(read_record,read_record3,reclength)) + if (memcmp(read_record,read_record3,reclength)) { printf("Can't find first record\n"); goto end; @@ -483,7 +483,7 @@ int main(int argc, char *argv[]) mi_rprev(file,read_record3,0) == 0 || mi_rnext(file,read_record3,0)) goto err; - if (bcmp(read_record,read_record3,reclength) != 0) + if (memcmp(read_record,read_record3,reclength) != 0) printf("Can't find first record\n"); if (!silent) @@ -495,7 +495,7 @@ int main(int argc, char *argv[]) mi_rnext(file,read_record3,0) == 0 || mi_rprev(file,read_record3,0)) goto err; - if (bcmp(read_record2,read_record3,reclength)) + if (memcmp(read_record2,read_record3,reclength)) printf("Can't find last record\n"); #ifdef NOT_ANYMORE if (!silent) @@ -509,7 +509,7 @@ int main(int argc, char *argv[]) bzero((char*) file->lastkey,file->s->base.max_key_length*2); if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX)) goto err; - if (bcmp(read_record+start,key,(uint) i)) + if (memcmp(read_record+start,key,(uint) i)) { puts("Didn't find right record"); goto end; @@ -528,7 +528,7 @@ int main(int argc, char *argv[]) opt_delete++; ant=1; while (mi_rnext(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; + memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-1) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1); @@ -546,7 +546,7 @@ int main(int argc, char *argv[]) opt_delete++; ant=1; while (mi_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; + memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-2) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2); @@ -566,7 +566,7 @@ int main(int argc, char *argv[]) if (mi_rnext(file,read_record,0)) goto err; /* Skall finnas poster */ while (mi_rnext(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; + memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-3) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3); @@ -581,7 +581,7 @@ int main(int argc, char *argv[]) opt_delete++; ant=0; while (mi_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; + memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-4) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4); @@ -604,7 +604,7 @@ int main(int argc, char *argv[]) for (i=min(2,keys) ; i-- > 0 ;) { if (mi_rsame(file,read_record2,(int) i)) goto err; - if (bcmp(read_record,read_record2,reclength) != 0) + if (memcmp(read_record,read_record2,reclength) != 0) { printf("is_rsame didn't find same record\n"); goto end; diff --git a/storage/myisam/mi_unique.c b/storage/myisam/mi_unique.c index 02fcd9289dd..fdba84a2e67 100644 --- a/storage/myisam/mi_unique.c +++ b/storage/myisam/mi_unique.c @@ -56,7 +56,7 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record, if (_mi_search_next(info,info->s->keyinfo+def->key, info->lastkey, MI_UNIQUE_HASH_LENGTH, SEARCH_BIGGER, info->s->state.key_root[def->key]) || - bcmp((char*) info->lastkey, (char*) key_buff, MI_UNIQUE_HASH_LENGTH)) + memcmp(info->lastkey, key_buff, MI_UNIQUE_HASH_LENGTH)) { info->page_changed=1; /* Can't optimize read next */ info->lastpos=lastpos; diff --git a/storage/myisammrg/CMakeLists.txt b/storage/myisammrg/CMakeLists.txt index 739bcd565bc..739bcd565bc 100755..100644 --- a/storage/myisammrg/CMakeLists.txt +++ b/storage/myisammrg/CMakeLists.txt diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 63d20f127a1..1b0dbb3fd0b 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -298,9 +298,8 @@ extern "C" int myisammrg_parent_open_callback(void *callback_param, if (! db || ! table_name) DBUG_RETURN(1); - DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", db_length, db, - table_name_length, table_name)); - + DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", (int) db_length, db, + (int) table_name_length, table_name)); /* Convert to lowercase if required. */ if (lower_case_table_names && table_name_length) diff --git a/strings/CMakeLists.txt b/strings/CMakeLists.txt index bb32f0d3f84..abc03302b64 100755..100644 --- a/strings/CMakeLists.txt +++ b/strings/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -SET(STRINGS_SOURCES bchange.c bcmp.c bfill.c bmove512.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c +SET(STRINGS_SOURCES bchange.c bfill.c bmove512.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-eucjpms.c ctype-extra.c ctype-gb2312.c ctype-gbk.c ctype-latin1.c ctype-mb.c ctype-simple.c ctype-sjis.c ctype-tis620.c ctype-uca.c ctype-ucs2.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype.c decimal.c dtoa.c int2str.c diff --git a/strings/Makefile.am b/strings/Makefile.am index 9b32f42c49a..fd884a1296a 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -30,19 +30,19 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c my_strchr.c dtoa.c strmov.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c my_strchr.c dtoa.c strmov.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s -CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c dtoa.c strmov.c +CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c dtoa.c strmov.c else #no assembler ASRCS = # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile -CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c dtoa.c +CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c dtoa.c endif endif @@ -66,7 +66,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc CHARSET_INFO.txt libmystrings_a_LIBADD= -conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c +conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c conf_to_src_LDADD= #force static linking of conf_to_src - essential when linking against #custom installation of libc diff --git a/strings/bcmp.c b/strings/bcmp.c deleted file mode 100644 index 1b6ed22fc22..00000000000 --- a/strings/bcmp.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - bcmp(s1, s2, len) returns 0 if the "len" bytes starting at "s1" are - identical to the "len" bytes starting at "s2", non-zero if they are - different. - Now only used with purify because purify gives wrong warnings when - comparing a shorter string with bcmp. -*/ - -#include <my_global.h> -#include "m_string.h" - -#ifdef HAVE_purify -#undef bcmp -#undef HAVE_BCMP -#endif - -#if !defined(bcmp) && !defined(HAVE_BCMP) - -#if defined(MC68000) && defined(DS90) - -int bcmp(s1,s2, len) -const char *s1; -const char *s2; -uint len; /* 0 <= len <= 65535 */ -{ - asm(" movl 12(a7),d0 "); - asm(" subqw #1,d0 "); - asm(" blt .L5 "); - asm(" movl 4(a7),a1 "); - asm(" movl 8(a7),a0 "); - asm(".L4: cmpmb (a0)+,(a1)+ "); - asm(" dbne d0,.L4 "); - asm(".L5: addqw #1,d0 "); -} - -#else - -#ifndef HAVE_purify -size_t bcmp(register const uchar *s1,register const uchar *s2, - register size_t len) -#else -size_t my_bcmp(register const uchar *s1,register const uchar *s2, - register size_t len) -#endif -{ - while (len-- != 0 && *s1++ == *s2++) ; - return len+1; -} - -#endif -#endif /* BSD_FUNCS */ diff --git a/strings/str_test.c b/strings/str_test.c index e4358196f27..0814647472c 100644 --- a/strings/str_test.c +++ b/strings/str_test.c @@ -50,10 +50,10 @@ int main(void) errors=tests=0; init_strings(); - test_arg("bcmp(from,to,5)",(long) my_test(bcmp(from,to,5)),1L); - test_arg("bcmp(from,from,5)",(long) bcmp(from,from,5),0L); + test_arg("memcmp(from,to,5)",(long) my_test(memcmp(from,to,5)),1L); + test_arg("memcmp(from,from,5)",(long) memcmp(from,from,5),0L); - test_arg("bcmp(from,to,0)",(long) bcmp(from,to,0),0L); + test_arg("memcmp(from,to,0)",(long) memcmp(from,to,0),0L); test_arg("strend(from)",(long) strend(from),(long) from+F_LEN); test_arg("strchr(v1,'M')",(long) strchr(v1,'M'),(long) v1); test_arg("strchr(v1,'y')",(long) strchr(v1,'y'),(long) v1+4); @@ -93,7 +93,7 @@ int main(void) test_strarg("bmove_upp(to+6,from+6,3)",(bmove_upp(to+6,from+6,3),0L),INT_MAX32, 3,T_CHAR,3,F_CHAR,0,0); test_strarg("bmove_upp(to,from,0)",(bmove_upp(to,from,0),0L),INT_MAX32,0,0); - test_strarg("bmove_align(to,from,8)",(bmove_align(to,from,8),0L),INT_MAX32, + test_strarg("memcpy(to,from,8)",(memcpy(to,from,8),0L),INT_MAX32, 8,F_CHAR,0,0); test_strarg("strappend(to,3,' ')",(strappend(to,3,' '),0L),INT_MAX32, 3,T_CHAR,1,0,T_LEN-4,T_CHAR,1,0,0,0); @@ -233,7 +233,7 @@ int compare_buff(const char *message, char * b1, char * b2, int length, { int i,error=0; - if (bcmp(b1,b2,length)) + if (memcmp(b1,b2,length)) { errors++; printf("func: '%s' Buffers differ\nIs: ",message); diff --git a/strings/xml.c b/strings/xml.c index 1b697ec6b26..f3cfaad54fa 100644 --- a/strings/xml.c +++ b/strings/xml.c @@ -123,16 +123,16 @@ static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a) a->beg=p->cur; a->end=p->cur; - if ((p->end - p->cur > 3) && !bcmp(p->cur,"<!--",4)) + if ((p->end - p->cur > 3) && !memcmp(p->cur,"<!--",4)) { - for (; (p->cur < p->end) && bcmp(p->cur, "-->", 3); p->cur++) + for (; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++) {} - if (!bcmp(p->cur, "-->", 3)) + if (!memcmp(p->cur, "-->", 3)) p->cur+=3; a->end=p->cur; lex=MY_XML_COMMENT; } - else if (!bcmp(p->cur, "<![CDATA[",9)) + else if (!memcmp(p->cur, "<![CDATA[",9)) { p->cur+= 9; for (; p->cur < p->end - 2 ; p->cur++) diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index ff522ac1d35..72c4d1ab2d0 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -32,6 +32,8 @@ ELSE() SET(HOSTNAME "hostname") ENDIF() +# XXX: shouldn't we just have variables for all this stuff and centralise +# XXX: their configuration in install_layout.cmake? IF(WIN32) SET(inst_location ${INSTALL_DOCREADMEDIR}) ELSE() @@ -41,10 +43,13 @@ ENDIF() FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${inifile}.cnf.sh ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} @ONLY) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} DESTINATION ${inst_location}) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} + DESTINATION ${inst_location} COMPONENT IniFiles) ENDFOREACH() IF(UNIX) + # XXX: again, used elsewhere (scripts/), should be standardised in + # XXX: install_layout.cmake IF(INSTALL_LAYOUT MATCHES "STANDALONE") SET(prefix ".") ELSE() @@ -64,7 +69,7 @@ IF(UNIX) INSTALL(FILES magic DESTINATION ${inst_location}) ENDIF() - INSTALL(FILES mysql.m4 DESTINATION ${INSTALL_SHAREDIR}/aclocal) + INSTALL(FILES mysql.m4 DESTINATION ${INSTALL_SHAREDIR}/aclocal COMPONENT Development) CONFIGURE_FILE(MySQL-shared-compat.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/MySQL-shared-compat.spec @ONLY) CONFIGURE_FILE(mysql.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/mysql.spec @ONLY) CONFIGURE_FILE(mysql.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/mysql.${VERSION}.spec @ONLY) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 2af9016d822..b4295027725 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -121,43 +121,62 @@ %define distro_specific 0 %endif %if %{distro_specific} - %if %(test -f /etc/redhat-release && echo 1 || echo 0) - %define rhelver %(rpm -qf --qf '%%{version}\\n' /etc/redhat-release | sed -e 's/^\\([0-9]*\\).*/\\1/g') - %if "%rhelver" == "4" - %define distro_description Red Hat Enterprise Linux 4 - %define distro_releasetag rhel4 + %if %(test -f /etc/enterprise-release && echo 1 || echo 0) + %define oelver %(rpm -qf --qf '%%{version}\\n' /etc/enterprise-release | sed -e 's/^\\([0-9]*\\).*/\\1/g') + %if "%oelver" == "4" + %define distro_description Oracle Enterprise Linux 4 + %define distro_releasetag oel4 %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel %define distro_requires chkconfig coreutils grep procps shadow-utils %else - %if "%rhelver" == "5" - %define distro_description Red Hat Enterprise Linux 5 - %define distro_releasetag rhel5 + %if "%oelver" == "5" + %define distro_description Oracle Enterprise Linux 5 + %define distro_releasetag oel5 %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel %define distro_requires chkconfig coreutils grep procps shadow-utils %else - %{error:Red Hat Enterprise Linux %{rhelver} is unsupported} + %{error:Oracle Enterprise Linux %{oelver} is unsupported} %endif %endif %else - %if %(test -f /etc/SuSE-release && echo 1 || echo 0) - %define susever %(rpm -qf --qf '%%{version}\\n' /etc/SuSE-release) - %if "%susever" == "10" - %define distro_description SUSE Linux Enterprise Server 10 - %define distro_releasetag sles10 - %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client readline-devel zlib-devel - %define distro_requires aaa_base coreutils grep procps pwdutils + %if %(test -f /etc/redhat-release && echo 1 || echo 0) + %define rhelver %(rpm -qf --qf '%%{version}\\n' /etc/redhat-release | sed -e 's/^\\([0-9]*\\).*/\\1/g') + %if "%rhelver" == "4" + %define distro_description Red Hat Enterprise Linux 4 + %define distro_releasetag rhel4 + %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel + %define distro_requires chkconfig coreutils grep procps shadow-utils %else - %if "%susever" == "11" - %define distro_description SUSE Linux Enterprise Server 11 - %define distro_releasetag sles11 - %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client procps pwdutils readline-devel zlib-devel - %define distro_requires aaa_base coreutils grep procps pwdutils + %if "%rhelver" == "5" + %define distro_description Red Hat Enterprise Linux 5 + %define distro_releasetag rhel5 + %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel + %define distro_requires chkconfig coreutils grep procps shadow-utils %else - %{error:SuSE %{susever} is unsupported} + %{error:Red Hat Enterprise Linux %{rhelver} is unsupported} %endif %endif %else - %{error:Unsupported distribution} + %if %(test -f /etc/SuSE-release && echo 1 || echo 0) + %define susever %(rpm -qf --qf '%%{version}\\n' /etc/SuSE-release) + %if "%susever" == "10" + %define distro_description SUSE Linux Enterprise Server 10 + %define distro_releasetag sles10 + %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client readline-devel zlib-devel + %define distro_requires aaa_base coreutils grep procps pwdutils + %else + %if "%susever" == "11" + %define distro_description SUSE Linux Enterprise Server 11 + %define distro_releasetag sles11 + %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client procps pwdutils readline-devel zlib-devel + %define distro_requires aaa_base coreutils grep procps pwdutils + %else + %{error:SuSE %{susever} is unsupported} + %endif + %endif + %else + %{error:Unsupported distribution} + %endif %endif %endif %else @@ -396,30 +415,30 @@ mkdir debug -e 's/ -ip / /' \ -e 's/^ //' \ -e 's/ $//'` - # XXX: MYSQL_UNIX_ADDR should be in cmake/* but mysql_version is included - # XXX: before install_layout so we can't just set it based on - # XXX: INSTALL_LAYOUT=RPM + # XXX: MYSQL_UNIX_ADDR should be in cmake/* but mysql_version is included before + # XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM ${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \ -DCMAKE_BUILD_TYPE=Debug \ -DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_debug}" \ -DMYSQL_SERVER_SUFFIX="%{server_suffix}" + echo BEGIN_DEBUG_CONFIG ; egrep '^#define' include/config.h ; echo END_DEBUG_CONFIG make VERBOSE=1 ) # Build full release mkdir release ( cd release - # XXX: MYSQL_UNIX_ADDR should be in cmake/* but mysql_version is included - # XXX: before install_layout so we can't just set it based on - # XXX: INSTALL_LAYOUT=RPM + # XXX: MYSQL_UNIX_ADDR should be in cmake/* but mysql_version is included before + # XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM ${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_release}" \ -DMYSQL_SERVER_SUFFIX="%{server_suffix}" + echo BEGIN_NORMAL_CONFIG ; egrep '^#define' include/config.h ; echo END_NORMAL_CONFIG make VERBOSE=1 ) @@ -470,10 +489,8 @@ install -d $RBR%{_sbindir} mv -v $RBR/%{_libdir}/*.a $RBR/%{_libdir}/mysql/ # Install logrotate and autostart -install -m 644 $MBD/release/support-files/mysql-log-rotate \ - $RBR%{_sysconfdir}/logrotate.d/mysql -install -m 755 $MBD/release/support-files/mysql.server \ - $RBR%{_sysconfdir}/init.d/mysql +install -m 644 $MBD/release/support-files/mysql-log-rotate $RBR%{_sysconfdir}/logrotate.d/mysql +install -m 755 $MBD/release/support-files/mysql.server $RBR%{_sysconfdir}/init.d/mysql # Create a symlink "rcmysql", pointing to the init.script. SuSE users # will appreciate that, as all services usually offer this. @@ -646,9 +663,9 @@ fi # so a "stop" is attempted even if there is no PID file. # (Maybe the "stop" doesn't work then, but we might fix that in itself.) if [ -x %{_sysconfdir}/init.d/mysql ] ; then - %{_sysconfdir}/init.d/mysql stop > /dev/null 2>&1 - echo "Giving mysqld 5 seconds to exit nicely" - sleep 5 + %{_sysconfdir}/init.d/mysql stop > /dev/null 2>&1 + echo "Giving mysqld 5 seconds to exit nicely" + sleep 5 fi %post -n MySQL-server%{product_suffix} @@ -682,10 +699,10 @@ if [ ! -d $mysql_datadir/test ] ; then mkdir $mysql_datadir/test; fi # for the other run levels exist(ed) before the upgrade? # use insserv for older SuSE Linux versions if [ -x /sbin/insserv ] ; then - /sbin/insserv %{_sysconfdir}/init.d/mysql + /sbin/insserv %{_sysconfdir}/init.d/mysql # use chkconfig on Enterprise Linux and newer SuSE releases elif [ -x /sbin/chkconfig ] ; then - /sbin/chkconfig --add mysql + /sbin/chkconfig --add mysql fi # ---------------------------------------------------------------------- @@ -783,21 +800,27 @@ cat $STATUS_FILE >> $STATUS_HISTORY rm $STATUS_FILE +#echo "Thank you for installing the MySQL Community Server! For Production +#systems, we recommend MySQL Enterprise, which contains enterprise-ready +#software, intelligent advisory services, and full production support with +#scheduled service packs and more. Visit www.mysql.com/enterprise for more +#information." + %preun -n MySQL-server%{product_suffix} if [ $1 = 0 ] ; then - # Stop MySQL before uninstalling it - if [ -x %{_sysconfdir}/init.d/mysql ] ; then - %{_sysconfdir}/init.d/mysql stop > /dev/null - # Remove autostart of MySQL - # For older SuSE Linux versions - if [ -x /sbin/insserv ] ; then - /sbin/insserv -r %{_sysconfdir}/init.d/mysql - # use chkconfig on Enterprise Linux and newer SuSE releases - elif [ -x /sbin/chkconfig ] ; then - /sbin/chkconfig --del mysql - fi - fi + # Stop MySQL before uninstalling it + if [ -x %{_sysconfdir}/init.d/mysql ] ; then + %{_sysconfdir}/init.d/mysql stop > /dev/null + # Remove autostart of MySQL + # For older SuSE Linux versions + if [ -x /sbin/insserv ] ; then + /sbin/insserv -r %{_sysconfdir}/init.d/mysql + # use chkconfig on Enterprise Linux and newer SuSE releases + elif [ -x /sbin/chkconfig ] ; then + /sbin/chkconfig --del mysql + fi + fi fi # We do not remove the mysql user since it may still own a lot of @@ -883,13 +906,13 @@ fi %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug %attr(755, root, root) %{_sbindir}/rcmysql -%attr(755, root, root) %{_libdir}/mysql/plugin/audit_null.so -%attr(755, root, root) %{_libdir}/mysql/plugin/daemon_example.so +%attr(755, root, root) %{_libdir}/mysql/plugin/adt_null.so +%attr(755, root, root) %{_libdir}/mysql/plugin/libdaemon_example.so %attr(755, root, root) %{_libdir}/mysql/plugin/mypluglib.so %attr(755, root, root) %{_libdir}/mysql/plugin/semisync_master.so %attr(755, root, root) %{_libdir}/mysql/plugin/semisync_slave.so -%attr(755, root, root) %{_libdir}/mysql/plugin/debug/audit_null.so -%attr(755, root, root) %{_libdir}/mysql/plugin/debug/daemon_example.so +%attr(755, root, root) %{_libdir}/mysql/plugin/debug/adt_null.so +%attr(755, root, root) %{_libdir}/mysql/plugin/debug/libdaemon_example.so %attr(755, root, root) %{_libdir}/mysql/plugin/debug/mypluglib.so %attr(755, root, root) %{_libdir}/mysql/plugin/debug/semisync_master.so %attr(755, root, root) %{_libdir}/mysql/plugin/debug/semisync_slave.so diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ea2f41abb73..b0e3342b1bc 100755..100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,4 +27,4 @@ IF(WITH_UNIT_TESTS) SET_TARGET_PROPERTIES(bug25714 PROPERTIES LINKER_LANGUAGE CXX) ENDIF() -INSTALL(TARGETS mysql_client_test DESTINATION bin) +INSTALL(TARGETS mysql_client_test DESTINATION ${INSTALL_BINDIR} COMPONENT Test) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a490cac054d..f18eb72a167 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -19060,6 +19060,63 @@ static void test_bug42373() } +/** + Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run +*/ + +static void test_bug54041() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind; + + DBUG_ENTER("test_bug54041"); + myheader("test_bug54041"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (a) VALUES (?)"); + check_stmt(stmt); + verify_param_count(stmt, 1); + + memset(&bind, 0, sizeof(bind)); + + /* Any type that does not support long data handling. */ + bind.buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_bind_param(stmt, &bind); + check_execute(stmt, rc); + + /* + Trick the client API into sending a long data packet for + the parameter. Long data is only supported for string and + binary types. + */ + stmt->params[0].buffer_type= MYSQL_TYPE_STRING; + + rc= mysql_stmt_send_long_data(stmt, 0, "data", 5); + check_execute(stmt, rc); + + /* Undo API violation. */ + stmt->params[0].buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_execute(stmt); + /* Incorrect arguments. */ + check_execute_r(stmt, rc); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + /* Bug#49972: Crash in prepared statements. @@ -19500,6 +19557,7 @@ static struct my_tests_st my_tests[]= { { "test_bug44495", test_bug44495 }, { "test_bug49972", test_bug49972 }, { "test_bug42373", test_bug42373 }, + { "test_bug54041", test_bug54041 }, { 0, 0 } }; diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt index dae2ed2bb2f..dae2ed2bb2f 100755..100644 --- a/vio/CMakeLists.txt +++ b/vio/CMakeLists.txt diff --git a/win/mysql_manifest.cmake b/win/mysql_manifest.cmake index 611553d68ac..611553d68ac 100755..100644 --- a/win/mysql_manifest.cmake +++ b/win/mysql_manifest.cmake diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 4be153bfdfa..4be153bfdfa 100755..100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt |