diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index e947df15e8e71..0defa2d41f1f3 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -126,8 +126,10 @@ get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL # implementation of SSL. --with-ssl=yes will first try system library # then the bundled one --with-ssl=system will use the system library. -# We use bundled by default as this is guaranteed to work with Galera -SSL_LIBRARY=--with-ssl=bundled +# We normally use bundled by default as this is guaranteed to work with Galera +# However as bundled gives problem on SuSE with tls_version1.test, system +# is used +SSL_LIBRARY=--with-ssl=system if [ "x$warning_mode" = "xpedantic" ]; then warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8023bb6ba38..ba1f422f602f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,15 @@ ENDIF() OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system libraries. Only set it you never plan to distribute the resulting binaries" OFF) +# +# Enable protection of statement's memory root after first SP/PS execution. +# Can be switched on only for debug build. +# +OPTION(WITH_PROTECT_STATEMENT_MEMROOT "Enable protection of statement's memory root after first SP/PS execution. Turned into account only for debug build" OFF) +IF (CMAKE_BUILD_TYPE MATCHES "Debug" AND WITH_PROTECT_STATEMENT_MEMROOT) + ADD_DEFINITIONS(-DPROTECT_STATEMENT_MEMROOT) +ENDIF() + INCLUDE(check_compiler_flag) INCLUDE(check_linker_flag) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 739c8729e1c77..b88150202cafb 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1639,7 +1639,7 @@ static struct my_option my_options[] = "given sequence numbers are printed.", &stop_pos_str, &stop_pos_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"table", 'T', "List entries for just this table (local log only).", + {"table", 'T', "List entries for just this table (affects only row events).", &table, &table, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"to-last-log", 't', "Requires -R. Will not stop at the end of the \ diff --git a/client/mysqltest.cc b/client/mysqltest.cc index dfba52e4bd158..5d9e4461f5eff 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1037,35 +1037,38 @@ static int do_read_query_result(struct st_connection *cn) static int do_stmt_prepare(struct st_connection *cn, const char *q, int q_len) { /* The cn->stmt is already set. */ + DBUG_ENTER("do_stmt_prepare"); if (!cn->has_thread) - return mysql_stmt_prepare(cn->stmt, q, q_len); + DBUG_RETURN(mysql_stmt_prepare(cn->stmt, q, q_len)); cn->cur_query= q; cn->cur_query_len= q_len; signal_connection_thd(cn, EMB_PREPARE_STMT); wait_query_thread_done(cn); - return cn->result; + DBUG_RETURN(cn->result); } static int do_stmt_execute(struct st_connection *cn) { + DBUG_ENTER("do_stmt_execute"); /* The cn->stmt is already set. */ if (!cn->has_thread) - return mysql_stmt_execute(cn->stmt); + DBUG_RETURN(mysql_stmt_execute(cn->stmt)); signal_connection_thd(cn, EMB_EXECUTE_STMT); wait_query_thread_done(cn); - return cn->result; + DBUG_RETURN(cn->result); } static int do_stmt_close(struct st_connection *cn) { + DBUG_ENTER("do_stmt_close"); /* The cn->stmt is already set. */ if (!cn->has_thread) - return mysql_stmt_close(cn->stmt); + DBUG_RETURN(mysql_stmt_close(cn->stmt)); signal_connection_thd(cn, EMB_CLOSE_STMT); wait_query_thread_done(cn); - return cn->result; + DBUG_RETURN(cn->result); } @@ -7967,6 +7970,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) if (!(count= mysql_warning_count(mysql))) DBUG_RETURN(0); + DBUG_PRINT("info", ("Warnings: %ud", count)); /* If one day we will support execution of multi-statements @@ -8422,6 +8426,7 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, char *query, size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings) { + my_bool ignore_second_execution= 0; MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL *mysql= cn->mysql; MYSQL_STMT *stmt; @@ -8429,6 +8434,9 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, DYNAMIC_STRING ds_execute_warnings; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); + DBUG_PRINT("info", + ("disable_warnings: %d prepare_warnings_enabled: %d", + (int) disable_warnings, (int) prepare_warnings_enabled)); if (!mysql) { @@ -8499,12 +8507,18 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); goto end; } + /* + We cannot run query twice if we get prepare warnings as these will otherwise be + disabled + */ + ignore_second_execution= (prepare_warnings_enabled && + mysql_warning_count(mysql) != 0); } /* Execute the query */ - if (do_stmt_execute(cn)) + if (!ignore_second_execution && do_stmt_execute(cn)) { handle_error(command, mysql_stmt_errno(stmt), mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); @@ -8579,7 +8593,10 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, that warnings from both the prepare and execute phase are shown. */ if (!disable_warnings && !prepare_warnings_enabled) + { + DBUG_PRINT("info", ("warnings disabled")); dynstr_set(&ds_prepare_warnings, NULL); + } } else { @@ -8682,7 +8699,9 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, error - function will not return */ -void run_prepare_stmt(struct st_connection *cn, struct st_command *command, const char *query, size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings) +void run_prepare_stmt(struct st_connection *cn, struct st_command *command, + const char *query, size_t query_len, DYNAMIC_STRING *ds, + DYNAMIC_STRING *ds_warnings) { MYSQL *mysql= cn->mysql; @@ -8843,9 +8862,8 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, */ void run_execute_stmt(struct st_connection *cn, struct st_command *command, - const char *query, size_t query_len, DYNAMIC_STRING *ds, - DYNAMIC_STRING *ds_warnings - ) + const char *query, size_t query_len, DYNAMIC_STRING *ds, + DYNAMIC_STRING *ds_warnings) { MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL *mysql= cn->mysql; diff --git a/cmake/stack_direction.c b/cmake/stack_direction.c deleted file mode 100644 index 1f7a5d0b13517..0000000000000 --- a/cmake/stack_direction.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2009 Sun Microsystems, Inc. - Use is subject to license terms. - - 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-1335 USA */ - -/* Check stack direction (0-down, 1-up) */ -int f(int *a) -{ - int b; - return(&b > a)?1:0; -} -/* - Prevent compiler optimizations by calling function - through pointer. -*/ -volatile int (*ptr_f)(int *) = f; -int main() -{ - int a; - return ptr_f(&a); -} diff --git a/configure.cmake b/configure.cmake index b13d527742bc9..dbd77a6e00f11 100644 --- a/configure.cmake +++ b/configure.cmake @@ -672,25 +672,11 @@ int main() } " HAVE_PTHREAD_YIELD_ZERO_ARG) -IF(NOT STACK_DIRECTION) - IF(CMAKE_CROSSCOMPILING AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR) - MESSAGE(FATAL_ERROR - "STACK_DIRECTION is not defined. Please specify -DSTACK_DIRECTION=1 " - "or -DSTACK_DIRECTION=-1 when calling cmake.") - ELSE() - TRY_RUN(STACKDIR_RUN_RESULT STACKDIR_COMPILE_RESULT - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/cmake/stack_direction.c - ) - # Test program returns 0 (down) or 1 (up). - # Convert to -1 or 1 - IF(STACKDIR_RUN_RESULT EQUAL 0) - SET(STACK_DIRECTION -1 CACHE INTERNAL "Stack grows direction") - ELSE() - SET(STACK_DIRECTION 1 CACHE INTERNAL "Stack grows direction") - ENDIF() - MESSAGE(STATUS "Checking stack direction : ${STACK_DIRECTION}") - ENDIF() +IF(STACK_DIRECTION) +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(parisc|hppa)") + SET(STACK_DIRECTION 1 CACHE INTERNAL "Stack grows direction") +ELSE() + SET(STACK_DIRECTION -1 CACHE INTERNAL "Stack grows direction") ENDIF() # diff --git a/debian/rules b/debian/rules index 08ca3b8f96e01..10915411a4510 100755 --- a/debian/rules +++ b/debian/rules @@ -51,16 +51,6 @@ ifeq (32,$(DEB_HOST_ARCH_BITS)) CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO endif -# Cross building requires stack direction instruction -ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) - ifneq (,$(filter $(DEB_HOST_ARCH_CPU),alpha amd64 arm arm64 i386 ia64 m68k mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x sh4 sparc64)) - CMAKEFLAGS += -DSTACK_DIRECTION=-1 - endif - ifneq (,$(filter $(DEB_HOST_ARCH_CPU),hppa)) - CMAKEFLAGS += -DSTACK_DIRECTION=1 - endif -endif - # Only attempt to build with PMEM on archs that have package libpmem-dev available # See https://packages.debian.org/search?searchon=names&keywords=libpmem-dev ifneq (,$(filter $(DEB_HOST_ARCH),amd64 arm64 ppc64el riscv64)) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 0b8d993adbfac..e221bbf269353 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -80,6 +80,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include "trx0sys.h" #include +#include #include "ha_innodb.h" #include @@ -2385,10 +2386,15 @@ static bool innodb_init() buf_flush_sync(); recv_sys.debug_free(); ut_ad(!os_aio_pending_reads()); - ut_ad(!os_aio_pending_writes()); ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex)); ut_ad(!buf_pool.get_oldest_modification(0)); ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex)); + /* os_aio_pending_writes() may hold here if some write_io_callback() + did not release the slot yet. However, the page write itself must + have completed, because the buf_pool.flush_list is empty. In debug + builds, we wait for this to happen, hoping to get a hung process if + this assumption does not hold. */ + ut_d(os_aio_wait_until_no_pending_writes(false)); log_sys.close_file(); if (xtrabackup_incremental) @@ -4693,7 +4699,9 @@ static bool xtrabackup_backup_func() goto fail; } - log_sys.create(); + if (!log_sys.create()) { + goto fail; + } /* get current checkpoint_lsn */ { mysql_mutex_lock(&recv_sys.mutex); @@ -6057,7 +6065,9 @@ static bool xtrabackup_prepare_func(char** argv) } recv_sys.create(); - log_sys.create(); + if (!log_sys.create()) { + goto error; + } recv_sys.recovery_on = true; xb_fil_io_init(); diff --git a/extra/wolfssl/CMakeLists.txt b/extra/wolfssl/CMakeLists.txt index c034db01ce2e9..271e76b8c45ae 100644 --- a/extra/wolfssl/CMakeLists.txt +++ b/extra/wolfssl/CMakeLists.txt @@ -102,6 +102,9 @@ ${WOLFCRYPT_SRCDIR}/rsa.c ${WOLFCRYPT_SRCDIR}/sha.c ${WOLFCRYPT_SRCDIR}/sha256.c ${WOLFCRYPT_SRCDIR}/sha512.c +${WOLFCRYPT_SRCDIR}/poly1305.c +${WOLFCRYPT_SRCDIR}/chacha.c +${WOLFCRYPT_SRCDIR}/chacha20_poly1305.c ${WOLFCRYPT_SRCDIR}/wc_port.c ${WOLFCRYPT_SRCDIR}/wc_encrypt.c ${WOLFCRYPT_SRCDIR}/hash.c @@ -159,6 +162,8 @@ IF(WOLFSSL_X86_64_BUILD) LIST(APPEND WOLFCRYPT_SOURCES ${WOLFCRYPT_SRCDIR}/aes_asm.S ${WOLFCRYPT_SRCDIR}/aes_gcm_asm.S + ${WOLFCRYPT_SRCDIR}/chacha_asm.S + ${WOLFCRYPT_SRCDIR}/poly1305_asm.S ${WOLFCRYPT_SRCDIR}/sha512_asm.S ${WOLFCRYPT_SRCDIR}/sha256_asm.S) ADD_DEFINITIONS(-maes -msse4.2 -mpclmul) diff --git a/extra/wolfssl/user_settings.h.in b/extra/wolfssl/user_settings.h.in index 2355fd1691ca6..425f6f154b9f0 100644 --- a/extra/wolfssl/user_settings.h.in +++ b/extra/wolfssl/user_settings.h.in @@ -19,11 +19,15 @@ #define HAVE_TLS_EXTENSIONS #define HAVE_AES_ECB #define HAVE_AESGCM +#define HAVE_CHACHA +#define HAVE_POLY1305 #define WOLFSSL_AES_COUNTER #define NO_WOLFSSL_STUB #define OPENSSL_ALL #define WOLFSSL_ALLOW_TLSV10 #define NO_OLD_TIMEVAL_NAME +#define HAVE_SECURE_RENEGOTIATION +#define HAVE_EXTENDED_MASTER /* TLSv1.3 definitions (all needed to build) */ #define WOLFSSL_TLS13 diff --git a/include/m_ctype.h b/include/m_ctype.h index 6812445c6d54b..4aa2c2d6e334f 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -1020,6 +1020,12 @@ struct charset_info_st return (coll->strnncollsp)(this, (uchar *) a, alen, (uchar *) b, blen); } + int strnncollsp(const LEX_CSTRING &a, const LEX_CSTRING &b) const + { + return (coll->strnncollsp)(this, (uchar *) a.str, a.length, + (uchar *) b.str, b.length); + } + size_t strnxfrm(char *dst, size_t dstlen, uint nweights, const char *src, size_t srclen, uint flags) const { diff --git a/include/my_alloc.h b/include/my_alloc.h index 944dcb6e1bdc5..caa4be8f0e528 100644 --- a/include/my_alloc.h +++ b/include/my_alloc.h @@ -53,6 +53,10 @@ typedef struct st_mem_root unsigned short first_block_usage; unsigned short flags; +#ifdef PROTECT_STATEMENT_MEMROOT + int read_only; +#endif + void (*error_handler)(void); PSI_memory_key psi_key; diff --git a/include/my_sys.h b/include/my_sys.h index a8246d9d3555f..528ef4b1d1930 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -161,6 +161,7 @@ extern my_thread_id (*sf_malloc_dbug_id)(void); typedef void (*MALLOC_SIZE_CB) (long long size, my_bool is_thread_specific); extern void set_malloc_size_cb(MALLOC_SIZE_CB func); +extern MALLOC_SIZE_CB update_malloc_size; /* defines when allocating data */ extern void *my_malloc(PSI_memory_key key, size_t size, myf MyFlags); @@ -898,6 +899,8 @@ extern void free_root(MEM_ROOT *root, myf MyFLAGS); extern void set_prealloc_root(MEM_ROOT *root, char *ptr); extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, size_t prealloc_size); +extern USED_MEM *get_last_memroot_block(MEM_ROOT* root); +extern void free_all_new_blocks(MEM_ROOT *root, USED_MEM *last_block); extern void protect_root(MEM_ROOT *root, int prot); extern char *strdup_root(MEM_ROOT *root,const char *str); static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) @@ -906,6 +909,7 @@ static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) } extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); + extern LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str); extern my_bool my_compress(uchar *, size_t *, size_t *); extern my_bool my_uncompress(uchar *, size_t , size_t *); diff --git a/include/mysql.h b/include/mysql.h index 031570a0fe5c7..a66dcc7bd0208 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -141,7 +141,6 @@ typedef unsigned long long my_ulonglong; #define ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN #define ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN #define ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS ER_UNSUPPORTED_ENGINE_FOR_GENERATED_COLUMNS -#define ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT ER_QUERY_RESULT_INCOMPLETE #define ER_KEY_COLUMN_DOES_NOT_EXITS ER_KEY_COLUMN_DOES_NOT_EXIST #define ER_DROP_PARTITION_NON_EXISTENT ER_PARTITION_DOES_NOT_EXIST diff --git a/include/mysql/service_my_crypt.h b/include/mysql/service_my_crypt.h index bb038aaa29550..1a4ebcfd0675c 100644 --- a/include/mysql/service_my_crypt.h +++ b/include/mysql/service_my_crypt.h @@ -45,7 +45,7 @@ extern "C" { /* The max key length of all supported algorithms */ #define MY_AES_MAX_KEY_LENGTH 32 -#define MY_AES_CTX_SIZE 672 +#define MY_AES_CTX_SIZE 1040 enum my_aes_mode { MY_AES_ECB, MY_AES_CBC diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index bbbe10121bad9..d4edd24291beb 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -1057,7 +1057,7 @@ class Client_field_extension: public Sql_alloc, public: Client_field_extension() { - memset(this, 0, sizeof(*this)); + memset((void*) this, 0, sizeof(*this)); } void copy_extended_metadata(MEM_ROOT *memroot, const Send_field_extended_metadata &src) diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc index 0de070e1994dc..8c9cdb54363d5 100644 --- a/mysql-test/include/have_innodb.inc +++ b/mysql-test/include/have_innodb.inc @@ -3,7 +3,7 @@ # will be skipped unless innodb is enabled # --disable_query_log -if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "MSAN%"`) +if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like 'MSAN%'`) { SET STATEMENT sql_log_bin=0 FOR call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operations"); diff --git a/mysql-test/include/have_innodb_16k.opt b/mysql-test/include/have_innodb_16k.opt new file mode 100644 index 0000000000000..2ece0f02d020d --- /dev/null +++ b/mysql-test/include/have_innodb_16k.opt @@ -0,0 +1 @@ +--innodb-page-size=16k diff --git a/mysql-test/include/have_innodb_32k.opt b/mysql-test/include/have_innodb_32k.opt new file mode 100644 index 0000000000000..cabc8fc73789a --- /dev/null +++ b/mysql-test/include/have_innodb_32k.opt @@ -0,0 +1 @@ +--innodb-page-size=32k diff --git a/mysql-test/include/have_innodb_4k.opt b/mysql-test/include/have_innodb_4k.opt new file mode 100644 index 0000000000000..e5b58602036b7 --- /dev/null +++ b/mysql-test/include/have_innodb_4k.opt @@ -0,0 +1 @@ +--innodb-page-size=4k diff --git a/mysql-test/include/have_innodb_64k.opt b/mysql-test/include/have_innodb_64k.opt new file mode 100644 index 0000000000000..c70123809fcbd --- /dev/null +++ b/mysql-test/include/have_innodb_64k.opt @@ -0,0 +1 @@ +--innodb-page-size=64k diff --git a/mysql-test/include/have_innodb_8k.opt b/mysql-test/include/have_innodb_8k.opt new file mode 100644 index 0000000000000..f75efe9af794e --- /dev/null +++ b/mysql-test/include/have_innodb_8k.opt @@ -0,0 +1 @@ +--innodb-page-size=8k diff --git a/mysql-test/include/have_normal_bzip.inc b/mysql-test/include/have_normal_bzip.inc new file mode 100644 index 0000000000000..36c06274398c8 --- /dev/null +++ b/mysql-test/include/have_normal_bzip.inc @@ -0,0 +1,9 @@ +--source include/have_compress.inc + +# Test that the system is using the default/standard bzip library. +# If not, we have to skip the test as the compression lengths displayed +# in the test will not match the results from used compression library. + +if (`select length(COMPRESS(space(5000))) != 33`) { + skip Test skipped as standard bzip is needed; +} diff --git a/mysql-test/include/linux.inc b/mysql-test/include/linux.inc index f24832ca4768f..cc126ff1d733b 100644 --- a/mysql-test/include/linux.inc +++ b/mysql-test/include/linux.inc @@ -1,4 +1,4 @@ -if (`select convert(@@version_compile_os using latin1) LIKE 'Linux' = 0`) +if (`select @@version_compile_os not LIKE 'Linux%'`) { skip Need Linux; } diff --git a/mysql-test/include/rpl_change_topology.inc b/mysql-test/include/rpl_change_topology.inc index 387ab196ad16b..b63700b059b75 100644 --- a/mysql-test/include/rpl_change_topology.inc +++ b/mysql-test/include/rpl_change_topology.inc @@ -5,15 +5,15 @@ # need to change topology after they have sourced include/rpl_init.inc # # This file sets up variables needed by include/rpl_sync.inc and many -# other replication scripts in the include/ directory. It also issues +# other replication scripts in the include/ directory. It also issues # CHANGE MASTER on all servers where the configuration changes from -# what it was before. It does not issue START SLAVE (use +# what it was before. It does not issue START SLAVE (use # include/rpl_start_slaves.inc for that). # # Note: it is not currently possible to change the number of servers # after the rpl_init.inc, without first calling rpl_end.inc. So the # test has to set $rpl_server_count to the total number of servers -# that the test uses, before it sources include/rpl_init.inc. After +# that the test uses, before it sources include/rpl_init.inc. After # that, $rpl_server_count must not change until after next time the # test sources include/rpl_end.inc. # @@ -37,7 +37,7 @@ # By default, CHANGE MASTER is executed with MASTER_LOG_FILE set # to the name of the last binlog file on the master (retrieved by # executing SHOW MASTER STATUS). This variable can be set to -# specify another filename. This variable should be a +# specify another filename. This variable should be a # comma-separated list of the following form: # # SERVER_NUMBER_1:FILE_NAME_1,SERVER_NUMBER_2:FILE_NAME_2,... @@ -45,7 +45,7 @@ # Before CHANGE MASTER is executed on server N, this script checks # if $rpl_master_log_file contains the text N:FILE_NAME. If it # does, then MASTER_LOG_FILE is set to FILE_NAME. Otherwise, -# MASTER_LOG_FILE is set to the last binlog on the master. For +# MASTER_LOG_FILE is set to the last binlog on the master. For # example, to specify that server_1 should start replicate from # master-bin.000007 and server_5 should start replicate from # master-bin.012345, do: @@ -53,9 +53,9 @@ # # $rpl_master_log_pos # By default, CHANGE MASTER is executed without specifying the -# MASTER_LOG_POS parameter. This variable can be set to set a -# specific position. It has the same form as $rpl_master_log_file -# (see above). For example, to specify that server_3 should start +# MASTER_LOG_POS parameter. This variable can be set to set a +# specific position. It has the same form as $rpl_master_log_file +# (see above). For example, to specify that server_3 should start # replicate from position 4711 of its master, do: # --let $rpl_master_log_pos= 3:4711 # @@ -72,7 +72,7 @@ # include/rpl_stop_slaves.inc # include/rpl_end.inc # -# $rpl_server_count_length: +# $rpl_server_count_length # Set to LENGTH($rpl_server_count). So if $rpl_server_count < 10, # then $rpl_server_count_length = 1; if 10 <= $rpl_server_count < # 100, then $rpl_server_count_length = 2, etc. @@ -83,12 +83,12 @@ # server N is a slave, then the N'th number is the master of server # N. If server N is not a slave, then the N'th number is just spaces # (so in fact it is not a number). For example, if $rpl_topology is -# '1->2,2->3,3->1,2->4,5->6', then $rpl_master_list is '3122 6'. +# '1->2,2->3,3->1,2->4,5->6', then $rpl_master_list is '3122 5'. # # $rpl_sync_chain_dirty -# This variable is set to 1. This tells include/rpl_sync.inc to +# This variable is set to 1. This tells include/rpl_sync.inc to # compute a new value for $rpl_sync_chain next time that -# include/rpl_sync.inc is sourced. See +# include/rpl_sync.inc is sourced. See # include/rpl_generate_sync_chain.inc and include/rpl_sync.inc for # details. @@ -124,7 +124,7 @@ if ($rpl_master_list == '') if ($rpl_debug) { --echo \$rpl_server_count='$rpl_server_count' - --echo \$rpl_server_count_length='$rpl_server_count_length' + --echo old \$rpl_server_count_length='$rpl_server_count_length' --echo new \$rpl_topology='$_rpl_topology' --echo old \$rpl_master_list='$rpl_master_list' --echo old \$rpl_sync_chain='$rpl_sync_chain' @@ -210,6 +210,10 @@ if (!$rpl_skip_change_master) --let $rpl_connection_name= server_$_rpl_master --source include/rpl_connection.inc --let $_rpl_master_log_file= query_get_value(SHOW MASTER STATUS, File, 1) + if ($rpl_debug) + { + --echo "\$rpl_master_log_file parameter not set for the master: $_rpl_master, use the latest binlog file by executing SHOW MASTER STATUS." + } } # Change connection. --let $rpl_connection_name= server_$_rpl_server @@ -224,6 +228,10 @@ if (!$rpl_skip_change_master) if (!$_rpl_master_log_pos_index) { --let $_rpl_master_log_pos= + if ($rpl_debug) + { + --echo "\$rpl_master_log_pos parameter not set for the master: $_rpl_master. Set log position to empty." + } } if ($rpl_master_log_file) { diff --git a/mysql-test/include/rpl_connect.inc b/mysql-test/include/rpl_connect.inc index e30769eb3353a..a962ba6f60132 100644 --- a/mysql-test/include/rpl_connect.inc +++ b/mysql-test/include/rpl_connect.inc @@ -5,7 +5,7 @@ # This script is normally used internally by rpl_init.inc and # master-slave.inc, but it can also be used in test cases that need to # create more connections or re-create connections after disconnect. -# +# Default ports SERVER_MYPORT_[1,2] are set by rpl_init.inc. # # ==== Usage ==== # diff --git a/mysql-test/include/rpl_end.inc b/mysql-test/include/rpl_end.inc index f49079db3328f..02564a9258038 100644 --- a/mysql-test/include/rpl_end.inc +++ b/mysql-test/include/rpl_end.inc @@ -103,11 +103,9 @@ while ($_rpl_server) --connection default --let $_rpl_server= $rpl_server_count ---let $_rpl_one= _1 while ($_rpl_server) { --disconnect server_$_rpl_server - --disconnect server_$_rpl_server$_rpl_one --dec $_rpl_server } diff --git a/mysql-test/include/rpl_for_each_slave.inc b/mysql-test/include/rpl_for_each_slave.inc index 65d242cf8948c..c1d4581dfa544 100644 --- a/mysql-test/include/rpl_for_each_slave.inc +++ b/mysql-test/include/rpl_for_each_slave.inc @@ -1,7 +1,7 @@ # ==== Purpose ==== # # Execute a .inc file once for each server that was configured as a -# slave by rpl_init.inc +# slave by rpl_init.inc, for example start_slave.inc or stop_slave.inc file. # # # ==== Usage ==== @@ -14,6 +14,20 @@ # $rpl_source_file # The file that will be sourced. # +# $rpl_server_count +# The number of servers to configure. If this is not set, the largest +# number in $rpl_topology will be used. +# This parameter is obtained from rpl_init.inc. +# +# $rpl_master_list +# This parameter is calculated from within rpl_init.inc. +# +# $rpl_server_count_length +# Set to LENGTH($rpl_server_count). So if $rpl_server_count < 10, +# then $rpl_server_count_length = 1; if 10 <= $rpl_server_count < +# 100, then $rpl_server_count_length = 2, etc. +# This parameter is calculated from within rpl_change_topology.inc. +# # $rpl_debug # See include/rpl_init.inc diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index acb9104ae6f40..26ce4e1b57fd8 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -3,18 +3,16 @@ # Set up replication on several servers in a specified topology. # # By default, this script does the following: -# - Creates the connections server_1, server_2, ..., server_N, as -# well as extra connections server_1_1, server_2_1, ..., -# server_N_1. server_I and server_I_1 are connections to the same -# server. -# - Verifies that @@server_id of all servers are different. +# - Creates the connections server_1, server_2, ..., server_N. # - Calls RESET MASTER, RESET SLAVE, USE test, CHANGE MASTER, START SLAVE. # - Sets the connection to server_1 before exiting. +# With $rpl_check_server_ids parameter, the script does the following: +# - Verifies that @@server_id of all servers are different. # # ==== Usage ==== # # 1. If you are going to use more than two servers, create -# rpl_test.cfg with the following contents: +# rpl_test.cnf with the following contents: # # !include ../my.cnf # [mysqld.1] @@ -34,8 +32,9 @@ # # (It is allowed, but not required, to configure SERVER_MYPORT_1 # and SERVER_MYPORT_2 too. If these variables are not set, the -# variables MASTER_MYPORT and SLAVE_MYPORT, configured in the -# default my.cnf used by the rpl suite, are used instead.) +# variables MASTER_MYPORT and SLAVE_MYPORT are used instead. +# These variables are configured in the rpl_1slave_base.cnf, +# that is used in the default my.cnf, which is used by the rpl suite.) # # 2. Execute the following near the top of the test: # @@ -147,18 +146,15 @@ if (!$rpl_debug) } -# Create two connections to each server; reset master/slave, select +# Create connection to the server; reset master/slave, select # database, set autoinc variables. --let $_rpl_server= $rpl_server_count ---let $_rpl_one= _1 while ($_rpl_server) { # Connect. --let $rpl_server_number= $_rpl_server --let $rpl_connection_name= server_$_rpl_server --source include/rpl_connect.inc - --let $rpl_connection_name= server_$_rpl_server$_rpl_one - --source include/rpl_connect.inc # Configure server. --let $rpl_connection_name= server_$_rpl_server @@ -203,7 +199,7 @@ if ($rpl_check_server_ids) while ($_rpl_server2) { --let $assert_text= Servers $_rpl_server and $_rpl_server2 should have different @@server_id - --let $assert_condition= [$_rpl_server:SELECT @@server_id AS i, i, 1] != [$_rpl_server2:SELECT @@server_id AS i, i, 1] + --let $assert_cond= [SELECT @@server_id AS i, i, 1] != $_rpl_server --source include/assert.inc --dec $_rpl_server2 @@ -212,18 +208,30 @@ if ($rpl_check_server_ids) } } -# $rpl_master_list must be set so that include/rpl_change_topology.inc -# knows which servers are initialized and not. +if ($rpl_debug) +{ + --echo ---- Check the topology and call CHANGE MASTER ---- +} + +# $rpl_master_list must be set so that include/rpl_change_topology.inc and later +# include/rpl_for_each_slave.inc knows which servers are initialized and not. --let $rpl_master_list= `SELECT REPEAT('x', $rpl_server_count * LENGTH($rpl_server_count))` --source include/rpl_change_topology.inc if (!$rpl_skip_start_slave) { + if ($rpl_debug) + { + --echo ---- Start slaves ---- + } --source include/rpl_start_slaves.inc } - +if ($rpl_debug) +{ + --echo ---- Set connection to the server_1 ---- +} --let $rpl_connection_name= server_1 --source include/rpl_connection.inc diff --git a/mysql-test/include/rpl_reconnect.inc b/mysql-test/include/rpl_reconnect.inc index cdbbd0a1bf112..9438c7744617e 100644 --- a/mysql-test/include/rpl_reconnect.inc +++ b/mysql-test/include/rpl_reconnect.inc @@ -72,11 +72,6 @@ if (!$_rpl_server_number) --source include/rpl_connection.inc --enable_reconnect ---let $_rpl_one= _1 ---let $rpl_connection_name= server_$rpl_server_number$_rpl_one ---source include/rpl_connection.inc ---enable_reconnect - if ($rpl_debug) { --echo ---- Wait for reconnect and disable reconnect on all connections ---- @@ -122,11 +117,5 @@ if (!$_rpl_server_number) --source include/wait_until_connected_again.inc --disable_reconnect ---let $rpl_connection_name= server_$rpl_server_number$_rpl_one ---source include/rpl_connection.inc ---source include/wait_until_connected_again.inc ---disable_reconnect - - --let $include_filename= rpl_reconnect.inc --source include/end_include_file.inc diff --git a/mysql-test/include/rpl_start_slaves.inc b/mysql-test/include/rpl_start_slaves.inc index fdd90eb12c5ef..9c1f9f7b2937e 100644 --- a/mysql-test/include/rpl_start_slaves.inc +++ b/mysql-test/include/rpl_start_slaves.inc @@ -19,7 +19,7 @@ # # $slave_timeout # Set the timeout when waiting for slave threads to stop and -# start, respectively. See include/wait_for_slave_param.inc +# start, respectively. See include/wait_for_slave_param.inc --let $include_filename= rpl_start_slaves.inc diff --git a/mysql-test/include/wait_for_slave_io_to_start.inc b/mysql-test/include/wait_for_slave_io_to_start.inc index cd8e5d374a4db..0cb4091755c2f 100644 --- a/mysql-test/include/wait_for_slave_io_to_start.inc +++ b/mysql-test/include/wait_for_slave_io_to_start.inc @@ -14,13 +14,14 @@ # # Parameters: # $slave_timeout -# See include/wait_for_slave_param.inc +# Timeout used when waiting for the slave IO thread to start. +# See include/wait_for_slave_param.inc. # # $rpl_allow_error # By default, this file fails if there is an error in the IO -# thread. However, the IO thread can recover and reconnect after -# certain errors. If such an error is expected, can set -# $rpl_allow_error=1. This will prevent this file from failing if +# thread. However, the IO thread can recover and reconnect after +# certain errors. If such an error is expected, can set +# $rpl_allow_error=1. This will prevent this file from failing if # there is an error in the IO thread. # # $rpl_debug diff --git a/mysql-test/include/wait_for_slave_sql_to_start.inc b/mysql-test/include/wait_for_slave_sql_to_start.inc index 4aea9fba5699f..9286f1a08a2e7 100644 --- a/mysql-test/include/wait_for_slave_sql_to_start.inc +++ b/mysql-test/include/wait_for_slave_sql_to_start.inc @@ -11,6 +11,7 @@ # # Parameters: # $slave_timeout +# Timeout used when waiting for the slave SQL thread to start. # See include/wait_for_slave_param.inc # # $rpl_debug @@ -25,7 +26,7 @@ let $slave_param= Slave_SQL_Running; let $slave_param_value= Yes; # Unfortunately, the slave sql thread sets Slave_SQL_Running=Yes -# *before* it clears Last_SQL_Errno. So we have to allow errors in +# *before* it clears Last_SQL_Errno. So we have to allow errors in # the SQL thread here. #--let $slave_error_param= Last_SQL_Errno diff --git a/mysql-test/include/wait_for_slave_to_start.inc b/mysql-test/include/wait_for_slave_to_start.inc index a916e2ea615ad..742e7f7e0b4a6 100644 --- a/mysql-test/include/wait_for_slave_to_start.inc +++ b/mysql-test/include/wait_for_slave_to_start.inc @@ -12,6 +12,7 @@ # # Parameters: # $slave_timeout +# Timeout used when waiting for the slave threads to start. # See include/wait_for_slave_param.inc # # $rpl_debug diff --git a/mysql-test/lib/My/Debugger.pm b/mysql-test/lib/My/Debugger.pm index 376325cf64496..b068698e3405f 100644 --- a/mysql-test/lib/My/Debugger.pm +++ b/mysql-test/lib/My/Debugger.pm @@ -94,7 +94,7 @@ py import subprocess,shlex,time valg=subprocess.Popen(shlex.split("""valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --num-callers=16 --quiet --suppressions=valgrind.supp --vgdb-error=0 {exe} {args} --loose-wait-for-pos-timeout=1500""")) time.sleep(2) -gdb.execute("target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=" + str(valg.pid)) +gdb.execute("target remote | vgdb --pid=" + str(valg.pid)) EEE pre => sub { my $debug_libraries_path= "/usr/lib/debug"; diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index b8bc9f8ec846a..2b32ef87b8196 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -20,9 +20,10 @@ package My::Platform; use strict; use File::Basename; use File::Path; +use Carp; use base qw(Exporter); -our @EXPORT= qw(IS_CYGWIN IS_WINDOWS IS_WIN32PERL IS_AIX +our @EXPORT= qw(IS_CYGWIN IS_MSYS IS_WINDOWS IS_WIN32PERL IS_AIX native_path posix_path mixed_path check_socket_path_length process_alive open_for_append); @@ -33,9 +34,15 @@ BEGIN { die "Could not execute 'cygpath': $!"; } eval 'sub IS_CYGWIN { 1 }'; + eval 'sub IS_MSYS { 0 }'; + } + elsif ($^O eq "msys") { + eval 'sub IS_CYGWIN { 1 }'; + eval 'sub IS_MSYS { 1 }'; } else { eval 'sub IS_CYGWIN { 0 }'; + eval 'sub IS_MSYS { 0 }'; } if ($^O eq "MSWin32") { eval 'sub IS_WIN32PERL { 1 }'; @@ -95,8 +102,13 @@ sub mixed_path { sub native_path { my ($path)= @_; - $path=~ s/\//\\/g - if (IS_CYGWIN or IS_WIN32PERL); + if (IS_CYGWIN) { + # \\\\ protects against 2 expansions (just for the case) + $path=~ s/\/+|\\+/\\\\\\\\/g; + } + elsif (IS_WINDOWS) { + $path=~ s/\/+/\\/g; + } return $path; } @@ -219,4 +231,69 @@ sub open_for_append } +sub check_cygwin_subshell +{ + # Only pipe (or sh-expansion) is fed to /bin/sh + my $out= `echo %comspec%|cat`; + return ($out =~ /\bcmd.exe\b/) ? 0 : 1; +} + +sub install_shell_wrapper() +{ + system("rm -f /bin/sh.exe") and die $!; + my $wrapper= <<'EOF'; +#!/bin/bash +if [[ -n "$MTR_PERL" && "$1" = "-c" ]]; then + shift + exec $(cygpath -m "$COMSPEC") /C "$@" +fi +exec /bin/bash "$@" +EOF + open(OUT, '>', "/bin/sh") or die "/bin/sh: $!\n"; + print OUT $wrapper; + close(OUT); + system("chmod +x /bin/sh") and die $!; + print "Cygwin subshell wrapper /bin/sh was installed, please restart MTR!\n"; + exit(0); +} + +sub uninstall_shell_wrapper() +{ + system("rm -f /bin/sh") and die $!; + system("cp /bin/bash.exe /bin/sh.exe") and die $!; +} + +sub cygwin_subshell_fix +{ + my ($opt_name, $opt_value)= @_; + if ($opt_name ne "cygwin-subshell-fix") { + confess "Wrong option name: ${opt_name}"; + } + if ($opt_value eq "do") { + if (check_cygwin_subshell()) { + install_shell_wrapper(); + } else { + print "Cygwin subshell fix was already installed, skipping...\n"; + } + } elsif ($opt_value eq "remove") { + if (check_cygwin_subshell()) { + print "Cygwin subshell fix was already uninstalled, skipping...\n"; + } else { + uninstall_shell_wrapper(); + } + } else { + die "Wrong --cygwin-subshell-fix value: ${opt_value} (expected do/remove)"; + } +} + +sub options +{ + if (IS_CYGWIN) { + return ('cygwin-subshell-fix=s' => \&cygwin_subshell_fix); + } else { + return (); + } +} + + 1; diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 69033649b46cb..e3b46b3709ea2 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -102,7 +102,7 @@ else # Find the safe process binary or script sub find_bin { - if (IS_WIN32PERL or IS_CYGWIN) + if (IS_WINDOWS) { # Use my_safe_process.exe my $exe= my_find_bin($bindir, ["lib/My/SafeProcess", "My/SafeProcess"], diff --git a/mysql-test/lib/My/Test.pm b/mysql-test/lib/My/Test.pm index 49ce2fb5af9f6..56e7cf6d8a4c1 100644 --- a/mysql-test/lib/My/Test.pm +++ b/mysql-test/lib/My/Test.pm @@ -111,7 +111,7 @@ sub read_test { $serialized =~ s/\\([0-9a-fA-F]{2})/chr(hex($1))/eg; my $test= Storable::thaw($serialized); use Data::Dumper; - die "wrong class (hack attempt?): ".ref($test)."\n".Dumper(\$test, $serialized) + confess "Not My::Test: ". ref($test). "\n". Dumper(\$test, $serialized) unless ref($test) eq 'My::Test'; resfile_from_test($test) if $::opt_resfile; return $test; diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 2a8ed65eb2c19..7d944ade71a62 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -48,6 +48,7 @@ our $timestamp= 0; our $timediff= 0; our $name; our $verbose; +# TODO: no option for that? Why is it different from $verbose? our $verbose_restart= 0; our $timer= 1; our $tests_total; diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index 1508bb9d34aae..d1406387fc62d 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -3072,6 +3072,40 @@ drop table t1; # End of 10.5 tests # # +# MDEV-32449 Server crashes in Alter_info::add_stat_drop_index upon CREATE TABLE +# +CREATE TABLE t1 ( +`altcol1` blob DEFAULT '', +KEY `altcol1` (`altcol1`(2300)) +) ROW_FORMAT=PAGE, ENGINE=Aria; +ALTER TABLE t1 ADD FOREIGN KEY h (`altcol1`) REFERENCES t1 (`altcol1`) ON UPDATE SET DEFAULT, ALGORITHM=COPY; +Warnings: +Note 1071 Specified key was too long; max key length is 2300 bytes +create or replace table t2 like t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `altcol1` blob DEFAULT '', + KEY `altcol1` (`altcol1`(2300)), + KEY `h` (`altcol1`(2300)) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 ROW_FORMAT=PAGE +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `altcol1` blob DEFAULT '', + KEY `altcol1` (`altcol1`(2300)) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 ROW_FORMAT=PAGE +drop table t1,t2; +# Another test for MDEV-32449 +CREATE TABLE t1 (a POINT, b POINT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t (b); +CREATE TEMPORARY TABLE t2 LIKE t1; +DROP TEMPORARY TABLE t2; +DROP TABLE t1; +# +# End of 10.6 tests +# +# # MDEV-26767 Server crashes when rename table and alter storage engine # alter table txxx engine=innodb, rename to tyyy; diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index ebf10008f4804..54e2d9db49035 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2369,6 +2369,32 @@ drop table t1; --echo # End of 10.5 tests --echo # +--echo # +--echo # MDEV-32449 Server crashes in Alter_info::add_stat_drop_index upon CREATE TABLE +--echo # + +CREATE TABLE t1 ( + `altcol1` blob DEFAULT '', + KEY `altcol1` (`altcol1`(2300)) +) ROW_FORMAT=PAGE, ENGINE=Aria; +ALTER TABLE t1 ADD FOREIGN KEY h (`altcol1`) REFERENCES t1 (`altcol1`) ON UPDATE SET DEFAULT, ALGORITHM=COPY; +create or replace table t2 like t1; +show create table t1; +show create table t2; +drop table t1,t2; + +--echo # Another test for MDEV-32449 + +CREATE TABLE t1 (a POINT, b POINT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t (b); +CREATE TEMPORARY TABLE t2 LIKE t1; +DROP TEMPORARY TABLE t2; +DROP TABLE t1; + +--echo # +--echo # End of 10.6 tests +--echo # + --echo # --echo # MDEV-26767 Server crashes when rename table and alter storage engine --echo # diff --git a/mysql-test/main/analyze.result b/mysql-test/main/analyze.result index a1332abd177ce..aac9ed7b3a25d 100644 --- a/mysql-test/main/analyze.result +++ b/mysql-test/main/analyze.result @@ -71,3 +71,351 @@ optimize table t1 extended; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'extended' at line 1 drop table t1; End of 5.0 tests +# +# Test analyze of text column (not yet supported) +# +set optimizer_use_condition_selectivity=4; +set histogram_type='single_prec_hb'; +set histogram_size=255; +create table t1 (a int not null, t tinytext, tx text); +insert into t1 select seq+1, repeat('X',seq*5), repeat('X',seq*10) from seq_0_to_50; +insert into t1 select seq+100, repeat('X',5), "" from seq_1_to_10; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze Warning Engine-independent statistics are not collected for column 'tx' +test.t1 analyze status OK +explain select count(*) from t1 where t='XXXXXX'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 61 Using where +select column_name, min_value, max_value, hist_size from mysql.column_stats where table_name='t1'; +column_name min_value max_value hist_size +a 1 110 255 +drop table t1; +set use_stat_tables=default; +set histogram_type=default; +set histogram_size=default; +# +# MDEV-31957 Concurrent ALTER and ANALYZE collecting statistics can +# result in stale statistical data +# +CREATE TABLE t1 (a INT, b VARCHAR(128)); +INSERT INTO t1 SELECT seq, CONCAT('s',seq) FROM seq_1_to_100; +connect con1,localhost,root,,; +ALTER TABLE t1 MODIFY b BLOB; +connection default; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +connection con1; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +connection default; +disconnect con1; +select db_name,table_name,column_name from mysql.column_stats; +db_name table_name column_name +test t1 a +drop table t1; +# +# Testing swapping columns +# +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=innodb; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 50.5000 +test t1 c 2.0000 +test t1 d 4.5000 +alter table t1 change b c varchar(200), change c b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 2.0000 +test t1 c 50.5000 +test t1 d 4.5000 +alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 4.5000 +test t1 c 2.0000 +test t1 d 50.5000 +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 c 4.5000 +test t1 d 2.0000 +test t1 e 50.5000 +alter table t1 change e d varchar(200), drop column d; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 c 4.5000 +test t1 d 50.5000 +# Test having non existing column in column_stats +insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1","b"); +alter table t1 change c d varchar(200), change d b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 50.5000 +test t1 d 4.5000 +# Test having a conflicting temporary name +insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1",concat("#sql_tmp_name#1",char(0))); +alter table t1 change d b varchar(200), change b d varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 4.5000 +test t1 d 50.5000 +drop table t1; +truncate table mysql.column_stats; +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=myisam; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 50.5000 +test t1 c 2.0000 +test t1 d 4.5000 +alter table t1 change b c varchar(200), change c b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 d 4.5000 +analyze table t1 persistent for columns(b,c) indexes all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 b 50.5000 +test t1 c 2.0000 +analyze table t1 persistent for columns(d) indexes all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 c 50.5000 +test t1 d 2.0000 +test t1 e 50.5000 +alter table t1 change e d varchar(200), drop column d; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +db_name table_name column_name avg_length +test t1 a 4.0000 +test t1 c 50.5000 +test t1 d 50.5000 +drop table t1; +truncate table mysql.column_stats; +create table t1 (a int, b blob, unique(b)) engine= innodb; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status OK +select column_name from mysql.column_stats where table_name = 't1'; +column_name +a +drop table t1; +create table t1 (a int, b blob, c int generated always as (length(b)) virtual) engine= innodb; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status OK +select column_name from mysql.column_stats where table_name = 't1'; +column_name +a +c +drop table t1; +CREATE or replace TABLE t1 (a INT, b CHAR(8)); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +ALTER TABLE t1 CHANGE b c INT, ORDER BY b; +SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1'; +db_name table_name column_name +test t1 a +test t1 c +drop table t1; +CREATE or replace TABLE t1 (a INT, b CHAR(8)); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +ALTER TABLE t1 RENAME COLUMN b to c, ALGORITHM=COPY; +SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1'; +db_name table_name column_name +test t1 a +test t1 c +drop table t1; +# +# Testing swapping indexes +# +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100), index (b), index(c), index(d,b)) engine=innodb; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.index_stats order by index_name, prefix_arity; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 1.0000 +test t1 b 2 1.0000 +test t1 c 1 20.0000 +test t1 c 2 1.0000 +test t1 d 1 10.0000 +test t1 d 2 1.0000 +test t1 d 3 1.0000 +alter table t1 rename index b to c, rename index c to d, rename index d to b; +select * from mysql.index_stats order by index_name; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 10.0000 +test t1 b 2 1.0000 +test t1 b 3 1.0000 +test t1 c 1 1.0000 +test t1 c 2 1.0000 +test t1 d 1 20.0000 +test t1 d 2 1.0000 +alter table t1 rename index b to c, rename index c to d, rename index d to e; +select * from mysql.index_stats order by index_name, prefix_arity; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 c 1 10.0000 +test t1 c 2 1.0000 +test t1 c 3 1.0000 +test t1 d 1 1.0000 +test t1 d 2 1.0000 +test t1 e 1 20.0000 +test t1 e 2 1.0000 +alter table t1 rename index e to b; +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` varchar(200) DEFAULT NULL, + `d` varchar(200) DEFAULT NULL, + `e` varchar(200) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `d` (`c`), + KEY `b` (`d`), + KEY `c` (`e`,`c`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +select * from mysql.index_stats order by index_name, prefix_arity; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 20.0000 +test t1 b 2 1.0000 +test t1 c 1 10.0000 +test t1 c 2 1.0000 +test t1 c 3 1.0000 +test t1 d 1 1.0000 +test t1 d 2 1.0000 +# Test having a conflicting temporary name +insert into mysql.index_stats (db_name,table_name,index_name,prefix_arity) values ("test","t1",concat("#sql_tmp_name#1",char(0)),1); +alter table t1 rename index c to d, rename index d to c; +select * from mysql.index_stats order by index_name, prefix_arity; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 20.0000 +test t1 b 2 1.0000 +test t1 c 1 1.0000 +test t1 c 2 1.0000 +test t1 d 1 10.0000 +test t1 d 2 1.0000 +test t1 d 3 1.0000 +drop table t1; +select * from mysql.index_stats order by index_name, prefix_arity; +db_name table_name index_name prefix_arity avg_frequency +# +# Test of adding key that replaces foreign key +# +CREATE TABLE t1 (aaaa INT, b INT, KEY(b), FOREIGN KEY(aaaa) REFERENCES t1(b)) ENGINE=InnoDB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; +index_name +aaaa +b +ALTER TABLE t1 ADD KEY idx(aaaa); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `aaaa` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `b` (`b`), + KEY `idx` (`aaaa`), + CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`aaaa`) REFERENCES `t1` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; +index_name +b +truncate table mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; +index_name +b +idx +ALTER TABLE t1 DROP KEY idx; +ERROR HY000: Cannot drop index 'idx': needed in a foreign key constraint +DROP TABLE t1; +# +# Check index rename where name is not changed +# +create or replace table t1 (a int primary key, b int, c int, key b (b,c)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `b` (`b`,`c`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select * from mysql.index_stats where table_name= "t1"; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 NULL +test t1 b 2 NULL +alter ignore table t1 rename key `b` to b, LOCK=shared; +select * from mysql.index_stats where table_name= "t1"; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 b 1 NULL +test t1 b 2 NULL +alter ignore table t1 rename key `b` to `B`, LOCK=shared; +select * from mysql.index_stats where table_name= "t1"; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 B 1 NULL +test t1 B 2 NULL +drop table t1; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/analyze.test b/mysql-test/main/analyze.test index 85a8815816237..e3b776f11ca40 100644 --- a/mysql-test/main/analyze.test +++ b/mysql-test/main/analyze.test @@ -1,3 +1,6 @@ +--source include/have_sequence.inc +--source include/have_innodb.inc + # # Bug #10901 Analyze Table on new table destroys table # This is minimal test case to get error @@ -87,3 +90,185 @@ optimize table t1 extended; drop table t1; --echo End of 5.0 tests + +--echo # +--echo # Test analyze of text column (not yet supported) +--echo # + +set optimizer_use_condition_selectivity=4; +set histogram_type='single_prec_hb'; +set histogram_size=255; + +create table t1 (a int not null, t tinytext, tx text); +insert into t1 select seq+1, repeat('X',seq*5), repeat('X',seq*10) from seq_0_to_50; +insert into t1 select seq+100, repeat('X',5), "" from seq_1_to_10; +analyze table t1; +explain select count(*) from t1 where t='XXXXXX'; +select column_name, min_value, max_value, hist_size from mysql.column_stats where table_name='t1'; + +drop table t1; + +set use_stat_tables=default; +set histogram_type=default; +set histogram_size=default; + +--echo # +--echo # MDEV-31957 Concurrent ALTER and ANALYZE collecting statistics can +--echo # result in stale statistical data +--echo # + +CREATE TABLE t1 (a INT, b VARCHAR(128)); +INSERT INTO t1 SELECT seq, CONCAT('s',seq) FROM seq_1_to_100; + +# We have to disable query log as the ANALYZE TABLE can be run in different +# order. The important thing is what is finally in column_stats +--disable_result_log +--connect (con1,localhost,root,,) +--send ALTER TABLE t1 MODIFY b BLOB + +--connection default +ANALYZE TABLE t1 PERSISTENT FOR ALL; + +--connection con1 +--reap +ANALYZE TABLE t1 PERSISTENT FOR ALL; +--connection default +--disconnect con1 +--enable_result_log +select db_name,table_name,column_name from mysql.column_stats; +drop table t1; + +--echo # +--echo # Testing swapping columns +--echo # + +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=innodb; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change b c varchar(200), change c b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change e d varchar(200), drop column d; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; + +--echo # Test having non existing column in column_stats + +insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1","b"); +alter table t1 change c d varchar(200), change d b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; + +--echo # Test having a conflicting temporary name +insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1",concat("#sql_tmp_name#1",char(0))); +alter table t1 change d b varchar(200), change b d varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; + +drop table t1; +truncate table mysql.column_stats; + +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=myisam; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change b c varchar(200), change c b varchar(200); +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +analyze table t1 persistent for columns(b,c) indexes all; +alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +analyze table t1 persistent for columns(d) indexes all; +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +alter table t1 change e d varchar(200), drop column d; +select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name; +drop table t1; +truncate table mysql.column_stats; + +create table t1 (a int, b blob, unique(b)) engine= innodb; +analyze table t1 persistent for all; +select column_name from mysql.column_stats where table_name = 't1'; +drop table t1; + +create table t1 (a int, b blob, c int generated always as (length(b)) virtual) engine= innodb; +analyze table t1 persistent for all; +select column_name from mysql.column_stats where table_name = 't1'; +drop table t1; + +CREATE or replace TABLE t1 (a INT, b CHAR(8)); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +ALTER TABLE t1 CHANGE b c INT, ORDER BY b; +SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1'; +drop table t1; + +CREATE or replace TABLE t1 (a INT, b CHAR(8)); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +ALTER TABLE t1 RENAME COLUMN b to c, ALGORITHM=COPY; +SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1'; +drop table t1; + +--echo # +--echo # Testing swapping indexes +--echo # + +create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100), index (b), index(c), index(d,b)) engine=innodb; +insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +select * from mysql.index_stats order by index_name, prefix_arity; +alter table t1 rename index b to c, rename index c to d, rename index d to b; +select * from mysql.index_stats order by index_name; + +alter table t1 rename index b to c, rename index c to d, rename index d to e; +select * from mysql.index_stats order by index_name, prefix_arity; +alter table t1 rename index e to b; +alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ; +show create table t1; +select * from mysql.index_stats order by index_name, prefix_arity; + +--echo # Test having a conflicting temporary name +insert into mysql.index_stats (db_name,table_name,index_name,prefix_arity) values ("test","t1",concat("#sql_tmp_name#1",char(0)),1); +alter table t1 rename index c to d, rename index d to c; +select * from mysql.index_stats order by index_name, prefix_arity; +drop table t1; +select * from mysql.index_stats order by index_name, prefix_arity; + +--echo # +--echo # Test of adding key that replaces foreign key +--echo # + +CREATE TABLE t1 (aaaa INT, b INT, KEY(b), FOREIGN KEY(aaaa) REFERENCES t1(b)) ENGINE=InnoDB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; + +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; + +ALTER TABLE t1 ADD KEY idx(aaaa); +SHOW CREATE TABLE t1; + +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; + +truncate table mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name; + +--error ER_DROP_INDEX_FK +ALTER TABLE t1 DROP KEY idx; +DROP TABLE t1; + +--echo # +--echo # Check index rename where name is not changed +--echo # + +create or replace table t1 (a int primary key, b int, c int, key b (b,c)); +show create table t1; +analyze table t1 persistent for all; +select * from mysql.index_stats where table_name= "t1"; +alter ignore table t1 rename key `b` to b, LOCK=shared; +select * from mysql.index_stats where table_name= "t1"; +alter ignore table t1 rename key `b` to `B`, LOCK=shared; +select * from mysql.index_stats where table_name= "t1"; +drop table t1; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysql-test/main/column_compression.inc b/mysql-test/main/column_compression.inc index 13952b739ae8e..27e5fc70837fe 100644 --- a/mysql-test/main/column_compression.inc +++ b/mysql-test/main/column_compression.inc @@ -70,7 +70,8 @@ TRUNCATE TABLE t1; SET column_compression_zlib_level= 1; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_compressions', 'Column_decompressions'); -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +# This is is using < as DATA_LENGTH produces different results on s390x-ubuntu-2004 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index e6bc6b6cb5850..7d846caeddef3 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -133,9 +133,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -40 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); @@ -348,9 +348,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -40 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); @@ -563,9 +563,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -40 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); @@ -778,9 +778,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -40 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); @@ -993,9 +993,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -60 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); @@ -1209,9 +1209,9 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME IN('Column_c VARIABLE_NAME VARIABLE_VALUE COLUMN_COMPRESSIONS 3 COLUMN_DECOMPRESSIONS 12 -SELECT DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; -DATA_LENGTH -36 +SELECT DATA_LENGTH < 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +DATA_LENGTH < 100 +1 TRUNCATE TABLE t1; SET column_compression_zlib_level= 9; INSERT INTO t1 VALUES(REPEAT('ab', 1000)); diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index f43cfd011d7c5..642399be1f650 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc +--source include/have_normal_bzip.inc let $MYSQLD_DATADIR= `select @@datadir`; diff --git a/mysql-test/main/column_compression_rpl.test b/mysql-test/main/column_compression_rpl.test index 86c73a77dbd53..df8e889016b8b 100644 --- a/mysql-test/main/column_compression_rpl.test +++ b/mysql-test/main/column_compression_rpl.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/master-slave.inc +--source include/have_normal_bzip.inc --let $engine_type= myisam --let $engine_type2= innodb diff --git a/mysql-test/main/compare.result b/mysql-test/main/compare.result index b8883784d21ae..70664e2cc1854 100644 --- a/mysql-test/main/compare.result +++ b/mysql-test/main/compare.result @@ -4,6 +4,8 @@ insert into t1 values ('000000000001'),('000000000002'); explain select * from t1 where id=000000000001; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 12 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t1`.`id` of type `char` = "1" of type `bigint` select * from t1 where id=000000000001; id 000000000001 diff --git a/mysql-test/main/ctype_collate.result b/mysql-test/main/ctype_collate.result index 29d27fd608b41..af2735bc03beb 100644 --- a/mysql-test/main/ctype_collate.result +++ b/mysql-test/main/ctype_collate.result @@ -606,6 +606,8 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition diff --git a/mysql-test/main/delayed.result b/mysql-test/main/delayed.result index 4b482c8bb667e..472a3cd53d580 100644 --- a/mysql-test/main/delayed.result +++ b/mysql-test/main/delayed.result @@ -355,97 +355,6 @@ ERROR 42S01: Table 't1' already exists DROP TABLE t2; DROP TABLE t1; # -# Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED -# -# This test is not supposed to work under --ps-protocol since -# INSERT DELAYED doesn't work under LOCK TABLES with this protocol. -DROP TABLE IF EXISTS t1, t2; -CREATE TABLE t1 (a INT); -CREATE TABLE t2 (a INT); -CREATE TABLE t3 (a INT); -# Test 1: Using LOCK TABLE -connect con1, localhost, root; -LOCK TABLE t1 WRITE; -connection default; -LOCK TABLE t2 WRITE; -# Sending: -INSERT DELAYED INTO t1 VALUES (1); -connection con1; -# Wait until INSERT DELAYED is blocked on table 't1'. -INSERT DELAYED INTO t2 VALUES (1); -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -UNLOCK TABLES; -connection default; -# Reaping: INSERT DELAYED INTO t1 VALUES (1) -UNLOCK TABLES; -# Test 2: Using ALTER TABLE -START TRANSACTION; -SELECT * FROM t1 WHERE a=0; -a -connection con1; -# Sending: -ALTER TABLE t1 MODIFY a INT UNSIGNED;; -connection default; -# Wait until ALTER TABLE is blocked on table 't1'. -INSERT DELAYED INTO t1 VALUES (3); -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -COMMIT; -connection con1; -# Reaping: ALTER TABLE t1 COMMENT 'test' -# Test 3: Using RENAME TABLE -connection default; -START TRANSACTION; -INSERT INTO t2 VALUES (1); -connection con1; -# Sending: -RENAME TABLE t1 to t5, t2 to t4; -connection default; -# Wait until RENAME TABLE is blocked on table 't1'. -INSERT DELAYED INTO t1 VALUES (4); -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -COMMIT; -connection con1; -# Reaping: RENAME TABLE t1 to t5, t2 to t4 -connection default; -# Reverting the renames -RENAME TABLE t5 to t1, t4 to t2; -# Test 4: Two INSERT DELAYED on the same table -START TRANSACTION; -INSERT INTO t2 VALUES (1); -connect con2, localhost, root; -LOCK TABLE t1 WRITE, t2 WRITE; -connection con1; -# Wait until LOCK TABLE is blocked on table 't2'. -INSERT DELAYED INTO t1 VALUES (5); -connection default; -# Wait until INSERT DELAYED is blocked on table 't1'. -INSERT DELAYED INTO t1 VALUES (6); -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -COMMIT; -connection con2; -# Reaping: LOCK TABLE t1 WRITE, t2 WRITE -UNLOCK TABLES; -connection con1; -# Reaping: INSERT DELAYED INTO t1 VALUES (5) -connection default; -# Test 5: LOCK TABLES + INSERT DELAYED in one connection. -# This test has triggered some asserts in metadata locking -# subsystem at some point in time.. -LOCK TABLE t1 WRITE; -INSERT DELAYED INTO t2 VALUES (7); -UNLOCK TABLES; -SET AUTOCOMMIT= 0; -LOCK TABLE t1 WRITE; -INSERT DELAYED INTO t2 VALUES (8); -UNLOCK TABLES; -SET AUTOCOMMIT= 1; -connection con2; -disconnect con2; -connection con1; -disconnect con1; -connection default; -DROP TABLE t1, t2, t3; -# # Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables". # connect con1,localhost,root,,; diff --git a/mysql-test/main/delayed.test b/mysql-test/main/delayed.test index a3a8e929b510c..6948a0049bf26 100644 --- a/mysql-test/main/delayed.test +++ b/mysql-test/main/delayed.test @@ -408,6 +408,9 @@ DROP TABLE t2; DROP TABLE t1; +# The following test is disabled as it fails randomly +if (0) +{ --echo # --echo # Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED --echo # @@ -566,6 +569,7 @@ connection default; DROP TABLE t1, t2, t3; --enable_ps_protocol --enable_view_protocol +} --echo # --echo # Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables". diff --git a/mysql-test/main/func_compress.test b/mysql-test/main/func_compress.test index f41a58981548a..221dddd59f558 100644 --- a/mysql-test/main/func_compress.test +++ b/mysql-test/main/func_compress.test @@ -1,4 +1,5 @@ -- source include/have_compress.inc +-- source include/have_normal_bzip.inc # # Test for compress and uncompress functions: # diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result index c8efcf09d41ef..37f2a19fc6c28 100644 --- a/mysql-test/main/func_debug.result +++ b/mysql-test/main/func_debug.result @@ -912,7 +912,8 @@ a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) -Note 1105 DBUG: types_compatible=no bisect=no +Note 1105 DBUG: found a mix of UINT and SINT +Note 1105 DBUG: types_compatible=yes bisect=yes SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) Warnings: @@ -950,7 +951,8 @@ a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) -Note 1105 DBUG: types_compatible=no bisect=no +Note 1105 DBUG: found a mix of UINT and SINT +Note 1105 DBUG: types_compatible=yes bisect=yes SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) Warnings: @@ -1624,7 +1626,8 @@ a b Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) -Note 1105 DBUG: types_compatible=no bisect=no +Note 1105 DBUG: found a mix of UINT and SINT +Note 1105 DBUG: types_compatible=yes bisect=no DROP TABLE t1; # # MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index 175e23ec65f27..4627208d79f37 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -935,6 +935,43 @@ Warning 1292 Truncated incorrect DECIMAL value: '0x' # End of 10.4 tests # # +# Start of 10.5 tests +# +# +# MDEV-31303: Key not used +# +CREATE TABLE `a` ( +`id` bigint AUTO_INCREMENT PRIMARY KEY, +`c1` bigint unsigned, +KEY (`c1`) +); +INSERT INTO `a` VALUES (1,9223382399205928659),(2,9223384207280813348), +(3,9223385953115437234),(4,9223387250780556749),(5,9223387354282558788), +(6,9223387603870501596),(7,9223389270813433667),(8,9223389903231468827), +(9,9223390280789586779),(10,9223391591398222899),(11,9223391875473564350), +(12,9223393152250049433),(13,9223393939696790223),(14,9223394417225350415), +(15,9223397646397141015),(16,9223398025879291243),(17,9223399038671098072), +(18,9223399534968874556),(19,9223400449518009285),(20,9223400860292643549), +(21,9223400940692256924),(22,9223401073791948119),(23,9223402820804649616), +(24,9223403470951992681),(25,9223405581879567267),(26,9223405754978563829), +(27,9223405972966828221), (28, 9223372036854775808), (29, 9223372036854775807) ; +explain SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775807 ); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE a range c1 c1 9 NULL 2 Using where; Using index +explain SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775808 ); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE a range c1 c1 9 NULL 2 Using where; Using index +SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775807 ); +c1 +9223372036854775807 +SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775808 ); +c1 +9223372036854775808 +drop table `a`; +# +# End of 10.5 tests +# +# # MDEV-29662 same values in `IN` set vs equal comparison produces # the different performance # diff --git a/mysql-test/main/func_in.test b/mysql-test/main/func_in.test index 847c48d31a94c..e39932a2d502e 100644 --- a/mysql-test/main/func_in.test +++ b/mysql-test/main/func_in.test @@ -712,6 +712,40 @@ SELECT ('0x',1) IN ((0,1),(1,1)); --echo # End of 10.4 tests --echo # +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-31303: Key not used +--echo # +CREATE TABLE `a` ( + `id` bigint AUTO_INCREMENT PRIMARY KEY, + `c1` bigint unsigned, + KEY (`c1`) +); + +INSERT INTO `a` VALUES (1,9223382399205928659),(2,9223384207280813348), +(3,9223385953115437234),(4,9223387250780556749),(5,9223387354282558788), +(6,9223387603870501596),(7,9223389270813433667),(8,9223389903231468827), +(9,9223390280789586779),(10,9223391591398222899),(11,9223391875473564350), +(12,9223393152250049433),(13,9223393939696790223),(14,9223394417225350415), +(15,9223397646397141015),(16,9223398025879291243),(17,9223399038671098072), +(18,9223399534968874556),(19,9223400449518009285),(20,9223400860292643549), +(21,9223400940692256924),(22,9223401073791948119),(23,9223402820804649616), +(24,9223403470951992681),(25,9223405581879567267),(26,9223405754978563829), +(27,9223405972966828221), (28, 9223372036854775808), (29, 9223372036854775807) ; + +explain SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775807 ); +explain SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775808 ); +SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775807 ); +SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775808 ); +drop table `a`; + +--echo # +--echo # End of 10.5 tests +--echo # + --echo # --echo # MDEV-29662 same values in `IN` set vs equal comparison produces --echo # the different performance @@ -845,4 +879,3 @@ drop table t1; --echo # --echo # End of 10.6 tests --echo # - diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index d7cbadd5e7598..bcb71b644c5af 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -906,5 +906,54 @@ SELECT * FROM t HAVING f = 'foo'; f DROP TABLE t; # +# MDEV-29731 Crash when HAVING in a correlated subquery references +# columns in the outer query +# +CREATE TABLE t (a INT, b INT); +SELECT 1 FROM t +WHERE b = (SELECT 1 FROM t GROUP BY a HAVING b = a+1); +1 +DROP TABLE t; +CREATE TABLE t (a INT, b INT, c INT); +SELECT 1 FROM t +WHERE (b,c) = (SELECT 1,1 FROM t GROUP BY a HAVING b = a+1 and c = a-1); +1 +DROP TABLE t; +CREATE TABLE t (a TEXT, b INT UNIQUE); +SELECT 1 FROM t +WHERE b IN (SELECT 1 FROM t +GROUP BY '', a +HAVING (CASE b WHEN 1 +'' THEN 3 ELSE a END) +ORDER BY b) +GROUP BY b HAVING b = 1; +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '' +DROP TABLE t; +CREATE TABLE t (a INT, b CHAR KEY UNIQUE); +CREATE VIEW v AS SELECT * FROM t WHERE a LIKE '' GROUP BY b HAVING a > a; +SELECT * FROM v AS v1 NATURAL JOIN v AS v5 NATURAL JOIN v +WHERE a LIKE '' AND b IN (SELECT a FROM t +WHERE a LIKE '' + GROUP BY a +HAVING b LIKE (b < +1 OR a > 1) >= b); +a b +DROP VIEW v; +DROP TABLE t; +EXECUTE IMMEDIATE 'SELECT LEAD(c) OVER (ORDER BY c) + FROM (SELECT 0 AS c) AS a NATURAL JOIN (SELECT 0 AS c) AS b;'; +LEAD(c) OVER (ORDER BY c) +NULL +CREATE TABLE t (a INT); +UPDATE t SET a = '' + WHERE 1 IN (SELECT * FROM +(SELECT * FROM +(SELECT * FROM t AS v5 NATURAL JOIN t AS v4 NATURAL JOIN t) AS v3 +NATURAL JOIN t +GROUP BY a) AS v2 +WHERE (0, a) IN ((0,-1),(+1,0)) +ORDER BY 1+AVG(a) OVER (ORDER BY a)) ORDER BY a; +DROP TABLE t; +# # End of 10.4 tests # diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test index 397b220978e18..7b8e72cfe1d27 100644 --- a/mysql-test/main/having.test +++ b/mysql-test/main/having.test @@ -950,8 +950,53 @@ DROP TABLE t1,t2; CREATE TABLE t (f VARCHAR(512)); INSERT INTO t VALUES ('a'),('b'); SELECT * FROM t HAVING f = 'foo'; +DROP TABLE t; + +--echo # +--echo # MDEV-29731 Crash when HAVING in a correlated subquery references +--echo # columns in the outer query +--echo # +CREATE TABLE t (a INT, b INT); +SELECT 1 FROM t + WHERE b = (SELECT 1 FROM t GROUP BY a HAVING b = a+1); +DROP TABLE t; + +CREATE TABLE t (a INT, b INT, c INT); +SELECT 1 FROM t + WHERE (b,c) = (SELECT 1,1 FROM t GROUP BY a HAVING b = a+1 and c = a-1); +DROP TABLE t; + +CREATE TABLE t (a TEXT, b INT UNIQUE); +SELECT 1 FROM t + WHERE b IN (SELECT 1 FROM t + GROUP BY '', a + HAVING (CASE b WHEN 1 +'' THEN 3 ELSE a END) + ORDER BY b) + GROUP BY b HAVING b = 1; +DROP TABLE t; + +CREATE TABLE t (a INT, b CHAR KEY UNIQUE); +CREATE VIEW v AS SELECT * FROM t WHERE a LIKE '' GROUP BY b HAVING a > a; +SELECT * FROM v AS v1 NATURAL JOIN v AS v5 NATURAL JOIN v + WHERE a LIKE '' AND b IN (SELECT a FROM t + WHERE a LIKE '' + GROUP BY a + HAVING b LIKE (b < +1 OR a > 1) >= b); +DROP VIEW v; +DROP TABLE t; -# Cleanup +EXECUTE IMMEDIATE 'SELECT LEAD(c) OVER (ORDER BY c) + FROM (SELECT 0 AS c) AS a NATURAL JOIN (SELECT 0 AS c) AS b;'; + +CREATE TABLE t (a INT); +UPDATE t SET a = '' + WHERE 1 IN (SELECT * FROM + (SELECT * FROM + (SELECT * FROM t AS v5 NATURAL JOIN t AS v4 NATURAL JOIN t) AS v3 + NATURAL JOIN t + GROUP BY a) AS v2 + WHERE (0, a) IN ((0,-1),(+1,0)) + ORDER BY 1+AVG(a) OVER (ORDER BY a)) ORDER BY a; DROP TABLE t; --echo # diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index ce9dbfb8c3d74..c4ea5bc4517d2 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -1804,7 +1804,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 13 +Handler_read_key 4 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 @@ -1819,7 +1819,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 7 +Handler_read_key 4 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index a34bf96a0efd1..bdaab88e01f2d 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -1811,7 +1811,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 13 +Handler_read_key 4 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 @@ -1826,7 +1826,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 7 +Handler_read_key 4 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 diff --git a/mysql-test/main/log_slow.result b/mysql-test/main/log_slow.result index 8f2d3194a271f..b236288b0bfdd 100644 --- a/mysql-test/main/log_slow.result +++ b/mysql-test/main/log_slow.result @@ -13,6 +13,7 @@ Variable_name Value log_slow_admin_statements ON log_slow_disabled_statements sp log_slow_filter admin,filesort,filesort_on_disk,filesort_priority_queue,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk +log_slow_max_warnings 10 log_slow_min_examined_row_limit 0 log_slow_query ON log_slow_query_file $PATH/mysqld-slow.log @@ -56,15 +57,15 @@ start_time timestamp(6) NO current_timestamp(6) on update current_timestamp(6) user_host mediumtext NO NULL query_time time(6) NO NULL lock_time time(6) NO NULL -rows_sent int(11) NO NULL -rows_examined int(11) NO NULL +rows_sent bigint(20) unsigned NO NULL +rows_examined bigint(20) unsigned NO NULL db varchar(512) NO NULL last_insert_id int(11) NO NULL insert_id int(11) NO NULL server_id int(10) unsigned NO NULL sql_text mediumtext NO NULL thread_id bigint(21) unsigned NO NULL -rows_affected int(11) NO NULL +rows_affected bigint(20) unsigned NO NULL flush slow logs; set long_query_time=0.1; set log_slow_filter=''; @@ -137,3 +138,54 @@ drop table t; # # End of 10.3 tests # +# +# MDEV-31742: incorrect examined rows in case of stored function usage +# +CREATE TABLE `tab_MDEV_30820` ( +`ID` int(11) NOT NULL AUTO_INCREMENT, +`NAME_F` varchar(50) DEFAULT NULL, +PRIMARY KEY (`ID`) +); +CREATE TABLE `tab2` ( +`ID` int(11) NOT NULL AUTO_INCREMENT, +`TAB1_ID` int(11) DEFAULT NULL, +PRIMARY KEY (`id`) +); +CREATE FUNCTION `get_zero`() RETURNS int(11) +BEGIN +RETURN(0) ; +END +// +for i in 1..100 do insert into tab_MDEV_30820 values (i,'qwerty'); end for ; // +for i in 1..1000 do insert into tab2 values (i,i+300); end for ; // +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION slow_query_log=ON; +SET SESSION long_query_time= 0; +SELECT 0 as zero, (SELECT ID FROM tab2 where tab2.TAB1_ID = +tab_MDEV_30820.ID ORDER BY 1 LIMIT 1 ) AS F1 FROM tab_MDEV_30820 ORDER BY 2 DESC LIMIT 2; +zero F1 +0 NULL +0 NULL +SELECT get_zero() as zero, (SELECT ID FROM tab2 where tab2.TAB1_ID = +tab_MDEV_30820.ID ORDER BY 1 LIMIT 1) AS F1 FROM tab_MDEV_30820 ORDER BY 2 DESC LIMIT 2; +zero F1 +0 NULL +0 NULL +# should be the same rows_examined +SELECT rows_examined FROM mysql.slow_log WHERE sql_text LIKE '%SELECT%tab_MDEV_30820%'; +rows_examined +100202 +100202 +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +SET SESSION slow_query_log=default; +drop table tab_MDEV_30820, tab2; +drop function get_zero; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/log_slow.test b/mysql-test/main/log_slow.test index 65da292b7ddbf..ea8b912765827 100644 --- a/mysql-test/main/log_slow.test +++ b/mysql-test/main/log_slow.test @@ -122,3 +122,70 @@ drop table t; --echo # --echo # End of 10.3 tests --echo # + + +--echo # +--echo # MDEV-31742: incorrect examined rows in case of stored function usage +--echo # + + +CREATE TABLE `tab_MDEV_30820` ( +`ID` int(11) NOT NULL AUTO_INCREMENT, +`NAME_F` varchar(50) DEFAULT NULL, + PRIMARY KEY (`ID`) +); + + CREATE TABLE `tab2` ( + `ID` int(11) NOT NULL AUTO_INCREMENT, + `TAB1_ID` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +); + +--disable_ps2_protocol +--disable_view_protocol + +--delimiter // +CREATE FUNCTION `get_zero`() RETURNS int(11) +BEGIN + RETURN(0) ; +END +// + +for i in 1..100 do insert into tab_MDEV_30820 values (i,'qwerty'); end for ; // +for i in 1..1000 do insert into tab2 values (i,i+300); end for ; // + +--delimiter ; + +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; + +SET SESSION slow_query_log=ON; +SET SESSION long_query_time= 0; + +SELECT 0 as zero, (SELECT ID FROM tab2 where tab2.TAB1_ID = +tab_MDEV_30820.ID ORDER BY 1 LIMIT 1 ) AS F1 FROM tab_MDEV_30820 ORDER BY 2 DESC LIMIT 2; + +SELECT get_zero() as zero, (SELECT ID FROM tab2 where tab2.TAB1_ID = +tab_MDEV_30820.ID ORDER BY 1 LIMIT 1) AS F1 FROM tab_MDEV_30820 ORDER BY 2 DESC LIMIT 2; + +--echo # should be the same rows_examined +SELECT rows_examined FROM mysql.slow_log WHERE sql_text LIKE '%SELECT%tab_MDEV_30820%'; + +## Reset to initial values +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +SET SESSION slow_query_log=default; + +drop table tab_MDEV_30820, tab2; +drop function get_zero; + +--enable_view_protocol +--enable_ps2_protocol + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/log_slow_debug.result b/mysql-test/main/log_slow_debug.result index eaf38425f8b03..5f4f4c6a05964 100644 --- a/mysql-test/main/log_slow_debug.result +++ b/mysql-test/main/log_slow_debug.result @@ -230,6 +230,91 @@ sql_text [slow] DEALLOCATE PREPARE stmt [slow] DROP SEQUENCE s4 # +# Start of 10.6 tests +# +# +# MDEV-32203 Raise notes when an index cannot be used on data type +# mismatch +# +CREATE TABLE t1 (a VARCHAR(10), KEY(a)); +insert into t1 select seq from seq_0_to_31; +SET note_verbosity=all; +SET log_slow_verbosity=all; +SET global log_output='FILE'; +set @org_slow_query_log_file=@@global.slow_query_log_file; +set global slow_query_log_file='MYSQLTEST_VARDIR/tmp/log_slow_debug-1.log'; +FLUSH SLOW LOGS; +SELECT * FROM t1 WHERE a=10; +a +10 +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` = "10" of type `int` +EXPLAIN SELECT * FROM t1 WHERE a=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index a a 13 NULL 32 Using where; Using index +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` = "10" of type `int` +FOUND 2 /# Warnings/ in log_slow_debug-1.log +FOUND 1 /# Note.*Cannot use key.*varchar.*10.*int/ in log_slow_debug-1.log +set global slow_query_log_file='MYSQLTEST_VARDIR/tmp/log_slow_debug-2.log'; +SET note_verbosity="explain"; +FLUSH SLOW LOGS; +EXPLAIN SELECT * FROM t1 WHERE a=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index a a 13 NULL 32 Using where; Using index +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` = "10" of type `int` +FOUND 1 /# Warnings/ in log_slow_debug-2.log +FOUND 1 /# Note.*Cannot use key.*varchar.*10.*int/ in log_slow_debug-2.log +set global slow_query_log_file='MYSQLTEST_VARDIR/tmp/log_slow_debug-3.log'; +SET log_slow_verbosity=replace(@@log_slow_verbosity, "warnings", ""); +SET log_slow_verbosity=replace(@@log_slow_verbosity, "full", ""); +SET note_verbosity=all; +FLUSH SLOW LOGS; +SELECT * FROM t1 WHERE a=10; +a +10 +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` = "10" of type `int` +EXPLAIN SELECT * FROM t1 WHERE a=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index a a 13 NULL 32 Using where; Using index +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` = "10" of type `int` +NOT FOUND /# Warnings/ in log_slow_debug-3.log +NOT FOUND /# Note.*Cannot use key.*varchar.*10.*int/ in log_slow_debug-3.log +set @@global.slow_query_log_file= @org_slow_query_log_file; +DROP TABLE t1; +# +# MDEV-30820: slow log Rows_examined out of range +# +CREATE TABLE `tab_MDEV_30820` ( +`ID` int(11) NOT NULL AUTO_INCREMENT, +`A` int(11), +PRIMARY KEY(ID) +); +insert into tab_MDEV_30820 values (null, 0),(null, 0); +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; +SET GLOBAL debug_dbug="+d,debug_huge_number_of_examined_rows"; +SELECT * FROM tab_MDEV_30820 ORDER BY 1; +ID A +1 0 +2 0 +SET GLOBAL debug_dbug=@old_dbug; +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +drop table tab_MDEV_30820; +# +# End of 10.4 test +# +# # Clean up # SET SESSION debug_dbug=@saved_dbug; diff --git a/mysql-test/main/log_slow_debug.test b/mysql-test/main/log_slow_debug.test index aba4cbc8dcb4f..ee0406112d204 100644 --- a/mysql-test/main/log_slow_debug.test +++ b/mysql-test/main/log_slow_debug.test @@ -1,4 +1,5 @@ -- source include/have_debug.inc +-- source include/have_sequence.inc SET @org_slow_query_log= @@global.slow_query_log; SET @org_log_output= @@global.log_output; @@ -82,6 +83,108 @@ TRUNCATE TABLE mysql.slow_log; --source include/log_slow_debug_common.inc CALL show_slow_log(); +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type +--echo # mismatch +--echo # + +CREATE TABLE t1 (a VARCHAR(10), KEY(a)); +insert into t1 select seq from seq_0_to_31; + +SET note_verbosity=all; +SET log_slow_verbosity=all; +SET global log_output='FILE'; +set @org_slow_query_log_file=@@global.slow_query_log_file; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval set global slow_query_log_file='$MYSQLTEST_VARDIR/tmp/log_slow_debug-1.log'; +FLUSH SLOW LOGS; +--disable_ps_protocol +SELECT * FROM t1 WHERE a=10; +EXPLAIN SELECT * FROM t1 WHERE a=10; +--enable_ps_protocol + +--let SEARCH_FILE = `SELECT @@slow_query_log_file` +--let SEARCH_PATTERN=# Warnings +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= # Note.*Cannot use key.*varchar.*10.*int +--source include/search_pattern_in_file.inc + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval set global slow_query_log_file='$MYSQLTEST_VARDIR/tmp/log_slow_debug-2.log'; +SET note_verbosity="explain"; +FLUSH SLOW LOGS; +EXPLAIN SELECT * FROM t1 WHERE a=10; + +--let SEARCH_FILE = `SELECT @@slow_query_log_file` +--let SEARCH_PATTERN=# Warnings +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= # Note.*Cannot use key.*varchar.*10.*int +--source include/search_pattern_in_file.inc + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval set global slow_query_log_file='$MYSQLTEST_VARDIR/tmp/log_slow_debug-3.log'; +SET log_slow_verbosity=replace(@@log_slow_verbosity, "warnings", ""); +SET log_slow_verbosity=replace(@@log_slow_verbosity, "full", ""); +SET note_verbosity=all; +FLUSH SLOW LOGS; +SELECT * FROM t1 WHERE a=10; +EXPLAIN SELECT * FROM t1 WHERE a=10; + +--let SEARCH_FILE = `SELECT @@slow_query_log_file` +--let SEARCH_PATTERN=# Warnings +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= # Note.*Cannot use key.*varchar.*10.*int +--source include/search_pattern_in_file.inc + +set @@global.slow_query_log_file= @org_slow_query_log_file; + +--remove_file $MYSQLTEST_VARDIR/tmp/log_slow_debug-1.log +--remove_file $MYSQLTEST_VARDIR/tmp/log_slow_debug-2.log +--remove_file $MYSQLTEST_VARDIR/tmp/log_slow_debug-3.log + +DROP TABLE t1; + +--echo # +--echo # MDEV-30820: slow log Rows_examined out of range +--echo # + +CREATE TABLE `tab_MDEV_30820` ( +`ID` int(11) NOT NULL AUTO_INCREMENT, +`A` int(11), +PRIMARY KEY(ID) +); + +insert into tab_MDEV_30820 values (null, 0),(null, 0); + +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL log_output= "TABLE"; + +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; + +SET GLOBAL debug_dbug="+d,debug_huge_number_of_examined_rows"; +SELECT * FROM tab_MDEV_30820 ORDER BY 1; +SET GLOBAL debug_dbug=@old_dbug; + + +## Reset to initial values +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; + +drop table tab_MDEV_30820; + +--echo # +--echo # End of 10.4 test +--echo # --echo # --echo # Clean up diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index d4f1f59ec1c91..1d642c0ade10b 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -73,15 +73,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show fields from mysql.slow_log; Field Type Null Key Default Extra @@ -89,15 +89,15 @@ start_time timestamp(6) NO current_timestamp(6) on update current_timestamp(6) user_host mediumtext NO NULL query_time time(6) NO NULL lock_time time(6) NO NULL -rows_sent int(11) NO NULL -rows_examined int(11) NO NULL +rows_sent bigint(20) unsigned NO NULL +rows_examined bigint(20) unsigned NO NULL db varchar(512) NO NULL last_insert_id int(11) NO NULL insert_id int(11) NO NULL server_id int(10) unsigned NO NULL sql_text mediumtext NO NULL thread_id bigint(21) unsigned NO NULL -rows_affected int(11) NO NULL +rows_affected bigint(20) unsigned NO NULL flush logs; flush tables; SET GLOBAL GENERAL_LOG=ON; @@ -180,15 +180,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' alter table mysql.general_log engine=myisam; alter table mysql.slow_log engine=myisam; @@ -209,15 +209,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' set global general_log='ON'; set global slow_query_log='ON'; @@ -287,15 +287,15 @@ ON UPDATE CURRENT_TIMESTAMP, `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, -`rows_sent` int(11) NOT NULL, -`rows_examined` int(11) NOT NULL, +`rows_sent` bigint(20) unsigned NOT NULL, +`rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` BIGINT(21) UNSIGNED NOT NULL, -`rows_affected` int(11) NOT NULL +`rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; set global general_log='ON'; set global slow_query_log='ON'; @@ -580,15 +580,15 @@ CREATE TABLE `db_17876.slow_log_data` ( `user_host` mediumtext , `query_time` time(6) , `lock_time` time(6) , -`rows_sent` int(11) , -`rows_examined` int(11) , +`rows_sent` bigint(20) unsigned, +`rows_examined` bigint(20) unsigned, `db` varchar(512) default NULL, `last_insert_id` int(11) default NULL, `insert_id` int(11) default NULL, `server_id` int(11) default NULL, `sql_text` mediumtext, `thread_id` bigint(21) unsigned default NULL, -`rows_affected` int(11) default NULL +`rows_affected` bigint(20) unsigned default NULL ); CREATE TABLE `db_17876.general_log_data` ( `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index 3ce49a21e7d72..1eee6be052430 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -307,15 +307,15 @@ CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` BIGINT(21) UNSIGNED NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; set global general_log='ON'; @@ -743,15 +743,15 @@ CREATE TABLE `db_17876.slow_log_data` ( `user_host` mediumtext , `query_time` time(6) , `lock_time` time(6) , - `rows_sent` int(11) , - `rows_examined` int(11) , + `rows_sent` bigint(20) unsigned, + `rows_examined` bigint(20) unsigned, `db` varchar(512) default NULL, `last_insert_id` int(11) default NULL, `insert_id` int(11) default NULL, `server_id` int(11) default NULL, `sql_text` mediumtext, `thread_id` bigint(21) unsigned default NULL, - `rows_affected` int(11) default NULL + `rows_affected` bigint(20) unsigned default NULL ); CREATE TABLE `db_17876.general_log_data` ( diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index ed13c668ec3a8..ce44ae2b6fbd0 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -457,6 +457,41 @@ create table t1 (f text not null, unique (f)); insert into t1 (f) select 'f'; drop table t1; # +# MDEV-32012 hash unique corrupts index on virtual blobs +# +create table t1 ( +f1 varchar(25), +v1 mediumtext generated always as (concat('f1:', f1)) virtual, +unique key (f1) using hash, +key (v1(1000)) +); +flush status; +insert ignore t1 (f1) values (9599),(94410); +show status like 'handler_read_next'; +Variable_name Value +Handler_read_next 1 +# the above MUST BE =1 +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +update t1 set f1=100 where f1=9599; +update t1 set f1=9599 where f1=100; +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +# +# MDEV-32015 insert into an empty table fails with hash unique +# +create table t1 (f1 varchar(25), unique (f1) using hash); +insert ignore t1 (f1) values ('new york'),('virginia'),('spouse'),(null),('zqekmqpwutxnzddrbjycyo'),('nebraska'),('illinois'),('qe'),('ekmqpwut'),('arizona'),('arizona'); +Warnings: +Warning 1062 Duplicate entry 'arizona' for key 'f1' +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +# # End of 10.4 tests # # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index c7914d1e5dd63..c06b4169afed2 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -456,6 +456,38 @@ create table t1 (f text not null, unique (f)); insert into t1 (f) select 'f'; drop table t1; +--echo # +--echo # MDEV-32012 hash unique corrupts index on virtual blobs +--echo # +create table t1 ( + f1 varchar(25), + v1 mediumtext generated always as (concat('f1:', f1)) virtual, + unique key (f1) using hash, + key (v1(1000)) +); +flush status; +insert ignore t1 (f1) values (9599),(94410); +# handler_read_next must be 1 below, meaning there was a hash collision above. +# if a change in the hash function causes these values not to collide anymore, +# the test must be adjusted to use some other values that collide. +# to find a collision add an assert into check_duplicate_long_entry_key() +# and run, like, insert...select * seq_from_1_to_1000000000 +show status like 'handler_read_next'; +--echo # the above MUST BE =1 +check table t1 extended; +update t1 set f1=100 where f1=9599; +update t1 set f1=9599 where f1=100; +check table t1 extended; +drop table t1; + +--echo # +--echo # MDEV-32015 insert into an empty table fails with hash unique +--echo # +create table t1 (f1 varchar(25), unique (f1) using hash); +insert ignore t1 (f1) values ('new york'),('virginia'),('spouse'),(null),('zqekmqpwutxnzddrbjycyo'),('nebraska'),('illinois'),('qe'),('ekmqpwut'),('arizona'),('arizona'); +check table t1 extended; +drop table t1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/long_unique_bugs_replication.result b/mysql-test/main/long_unique_bugs_replication.result index af583d00ceafa..39b0ebe26d23d 100644 --- a/mysql-test/main/long_unique_bugs_replication.result +++ b/mysql-test/main/long_unique_bugs_replication.result @@ -1,3 +1,6 @@ +# +# MDEV-22722 Assertion "inited==NONE" failed in handler::ha_index_init on the slave during UPDATE +# include/master-slave.inc [connection master] create table t1 (i1 int, a1 text, unique key i1 (a1)) engine=myisam; @@ -6,7 +9,21 @@ insert into t1 values (2,2); update t1 set a1 = 'd' limit 1; update t1 set a1 = 'd2' where i1= 2; connection slave; -connection slave; connection master; drop table t1; +# +# MDEV-32093 long uniques break old->new replication +# +connection slave; +create table t1 (id int not null, b1 varchar(255) not null, b2 varchar(2550) not null, unique (id), unique key (b1,b2) using hash) default charset utf8mb3; +set global slave_exec_mode=idempotent; +binlog 'aRf2ZA8BAAAA/AAAAAABAAAAAAQAMTAuNS4xNS1NYXJpYURCLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABpF/ZkEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFRmTlk'; +binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw=='; +binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw=='; +binlog 'bBf2ZBMBAAAANAAAAHUkAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AaTGFIg==bBf2ZBgBAAAASAAAAL0kAAAAAHEAAAAAAAEABP//8I+kAAABAGIBAGWuv1VNCQAAAPBuWwAAAQBiAQBlrr9VTQkAAADxS9Lu'; +drop table t1; +set global slave_exec_mode=default; +# +# End of 10.4 tests +# include/rpl_end.inc diff --git a/mysql-test/main/long_unique_bugs_replication.test b/mysql-test/main/long_unique_bugs_replication.test index 1cacd088bee6d..9c44d13e6a5e3 100644 --- a/mysql-test/main/long_unique_bugs_replication.test +++ b/mysql-test/main/long_unique_bugs_replication.test @@ -2,9 +2,9 @@ # Long unique bugs related to master slave replication # -# -# MDEV-22722 Assertion "inited==NONE" failed in handler::ha_index_init on the slave during UPDATE -# +--echo # +--echo # MDEV-22722 Assertion "inited==NONE" failed in handler::ha_index_init on the slave during UPDATE +--echo # --source include/have_binlog_format_row.inc --source include/master-slave.inc @@ -16,9 +16,34 @@ update t1 set a1 = 'd' limit 1; update t1 set a1 = 'd2' where i1= 2; sync_slave_with_master; -connection slave; connection master; drop table t1; +--echo # +--echo # MDEV-32093 long uniques break old->new replication +--echo # + +# this is techically a bug in replication, but it needs an old master +# so we'll run it as a non-replicated test with BINLOG command +sync_slave_with_master; +create table t1 (id int not null, b1 varchar(255) not null, b2 varchar(2550) not null, unique (id), unique key (b1,b2) using hash) default charset utf8mb3; +set global slave_exec_mode=idempotent; + +# Format_description_log_event, MariaDB-10.5.15 +binlog 'aRf2ZA8BAAAA/AAAAAABAAAAAAQAMTAuNS4xNS1NYXJpYURCLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABpF/ZkEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFRmTlk'; + +### INSERT t1 VALUES (42127, 'b', 'e', 39952170926) +binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw=='; +binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw=='; + +### UPDATE t1 WHERE (42127, 'b', 'e', 39952170926) SET (23406, 'b', 'e', 39952170926) +binlog 'bBf2ZBMBAAAANAAAAHUkAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AaTGFIg==bBf2ZBgBAAAASAAAAL0kAAAAAHEAAAAAAAEABP//8I+kAAABAGIBAGWuv1VNCQAAAPBuWwAAAQBiAQBlrr9VTQkAAADxS9Lu'; + +drop table t1; +set global slave_exec_mode=default; + +--echo # +--echo # End of 10.4 tests +--echo # --source include/rpl_end.inc diff --git a/mysql-test/main/mrr_icp_extra.result b/mysql-test/main/mrr_icp_extra.result index 8f6ee88acc62b..1b33b008f35d2 100644 --- a/mysql-test/main/mrr_icp_extra.result +++ b/mysql-test/main/mrr_icp_extra.result @@ -30,6 +30,8 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition; Rowid-ordered scan diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index eaeb371d53545..b036d4870cda2 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -1384,12 +1384,17 @@ INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), EXPLAIN DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -1400,6 +1405,8 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL i NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -1530,12 +1537,15 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -1546,6 +1556,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -1582,12 +1593,15 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -1598,6 +1612,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -1876,12 +1891,17 @@ INSERT INTO t2 (i) SELECT i FROM t1; EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 update `test`.`t2` set `test`.`t2`.`a` = 10 where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -1892,6 +1912,8 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL i NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -2025,12 +2047,15 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 update `test`.`t2` set `test`.`t2`.`d` = 10 where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -2041,6 +2066,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -2077,12 +2103,15 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 update `test`.`t2` set `test`.`t2`.`d` = 10 where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value @@ -2093,6 +2122,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: +Note 1105 Cannot use key `a` part[1] for lookup: `test`.`t2`.`b` of type `char` = "10" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value diff --git a/mysql-test/main/mysql_install_db_win.test b/mysql-test/main/mysql_install_db_win.test index fd3bf6d24b0dd..f6113847b8d28 100644 --- a/mysql-test/main/mysql_install_db_win.test +++ b/mysql-test/main/mysql_install_db_win.test @@ -46,7 +46,7 @@ rmdir $ddir; # MDEV-28471 - mysql_install_db.exe fails with --innodb-page-size=64K --disable_result_log -exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R --innodb-page-size=64K --verbose +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R --innodb-page-size=64K --verbose; --enable_result_log rmdir $ddir; diff --git a/mysql-test/main/mysqlbinlog_row_compressed.test b/mysql-test/main/mysqlbinlog_row_compressed.test index 5c4aff00663e3..be9736347c96c 100644 --- a/mysql-test/main/mysqlbinlog_row_compressed.test +++ b/mysql-test/main/mysqlbinlog_row_compressed.test @@ -4,6 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_row.inc +--source include/have_normal_bzip.inc # # diff --git a/mysql-test/main/mysqlbinlog_stmt_compressed.test b/mysql-test/main/mysqlbinlog_stmt_compressed.test index 75dae6fa84e78..08db2009d6067 100644 --- a/mysql-test/main/mysqlbinlog_stmt_compressed.test +++ b/mysql-test/main/mysqlbinlog_stmt_compressed.test @@ -4,7 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_statement.inc - +--source include/have_normal_bzip.inc # # # mysqlbinlog: compressed query event diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index c90db85efcaf6..0c419c740e277 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -215,6 +215,7 @@ The following specify which files/extra groups are read (specified before remain Default flags for the regex library. Any combination of: DOTALL, DUPNAMES, EXTENDED, EXTENDED_MORE, EXTRA, MULTILINE, UNGREEDY + Use 'ALL' to set all combinations. --default-storage-engine=name The default storage engine for new tables --default-time-zone=name @@ -490,12 +491,14 @@ The following specify which files/extra groups are read (specified before remain --log-disabled-statements=name Don't log certain types of statements to general log. Any combination of: slave, sp + Use 'ALL' to set all combinations. --log-error[=name] Log errors to file (instead of stdout). If file name is not specified then 'datadir'/'log-basename'.err or the 'pid-file' path with extension .err is used --log-isam[=name] Log all MyISAM changes to file. --log-output=name How logs should be written. Any combination of: NONE, FILE, TABLE + Use 'ALL' to set all combinations. --log-queries-not-using-indexes Log queries that are executed without benefit of any index to the slow log if it is open. Same as @@ -514,15 +517,20 @@ The following specify which files/extra groups are read (specified before remain --log-slow-disabled-statements=name Don't log certain types of statements to slow log. Any combination of: admin, call, slave, sp + Use 'ALL' to set all combinations. --log-slow-filter=name Log only certain types of queries to the slow log. If - variable empty alll kind of queries are logged. All - types are bound by slow_query_time, except - 'not_using_index' which is always logged if enabled. Any - combination of: admin, filesort, filesort_on_disk, + variable empty all kind of queries are logged. All types + are bound by slow_query_time, except 'not_using_index' + which is always logged if enabled. Any combination of: + admin, filesort, filesort_on_disk, filesort_priority_queue, full_join, full_scan, not_using_index, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk + Use 'ALL' to set all combinations. + --log-slow-max-warnings=# + Max numbers of warnings printed to slow query log per + statement --log-slow-min-examined-row-limit=# Don't write queries to slow log that examine fewer rows than that @@ -550,7 +558,8 @@ The following specify which files/extra groups are read (specified before remain (Defaults to on; use --skip-log-slow-slave-statements to disable.) --log-slow-verbosity=name Verbosity level for the slow log. Any combination of: - innodb, query_plan, explain, engine, full + innodb, query_plan, explain, engine, warnings, full + Use 'ALL' to set all combinations. --log-tc=name Path to transaction coordinator log (used for transactions that affect more than one storage engine, when binary log is disabled). @@ -668,6 +677,7 @@ The following specify which files/extra groups are read (specified before remain Specifies how corrupted tables should be automatically repaired. Any combination of: DEFAULT, BACKUP, FORCE, QUICK, BACKUP_ALL, OFF + Use 'ALL' to set all combinations. --myisam-repair-threads=# If larger than 1, when repairing a MyISAM table all indexes will be created in parallel, with one thread per @@ -696,6 +706,11 @@ The following specify which files/extra groups are read (specified before remain --net-write-timeout=# Number of seconds to wait for a block to be written to a connection before aborting the write + --note-verbosity=name + Verbosity level for note-warnings given to the user. See + also @@sql_notes.. Any combination of: basic, + unusable_keys, explain + Use 'ALL' to set all combinations. --old Use compatible behavior from previous MariaDB version. See also --old-mode --old-alter-table[=name] @@ -707,6 +722,7 @@ The following specify which files/extra groups are read (specified before remain NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO, ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3, IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM + Use 'ALL' to set all combinations. --old-passwords Use old password encryption method (needed for 4.0 and older clients) --old-style-user-limits @@ -749,6 +765,10 @@ The following specify which files/extra groups are read (specified before remain --optimizer-max-sel-arg-weight=# The maximum weight of the SEL_ARG graph. Set to 0 for no limit + --optimizer-max-sel-args=# + The maximum number of SEL_ARG objects created when + optimizing a range. If more objects would be needed, the + range will not be used by the optimizer. --optimizer-prune-level=# Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from @@ -1358,6 +1378,7 @@ The following specify which files/extra groups are read (specified before remain variable is empty, no conversions are allowed and it is expected that the types match exactly. Any combination of: ALL_LOSSY, ALL_NON_LOSSY + Use 'ALL' to set all combinations. --slow-launch-time=# If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be @@ -1388,6 +1409,7 @@ The following specify which files/extra groups are read (specified before remain NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH, EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT, TIME_ROUND_FRACTIONAL + Use 'ALL' to set all combinations. --sql-safe-updates If set to 1, UPDATEs and DELETEs need either a key in the WHERE clause, or a LIMIT clause, or else they will aborted. Prevents the common mistake of accidentally @@ -1498,6 +1520,7 @@ The following specify which files/extra groups are read (specified before remain --time-format=name The TIME format (ignored) --tls-version=name TLS protocol version for secure connections.. Any combination of: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3 + Use 'ALL' to set all combinations. --tmp-disk-table-size=# Max size for data for an internal temporary on-disk MyISAM or Aria table. @@ -1679,6 +1702,7 @@ log-slave-updates FALSE log-slow-admin-statements TRUE log-slow-disabled-statements sp log-slow-filter admin,filesort,filesort_on_disk,filesort_priority_queue,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk +log-slow-max-warnings 10 log-slow-min-examined-row-limit 0 log-slow-query FALSE log-slow-query-time 10 @@ -1736,6 +1760,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 net-write-timeout 60 +note-verbosity basic,explain old FALSE old-alter-table DEFAULT old-mode UTF8_IS_UTF8MB3 @@ -1750,6 +1775,7 @@ optimizer-key-copy-cost 0.015685 optimizer-key-lookup-cost 0.435777 optimizer-key-next-find-cost 0.082347 optimizer-max-sel-arg-weight 32000 +optimizer-max-sel-args 16000 optimizer-prune-level 2 optimizer-row-copy-cost 0.060866 optimizer-row-lookup-cost 0.130839 diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index de337cba221f6..05720c9490d03 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -5399,15 +5399,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' SET @@global.log_output= @old_log_output_state; SET @@global.slow_query_log= @old_slow_query_log_state; @@ -5886,15 +5886,15 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log'; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; @@ -5981,15 +5981,15 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log'; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; @@ -6086,15 +6086,15 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log'; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; @@ -6546,15 +6546,15 @@ DROP TABLE IF EXISTS mysql.column_stats; - - + + - + diff --git a/mysql-test/main/no-threads-master.opt b/mysql-test/main/no-threads.opt similarity index 100% rename from mysql-test/main/no-threads-master.opt rename to mysql-test/main/no-threads.opt diff --git a/mysql-test/main/no-threads.test b/mysql-test/main/no-threads.test index c1a608a57e682..8235ff6728457 100644 --- a/mysql-test/main/no-threads.test +++ b/mysql-test/main/no-threads.test @@ -2,7 +2,6 @@ # an additional util connection and other statistics data -- source include/no_view_protocol.inc ---source include/one_thread_per_connection.inc # # Test the --thread-handler=no-threads option # diff --git a/mysql-test/main/null_key.result b/mysql-test/main/null_key.result index cee3484a304ad..0b1446fd72e1c 100644 --- a/mysql-test/main/null_key.result +++ b/mysql-test/main/null_key.result @@ -1,4 +1,5 @@ drop table if exists t1,t2; +set @@note_verbosity=replace(@@note_verbosity,"explain",""); create table t1 (a int, b int not null,unique key (a,b),index(b)) engine=myisam; insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6); Warnings: @@ -475,3 +476,5 @@ INSERT INTO t1 VALUES ('9','k'),(NULL,'r'); SELECT * FROM t1 WHERE (f3 = 83) OR (f10 = 'z' AND f3 IS NULL); f3 f10 DROP TABLE t1; +## end of 10.6 tests +set @@note_verbosity=default; diff --git a/mysql-test/main/null_key.test b/mysql-test/main/null_key.test index 26ac9a081f9c4..7fc21ee1e1d9f 100644 --- a/mysql-test/main/null_key.test +++ b/mysql-test/main/null_key.test @@ -5,6 +5,9 @@ drop table if exists t1,t2; --enable_warnings +# Disable wrong key warnings for this test (to test @@note_verbosity usage) +set @@note_verbosity=replace(@@note_verbosity,"explain",""); + create table t1 (a int, b int not null,unique key (a,b),index(b)) engine=myisam; insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6); explain select * from t1 where a is null; @@ -288,3 +291,6 @@ INSERT INTO t1 VALUES ('9','k'),(NULL,'r'); SELECT * FROM t1 WHERE (f3 = 83) OR (f10 = 'z' AND f3 IS NULL); DROP TABLE t1; +--echo ## end of 10.6 tests + +set @@note_verbosity=default; diff --git a/mysql-test/main/order_by_pack_big.test b/mysql-test/main/order_by_pack_big.test index 5e39d9f298829..ec8e0c12c54cf 100644 --- a/mysql-test/main/order_by_pack_big.test +++ b/mysql-test/main/order_by_pack_big.test @@ -112,9 +112,12 @@ set sort_buffer_size=262144*10; --source include/analyze-format.inc eval analyze format=json $query; flush status; +# Enable view-protocol after fix MDEV-27871 +--disable_view_protocol --disable_ps2_protocol eval $query; --enable_ps2_protocol +--enable_view_protocol show status like '%sort%'; set sort_buffer_size=default; @@ -126,9 +129,12 @@ set sort_buffer_size=32768; --source include/analyze-format.inc eval analyze format=json $query; flush status; +# Enable view-protocol after fix MDEV-27871 +--disable_view_protocol --disable_ps2_protocol eval $query; --enable_ps2_protocol +--enable_view_protocol show status like '%sort%'; set sort_buffer_size=default; diff --git a/mysql-test/main/partition.result b/mysql-test/main/partition.result index 9155f90d7817c..3cb9b3043cd8a 100644 --- a/mysql-test/main/partition.result +++ b/mysql-test/main/partition.result @@ -2859,6 +2859,19 @@ id select_type table type possible_keys key key_len ref rows Extra set optimizer_switch=@tmp_os; drop table t1,t2,t3; # +# MDEV-32388 MSAN / Valgrind errors in +# Item_func_like::get_mm_leaf upon query from partitioned table +# +CREATE TABLE t1 (a INT) PARTITION BY HASH(a) PARTITIONS 2; +INSERT INTO t1 VALUES (1),(2); +SELECT * FROM t1 WHERE a LIKE '1'; +a +1 +DROP TABLE t1; +# +# End of 10.6 tests +# +# # MDEV-31494 Server crashes in ha_partition::index_blocks / # get_key_scans_params # diff --git a/mysql-test/main/partition.test b/mysql-test/main/partition.test index a6b583798ce87..ca22e77971b46 100644 --- a/mysql-test/main/partition.test +++ b/mysql-test/main/partition.test @@ -3067,6 +3067,20 @@ set optimizer_switch=@tmp_os; drop table t1,t2,t3; +--echo # +--echo # MDEV-32388 MSAN / Valgrind errors in +--echo # Item_func_like::get_mm_leaf upon query from partitioned table +--echo # + +CREATE TABLE t1 (a INT) PARTITION BY HASH(a) PARTITIONS 2; +INSERT INTO t1 VALUES (1),(2); +SELECT * FROM t1 WHERE a LIKE '1'; +DROP TABLE t1; + +--echo # +--echo # End of 10.6 tests +--echo # + --echo # --echo # MDEV-31494 Server crashes in ha_partition::index_blocks / --echo # get_key_scans_params diff --git a/mysql-test/main/partition_explicit_prune.result b/mysql-test/main/partition_explicit_prune.result index f4436c5040c24..d31790e4433c3 100644 --- a/mysql-test/main/partition_explicit_prune.result +++ b/mysql-test/main/partition_explicit_prune.result @@ -350,7 +350,6 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 HANDLER_READ_FIRST 1 -HANDLER_READ_KEY 8 HANDLER_TMP_WRITE 24 # Should be 1 commit # 4 locks (1 ha_partition + 1 ha_innobase) x 2 (lock/unlock) @@ -775,7 +774,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 -HANDLER_READ_KEY 8 +HANDLER_READ_KEY 6 HANDLER_READ_RND_NEXT 2 HANDLER_TMP_WRITE 24 HANDLER_UPDATE 2 diff --git a/mysql-test/main/partition_innodb2.result b/mysql-test/main/partition_innodb2.result index 4476eb91447af..4d75b46825968 100644 --- a/mysql-test/main/partition_innodb2.result +++ b/mysql-test/main/partition_innodb2.result @@ -18,7 +18,7 @@ mod(seq, 10), seq from seq_1_to_50; explain delete t1, t2 from t1, t2 where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where -1 SIMPLE t2 ref a a 5 test.t1.a 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL # Using where +1 SIMPLE t2 ref a a 5 test.t1.a # delete t1, t2 from t1, t2 where t1.a=t2.a; drop table t1,t2; diff --git a/mysql-test/main/partition_innodb2.test b/mysql-test/main/partition_innodb2.test index 7581c5db4ca4a..e2089ae3e8a85 100644 --- a/mysql-test/main/partition_innodb2.test +++ b/mysql-test/main/partition_innodb2.test @@ -23,6 +23,7 @@ create table t2 ( insert into t2 select mod(seq, 10), seq from seq_1_to_50; +--replace_column 9 # explain delete t1, t2 from t1, t2 where t1.a=t2.a; delete t1, t2 from t1, t2 where t1.a=t2.a; diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result index 138aeff1fde25..e14b78baf32dd 100644 --- a/mysql-test/main/range.result +++ b/mysql-test/main/range.result @@ -642,6 +642,8 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t1 where a='aaa' collate latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL a NULL NULL NULL 9 Using where +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of collation `latin1_swedish_ci` = "'aaa' collate latin1_german1_ci" of collation `latin1_german1_ci` drop table t1; CREATE TABLE t1 ( `CLIENT` char(3) character set latin1 collate latin1_bin NOT NULL default '000', @@ -2236,6 +2238,8 @@ INSERT INTO t2 VALUES ('2001-01-01 11:22:33'); EXPLAIN SELECT * FROM t2 WHERE b=CAST('2001-01-01' AS DATE); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index b b 67 NULL 5 Using where; Using index +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "cast('2001-01-01' as date)" of type `date` SELECT * FROM t2 WHERE b=CAST('2001-01-01' AS DATE); b 2001#01#01 @@ -2250,6 +2254,8 @@ EXPLAIN SELECT * FROM t1, t2 WHERE a=b ORDER BY BINARY a, BINARY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort 1 SIMPLE t2 ALL b NULL NULL NULL 5 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "`t1`.`a`" of type `datetime` SELECT * FROM t1, t2 WHERE a=b ORDER BY BINARY a, BINARY b; a b 2001-01-01 00:00:00 2001#01#01 @@ -2262,6 +2268,8 @@ EXPLAIN SELECT * FROM t1, t2 WHERE b=a ORDER BY BINARY a, BINARY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort 1 SIMPLE t2 ALL b NULL NULL NULL 5 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "`t1`.`a`" of type `datetime` SELECT * FROM t1, t2 WHERE b=a ORDER BY BINARY a, BINARY b; a b 2001-01-01 00:00:00 2001#01#01 diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result index faaf2d233c4fd..a8d547f101d21 100644 --- a/mysql-test/main/range_mrr_icp.result +++ b/mysql-test/main/range_mrr_icp.result @@ -645,6 +645,8 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t1 where a='aaa' collate latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL a NULL NULL NULL 9 Using where +Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of collation `latin1_swedish_ci` = "'aaa' collate latin1_german1_ci" of collation `latin1_german1_ci` drop table t1; CREATE TABLE t1 ( `CLIENT` char(3) character set latin1 collate latin1_bin NOT NULL default '000', @@ -2239,6 +2241,8 @@ INSERT INTO t2 VALUES ('2001-01-01 11:22:33'); EXPLAIN SELECT * FROM t2 WHERE b=CAST('2001-01-01' AS DATE); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index b b 67 NULL 5 Using where; Using index +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "cast('2001-01-01' as date)" of type `date` SELECT * FROM t2 WHERE b=CAST('2001-01-01' AS DATE); b 2001#01#01 @@ -2253,6 +2257,8 @@ EXPLAIN SELECT * FROM t1, t2 WHERE a=b ORDER BY BINARY a, BINARY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort 1 SIMPLE t2 ALL b NULL NULL NULL 5 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "`t1`.`a`" of type `datetime` SELECT * FROM t1, t2 WHERE a=b ORDER BY BINARY a, BINARY b; a b 2001-01-01 00:00:00 2001#01#01 @@ -2265,6 +2271,8 @@ EXPLAIN SELECT * FROM t1, t2 WHERE b=a ORDER BY BINARY a, BINARY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort 1 SIMPLE t2 ALL b NULL NULL NULL 5 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `b` part[0] for lookup: `test`.`t2`.`b` of type `varchar` = "`t1`.`a`" of type `datetime` SELECT * FROM t1, t2 WHERE b=a ORDER BY BINARY a, BINARY b; a b 2001-01-01 00:00:00 2001#01#01 diff --git a/mysql-test/main/set_statement.result b/mysql-test/main/set_statement.result index a1b1d3659ffc7..810ec32eee26c 100644 --- a/mysql-test/main/set_statement.result +++ b/mysql-test/main/set_statement.result @@ -1367,4 +1367,16 @@ SET sql_mode=ORACLE; SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown'; SET sql_mode=default; SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown'; +# +# MDEV-17711 Assertion `arena_for_set_stmt== 0' failed in LEX::set_arena_for_set_stmt upon SET STATEMENT +# +set rand_seed1=1, rand_seed2=2; +set statement rand_seed1=4 for select 2, @@rand_seed1, @@rand_seed2; +set statement rand_seed2=5 for select 3, @@rand_seed1, @@rand_seed2 $ +2 @@rand_seed1 @@rand_seed2 +2 4 2 +3 @@rand_seed1 @@rand_seed2 +3 1 5 +# # End of 10.4 tests +# diff --git a/mysql-test/main/set_statement.test b/mysql-test/main/set_statement.test index 86a5b7a5eabb6..b8df5b1797dc2 100644 --- a/mysql-test/main/set_statement.test +++ b/mysql-test/main/set_statement.test @@ -1197,4 +1197,18 @@ SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unk SET sql_mode=default; SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown'; +--echo # +--echo # MDEV-17711 Assertion `arena_for_set_stmt== 0' failed in LEX::set_arena_for_set_stmt upon SET STATEMENT +--echo # + +--disable_ps_protocol +--delimiter $ +set rand_seed1=1, rand_seed2=2; +set statement rand_seed1=4 for select 2, @@rand_seed1, @@rand_seed2; +set statement rand_seed2=5 for select 3, @@rand_seed1, @@rand_seed2 $ +--delimiter ; +--enable_ps_protocol + +--echo # --echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 48c276da8c891..cb94f40e0f7c1 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8923,6 +8923,31 @@ CREATE TABLE t1 (a INT); CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1)); ERROR 42000: PROCEDURE does not support subqueries or stored functions DROP TABLE t1; +# +# MDEV-23902: MariaDB crash on calling function +# +CREATE FUNCTION f2 () RETURNS VARCHAR(1) +BEGIN +DECLARE rec1 ROW TYPE OF v1; +SELECT z INTO rec1 FROM v1; +RETURN 1; +END| +CREATE FUNCTION f1 () RETURNS VARCHAR(1) RETURN f2() ; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN f_not_exist(); +CREATE VIEW v1 AS SELECT f3() z; +SELECT f1(); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +# Check that crash doen't happen in case f3 completes with success. +DROP FUNCTION f3; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN '!'; +SELECT f1(); +f1() +1 +# Clean up +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP VIEW v1; # End of 10.4 tests # # diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index a087518ed6fa4..9d2ea3cfdfc34 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10534,6 +10534,38 @@ CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1) DROP TABLE t1; +--echo # +--echo # MDEV-23902: MariaDB crash on calling function +--echo # + +--delimiter | +CREATE FUNCTION f2 () RETURNS VARCHAR(1) +BEGIN + DECLARE rec1 ROW TYPE OF v1; + SELECT z INTO rec1 FROM v1; + RETURN 1; +END| +--delimiter ; + +CREATE FUNCTION f1 () RETURNS VARCHAR(1) RETURN f2() ; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN f_not_exist(); +CREATE VIEW v1 AS SELECT f3() z; + +--error ER_VIEW_INVALID +SELECT f1(); + +--echo # Check that crash doen't happen in case f3 completes with success. +DROP FUNCTION f3; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN '!'; + +SELECT f1(); + +--echo # Clean up +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP VIEW v1; + --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/ssl_cipher.result b/mysql-test/main/ssl_cipher.result index 42f37f488e7c0..d549ec7d2b449 100644 --- a/mysql-test/main/ssl_cipher.result +++ b/mysql-test/main/ssl_cipher.result @@ -66,3 +66,5 @@ VARIABLE_VALUE like '%AES128-SHA%' 1 disconnect ssl_con; connection default; +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +FOUND 2 /TLSv1.0 and TLSv1.1 are insecure/ in mysqld.1.err diff --git a/mysql-test/main/ssl_cipher.test b/mysql-test/main/ssl_cipher.test index 4671b085ce782..0d33ec5d5e020 100644 --- a/mysql-test/main/ssl_cipher.test +++ b/mysql-test/main/ssl_cipher.test @@ -2,6 +2,11 @@ # Various tests that require setting of a specific ssl_cipher # which currently doesn't work in OpenSSL 1.1.1 # + +--disable_query_log +CALL mtr.add_suppression("are insecure"); +--enable_query_log + --source include/have_ssl_communication.inc if (`select @@version_ssl_library like 'OpenSSL 1.1.1%'`) { @@ -101,3 +106,9 @@ SHOW STATUS LIKE 'Ssl_cipher'; SELECT VARIABLE_VALUE like '%AES128-SHA%' FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher_list'; disconnect ssl_con; connection default; + +# MDEV-31369 Disable TLS v1.0 and 1.1 for MariaDB +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN= TLSv1.0 and TLSv1.1 are insecure +--source include/search_pattern_in_file.inc diff --git a/mysql-test/main/stat_tables.result b/mysql-test/main/stat_tables.result index a6642d66fb7c9..be1a88e97436a 100644 --- a/mysql-test/main/stat_tables.result +++ b/mysql-test/main/stat_tables.result @@ -562,14 +562,14 @@ test.t1 analyze Warning Engine-independent statistics are not collected for colu test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL DELETE FROM mysql.column_stats WHERE db_name='test' AND table_name='t1' AND column_name='t'; INSERT INTO mysql.column_stats VALUES ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL SELECT pk FROM t1; pk @@ -593,7 +593,7 @@ pk c 2 bar SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); SELECT * FROM t1; @@ -923,4 +923,82 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 2.78 10.00 Using where drop table t1; set @@global.histogram_size=@save_histogram_size; +# # End of 10.4 tests +# +# +# MDEV-29693 ANALYZE TABLE still flushes table definition cache +# when engine-independent statistics is used +# +create table t1 (a int); +insert into t1 select seq from seq_0_to_99; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connect con1, localhost, root,,; +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection default; +update t1 set a= a +100; +# Explain shows outdated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection default; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# Now explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 1.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 1.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +# Run update and analyze in con1: +update t1 set a= a - 150; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +connection default; +# Explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +disconnect con1; +drop table t1; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/stat_tables.test b/mysql-test/main/stat_tables.test index 895db3ce72e5d..8333613dce405 100644 --- a/mysql-test/main/stat_tables.test +++ b/mysql-test/main/stat_tables.test @@ -1,7 +1,6 @@ # Tests will be skipped for the view protocol because the view protocol creates # an additional util connection and other statistics data --- source include/no_view_protocol.inc - +--source include/no_view_protocol.inc --source include/have_stat_tables.inc --source include/have_partition.inc --source include/have_sequence.inc @@ -641,4 +640,64 @@ drop table t1; set @@global.histogram_size=@save_histogram_size; +--echo # --echo # End of 10.4 tests +--echo # + +--echo # +--echo # MDEV-29693 ANALYZE TABLE still flushes table definition cache +--echo # when engine-independent statistics is used +--echo # + +create table t1 (a int); +insert into t1 select seq from seq_0_to_99; +analyze table t1 persistent for all; +analyze table t1 persistent for all; + +explain extended select count(*) from t1 where a < 50; + +connect (con1, localhost, root,,); +--connection con1 +explain extended select count(*) from t1 where a < 50; + +let $open_tables=`select variable_value from information_schema.global_status where variable_name="OPENED_TABLES"`; + +--connection default +update t1 set a= a +100; + +--echo # Explain shows outdated statistics: +explain extended select count(*) from t1 where a < 50; +--connection con1 +explain extended select count(*) from t1 where a < 50; + +--connection default +analyze table t1 persistent for all; +--echo # Now explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; +--connection con1 +explain extended select count(*) from t1 where a < 50; + +--connection con1 +--echo # Run update and analyze in con1: +update t1 set a= a - 150; +analyze table t1 persistent for all; + +--connection default +--echo # Explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; + +disconnect con1; + +let $new_open_tables=`select variable_value from information_schema.global_status where variable_name="OPENED_TABLES"`; + +if ($open_tables != $new_open_tables) +{ +--let $diff=`select $new_open_tables - $open_tables` +--echo "Fail: Test opened $diff new tables, 0 was expected" +} + +drop table t1; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysql-test/main/stat_tables_flush.result b/mysql-test/main/stat_tables_flush.result new file mode 100644 index 0000000000000..36d847977b916 --- /dev/null +++ b/mysql-test/main/stat_tables_flush.result @@ -0,0 +1,190 @@ +# +# Check that ANALYZE TABLE is remembered by MyISAM and Aria +# +create table t1 (a int) engine=myisam; +insert into t1 select seq from seq_0_to_99; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +update t1 set a=100 where a=1; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +update t1 set a=100 where a=2; +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# Aria transactional=0 +ALTER TABLE t1 ENGINE=aria transactional=0; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +update t1 set a=100 where a=10; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +update t1 set a=100 where a=11; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +update t1 set a=100 where a=12; +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +# Aria transactional=1 +ALTER TABLE t1 ENGINE=aria transactional=1; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +update t1 set a=100 where a=20; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +update t1 set a=100 where a=21; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +update t1 set a=100 where a=22; +flush tables; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +drop table t1; +# +# Test that histograms are read after flush +# +create table t1 (a int); +insert into t1 select seq from seq_1_to_10; +insert into t1 select A.seq from seq_10_to_20 A, seq_1_to_9 B; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027083745, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 109, + "cost": 0.027083745, + "filtered": 3.669724703, + "attached_condition": "t1.a between 2 and 5" + } + } + ] + } +} +explain format=json select * from t1 where a between 12 and 15; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027083745, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 109, + "cost": 0.027083745, + "filtered": 33.02752304, + "attached_condition": "t1.a between 12 and 15" + } + } + ] + } +} +flush tables; +set @@optimizer_use_condition_selectivity=3; +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027083745, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 109, + "cost": 0.027083745, + "filtered": 15.78947353, + "attached_condition": "t1.a between 2 and 5" + } + } + ] + } +} +set @@optimizer_use_condition_selectivity=4; +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027083745, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 109, + "cost": 0.027083745, + "filtered": 3.669724703, + "attached_condition": "t1.a between 2 and 5" + } + } + ] + } +} +drop table t1; +set @@optimizer_use_condition_selectivity=default; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/stat_tables_flush.test b/mysql-test/main/stat_tables_flush.test new file mode 100644 index 0000000000000..4c916f47ad76a --- /dev/null +++ b/mysql-test/main/stat_tables_flush.test @@ -0,0 +1,72 @@ +--source include/have_sequence.inc + +--echo # +--echo # Check that ANALYZE TABLE is remembered by MyISAM and Aria +--echo # + +create table t1 (a int) engine=myisam; +insert into t1 select seq from seq_0_to_99; +analyze table t1 persistent for all; +flush tables; +analyze table t1 persistent for all; +update t1 set a=100 where a=1; +analyze table t1 persistent for all; +update t1 set a=100 where a=2; +flush tables; +analyze table t1 persistent for all; + +--echo # Aria transactional=0 +ALTER TABLE t1 ENGINE=aria transactional=0; +analyze table t1 persistent for all; +update t1 set a=100 where a=10; +analyze table t1 persistent for all; +analyze table t1 persistent for all; +flush tables; +analyze table t1 persistent for all; +update t1 set a=100 where a=11; +analyze table t1 persistent for all; +update t1 set a=100 where a=12; +flush tables; +analyze table t1 persistent for all; + +--echo # Aria transactional=1 + +ALTER TABLE t1 ENGINE=aria transactional=1; +analyze table t1 persistent for all; +update t1 set a=100 where a=20; +analyze table t1 persistent for all; +analyze table t1 persistent for all; +flush tables; +analyze table t1 persistent for all; +update t1 set a=100 where a=21; +analyze table t1 persistent for all; +update t1 set a=100 where a=22; +flush tables; +analyze table t1 persistent for all; +drop table t1; + +--echo # +--echo # Test that histograms are read after flush +--echo # + +create table t1 (a int); +insert into t1 select seq from seq_1_to_10; + +insert into t1 select A.seq from seq_10_to_20 A, seq_1_to_9 B; +analyze table t1 persistent for all; + +explain format=json select * from t1 where a between 2 and 5; +explain format=json select * from t1 where a between 12 and 15; + +flush tables; +set @@optimizer_use_condition_selectivity=3; +explain format=json select * from t1 where a between 2 and 5; +set @@optimizer_use_condition_selectivity=4; +explain format=json select * from t1 where a between 2 and 5; + +drop table t1; +set @@optimizer_use_condition_selectivity=default; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysql-test/main/stat_tables_innodb.result b/mysql-test/main/stat_tables_innodb.result index c90e99a9bbfa3..a7901c994b1bd 100644 --- a/mysql-test/main/stat_tables_innodb.result +++ b/mysql-test/main/stat_tables_innodb.result @@ -594,14 +594,14 @@ test.t1 analyze Warning Engine-independent statistics are not collected for colu test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL DELETE FROM mysql.column_stats WHERE db_name='test' AND table_name='t1' AND column_name='t'; INSERT INTO mysql.column_stats VALUES ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL SELECT pk FROM t1; pk @@ -625,7 +625,7 @@ pk c 2 bar SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 pk 1 2 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c bar foo 0.0000 3.0000 1.0000 0 NULL NULL CREATE OR REPLACE TABLE t1 (pk int PRIMARY KEY, a char(7)); SELECT * FROM t1; @@ -955,7 +955,85 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 2.78 10.00 Using where drop table t1; set @@global.histogram_size=@save_histogram_size; +# # End of 10.4 tests +# +# +# MDEV-29693 ANALYZE TABLE still flushes table definition cache +# when engine-independent statistics is used +# +create table t1 (a int); +insert into t1 select seq from seq_0_to_99; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connect con1, localhost, root,,; +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection default; +update t1 set a= a +100; +# Explain shows outdated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 50.51 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection default; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# Now explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 1.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 1.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +connection con1; +# Run update and analyze in con1: +update t1 set a= a - 150; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +connection default; +# Explain shows updated statistics: +explain extended select count(*) from t1 where a < 50; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 Using where +Warnings: +Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`a` < 50 +disconnect con1; +drop table t1; +# +# End of 10.6 tests +# set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/stat_tables_missing.result b/mysql-test/main/stat_tables_missing.result index 3f8f9e982ae7d..f7a1fcfbb9064 100644 --- a/mysql-test/main/stat_tables_missing.result +++ b/mysql-test/main/stat_tables_missing.result @@ -2,6 +2,9 @@ create table t1 (a int); alter table mysql.column_stats rename to mysql.column_stats1; flush tables; alter table t1 change a b varchar(100); +Warnings: +Warning 1177 Got error 1146 when trying to open statistics table `table_stats` for updating statistics +Warning 1177 Got error 1146 when trying to open statistics table `table_stats` for updating statistics show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/main/statistics.result b/mysql-test/main/statistics.result index 3aa9fd1d3061d..f5ea0bf92e037 100644 --- a/mysql-test/main/statistics.result +++ b/mysql-test/main/statistics.result @@ -72,7 +72,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -95,7 +95,7 @@ COUNT(*) SELECT * FROM mysql.column_stats WHERE db_name='test' AND table_name='t1' AND column_name='a'; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL SELECT MIN(t1.a), MAX(t1.a), (SELECT COUNT(*) FROM t1 WHERE t1.b IS NULL) / (SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.a)", @@ -226,7 +226,7 @@ hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats ORDER BY db_name, table_name, column_name; db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) -test t1 a 0 49 0.0000 1.0000 4 SINGLE_PREC_HB 0.180,0.204,0.247,0.184,0.184 +test t1 a 0 49 0.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 SINGLE_PREC_HB 0.000,0.247,0.502,0.251,0.000 test t1 c aaaa dddddddd 0.1250 7.0000 4 SINGLE_PREC_HB 0.000,0.333,0.333,0.333,0.000 test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 SINGLE_PREC_HB 0.000,0.098,0.000,0.902,0.000 @@ -246,7 +246,7 @@ hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats ORDER BY db_name, table_name, column_name; db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) -test t1 a 0 49 0.0000 1.0000 8 DOUBLE_PREC_HB 0.18367,0.20407,0.24489,0.18367,0.18369 +test t1 a 0 49 0.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 8 DOUBLE_PREC_HB 0.00000,0.24999,0.50001,0.25000,0.00000 test t1 c aaaa dddddddd 0.1250 7.0000 8 DOUBLE_PREC_HB 0.00000,0.33333,0.33333,0.33333,0.00000 test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 8 DOUBLE_PREC_HB 0.00000,0.10161,0.00000,0.89839,0.00000 @@ -293,13 +293,13 @@ test t1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -322,13 +322,13 @@ test s1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test s1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test s1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test s1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -351,13 +351,13 @@ test t1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -379,7 +379,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -420,7 +420,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL @@ -445,7 +445,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -472,7 +472,7 @@ db_name table_name cardinality test s1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test s1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -510,7 +510,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -545,7 +545,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -556,6 +556,13 @@ test t1 PRIMARY 1 1.0000 test t1 idx2 1 7.0000 test t1 idx2 2 2.3846 test t1 idx3 1 8.5000 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(x) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM mysql.column_stats where column_name="x"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL ALTER TABLE t1 CHANGE COLUMN x b varchar(32); SHOW CREATE TABLE t1; Table Create Table @@ -574,7 +581,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -591,7 +598,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -632,7 +639,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -661,7 +668,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -672,15 +679,15 @@ test t1 PRIMARY 1 1.0000 test t1 idx2 1 7.0000 test t1 idx2 2 2.3846 test t1 idx3 1 8.5000 -LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' - INTO TABLE mysql.column_stats +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' IGNORE +INTO TABLE mysql.column_stats FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_index_stats' INTO TABLE mysql.index_stats FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -714,7 +721,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -777,7 +784,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -792,7 +799,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b NULL NULL 1.0000 NULL NULL 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -816,7 +823,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -848,7 +855,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -878,7 +885,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -893,7 +900,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -975,7 +982,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1006,8 +1013,8 @@ test t1 40 test t2 40 SELECT * FROM mysql.column_stats ORDER BY column_name, table_name; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL -test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL +test t2 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL @@ -1051,7 +1058,7 @@ db_name table_name cardinality test t2 40 SELECT * FROM mysql.column_stats ORDER BY column_name; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t2 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1110,12 +1117,17 @@ test t2 idx4 1 6.2000 test t2 idx4 2 1.7222 test t2 idx4 3 1.1154 test t2 idx4 4 1.0000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL ALTER TABLE t2 CHANGE COLUMN b b varchar(30); SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; db_name table_name index_name prefix_arity avg_frequency test t2 idx2 1 7.0000 test t2 idx2 2 2.3846 test t2 idx3 1 8.5000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -1151,6 +1163,9 @@ test t2 idx4 1 6.2000 test t2 idx4 2 1.7222 test t2 idx4 3 1.1154 test t2 idx4 4 1.0000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t2 b 0 zzzzzzzzzzzzzzzzzz 0.0000 13.9000 6.6667 0 NULL NULL ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -1224,7 +1239,7 @@ test.t1 analyze Warning Engine-independent statistics are not collected for colu test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1280,7 +1295,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL diff --git a/mysql-test/main/statistics.test b/mysql-test/main/statistics.test index 7faf35be9a5fa..c964bc2ec2346 100644 --- a/mysql-test/main/statistics.test +++ b/mysql-test/main/statistics.test @@ -315,6 +315,10 @@ SELECT * FROM mysql.column_stats; --sorted_result SELECT * FROM mysql.index_stats; +# Add 'x' back that was deleted above +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(x) INDEXES(); +SELECT * FROM mysql.column_stats where column_name="x"; + ALTER TABLE t1 CHANGE COLUMN x b varchar(32); SHOW CREATE TABLE t1; --sorted_result @@ -357,7 +361,7 @@ SELECT * FROM mysql.index_stats; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval -LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/save_column_stats' +LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/save_column_stats' IGNORE INTO TABLE mysql.column_stats FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR @@ -505,14 +509,17 @@ SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL; SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; +SELECT * FROM mysql.column_stats where column_name="b"; ALTER TABLE t2 CHANGE COLUMN b b varchar(30); SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; +SELECT * FROM mysql.column_stats where column_name="b"; ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; ALTER TABLE t2 CHANGE COLUMN b b varchar(32); SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; +SELECT * FROM mysql.column_stats where column_name="b"; ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; diff --git a/mysql-test/main/statistics_json.result b/mysql-test/main/statistics_json.result index 7b7cc86642c23..0d1953e922bb3 100644 --- a/mysql-test/main/statistics_json.result +++ b/mysql-test/main/statistics_json.result @@ -78,7 +78,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -101,7 +101,7 @@ COUNT(*) SELECT * FROM mysql.column_stats WHERE db_name='test' AND table_name='t1' AND column_name='a'; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL SELECT MIN(t1.a), MAX(t1.a), (SELECT COUNT(*) FROM t1 WHERE t1.b IS NULL) / (SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.a)", @@ -232,34 +232,7 @@ hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats ORDER BY db_name, table_name, column_name; db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) -test t1 a 0 49 0.0000 1.0000 4 JSON_HB { - "target_histogram_size": 4, - "collected_at": "REPLACED", - "collected_by": "REPLACED", - "histogram_hb": [ - { - "start": "0", - "size": 0.275, - "ndv": 11 - }, - { - "start": "12", - "size": 0.275, - "ndv": 11 - }, - { - "start": "29", - "size": 0.275, - "ndv": 11 - }, - { - "start": "41", - "end": "49", - "size": 0.175, - "ndv": 7 - } - ] -} +test t1 a 0 49 0.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 JSON_HB { "target_histogram_size": 4, "collected_at": "REPLACED", @@ -409,49 +382,7 @@ hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats ORDER BY db_name, table_name, column_name; db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) -test t1 a 0 49 0.0000 1.0000 7 JSON_HB { - "target_histogram_size": 8, - "collected_at": "REPLACED", - "collected_by": "REPLACED", - "histogram_hb": [ - { - "start": "0", - "size": 0.15, - "ndv": 6 - }, - { - "start": "7", - "size": 0.15, - "ndv": 6 - }, - { - "start": "14", - "size": 0.15, - "ndv": 6 - }, - { - "start": "22", - "size": 0.15, - "ndv": 6 - }, - { - "start": "31", - "size": 0.15, - "ndv": 6 - }, - { - "start": "38", - "size": 0.15, - "ndv": 6 - }, - { - "start": "44", - "end": "49", - "size": 0.1, - "ndv": 4 - } - ] -} +test t1 a 0 49 0.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 5 JSON_HB { "target_histogram_size": 8, "collected_at": "REPLACED", @@ -653,13 +584,13 @@ test t1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -682,13 +613,13 @@ test s1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test s1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test s1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test s1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -711,13 +642,13 @@ test t1 40 test t3 17 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL +test t3 a 0 38 0.0000 4.0000 1.0000 NULL NULL NULL test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL SELECT * FROM mysql.index_stats; @@ -739,7 +670,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -780,7 +711,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL @@ -805,7 +736,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -832,7 +763,7 @@ db_name table_name cardinality test s1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test s1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -870,7 +801,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -905,7 +836,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -916,6 +847,13 @@ test t1 PRIMARY 1 1.0000 test t1 idx2 1 7.0000 test t1 idx2 2 2.3846 test t1 idx3 1 8.5000 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(x) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM mysql.column_stats where column_name="x"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL ALTER TABLE t1 CHANGE COLUMN x b varchar(32); SHOW CREATE TABLE t1; Table Create Table @@ -934,7 +872,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -951,7 +889,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -992,7 +930,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1021,7 +959,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1032,15 +970,15 @@ test t1 PRIMARY 1 1.0000 test t1 idx2 1 7.0000 test t1 idx2 2 2.3846 test t1 idx3 1 8.5000 -LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' - INTO TABLE mysql.column_stats +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' IGNORE +INTO TABLE mysql.column_stats FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_index_stats' INTO TABLE mysql.index_stats FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1074,7 +1012,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1137,7 +1075,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1152,7 +1090,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b NULL NULL 1.0000 NULL NULL 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1176,7 +1114,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1208,7 +1146,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1238,7 +1176,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1253,7 +1191,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1335,7 +1273,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1366,8 +1304,8 @@ test t1 40 test t2 40 SELECT * FROM mysql.column_stats ORDER BY column_name, table_name; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL -test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL +test t2 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL @@ -1411,7 +1349,7 @@ db_name table_name cardinality test t2 40 SELECT * FROM mysql.column_stats ORDER BY column_name; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t2 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL @@ -1470,12 +1408,17 @@ test t2 idx4 1 6.2000 test t2 idx4 2 1.7222 test t2 idx4 3 1.1154 test t2 idx4 4 1.0000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL ALTER TABLE t2 CHANGE COLUMN b b varchar(30); SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name; db_name table_name index_name prefix_arity avg_frequency test t2 idx2 1 7.0000 test t2 idx2 2 2.3846 test t2 idx3 1 8.5000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -1511,6 +1454,9 @@ test t2 idx4 1 6.2000 test t2 idx4 2 1.7222 test t2 idx4 3 1.1154 test t2 idx4 4 1.0000 +SELECT * FROM mysql.column_stats where column_name="b"; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t2 b 0 zzzzzzzzzzzzzzzzzz 0.0000 13.9000 6.6667 0 NULL NULL ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -1584,7 +1530,7 @@ test.t1 analyze Warning Engine-independent statistics are not collected for colu test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -1640,7 +1586,7 @@ db_name table_name cardinality test t1 40 SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL +test t1 a 0 49 0.0000 4.0000 1.0000 NULL NULL NULL test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL @@ -4765,254 +4711,256 @@ set histogram_size=50; ANALYZE TABLE Country, City, CountryLanguage persistent for all; SELECT column_name, min_value, max_value, hist_size, hist_type, histogram FROM mysql.column_stats; column_name min_value max_value hist_size hist_type histogram -Code ABW ZWE 48 JSON_HB { +Code ABW ZWE NULL NULL NULL +Name Afghanistan Zimbabwe 48 JSON_HB { "target_histogram_size": 50, "collected_at": "REPLACED", "collected_by": "REPLACED", "histogram_hb": [ { - "start": "ABW", + "start": "Afghanistan", "size": 0.020920502, "ndv": 5 }, { - "start": "AND", + "start": "Angola", "size": 0.020920502, "ndv": 5 }, { - "start": "ASM", + "start": "Armenia", "size": 0.020920502, "ndv": 5 }, { - "start": "AUT", + "start": "Bahamas", "size": 0.020920502, "ndv": 5 }, { - "start": "BFA", + "start": "Belgium", "size": 0.020920502, "ndv": 5 }, { - "start": "BIH", + "start": "Bolivia", "size": 0.020920502, "ndv": 5 }, { - "start": "BRA", + "start": "British Indian Ocean Territory", "size": 0.020920502, "ndv": 5 }, { - "start": "BWA", + "start": "Cambodia", "size": 0.020920502, "ndv": 5 }, { - "start": "CHL", + "start": "Central African Republic", "size": 0.020920502, "ndv": 5 }, { - "start": "COG", + "start": "Cocos (Keeling) Islands", "size": 0.020920502, "ndv": 5 }, { - "start": "CRI", + "start": "Cook Islands", "size": 0.020920502, "ndv": 5 }, { - "start": "CZE", + "start": "Czech Republic", "size": 0.020920502, "ndv": 5 }, { - "start": "DOM", + "start": "Dominican Republic", "size": 0.020920502, "ndv": 5 }, { - "start": "ESH", + "start": "Equatorial Guinea", "size": 0.020920502, "ndv": 5 }, { - "start": "FJI", + "start": "Faroe Islands", "size": 0.020920502, "ndv": 5 }, { - "start": "GAB", + "start": "French Polynesia", "size": 0.020920502, "ndv": 5 }, { - "start": "GIN", + "start": "Germany", "size": 0.020920502, "ndv": 5 }, { - "start": "GRC", + "start": "Grenada", "size": 0.020920502, "ndv": 5 }, { - "start": "GUM", + "start": "Guinea-Bissau", "size": 0.020920502, "ndv": 5 }, { - "start": "HRV", + "start": "Honduras", "size": 0.020920502, "ndv": 5 }, { - "start": "IOT", + "start": "Indonesia", "size": 0.020920502, "ndv": 5 }, { - "start": "ISR", + "start": "Italy", "size": 0.020920502, "ndv": 5 }, { - "start": "KAZ", + "start": "Kenya", "size": 0.020920502, "ndv": 5 }, { - "start": "KNA", + "start": "Latvia", "size": 0.020920502, "ndv": 5 }, { - "start": "LBR", + "start": "Liechtenstein", "size": 0.020920502, "ndv": 5 }, { - "start": "LSO", + "start": "Madagascar", "size": 0.020920502, "ndv": 5 }, { - "start": "MAR", + "start": "Malta", "size": 0.020920502, "ndv": 5 }, { - "start": "MEX", + "start": "Mayotte", "size": 0.020920502, "ndv": 5 }, { - "start": "MMR", + "start": "Mongolia", "size": 0.020920502, "ndv": 5 }, { - "start": "MSR", + "start": "Namibia", "size": 0.020920502, "ndv": 5 }, { - "start": "MYT", + "start": "New Caledonia", "size": 0.020920502, "ndv": 5 }, { - "start": "NGA", + "start": "Niue", "size": 0.020920502, "ndv": 5 }, { - "start": "NPL", + "start": "Oman", "size": 0.020920502, "ndv": 5 }, { - "start": "PAN", + "start": "Papua New Guinea", "size": 0.020920502, "ndv": 5 }, { - "start": "PNG", + "start": "Poland", "size": 0.020920502, "ndv": 5 }, { - "start": "PRY", + "start": "Russian Federation", "size": 0.020920502, "ndv": 5 }, { - "start": "ROM", + "start": "Saint Lucia", "size": 0.020920502, "ndv": 5 }, { - "start": "SEN", + "start": "Sao Tome and Principe", "size": 0.020920502, "ndv": 5 }, { - "start": "SLB", + "start": "Singapore", "size": 0.020920502, "ndv": 5 }, { - "start": "SPM", + "start": "South Africa", "size": 0.020920502, "ndv": 5 }, { - "start": "SWE", + "start": "Sudan", "size": 0.020920502, "ndv": 5 }, { - "start": "TCD", + "start": "Switzerland", "size": 0.020920502, "ndv": 5 }, { - "start": "TKM", + "start": "Thailand", "size": 0.020920502, "ndv": 5 }, { - "start": "TUR", + "start": "Tunisia", "size": 0.020920502, "ndv": 5 }, { - "start": "UKR", + "start": "Uganda", "size": 0.020920502, "ndv": 5 }, { - "start": "VAT", + "start": "United States Minor Outlying Islands", "size": 0.020920502, "ndv": 5 }, { - "start": "VNM", + "start": "Vietnam", "size": 0.020920502, "ndv": 5 }, { - "start": "YUG", - "end": "ZWE", + "start": "Yemen", + "end": "Zimbabwe", "size": 0.016736402, "ndv": 4 } ] } +ID 1 4079 NULL NULL NULL Country ABW ZWE 39 JSON_HB { "target_histogram_size": 50, "collected_at": "REPLACED", @@ -5216,549 +5164,301 @@ Country ABW ZWE 39 JSON_HB { } ] } -Name Afghanistan Zimbabwe 48 JSON_HB { +SurfaceArea 0.40 17075400.00 48 JSON_HB { "target_histogram_size": 50, "collected_at": "REPLACED", "collected_by": "REPLACED", "histogram_hb": [ { - "start": "Afghanistan", + "start": "0.40", "size": 0.020920502, "ndv": 5 }, { - "start": "Angola", + "start": "16.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Armenia", + "start": "49.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Bahamas", + "start": "96.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Belgium", + "start": "181.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Bolivia", + "start": "242.00", "size": 0.020920502, "ndv": 5 }, { - "start": "British Indian Ocean Territory", + "start": "314.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Cambodia", + "start": "373.00", "size": 0.020920502, - "ndv": 5 + "ndv": 4 }, { - "start": "Central African Republic", + "start": "455.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Cocos (Keeling) Islands", + "start": "618.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Cook Islands", + "start": "726.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Czech Republic", + "start": "1102.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Dominican Republic", + "start": "2510.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Equatorial Guinea", + "start": "4033.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Faroe Islands", + "start": "8875.00", "size": 0.020920502, "ndv": 5 }, { - "start": "French Polynesia", + "start": "11295.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Germany", + "start": "17364.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Grenada", + "start": "21041.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Guinea-Bissau", + "start": "26338.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Honduras", + "start": "28896.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Indonesia", + "start": "36125.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Italy", + "start": "45227.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Kenya", + "start": "51197.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Latvia", + "start": "65301.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Liechtenstein", + "start": "75517.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Madagascar", + "start": "88946.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Malta", + "start": "102173.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Mayotte", + "start": "111369.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Mongolia", + "start": "120538.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Namibia", + "start": "147181.00", "size": 0.020920502, "ndv": 5 }, { - "start": "New Caledonia", + "start": "185180.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Niue", + "start": "236800.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Oman", + "start": "245857.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Papua New Guinea", + "start": "283561.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Poland", + "start": "323250.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Russian Federation", + "start": "342000.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Saint Lucia", + "start": "438317.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Sao Tome and Principe", + "start": "475442.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Singapore", + "start": "551500.00", "size": 0.020920502, "ndv": 5 }, { - "start": "South Africa", + "start": "622984.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Sudan", + "start": "756626.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Switzerland", + "start": "883749.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Thailand", + "start": "1098581.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Tunisia", + "start": "1246700.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Uganda", + "start": "1648195.00", "size": 0.020920502, "ndv": 5 }, { - "start": "United States Minor Outlying Islands", + "start": "2166090.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Vietnam", + "start": "2780400.00", "size": 0.020920502, "ndv": 5 }, { - "start": "Yemen", - "end": "Zimbabwe", + "start": "9572900.00", + "end": "17075400.00", "size": 0.016736402, "ndv": 4 } ] } -SurfaceArea 0.40 17075400.00 48 JSON_HB { +Population 0 1277558000 48 JSON_HB { "target_histogram_size": 50, "collected_at": "REPLACED", "collected_by": "REPLACED", "histogram_hb": [ { - "start": "0.40", - "size": 0.020920502, - "ndv": 5 + "start": "0", + "size": 0.029288703, + "ndv": 1 }, { - "start": "16.00", + "start": "50", "size": 0.020920502, - "ndv": 5 + "ndv": 4 }, { - "start": "49.00", + "start": "2000", "size": 0.020920502, - "ndv": 5 + "ndv": 4 }, { - "start": "96.00", + "start": "7000", "size": 0.020920502, - "ndv": 5 + "ndv": 4 }, { - "start": "181.00", + "start": "15000", "size": 0.020920502, "ndv": 5 }, { - "start": "242.00", + "start": "25000", "size": 0.020920502, "ndv": 5 }, { - "start": "314.00", + "start": "38000", "size": 0.020920502, "ndv": 5 }, { - "start": "373.00", + "start": "68000", "size": 0.020920502, "ndv": 4 }, { - "start": "455.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "618.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "726.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "1102.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "2510.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "4033.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "8875.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "11295.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "17364.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "21041.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "26338.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "28896.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "36125.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "45227.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "51197.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "65301.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "75517.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "88946.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "102173.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "111369.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "120538.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "147181.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "185180.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "236800.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "245857.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "283561.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "323250.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "342000.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "438317.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "475442.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "551500.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "622984.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "756626.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "883749.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "1098581.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "1246700.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "1648195.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "2166090.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "2780400.00", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "9572900.00", - "end": "17075400.00", - "size": 0.016736402, - "ndv": 4 - } - ] -} -Population 0 1277558000 48 JSON_HB { - "target_histogram_size": 50, - "collected_at": "REPLACED", - "collected_by": "REPLACED", - "histogram_hb": [ - { - "start": "0", - "size": 0.029288703, - "ndv": 1 - }, - { - "start": "50", - "size": 0.020920502, - "ndv": 4 - }, - { - "start": "2000", - "size": 0.020920502, - "ndv": 4 - }, - { - "start": "7000", - "size": 0.020920502, - "ndv": 4 - }, - { - "start": "15000", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "25000", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "38000", - "size": 0.020920502, - "ndv": 5 - }, - { - "start": "68000", - "size": 0.020920502, - "ndv": 4 - }, - { - "start": "78000", + "start": "78000", "size": 0.020920502, "ndv": 5 }, @@ -6203,264 +5903,6 @@ Capital 1 4074 47 JSON_HB { } ] } -ID 1 4079 50 JSON_HB { - "target_histogram_size": 50, - "collected_at": "REPLACED", - "collected_by": "REPLACED", - "histogram_hb": [ - { - "start": "1", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "83", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "165", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "247", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "329", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "411", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "493", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "575", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "657", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "739", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "821", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "903", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "985", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1067", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1149", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1231", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1313", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1395", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1477", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1559", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1641", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1723", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1805", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1887", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "1969", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2051", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2133", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2215", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2297", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2379", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2461", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2543", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2625", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2707", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2789", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2871", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "2953", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3035", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3117", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3199", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3281", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3363", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3445", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3527", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3609", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3691", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3773", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3855", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "3937", - "size": 0.020102966, - "ndv": 82 - }, - { - "start": "4019", - "end": "4079", - "size": 0.014954646, - "ndv": 61 - } - ] -} Name A Coruña (La Coruña) Ürgenc 50 JSON_HB { "target_histogram_size": 50, "collected_at": "REPLACED", @@ -7728,10 +7170,10 @@ Percentage 0.0 99.9 47 JSON_HB { } analyze select * from Country use index () where Code between 'BBC' and 'GGG'; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 24.58 25.52 Using where +1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 20.00 25.52 Using where analyze select * from Country use index () where Code < 'BBC'; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 8.37 7.11 Using where +1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 4.00 7.11 Using where set histogram_type=@save_histogram_type; set histogram_size=@save_histogram_size; DROP SCHEMA world; @@ -8294,6 +7736,8 @@ analyze table t1 persistent for all; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '13715197108439488792' select histogram from mysql.column_stats where table_name='t1' and db_name=database(); histogram diff --git a/mysql-test/main/subselect3.inc b/mysql-test/main/subselect3.inc index f5d72898779a1..25ca4eea34e72 100644 --- a/mysql-test/main/subselect3.inc +++ b/mysql-test/main/subselect3.inc @@ -646,14 +646,14 @@ DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); --disable_ps2_protocol -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; --enable_ps2_protocol delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; drop table t1; let $datadir=`select @@datadir`; ---remove_file $datadir/test/subselect.out.file.1 +--remove_file $MYSQLTEST_VARDIR/tmp/subselect.out.file.1 # # Bug #37894: Assertion in init_read_record_seq in handler.h line 1444 diff --git a/mysql-test/main/subselect3.result b/mysql-test/main/subselect3.result index 0504a9ab39cb5..9b78bb86c1bdd 100644 --- a/mysql-test/main/subselect3.result +++ b/mysql-test/main/subselect3.result @@ -805,9 +805,9 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; a b 1 0.123 diff --git a/mysql-test/main/subselect3_jcl6.result b/mysql-test/main/subselect3_jcl6.result index 81e3d135ad332..f1cb7271e025b 100644 --- a/mysql-test/main/subselect3_jcl6.result +++ b/mysql-test/main/subselect3_jcl6.result @@ -808,9 +808,9 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; a b 1 0.123 diff --git a/mysql-test/main/subselect_sj2.result b/mysql-test/main/subselect_sj2.result index 978f4b72a98ef..1ee106aa6e8dc 100644 --- a/mysql-test/main/subselect_sj2.result +++ b/mysql-test/main/subselect_sj2.result @@ -969,6 +969,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index PRIMARY,d d 9 NULL 17 Using where; Using index; LooseScan 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index; FirstMatch(t2) 1 PRIMARY t1 ref b b 4 test.t2.d 1 +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` explain SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 @@ -978,6 +980,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index_merge PRIMARY,d d,PRIMARY 4,4 NULL 2 Using sort_union(d,PRIMARY); Using where; Start temporary 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index 1 PRIMARY t1 ref b b 4 test.t2.d 1 End temporary +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 WHERE a = d AND ( pk < 2 OR d = 'z' ) and f > 0 diff --git a/mysql-test/main/subselect_sj2_jcl6.result b/mysql-test/main/subselect_sj2_jcl6.result index c4d121616e749..34cfe2d11452a 100644 --- a/mysql-test/main/subselect_sj2_jcl6.result +++ b/mysql-test/main/subselect_sj2_jcl6.result @@ -976,6 +976,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index PRIMARY,d d 9 NULL 17 Using where; Using index; LooseScan 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index; FirstMatch(t2) 1 PRIMARY t1 ref b b 4 test.t2.d 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` explain SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 @@ -985,6 +987,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index_merge PRIMARY,d d,PRIMARY 4,4 NULL 2 Using sort_union(d,PRIMARY); Using where; Start temporary 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index 1 PRIMARY t1 ref b b 4 test.t2.d 1 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 WHERE a = d AND ( pk < 2 OR d = 'z' ) and f > 0 diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result index c639b384522ee..d022820e1fd3e 100644 --- a/mysql-test/main/subselect_sj2_mat.result +++ b/mysql-test/main/subselect_sj2_mat.result @@ -971,6 +971,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index PRIMARY,d d 9 NULL 17 Using where; Using index; LooseScan 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index; FirstMatch(t2) 1 PRIMARY t1 ref b b 4 test.t2.d 1 +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` explain SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 @@ -980,6 +982,8 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index_merge PRIMARY,d d,PRIMARY 4,4 NULL 2 Using sort_union(d,PRIMARY); Using where; Start temporary 1 PRIMARY t1 ref a a 5 test.t2.d 1 Using where; Using index 1 PRIMARY t1 ref b b 4 test.t2.d 1 End temporary +Warnings: +Note 1105 Cannot use key `d` part[0] for lookup: `test`.`t2`.`d` of type `varchar` = "`t1`.`a`" of type `int` SELECT * FROM t1 WHERE b IN ( SELECT d FROM t2, t1 WHERE a = d AND ( pk < 2 OR d = 'z' ) and f > 0 diff --git a/mysql-test/main/system_mysql_db.result b/mysql-test/main/system_mysql_db.result index b89381da5c348..bd63549a4411f 100644 --- a/mysql-test/main/system_mysql_db.result +++ b/mysql-test/main/system_mysql_db.result @@ -204,15 +204,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show create table table_stats; Table Create Table diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index 2ed1e8ae618ca..d580edbc96106 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -242,15 +242,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show create table table_stats; Table Create Table diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index a257c16b8657e..644d2b8a23f2a 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -246,15 +246,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show create table table_stats; Table Create Table diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index fde130839d4d9..0a7cf2a953142 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -226,15 +226,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show create table table_stats; Table Create Table diff --git a/mysql-test/main/system_mysql_db_fix50568.result b/mysql-test/main/system_mysql_db_fix50568.result index 763fcb866d091..0598f0a5fc489 100644 --- a/mysql-test/main/system_mysql_db_fix50568.result +++ b/mysql-test/main/system_mysql_db_fix50568.result @@ -247,15 +247,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' show create table table_stats; Table Create Table diff --git a/mysql-test/main/table_elim.result b/mysql-test/main/table_elim.result index 580b1cf5a0d12..34c2781410640 100644 --- a/mysql-test/main/table_elim.result +++ b/mysql-test/main/table_elim.result @@ -250,11 +250,15 @@ explain select t1.* from t1 left join t2 on t2.a='foo' collate latin1_general_ci id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 10 NULL 2 Using index 1 SIMPLE t2 index PRIMARY PRIMARY 10 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of collation `latin1_general_cs` = "'foo' collate latin1_general_ci" of collation `latin1_general_ci` this must not use table elimination: explain select t1.* from t1 left join t2 on t2.a=t1.a collate latin1_general_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 10 NULL 2 Using index 1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of collation `latin1_general_cs` = "`t1`.`a` collate latin1_general_ci" of collation `latin1_general_ci` drop table t1,t2; create table t1 (a int primary key); insert into t1 values (1),(2); @@ -265,11 +269,15 @@ explain select t1.* from t1 left join t2 on t2.a=1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index 1 SIMPLE t2 index PRIMARY PRIMARY 10 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `char` = "1" of type `int` this must not use table elimination: explain select t1.* from t1 left join t2 on t2.a=t1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index 1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1) +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `char` = "`t1`.`a`" of type `int` drop table t1, t2; create table t1 (a char(10) primary key); insert into t1 values ('foo'),('bar'); diff --git a/mysql-test/main/tls_version.result b/mysql-test/main/tls_version.result index d1b20a121fed0..3d9565983e834 100644 --- a/mysql-test/main/tls_version.result +++ b/mysql-test/main/tls_version.result @@ -12,3 +12,5 @@ Variable_name Value Ssl_version TLSv1.2 @@tls_version TLSv1.1,TLSv1.2 +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +FOUND 1 /TLSv1.0 and TLSv1.1 are insecure/ in mysqld.1.err diff --git a/mysql-test/main/tls_version.test b/mysql-test/main/tls_version.test index 875fed19821ad..50448f898e9c6 100644 --- a/mysql-test/main/tls_version.test +++ b/mysql-test/main/tls_version.test @@ -22,3 +22,8 @@ # finally list available protocols --exec $MYSQL --host=localhost --ssl -e "select @@tls_version;" +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN= TLSv1.0 and TLSv1.1 are insecure +--source include/search_pattern_in_file.inc + diff --git a/mysql-test/main/tls_version1.result b/mysql-test/main/tls_version1.result index 8333bfec15933..caabed832cb5b 100644 --- a/mysql-test/main/tls_version1.result +++ b/mysql-test/main/tls_version1.result @@ -4,3 +4,5 @@ Variable_name Value Ssl_version TLSv1 @@tls_version TLSv1.0 +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +FOUND 1 /TLSv1.0 and TLSv1.1 are insecure/ in mysqld.1.err diff --git a/mysql-test/main/tls_version1.test b/mysql-test/main/tls_version1.test index d38de876ba347..788284c36df63 100644 --- a/mysql-test/main/tls_version1.test +++ b/mysql-test/main/tls_version1.test @@ -10,3 +10,8 @@ --exec $MYSQL --host=localhost --ssl --tls_version=TLSv1.0 -e "show status like 'ssl_version';" --exec $MYSQL --host=localhost --ssl -e "select @@tls_version;" +call mtr.add_suppression("TLSv1.0 and TLSv1.1 are insecure"); +--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN= TLSv1.0 and TLSv1.1 are insecure +--source include/search_pattern_in_file.inc + diff --git a/mysql-test/main/type_binary.result b/mysql-test/main/type_binary.result index ca0495e38994d..d1aa4ada5af94 100644 --- a/mysql-test/main/type_binary.result +++ b/mysql-test/main/type_binary.result @@ -220,3 +220,180 @@ def CAST(a AS BINARY(16777215)) 250 16777215 0 Y 128 0 63 def CAST(a AS BINARY(16777216)) 251 16777216 0 Y 128 0 63 CAST(a AS BINARY(0)) CAST(a AS BINARY(1)) CAST(a AS BINARY(16)) CAST(a AS BINARY(255)) CAST(a AS BINARY(256)) CAST(a AS BINARY(512)) CAST(a AS BINARY(513)) CAST(a AS BINARY(65532)) CAST(a AS BINARY(65533)) CAST(a AS BINARY(65534)) CAST(a AS BINARY(65535)) CAST(a AS BINARY(65536)) CAST(a AS BINARY(16777215)) CAST(a AS BINARY(16777216)) DROP TABLE t1; +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col VARBINARY(32), KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101" of type `int` +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030" of type `bigint` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030.1" of type `decimal` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030.1e0" of type `double` +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `int` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `int unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `bigint` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `bigint unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `decimal` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `float` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `double` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_binary.test b/mysql-test/main/type_binary.test index 04cdc94e6d885..bfc9222762a32 100644 --- a/mysql-test/main/type_binary.test +++ b/mysql-test/main/type_binary.test @@ -156,3 +156,22 @@ FROM t1; --disable_metadata --enable_view_protocol DROP TABLE t1; + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col VARBINARY(32), KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_bit.result b/mysql-test/main/type_bit.result index e051a52d56a19..d075e883ac2f8 100644 --- a/mysql-test/main/type_bit.result +++ b/mysql-test/main/type_bit.result @@ -1884,3 +1884,157 @@ DROP TABLE t1; # # End of 10.5 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIT(64), KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (CONCAT(20230100+i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_bit.test b/mysql-test/main/type_bit.test index 846fc34e2e989..8bab78adeaf8a 100644 --- a/mysql-test/main/type_bit.test +++ b/mysql-test/main/type_bit.test @@ -571,3 +571,22 @@ DROP TABLE t1; --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIT(64), KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (CONCAT(20230100+i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_bit_innodb.result b/mysql-test/main/type_bit_innodb.result index 67b4ff5567489..fc932c8749e91 100644 --- a/mysql-test/main/type_bit_innodb.result +++ b/mysql-test/main/type_bit_innodb.result @@ -424,3 +424,157 @@ hex(f1) hex(f2) 0 0 drop table t1; SET GLOBAL innodb_stats_persistent=@save_stats_persistent; +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIT(64), KEY(indexed_col)) ENGINE=InnoDB; +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (CONCAT(20230100+i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bit` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_bit_innodb.test b/mysql-test/main/type_bit_innodb.test index 5fc7c18824603..196f28f12ec6b 100644 --- a/mysql-test/main/type_bit_innodb.test +++ b/mysql-test/main/type_bit_innodb.test @@ -160,3 +160,21 @@ select hex(f1), hex(f2) from t1; drop table t1; SET GLOBAL innodb_stats_persistent=@save_stats_persistent; + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIT(64), KEY(indexed_col)) ENGINE=InnoDB; +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (CONCAT(20230100+i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_blob.result b/mysql-test/main/type_blob.result index b5e88e660287b..1e25dd16adecc 100644 --- a/mysql-test/main/type_blob.result +++ b/mysql-test/main/type_blob.result @@ -1159,3 +1159,263 @@ drop table t1; # # End of 10.4 test # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BLOB, KEY(indexed_col(64))); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101" of type `int` +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030" of type `bigint` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030.1" of type `decimal` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030.1e0" of type `double` +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +DROP TABLE t1; +SET note_verbosity=DEFAULT; +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TEXT, KEY(indexed_col(64))); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101" of type `int` +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030" of type `bigint` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030.1" of type `decimal` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "20230101102030.1e0" of type `double` +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `int` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `int unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `bigint` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `bigint unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `decimal` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `float` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `double` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `blob` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = ``t2``.``not_indexed_col``` +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_blob.test b/mysql-test/main/type_blob.test index 021ead2e87c1e..ad58946afeaa5 100644 --- a/mysql-test/main/type_blob.test +++ b/mysql-test/main/type_blob.test @@ -777,3 +777,34 @@ drop table t1; --echo # --echo # End of 10.4 test --echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BLOB, KEY(indexed_col(64))); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TEXT, KEY(indexed_col(64))); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_date.result b/mysql-test/main/type_date.result index feac3295fafa6..b5cd3bf3b61ae 100644 --- a/mysql-test/main/type_date.result +++ b/mysql-test/main/type_date.result @@ -1164,3 +1164,125 @@ set sql_mode=default; # # End of 10.4 tests # +# +# Start of 10.6 tests +# +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DATE, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +2023-01-01 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '10:20:30' +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '\x00' +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '0' +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 20230101 +2023-01-02 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 20230101 +2023-01-02 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 2023-01-01 +2023-01-02 2023-01-02 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '0' +Warning 1292 Incorrect datetime value: '1' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_date.test b/mysql-test/main/type_date.test index 81cad6b5af5f4..d4981183c10f7 100644 --- a/mysql-test/main/type_date.test +++ b/mysql-test/main/type_date.test @@ -806,3 +806,26 @@ set sql_mode=default; --echo # --echo # End of 10.4 tests --echo # + + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DATE, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_datetime.result b/mysql-test/main/type_datetime.result index 0c351bcb3cd51..a1e2c8fc222e2 100644 --- a/mysql-test/main/type_datetime.result +++ b/mysql-test/main/type_datetime.result @@ -1585,3 +1585,125 @@ DROP TABLE t1; # # End of 10.4 tests # +# +# Start of 10.6 tests +# +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DATETIME, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +2023-01-01 00:00:00 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '10:20:30' +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '\x00' +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Warning 1292 Truncated incorrect datetime value: '0' +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 20230101 +2023-01-02 00:00:00 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 20230101 +2023-01-02 00:00:00 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 +2023-01-02 00:00:00 2023-01-02 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '0' +Warning 1292 Incorrect datetime value: '1' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_datetime.test b/mysql-test/main/type_datetime.test index 4a14bee431903..3c46d10718f1b 100644 --- a/mysql-test/main/type_datetime.test +++ b/mysql-test/main/type_datetime.test @@ -1055,3 +1055,26 @@ DROP TABLE t1; --echo # --echo # End of 10.4 tests --echo # + + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DATETIME, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_enum.result b/mysql-test/main/type_enum.result index a935e3d63cb23..df9c07c6ebe49 100644 --- a/mysql-test/main/type_enum.result +++ b/mysql-test/main/type_enum.result @@ -1903,6 +1903,8 @@ EXPLAIN SELECT t1.* FROM t1,t2 WHERE t1.c1=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system PRIMARY NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `enum` = "`t1`.`c1`" of type `date` SELECT t1.* FROM t1 LEFT JOIN t2 USING (c1); c1 2001-01-01 @@ -1912,6 +1914,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 USING (c1); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `enum` = "`t1`.`c1`" of type `date` DROP TABLE t1, t2; # # MDEV-6978 Bad results with join comparing case insensitive VARCHAR/ENUM/SET expression to a _bin ENUM column @@ -1942,6 +1946,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 SET('a') CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1969,6 +1975,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1996,6 +2004,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; # # MDEV-6991 GROUP_MIN_MAX optimization is erroneously applied in some cases @@ -2354,6 +2364,208 @@ a FLOOR(a) CEILING(a) TRUNCATE(a,0) ROUND(a) DROP TABLE t2; DROP TABLE t1; # +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 ( +indexed_col ENUM('2001','2002','2003','2004','2005','2006','2007','2008','2009','2010'), +KEY(indexed_col) +); +FOR i IN 1..10 +DO +INSERT INTO t1 VALUES (i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "DATE'2001-01-01'" of type `date` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "`t2`.`not_indexed_col`" of type `date` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "`t2`.`not_indexed_col`" of type `datetime` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `enum` = "`t2`.`not_indexed_col`" of type `timestamp` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of collation `latin1_swedish_ci` = "`t2`.`not_indexed_col`" of collation `binary` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = ``t2``.``not_indexed_col``` +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +# # MDEV-29062 Wrong result set metadata for a mix of INT+ENUM # CREATE TABLE t1 diff --git a/mysql-test/main/type_enum.test b/mysql-test/main/type_enum.test index 30a10407f89d4..8cc5d1d603b69 100644 --- a/mysql-test/main/type_enum.test +++ b/mysql-test/main/type_enum.test @@ -556,6 +556,26 @@ SELECT * FROM t2; DROP TABLE t2; DROP TABLE t1; +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 ( + indexed_col ENUM('2001','2002','2003','2004','2005','2006','2007','2008','2009','2010'), + KEY(indexed_col) +); +DELIMITER $$; +FOR i IN 1..10 +DO + INSERT INTO t1 VALUES (i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; --echo # --echo # MDEV-29062 Wrong result set metadata for a mix of INT+ENUM diff --git a/mysql-test/main/type_float.result b/mysql-test/main/type_float.result index ddb80bf24e8de..9f01f22b3c770 100644 --- a/mysql-test/main/type_float.result +++ b/mysql-test/main/type_float.result @@ -538,6 +538,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 8 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `double` = "`t1`.`a`" of type `datetime` DROP TABLE t1,t2; # # MDEV-6971 Bad results with joins comparing TIME and DOUBLE/DECIMAL columns @@ -568,6 +570,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 USING(a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 8 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `double` = "`t1`.`a`" of type `time` DROP TABLE t1,t2; # # End of 10.0 tests @@ -1170,6 +1174,262 @@ fdec 123.456.789,12345678900000000000000000000000000000 # End of 10.4 tests # # +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col FLOAT, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "DATE'2001-01-01'" of type `date` +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "TIME'10:20:30'" of type `time` +Warning 1292 Incorrect time value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230100 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230100 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230100 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "`t2`.`not_indexed_col`" of type `date` +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "`t2`.`not_indexed_col`" of type `datetime` +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `float` = "`t2`.`not_indexed_col`" of type `timestamp` +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +Warning 1292 Incorrect datetime value: '20230132' for column `test`.`t1`.`indexed_col` at row 31 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-01' +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-01' +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DOUBLE, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `double` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-01' +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-01' +Warning 1292 Truncated incorrect DOUBLE value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +# # Start of 10.9 tests # # diff --git a/mysql-test/main/type_float.test b/mysql-test/main/type_float.test index 6a1636cf9b9fe..12e3f070fdeb3 100644 --- a/mysql-test/main/type_float.test +++ b/mysql-test/main/type_float.test @@ -720,6 +720,37 @@ DELIMITER ;$$ --echo # End of 10.4 tests --echo # +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col FLOAT, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DOUBLE, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; --echo # --echo # Start of 10.9 tests diff --git a/mysql-test/main/type_int.result b/mysql-test/main/type_int.result index c25b213c7c4be..9a54c9a528711 100644 --- a/mysql-test/main/type_int.result +++ b/mysql-test/main/type_int.result @@ -1688,3 +1688,256 @@ drop table t1; # # End of 10.5 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col INT, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIGINT, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '10:20:30' +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01' +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01 10:20:30' +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_int.test b/mysql-test/main/type_int.test index c339bfa1834b9..c47ab501116c3 100644 --- a/mysql-test/main/type_int.test +++ b/mysql-test/main/type_int.test @@ -567,3 +567,36 @@ drop table t1; --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col INT, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIGINT, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_newdecimal.result b/mysql-test/main/type_newdecimal.result index d42de5b7e0dcf..f63aafefb7c70 100644 --- a/mysql-test/main/type_newdecimal.result +++ b/mysql-test/main/type_newdecimal.result @@ -2134,6 +2134,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 14 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `decimal` = "`t1`.`a`" of type `datetime` DROP TABLE t1,t2; # # MDEV-6971 Bad results with joins comparing TIME and DOUBLE/DECIMAL columns @@ -2164,6 +2166,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 USING(a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 14 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `decimal` = "`t1`.`a`" of type `time` DROP TABLE t1,t2; # # End of 10.0 tests @@ -2802,3 +2806,131 @@ DROP TABLE t2,t1; # # End of 10.4 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DECIMAL(30,6), KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101.000000 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101.000000 20230101 +20230102.000000 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101.000000 20230101 +20230102.000000 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101.000000 2023-01-01 +20230102.000000 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101.000000 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101.000000 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `decimal` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01' +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01' +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_newdecimal.test b/mysql-test/main/type_newdecimal.test index af5dc43fbd303..af82b7d601c7c 100644 --- a/mysql-test/main/type_newdecimal.test +++ b/mysql-test/main/type_newdecimal.test @@ -2011,3 +2011,21 @@ DROP TABLE t2,t1; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col DECIMAL(30,6), KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_set.result b/mysql-test/main/type_set.result index 5821bbae9848e..bd8a0e95eaa6b 100644 --- a/mysql-test/main/type_set.result +++ b/mysql-test/main/type_set.result @@ -133,6 +133,8 @@ EXPLAIN SELECT t1.* FROM t1,t2 WHERE t1.c1=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system PRIMARY NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `set` = "`t1`.`c1`" of type `date` SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1=t2.c1; c1 2001-01-01 @@ -142,6 +144,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `set` = "`t1`.`c1`" of type `date` DROP TABLE t1, t2; # # MDEV-6978 Bad results with join comparing case insensitive VARCHAR/ENUM/SET expression to a _bin ENUM column @@ -172,6 +176,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 SET('a') CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -199,6 +205,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -226,6 +234,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of collation `latin1_bin` = "`t1`.`c1` collate latin1_swedish_ci" of collation `latin1_swedish_ci` DROP TABLE IF EXISTS t1,t2; # # MDEV-6993 Bad results with join comparing DECIMAL and ENUM/SET columns @@ -380,6 +390,208 @@ a FLOOR(a) CEILING(a) TRUNCATE(a,0) ROUND(a) DROP TABLE t2; DROP TABLE t1; # +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 ( +indexed_col SET('2001','2002','2003','2004','2005','2006','2007','2008','2009','2010'), +KEY(indexed_col) +); +FOR i IN 1..10 +DO +INSERT INTO t1 VALUES (CONCAT(2000+i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "DATE'2001-01-01'" of type `date` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "`t2`.`not_indexed_col`" of type `date` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "`t2`.`not_indexed_col`" of type `datetime` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `set` = "`t2`.`not_indexed_col`" of type `timestamp` +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +Warning 1292 Truncated incorrect datetime value: '2001' +Warning 1292 Truncated incorrect datetime value: '2002' +Warning 1292 Truncated incorrect datetime value: '2003' +Warning 1292 Truncated incorrect datetime value: '2004' +Warning 1292 Truncated incorrect datetime value: '2005' +Warning 1292 Truncated incorrect datetime value: '2006' +Warning 1292 Truncated incorrect datetime value: '2007' +Warning 1292 Truncated incorrect datetime value: '2008' +Warning 1292 Truncated incorrect datetime value: '2009' +Warning 1292 Truncated incorrect datetime value: '2010' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of collation `latin1_swedish_ci` = "`t2`.`not_indexed_col`" of collation `binary` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = ``t2``.``not_indexed_col``` +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +# # MDEV-29062 Wrong result set metadata for a mix of INT+ENUM # CREATE TABLE t1 diff --git a/mysql-test/main/type_set.test b/mysql-test/main/type_set.test index 0ef2d158c4d4d..95732681be465 100644 --- a/mysql-test/main/type_set.test +++ b/mysql-test/main/type_set.test @@ -262,6 +262,26 @@ SELECT * FROM t2; DROP TABLE t2; DROP TABLE t1; +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 ( + indexed_col SET('2001','2002','2003','2004','2005','2006','2007','2008','2009','2010'), + KEY(indexed_col) +); +DELIMITER $$; +FOR i IN 1..10 +DO + INSERT INTO t1 VALUES (CONCAT(2000+i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; --echo # --echo # MDEV-29062 Wrong result set metadata for a mix of INT+ENUM diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index 34bf165a3e43e..caf0b50714cb3 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -2492,3 +2492,115 @@ DROP TABLE t1; # # End of 10.4 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TIME, KEY(indexed_col)); +FOR i IN 1..15 +DO +INSERT INTO t1 VALUES (MAKETIME(0,0,i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +Warnings: +Warning 1292 Truncated incorrect time value: '\x00' +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +00:00:01 1 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +Warning 1292 Truncated incorrect time value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +Warning 1292 Truncated incorrect time value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index a75b278b1deca..6d33c96a637d4 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -1623,3 +1623,21 @@ DROP TABLE t1; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TIME, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..15 +DO + INSERT INTO t1 VALUES (MAKETIME(0,0,i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index 064dee6715dc1..73c6c6ba0a83e 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1372,3 +1372,122 @@ drop table t1; # # End of 10.10 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TIMESTAMP, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +2023-01-01 00:00:00 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '10:20:30' +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '\x00' +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '0' +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 20230101 +2023-01-02 00:00:00 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 20230101 +2023-01-02 00:00:00 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 +2023-01-02 00:00:00 2023-01-02 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +2023-01-01 00:00:00 2023-01-01 00:00:00 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Incorrect datetime value: '0' +Warning 1292 Incorrect datetime value: '1' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index f869fa064d682..76589f1f6bcc7 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -923,3 +923,21 @@ drop table t1; --echo # --echo # End of 10.10 tests --echo # + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col TIMESTAMP, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_uint.result b/mysql-test/main/type_uint.result index 7a90d6f0689cd..b4118edcd057c 100644 --- a/mysql-test/main/type_uint.result +++ b/mysql-test/main/type_uint.result @@ -66,7 +66,262 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`a` of type `int unsigned` = "`t1`.`a`" of type `date` DROP TABLE t1,t2; # # End of 10.0 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col INT UNSIGNED, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "TIME'10:20:30'" of type `time` +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `int unsigned` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIGINT UNSIGNED, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '10:20:30' +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01' +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '2001-01-01 10:20:30' +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint unsigned` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint unsigned` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `bigint unsigned` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '2001-01-01' +Warning 1292 Truncated incorrect INTEGER value: '2001-01-02' +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_uint.test b/mysql-test/main/type_uint.test index ae48b30997ab3..72f32de848b96 100644 --- a/mysql-test/main/type_uint.test +++ b/mysql-test/main/type_uint.test @@ -48,3 +48,36 @@ DROP TABLE t1,t2; --echo # --echo # End of 10.0 tests --echo # + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col INT UNSIGNED, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col BIGINT UNSIGNED, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (MAKEDATE(2023, i)); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index ea31dddabda68..bb752719caf84 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -612,6 +612,8 @@ EXPLAIN SELECT t1.* FROM t1,t2 WHERE t1.c1=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system PRIMARY NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 22 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `varchar` = "`t1`.`c1`" of type `date` SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1=t2.c1; c1 2001-01-01 @@ -621,6 +623,8 @@ EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t2 index PRIMARY PRIMARY 22 NULL 2 Using where; Using index +Warnings: +Note 1105 Cannot use key `PRIMARY` part[0] for lookup: `test`.`t2`.`c1` of type `varchar` = "`t1`.`c1`" of type `date` DROP TABLE IF EXISTS t1,t2; # # MDEV-6989 BINARY and COLLATE xxx_bin comparisions are not used for optimization in some cases @@ -767,3 +771,182 @@ DROP TABLE vchar; # # End of 10.5 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col VARCHAR(32), KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +20230101 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101" of type `int` +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030" of type `bigint` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030.1" of type `decimal` +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "20230101102030.1e0" of type `double` +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "DATE'2001-01-01'" of type `date` +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "TIME'10:20:30'" of type `time` +Warning 1292 Truncated incorrect time value: '20230101' +Warning 1292 Truncated incorrect time value: '20230102' +Warning 1292 Truncated incorrect time value: '20230103' +Warning 1292 Truncated incorrect time value: '20230104' +Warning 1292 Truncated incorrect time value: '20230105' +Warning 1292 Truncated incorrect time value: '20230106' +Warning 1292 Truncated incorrect time value: '20230107' +Warning 1292 Truncated incorrect time value: '20230108' +Warning 1292 Truncated incorrect time value: '20230109' +Warning 1292 Truncated incorrect time value: '20230110' +Warning 1292 Truncated incorrect time value: '20230111' +Warning 1292 Truncated incorrect time value: '20230112' +Warning 1292 Truncated incorrect time value: '20230113' +Warning 1292 Truncated incorrect time value: '20230114' +Warning 1292 Truncated incorrect time value: '20230115' +Warning 1292 Truncated incorrect time value: '20230116' +Warning 1292 Truncated incorrect time value: '20230117' +Warning 1292 Truncated incorrect time value: '20230118' +Warning 1292 Truncated incorrect time value: '20230119' +Warning 1292 Truncated incorrect time value: '20230120' +Warning 1292 Truncated incorrect time value: '20230121' +Warning 1292 Truncated incorrect time value: '20230122' +Warning 1292 Truncated incorrect time value: '20230123' +Warning 1292 Truncated incorrect time value: '20230124' +Warning 1292 Truncated incorrect time value: '20230125' +Warning 1292 Truncated incorrect time value: '20230126' +Warning 1292 Truncated incorrect time value: '20230127' +Warning 1292 Truncated incorrect time value: '20230128' +Warning 1292 Truncated incorrect time value: '20230129' +Warning 1292 Truncated incorrect time value: '20230130' +Warning 1292 Truncated incorrect time value: '20230131' +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "TIMESTAMP'2001-01-01 10:20:30'" of type `datetime` +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = _utf8mb3'0' collate utf8mb3_bin` +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `int` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 20230101 +20230102 20230102 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `int unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `bigint` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `bigint unsigned` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `decimal` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `float` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `double` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 +20230102 2023-01-02 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +20230101 2023-01-01 00:00:00 +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `varchar` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten condition: `convert(``t1``.``indexed_col`` using utf8mb3) = ``t2``.``not_indexed_col``` +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_varchar.test b/mysql-test/main/type_varchar.test index f63523e226beb..46b37554575af 100644 --- a/mysql-test/main/type_varchar.test +++ b/mysql-test/main/type_varchar.test @@ -396,3 +396,22 @@ DROP TABLE vchar; --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col VARCHAR(32), KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (20230100+i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_year.result b/mysql-test/main/type_year.result index aaee5049c634d..6e3a7731b3859 100644 --- a/mysql-test/main/type_year.result +++ b/mysql-test/main/type_year.result @@ -703,3 +703,110 @@ DROP TABLE t1; # # End of 10.5 tests # +# +# MDEV-32203 Raise notes when an index cannot be used on data type mismatch +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col YEAR, KEY(indexed_col)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (2023 + i); +END FOR; +$$ +SELECT * FROM t1 WHERE indexed_col=20230101; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +indexed_col +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +indexed_col +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +indexed_col +SELECT * FROM t1 WHERE indexed_col=0x00; +indexed_col +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +indexed_col +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `year` = "`t2`.`not_indexed_col`" of type `date` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `year` = "`t2`.`not_indexed_col`" of type `datetime` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +Warnings: +Note 1105 Cannot use key `indexed_col` part[0] for lookup: `test`.`t1`.`indexed_col` of type `year` = "`t2`.`not_indexed_col`" of type `timestamp` +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +indexed_col not_indexed_col +DROP TABLE t2; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_year.test b/mysql-test/main/type_year.test index 52783a21b74bb..2edb67a89eb61 100644 --- a/mysql-test/main/type_year.test +++ b/mysql-test/main/type_year.test @@ -386,3 +386,22 @@ DROP TABLE t1; --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # MDEV-32203 Raise notes when an index cannot be used on data type mismatch +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (indexed_col YEAR, KEY(indexed_col)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (2023 + i); +END FOR; +$$ +DELIMITER ;$$ +--source unusable_keys_literals.inc +--source unusable_keys_joins.inc +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/unusable_keys_joins.inc b/mysql-test/main/unusable_keys_joins.inc new file mode 100644 index 0000000000000..14d235fab30b6 --- /dev/null +++ b/mysql-test/main/unusable_keys_joins.inc @@ -0,0 +1,66 @@ +--enable_prepare_warnings +CREATE TABLE t2 (not_indexed_col INT); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col INT UNSIGNED); +INSERT INTO t2 VALUES (20230101),(20230102); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col BIGINT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col BIGINT UNSIGNED); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col DECIMAL(30,6)); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col FLOAT); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col DOUBLE); +INSERT INTO t2 VALUES (20230101102030),(20230101102031); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col DATE); +INSERT INTO t2 VALUES ('2023-01-01'),('2023-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col DATETIME); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col TIMESTAMP); +INSERT INTO t2 VALUES ('2023-01-01 00:00:00'),('2023-01-01 00:00:01'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col VARBINARY(32)); +INSERT INTO t2 VALUES (0x30),(0x31); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col VARCHAR(32)); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; + +CREATE TABLE t2 (not_indexed_col VARCHAR(32) CHARACTER SET utf8mb3); +INSERT INTO t2 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1, t2 WHERE indexed_col=not_indexed_col; +DROP TABLE t2; +--disable_prepare_warnings diff --git a/mysql-test/main/unusable_keys_literals.inc b/mysql-test/main/unusable_keys_literals.inc new file mode 100644 index 0000000000000..e19baa16f3c1c --- /dev/null +++ b/mysql-test/main/unusable_keys_literals.inc @@ -0,0 +1,14 @@ +--enable_prepare_warnings +SELECT * FROM t1 WHERE indexed_col=20230101; +SELECT * FROM t1 WHERE indexed_col=20230101102030; +SELECT * FROM t1 WHERE indexed_col=20230101102030.1; +SELECT * FROM t1 WHERE indexed_col=20230101102030.1e0; +SELECT * FROM t1 WHERE indexed_col='10:20:30'; +SELECT * FROM t1 WHERE indexed_col='2001-01-01'; +SELECT * FROM t1 WHERE indexed_col='2001-01-01 10:20:30'; +SELECT * FROM t1 WHERE indexed_col=DATE'2001-01-01'; +SELECT * FROM t1 WHERE indexed_col=TIME'10:20:30'; +SELECT * FROM t1 WHERE indexed_col=TIMESTAMP'2001-01-01 10:20:30'; +SELECT * FROM t1 WHERE indexed_col=0x00; +SELECT * FROM t1 WHERE indexed_col=_utf8mb3'0' COLLATE utf8mb3_bin; +--disable_prepare_warnings diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 1858f41d9dd8b..b009d3205b0ac 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -7019,5 +7019,17 @@ ERROR HY000: View 'test.v' references invalid table(s) or column(s) or function( DROP VIEW v; DROP FUNCTION f; # +# MDEV-32164 Server crashes in JOIN::cleanup after erroneous query with +# view +# +CREATE TABLE t1 (a INT, b INT, KEY (a,b)) ENGINE=InnoDB; +CREATE VIEW v1 AS SELECT a FROM t1 WHERE a != '' GROUP BY a; +INSERT INTO t1 VALUES (1,NULL),(2,0),(3,NULL); +CREATE TABLE t2 (c INT) ENGINE=InnoDB; +CREATE TEMPORARY TABLE tmp SELECT v1.a FROM v1 JOIN t2 ON (v1.a = t2.c); +ERROR 22007: Truncated incorrect DECIMAL value: '' +DROP VIEW v1; +DROP TABLE t1, t2; +# # End of 10.6 tests # diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index 34c9e4685f94b..84794c4a18409 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -2,6 +2,7 @@ # Save the initial number of concurrent sessions. --source include/count_sessions.inc --source include/default_optimizer_switch.inc +--source include/have_innodb.inc SET optimizer_switch='outer_join_with_cache=off'; @@ -6782,6 +6783,21 @@ SELECT * FROM v; DROP VIEW v; DROP FUNCTION f; +--echo # +--echo # MDEV-32164 Server crashes in JOIN::cleanup after erroneous query with +--echo # view +--echo # + +CREATE TABLE t1 (a INT, b INT, KEY (a,b)) ENGINE=InnoDB; +CREATE VIEW v1 AS SELECT a FROM t1 WHERE a != '' GROUP BY a; +INSERT INTO t1 VALUES (1,NULL),(2,0),(3,NULL); +CREATE TABLE t2 (c INT) ENGINE=InnoDB; +--error ER_TRUNCATED_WRONG_VALUE +CREATE TEMPORARY TABLE tmp SELECT v1.a FROM v1 JOIN t2 ON (v1.a = t2.c); +# Cleanup +DROP VIEW v1; +DROP TABLE t1, t2; + --echo # --echo # End of 10.6 tests --echo # diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 84adc3e5cb403..431ee8d518bfd 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -351,7 +351,7 @@ END main(); sub main { - $ENV{MTR_PERL}=$^X; + $ENV{MTR_PERL}= mixed_path($^X); # Default, verbosity on report_option('verbose', 0); @@ -499,7 +499,7 @@ sub main { mark_time_used('init'); my ($prefix, $fail, $completed, $extra_warnings)= - run_test_server($server, $tests, \%children); + Manager::run($server, $tests, \%children); exit(0) if $opt_start_exit; @@ -585,23 +585,205 @@ sub main { } -sub run_test_server ($$$) { - my ($server, $tests, $children) = @_; +package Manager; +use POSIX ":sys_wait_h"; +use File::Basename; +use File::Find; +use IO::Socket::INET; +use IO::Select; +use mtr_report; +use My::Platform; + +my $num_saved_datadir; # Number of datadirs saved in vardir/log/ so far. +my $num_failed_test; # Number of tests failed so far +my $test_failure; # Set true if test suite failed +my $extra_warnings; # Warnings found during server shutdowns + +my $completed; +my %running; +my $result; +my $exe_mysqld; # Used as hint to CoreDump +my %names; + +sub parse_protocol($$) { + my $sock= shift; + my $line= shift; + + if ($line eq 'TESTRESULT'){ + mtr_verbose2("Got TESTRESULT from ". $names{$sock}); + $result= My::Test::read_test($sock); + + # Report test status + mtr_report_test($result); + + if ( $result->is_failed() ) { + + # Save the workers "savedir" in var/log + my $worker_savedir= $result->{savedir}; + my $worker_savename= basename($worker_savedir); + my $savedir= "$opt_vardir/log/$worker_savename"; + + # Move any core files from e.g. mysqltest + foreach my $coref (glob("core*"), glob("*.dmp")) + { + mtr_report(" - found '$coref', moving it to '$worker_savedir'"); + ::move($coref, $worker_savedir); + } + + find( + { + no_chdir => 1, + wanted => sub + { + My::CoreDump::core_wanted(\$num_saved_cores, + $opt_max_save_core, + @opt_cases == 0, + $exe_mysqld, $opt_parallel); + } + }, + $worker_savedir); + + if ($num_saved_datadir >= $opt_max_save_datadir) + { + mtr_report(" - skipping '$worker_savedir/'"); + main::rmtree($worker_savedir); + } + else + { + mtr_report(" - saving '$worker_savedir/' to '$savedir/'"); + rename($worker_savedir, $savedir); + $num_saved_datadir++; + } + main::resfile_print_test(); + $num_failed_test++ unless ($result->{retries} || + $result->{exp_fail}); + + $test_failure= 1; + if ( !$opt_force ) { + # Test has failed, force is off + push(@$completed, $result); + if ($result->{'dont_kill_server'}) + { + mtr_verbose2("${line}: saying BYE to ". $names{$sock}); + print $sock "BYE\n"; + return 2; + } + return ["Failure", 1, $completed, $extra_warnings]; + } + elsif ($opt_max_test_fail > 0 and + $num_failed_test >= $opt_max_test_fail) { + push(@$completed, $result); + mtr_report("Too many tests($num_failed_test) failed!", + "Terminating..."); + return ["Too many failed", 1, $completed, $extra_warnings]; + } + } - my $num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far. - my $num_failed_test= 0; # Number of tests failed so far - my $test_failure= 0; # Set true if test suite failed - my $extra_warnings= []; # Warnings found during server shutdowns + main::resfile_print_test(); + # Retry test run after test failure + my $retries= $result->{retries} || 2; + my $test_has_failed= $result->{failures} || 0; + if ($test_has_failed and $retries <= $opt_retry){ + # Test should be run one more time unless it has failed + # too many times already + my $tname= $result->{name}; + my $failures= $result->{failures}; + if ($opt_retry > 1 and $failures >= $opt_retry_failure){ + mtr_report("\nTest $tname has failed $failures times,", + "no more retries!\n"); + } + else { + mtr_report("\nRetrying test $tname, ". + "attempt($retries/$opt_retry)...\n"); + #saving the log file as filename.failed in case of retry + if ( $result->is_failed() ) { + my $worker_logdir= $result->{savedir}; + my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log"; + + if (-e $log_file_name) { + $result->{'logfile-failed'} = ::mtr_lastlinesfromfile($log_file_name, 20); + } else { + $result->{'logfile-failed'} = ""; + } - my $completed= []; - my %running; - my $result; - my $exe_mysqld= find_mysqld($bindir) || ""; # Used as hint to CoreDump + rename $log_file_name, $log_file_name.".failed"; + } + { + local @$result{'retries', 'result'}; + delete $result->{result}; + $result->{retries}= $retries+1; + $result->write_test($sock, 'TESTCASE'); + } + push(@$completed, $result); + return 2; + } + } - my $suite_timeout= start_timer(suite_timeout()); + # Repeat test $opt_repeat number of times + my $repeat= $result->{repeat} || 1; + if ($repeat < $opt_repeat) + { + $result->{retries}= 0; + $result->{rep_failures}++ if $result->{failures}; + $result->{failures}= 0; + delete($result->{result}); + $result->{repeat}= $repeat+1; + $result->write_test($sock, 'TESTCASE'); + return 2; + } + + # Remove from list of running + mtr_error("'", $result->{name},"' is not known to be running") + unless delete $running{$result->key()}; + + # Save result in completed list + push(@$completed, $result); + + } # if ($line eq 'TESTRESULT') + elsif ($line=~ /^START (.*)$/){ + # Send first test + $names{$sock}= $1; + } + elsif ($line eq 'WARNINGS'){ + my $fake_test= My::Test::read_test($sock); + my $test_list= join (" ", @{$fake_test->{testnames}}); + push @$extra_warnings, $test_list; + my $report= $fake_test->{'warnings'}; + mtr_report("***Warnings generated in error logs during shutdown ". + "after running tests: $test_list\n\n$report"); + $test_failure= 1; + if ( !$opt_force ) { + # Test failure due to warnings, force is off + mtr_verbose2("Socket loop exiting 3"); + return ["Warnings in log", 1, $completed, $extra_warnings]; + } + return 1; + } + elsif ($line =~ /^SPENT/) { + main::add_total_times($line); + } + elsif ($line eq 'VALGREP' && $opt_valgrind) { + $valgrind_reports= 1; + } + else { + mtr_error("Unknown response: '$line' from client"); + } + return 0; +} + +sub run ($$$) { + my ($server, $tests, $children) = @_; + my $suite_timeout= main::start_timer(main::suite_timeout()); + $exe_mysqld= main::find_mysqld($bindir) || ""; # Used as hint to CoreDump + $num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far. + $num_failed_test= 0; # Number of tests failed so far + $test_failure= 0; # Set true if test suite failed + $extra_warnings= []; # Warnings found during server shutdowns + $completed= []; my $s= IO::Select->new(); my $childs= 0; + $s->add($server); while (1) { if ($opt_stop_file) @@ -609,190 +791,60 @@ ($$$) if (mtr_wait_lock_file($opt_stop_file, $opt_stop_keep_alive)) { # We were waiting so restart timer process - my $suite_timeout= start_timer(suite_timeout()); + my $suite_timeout= main::start_timer(main::suite_timeout()); } } - mark_time_used('admin'); + main::mark_time_used('admin'); my @ready = $s->can_read(1); # Wake up once every second - mtr_debug("Got ". (0 + @ready). " connection(s)"); - mark_time_idle(); - foreach my $sock (@ready) { + if (@ready > 0) { + mtr_verbose2("Got ". (0 + @ready). " connection(s)"); + } + main::mark_time_idle(); + my $i= 0; + sock_loop: foreach my $sock (@ready) { + ++$i; if ($sock == $server) { # New client connected ++$childs; my $child= $sock->accept(); - mtr_verbose2("Client connected (got ${childs} childs)"); + mtr_verbose2("Connection ${i}: Worker connected (got ${childs} childs)"); $s->add($child); print $child "HELLO\n"; } else { - my $line= <$sock>; - if (!defined $line) { - # Client disconnected - --$childs; - mtr_verbose2("Child closed socket (left ${childs} childs)"); - $s->remove($sock); - $sock->close; - next; - } - chomp($line); - - if ($line eq 'TESTRESULT'){ - $result= My::Test::read_test($sock); - - # Report test status - mtr_report_test($result); - - if ( $result->is_failed() ) { - - # Save the workers "savedir" in var/log - my $worker_savedir= $result->{savedir}; - my $worker_savename= basename($worker_savedir); - my $savedir= "$opt_vardir/log/$worker_savename"; - - # Move any core files from e.g. mysqltest - foreach my $coref (glob("core*"), glob("*.dmp")) - { - mtr_report(" - found '$coref', moving it to '$worker_savedir'"); - move($coref, $worker_savedir); - } - - find( - { - no_chdir => 1, - wanted => sub - { - My::CoreDump::core_wanted(\$num_saved_cores, - $opt_max_save_core, - @opt_cases == 0, - $exe_mysqld, $opt_parallel); - } - }, - $worker_savedir); - - if ($num_saved_datadir >= $opt_max_save_datadir) - { - mtr_report(" - skipping '$worker_savedir/'"); - rmtree($worker_savedir); - } - else - { - mtr_report(" - saving '$worker_savedir/' to '$savedir/'"); - rename($worker_savedir, $savedir); - $num_saved_datadir++; - } - resfile_print_test(); - $num_failed_test++ unless ($result->{retries} || - $result->{exp_fail}); - - $test_failure= 1; - if ( !$opt_force ) { - # Test has failed, force is off - push(@$completed, $result); - if ($result->{'dont_kill_server'}) - { - print $sock "BYE\n"; - next; - } - return ("Failure", 1, $completed, $extra_warnings); - } - elsif ($opt_max_test_fail > 0 and - $num_failed_test >= $opt_max_test_fail) { - push(@$completed, $result); - mtr_report("Too many tests($num_failed_test) failed!", - "Terminating..."); - return ("Too many failed", 1, $completed, $extra_warnings); - } - } - - resfile_print_test(); - # Retry test run after test failure - my $retries= $result->{retries} || 2; - my $test_has_failed= $result->{failures} || 0; - if ($test_has_failed and $retries <= $opt_retry){ - # Test should be run one more time unless it has failed - # too many times already - my $tname= $result->{name}; - my $failures= $result->{failures}; - if ($opt_retry > 1 and $failures >= $opt_retry_failure){ - mtr_report("\nTest $tname has failed $failures times,", - "no more retries!\n"); - } - else { - mtr_report("\nRetrying test $tname, ". - "attempt($retries/$opt_retry)...\n"); - #saving the log file as filename.failed in case of retry - if ( $result->is_failed() ) { - my $worker_logdir= $result->{savedir}; - my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log"; - - if (-e $log_file_name) { - $result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20); - } else { - $result->{'logfile-failed'} = ""; - } - - rename $log_file_name, $log_file_name.".failed"; - } - { - local @$result{'retries', 'result'}; - delete $result->{result}; - $result->{retries}= $retries+1; - $result->write_test($sock, 'TESTCASE'); - } - push(@$completed, $result); - next; - } - } - - # Repeat test $opt_repeat number of times - my $repeat= $result->{repeat} || 1; - if ($repeat < $opt_repeat) - { - $result->{retries}= 0; - $result->{rep_failures}++ if $result->{failures}; - $result->{failures}= 0; - delete($result->{result}); - $result->{repeat}= $repeat+1; - $result->write_test($sock, 'TESTCASE'); - next; - } - - # Remove from list of running - mtr_error("'", $result->{name},"' is not known to be running") - unless delete $running{$result->key()}; - - # Save result in completed list - push(@$completed, $result); - - } - elsif ($line eq 'START'){ - ; # Send first test - } - elsif ($line eq 'WARNINGS'){ - my $fake_test= My::Test::read_test($sock); - my $test_list= join (" ", @{$fake_test->{testnames}}); - push @$extra_warnings, $test_list; - my $report= $fake_test->{'warnings'}; - mtr_report("***Warnings generated in error logs during shutdown ". - "after running tests: $test_list\n\n$report"); - $test_failure= 1; - if ( !$opt_force ) { - # Test failure due to warnings, force is off - return ("Warnings in log", 1, $completed, $extra_warnings); + my $j= 0; + $sock->blocking(0); + while (my $line= <$sock>) { + ++$j; + chomp($line); + mtr_verbose2("Connection ${i}.${j}". (exists $names{$sock} ? " from $names{$sock}" : "") .": $line"); + + $sock->blocking(1); + my $res= parse_protocol($sock, $line); + $sock->blocking(0); + if (ref $res eq 'ARRAY') { + return @$res; + } elsif ($res == 1) { + next; + } elsif ($res == 2) { + next sock_loop; } + if (IS_WINDOWS and !IS_CYGWIN) { + # Strawberry and ActiveState don't support blocking(0), the next iteration will be blocked! + # If there is next response now in the buffer and it is TESTRESULT we are affected by MDEV-30836 and the manager will hang. + last; + } + } + $sock->blocking(1); + if ($j == 0) { + # Client disconnected + --$childs; + mtr_verbose2((exists $names{$sock} ? $names{$sock} : "Worker"). " closed socket (left ${childs} childs)"); + $s->remove($sock); + $sock->close; next; } - elsif ($line =~ /^SPENT/) { - add_total_times($line); - } - elsif ($line eq 'VALGREP' && $opt_valgrind) { - $valgrind_reports= 1; - } - else { - mtr_error("Unknown response: '$line' from client"); - } # Find next test to schedule # - Try to use same configuration as worker used last time @@ -805,7 +857,7 @@ ($$$) last unless defined $t; - if (run_testcase_check_skip_test($t)){ + if (main::run_testcase_check_skip_test($t)){ # Move the test to completed list #mtr_report("skip - Moving test $i to completed"); push(@$completed, splice(@$tests, $i, 1)); @@ -851,7 +903,7 @@ ($$$) # At this point we have found next suitable test $next= splice(@$tests, $i, 1); last; - } + } # for(my $i= 0; $i <= @$tests; $i++) # Use second best choice if no other test has been found if (!$next and defined $second_best){ @@ -870,11 +922,11 @@ ($$$) } else { # No more test, tell child to exit - #mtr_report("Saying BYE to child"); + mtr_verbose2("Saying BYE to ". $names{$sock}); print $sock "BYE\n"; - } - } - } + } # else (!$next) + } # else ($sock != $server) + } # foreach my $sock (@ready) if (!IS_WINDOWS) { foreach my $pid (keys %$children) @@ -906,7 +958,7 @@ ($$$) # ---------------------------------------------------- # Check if test suite timer expired # ---------------------------------------------------- - if ( has_expired($suite_timeout) ) + if ( main::has_expired($suite_timeout) ) { mtr_report("Test suite timeout! Terminating..."); return ("Timeout", 1, $completed, $extra_warnings); @@ -914,6 +966,9 @@ ($$$) } } +1; + +package main; sub run_worker ($) { my ($server_port, $thread_num)= @_; @@ -934,7 +989,10 @@ ($) # -------------------------------------------------------------------------- # Set worker name # -------------------------------------------------------------------------- - report_option('name',"worker[$thread_num]"); + report_option('name',"worker[". sprintf("%02d", $thread_num). "]"); + my $proc_title= basename($0). " ${mtr_report::name} :". $server->sockport(). " -> :${server_port}"; + $0= $proc_title; + mtr_verbose2("Running at PID $$"); # -------------------------------------------------------------------------- # Set different ports per thread @@ -960,7 +1018,7 @@ ($) } # Ask server for first test - print $server "START\n"; + print $server "START ${mtr_report::name}\n"; mark_time_used('init'); @@ -968,6 +1026,7 @@ ($) chomp($line); if ($line eq 'TESTCASE'){ my $test= My::Test::read_test($server); + $0= $proc_title. " ". $test->{name}; # Clear comment and logfile, to avoid # reusing them from previous test @@ -984,11 +1043,12 @@ ($) run_testcase($test, $server); #$test->{result}= 'MTR_RES_PASSED'; # Send it back, now with results set + mtr_verbose2('Writing TESTRESULT'); $test->write_test($server, 'TESTRESULT'); mark_time_used('restart'); } elsif ($line eq 'BYE'){ - mtr_report("Server said BYE"); + mtr_verbose2("Manager said BYE"); # We need to gracefully shut down the servers to see any # Valgrind memory leak errors etc. since last server restart. if ($opt_warnings) { @@ -1217,7 +1277,8 @@ sub command_line_setup { 'xml-report=s' => \$opt_xml_report, My::Debugger::options(), - My::CoreDump::options() + My::CoreDump::options(), + My::Platform::options() ); # fix options (that take an optional argument and *only* after = sign @@ -1253,6 +1314,9 @@ sub command_line_setup { } if (IS_CYGWIN) { + if (My::Platform::check_cygwin_subshell()) { + die("Cygwin /bin/sh subshell requires fix with --cygwin-subshell-fix=do\n"); + } # Use mixed path format i.e c:/path/to/ $glob_mysql_test_dir= mixed_path($glob_mysql_test_dir); } @@ -1748,11 +1812,12 @@ sub collect_mysqld_features { # to simplify the parsing, we'll merge all nicely formatted --help texts $list =~ s/\n {22}(\S)/ $1/g; - my @list= split '\n', $list; + my @list= split '\R', $list; $mysql_version_id= 0; + my $exe= basename($exe_mysqld); while (defined(my $line = shift @list)){ - if ($line =~ /^\Q$exe_mysqld\E\s+Ver\s(\d+)\.(\d+)\.(\d+)(\S*)/ ) { + if ($line =~ /\W\Q$exe\E\s+Ver\s(\d+)\.(\d+)\.(\d+)(\S*)/ ) { $mysql_version_id= $1*10000 + $2*100 + $3; mtr_report("MariaDB Version $1.$2.$3$4"); last; @@ -1784,7 +1849,7 @@ sub collect_mysqld_features { next; } - last if /^$/; # then goes a list of variables, it ends with an empty line + last if /^\r?$/; # then goes a list of variables, it ends with an empty line # Put a variable into hash /^([\S]+)[ \t]+(.*?)\r?$/ or die "Could not parse mysqld --help: $_\n"; @@ -1815,7 +1880,7 @@ () my $list = `$cmd` or mtr_error("Could not connect to extern server using command: '$cmd'"); - foreach my $line (split('\n', $list )) + foreach my $line (split('\R', $list )) { # Put variables into hash if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ ) @@ -1906,7 +1971,7 @@ ($$) if ( $opt_debug ) { mtr_add_arg($args, - "--loose-debug=$debug_d:t:A,%s/log/%s.trace", + "--loose-debug=d,info,warning,warnings:t:A,%s/log/%s.trace", $path_vardir_trace, $client_name) } } @@ -2959,7 +3024,7 @@ sub initialize_servers { # sub sql_to_bootstrap { my ($sql) = @_; - my @lines= split(/\n/, $sql); + my @lines= split(/\R/, $sql); my $result= "\n"; my $delimiter= ';'; @@ -4118,9 +4183,8 @@ ($$) } return ($res == 62) ? 0 : $res; - } - - if ($proc) + } # if ($proc and $proc eq $test) + elsif ($proc) { # It was not mysqltest that exited, add to a wait-to-be-started-again list. $keep_waiting_proc{$proc} = 1; @@ -4149,7 +4213,7 @@ ($$) { # do nothing } - } + } # foreach my $wait_for_proc next; @@ -5547,7 +5611,11 @@ ($) mtr_init_args(\$args); mtr_add_arg($args, "--defaults-file=%s", $path_config_file); - mtr_add_arg($args, "--silent"); + if ($opt_verbose > 1) { + mtr_add_arg($args, "--verbose"); + } else { + mtr_add_arg($args, "--silent"); + } mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--logdir=%s/log", $opt_vardir); diff --git a/mysql-test/suite/archive/archive.test b/mysql-test/suite/archive/archive.test index df5f650332138..c968ed1e13826 100644 --- a/mysql-test/suite/archive/archive.test +++ b/mysql-test/suite/archive/archive.test @@ -1609,6 +1609,8 @@ CREATE TABLE t1(a INT, b BLOB) ENGINE=archive; SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; INSERT INTO t1 VALUES(1, 'sampleblob1'),(2, 'sampleblob2'); +# Compression length depends on zip library +--replace_result 583 584 291 292 SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result index b11484367b8b0..4625a6cab2142 100644 --- a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result +++ b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result @@ -217,3 +217,11 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test`; INSERT INTO tm VALUES (1),(1) master-bin.000001 # Query # # COMMIT DROP TABLE tm; +connection default; +SET pseudo_slave_mode=1; +XA START 'a'; +XA END 'a'; +XA PREPARE 'a'; +XA ROLLBACK 'a'; +ERROR XA100: XA_RBROLLBACK: Transaction branch was rolled back +include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test index 52b4ad2037b51..501403f46fc7e 100644 --- a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test +++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test @@ -134,3 +134,15 @@ XA ROLLBACK '1'; --source include/show_binlog_events.inc DROP TABLE tm; + +# MDEV-32257 dangling XA-rollback in binlog from emtpy XA +--connection default +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +SET pseudo_slave_mode=1; +XA START 'a'; +XA END 'a'; +XA PREPARE 'a'; +--error ER_XA_RBROLLBACK +XA ROLLBACK 'a'; +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/compat/oracle/t/column_compression.test b/mysql-test/suite/compat/oracle/t/column_compression.test index 6fcdd11989053..01d4977ba961f 100644 --- a/mysql-test/suite/compat/oracle/t/column_compression.test +++ b/mysql-test/suite/compat/oracle/t/column_compression.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc +--source include/have_normal_bzip.inc SET sql_mode=ORACLE; diff --git a/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result b/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result index 72cd3e089315b..fc49d8313f53d 100644 --- a/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result +++ b/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result @@ -14,19 +14,19 @@ Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT `encrypted`=yes `encryption_key_id`=1 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=COMPACT `encrypted`=yes `encryption_key_id`=1 show create table innodb_dynamic; Table Create Table innodb_dynamic CREATE TABLE `innodb_dynamic` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC `encrypted`=yes `encryption_key_id`=33 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC `encrypted`=yes `encryption_key_id`=33 show create table innodb_redundant; Table Create Table innodb_redundant CREATE TABLE `innodb_redundant` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT `encrypted`=yes `encryption_key_id`=4 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=REDUNDANT `encrypted`=yes `encryption_key_id`=4 create procedure innodb_insert_proc (repeat_count int) begin declare current_num int; @@ -56,6 +56,7 @@ count(*) select count(*) from innodb_redundant where c1 < 1500000; count(*) 5000 +# restart update innodb_compact set c1 = c1 + 1; update innodb_dynamic set c1 = c1 + 1; update innodb_redundant set c1 = c1 + 1; @@ -74,39 +75,40 @@ Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=COMPACT alter table innodb_dynamic engine=innodb encrypted=DEFAULT encryption_key_id=DEFAULT; show create table innodb_dynamic; Table Create Table innodb_dynamic CREATE TABLE `innodb_dynamic` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC alter table innodb_redundant engine=innodb encrypted=DEFAULT encryption_key_id=DEFAULT; show create table innodb_redundant; Table Create Table innodb_redundant CREATE TABLE `innodb_redundant` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=REDUNDANT +# restart show create table innodb_compact; Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=COMPACT show create table innodb_dynamic; Table Create Table innodb_dynamic CREATE TABLE `innodb_dynamic` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC show create table innodb_redundant; Table Create Table innodb_redundant CREATE TABLE `innodb_redundant` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=REDUNDANT update innodb_compact set c1 = c1 + 1; update innodb_dynamic set c1 = c1 + 1; update innodb_redundant set c1 = c1 + 1; diff --git a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result index 6482a5d960d8d..e503cb9a95c38 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result +++ b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result @@ -11,6 +11,7 @@ call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); call mtr.add_suppression("InnoDB: Missing FILE_CHECKPOINT"); call mtr.add_suppression("InnoDB: Log scan aborted at LSN"); call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); +call mtr.add_suppression("InnoDB: Encryption key is not found for"); # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt create table t1(a int not null primary key auto_increment, c char(200), b blob, index(b(10))) engine=innodb row_format=compressed encrypted=yes encryption_key_id=20; create table t2(a int not null primary key auto_increment, c char(200), b blob, index(b(10))) engine=innodb row_format=compressed encrypted=yes; @@ -40,5 +41,6 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +FOUND 1 /\[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd/ in mysqld.1.err # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test index 1eca1d8cf73f8..22fcd75446e7b 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test +++ b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test @@ -16,6 +16,7 @@ call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); call mtr.add_suppression("InnoDB: Missing FILE_CHECKPOINT"); call mtr.add_suppression("InnoDB: Log scan aborted at LSN"); call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); +call mtr.add_suppression("InnoDB: Encryption key is not found for"); -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt -- source include/restart_mysqld.inc @@ -73,6 +74,10 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN = \[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd; +--source include/search_pattern_in_file.inc + # # In above server does start but InnoDB refuses to start # thus we need to restart server with correct key file diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index dbcead827eefb..154eaef5a2641 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -171,9 +171,9 @@ def mysql slow_log insert_id 9 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) def mysql slow_log last_insert_id 8 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL def mysql slow_log lock_time 4 NULL NO time NULL NULL NULL NULL 6 NULL NULL time(6) select,insert,update,references NEVER NULL def mysql slow_log query_time 3 NULL NO time NULL NULL NULL NULL 6 NULL NULL time(6) select,insert,update,references NEVER NULL -def mysql slow_log rows_affected 13 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL -def mysql slow_log rows_examined 6 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL -def mysql slow_log rows_sent 5 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL +def mysql slow_log rows_affected 13 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL +def mysql slow_log rows_examined 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL +def mysql slow_log rows_sent 5 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8mb3 utf8mb3_general_ci mediumtext select,insert,update,references NEVER NULL def mysql slow_log start_time 1 current_timestamp(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update current_timestamp(6) select,insert,update,references NEVER NULL @@ -497,15 +497,15 @@ NULL mysql slow_log start_time timestamp NULL NULL NULL NULL timestamp(6) 1.0000 mysql slow_log user_host mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log query_time time NULL NULL NULL NULL time(6) NULL mysql slow_log lock_time time NULL NULL NULL NULL time(6) -NULL mysql slow_log rows_sent int NULL NULL NULL NULL int(11) -NULL mysql slow_log rows_examined int NULL NULL NULL NULL int(11) +NULL mysql slow_log rows_sent bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql slow_log rows_examined bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql slow_log db varchar 512 1536 utf8mb3 utf8mb3_general_ci varchar(512) NULL mysql slow_log last_insert_id int NULL NULL NULL NULL int(11) NULL mysql slow_log insert_id int NULL NULL NULL NULL int(11) NULL mysql slow_log server_id int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql slow_log sql_text mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log thread_id bigint NULL NULL NULL NULL bigint(21) unsigned -NULL mysql slow_log rows_affected int NULL NULL NULL NULL int(11) +NULL mysql slow_log rows_affected bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql tables_priv Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql tables_priv Db char 64 192 utf8mb3 utf8mb3_bin char(64) 3.0000 mysql tables_priv User char 128 384 utf8mb3 utf8mb3_bin char(128) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index d609a2f4b73fd..9fac1a2244040 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -157,9 +157,9 @@ def mysql slow_log insert_id 9 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) def mysql slow_log last_insert_id 8 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL def mysql slow_log lock_time 4 NULL NO time NULL NULL NULL NULL 6 NULL NULL time(6) NEVER NULL def mysql slow_log query_time 3 NULL NO time NULL NULL NULL NULL 6 NULL NULL time(6) NEVER NULL -def mysql slow_log rows_affected 13 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def mysql slow_log rows_examined 6 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def mysql slow_log rows_sent 5 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL +def mysql slow_log rows_affected 13 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL +def mysql slow_log rows_examined 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL +def mysql slow_log rows_sent 5 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned NEVER NULL def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8mb3 utf8mb3_general_ci mediumtext NEVER NULL def mysql slow_log start_time 1 current_timestamp(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update current_timestamp(6) NEVER NULL @@ -480,15 +480,15 @@ NULL mysql slow_log start_time timestamp NULL NULL NULL NULL timestamp(6) 1.0000 mysql slow_log user_host mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log query_time time NULL NULL NULL NULL time(6) NULL mysql slow_log lock_time time NULL NULL NULL NULL time(6) -NULL mysql slow_log rows_sent int NULL NULL NULL NULL int(11) -NULL mysql slow_log rows_examined int NULL NULL NULL NULL int(11) +NULL mysql slow_log rows_sent bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql slow_log rows_examined bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql slow_log db varchar 512 1536 utf8mb3 utf8mb3_general_ci varchar(512) NULL mysql slow_log last_insert_id int NULL NULL NULL NULL int(11) NULL mysql slow_log insert_id int NULL NULL NULL NULL int(11) NULL mysql slow_log server_id int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql slow_log sql_text mediumtext 16777215 16777215 utf8mb3 utf8mb3_general_ci mediumtext NULL mysql slow_log thread_id bigint NULL NULL NULL NULL bigint(21) unsigned -NULL mysql slow_log rows_affected int NULL NULL NULL NULL int(11) +NULL mysql slow_log rows_affected bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql tables_priv Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql tables_priv Db char 64 192 utf8mb3 utf8mb3_bin char(64) 3.0000 mysql tables_priv User char 128 384 utf8mb3 utf8mb3_bin char(128) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index ffdf0ea6e4be3..b6e27070ba63f 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -13,9 +13,6 @@ galera_as_slave_ctas : MDEV-28378 timeout galera_pc_recovery : MDEV-25199 cluster fails to start up galera_sst_encrypted : MDEV-29876 Galera test failure on galera_sst_encrypted -galera_binlog_checksum : MDEV-29861 Galera test case hangs -galera_var_notify_ssl_ipv6 : MDEV-29861 Galera test case hangs -galera_var_notify_cmd: MDEV-29861 Galera test case hangs galera_var_node_address : MDEV-20485 Galera test failure MDEV-26575 : MDEV-29878 Galera test failure on MDEV-26575 galera_bf_abort_shutdown : MDEV-29918 Assertion failure on galera_bf_abort_shutdown diff --git a/mysql-test/suite/galera/r/galera_partition.result b/mysql-test/suite/galera/r/galera_partition.result index 0e8894794d7cd..7b4d6e41054f2 100644 --- a/mysql-test/suite/galera/r/galera_partition.result +++ b/mysql-test/suite/galera/r/galera_partition.result @@ -3,8 +3,6 @@ connection node_1; connection node_1; call mtr.add_suppression("WSREP: RSU failed due to pending transactions, schema: test, query ALTER.*"); call mtr.add_suppression("WSREP: ALTER TABLE isolation failure"); -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; -connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4; connection node_1; CREATE TABLE t1( id bigint unsigned NOT NULL AUTO_INCREMENT, @@ -396,33 +394,24 @@ insert into t1 (id, dt) values (350, '2010-12-17 00:00:00'); SELECT COUNT(*) FROM t1; COUNT(*) 350 -connection node_2; -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -call p1(10); -connection node_3; -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -call p1(10); -connection node_4; -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -call p1(10); connection node_1; +call p1(10);; +connection node_2; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; SET SESSION wsrep_OSU_method='RSU'; -SELECT @@wsrep_OSU_method; -@@wsrep_OSU_method -RSU SET SESSION sql_log_bin = 0; ALTER TABLE t1 DROP PARTITION rx2009xx; ALTER TABLE t1 DROP PARTITION rx201004; ALTER TABLE t1 DROP PARTITION rx201008; SET SESSION wsrep_OSU_METHOD='TOI'; +SET SESSION sql_log_bin = 1; SELECT @@wsrep_OSU_method; @@wsrep_OSU_method TOI connection node_2; -connection node_3; -connection node_4; +disconnect node_2a; +connection node_1; connection node_1; DROP TABLE t1; DROP PROCEDURE p1; -disconnect node_3; -disconnect node_4; diff --git a/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result b/mysql-test/suite/galera/r/mariadb_tzinfo_to_sql.result old mode 100755 new mode 100644 diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test index 0d878db29b8a0..e22f0240a594f 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test +++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test @@ -27,7 +27,6 @@ SET SESSION wsrep_sync_wait = 0; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; --connection node_2 ---sleep 1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc @@ -47,7 +46,6 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5); --connection node_2 --sleep 5 - --let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1) --connection node_1 --disable_query_log diff --git a/mysql-test/suite/galera/t/galera_partition.cnf b/mysql-test/suite/galera/t/galera_partition.cnf deleted file mode 100644 index 525eece04abaf..0000000000000 --- a/mysql-test/suite/galera/t/galera_partition.cnf +++ /dev/null @@ -1,22 +0,0 @@ -!include ../galera_4nodes.cnf - -[mysqld.1] -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M;gmcast.segment=1' -wsrep_slave_threads=10 -wsrep_debug=1 - -[mysqld.2] -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M;gmcast.segment=1' -wsrep_slave_threads=10 -wsrep_debug=1 - -[mysqld.3] -wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M;gmcast.segment=2' -wsrep_slave_threads=10 -wsrep_debug=1 - -[mysqld.4] -wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M;gmcast.segment=3' -wsrep_slave_threads=10 -wsrep_debug=1 - diff --git a/mysql-test/suite/galera/t/galera_partition.test b/mysql-test/suite/galera/t/galera_partition.test index 3de45d5400064..269291311f1df 100644 --- a/mysql-test/suite/galera/t/galera_partition.test +++ b/mysql-test/suite/galera/t/galera_partition.test @@ -1,17 +1,15 @@ --source include/galera_cluster.inc --source include/have_partition.inc --source include/big_test.inc +--source include/force_restart.inc --connection node_1 call mtr.add_suppression("WSREP: RSU failed due to pending transactions, schema: test, query ALTER.*"); call mtr.add_suppression("WSREP: ALTER TABLE isolation failure"); ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 ---connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 - --connection node_1 ---let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc CREATE TABLE t1( @@ -408,50 +406,37 @@ insert into t1 (id, dt) values (350, '2010-12-17 00:00:00'); SELECT COUNT(*) FROM t1; ---connection node_2 -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -send call p1(10); - ---connection node_3 -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -send call p1(10); +--connection node_1 +--send call p1(10); ---connection node_4 -call mtr.add_suppression("WSREP: Sending JOIN failed:"); -send call p1(10); +--connection node_2 ---connection node_1 +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a SET SESSION wsrep_OSU_method='RSU'; -SELECT @@wsrep_OSU_method; SET SESSION sql_log_bin = 0; ---error 0,ER_LOCK_DEADLOCK +--error 0,ER_LOCK_DEADLOCK,ER_LOCK_WAIT_TIMEOUT ALTER TABLE t1 DROP PARTITION rx2009xx; ---error 0,ER_LOCK_DEADLOCK +--error 0,ER_LOCK_DEADLOCK,ER_LOCK_WAIT_TIMEOUT ALTER TABLE t1 DROP PARTITION rx201004; ---error 0,ER_LOCK_DEADLOCK +--error 0,ER_LOCK_DEADLOCK,ER_LOCK_WAIT_TIMEOUT ALTER TABLE t1 DROP PARTITION rx201008; SET SESSION wsrep_OSU_METHOD='TOI'; +SET SESSION sql_log_bin = 1; SELECT @@wsrep_OSU_method; --connection node_2 ---error 0,ER_LOCK_DEADLOCK -reap; +--disconnect node_2a ---connection node_3 ---error 0,ER_LOCK_DEADLOCK -reap; - ---connection node_4 ---error 0,ER_LOCK_DEADLOCK +--connection node_1 +--error 0,ER_LOCK_DEADLOCK,ER_LOCK_WAIT_TIMEOUT reap; --connection node_1 DROP TABLE t1; DROP PROCEDURE p1; ---disconnect node_3 ---disconnect node_4 diff --git a/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test b/mysql-test/suite/galera/t/mariadb_tzinfo_to_sql.test old mode 100755 new mode 100644 diff --git a/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test old mode 100755 new mode 100644 diff --git a/mysql-test/suite/galera_sr/r/MDEV-32051.result b/mysql-test/suite/galera_sr/r/MDEV-32051.result new file mode 100644 index 0000000000000..2328bdb57b02b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MDEV-32051.result @@ -0,0 +1,38 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +connection node_1; +SET SESSION wsrep_trx_fragment_size=1; +SET DEBUG_SYNC='wsrep_before_certification SIGNAL before_fragment WAIT_FOR continue'; +INSERT INTO t1 VALUES (2); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1a; +SET SESSION wsrep_sync_wait=0; +SET DEBUG_SYNC='now WAIT_FOR before_fragment'; +SET GLOBAL wsrep_provider_options = 'dbug=d,before_replicate_sync'; +SET DEBUG_SYNC='now SIGNAL continue'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET DEBUG_SYNC='RESET'; +connection node_2; +TRUNCATE TABLE t1; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=before_replicate_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 +connection node_2; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/MDEV-32051.test b/mysql-test/suite/galera_sr/t/MDEV-32051.test new file mode 100644 index 0000000000000..bfdea3f13e711 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MDEV-32051.test @@ -0,0 +1,72 @@ +# +# MDEV-32051 : Failed to insert streaming client +# +# Test outline: +# To reproduce we need a autocommit INSERT with streaming enabled, +# and a conflicting TRUNCATE. +# The INSERT is BF aborted by TRUNCATE during replication of the commit +# fragment, so that the INSERT must be rolled back replayed. During +# replay it fails certification, finally the statement is retried and +# succeeds. If bug is present, the streaming client for the INSERT does +# not get deleted after replay, causing the warning (or assert in debug builds) +# when retrying attempts to create the same streaming client with the same id. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +# +# Issue an INSERT and block it right before certification +# of the commit fragment. This is needed to setup for +# before_replicate_sync in galera, to make sure we catch +# the commit fragment. +# +--connection node_1 +SET SESSION wsrep_trx_fragment_size=1; +SET DEBUG_SYNC='wsrep_before_certification SIGNAL before_fragment WAIT_FOR continue'; +--send INSERT INTO t1 VALUES (2) + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_sync_wait=0; +SET DEBUG_SYNC='now WAIT_FOR before_fragment'; +--let galera_sync_point = before_replicate_sync +--source include/galera_set_sync_point.inc +SET DEBUG_SYNC='now SIGNAL continue'; +--source include/galera_wait_sync_point.inc +SET DEBUG_SYNC='RESET'; + +# +# Commit fragment of INSERT is now parked in galera side +# before replication. Issue the conflicting DDL +# +--connection node_2 +TRUNCATE TABLE t1; + +--connection node_1a +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc + +# INSERT is first aborted, but ultimately succeeds because of wsrep_autocommit_retry +# If bug is present: +# [Warning] WSREP: Failed to insert streaming client +# server_state.cpp:1152: void wsrep::server_state::start_streaming_client(wsrep::client_state*): Assertion `0' failed. +--connection node_1 +--reap + +SELECT * FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + +--connection node_2 + +SELECT * FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + + +DROP TABLE t1; diff --git a/mysql-test/suite/gcol/disabled.def b/mysql-test/suite/gcol/disabled.def new file mode 100644 index 0000000000000..77359887431cf --- /dev/null +++ b/mysql-test/suite/gcol/disabled.def @@ -0,0 +1,12 @@ +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# : BUG# +# +# Do not use any TAB characters for whitespace. +# +############################################################################## +gcol.innodb_virtual_fk: MDEV-29181 Constant failures "InnoDB: tried to purge non-delete-marked record in index" diff --git a/mysql-test/suite/gcol/r/innodb_virtual_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_purge.result index 48a2d31338267..1fcbd05f354fe 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_purge.result @@ -159,4 +159,18 @@ UNIQUE(pk), KEY(e) ) ENGINE=InnoDB; DROP TABLE t1, t2; +# +# MDEV-30024 InnoDB: tried to purge non-delete-marked record +# of an index on a virtual column prefix +# +CREATE TABLE t(a BINARY(8), b CHAR(8) AS (a) VIRTUAL, KEY(b(4))) +CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t (a) VALUES (''),(''); +UPDATE t SET a = 'x'; +UPDATE t SET a = ''; +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE t EXTENDED; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_purge.test index e9e4caf8e07fc..3db1b8757ff15 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_purge.test @@ -172,5 +172,19 @@ dec $n; DROP TABLE t1, t2; +--echo # +--echo # MDEV-30024 InnoDB: tried to purge non-delete-marked record +--echo # of an index on a virtual column prefix +--echo # + +CREATE TABLE t(a BINARY(8), b CHAR(8) AS (a) VIRTUAL, KEY(b(4))) +CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t (a) VALUES (''),(''); +UPDATE t SET a = 'x'; +UPDATE t SET a = ''; +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE t EXTENDED; +DROP TABLE t; + --source include/wait_until_count_sessions.inc SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/fk_col_alter.result b/mysql-test/suite/innodb/r/fk_col_alter.result index 36c5a3aa1afe5..1e8914ffc49af 100644 --- a/mysql-test/suite/innodb/r/fk_col_alter.result +++ b/mysql-test/suite/innodb/r/fk_col_alter.result @@ -81,4 +81,14 @@ DROP TABLE t2, t1; CREATE TABLE t (a VARCHAR(40), b INT, C INT) ENGINE=InnoDB; ALTER TABLE t MODIFY a VARCHAR(50), DROP b; DROP TABLE t; +# +# MDEV-32060 Server aborts when table doesn't +# have referenced index +# +SET SESSION FOREIGN_KEY_CHECKS = OFF; +CREATE TABLE t1 (a VARCHAR(16) KEY, FOREIGN KEY(a) REFERENCES t2(b)) ENGINE=InnoDB; +CREATE TABLE t2 (b VARCHAR(8)) ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = ON; +ALTER TABLE t2 MODIFY b VARCHAR(16), ADD KEY(b); +DROP TABLE t1, t2; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 61645e56c0cfd..a439f6d7981b0 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -1029,7 +1029,39 @@ CREATE OR REPLACE TABLE t1 (b INT) ENGINE=InnoDB; connection default; INSERT INTO t2 VALUES (1); connection con1; -disconnect con1; connection default; DROP TABLE IF EXISTS t2, t1; +# +# MDEV-30531 Corrupt index(es) on busy table when using FOREIGN KEY +# +SET @freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +CREATE TABLE collections ( +id int(11) unsigned NOT NULL AUTO_INCREMENT, +collectionhash varchar(255) NOT NULL DEFAULT '0', +PRIMARY KEY (id), +UNIQUE KEY ix_collection_collectionhash (collectionhash) +) ENGINE=InnoDB; +CREATE TABLE binaries ( +id bigint(20) unsigned NOT NULL AUTO_INCREMENT, +collections_id int(11) unsigned NOT NULL DEFAULT 0, +binaryhash binary(16) NOT NULL DEFAULT '0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +PRIMARY KEY (id), +UNIQUE KEY ix_binary_binaryhash (binaryhash), +CONSTRAINT FK_collections FOREIGN KEY (collections_id) REFERENCES collections (id) ON DELETE CASCADE +) ENGINE=InnoDB; +INSERT INTO collections (id) VALUES (NULL); +connection con1; +INSERT INTO binaries (id,collections_id) VALUES (NULL,1); +REPLACE INTO collections (id) VALUES (NULL); +connection default; +REPLACE INTO binaries (id) VALUES (NULL); +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE binaries, collections EXTENDED; +Table Op Msg_type Msg_text +test.binaries check status OK +test.collections check status OK +SET GLOBAL innodb_purge_rseg_truncate_frequency=@freq; +disconnect con1; +DROP TABLE binaries, collections; # End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index 8ac0d4d41fab2..6f5774d12b129 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -468,6 +468,29 @@ SET DEBUG_SYNC="now SIGNAL con1_signal"; connection con1; DROP TABLE t1; connection default; +# +# MDEV-28122 Optimize table crash while applying online log +# +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, +f3 CHAR(200), f4 CHAR(200), +f5 VARCHAR(87), PRIMARY KEY(f1))ENGINE=InnoDB; +INSERT INTO t1 VALUES(6000, 6000, "InnoDB", +"MariaDB", repeat('a', 87)); +SET DEBUG_SYNC="inplace_after_index_build SIGNAL dml_start WAIT_FOR dml_commit"; +ALTER TABLE t1 FORCE; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR dml_start"; +BEGIN; +INSERT INTO t1 SELECT seq, seq, "IDB", "MDB", repeat('a', 87) FROM seq_1_to_127; +INSERT INTO t1 VALUES(128, 128, "IDB", "MDB", repeat('a', 86)); +INSERT INTO t1 VALUES(129, 129, "idb", "mdb", repeat('a', 2)); +COMMIT; +SET DEBUG_SYNC="now SIGNAL dml_commit"; +connection default; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; SET DEBUG_SYNC=RESET; disconnect con1; SET GLOBAL innodb_monitor_enable = default; diff --git a/mysql-test/suite/innodb/r/innodb-xa.result b/mysql-test/suite/innodb/r/innodb-xa.result index 6eae842b14c36..6651bd5090db4 100644 --- a/mysql-test/suite/innodb/r/innodb-xa.result +++ b/mysql-test/suite/innodb/r/innodb-xa.result @@ -15,3 +15,30 @@ xa prepare 'xid2'; release savepoint `sv1`; xa commit 'xid2'; drop table t1; +# +# MDEV-31928 Assertion xid ... < 128 failed in trx_undo_write_xid() +# +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +XA START 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +INSERT INTO t VALUES(1); +XA END 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +XA PREPARE 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +XA COMMIT 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +DROP TABLE t; +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 0114393218648..e7f956df13cef 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -180,7 +180,7 @@ ROLLBACK; connection stop_purge; COMMIT; connection default; -InnoDB 2 transactions not purged +InnoDB 1 transactions not purged SET DEBUG_SYNC='now SIGNAL logged'; connection ddl; connection default; diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result index a3ac942d8fa8f..e4b8714768e3c 100644 --- a/mysql-test/suite/innodb/r/monitor.result +++ b/mysql-test/suite/innodb/r/monitor.result @@ -434,6 +434,8 @@ LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 0 SET GLOBAL innodb_monitor_enable='%'; +SET GLOBAL innodb_monitor_reset_all= '%', innodb_compression_algorithm= foo; +ERROR 42000: Variable 'innodb_compression_algorithm' can't be set to the value of 'foo' INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; diff --git a/mysql-test/suite/innodb/r/read_only_recovery.result b/mysql-test/suite/innodb/r/read_only_recovery.result index 2db128632464c..add0da94cab0d 100644 --- a/mysql-test/suite/innodb/r/read_only_recovery.result +++ b/mysql-test/suite/innodb/r/read_only_recovery.result @@ -36,6 +36,7 @@ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; a 3 +SET GLOBAL innodb_max_purge_lag_wait=0; # restart SELECT * FROM t; a diff --git a/mysql-test/suite/innodb/r/row_size_error_log_warnings_3.result b/mysql-test/suite/innodb/r/row_size_error_log_warnings_3.result index d00ac93831086..21085e4cd7e71 100644 --- a/mysql-test/suite/innodb/r/row_size_error_log_warnings_3.result +++ b/mysql-test/suite/innodb/r/row_size_error_log_warnings_3.result @@ -51,14 +51,13 @@ set global innodb_compression_level=1; CREATE TABLE t1( f1 INT, f2 CHAR(200), f3 CHAR(200), f4 CHAR(200), f5 CHAR(200), f6 CHAR(200), -f7 CHAR(200), f8 CHAR(200), f9 CHAR(200), -f10 CHAR(200), PRIMARY KEY(f1, f2(20), f3(20), f4(20)) +f7 CHAR(200), f8 CHAR(200), f9 CHAR(106), +PRIMARY KEY(f1, f2(20), f3(20), f4(20)) ) ROW_FORMAT=COMPRESSED, ENGINE=InnoDB; INSERT INTO t1 SELECT seq, repeat('a', 200), repeat('b', 200), repeat('c', 200), repeat('d', 200), repeat('d', 200), repeat('e', 200), -repeat('e', 200), repeat('f', 200), -repeat('g', 200) FROM seq_1_to_20; +repeat('f', 200), repeat('g', 106) FROM seq_1_to_20; DROP TABLE t1; set global innodb_compression_level=default; CREATE TABLE t1(f1 char(200), f2 char(200), f3 char(200), diff --git a/mysql-test/suite/innodb/r/scrub.result b/mysql-test/suite/innodb/r/scrub.result new file mode 100644 index 0000000000000..4c14088f4298f --- /dev/null +++ b/mysql-test/suite/innodb/r/scrub.result @@ -0,0 +1,15 @@ +SET GLOBAL +innodb_file_per_table=OFF, +innodb_purge_rseg_truncate_frequency=1, +innodb_immediate_scrub_data_uncompressed=ON; +Warnings: +Warning 1287 '@@innodb_file_per_table' is deprecated and will be removed in a future release +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, +f3 INT NOT NULL, INDEX(f1), +INDEX(f2), INDEX(f3))ENGINE=InnoDB; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +DROP TABLE t1; +SET GLOBAL innodb_max_purge_lag_wait=0; +# restart diff --git a/mysql-test/suite/innodb/r/scrub_debug.result b/mysql-test/suite/innodb/r/scrub_debug.result new file mode 100644 index 0000000000000..5fbf1250b212a --- /dev/null +++ b/mysql-test/suite/innodb/r/scrub_debug.result @@ -0,0 +1,22 @@ +SET @save_debug=@@GLOBAL.INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG; +SET @save_scrub=@@GLOBAL.INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED; +SET @save_freq=@@GLOBAL.INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY; +SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY=1; +SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=1; +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; +CREATE TABLE t1(f1 INT AUTO_INCREMENT PRIMARY KEY, +f2 VARCHAR(256) GENERATED ALWAYS as('repairman'), +INDEX idx(f2))ENGINE= InnoDB; +INSERT INTO t1(f1) SELECT seq FROM seq_1_to_50; +FLUSH TABLE t1 FOR EXPORT; +FOUND 108 /repairman/ in t1.ibd +UNLOCK TABLES; +ALTER TABLE t1 DROP INDEX idx; +InnoDB 0 transactions not purged +FLUSH TABLE t1 FOR EXPORT; +NOT FOUND /repairman/ in t1.ibd +UNLOCK TABLES; +DROP TABLE t1; +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; +SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; +SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY = @save_freq; diff --git a/mysql-test/suite/innodb/r/strict_mode.result b/mysql-test/suite/innodb/r/strict_mode.result index 7be5f961cccad..ae149f96ddb27 100644 --- a/mysql-test/suite/innodb/r/strict_mode.result +++ b/mysql-test/suite/innodb/r/strict_mode.result @@ -396,3 +396,18 @@ set innodb_strict_mode = 1; alter table t1 engine=InnoDB; ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs drop table t1; +# +# MDEV-32128 wrong table name in innodb's "row too big" errors +# +create temporary table t1 ( +c1 char(255), c2 char(255), c3 char(255), c4 char(255), +c5 char(255), c6 char(255), c7 char(255), c8 char(255), +c9 char(255), c10 char(255), c11 char(255), c12 char(255), +c13 char(255), c14 char(255), c15 char(255), c16 char(255), +c17 char(255), c18 char(255), c19 char(255), c20 char(255), +c21 char(255), c22 char(255), c23 char(255), c24 char(255), +c25 char(255), c26 char(255), c27 char(255), c28 char(255), +c29 char(255), c30 char(255), c31 char(255), c32 char(255) +) engine=innodb; +ERROR 42000: Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline. +FOUND 1 /Cannot add field `c32` in table `test`.`t1` because/ in mysqld.1.err diff --git a/mysql-test/suite/innodb/r/xa_prepare_reset_supremum_lock.result b/mysql-test/suite/innodb/r/xa_prepare_reset_supremum_lock.result new file mode 100644 index 0000000000000..bd971adf9668e --- /dev/null +++ b/mysql-test/suite/innodb/r/xa_prepare_reset_supremum_lock.result @@ -0,0 +1,33 @@ +CREATE TABLE t ( +`a` INT NOT NULL, +PRIMARY KEY (`a`) +) ENGINE=InnoDB; +INSERT INTO t VALUES(10); +INSERT INTO t VALUES(20); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +XA START '1'; +SELECT * FROM t WHERE a > 20 FOR UPDATE; +a +INSERT INTO t VALUES(40); +XA END '1'; +XA PREPARE '1'; +connect con1,localhost,root; +SET innodb_lock_wait_timeout=1; +INSERT INTO t VALUES(50); +connection default; +XA COMMIT '1'; +XA START '1'; +SELECT * FROM t WHERE a > 20 LOCK IN SHARE MODE; +a +40 +50 +INSERT INTO t VALUES (5); +XA END '1'; +XA PREPARE '1'; +connection con1; +INSERT INTO t VALUES (60); +INSERT INTO t VALUES (30); +disconnect con1; +connection default; +XA COMMIT '1'; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/xap_release_locks_on_dict_stats_table.result b/mysql-test/suite/innodb/r/xap_release_locks_on_dict_stats_table.result new file mode 100644 index 0000000000000..1a849f1c4779d --- /dev/null +++ b/mysql-test/suite/innodb/r/xap_release_locks_on_dict_stats_table.result @@ -0,0 +1,17 @@ +call mtr.add_suppression("bytes freed by"); +SET @old_innodb_stats_persistent = @@innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent=1; +CREATE TABLE t ENGINE=InnoDB AS SELECT 1; +SET @old_debug_dbug = @@global.debug_dbug; +XA START 'a'; +INSERT INTO mysql.innodb_index_stats SELECT '','' AS table_name,index_name,LAST_UPDATE,stat_name,0 AS stat_value,sample_size,stat_description FROM mysql.innodb_index_stats WHERE table_name='dummy' FOR UPDATE; +SET GLOBAL debug_dbug = "+d,dict_stats_save_exit_notify"; +INSERT INTO t VALUES (1); +XA END 'a'; +XA PREPARE 'a'; +SET DEBUG_SYNC="now WAIT_FOR dict_stats_save_finished"; +SET @@global.debug_dbug = @old_debug_dbug; +SET DEBUG_SYNC="RESET"; +SET GLOBAL innodb_stats_persistent = @old_innodb_stats_persistent; +XA COMMIT 'a'; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/fk_col_alter.test b/mysql-test/suite/innodb/t/fk_col_alter.test index 7834f65776253..5e8d96e06456a 100644 --- a/mysql-test/suite/innodb/t/fk_col_alter.test +++ b/mysql-test/suite/innodb/t/fk_col_alter.test @@ -111,4 +111,15 @@ DROP TABLE t2, t1; CREATE TABLE t (a VARCHAR(40), b INT, C INT) ENGINE=InnoDB; ALTER TABLE t MODIFY a VARCHAR(50), DROP b; DROP TABLE t; + +--echo # +--echo # MDEV-32060 Server aborts when table doesn't +--echo # have referenced index +--echo # +SET SESSION FOREIGN_KEY_CHECKS = OFF; +CREATE TABLE t1 (a VARCHAR(16) KEY, FOREIGN KEY(a) REFERENCES t2(b)) ENGINE=InnoDB; +CREATE TABLE t2 (b VARCHAR(8)) ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = ON; +ALTER TABLE t2 MODIFY b VARCHAR(16), ADD KEY(b); +DROP TABLE t1, t2; --echo # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index dd375c099cb7b..31ab5168d0637 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -1071,12 +1071,53 @@ INSERT INTO t2 VALUES (1); --reap # Cleanup ---disconnect con1 --connection default --disable_warnings DROP TABLE IF EXISTS t2, t1; --enable_warnings +--echo # +--echo # MDEV-30531 Corrupt index(es) on busy table when using FOREIGN KEY +--echo # + +SET @freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; + +CREATE TABLE collections ( + id int(11) unsigned NOT NULL AUTO_INCREMENT, + collectionhash varchar(255) NOT NULL DEFAULT '0', + PRIMARY KEY (id), + UNIQUE KEY ix_collection_collectionhash (collectionhash) +) ENGINE=InnoDB; +CREATE TABLE binaries ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + collections_id int(11) unsigned NOT NULL DEFAULT 0, + binaryhash binary(16) NOT NULL DEFAULT '0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + PRIMARY KEY (id), + UNIQUE KEY ix_binary_binaryhash (binaryhash), + CONSTRAINT FK_collections FOREIGN KEY (collections_id) REFERENCES collections (id) ON DELETE CASCADE +) ENGINE=InnoDB; + +INSERT INTO collections (id) VALUES (NULL); + +--connection con1 +INSERT INTO binaries (id,collections_id) VALUES (NULL,1); +--send + REPLACE INTO collections (id) VALUES (NULL); + +--connection default +--error 0,ER_LOCK_DEADLOCK,ER_NO_REFERENCED_ROW_2 +REPLACE INTO binaries (id) VALUES (NULL); + +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE binaries, collections EXTENDED; +SET GLOBAL innodb_purge_rseg_truncate_frequency=@freq; + +--disconnect con1 + +# Cleanup +DROP TABLE binaries, collections; + --echo # End of 10.6 tests --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test index 5f0562e11ed30..2f16b34a0c5a2 100644 --- a/mysql-test/suite/innodb/t/innodb-table-online.test +++ b/mysql-test/suite/innodb/t/innodb-table-online.test @@ -2,6 +2,7 @@ --source include/innodb_encrypt_log.inc --source include/have_debug.inc --source include/have_debug_sync.inc +--source include/have_sequence.inc let $innodb_metrics_select= SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl'; @@ -436,6 +437,32 @@ connection con1; reap; DROP TABLE t1; connection default; + +--echo # +--echo # MDEV-28122 Optimize table crash while applying online log +--echo # +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, + f3 CHAR(200), f4 CHAR(200), + f5 VARCHAR(87), PRIMARY KEY(f1))ENGINE=InnoDB; +INSERT INTO t1 VALUES(6000, 6000, "InnoDB", + "MariaDB", repeat('a', 87)); + +SET DEBUG_SYNC="inplace_after_index_build SIGNAL dml_start WAIT_FOR dml_commit"; +SEND ALTER TABLE t1 FORCE; + +connection con1; +SET DEBUG_SYNC="now WAIT_FOR dml_start"; +BEGIN; +INSERT INTO t1 SELECT seq, seq, "IDB", "MDB", repeat('a', 87) FROM seq_1_to_127; +INSERT INTO t1 VALUES(128, 128, "IDB", "MDB", repeat('a', 86)); +INSERT INTO t1 VALUES(129, 129, "idb", "mdb", repeat('a', 2)); +COMMIT; +SET DEBUG_SYNC="now SIGNAL dml_commit"; + +connection default; +reap; +CHECK TABLE t1; +DROP TABLE t1; SET DEBUG_SYNC=RESET; disconnect con1; diff --git a/mysql-test/suite/innodb/t/innodb-xa.test b/mysql-test/suite/innodb/t/innodb-xa.test index d94cd75aa147a..9eb5848b04d33 100644 --- a/mysql-test/suite/innodb/t/innodb-xa.test +++ b/mysql-test/suite/innodb/t/innodb-xa.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc ---disable_abort_on_error +--error ER_XAER_NOTA xa rollback 'xid2'; drop table if exists t1; create table t1(a int)engine=innodb; @@ -9,9 +9,42 @@ xa start 'xid2'; insert into `t1` values (1); savepoint `sv1`; xa end 'xid2'; +--error ER_XAER_RMFAIL start transaction; xa prepare 'xid2'; release savepoint `sv1`; xa commit 'xid2'; drop table t1; +-- echo # +-- echo # MDEV-31928 Assertion xid ... < 128 failed in trx_undo_write_xid() +-- echo # + +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +--error ER_PARSE_ERROR +XA START 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; + +INSERT INTO t VALUES(1); + +--error ER_PARSE_ERROR +XA END 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA PREPARE 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA COMMIT 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; + +DROP TABLE t; + +-- echo # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index dbffa76727782..e94583cd25054 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -200,7 +200,7 @@ COMMIT; connection default; # Wait for purge to empty the table. -let $wait_all_purged=2; +let $wait_all_purged=1; --source include/wait_all_purged.inc let $wait_all_purged=0; diff --git a/mysql-test/suite/innodb/t/monitor.test b/mysql-test/suite/innodb/t/monitor.test index 89c4164b7167e..63c339e948967 100644 --- a/mysql-test/suite/innodb/t/monitor.test +++ b/mysql-test/suite/innodb/t/monitor.test @@ -330,6 +330,8 @@ SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_enable='%'; +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL innodb_monitor_reset_all= '%', innodb_compression_algorithm= foo; INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME diff --git a/mysql-test/suite/innodb/t/read_only_recovery.test b/mysql-test/suite/innodb/t/read_only_recovery.test index 30876c2fbcff9..471462130903d 100644 --- a/mysql-test/suite/innodb/t/read_only_recovery.test +++ b/mysql-test/suite/innodb/t/read_only_recovery.test @@ -38,6 +38,7 @@ UPDATE t SET a=3 WHERE a=1; SELECT * FROM t; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; +SET GLOBAL innodb_max_purge_lag_wait=0; --let $restart_parameters= --source include/restart_mysqld.inc SELECT * FROM t; diff --git a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test index 209c86a29b5da..dab9bcfa86429 100644 --- a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test +++ b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test @@ -1,6 +1,7 @@ --source include/have_innodb.inc --source include/have_sequence.inc --source include/innodb_page_size_small.inc +--source include/have_normal_bzip.inc call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page."); @@ -49,15 +50,14 @@ set global innodb_compression_level=1; CREATE TABLE t1( f1 INT, f2 CHAR(200), f3 CHAR(200), f4 CHAR(200), f5 CHAR(200), f6 CHAR(200), - f7 CHAR(200), f8 CHAR(200), f9 CHAR(200), - f10 CHAR(200), PRIMARY KEY(f1, f2(20), f3(20), f4(20)) + f7 CHAR(200), f8 CHAR(200), f9 CHAR(106), + PRIMARY KEY(f1, f2(20), f3(20), f4(20)) ) ROW_FORMAT=COMPRESSED, ENGINE=InnoDB; INSERT INTO t1 SELECT seq, repeat('a', 200), repeat('b', 200), repeat('c', 200), repeat('d', 200), repeat('d', 200), repeat('e', 200), - repeat('e', 200), repeat('f', 200), - repeat('g', 200) FROM seq_1_to_20; + repeat('f', 200), repeat('g', 106) FROM seq_1_to_20; DROP TABLE t1; set global innodb_compression_level=default; diff --git a/mysql-test/suite/innodb/t/scrub.test b/mysql-test/suite/innodb/t/scrub.test new file mode 100644 index 0000000000000..a2f4e5757f5dd --- /dev/null +++ b/mysql-test/suite/innodb/t/scrub.test @@ -0,0 +1,19 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/not_embedded.inc + +SET GLOBAL + innodb_file_per_table=OFF, + innodb_purge_rseg_truncate_frequency=1, + innodb_immediate_scrub_data_uncompressed=ON; +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, + f3 INT NOT NULL, INDEX(f1), + INDEX(f2), INDEX(f3))ENGINE=InnoDB; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +DROP TABLE t1; +SET GLOBAL innodb_max_purge_lag_wait=0; +# The crash recovery would occasionally fail. +let $shutdown_timeout=0; +--source include/restart_mysqld.inc diff --git a/mysql-test/suite/innodb/t/scrub_debug.test b/mysql-test/suite/innodb/t/scrub_debug.test new file mode 100644 index 0000000000000..141b0f0c5baaf --- /dev/null +++ b/mysql-test/suite/innodb/t/scrub_debug.test @@ -0,0 +1,31 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/have_debug.inc + +SET @save_debug=@@GLOBAL.INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG; +SET @save_scrub=@@GLOBAL.INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED; +SET @save_freq=@@GLOBAL.INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY; + +SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY=1; +SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=1; +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; +let $MYSQLD_DATADIR=`select @@datadir`; +CREATE TABLE t1(f1 INT AUTO_INCREMENT PRIMARY KEY, + f2 VARCHAR(256) GENERATED ALWAYS as('repairman'), + INDEX idx(f2))ENGINE= InnoDB; +INSERT INTO t1(f1) SELECT seq FROM seq_1_to_50; +FLUSH TABLE t1 FOR EXPORT; +let SEARCH_PATTERN= repairman; +let SEARCH_FILE= $MYSQLD_DATADIR/test/t1.ibd; +-- source include/search_pattern_in_file.inc +UNLOCK TABLES; + +ALTER TABLE t1 DROP INDEX idx; +-- source include/wait_all_purged.inc +FLUSH TABLE t1 FOR EXPORT; +-- source include/search_pattern_in_file.inc +UNLOCK TABLES; +DROP TABLE t1; +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; +SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; +SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY = @save_freq; diff --git a/mysql-test/suite/innodb/t/strict_mode.test b/mysql-test/suite/innodb/t/strict_mode.test index 9154d6b73ae0f..34ccce5e0d2b6 100644 --- a/mysql-test/suite/innodb/t/strict_mode.test +++ b/mysql-test/suite/innodb/t/strict_mode.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/not_embedded.inc --echo # --echo # Bug #17852083 PRINT A WARNING WHEN DDL HAS AN ERROR IN @@ -401,3 +402,21 @@ set innodb_strict_mode = 1; alter table t1 engine=InnoDB; drop table t1; + +--echo # +--echo # MDEV-32128 wrong table name in innodb's "row too big" errors +--echo # +--error ER_TOO_BIG_ROWSIZE +create temporary table t1 ( + c1 char(255), c2 char(255), c3 char(255), c4 char(255), + c5 char(255), c6 char(255), c7 char(255), c8 char(255), + c9 char(255), c10 char(255), c11 char(255), c12 char(255), + c13 char(255), c14 char(255), c15 char(255), c16 char(255), + c17 char(255), c18 char(255), c19 char(255), c20 char(255), + c21 char(255), c22 char(255), c23 char(255), c24 char(255), + c25 char(255), c26 char(255), c27 char(255), c28 char(255), + c29 char(255), c30 char(255), c31 char(255), c32 char(255) +) engine=innodb; +let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN=Cannot add field `c32` in table `test`.`t1` because; +source include/search_pattern_in_file.inc; diff --git a/mysql-test/suite/innodb/t/xa_prepare_reset_supremum_lock.test b/mysql-test/suite/innodb/t/xa_prepare_reset_supremum_lock.test new file mode 100644 index 0000000000000..180e44d05ae83 --- /dev/null +++ b/mysql-test/suite/innodb/t/xa_prepare_reset_supremum_lock.test @@ -0,0 +1,48 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc + +CREATE TABLE t ( + `a` INT NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB; + + +INSERT INTO t VALUES(10); +INSERT INTO t VALUES(20); + +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +XA START '1'; +SELECT * FROM t WHERE a > 20 FOR UPDATE; +# The following INSERT is necessary because trx_prepare() resets locks +# only if there were modifications in transaction. +INSERT INTO t VALUES(40); +XA END '1'; +XA PREPARE '1'; + +connect (con1,localhost,root); +SET innodb_lock_wait_timeout=1; +# The following INSERT must not be blocked if XA PREPARE released supremum lock +INSERT INTO t VALUES(50); + +--connection default +XA COMMIT '1'; + +XA START '1'; +SELECT * FROM t WHERE a > 20 LOCK IN SHARE MODE; +# The following INSERT is necessary because trx_prepare() resets locks +# only if there were modifications in transaction. +INSERT INTO t VALUES (5); +XA END '1'; +XA PREPARE '1'; + +--connection con1 +# The following INSERT must not be blocked if XA PREPARE released supremum lock +INSERT INTO t VALUES (60); +# The following INSERT must not be blocked if XA PREPARE released shared lock +INSERT INTO t VALUES (30); +--disconnect con1 + +--connection default +XA COMMIT '1'; +DROP TABLE t; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/xap_release_locks_on_dict_stats_table.test b/mysql-test/suite/innodb/t/xap_release_locks_on_dict_stats_table.test new file mode 100644 index 0000000000000..a02a032ef614b --- /dev/null +++ b/mysql-test/suite/innodb/t/xap_release_locks_on_dict_stats_table.test @@ -0,0 +1,33 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# Some memory is allocated in dict_stats_save() function for additional sync +# point. The memory is allocated in current_thd->mem_root pool after +# dict_stats_func() arranged new thd and freed after destroy_background_thd() +# attached background thread thd to the current_thd. That's there are +# different thread id's for memory allocation and deallocation, what causes +# the following warnings. This is not an error because the memory is still +# allocated and deallocated by the same thread in pool. +call mtr.add_suppression("bytes freed by"); + +SET @old_innodb_stats_persistent = @@innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent=1; +CREATE TABLE t ENGINE=InnoDB AS SELECT 1; + +SET @old_debug_dbug = @@global.debug_dbug; + +XA START 'a'; +INSERT INTO mysql.innodb_index_stats SELECT '','' AS table_name,index_name,LAST_UPDATE,stat_name,0 AS stat_value,sample_size,stat_description FROM mysql.innodb_index_stats WHERE table_name='dummy' FOR UPDATE; # Note the SELECT is empty +SET GLOBAL debug_dbug = "+d,dict_stats_save_exit_notify"; +INSERT INTO t VALUES (1); +XA END 'a'; +XA PREPARE 'a'; + +# Locking queue validation will crash the server if the bug is not fixed +SET DEBUG_SYNC="now WAIT_FOR dict_stats_save_finished"; +SET @@global.debug_dbug = @old_debug_dbug; +SET DEBUG_SYNC="RESET"; +SET GLOBAL innodb_stats_persistent = @old_innodb_stats_persistent; +XA COMMIT 'a'; +DROP TABLE t; diff --git a/mysql-test/suite/innodb_gis/r/gis_split_nan.result b/mysql-test/suite/innodb_gis/r/gis_split_nan.result index 5d3d5c8910865..ce019203b883e 100644 --- a/mysql-test/suite/innodb_gis/r/gis_split_nan.result +++ b/mysql-test/suite/innodb_gis/r/gis_split_nan.result @@ -20,12 +20,6 @@ INSERT INTO gis_point VALUES (108, ST_POINTFROMWKB(POINT(0,10))), (109, ST_POINTFROMWKB(POINT(-10,0))), (110, ST_POINTFROMWKB(POINT(0,-10))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_point VALUES (111, ST_POINTFROMWKB(ST_ASWKB(ST_POINTFROMTEXT('POINT(1 1)')))), (112, ST_POINTFROMWKB(ST_ASWKB(ST_POINTFROMTEXT('POINT(1e308 1e308)')))), @@ -45,18 +39,10 @@ INSERT INTO gis_linestring VALUES (207, ST_LINEFROMWKB(LINESTRING(POINT(0,0), POINT(5,5)))), (208, ST_LINEFROMWKB(LINESTRING(POINT(0,0), POINT(-5,-5), POINT(-10,10)))), (209, ST_LINEFROMWKB(LINESTRING(POINT(0,0), POINT(2,2), POINT(4,4), POINT(6,6), POINT(8,8)))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_linestring VALUES (210, ST_LINESTRINGFROMWKB(LINESTRING(POINT(0,0), POINT(5,5)))), (211, ST_LINESTRINGFROMWKB(LINESTRING(POINT(0,0), POINT(-50,-50), POINT(10,-10)))), (212, ST_LINESTRINGFROMWKB(LINESTRING(POINT(0,0), POINT(1e308,1e308), POINT(1e308,-1e308)))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_linestring VALUES (213, ST_LINEFROMWKB(ST_ASWKB(ST_LINEFROMTEXT('LINESTRING(1e308 1e308,1e308 -1e308)')))), (214, ST_LINEFROMWKB(ST_ASWKB(ST_LINEFROMTEXT('LINESTRING(1 1,2 2,3 3,4 4,5 5,6 6,7 7,8 8,9 9)')))), @@ -75,19 +61,11 @@ INSERT INTO gis_polygon VALUES (308, ST_POLYFROMWKB(POLYGON(LINESTRING(POINT(0,0), POINT(0,15), POINT(15,15), POINT(15,0), POINT(0,0))))), (309, ST_POLYFROMWKB(POLYGON(LINESTRING(POINT(0,0), POINT(0,10), POINT(10,10), POINT(10,0), POINT(0,0)), LINESTRING(POINT(4,4), POINT(4,6), POINT(6,6), POINT(6,4), POINT(4,4))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_polygon VALUES (310, ST_POLYGONFROMWKB(POLYGON(LINESTRING(POINT(0,0), POINT(0,5), POINT(5,5), POINT(0,0))))), (311, ST_POLYGONFROMWKB(POLYGON(LINESTRING(POINT(10,10), POINT(10,15), POINT(15,15), POINT(15,10), POINT(10,10))))), (312, ST_POLYGONFROMWKB(POLYGON(LINESTRING(POINT(10,10), POINT(10,20), POINT(20,20), POINT(20,10), POINT(10,10)), LINESTRING(POINT(14,14), POINT(14,16), POINT(16,16), POINT(16,14), POINT(14,14))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_polygon VALUES (313, ST_POLYFROMWKB(ST_ASWKB(ST_POLYFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0,5 5,0 0))')))), (314, ST_POLYFROMWKB(ST_ASWKB(ST_POLYGONFROMTEXT('POLYGON((10 0,10 10,0 10,-10 10,-10 0,-10 -10,0 10,10 -10,10 0))')))), @@ -105,18 +83,10 @@ INSERT INTO gis_multi_point VALUES (407, ST_GEOMFROMWKB(MULTIPOINT(POINT(0,0)))), (408, ST_GEOMFROMWKB(MULTIPOINT(POINT(0,0), POINT(10,10)))), (409, ST_GEOMFROMWKB(MULTIPOINT(POINT(0,0), POINT(2,2), POINT(4,4), POINT(6,6)))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_point VALUES (410, ST_GEOMFROMWKB(MULTIPOINT(POINT(0,0)))), (411, ST_GEOMFROMWKB(MULTIPOINT(POINT(0,0), POINT(1e308,1e308)))), (412, ST_GEOMFROMWKB(MULTIPOINT(POINT(1e308,1e308), POINT(-1e308,1e308), POINT(1e308,-1e308), POINT(-1e308,-1e308)))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_point VALUES (413, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTIPOINT(0 0)')))), (414, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTIPOINT(0 0,1e308 1e308,-1e308 -1e308)')))), @@ -135,19 +105,11 @@ INSERT INTO gis_multi_linestring VALUES (508, ST_GEOMFROMWKB(MULTILINESTRING(LINESTRING(POINT(0,0), POINT(12,12), POINT(24,24))))), (509, ST_GEOMFROMWKB(MULTILINESTRING(LINESTRING(POINT(0,0), POINT(2,2), POINT(4,4)), LINESTRING(POINT(6,6), POINT(8,8), POINT(10,10))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_linestring VALUES (510, ST_GEOMFROMWKB(MULTILINESTRING(LINESTRING(POINT(0,0), POINT(2,2), POINT(4,4))))), (511, ST_GEOMFROMWKB(MULTILINESTRING(LINESTRING(POINT(0,0), POINT(1,1), POINT(2,2))))), (512, ST_GEOMFROMWKB(MULTILINESTRING(LINESTRING(POINT(0,0), POINT(12,12), POINT(24,24)), LINESTRING(POINT(36,36), POINT(48,48), POINT(50,50))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_linestring VALUES (513, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,10 10),(0 10,10 0))')))), (514, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,10 10,-10 10,0 0),(0 0,-10 -10,10 -10,0 0))')))), @@ -167,10 +129,6 @@ INSERT INTO gis_multi_polygon VALUES LINESTRING(POINT(4,4), POINT(4,6), POINT(6,6), POINT(6,4), POINT(4,4)))))), (609, ST_GEOMFROMWKB(MULTIPOLYGON(POLYGON(LINESTRING(POINT(0,0), POINT(5,0), POINT(5,5), POINT(0,5), POINT(0,0))), POLYGON(LINESTRING(POINT(0,0), POINT(-5,0), POINT(-5,-5), POINT(0,-5), POINT(0,0)))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_polygon VALUES (610, ST_GEOMFROMWKB(MULTIPOLYGON(POLYGON(LINESTRING(POINT(0,0), POINT(-5,0), POINT(-5,-5), POINT(0,-5), POINT(0,0)))))), (611, ST_GEOMFROMWKB(MULTIPOLYGON(POLYGON(LINESTRING(POINT(10,10), POINT(20,10), POINT(20,20), POINT(10,20), POINT(10,10)), @@ -178,10 +136,6 @@ LINESTRING(POINT(14,14), POINT(14,16), POINT(16,16), POINT(16,14), POINT(14,14)) (612, ST_GEOMFROMWKB(MULTIPOLYGON(POLYGON(LINESTRING(POINT(0,0), POINT(0,10), POINT(10,10), POINT(10,0), POINT(0,0)), LINESTRING(POINT(4,4), POINT(4,6), POINT(6,6), POINT(6,4), POINT(4,4))), POLYGON(LINESTRING(POINT(0,0), POINT(-5,0), POINT(-5,-5), POINT(0,-5), POINT(0,0)))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_multi_polygon VALUES (613, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,5 5,5 -5,0 0)),((0 0,-5 5,-5 -5,0 0)))')))), (614, ST_GEOMFROMWKB(ST_ASWKB(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,10 10,-10 10,0 0)),((0 0,-10 -10,10 -10,0 0)))')))), @@ -212,10 +166,6 @@ LINESTRING(POINT(10,10), POINT(5,5), POINT(0,10))), MULTIPOLYGON(POLYGON(LINESTRING(POINT(0,0), POINT(0,10), POINT(10,10), POINT(10,0), POINT(0,0)), LINESTRING(POINT(4,4), POINT(4,6), POINT(6,6), POINT(6,4), POINT(4,4))), POLYGON(LINESTRING(POINT(0,0), POINT(-10,0), POINT(-10,-10), POINT(0,0))))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_geometrycollection VALUES (710, ST_GEOMETRYCOLLECTIONFROMWKB(GEOMETRYCOLLECTION(POINT(0,0), LINESTRING(POINT(0,0), POINT(100,100))))), @@ -229,10 +179,6 @@ LINESTRING(POINT(10,10), POINT(5,5), POINT(0,10))), MULTIPOLYGON(POLYGON(LINESTRING(POINT(0,0), POINT(0,10), POINT(10,10), POINT(10,0), POINT(0,0)), LINESTRING(POINT(4,4), POINT(4,6), POINT(6,6), POINT(6,4), POINT(4,4))), POLYGON(LINESTRING(POINT(0,0), POINT(-10,0), POINT(-10,-10), POINT(0,0))))))); -Warnings: -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. -Warning 3195 st_geometryfromwkb(geometry) is deprecated and will be replaced by st_srid(geometry, 0) in a future version. Use st_geometryfromwkb(st_aswkb(geometry), 0) instead. INSERT INTO gis_geometrycollection VALUES (713, ST_GEOMCOLLFROMWKB(ST_ASWKB(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION(' 'POINT(0 0),' @@ -240,33 +186,6 @@ INSERT INTO gis_geometrycollection VALUES 'POLYGON((0 0,0 10,10 10,10 0,0 0)),' 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10),' 'MULTILINESTRING((0 0,10 10),(0 10,10 0)),' - 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5))))')))), -(714, ST_GEOMCOLLFROMWKB(ST_ASWKB(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION(' - 'POINT(0 0)),' - 'GEOMETRYCOLLECTION(' - 'LINESTRING(0 0,10 10)),' - 'GEOMETRYCOLLECTION(' - 'POLYGON((0 0,0 10,10 10,10 0,0 0))),' - 'GEOMETRYCOLLECTION(' - 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10)),' - 'GEOMETRYCOLLECTION(' - 'MULTILINESTRING((0 0,10 10),(0 10,10 0))),' - 'GEOMETRYCOLLECTION(' - 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5)))))')))), -(715, ST_GEOMCOLLFROMWKB(ST_ASWKB(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION(),' - 'POINT(0 0),' - 'GEOMETRYCOLLECTION(' - 'LINESTRING(0 0,10 10),' - 'GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION())),' - 'GEOMETRYCOLLECTION(),' - 'GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION()),' - 'POLYGON((0 0,0 10,10 10,10 0,0 0)),' - 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10),' - 'MULTILINESTRING((0 0,10 10),(0 10,10 0)),' 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5))))')))); # Creating a table with spatial index column CREATE TABLE geom_index (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY NOT NULL, SPATIAL INDEX(g)); diff --git a/mysql-test/suite/innodb_gis/t/gis_split_nan.test b/mysql-test/suite/innodb_gis/t/gis_split_nan.test index 0c55a2104754a..fa45251875c7a 100644 --- a/mysql-test/suite/innodb_gis/t/gis_split_nan.test +++ b/mysql-test/suite/innodb_gis/t/gis_split_nan.test @@ -1,7 +1,6 @@ --source include/have_innodb.inc ---source include/have_debug.inc --source include/have_geometry.inc ---source include/have_innodb_4k.inc +--source include/innodb_page_size.inc ############################################################################################ # Creating the spatial objects # @@ -233,33 +232,6 @@ INSERT INTO gis_geometrycollection VALUES 'POLYGON((0 0,0 10,10 10,10 0,0 0)),' 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10),' 'MULTILINESTRING((0 0,10 10),(0 10,10 0)),' - 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5))))')))), - (714, ST_GEOMCOLLFROMWKB(ST_ASWKB(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION(' - 'POINT(0 0)),' - 'GEOMETRYCOLLECTION(' - 'LINESTRING(0 0,10 10)),' - 'GEOMETRYCOLLECTION(' - 'POLYGON((0 0,0 10,10 10,10 0,0 0))),' - 'GEOMETRYCOLLECTION(' - 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10)),' - 'GEOMETRYCOLLECTION(' - 'MULTILINESTRING((0 0,10 10),(0 10,10 0))),' - 'GEOMETRYCOLLECTION(' - 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5)))))')))), - (715, ST_GEOMCOLLFROMWKB(ST_ASWKB(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION(),' - 'POINT(0 0),' - 'GEOMETRYCOLLECTION(' - 'LINESTRING(0 0,10 10),' - 'GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION())),' - 'GEOMETRYCOLLECTION(),' - 'GEOMETRYCOLLECTION(' - 'GEOMETRYCOLLECTION()),' - 'POLYGON((0 0,0 10,10 10,10 0,0 0)),' - 'MULTIPOINT(0 0,2 2,4 4,6 6,8 8,10 10),' - 'MULTILINESTRING((0 0,10 10),(0 10,10 0)),' 'MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 10,10 10,10 5,5 5))))')))); ############################################################################################ diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result b/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result index 1f3b72ec2c9cc..fb17b0b4312b5 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result @@ -1,5 +1,4 @@ SET default_storage_engine=InnoDB; -set global innodb_file_per_table=1; ### Test 1 ### create table worklog5743(a TEXT not null, primary key (a(768))) ROW_FORMAT=DYNAMIC; show warnings; @@ -105,7 +104,7 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 1982. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx4 on worklog5743_1(a2(434)); +create index idx4 on worklog5743_1(a2(290)); show warnings; Level Code Message create index idx5 on worklog5743_1(a1, a2(430)); @@ -113,27 +112,42 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 1982. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx6 on worklog5743_1(a1, a2(428)); +create index idx6 on worklog5743_1(a1, a2(283)); show warnings; Level Code Message SET sql_mode= ''; +set innodb_strict_mode=off; create index idx1 on worklog5743_2(a2(4000)); -ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 1982. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx3 on worklog5743_2(a2(769)); +Warnings: +Note 1071 Specified key was too long; max key length is 1173 bytes +Warning 139 Row size too large (> 1982). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline. +set innodb_strict_mode=on; show warnings; Level Code Message -create index idx4 on worklog5743_2(a2(768)); +Note 1071 Specified key was too long; max key length is 1173 bytes +Warning 139 Row size too large (> 1982). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline. +show create table worklog5743_2; +Table Create Table +worklog5743_2 CREATE TABLE `worklog5743_2` ( + `a1` int(11) DEFAULT NULL, + `a2` text NOT NULL, + KEY `idx1` (`a2`(1173)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci KEY_BLOCK_SIZE=2 +drop index idx1 on worklog5743_2; +create index idx3 on worklog5743_2(a2(769)); show warnings; Level Code Message -create index idx5 on worklog5743_2(a1, a2(765)); +create index idx4 on worklog5743_2(a2(768)); show warnings; Level Code Message -create index idx6 on worklog5743_2(a1, a2(764)); +create index idx6 on worklog5743_2(a1, a2(768)); show warnings; Level Code Message +set innodb_strict_mode=off; create index idx1 on worklog5743_4(a2(4000)); Warnings: Note 1071 Specified key was too long; max key length is 1173 bytes +set innodb_strict_mode=on; show warnings; Level Code Message Note 1071 Specified key was too long; max key length is 1173 bytes @@ -143,16 +157,13 @@ worklog5743_4 CREATE TABLE `worklog5743_4` ( `a1` int(11) DEFAULT NULL, `a2` text NOT NULL, KEY `idx1` (`a2`(1173)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci KEY_BLOCK_SIZE=4 create index idx3 on worklog5743_4(a2(769)); show warnings; Level Code Message create index idx4 on worklog5743_4(a2(768)); show warnings; Level Code Message -create index idx5 on worklog5743_4(a1, a2(765)); -show warnings; -Level Code Message create index idx6 on worklog5743_4(a1, a2(764)); show warnings; Level Code Message @@ -191,10 +202,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE worklog5743_1 ref idx6 idx6 5 const 1 explain select a1, left(a2, 20) from worklog5743_2 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE worklog5743_2 ref idx5,idx6 idx5 5 const 1 +1 SIMPLE worklog5743_2 ref idx6 idx6 5 const 1 explain select a1, left(a2, 20) from worklog5743_4 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE worklog5743_4 ref idx5,idx6 idx5 5 const 1 +1 SIMPLE worklog5743_4 ref idx6 idx6 5 const 1 select a1, left(a2, 20) from worklog5743_1 where a1 = 9; a1 left(a2, 20) 9 aaaaaaaaaaaaaaaaaaaa @@ -226,7 +237,7 @@ create index idx1 on worklog5743(a2); ERROR 42000: Specified key was too long; max key length is 1173 bytes show warnings; Level Code Message -Warning 1071 Specified key was too long; max key length is 3072 bytes +Note 1071 Specified key was too long; max key length is 3072 bytes Error 1071 Specified key was too long; max key length is 1173 bytes drop table worklog5743; create table worklog5743(a1 int, a2 varchar(3072)) ROW_FORMAT=DYNAMIC; @@ -281,6 +292,8 @@ connection default; rollback; drop table worklog5743; ### Test 6 ### +create table worklog5743(a TEXT not null, primary key (a(1000))); +drop table worklog5743; create table worklog5743(a TEXT) ROW_FORMAT=COMPACT; create index idx on worklog5743(a(768)); ERROR HY000: Index column size too large. The maximum column size is 767 bytes @@ -326,7 +339,7 @@ worklog5743 CREATE TABLE `worklog5743` ( `a` text NOT NULL, KEY `idx1` (`a`(769)), KEY `idx2` (`a`(768)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC insert into worklog5743 values(repeat("a", 768)); drop table worklog5743; create table worklog5743(a TEXT not null) ROW_FORMAT=REDUNDANT; @@ -339,4 +352,3 @@ create index idx on worklog5743(a(768)); ERROR HY000: Index column size too large. The maximum column size is 767 bytes create index idx2 on worklog5743(a(767)); drop table worklog5743; -SET GLOBAL innodb_file_per_table=1; diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result index 3474fb637c23c..0e4f98a410a24 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result @@ -1,5 +1,4 @@ SET default_storage_engine=InnoDB; -set global innodb_file_per_table=1; ### Test 1 ### create table worklog5743(a TEXT not null, primary key (a(1000))) ROW_FORMAT=DYNAMIC; show warnings; @@ -109,7 +108,7 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 4030. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx4 on worklog5743_1(a2(434)); +create index idx4 on worklog5743_1(a2(290)); show warnings; Level Code Message create index idx5 on worklog5743_1(a1, a2(430)); @@ -117,7 +116,7 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 4030. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx6 on worklog5743_1(a1, a2(428)); +create index idx6 on worklog5743_1(a1, a2(283)); show warnings; Level Code Message create index idx2 on worklog5743_2(a2(4000)); @@ -131,7 +130,7 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 4030. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx4 on worklog5743_2(a2(946)); +create index idx4 on worklog5743_2(a2(802)); show warnings; Level Code Message create index idx5 on worklog5743_2(a1, a2(942)); @@ -139,7 +138,7 @@ ERROR 42000: Row size too large. The maximum row size for the used table type, n show warnings; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is 4030. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs -create index idx6 on worklog5743_2(a1, a2(940)); +create index idx6 on worklog5743_2(a1, a2(795)); show warnings; Level Code Message create index idx3 on worklog5743_4(a2(1537)); @@ -362,7 +361,7 @@ worklog5743 CREATE TABLE `worklog5743` ( `a` text NOT NULL, KEY `idx1` (`a`(1536)), KEY `idx2` (`a`(1536)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC drop table worklog5743; create table worklog5743(a TEXT not null) ROW_FORMAT=REDUNDANT; create index idx on worklog5743(a(768)); @@ -374,4 +373,3 @@ create index idx on worklog5743(a(768)); ERROR HY000: Index column size too large. The maximum column size is 767 bytes create index idx2 on worklog5743(a(767)); drop table worklog5743; -SET GLOBAL innodb_file_per_table=1; diff --git a/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test b/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test index 960ad1ebcf590..8b3a2af927c21 100644 --- a/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test +++ b/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test @@ -6,8 +6,6 @@ SET default_storage_engine=InnoDB; --disable_query_log call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is"); -SET @save_innodb_read_only_compressed=@@GLOBAL.innodb_read_only_compressed; -SET GLOBAL innodb_read_only_compressed=OFF; --enable_query_log -- echo ### Test 1 ### @@ -140,38 +138,40 @@ show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx3 on worklog5743_1(a2(436)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx4 on worklog5743_1(a2(434)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx4 on worklog5743_1(a2(290)); show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx5 on worklog5743_1(a1, a2(430)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx6 on worklog5743_1(a1, a2(428)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx6 on worklog5743_1(a1, a2(283)); show warnings; # Test edge cases for indexes using key_block_size=2 SET sql_mode= ''; ---error ER_TOO_BIG_ROWSIZE +set innodb_strict_mode=off; create index idx1 on worklog5743_2(a2(4000)); +set innodb_strict_mode=on; +show warnings; +show create table worklog5743_2; +drop index idx1 on worklog5743_2; create index idx3 on worklog5743_2(a2(769)); show warnings; create index idx4 on worklog5743_2(a2(768)); show warnings; -create index idx5 on worklog5743_2(a1, a2(765)); -show warnings; -create index idx6 on worklog5743_2(a1, a2(764)); +create index idx6 on worklog5743_2(a1, a2(768)); show warnings; # Test edge cases for indexes using key_block_size=4 +set innodb_strict_mode=off; create index idx1 on worklog5743_4(a2(4000)); +set innodb_strict_mode=on; show warnings; show create table worklog5743_4; create index idx3 on worklog5743_4(a2(769)); show warnings; create index idx4 on worklog5743_4(a2(768)); show warnings; -create index idx5 on worklog5743_4(a1, a2(765)); -show warnings; create index idx6 on worklog5743_4(a1, a2(764)); show warnings; SET sql_mode= default; @@ -309,6 +309,9 @@ rollback; drop table worklog5743; -- echo ### Test 6 ### +create table worklog5743(a TEXT not null, primary key (a(1000))); +drop table worklog5743; + create table worklog5743(a TEXT) ROW_FORMAT=COMPACT; # Excercise the column length check in ha_innobase::add_index() @@ -372,7 +375,4 @@ create table worklog5743(a TEXT not null) ROW_FORMAT=COMPACT; -- error ER_INDEX_COLUMN_TOO_LONG create index idx on worklog5743(a(768)); create index idx2 on worklog5743(a(767)); ---disable_query_log -SET GLOBAL innodb_read_only_compressed=@save_innodb_read_only_compressed; ---enable_query_log drop table worklog5743; diff --git a/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test b/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test index 23fb37e8d7389..cc41b13db074d 100644 --- a/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test +++ b/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test @@ -6,8 +6,6 @@ SET default_storage_engine=InnoDB; --disable_query_log call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is"); -SET @save_innodb_read_only_compressed=@@GLOBAL.innodb_read_only_compressed; -SET GLOBAL innodb_read_only_compressed=OFF; --enable_query_log -- echo ### Test 1 ### @@ -142,14 +140,14 @@ show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx3 on worklog5743_1(a2(436)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx4 on worklog5743_1(a2(434)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx4 on worklog5743_1(a2(290)); show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx5 on worklog5743_1(a1, a2(430)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx6 on worklog5743_1(a1, a2(428)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx6 on worklog5743_1(a1, a2(283)); show warnings; # Test edge cases for indexes using key_block_size=2 @@ -159,14 +157,14 @@ show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx3 on worklog5743_2(a2(948)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx4 on worklog5743_2(a2(946)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx4 on worklog5743_2(a2(802)); show warnings; -- error ER_TOO_BIG_ROWSIZE create index idx5 on worklog5743_2(a1, a2(942)); show warnings; -# Bug#13391353 Limit is one byte less on on 32bit-Linux only -create index idx6 on worklog5743_2(a1, a2(940)); +# MDEV-27634 innodb_zip tests failing on s390x +create index idx6 on worklog5743_2(a1, a2(795)); show warnings; # Test edge cases for indexes using key_block_size=4 @@ -394,7 +392,4 @@ create table worklog5743(a TEXT not null) ROW_FORMAT=COMPACT; -- error ER_INDEX_COLUMN_TOO_LONG create index idx on worklog5743(a(768)); create index idx2 on worklog5743(a(767)); ---disable_query_log -SET GLOBAL innodb_read_only_compressed=@save_innodb_read_only_compressed; ---enable_query_log drop table worklog5743; diff --git a/mysql-test/suite/mariabackup/data_directory.result b/mysql-test/suite/mariabackup/data_directory.result index 4e45127bd6a7c..8692c35239e6e 100644 --- a/mysql-test/suite/mariabackup/data_directory.result +++ b/mysql-test/suite/mariabackup/data_directory.result @@ -11,3 +11,9 @@ SELECT * FROM t; a 1 DROP TABLE t; +# +# MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +# +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/mariabackup/data_directory.test b/mysql-test/suite/mariabackup/data_directory.test index a89b7bdccc472..ffb3ab3073c5e 100644 --- a/mysql-test/suite/mariabackup/data_directory.test +++ b/mysql-test/suite/mariabackup/data_directory.test @@ -21,4 +21,19 @@ rmdir $table_data_dir; SELECT * FROM t; DROP TABLE t; rmdir $targetdir; + +--echo # +--echo # MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +--echo # +let $DATADIR= `select @@datadir`; +chmod 0000 $DATADIR/ibdata1; +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +chmod 0755 $DATADIR/ibdata1; rmdir $table_data_dir; +rmdir $targetdir; +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/suite/parts/r/alter_table.result b/mysql-test/suite/parts/r/alter_table.result index b887cea36f098..fa458c977c211 100644 --- a/mysql-test/suite/parts/r/alter_table.result +++ b/mysql-test/suite/parts/r/alter_table.result @@ -344,3 +344,17 @@ connection default; drop database EXISTENT; drop user alan; drop tables t1, tp1, tp2, tp4; +# +# MDEV-31014 Database privileges are insufficient for CONVERT TABLE TO PARTITION +# +create database db; +create user u@localhost; +grant all on db.* to u@localhost; +connect con1,localhost,u,,db; +create table t1 (a int) partition by range(a) (p1 values less than (100), p2 values less than (1000)); +alter table t1 convert partition p2 to table tp; +alter table t1 convert table tp to partition p2 values less than (1000); +disconnect con1; +connection default; +drop user u@localhost; +drop database db; diff --git a/mysql-test/suite/parts/t/alter_table.test b/mysql-test/suite/parts/t/alter_table.test index 741a9450c8ef5..9b75add3afa1b 100644 --- a/mysql-test/suite/parts/t/alter_table.test +++ b/mysql-test/suite/parts/t/alter_table.test @@ -301,3 +301,21 @@ alter table t1 convert partition p1 to table tp1; drop database EXISTENT; drop user alan; drop tables t1, tp1, tp2, tp4; + +--echo # +--echo # MDEV-31014 Database privileges are insufficient for CONVERT TABLE TO PARTITION +--echo # +create database db; +create user u@localhost; +grant all on db.* to u@localhost; + +--connect (con1,localhost,u,,db) +create table t1 (a int) partition by range(a) (p1 values less than (100), p2 values less than (1000)); +alter table t1 convert partition p2 to table tp; +alter table t1 convert table tp to partition p2 values less than (1000); + +# Cleanup +--disconnect con1 +--connection default +drop user u@localhost; +drop database db; diff --git a/mysql-test/suite/perfschema/r/privilege_table_io.result b/mysql-test/suite/perfschema/r/privilege_table_io.result index 6dd885281b3a1..8be4b9583eca0 100644 --- a/mysql-test/suite/perfschema/r/privilege_table_io.result +++ b/mysql-test/suite/perfschema/r/privilege_table_io.result @@ -122,6 +122,8 @@ wait/io/table/sql/handler TABLE mysql db fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 +wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 +wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql roles_mapping fetch 1 wait/io/table/sql/handler TABLE mysql tables_priv fetch 1 wait/io/table/sql/handler TABLE mysql tables_priv fetch 1 diff --git a/mysql-test/suite/plugins/t/show_all_plugins.test b/mysql-test/suite/plugins/t/show_all_plugins.test index 77723d3217007..171bcc93bbddc 100644 --- a/mysql-test/suite/plugins/t/show_all_plugins.test +++ b/mysql-test/suite/plugins/t/show_all_plugins.test @@ -1,7 +1,7 @@ +--source include/have_udf.inc if (!$DIALOG_EXAMPLES_SO) { skip requires dialog_examples.so; } if (!$HA_EXAMPLE_SO) { skip requires ha_examples.so; } if (!$LIBDAEMON_EXAMPLE_SO) { skip requires libdaemon_examples.so; } -if (!$UDF_EXAMPLE_SO) { skip requires udf_example.so; } if (!$EXAMPLE_KEY_MANAGEMENT_SO) { skip requires example_key_management.so; } if (`SELECT VERSION() LIKE '%embedded%'`) { skip Disabled for embedded until MDEV-8664 is resolved; } diff --git a/mysql-test/suite/roles/acl_statistics.result b/mysql-test/suite/roles/acl_statistics.result index c60e0297af362..003bc263b7321 100644 --- a/mysql-test/suite/roles/acl_statistics.result +++ b/mysql-test/suite/roles/acl_statistics.result @@ -6,7 +6,7 @@ Acl_function_grants 0 Acl_procedure_grants 0 Acl_package_spec_grants 0 Acl_package_body_grants 0 -Acl_proxy_users 2 +Acl_proxy_users 4 Acl_role_grants 0 Acl_roles 0 Acl_table_grants 1 @@ -25,7 +25,7 @@ PROCEDURE_GRANTS 0 SELECT count(*) PROXY_USERS from mysql.proxies_priv; PROXY_USERS -2 +4 SELECT count(*) ROLE_GRANTS from mysql.roles_mapping; ROLE_GRANTS 0 @@ -71,7 +71,7 @@ Acl_function_grants 3 Acl_procedure_grants 2 Acl_package_spec_grants 0 Acl_package_body_grants 0 -Acl_proxy_users 3 +Acl_proxy_users 5 Acl_role_grants 4 Acl_roles 2 Acl_table_grants 3 @@ -90,7 +90,7 @@ PROCEDURE_GRANTS 2 SELECT count(*) PROXY_USERS from mysql.proxies_priv; PROXY_USERS -3 +5 SELECT count(*) ROLE_GRANTS from mysql.roles_mapping; ROLE_GRANTS 4 diff --git a/mysql-test/suite/rpl/my.cnf b/mysql-test/suite/rpl/my.cnf index 74233b056c730..d61e32ed51a59 100644 --- a/mysql-test/suite/rpl/my.cnf +++ b/mysql-test/suite/rpl/my.cnf @@ -1,8 +1,8 @@ # Use settings from rpl_1slave_base.cnf # add setting to connect the slave to the master by default !include rpl_1slave_base.cnf -!include include/default_client.cnf - - -[mysqld.2] - +# Override specific server settings using [mariadb-x.y] option group +# from `test.cnf` file right after including this file. +# E.g. after !include ../my.cnf, in your `test.cnf`, specify your configuration +# in option group e.g [mysqld.x], so that number `x` corresponds to the number +# in the rpl server topology. diff --git a/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result b/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result index f3cffb6c4d8c6..621097e9ff876 100644 --- a/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result +++ b/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result @@ -28,8 +28,8 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, @@ -48,15 +48,15 @@ slow_log CREATE TABLE `slow_log` ( `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, `db` varchar(512) NOT NULL, `last_insert_id` int(11) NOT NULL, `insert_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, `sql_text` mediumtext NOT NULL, `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL + `rows_affected` bigint(20) unsigned NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='Slow log' SET GLOBAL general_log = 'OFF'; SET GLOBAL slow_query_log = 'OFF'; diff --git a/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result b/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result new file mode 100644 index 0000000000000..b14f7b0154123 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result @@ -0,0 +1,48 @@ +include/master-slave.inc +[connection master] +connection master; +create table t1 (a int primary key, b int) engine=innodb; +insert t1 values (1,1); +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +include/stop_slave.inc +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; +set @save_slave_trans_retries= @@global.slave_transaction_retries; +set @@global.innodb_lock_wait_timeout= 1; +set @@global.slave_transaction_retries= 0; +connection master; +update t1 set b=b+10 where a=1; +include/save_master_gtid.inc +connection slave1; +BEGIN; +SELECT * FROM t1 WHERE a=1 FOR UPDATE; +a b +1 1 +connection slave; +include/start_slave.inc +include/wait_for_slave_sql_error.inc [errno=1205] +connection slave1; +ROLLBACK; +connection slave; +set @save_dbug = @@global.debug_dbug; +set @@global.debug_dbug= "+d,delay_sql_thread_after_release_run_lock"; +include/start_slave.inc +set debug_sync= "now wait_for sql_thread_run_lock_released"; +# Validating that the SQL thread is running.. +# ..success +# Validating that Last_SQL_Errno is cleared.. +# ..success +set debug_sync= "now signal sql_thread_continue"; +set @@global.debug_dbug= @saved_dbug; +set debug_sync= "RESET"; +# Cleanup +connection master; +drop table t1; +connection slave; +include/stop_slave.inc +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; +set @@global.slave_transaction_retries= @save_slave_trans_retries; +include/start_slave.inc +include/rpl_end.inc +# End of rpl_sql_thd_start_errno_cleared.test diff --git a/mysql-test/suite/rpl/r/rpl_xa_prepare_gtid_fail.result b/mysql-test/suite/rpl/r/rpl_xa_prepare_gtid_fail.result index f3fecbda34953..dd0d132471e04 100644 --- a/mysql-test/suite/rpl/r/rpl_xa_prepare_gtid_fail.result +++ b/mysql-test/suite/rpl/r/rpl_xa_prepare_gtid_fail.result @@ -2,14 +2,14 @@ include/master-slave.inc [connection master] connection slave; include/stop_slave.inc +set @save_par_thds= @@global.slave_parallel_threads; +set @save_strict_mode= @@global.gtid_strict_mode; +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; change master to master_use_gtid=slave_pos; set @@global.slave_parallel_threads= 4; set @@global.slave_parallel_mode= optimistic; set @@global.gtid_strict_mode=ON; -set sql_log_bin= 0; -alter table mysql.gtid_slave_pos engine=innodb; -call mtr.add_suppression("Deadlock found.*"); -set sql_log_bin= 1; +set statement sql_log_bin=0 for alter table mysql.gtid_slave_pos engine=innodb; include/start_slave.inc connection master; create table t1 (a int primary key, b int) engine=innodb; @@ -27,25 +27,25 @@ xa end '1'; xa prepare '1'; xa commit '1'; include/save_master_gtid.inc -connection slave; connection slave1; BEGIN; SELECT * FROM mysql.gtid_slave_pos WHERE seq_no=100 FOR UPDATE; domain_id sub_id server_id seq_no connection slave; include/start_slave.inc -include/wait_for_slave_sql_error.inc [errno=1942,1213] +include/wait_for_slave_sql_error.inc [errno=1942] +include/stop_slave_io.inc connection slave1; ROLLBACK; # Cleanup connection master; drop table t1; connection slave; -include/stop_slave.inc +# TODO: Remove after fixing MDEV-21777 set @@global.gtid_slave_pos= "0-1-100"; -set @@global.slave_parallel_threads= 0; -set @@global.gtid_strict_mode= 0; -set @@global.innodb_lock_wait_timeout= 50; +set @@global.slave_parallel_threads= @save_par_thds; +set @@global.gtid_strict_mode= @save_strict_mode; +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; include/start_slave.inc include/rpl_end.inc # End of rpl_xa_prepare_gtid_fail.test diff --git a/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test new file mode 100644 index 0000000000000..f6dcfd91409f8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test @@ -0,0 +1,93 @@ +# +# Ensure that when the slave restarts, the last error code displayed by +# SHOW SLAVE STATUS is cleared before Slave_SQL_Running is set. +# +# To ensure that, this test uses the debug_sync mechanism to pause an errored +# and restarting slave's SQL thread after it has set its running state to YES, +# and then ensures that Last_SQL_Errno is 0. The slave error is a forced innodb +# row lock timeout. +# +# +# References +# MDEV-31177: SHOW SLAVE STATUS Last_SQL_Errno Race Condition on Errored +# Slave Restart +# +source include/have_binlog_format_row.inc; +source include/have_innodb.inc; +source include/have_debug.inc; +source include/have_debug_sync.inc; +source include/master-slave.inc; + +--connection master +create table t1 (a int primary key, b int) engine=innodb; +insert t1 values (1,1); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; +set @save_slave_trans_retries= @@global.slave_transaction_retries; +set @@global.innodb_lock_wait_timeout= 1; +set @@global.slave_transaction_retries= 0; + +--connection master +update t1 set b=b+10 where a=1; +--source include/save_master_gtid.inc + +--connection slave1 +BEGIN; +--eval SELECT * FROM t1 WHERE a=1 FOR UPDATE + +--connection slave +--source include/start_slave.inc + +--let $slave_sql_errno= 1205 +--source include/wait_for_slave_sql_error.inc + +--connection slave1 +ROLLBACK; + +--connection slave +set @save_dbug = @@global.debug_dbug; +set @@global.debug_dbug= "+d,delay_sql_thread_after_release_run_lock"; +--source include/start_slave.inc +set debug_sync= "now wait_for sql_thread_run_lock_released"; + +--let $sql_running = query_get_value("SHOW SLAVE STATUS", Slave_SQL_Running, 1) +--echo # Validating that the SQL thread is running.. +if (`SELECT strcmp("$sql_running", "YES") != 0`) +{ + --echo # ..failed + --echo # Slave_SQL_Running: $sql_running + --die Slave SQL thread is not running +} +--echo # ..success + +--let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1) +--echo # Validating that Last_SQL_Errno is cleared.. +if ($last_error) +{ + --echo # ..failed + --echo # Last_SQL_Errno: $last_error + --die SHOW SLAVE STATUS shows the error from the last session on startup +} +--echo # ..success + +set debug_sync= "now signal sql_thread_continue"; + +set @@global.debug_dbug= @saved_dbug; +set debug_sync= "RESET"; + +--echo # Cleanup +--connection master +drop table t1; + +--connection slave +--source include/stop_slave.inc +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; +set @@global.slave_transaction_retries= @save_slave_trans_retries; +--source include/start_slave.inc + +--source include/rpl_end.inc +--echo # End of rpl_sql_thd_start_errno_cleared.test diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test b/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test index 8042b355754f5..aa1b088ed232c 100644 --- a/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test +++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_gtid_fail.test @@ -6,8 +6,8 @@ # GTID slave state, then the slave should immediately quit in error, without # retry. # -# This tests validates the above behavior by simulating a deadlock on the -# GTID slave state table during the second part of XA PREPARE's commit, to +# This tests validates the above behavior by forcing a lock-wait timeout on +# the GTID slave state table during the second part of XA PREPARE's commit, to # ensure that the appropriate error is reported and the transaction was never # retried. # @@ -23,23 +23,19 @@ source include/have_innodb.inc; --connection slave --source include/stop_slave.inc ---let $save_par_thds= `SELECT @@global.slave_parallel_threads` ---let $save_strict_mode= `SELECT @@global.gtid_strict_mode` ---let $save_innodb_lock_wait_timeout= `SELECT @@global.innodb_lock_wait_timeout` +set @save_par_thds= @@global.slave_parallel_threads; +set @save_strict_mode= @@global.gtid_strict_mode; +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; change master to master_use_gtid=slave_pos; set @@global.slave_parallel_threads= 4; set @@global.slave_parallel_mode= optimistic; set @@global.gtid_strict_mode=ON; -set sql_log_bin= 0; -alter table mysql.gtid_slave_pos engine=innodb; -call mtr.add_suppression("Deadlock found.*"); -set sql_log_bin= 1; +set statement sql_log_bin=0 for alter table mysql.gtid_slave_pos engine=innodb; --source include/start_slave.inc --connection master -let $datadir= `select @@datadir`; create table t1 (a int primary key, b int) engine=innodb; insert t1 values (1,1); --source include/save_master_gtid.inc @@ -64,11 +60,6 @@ xa prepare '1'; xa commit '1'; --source include/save_master_gtid.inc - ---connection slave - -#--eval set statement sql_log_bin=0 for insert into mysql.gtid_slave_pos values ($gtid_domain_id, 5, $gtid_server_id, $xap_seq_no) - --connection slave1 BEGIN; --eval SELECT * FROM mysql.gtid_slave_pos WHERE seq_no=$xap_seq_no FOR UPDATE @@ -76,9 +67,14 @@ BEGIN; --connection slave --source include/start_slave.inc ---let $slave_sql_errno= 1942,1213 +--let $slave_sql_errno= 1942 --source include/wait_for_slave_sql_error.inc +# TODO: Remove after fixing MDEV-21777 +# Stop the IO thread too, so the existing relay logs are force purged on slave +# restart, as to not re-execute the already-prepared transaction +--source include/stop_slave_io.inc + --let $retried_tx_test= query_get_value(SHOW ALL SLAVES STATUS, Retried_transactions, 1) if ($retried_tx_initial != $retried_tx_test) { @@ -95,11 +91,11 @@ ROLLBACK; drop table t1; --connection slave ---source include/stop_slave.inc +--echo # TODO: Remove after fixing MDEV-21777 --eval set @@global.gtid_slave_pos= "$new_gtid" ---eval set @@global.slave_parallel_threads= $save_par_thds ---eval set @@global.gtid_strict_mode= $save_strict_mode ---eval set @@global.innodb_lock_wait_timeout= $save_innodb_lock_wait_timeout +set @@global.slave_parallel_threads= @save_par_thds; +set @@global.gtid_strict_mode= @save_strict_mode; +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; --source include/start_slave.inc --source include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/log_slow_verbosity_basic.result b/mysql-test/suite/sys_vars/r/log_slow_verbosity_basic.result new file mode 100644 index 0000000000000..e5dcc8fcafec7 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/log_slow_verbosity_basic.result @@ -0,0 +1,98 @@ +SET @start_global_value = @@global.log_slow_verbosity; +select @@global.log_slow_verbosity = @@session.log_slow_verbosity; +@@global.log_slow_verbosity = @@session.log_slow_verbosity +1 +SET @@global.log_slow_verbosity="",@@session.log_slow_verbosity=""; +show global variables like 'log_slow_verbosity'; +Variable_name Value +log_slow_verbosity +show session variables like 'log_slow_verbosity'; +Variable_name Value +log_slow_verbosity +select * from information_schema.global_variables where variable_name='log_slow_verbosity'; +VARIABLE_NAME VARIABLE_VALUE +LOG_SLOW_VERBOSITY +select * from information_schema.session_variables where variable_name='log_slow_verbosity'; +VARIABLE_NAME VARIABLE_VALUE +LOG_SLOW_VERBOSITY +set global log_slow_verbosity=1; +select @@global.log_slow_verbosity; +@@global.log_slow_verbosity +innodb +set session log_slow_verbosity=1; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb +set session log_slow_verbosity=1; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb +set session log_slow_verbosity=2; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +query_plan +set session log_slow_verbosity=3; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb,query_plan +set session log_slow_verbosity=4; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +explain +set session log_slow_verbosity=5; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb,explain +set session log_slow_verbosity=6; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +query_plan,explain +set session log_slow_verbosity=7; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb,query_plan,explain +set session log_slow_verbosity=8; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +engine +set session log_slow_verbosity=16; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +warnings +set session log_slow_verbosity=32; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +full +set session log_slow_verbosity='innodb'; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb +set session log_slow_verbosity='query_plan'; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +query_plan +set session log_slow_verbosity='innodb,query_plan'; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb,query_plan +set session log_slow_verbosity='explain'; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +explain +set session log_slow_verbosity='innodb,query_plan,explain,engine,warnings,full'; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity +innodb,query_plan,explain,engine,warnings,full +set session log_slow_verbosity=''; +select @@session.log_slow_verbosity; +@@session.log_slow_verbosity + +set session log_slow_verbosity=1.1; +ERROR 42000: Incorrect argument type to variable 'log_slow_verbosity' +set session log_slow_verbosity=1e1; +ERROR 42000: Incorrect argument type to variable 'log_slow_verbosity' +set session log_slow_verbosity="foo"; +ERROR 42000: Variable 'log_slow_verbosity' can't be set to the value of 'foo' +set session log_slow_verbosity=64; +ERROR 42000: Variable 'log_slow_verbosity' can't be set to the value of '64' +SET @@global.log_slow_verbosity = @start_global_value; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index b7f9147556e6b..1ba2756f397ff 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,6 +1,4 @@ ---- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result -+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result -@@ -44,7 +44,7 @@ READ_ONLY NO +@@ -44,7 +44,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -9,7 +7,7 @@ VARIABLE_COMMENT Block size to be used for Aria index pages. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 32768 -@@ -54,7 +54,7 @@ READ_ONLY YES +@@ -54,7 +54,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -18,7 +16,7 @@ VARIABLE_COMMENT Interval between tries to do an automatic checkpoints. In seconds; 0 means 'no automatic checkpoints' which makes sense only for testing. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -64,7 +64,7 @@ READ_ONLY NO +@@ -64,7 +64,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_LOG_ACTIVITY VARIABLE_SCOPE GLOBAL @@ -27,7 +25,7 @@ VARIABLE_COMMENT Number of bytes that the transaction log has to grow between checkpoints before a new checkpoint is written to the log. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -84,7 +84,7 @@ READ_ONLY NO +@@ -84,7 +84,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_FORCE_START_AFTER_RECOVERY_FAILURES VARIABLE_SCOPE GLOBAL @@ -36,7 +34,7 @@ VARIABLE_COMMENT Number of consecutive log recovery failures after which logs will be automatically deleted to cure the problem; 0 (the default) disables the feature. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -104,7 +104,7 @@ READ_ONLY NO +@@ -104,7 +104,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -45,7 +43,7 @@ VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -114,7 +114,7 @@ READ_ONLY NO +@@ -124,7 +124,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_LOG_FILE_SIZE VARIABLE_SCOPE GLOBAL @@ -54,7 +52,7 @@ VARIABLE_COMMENT Limit for transaction log size NUMERIC_MIN_VALUE 8388608 NUMERIC_MAX_VALUE 4294967295 -@@ -144,10 +144,10 @@ READ_ONLY NO +@@ -154,10 +154,10 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_AGE_THRESHOLD VARIABLE_SCOPE GLOBAL @@ -67,7 +65,7 @@ NUMERIC_BLOCK_SIZE 100 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -164,7 +164,7 @@ READ_ONLY YES +@@ -174,7 +174,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_DIVISION_LIMIT VARIABLE_SCOPE GLOBAL @@ -76,7 +74,7 @@ VARIABLE_COMMENT The minimum percentage of warm blocks in key cache NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100 -@@ -174,7 +174,7 @@ READ_ONLY NO +@@ -184,7 +184,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_FILE_HASH_SIZE VARIABLE_SCOPE GLOBAL @@ -85,7 +83,7 @@ VARIABLE_COMMENT Number of hash buckets for open and changed files. If you have a lot of Aria files open you should increase this for faster flush of changes. A good value is probably 1/10 of number of possible open Aria files. NUMERIC_MIN_VALUE 128 NUMERIC_MAX_VALUE 16384 -@@ -204,7 +204,7 @@ READ_ONLY NO +@@ -214,7 +214,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -94,7 +92,7 @@ VARIABLE_COMMENT Number of threads to use when repairing Aria tables. The value of 1 disables parallel repair. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -217,7 +217,7 @@ VARIABLE_SCOPE SESSION +@@ -227,7 +227,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE. NUMERIC_MIN_VALUE 16376 @@ -103,7 +101,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -274,7 +274,7 @@ READ_ONLY NO +@@ -284,7 +284,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_INCREMENT VARIABLE_SCOPE SESSION @@ -112,7 +110,7 @@ VARIABLE_COMMENT Auto-increment columns are incremented by this NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -284,7 +284,7 @@ READ_ONLY NO +@@ -294,7 +294,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_OFFSET VARIABLE_SCOPE SESSION @@ -121,7 +119,7 @@ VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -294,7 +294,7 @@ READ_ONLY NO +@@ -304,7 +304,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME BACK_LOG VARIABLE_SCOPE GLOBAL @@ -130,7 +128,7 @@ VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -347,7 +347,7 @@ VARIABLE_SCOPE GLOBAL +@@ -357,7 +357,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance NUMERIC_MIN_VALUE 4096 @@ -139,7 +137,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -364,20 +364,20 @@ READ_ONLY NO +@@ -374,20 +374,20 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME BINLOG_COMMIT_WAIT_COUNT VARIABLE_SCOPE GLOBAL @@ -164,7 +162,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -394,7 +394,7 @@ READ_ONLY NO +@@ -404,7 +404,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME BINLOG_EXPIRE_LOGS_SECONDS VARIABLE_SCOPE GLOBAL @@ -173,7 +171,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after binlog_expire_logs_seconds seconds; It and expire_logs_days are linked, such that changes in one are converted into the other. Possible purges happen at startup and at binary log rotation. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8553600 -@@ -407,7 +407,7 @@ VARIABLE_SCOPE GLOBAL +@@ -417,7 +417,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of file cache for the binary log NUMERIC_MIN_VALUE 8192 @@ -182,7 +180,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -457,7 +457,7 @@ VARIABLE_SCOPE GLOBAL +@@ -467,7 +467,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance. NUMERIC_MIN_VALUE 4096 @@ -191,7 +189,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -467,7 +467,7 @@ VARIABLE_SCOPE SESSION +@@ -477,7 +477,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread! NUMERIC_MIN_VALUE 0 @@ -200,7 +198,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -654,7 +654,7 @@ READ_ONLY NO +@@ -664,7 +664,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME CONNECT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -209,7 +207,7 @@ VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 31536000 -@@ -704,7 +704,7 @@ READ_ONLY YES +@@ -714,7 +714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_LONG VARIABLE_SCOPE SESSION @@ -218,7 +216,7 @@ VARIABLE_COMMENT Long search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 33 -@@ -714,7 +714,7 @@ READ_ONLY NO +@@ -724,7 +724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_SHORT VARIABLE_SCOPE SESSION @@ -227,7 +225,7 @@ VARIABLE_COMMENT Short search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 32 -@@ -724,7 +724,7 @@ READ_ONLY NO +@@ -734,7 +734,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_LONG VARIABLE_SCOPE SESSION @@ -236,7 +234,7 @@ VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -734,7 +734,7 @@ READ_ONLY NO +@@ -744,7 +744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_SHORT VARIABLE_SCOPE SESSION @@ -245,7 +243,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -784,7 +784,7 @@ READ_ONLY NO +@@ -794,7 +794,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_WEEK_FORMAT VARIABLE_SCOPE SESSION @@ -254,7 +252,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -794,7 +794,7 @@ READ_ONLY NO +@@ -804,7 +804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_LIMIT VARIABLE_SCOPE GLOBAL @@ -263,7 +261,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -804,7 +804,7 @@ READ_ONLY NO +@@ -814,7 +814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -272,7 +270,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -814,7 +814,7 @@ READ_ONLY NO +@@ -824,7 +824,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_QUEUE_SIZE VARIABLE_SCOPE GLOBAL @@ -281,7 +279,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -844,7 +844,7 @@ READ_ONLY NO +@@ -854,7 +854,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DIV_PRECISION_INCREMENT VARIABLE_SCOPE SESSION @@ -290,7 +288,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -954,7 +954,7 @@ READ_ONLY YES +@@ -964,7 +964,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -299,7 +297,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -984,7 +984,7 @@ READ_ONLY NO +@@ -994,7 +994,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME FLUSH_TIME VARIABLE_SCOPE GLOBAL @@ -308,7 +306,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1014,7 +1014,7 @@ READ_ONLY NO +@@ -1024,7 +1024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MAX_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -317,7 +315,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1024,7 +1024,7 @@ READ_ONLY YES +@@ -1034,7 +1034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MIN_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -326,7 +324,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -1034,7 +1034,7 @@ READ_ONLY YES +@@ -1044,7 +1044,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT VARIABLE_SCOPE GLOBAL @@ -335,7 +333,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1204,7 +1204,7 @@ READ_ONLY YES +@@ -1214,7 +1214,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HISTOGRAM_SIZE VARIABLE_SCOPE SESSION @@ -344,7 +342,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1234,7 +1234,7 @@ READ_ONLY YES +@@ -1244,7 +1244,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HOST_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -353,7 +351,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1344,7 +1344,7 @@ READ_ONLY NO +@@ -1354,7 +1354,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME INTERACTIVE_TIMEOUT VARIABLE_SCOPE SESSION @@ -362,7 +360,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1377,7 +1377,7 @@ VARIABLE_SCOPE SESSION +@@ -1387,7 +1387,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -371,7 +369,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1394,7 +1394,7 @@ READ_ONLY NO +@@ -1404,7 +1404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME JOIN_CACHE_LEVEL VARIABLE_SCOPE SESSION @@ -380,7 +378,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1417,7 +1417,7 @@ VARIABLE_SCOPE GLOBAL +@@ -1427,7 +1427,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -389,7 +387,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1574,7 +1574,7 @@ READ_ONLY YES +@@ -1584,7 +1584,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOCK_WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -398,7 +396,16 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1694,7 +1694,7 @@ READ_ONLY NO +@@ -1704,7 +1704,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME LOG_SLOW_MAX_WARNINGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1000 +@@ -1714,7 +1714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -407,7 +414,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1734,7 +1734,7 @@ READ_ONLY NO +@@ -1754,7 +1754,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -416,7 +423,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1764,7 +1764,7 @@ READ_ONLY NO +@@ -1784,7 +1784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION @@ -425,7 +432,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1814,7 +1814,7 @@ READ_ONLY NO +@@ -1834,7 +1834,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -434,7 +441,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1827,14 +1827,14 @@ VARIABLE_SCOPE GLOBAL +@@ -1847,14 +1847,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the transactional cache NUMERIC_MIN_VALUE 4096 @@ -451,7 +458,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1847,14 +1847,14 @@ VARIABLE_SCOPE GLOBAL +@@ -1867,14 +1867,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the statement cache NUMERIC_MIN_VALUE 4096 @@ -468,7 +475,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -1864,7 +1864,7 @@ READ_ONLY NO +@@ -1884,7 +1884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -477,7 +484,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1874,7 +1874,7 @@ READ_ONLY NO +@@ -1894,7 +1894,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -486,7 +493,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1894,7 +1894,7 @@ READ_ONLY YES +@@ -1914,7 +1914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -495,7 +502,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -1907,14 +1907,14 @@ VARIABLE_SCOPE SESSION +@@ -1927,14 +1927,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -512,7 +519,7 @@ VARIABLE_COMMENT Alias for max_delayed_threads. Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1934,7 +1934,7 @@ READ_ONLY NO +@@ -1954,7 +1954,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -521,7 +528,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1964,7 +1964,7 @@ READ_ONLY NO +@@ -1984,7 +1984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -530,7 +537,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1977,14 +1977,14 @@ VARIABLE_SCOPE SESSION +@@ -1997,14 +1997,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum size of the container of a rowid filter NUMERIC_MIN_VALUE 1024 @@ -547,7 +554,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2004,7 +2004,7 @@ READ_ONLY NO +@@ -2024,7 +2024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION @@ -556,7 +563,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -2014,7 +2014,7 @@ READ_ONLY NO +@@ -2034,7 +2034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -565,7 +572,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2034,7 +2034,7 @@ READ_ONLY NO +@@ -2054,7 +2054,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -574,7 +581,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2054,7 +2054,7 @@ READ_ONLY NO +@@ -2074,7 +2074,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -583,7 +590,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2064,7 +2064,7 @@ READ_ONLY NO +@@ -2084,7 +2084,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -592,7 +599,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2074,7 +2074,7 @@ READ_ONLY YES +@@ -2094,7 +2094,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -601,7 +608,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2084,7 +2084,7 @@ READ_ONLY YES +@@ -2104,7 +2104,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -610,7 +617,7 @@ VARIABLE_COMMENT Alias for log_slow_min_examined_row_limit. Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2094,7 +2094,7 @@ READ_ONLY NO +@@ -2114,7 +2114,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -619,7 +626,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2104,7 +2104,7 @@ READ_ONLY NO +@@ -2124,7 +2124,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -628,7 +635,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2114,7 +2114,7 @@ READ_ONLY YES +@@ -2134,7 +2134,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -637,7 +644,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2137,7 +2137,7 @@ VARIABLE_SCOPE GLOBAL +@@ -2157,7 +2157,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Restricts the total memory used for memory mapping of MySQL tables NUMERIC_MIN_VALUE 7 @@ -646,7 +653,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2154,10 +2154,10 @@ READ_ONLY YES +@@ -2174,10 +2174,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -659,7 +666,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2167,7 +2167,7 @@ VARIABLE_SCOPE SESSION +@@ -2187,7 +2187,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -668,7 +675,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2204,7 +2204,7 @@ READ_ONLY NO +@@ -2224,7 +2224,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME NET_BUFFER_LENGTH VARIABLE_SCOPE SESSION @@ -677,7 +684,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2214,7 +2214,7 @@ READ_ONLY NO +@@ -2234,7 +2234,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -686,7 +693,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2224,7 +2224,7 @@ READ_ONLY NO +@@ -2244,7 +2244,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -695,7 +702,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2234,7 +2234,7 @@ READ_ONLY NO +@@ -2254,7 +2254,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -704,7 +711,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2284,7 +2284,7 @@ READ_ONLY NO +@@ -2314,7 +2314,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -713,7 +720,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2294,7 +2294,7 @@ READ_ONLY YES +@@ -2324,7 +2324,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_EXTRA_PRUNING_DEPTH VARIABLE_SCOPE SESSION @@ -722,7 +729,16 @@ VARIABLE_COMMENT If the optimizer needs to enumerate join prefix of this size or larger, then it will try aggressively prune away the search space. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2304,17 +2304,17 @@ READ_ONLY NO +@@ -2334,7 +2334,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2344,7 +2344,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION @@ -730,11 +746,8 @@ +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO + NUMERIC_MAX_VALUE 4294967295 +@@ -2354,7 +2354,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -743,7 +756,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search: 1 - prune plans based on cost and number of retrieved rows eq_ref: 2 - prune also if we find an eq_ref chain NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2 -@@ -2324,7 +2324,7 @@ READ_ONLY NO +@@ -2364,7 +2364,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -752,7 +765,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2334,7 +2334,7 @@ READ_ONLY NO +@@ -2374,7 +2374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -761,7 +774,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2364,17 +2364,17 @@ READ_ONLY NO +@@ -2404,17 +2404,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -782,7 +795,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2394,7 +2394,7 @@ READ_ONLY YES +@@ -2434,7 +2434,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -791,7 +804,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2404,7 +2404,7 @@ READ_ONLY YES +@@ -2444,7 +2444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -800,7 +813,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2414,7 +2414,7 @@ READ_ONLY YES +@@ -2454,7 +2454,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -809,7 +822,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2424,7 +2424,7 @@ READ_ONLY YES +@@ -2464,7 +2464,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -818,7 +831,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2434,7 +2434,7 @@ READ_ONLY YES +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -827,7 +840,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2444,7 +2444,7 @@ READ_ONLY YES +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -836,7 +849,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2454,7 +2454,7 @@ READ_ONLY YES +@@ -2494,7 +2494,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -845,7 +858,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2464,7 +2464,7 @@ READ_ONLY YES +@@ -2504,7 +2504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -854,7 +867,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2474,7 +2474,7 @@ READ_ONLY YES +@@ -2514,7 +2514,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -863,7 +876,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2484,7 +2484,7 @@ READ_ONLY YES +@@ -2524,7 +2524,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -872,7 +885,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2494,7 +2494,7 @@ READ_ONLY YES +@@ -2534,7 +2534,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -881,7 +894,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2504,7 +2504,7 @@ READ_ONLY YES +@@ -2544,7 +2544,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -890,7 +903,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2514,7 +2514,7 @@ READ_ONLY YES +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -899,7 +912,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2524,7 +2524,7 @@ READ_ONLY YES +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -908,7 +921,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2534,7 +2534,7 @@ READ_ONLY YES +@@ -2574,7 +2574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -917,7 +930,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2544,7 +2544,7 @@ READ_ONLY YES +@@ -2584,7 +2584,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -926,7 +939,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2554,7 +2554,7 @@ READ_ONLY YES +@@ -2594,7 +2594,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -935,7 +948,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2564,7 +2564,7 @@ READ_ONLY YES +@@ -2604,7 +2604,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT VARIABLE_SCOPE GLOBAL @@ -944,7 +957,7 @@ VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2574,7 +2574,7 @@ READ_ONLY YES +@@ -2614,7 +2614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES VARIABLE_SCOPE GLOBAL @@ -953,7 +966,7 @@ VARIABLE_COMMENT Maximum number of memory pool instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2584,7 +2584,7 @@ READ_ONLY YES +@@ -2624,7 +2624,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS VARIABLE_SCOPE GLOBAL @@ -962,7 +975,7 @@ VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2594,7 +2594,7 @@ READ_ONLY YES +@@ -2634,7 +2634,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -971,7 +984,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2604,7 +2604,7 @@ READ_ONLY YES +@@ -2644,7 +2644,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -980,7 +993,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2614,7 +2614,7 @@ READ_ONLY YES +@@ -2654,7 +2654,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES VARIABLE_SCOPE GLOBAL @@ -989,7 +1002,7 @@ VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2624,7 +2624,7 @@ READ_ONLY YES +@@ -2664,7 +2664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES VARIABLE_SCOPE GLOBAL @@ -998,7 +1011,7 @@ VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2634,7 +2634,7 @@ READ_ONLY YES +@@ -2674,7 +2674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -1007,7 +1020,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2644,7 +2644,7 @@ READ_ONLY YES +@@ -2684,7 +2684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1016,7 +1029,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2654,7 +2654,7 @@ READ_ONLY YES +@@ -2694,7 +2694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -1025,7 +1038,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2664,7 +2664,7 @@ READ_ONLY YES +@@ -2704,7 +2704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1034,7 +1047,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2674,7 +2674,7 @@ READ_ONLY YES +@@ -2714,7 +2714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH VARIABLE_SCOPE GLOBAL @@ -1043,7 +1056,7 @@ VARIABLE_COMMENT Maximum length of displayed sql text. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2684,7 +2684,7 @@ READ_ONLY YES +@@ -2724,7 +2724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -1052,7 +1065,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2694,7 +2694,7 @@ READ_ONLY YES +@@ -2734,7 +2734,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -1061,7 +1074,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2704,7 +2704,7 @@ READ_ONLY YES +@@ -2744,7 +2744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK VARIABLE_SCOPE GLOBAL @@ -1070,7 +1083,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 256 -@@ -2714,7 +2714,7 @@ READ_ONLY YES +@@ -2754,7 +2754,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -1079,7 +1092,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2724,7 +2724,7 @@ READ_ONLY YES +@@ -2764,7 +2764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1088,7 +1101,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2734,7 +2734,7 @@ READ_ONLY YES +@@ -2774,7 +2774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT VARIABLE_SCOPE GLOBAL @@ -1097,7 +1110,7 @@ VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2744,7 +2744,7 @@ READ_ONLY YES +@@ -2784,7 +2784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1106,7 +1119,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2754,7 +2754,7 @@ READ_ONLY YES +@@ -2794,7 +2794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1115,7 +1128,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2764,7 +2764,7 @@ READ_ONLY YES +@@ -2804,7 +2804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1124,7 +1137,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2774,7 +2774,7 @@ READ_ONLY YES +@@ -2814,7 +2814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1133,7 +1146,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2784,7 +2784,7 @@ READ_ONLY YES +@@ -2824,7 +2824,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1142,7 +1155,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2794,7 +2794,7 @@ READ_ONLY YES +@@ -2834,7 +2834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1151,7 +1164,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2844,7 +2844,7 @@ READ_ONLY YES +@@ -2884,7 +2884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1160,7 +1173,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2864,7 +2864,7 @@ READ_ONLY NO +@@ -2904,7 +2904,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1169,7 +1182,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2874,7 +2874,7 @@ READ_ONLY NO +@@ -2914,7 +2914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1178,7 +1191,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2934,7 +2934,7 @@ READ_ONLY NO +@@ -2974,7 +2974,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1187,7 +1200,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2944,7 +2944,7 @@ READ_ONLY NO +@@ -2984,7 +2984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1196,7 +1209,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2954,7 +2954,7 @@ READ_ONLY NO +@@ -2994,7 +2994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1205,7 +1218,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2967,7 +2967,7 @@ VARIABLE_SCOPE GLOBAL +@@ -3007,7 +3007,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1214,7 +1227,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3004,7 +3004,7 @@ READ_ONLY NO +@@ -3044,7 +3044,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1223,7 +1236,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3017,7 +3017,7 @@ VARIABLE_SCOPE SESSION ONLY +@@ -3057,7 +3057,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1232,7 +1245,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3027,14 +3027,14 @@ VARIABLE_SCOPE SESSION ONLY +@@ -3067,14 +3067,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1249,7 +1262,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3044,7 +3044,7 @@ READ_ONLY NO +@@ -3084,7 +3084,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1258,7 +1271,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3064,7 +3064,7 @@ READ_ONLY NO +@@ -3104,7 +3104,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1267,7 +1280,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3084,10 +3084,10 @@ READ_ONLY NO +@@ -3124,10 +3124,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1280,7 +1293,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3124,7 +3124,7 @@ READ_ONLY YES +@@ -3164,7 +3164,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1289,7 +1302,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3204,7 +3204,7 @@ READ_ONLY NO +@@ -3244,7 +3244,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1298,7 +1311,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3214,7 +3214,7 @@ READ_ONLY NO +@@ -3254,7 +3254,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1307,7 +1320,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3257,7 +3257,7 @@ VARIABLE_SCOPE SESSION +@@ -3297,7 +3297,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1316,7 +1329,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3474,7 +3474,7 @@ READ_ONLY NO +@@ -3514,7 +3514,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1325,7 +1338,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3564,7 +3564,7 @@ READ_ONLY NO +@@ -3604,7 +3604,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1334,7 +1347,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -3574,7 +3574,7 @@ READ_ONLY NO +@@ -3614,7 +3614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1343,7 +1356,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -3634,7 +3634,7 @@ READ_ONLY NO +@@ -3674,7 +3674,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1352,7 +1365,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3717,7 +3717,7 @@ VARIABLE_SCOPE SESSION +@@ -3757,7 +3757,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1361,7 +1374,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3727,7 +3727,7 @@ VARIABLE_SCOPE SESSION +@@ -3767,7 +3767,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 0 @@ -1370,7 +1383,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3737,14 +3737,14 @@ VARIABLE_SCOPE SESSION +@@ -3777,14 +3777,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 0 @@ -1387,7 +1400,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3754,7 +3754,7 @@ READ_ONLY NO +@@ -3794,7 +3794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1396,7 +1409,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3894,7 +3894,7 @@ READ_ONLY YES +@@ -3934,7 +3934,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1405,7 +1418,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -3921,7 +3921,7 @@ order by variable_name; +@@ -3961,7 +3961,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index fc7d6f8ce48fe..73beb03a75adf 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1695,13 +1695,23 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_FILTER VARIABLE_SCOPE SESSION VARIABLE_TYPE SET -VARIABLE_COMMENT Log only certain types of queries to the slow log. If variable empty alll kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled +VARIABLE_COMMENT Log only certain types of queries to the slow log. If variable empty all kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST admin,filesort,filesort_on_disk,filesort_priority_queue,full_join,full_scan,not_using_index,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME LOG_SLOW_MAX_WARNINGS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 1000 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -1769,7 +1779,7 @@ VARIABLE_COMMENT Verbosity level for the slow log NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST innodb,query_plan,explain,engine,full +ENUM_VALUE_LIST innodb,query_plan,explain,engine,warnings,full READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS @@ -2252,6 +2262,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME NOTE_VERBOSITY +VARIABLE_SCOPE SESSION +VARIABLE_TYPE SET +VARIABLE_COMMENT Verbosity level for note-warnings given to the user. See also @@sql_notes. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST basic,unusable_keys,explain +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -2382,12 +2402,22 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO @@ -3485,7 +3515,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT If set to 1, the default, warning_count is incremented each time a Note warning is encountered. If set to 0, Note warnings are not recorded. mysqldump has outputs to set this variable to 0 so that no unnecessary increments occur when data is reloaded. +VARIABLE_COMMENT If set to 1, the default, warning_count is incremented each time a Note warning is encountered. If set to 0, Note warnings are not recorded. mysqldump has outputs to set this variable to 0 so that no unnecessary increments occur when data is reloaded. See also note_verbosity, which allows one to define with notes are sent. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index a0e6e75c19056..e4ab36445a37a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,3 @@ ---- sysvars_server_notembedded.result 2023-08-10 08:06:11.664961456 +0200 -+++ sysvars_server_notembedded,32bit.result 2023-08-10 08:07:58.765154715 +0200 @@ -44,7 +44,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE @@ -399,6 +397,15 @@ NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 @@ -1854,7 +1854,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME LOG_SLOW_MAX_WARNINGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1000 +@@ -1864,7 +1864,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -407,7 +414,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1894,7 +1894,7 @@ +@@ -1904,7 +1904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -416,7 +423,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1924,7 +1924,7 @@ +@@ -1934,7 +1934,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION @@ -425,7 +432,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1984,7 +1984,7 @@ +@@ -1994,7 +1994,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -434,7 +441,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1997,14 +1997,14 @@ +@@ -2007,14 +2007,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the transactional cache NUMERIC_MIN_VALUE 4096 @@ -451,7 +458,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -2017,14 +2017,14 @@ +@@ -2027,14 +2027,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the statement cache NUMERIC_MIN_VALUE 4096 @@ -468,7 +475,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -2034,7 +2034,7 @@ +@@ -2044,7 +2044,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -477,7 +484,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2044,7 +2044,7 @@ +@@ -2054,7 +2054,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -486,7 +493,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2064,7 +2064,7 @@ +@@ -2074,7 +2074,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -495,7 +502,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -2077,14 +2077,14 @@ +@@ -2087,14 +2087,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -512,7 +519,7 @@ VARIABLE_COMMENT Alias for max_delayed_threads. Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2104,7 +2104,7 @@ +@@ -2114,7 +2114,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -521,7 +528,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2134,7 +2134,7 @@ +@@ -2144,7 +2144,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -530,7 +537,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2157,14 +2157,14 @@ +@@ -2167,14 +2167,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum size of the container of a rowid filter NUMERIC_MIN_VALUE 1024 @@ -547,7 +554,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2184,7 +2184,7 @@ +@@ -2194,7 +2194,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION @@ -556,7 +563,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -2194,7 +2194,7 @@ +@@ -2204,7 +2204,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -565,7 +572,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2214,7 +2214,7 @@ +@@ -2224,7 +2224,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -574,7 +581,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2234,7 +2234,7 @@ +@@ -2244,7 +2244,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -583,7 +590,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2244,7 +2244,7 @@ +@@ -2254,7 +2254,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -592,7 +599,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2254,7 +2254,7 @@ +@@ -2264,7 +2264,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -601,7 +608,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2264,7 +2264,7 @@ +@@ -2274,7 +2274,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -610,7 +617,7 @@ VARIABLE_COMMENT Alias for log_slow_min_examined_row_limit. Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2274,7 +2274,7 @@ +@@ -2284,7 +2284,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -619,7 +626,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2284,7 +2284,7 @@ +@@ -2294,7 +2294,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -628,7 +635,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2294,7 +2294,7 @@ +@@ -2304,7 +2304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -637,7 +644,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2317,7 +2317,7 @@ +@@ -2327,7 +2327,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Restricts the total memory used for memory mapping of MySQL tables NUMERIC_MIN_VALUE 7 @@ -646,7 +653,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2334,10 +2334,10 @@ +@@ -2344,10 +2344,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -659,7 +666,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2347,7 +2347,7 @@ +@@ -2357,7 +2357,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -668,7 +675,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2384,7 +2384,7 @@ +@@ -2394,7 +2394,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME NET_BUFFER_LENGTH VARIABLE_SCOPE SESSION @@ -677,7 +684,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2394,7 +2394,7 @@ +@@ -2404,7 +2404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -686,7 +693,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2404,7 +2404,7 @@ +@@ -2414,7 +2414,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -695,7 +702,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2414,7 +2414,7 @@ +@@ -2424,7 +2424,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -704,7 +711,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2464,7 +2464,7 @@ +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -713,7 +720,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2494,7 +2494,7 @@ +@@ -2514,7 +2514,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_EXTRA_PRUNING_DEPTH VARIABLE_SCOPE SESSION @@ -722,7 +729,16 @@ VARIABLE_COMMENT If the optimizer needs to enumerate join prefix of this size or larger, then it will try aggressively prune away the search space. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2554,17 +2554,17 @@ +@@ -2574,7 +2574,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2584,7 +2584,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION @@ -730,11 +746,8 @@ +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO + NUMERIC_MAX_VALUE 4294967295 +@@ -2594,7 +2594,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -743,7 +756,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search: 1 - prune plans based on cost and number of retrieved rows eq_ref: 2 - prune also if we find an eq_ref chain NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2 -@@ -2634,7 +2634,7 @@ +@@ -2664,7 +2664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -752,7 +765,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2644,7 +2644,7 @@ +@@ -2674,7 +2674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -761,7 +774,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2674,17 +2674,17 @@ +@@ -2704,17 +2704,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -782,7 +795,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2714,7 +2714,7 @@ +@@ -2744,7 +2744,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -791,7 +804,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2724,7 +2724,7 @@ +@@ -2754,7 +2754,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -800,7 +813,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2734,7 +2734,7 @@ +@@ -2764,7 +2764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -809,7 +822,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2744,7 +2744,7 @@ +@@ -2774,7 +2774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -818,7 +831,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2754,7 +2754,7 @@ +@@ -2784,7 +2784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -827,7 +840,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2764,7 +2764,7 @@ +@@ -2794,7 +2794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -836,7 +849,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2774,7 +2774,7 @@ +@@ -2804,7 +2804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -845,7 +858,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2784,7 +2784,7 @@ +@@ -2814,7 +2814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -854,7 +867,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2794,7 +2794,7 @@ +@@ -2824,7 +2824,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -863,7 +876,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2804,7 +2804,7 @@ +@@ -2834,7 +2834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -872,7 +885,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2814,7 +2814,7 @@ +@@ -2844,7 +2844,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -881,7 +894,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2824,7 +2824,7 @@ +@@ -2854,7 +2854,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -890,7 +903,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2834,7 +2834,7 @@ +@@ -2864,7 +2864,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -899,7 +912,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2844,7 +2844,7 @@ +@@ -2874,7 +2874,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -908,7 +921,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2854,7 +2854,7 @@ +@@ -2884,7 +2884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -917,7 +930,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2864,7 +2864,7 @@ +@@ -2894,7 +2894,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -926,7 +939,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2874,7 +2874,7 @@ +@@ -2904,7 +2904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -935,7 +948,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2884,7 +2884,7 @@ +@@ -2914,7 +2914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT VARIABLE_SCOPE GLOBAL @@ -944,7 +957,7 @@ VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2894,7 +2894,7 @@ +@@ -2924,7 +2924,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES VARIABLE_SCOPE GLOBAL @@ -953,7 +966,7 @@ VARIABLE_COMMENT Maximum number of memory pool instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2904,7 +2904,7 @@ +@@ -2934,7 +2934,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS VARIABLE_SCOPE GLOBAL @@ -962,7 +975,7 @@ VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2914,7 +2914,7 @@ +@@ -2944,7 +2944,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -971,7 +984,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2924,7 +2924,7 @@ +@@ -2954,7 +2954,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -980,7 +993,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2934,7 +2934,7 @@ +@@ -2964,7 +2964,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES VARIABLE_SCOPE GLOBAL @@ -989,7 +1002,7 @@ VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2944,7 +2944,7 @@ +@@ -2974,7 +2974,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES VARIABLE_SCOPE GLOBAL @@ -998,7 +1011,7 @@ VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2954,7 +2954,7 @@ +@@ -2984,7 +2984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -1007,7 +1020,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2964,7 +2964,7 @@ +@@ -2994,7 +2994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1016,7 +1029,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2974,7 +2974,7 @@ +@@ -3004,7 +3004,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -1025,7 +1038,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2984,7 +2984,7 @@ +@@ -3014,7 +3014,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1034,7 +1047,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2994,7 +2994,7 @@ +@@ -3024,7 +3024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH VARIABLE_SCOPE GLOBAL @@ -1043,7 +1056,7 @@ VARIABLE_COMMENT Maximum length of displayed sql text. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3004,7 +3004,7 @@ +@@ -3034,7 +3034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -1052,7 +1065,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3014,7 +3014,7 @@ +@@ -3044,7 +3044,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -1061,7 +1074,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3024,7 +3024,7 @@ +@@ -3054,7 +3054,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK VARIABLE_SCOPE GLOBAL @@ -1070,7 +1083,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 256 -@@ -3034,7 +3034,7 @@ +@@ -3064,7 +3064,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -1079,7 +1092,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3044,7 +3044,7 @@ +@@ -3074,7 +3074,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1088,7 +1101,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3054,7 +3054,7 @@ +@@ -3084,7 +3084,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT VARIABLE_SCOPE GLOBAL @@ -1097,7 +1110,7 @@ VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3064,7 +3064,7 @@ +@@ -3094,7 +3094,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1106,7 +1119,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3074,7 +3074,7 @@ +@@ -3104,7 +3104,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1115,7 +1128,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3084,7 +3084,7 @@ +@@ -3114,7 +3114,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1124,7 +1137,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3094,7 +3094,7 @@ +@@ -3124,7 +3124,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1133,7 +1146,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -3104,7 +3104,7 @@ +@@ -3134,7 +3134,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1142,7 +1155,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3114,7 +3114,7 @@ +@@ -3144,7 +3144,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1151,7 +1164,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3164,7 +3164,7 @@ +@@ -3194,7 +3194,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1160,7 +1173,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3184,7 +3184,7 @@ +@@ -3214,7 +3214,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1169,7 +1182,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3194,7 +3194,7 @@ +@@ -3224,7 +3224,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1178,7 +1191,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3254,7 +3254,7 @@ +@@ -3284,7 +3284,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1187,7 +1200,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3264,7 +3264,7 @@ +@@ -3294,7 +3294,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1196,7 +1209,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3274,7 +3274,7 @@ +@@ -3304,7 +3304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1205,7 +1218,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3287,7 +3287,7 @@ +@@ -3317,7 +3317,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1214,7 +1227,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3324,7 +3324,7 @@ +@@ -3354,7 +3354,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1223,7 +1236,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3337,7 +3337,7 @@ +@@ -3367,7 +3367,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1232,7 +1245,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3347,14 +3347,14 @@ +@@ -3377,14 +3377,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1249,7 +1262,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3367,14 +3367,14 @@ +@@ -3397,14 +3397,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) NUMERIC_MIN_VALUE 0 @@ -1266,7 +1279,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3394,7 +3394,7 @@ +@@ -3424,7 +3424,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1275,7 +1288,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3614,10 +3614,10 @@ +@@ -3644,10 +3644,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1288,7 +1301,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3634,20 +3634,20 @@ +@@ -3664,20 +3664,20 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -1313,7 +1326,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3704,10 +3704,10 @@ +@@ -3734,10 +3734,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL VARIABLE_SCOPE GLOBAL @@ -1326,7 +1339,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3744,7 +3744,7 @@ +@@ -3774,7 +3774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1335,7 +1348,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3884,7 +3884,7 @@ +@@ -3914,7 +3914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1344,7 +1357,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3914,7 +3914,7 @@ +@@ -3944,7 +3944,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1353,7 +1366,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3944,7 +3944,7 @@ +@@ -3974,7 +3974,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED VARIABLE_SCOPE GLOBAL @@ -1362,7 +1375,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3964,7 +3964,7 @@ +@@ -3994,7 +3994,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SLAVE_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1371,7 +1384,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3974,7 +3974,7 @@ +@@ -4004,7 +4004,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_WORKERS VARIABLE_SCOPE GLOBAL @@ -1380,7 +1393,7 @@ VARIABLE_COMMENT Alias for slave_parallel_threads NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4014,7 +4014,7 @@ +@@ -4044,7 +4044,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_TRANSACTION_RETRIES VARIABLE_SCOPE GLOBAL @@ -1389,7 +1402,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4034,7 +4034,7 @@ +@@ -4064,7 +4064,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_TRANSACTION_RETRY_INTERVAL VARIABLE_SCOPE GLOBAL @@ -1398,7 +1411,7 @@ VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3600 -@@ -4054,7 +4054,7 @@ +@@ -4084,7 +4084,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1407,7 +1420,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -4097,7 +4097,7 @@ +@@ -4127,7 +4127,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1416,7 +1429,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4324,7 +4324,7 @@ +@@ -4354,7 +4354,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1425,7 +1438,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4434,7 +4434,7 @@ +@@ -4464,7 +4464,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1434,7 +1447,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -4444,7 +4444,7 @@ +@@ -4474,7 +4474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1443,7 +1456,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -4504,7 +4504,7 @@ +@@ -4534,7 +4534,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1452,7 +1465,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4677,7 +4677,7 @@ +@@ -4707,7 +4707,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1461,7 +1474,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4687,7 +4687,7 @@ +@@ -4717,7 +4717,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 0 @@ -1470,7 +1483,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4697,14 +4697,14 @@ +@@ -4727,14 +4727,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 0 @@ -1487,7 +1500,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4714,7 +4714,7 @@ +@@ -4744,7 +4744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1496,7 +1509,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4854,7 +4854,7 @@ +@@ -4884,7 +4884,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1505,7 +1518,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4881,7 +4881,7 @@ +@@ -4911,7 +4911,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index b49df2673eb2d..450146be10153 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1845,13 +1845,23 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_FILTER VARIABLE_SCOPE SESSION VARIABLE_TYPE SET -VARIABLE_COMMENT Log only certain types of queries to the slow log. If variable empty alll kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled +VARIABLE_COMMENT Log only certain types of queries to the slow log. If variable empty all kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST admin,filesort,filesort_on_disk,filesort_priority_queue,full_join,full_scan,not_using_index,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME LOG_SLOW_MAX_WARNINGS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 1000 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -1919,7 +1929,7 @@ VARIABLE_COMMENT Verbosity level for the slow log NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST innodb,query_plan,explain,engine,full +ENUM_VALUE_LIST innodb,query_plan,explain,engine,warnings,full READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS @@ -2422,6 +2432,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME NOTE_VERBOSITY +VARIABLE_SCOPE SESSION +VARIABLE_TYPE SET +VARIABLE_COMMENT Verbosity level for note-warnings given to the user. See also @@sql_notes. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST basic,unusable_keys,explain +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN @@ -2552,12 +2572,22 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO @@ -4175,7 +4205,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT If set to 1, the default, warning_count is incremented each time a Note warning is encountered. If set to 0, Note warnings are not recorded. mysqldump has outputs to set this variable to 0 so that no unnecessary increments occur when data is reloaded. +VARIABLE_COMMENT If set to 1, the default, warning_count is incremented each time a Note warning is encountered. If set to 0, Note warnings are not recorded. mysqldump has outputs to set this variable to 0 so that no unnecessary increments occur when data is reloaded. See also note_verbosity, which allows one to define with notes are sent. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/t/log_slow_verbosity_basic.test b/mysql-test/suite/sys_vars/t/log_slow_verbosity_basic.test new file mode 100644 index 0000000000000..3e27f25b63cc0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/log_slow_verbosity_basic.test @@ -0,0 +1,73 @@ +# set session + +SET @start_global_value = @@global.log_slow_verbosity; +select @@global.log_slow_verbosity = @@session.log_slow_verbosity; +SET @@global.log_slow_verbosity="",@@session.log_slow_verbosity=""; + +# +# exists as global only +# +show global variables like 'log_slow_verbosity'; +show session variables like 'log_slow_verbosity'; +select * from information_schema.global_variables where variable_name='log_slow_verbosity'; +select * from information_schema.session_variables where variable_name='log_slow_verbosity'; + +# +# show that it's writable +# +set global log_slow_verbosity=1; +select @@global.log_slow_verbosity; +set session log_slow_verbosity=1; +select @@session.log_slow_verbosity; + +# +# all valid values +# +set session log_slow_verbosity=1; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=2; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=3; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=4; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=5; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=6; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=7; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=8; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=16; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=32; +select @@session.log_slow_verbosity; + + +set session log_slow_verbosity='innodb'; +select @@session.log_slow_verbosity; +set session log_slow_verbosity='query_plan'; +select @@session.log_slow_verbosity; +set session log_slow_verbosity='innodb,query_plan'; +select @@session.log_slow_verbosity; +set session log_slow_verbosity='explain'; +select @@session.log_slow_verbosity; +set session log_slow_verbosity='innodb,query_plan,explain,engine,warnings,full'; +select @@session.log_slow_verbosity; +set session log_slow_verbosity=''; +select @@session.log_slow_verbosity; + +# +# incorrect types/values +# +--error ER_WRONG_TYPE_FOR_VAR +set session log_slow_verbosity=1.1; +--error ER_WRONG_TYPE_FOR_VAR +set session log_slow_verbosity=1e1; +--error ER_WRONG_VALUE_FOR_VAR +set session log_slow_verbosity="foo"; +--error ER_WRONG_VALUE_FOR_VAR +set session log_slow_verbosity=64; + +SET @@global.log_slow_verbosity = @start_global_value; diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 158dfc489354d..eff5a031bf458 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -172,6 +172,9 @@ void init_alloc_root(PSI_memory_key key, MEM_ROOT *mem_root, size_t block_size, mem_root->block_num= 4; /* We shift this with >>2 */ mem_root->first_block_usage= 0; mem_root->psi_key= key; +#ifdef PROTECT_STATEMENT_MEMROOT + mem_root->read_only= 0; +#endif #if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG)) if (pre_alloc_size) @@ -279,6 +282,10 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) DBUG_PRINT("enter",("root: %p", mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); +#ifdef PROTECT_STATEMENT_MEMROOT + DBUG_ASSERT(mem_root->read_only == 0); +#endif + DBUG_EXECUTE_IF("simulate_out_of_memory", { if (mem_root->error_handler) @@ -554,6 +561,45 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr) } +/* + Remember last MEM_ROOT block. + + This allows one to free all new allocated blocks. +*/ + +USED_MEM *get_last_memroot_block(MEM_ROOT* root) +{ + return root->used ? root->used : root->pre_alloc; +} + +/* + Free all newly allocated blocks +*/ + +void free_all_new_blocks(MEM_ROOT *root, USED_MEM *last_block) +{ + USED_MEM *old, *next; + if (!root->used) + return; /* Nothing allocated */ + return; + /* + Free everying allocated up to, but not including, last_block. + However do not go past pre_alloc as we do not want to free + that one. This should not be a problem as in almost all normal + usage pre_alloc is last in the list. + */ + + for (next= root->used ; + next && next != last_block && next != root->pre_alloc ; ) + { + old= next; next= next->next; + root_free(root, old, old->size); + } + root->used= next; + root->block_num= 4; + root->first_block_usage= 0; +} + /** Change protection for all blocks in the mem root */ diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index d1b2c599372b2..0343e06a2f69a 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -837,15 +837,21 @@ static int setval(const struct my_option *opts, void *value, char *argument, *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err); if (err) { - /* Accept an integer representation of the set */ - char *endptr; - ulonglong arg= (ulonglong) strtol(argument, &endptr, 10); - if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1))) + /* Check if option 'all' is used (to set all bits) */ + if (!my_strcasecmp(&my_charset_latin1, argument, "all")) + *(ulonglong*) value= ((1ULL << opts->typelib->count) - 1); + else { - res= EXIT_ARGUMENT_INVALID; - goto ret; - }; - *(ulonglong*)value= arg; + /* Accept an integer representation of the set */ + char *endptr; + ulonglong arg= (ulonglong) strtol(argument, &endptr, 10); + if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1))) + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + *(ulonglong*)value= arg; + } err= 0; } break; @@ -1644,6 +1650,8 @@ void my_print_help(const struct my_option *options) printf(" to disable.)\n"); } } + else if ((optp->var_type & GET_TYPE_MASK) == GET_SET) + printf(" Use 'ALL' to set all combinations.\n"); } DBUG_VOID_RETURN; } diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index b5193a9cd8ea2..71527a9bc2784 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -420,6 +420,7 @@ uchar *my_large_malloc(size_t *size, myf my_flags) if (ptr != NULL) { MEM_MAKE_DEFINED(ptr, *size); + update_malloc_size(*size, 0); } DBUG_RETURN(ptr); @@ -452,31 +453,36 @@ void my_large_free(void *ptr, size_t size) { my_error(EE_BADMEMORYRELEASE, MYF(ME_ERROR_LOG_ONLY), ptr, size, errno); } -# if !__has_feature(memory_sanitizer) +#if !__has_feature(memory_sanitizer) else { MEM_MAKE_ADDRESSABLE(ptr, size); } -# endif +#endif + update_malloc_size(- (longlong) size, 0); #elif defined(_WIN32) /* When RELEASE memory, the size parameter must be 0. Do not use MEM_RELEASE with MEM_DECOMMIT. */ - if (ptr && !VirtualFree(ptr, 0, MEM_RELEASE)) + if (ptr) { - my_error(EE_BADMEMORYRELEASE, MYF(ME_ERROR_LOG_ONLY), ptr, size, - GetLastError()); + if (!VirtualFree(ptr, 0, MEM_RELEASE)) + { + my_error(EE_BADMEMORYRELEASE, MYF(ME_ERROR_LOG_ONLY), ptr, size, + GetLastError()); + } + update_malloc_size(- (longlong) size, 0); } -# if !__has_feature(memory_sanitizer) +#if !__has_feature(memory_sanitizer) else { MEM_MAKE_ADDRESSABLE(ptr, size); } -# endif +#endif /* memory_sanitizer */ #else my_free_lock(ptr); -#endif +#endif /* HAVE_MMMAP */ DBUG_VOID_RETURN; } diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c index 1b6b68816f8cc..45f16bac0547f 100644 --- a/mysys/my_lockmem.c +++ b/mysys/my_lockmem.c @@ -32,7 +32,7 @@ struct st_mem_list LIST *mem_list; -uchar *my_malloc_lock(uint size,myf MyFlags) +uchar *my_malloc_lock(size_t size, myf MyFlags) { int success; uint pagesize= my_system_page_size; @@ -70,6 +70,7 @@ uchar *my_malloc_lock(uint size,myf MyFlags) mysql_mutex_lock(&THR_LOCK_malloc); mem_list=list_add(mem_list,&element->list); mysql_mutex_unlock(&THR_LOCK_malloc); + update_malloc_size((longlong) size, 0); } DBUG_RETURN(ptr); } @@ -88,6 +89,7 @@ void my_free_lock(uchar *ptr) { /* Found locked mem */ (void) munlock((uchar*) ptr,element->size); mem_list=list_delete(mem_list,list); + update_malloc_size(- (longlong) element->size, 0); break; } } diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index a2371ea1ad00c..64c888ff8686d 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -45,7 +45,11 @@ typedef struct my_memory_header my_memory_header; 1 - failure, abort the allocation */ -static MALLOC_SIZE_CB update_malloc_size= 0; +static void dummy(long long size __attribute__((unused)), + my_bool is_thread_specific __attribute__((unused))) +{} + +MALLOC_SIZE_CB update_malloc_size= dummy; void set_malloc_size_cb(MALLOC_SIZE_CB func) { diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index 6d2dc72b097c3..49e02b339c793 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -42,9 +42,15 @@ IF(HAVE_PAM_APPL_H AND HAVE_GETGROUPLIST) IF (TARGET auth_pam) MYSQL_ADD_EXECUTABLE(auth_pam_tool auth_pam_tool.c DESTINATION ${INSTALL_PLUGINDIR}/auth_pam_tool_dir COMPONENT Server) TARGET_LINK_LIBRARIES(auth_pam_tool pam) + IF (CMAKE_MAJOR_VERSION EQUAL 2) + # 2.8.12 bug (in CentOS 7) + SET(user mysql) + ELSE() + SET(user "%{mysqld_user}") + ENDIF() SET(CPACK_RPM_server_USER_FILELIST ${CPACK_RPM_server_USER_FILELIST} - "%attr(700,-,-) ${INSTALL_PLUGINDIRABS}/auth_pam_tool_dir" - "%attr(4755,-,-) ${INSTALL_PLUGINDIRABS}/auth_pam_tool_dir/auth_pam_tool") + "%attr(700,${user},-) ${INSTALL_PLUGINDIRABS}/auth_pam_tool_dir" + "%attr(4755,root,-) ${INSTALL_PLUGINDIRABS}/auth_pam_tool_dir/auth_pam_tool") SET(CPACK_RPM_server_USER_FILELIST ${CPACK_RPM_server_USER_FILELIST} PARENT_SCOPE) ENDIF() IF(TARGET auth_pam OR TARGET auth_pam_v1) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result index d4291e6f8f830..b6fd55e1df7e7 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result @@ -105,6 +105,8 @@ c EXPLAIN SELECT * FROM t1 WHERE c=CAST('0.0.0.1' AS INET4); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `c` part[0] for lookup: `test`.`t1`.`c` of type `varchar` = "cast('0.0.0.1' as inet4)" of type `inet4` DROP TABLE t1; # # End of 10.10 tests diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result index c2577ef44dfd1..da67e05a163aa 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result @@ -105,6 +105,8 @@ c EXPLAIN SELECT * FROM t1 WHERE c=CAST('::1' AS INET6); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `c` part[0] for lookup: `test`.`t1`.`c` of type `varchar` = "cast('::1' as inet6)" of type `inet6` DROP TABLE t1; # # End of 10.5 tests diff --git a/scripts/mariadb_system_tables.sql b/scripts/mariadb_system_tables.sql index 5d2f83b9f3cf1..a3f6824ceb97c 100644 --- a/scripts/mariadb_system_tables.sql +++ b/scripts/mariadb_system_tables.sql @@ -161,7 +161,7 @@ DROP PREPARE stmt; -- Create slow_log if CSV is enabled. -SET @str = IF (@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, user_host MEDIUMTEXT NOT NULL, query_time TIME(6) NOT NULL, lock_time TIME(6) NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, sql_text MEDIUMTEXT NOT NULL, thread_id BIGINT(21) UNSIGNED NOT NULL, rows_affected INTEGER NOT NULL) engine=CSV CHARACTER SET utf8mb3 comment="Slow log"', 'SET @dummy = 0'); +SET @str = IF (@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, user_host MEDIUMTEXT NOT NULL, query_time TIME(6) NOT NULL, lock_time TIME(6) NOT NULL, rows_sent BIGINT UNSIGNED NOT NULL, rows_examined BIGINT UNSIGNED NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, sql_text MEDIUMTEXT NOT NULL, thread_id BIGINT(21) UNSIGNED NOT NULL, rows_affected BIGINT UNSIGNED NOT NULL) engine=CSV CHARACTER SET utf8mb3 comment="Slow log"', 'SET @dummy = 0'); PREPARE stmt FROM @str; EXECUTE stmt; @@ -302,6 +302,7 @@ set @had_proxies_priv_table= @@warning_count != 0; -- and for upgrades CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; INSERT INTO tmp_proxies_priv VALUES ('localhost', 'root', '', '', TRUE, '', now()); +REPLACE INTO tmp_proxies_priv SELECT 'localhost',IFNULL(@auth_root_socket, 'root'), '', '', TRUE, '', now() FROM DUAL; INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; DROP TABLE tmp_proxies_priv; diff --git a/scripts/mariadb_system_tables_data.sql b/scripts/mariadb_system_tables_data.sql index 28d603cc559f5..85489e7866e94 100644 --- a/scripts/mariadb_system_tables_data.sql +++ b/scripts/mariadb_system_tables_data.sql @@ -46,9 +46,9 @@ IF @auth_root_socket is not null THEN INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @auth_root_socket IS NULL; INSERT INTO global_priv SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL; -DROP TABLE tmp_user_nopasswd, tmp_user_socket; CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; -INSERT INTO tmp_proxies_priv SELECT @current_hostname, 'root', '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; +INSERT INTO tmp_proxies_priv SELECT Host, User, '', '', TRUE, '', now() FROM tmp_user_nopasswd WHERE Host != 'localhost' AND @auth_root_socket IS NULL; +REPLACE INTO tmp_proxies_priv SELECT @current_hostname, IFNULL(@auth_root_socket, 'root'), '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; -DROP TABLE tmp_proxies_priv; +DROP TABLE tmp_user_nopasswd, tmp_user_socket, tmp_proxies_priv; diff --git a/scripts/mariadb_system_tables_fix.sql b/scripts/mariadb_system_tables_fix.sql index dcc89e10059ff..01ec5633004e1 100644 --- a/scripts/mariadb_system_tables_fix.sql +++ b/scripts/mariadb_system_tables_fix.sql @@ -300,14 +300,14 @@ SET GLOBAL log_slow_query = 'OFF'; ALTER TABLE slow_log ADD COLUMN thread_id BIGINT(21) UNSIGNED NOT NULL AFTER sql_text; ALTER TABLE slow_log - ADD COLUMN rows_affected INTEGER NOT NULL AFTER thread_id; + ADD COLUMN rows_affected BIGINT UNSIGNED NOT NULL AFTER thread_id; ALTER TABLE slow_log MODIFY start_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, MODIFY user_host MEDIUMTEXT NOT NULL, MODIFY query_time TIME(6) NOT NULL, MODIFY lock_time TIME(6) NOT NULL, - MODIFY rows_sent INTEGER NOT NULL, - MODIFY rows_examined INTEGER NOT NULL, + MODIFY rows_sent BIGINT UNSIGNED NOT NULL, + MODIFY rows_examined BIGINT UNSIGNED NOT NULL, MODIFY db VARCHAR(512) NOT NULL, MODIFY last_insert_id INTEGER NOT NULL, MODIFY insert_id INTEGER NOT NULL, diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 5e4a193b74772..5dce2462d0179 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -85,7 +85,7 @@ PREPARE stmt FROM @stmt; EXECUTE stmt; DROP PREPARE stmt; -SET @stmt = IF (@cond = '1', 'CREATE TABLE IF NOT EXISTS slow_log ( start_time timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), user_host mediumtext NOT NULL, query_time time(6) NOT NULL, lock_time time(6) NOT NULL, rows_sent int(11) NOT NULL, rows_examined int(11) NOT NULL, db varchar(512) NOT NULL, last_insert_id int(11) NOT NULL, insert_id int(11) NOT NULL, server_id int(10) unsigned NOT NULL, sql_text mediumtext NOT NULL, thread_id bigint(21) unsigned NOT NULL) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT=\"Slow log\"', 'SET @dummy = 0'); +SET @stmt = IF (@cond = '1', 'CREATE TABLE IF NOT EXISTS slow_log ( start_time timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), user_host mediumtext NOT NULL, query_time time(6) NOT NULL, lock_time time(6) NOT NULL, rows_sent bigint(20) UNSIGNED NOT NULL, rows_examined bigint(20) UNSIGNED NOT NULL, db varchar(512) NOT NULL, last_insert_id int(11) NOT NULL, insert_id int(11) NOT NULL, server_id int(10) unsigned NOT NULL, sql_text mediumtext NOT NULL, thread_id bigint(21) unsigned NOT NULL) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT=\"Slow log\"', 'SET @dummy = 0'); PREPARE stmt FROM @stmt; EXECUTE stmt; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 0284359fbc7df..60105c91ed90a 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -188,8 +188,8 @@ SET (SQL_SOURCE ${MYSYS_LIBWRAP_SOURCE} ) -IF(CMAKE_C_COMPILER_ID MATCHES "Clang" AND - NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.0.0") +MY_CHECK_CXX_COMPILER_FLAG(-Wno-unused-but-set-variable) +IF(have_CXX__Wno_unused_but_set_variable) ADD_COMPILE_FLAGS(${CMAKE_CURRENT_BINARY_DIR}/yy_mariadb.cc ${CMAKE_CURRENT_BINARY_DIR}/yy_oracle.cc COMPILE_FLAGS "-Wno-unused-but-set-variable") diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index f363816fe4914..362463a7f22c8 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -87,7 +87,9 @@ struct st_debug_sync_globals ulonglong dsp_executed; /* statistics */ ulonglong dsp_max_active; /* statistics */ - st_debug_sync_globals() : ds_signal_set(PSI_NOT_INSTRUMENTED, signal_key) {}; + st_debug_sync_globals() : + ds_signal_set(PSI_NOT_INSTRUMENTED, signal_key), + dsp_hits (0), dsp_executed(0), dsp_max_active(0) {}; ~st_debug_sync_globals() { clear_set(); @@ -163,7 +165,7 @@ struct st_debug_sync_globals } }; -static st_debug_sync_globals debug_sync_global; /* All globals in one object */ +static st_debug_sync_globals *debug_sync_global; /* All globals in one object */ /** Callbacks from C files. @@ -237,16 +239,19 @@ int debug_sync_init(void) init_debug_sync_psi_keys(); #endif + if (!debug_sync_global) + debug_sync_global= new st_debug_sync_globals(); + if (opt_debug_sync_timeout) { int rc; /* Initialize the global variables. */ - debug_sync_global.clear_set(); + debug_sync_global->clear_set(); if ((rc= mysql_cond_init(key_debug_sync_globals_ds_cond, - &debug_sync_global.ds_cond, NULL)) || + &debug_sync_global->ds_cond, NULL)) || (rc= mysql_mutex_init(key_debug_sync_globals_ds_mutex, - &debug_sync_global.ds_mutex, + &debug_sync_global->ds_mutex, MY_MUTEX_INIT_FAST))) DBUG_RETURN(rc); /* purecov: inspected */ @@ -276,21 +281,25 @@ void debug_sync_end(void) debug_sync_C_callback_ptr= NULL; /* Destroy the global variables. */ - debug_sync_global.clear_set(); - mysql_cond_destroy(&debug_sync_global.ds_cond); - mysql_mutex_destroy(&debug_sync_global.ds_mutex); + debug_sync_global->clear_set(); + mysql_cond_destroy(&debug_sync_global->ds_cond); + mysql_mutex_destroy(&debug_sync_global->ds_mutex); /* Print statistics. */ { sql_print_information("Debug sync points hit: %lld", - debug_sync_global.dsp_hits); + debug_sync_global->dsp_hits); sql_print_information("Debug sync points executed: %lld", - debug_sync_global.dsp_executed); + debug_sync_global->dsp_executed); sql_print_information("Debug sync points max active per thread: %lld", - debug_sync_global.dsp_max_active); + debug_sync_global->dsp_max_active); } } + delete debug_sync_global; + /* Just to be safe */ + debug_sync_global= NULL; + DBUG_VOID_RETURN; } @@ -360,11 +369,11 @@ void debug_sync_init_thread(THD *thd) */ static const char *get_signal_set_as_string() { - mysql_mutex_assert_owner(&debug_sync_global.ds_mutex); + mysql_mutex_assert_owner(&debug_sync_global->ds_mutex); size_t req_size= 1; // In case of empty set for the end '\0' char. - for (size_t i= 0; i < debug_sync_global.ds_signal_set.size(); i++) - req_size+= debug_sync_global.ds_signal_set.at(i)->length + 1; + for (size_t i= 0; i < debug_sync_global->ds_signal_set.size(); i++) + req_size+= debug_sync_global->ds_signal_set.at(i)->length + 1; char *buf= (char *) my_malloc(PSI_NOT_INSTRUMENTED, req_size, MYF(0)); if (!buf) @@ -372,11 +381,11 @@ static const char *get_signal_set_as_string() memset(buf, '\0', req_size); char *cur_pos= buf; - for (size_t i= 0; i < debug_sync_global.ds_signal_set.size(); i++) + for (size_t i= 0; i < debug_sync_global->ds_signal_set.size(); i++) { - const LEX_CSTRING *signal= debug_sync_global.ds_signal_set.at(i); + const LEX_CSTRING *signal= debug_sync_global->ds_signal_set.at(i); memcpy(cur_pos, signal->str, signal->length); - if (i != debug_sync_global.ds_signal_set.size() - 1) + if (i != debug_sync_global->ds_signal_set.size() - 1) cur_pos[signal->length]= ','; else cur_pos[signal->length] = '\0'; @@ -415,12 +424,24 @@ void debug_sync_end_thread(THD *thd) } /* Statistics. */ - mysql_mutex_lock(&debug_sync_global.ds_mutex); - debug_sync_global.dsp_hits+= ds_control->dsp_hits; - debug_sync_global.dsp_executed+= ds_control->dsp_executed; - if (debug_sync_global.dsp_max_active < ds_control->dsp_max_active) - debug_sync_global.dsp_max_active= ds_control->dsp_max_active; - mysql_mutex_unlock(&debug_sync_global.ds_mutex); + /* + Protect access with debug_sync_global->ds_mutex only if + it had been initialized. + */ + if (debug_sync_C_callback_ptr) + mysql_mutex_lock(&debug_sync_global->ds_mutex); + + debug_sync_global->dsp_hits+= ds_control->dsp_hits; + debug_sync_global->dsp_executed+= ds_control->dsp_executed; + if (debug_sync_global->dsp_max_active < ds_control->dsp_max_active) + debug_sync_global->dsp_max_active= ds_control->dsp_max_active; + + /* + Protect access with debug_sync_global->ds_mutex only if + it had been initialized. + */ + if (debug_sync_C_callback_ptr) + mysql_mutex_unlock(&debug_sync_global->ds_mutex); my_free(ds_control); thd->debug_sync_control= NULL; @@ -668,9 +689,9 @@ static void debug_sync_reset(THD *thd) ds_control->ds_active= 0; /* Clear the global signal. */ - mysql_mutex_lock(&debug_sync_global.ds_mutex); - debug_sync_global.clear_set(); - mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global->ds_mutex); + debug_sync_global->clear_set(); + mysql_mutex_unlock(&debug_sync_global->ds_mutex); DBUG_VOID_RETURN; } @@ -1454,14 +1475,14 @@ uchar *debug_sync_value_ptr(THD *thd) static const char on[]= "ON - current signals: '"; // Ensure exclusive access to debug_sync_global.ds_signal - mysql_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global->ds_mutex); size_t lgt= sizeof(on) + 1; /* +1 as we'll have to append ' at the end. */ - for (size_t i= 0; i < debug_sync_global.ds_signal_set.size(); i++) + for (size_t i= 0; i < debug_sync_global->ds_signal_set.size(); i++) { /* Assume each signal is separated by a comma, hence +1. */ - lgt+= debug_sync_global.ds_signal_set.at(i)->length + 1; + lgt+= debug_sync_global->ds_signal_set.at(i)->length + 1; } char *vend; @@ -1471,18 +1492,18 @@ uchar *debug_sync_value_ptr(THD *thd) { vend= value + lgt - 1; /* reserve space for '\0'. */ vptr= debug_sync_bmove_len(value, vend, STRING_WITH_LEN(on)); - for (size_t i= 0; i < debug_sync_global.ds_signal_set.size(); i++) + for (size_t i= 0; i < debug_sync_global->ds_signal_set.size(); i++) { - const LEX_CSTRING *s= debug_sync_global.ds_signal_set.at(i); + const LEX_CSTRING *s= debug_sync_global->ds_signal_set.at(i); vptr= debug_sync_bmove_len(vptr, vend, s->str, s->length); - if (i != debug_sync_global.ds_signal_set.size() - 1) + if (i != debug_sync_global->ds_signal_set.size() - 1) *(vptr++)= ','; } DBUG_ASSERT(vptr < vend); *(vptr++)= '\''; *vptr= '\0'; /* We have one byte reserved for the worst case. */ } - mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global->ds_mutex); } else { @@ -1554,7 +1575,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) threads just reads an old cached version of the signal. */ - mysql_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global->ds_mutex); if (action->signal.length()) { @@ -1566,15 +1587,15 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) variable for each one. */ while (!error && (pos= action->signal.strstr(",", 1, offset)) > 0) { - error= debug_sync_global.set_signal(action->signal.ptr() + offset, - pos - offset); + error= debug_sync_global->set_signal(action->signal.ptr() + offset, + pos - offset); offset= pos + 1; } if (error || /* The last signal in the list. */ - debug_sync_global.set_signal(action->signal.ptr() + offset, - action->signal.length() - offset)) + debug_sync_global->set_signal(action->signal.ptr() + offset, + action->signal.length() - offset)) { /* Error is reported by my_malloc(). @@ -1583,7 +1604,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) debug_sync_emergency_disable(); /* purecov: tested */ } /* Wake threads waiting in a sync point. */ - mysql_cond_broadcast(&debug_sync_global.ds_cond); + mysql_cond_broadcast(&debug_sync_global->ds_cond); DBUG_PRINT("debug_sync_exec", ("signal '%s' at: '%s'", sig_emit, dsp_name)); } /* end if (action->signal.length()) */ @@ -1610,8 +1631,8 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) old_mutex= thd->mysys_var->current_mutex; old_cond= thd->mysys_var->current_cond; restore_current_mutex = true; - thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex; - thd->mysys_var->current_cond= &debug_sync_global.ds_cond; + thd->mysys_var->current_mutex= &debug_sync_global->ds_mutex; + thd->mysys_var->current_cond= &debug_sync_global->ds_cond; } else restore_current_mutex = false; @@ -1640,13 +1661,13 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) The facility can become disabled when some thread cannot get the required dynamic memory allocated. */ - while (!debug_sync_global.is_signalled(action->wait_for.ptr(), - action->wait_for.length()) && + while (!debug_sync_global->is_signalled(action->wait_for.ptr(), + action->wait_for.length()) && !(thd->killed & KILL_HARD_BIT) && opt_debug_sync_timeout) { - error= mysql_cond_timedwait(&debug_sync_global.ds_cond, - &debug_sync_global.ds_mutex, + error= mysql_cond_timedwait(&debug_sync_global->ds_cond, + &debug_sync_global->ds_mutex, &abstime); // TODO turn this into a for loop printing. DBUG_EXECUTE("debug_sync", { @@ -1668,7 +1689,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) } if (action->clear_event) - debug_sync_global.clear_signal(action->wait_for); + debug_sync_global->clear_signal(action->wait_for); DBUG_EXECUTE("debug_sync_exec", if (thd->killed) @@ -1688,7 +1709,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) protected mutex must always unlocked _before_ mysys_var->mutex is locked. (See comment in THD::exit_cond().) */ - mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global->ds_mutex); if (restore_current_mutex) { mysql_mutex_lock(&thd->mysys_var->mutex); @@ -1703,7 +1724,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) else { /* In case we don't wait, we just release the mutex. */ - mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global->ds_mutex); } /* end if (action->wait_for.length()) */ } /* end if (action->execute) */ diff --git a/sql/events.cc b/sql/events.cc index 8a01f1f692b8d..0115a62ae6aa1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -930,6 +930,8 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap) We will need Event_db_repository anyway, even if the scheduler is disabled - to perform events DDL. */ + DBUG_ASSERT(db_repository == 0); + if (!(db_repository= new Event_db_repository)) { res= TRUE; /* fatal error: request unireg_abort */ diff --git a/sql/field.cc b/sql/field.cc index 6d7cef198a8f9..f972c71558de0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1357,37 +1357,46 @@ bool Field::cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond, /* This handles all numeric and BIT data types. */ -bool Field::can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const +Data_type_compatibility +Field::can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) const { DBUG_ASSERT(cmp_type() != STRING_RESULT); DBUG_ASSERT(cmp_type() != TIME_RESULT); - return item->cmp_type() != TIME_RESULT; + return item->cmp_type() != TIME_RESULT ? + Data_type_compatibility::OK : + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } /* This handles all numeric and BIT data types. */ -bool Field::can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const +Data_type_compatibility +Field::can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) const { DBUG_ASSERT(cmp_type() != STRING_RESULT); DBUG_ASSERT(cmp_type() != TIME_RESULT); - return const_item->cmp_type() != TIME_RESULT; + return const_item->cmp_type() != TIME_RESULT ? + Data_type_compatibility::OK : + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } /* This covers all numeric types, BIT */ -bool Field::can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const +Data_type_compatibility +Field::can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const { DBUG_ASSERT(cmp_type() != TIME_RESULT); // Handled in Field_temporal DBUG_ASSERT(cmp_type() != STRING_RESULT); // Handled in Field_str descendants - return item->cmp_type() != TIME_RESULT; + return item->cmp_type() != TIME_RESULT ? + Data_type_compatibility::OK : + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } @@ -2051,13 +2060,35 @@ int Field::store_to_statistical_minmax_field(Field *field, String *val) } -int Field::store_from_statistical_minmax_field(Field *stat_field, String *str) +int Field::store_from_statistical_minmax_field(Field *stat_field, String *str, + MEM_ROOT *mem) { stat_field->val_str(str); return store_text(str->ptr(), str->length(), &my_charset_bin); } +/* + Same as above, but store the string in the statistics mem_root to make it + easy to free everything by just freeing the mem_root. +*/ + +int Field_blob::store_from_statistical_minmax_field(Field *stat_field, + String *str, + MEM_ROOT *mem) +{ + String *tmp= stat_field->val_str(str); + uchar *ptr; + if (!(ptr= (uchar*) memdup_root(mem, tmp->ptr(), tmp->length()))) + { + set_ptr((uint32) 0, NULL); + return 1; + } + set_ptr(tmp->length(), ptr); + return 0; +} + + /** Pack the field into a format suitable for storage and transfer. @@ -5943,17 +5974,21 @@ my_decimal *Field_temporal::val_decimal(my_decimal *d) } -bool Field_temporal::can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *value) const +Data_type_compatibility +Field_temporal::can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *value) const { - return true; // Field is of TIME_RESULT, which supersedes everything else. + // Field is of TIME_RESULT, which supersedes everything else. + return Data_type_compatibility::OK; } -bool Field_temporal::can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const +Data_type_compatibility +Field_temporal::can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) const { - return true; // Field is of TIME_RESULT, which supersedes everything else. + // Field is of TIME_RESULT, which supersedes everything else. + return Data_type_compatibility::OK; } @@ -7448,43 +7483,52 @@ uint32 Field_longstr::max_data_length() const } -bool +Data_type_compatibility Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond, const Item *item) const { - return cmp_is_done_using_type_handler_of_this(cond, item) && - charset() == cond->compare_collation(); + return !cmp_is_done_using_type_handler_of_this(cond, item) ? + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE : + charset() != cond->compare_collation() ? + Data_type_compatibility::INCOMPATIBLE_COLLATION : + Data_type_compatibility::OK; } -bool +Data_type_compatibility Field_longstr::cmp_to_string_with_stricter_collation(const Item_bool_func *cond, const Item *item) const { - return cmp_is_done_using_type_handler_of_this(cond, item) && - (charset() == cond->compare_collation() || - cond->compare_collation()->state & MY_CS_BINSORT); + return !cmp_is_done_using_type_handler_of_this(cond, item) ? + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE : + (charset() != cond->compare_collation() && + !(cond->compare_collation()->state & MY_CS_BINSORT)) ? + Data_type_compatibility::INCOMPATIBLE_COLLATION : + Data_type_compatibility::OK; } -bool Field_longstr::can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const +Data_type_compatibility +Field_longstr::can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) const { DBUG_ASSERT(cmp_type() == STRING_RESULT); return cmp_to_string_with_stricter_collation(cond, item); } -bool Field_longstr::can_optimize_hash_join(const Item_bool_func *cond, - const Item *item) const +Data_type_compatibility +Field_longstr::can_optimize_hash_join(const Item_bool_func *cond, + const Item *item) const { DBUG_ASSERT(cmp_type() == STRING_RESULT); return cmp_to_string_with_same_collation(cond, item); } -bool Field_longstr::can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const +Data_type_compatibility +Field_longstr::can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) const { /* Can't use indexes when comparing a string to a number or a date @@ -7495,9 +7539,10 @@ bool Field_longstr::can_optimize_group_min_max(const Item_bool_func *cond, } -bool Field_longstr::can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const +Data_type_compatibility +Field_longstr::can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const { return is_eq_func ? cmp_to_string_with_stricter_collation(cond, item) : @@ -9717,24 +9762,27 @@ bool Field_num::is_equal(const Column_definition &new_field) const } -bool Field_enum::can_optimize_range_or_keypart_ref(const Item_bool_func *cond, - const Item *item) const +Data_type_compatibility +Field_enum::can_optimize_range_or_keypart_ref(const Item_bool_func *cond, + const Item *item) const { switch (item->cmp_type()) { case TIME_RESULT: - return false; + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; case INT_RESULT: case DECIMAL_RESULT: case REAL_RESULT: - return true; + return Data_type_compatibility::OK; case STRING_RESULT: - return charset() == cond->compare_collation(); + return charset() == cond->compare_collation() ? + Data_type_compatibility::OK : + Data_type_compatibility::INCOMPATIBLE_COLLATION; case ROW_RESULT: DBUG_ASSERT(0); break; } - return false; + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } @@ -11265,6 +11313,102 @@ void Field::set_warning_truncated_wrong_value(const char *type_arg, } +/* + Give warning for unusable key + + Note that the caller is responsible to call it only under ther + right note_verbosity level +*/ + +void Field::raise_note_cannot_use_key_part(THD *thd, + uint keynr, uint part, + const LEX_CSTRING &op, + Item *value, + Data_type_compatibility reason) + const +{ + StringBuffer<128> value_buffer; + const LEX_CSTRING keyname= table->s->key_info[keynr].name; + size_t value_length; + + value->print(&value_buffer, QT_EXPLAIN); + value_length= Well_formed_prefix(value_buffer.charset(), + value_buffer.ptr(), + MY_MIN(value_buffer.length(), 64)).length(); + /* + We must use c_ptr() here for the 'T' argument as it only works with + zero terminated strings. + */ + switch (reason){ + case Data_type_compatibility::INCOMPATIBLE_COLLATION: + { + const LEX_CSTRING colf(charset()->coll_name); + const LEX_CSTRING colv(value->collation.collation->coll_name); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, + "Cannot use key %`.*s part[%u] for lookup: " + "%`.*s.%`.*s.%`.*s of collation %`.*s " + "%.*s \"%.*T\" of collation %`.*s", + (int) keyname.length, keyname.str, + part, + (int) table->s->db.length, table->s->db.str, + (int) table->s->table_name.length, + table->s->table_name.str, + (int) field_name.length, field_name.str, + (int) colf.length, colf.str, + (int) op.length, op.str, + (int) value_length, value_buffer.c_ptr_safe(), + (int) colv.length, colv.str); + } + break; + case Data_type_compatibility::OK: + DBUG_ASSERT(0); + /* fall through */ + case Data_type_compatibility::INCOMPATIBLE_DATA_TYPE: + { + const LEX_CSTRING dtypef(type_handler()->name().lex_cstring()); + const LEX_CSTRING dtypev(value->type_handler()->name().lex_cstring()); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, + "Cannot use key %`.*s part[%u] for lookup: " + "%`.*s.%`.*s.%`.*s of type %`.*s " + "%.*s \"%.*T\" of type %`.*s", + (int) keyname.length, keyname.str, + part, + (int) table->s->db.length, table->s->db.str, + (int) table->s->table_name.length, + table->s->table_name.str, + (int) field_name.length, field_name.str, + (int) dtypef.length, dtypef.str, + (int) op.length, op.str, + (int) value_length, value_buffer.c_ptr_safe(), + (int) dtypev.length, dtypev.str); + } + break; + } +} + + +/* + Give warning for unusable key + + Note that the caller is responsible to call it only under ther + right note_verbosity level +*/ + +void Field::raise_note_key_become_unused(THD *thd, const String &expr) const +{ + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, + "Cannot use key parts with %`.*s.%`.*s.%`.*s " + "in the rewritten condition: %`.*s", + (int) table->s->db.length, table->s->db.str, + (int) table->s->table_name.length, table->s->table_name.str, + (int) field_name.length, field_name.str, + (int) expr.length(), expr.ptr()); +} + + /* @brief Return possible keys for a field diff --git a/sql/field.h b/sql/field.h index 917d4aecf94b8..98f526c6ff142 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1017,7 +1017,8 @@ class Field: public Value_source field statistical table field str value buffer */ - virtual int store_from_statistical_minmax_field(Field *field, String *str); + virtual int store_from_statistical_minmax_field(Field *field, String *str, + MEM_ROOT *mem); #ifdef HAVE_MEM_CHECK /** @@ -1654,6 +1655,12 @@ class Field: public Value_source virtual void print_key_value(String *out, uint32 length); void print_key_part_value(String *out, const uchar *key, uint32 length); void print_key_value_binary(String *out, const uchar* key, uint32 length); + void raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, + const LEX_CSTRING &op, + Item *value, + const Data_type_compatibility reason) + const; + void raise_note_key_become_unused(THD *thd, const String &expr) const; protected: bool set_warning(unsigned int code, int cuted_increment) const { @@ -1682,11 +1689,12 @@ class Field: public Value_source Copy_func *get_identical_copy_func() const; bool cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond, const Item *item) const; - bool can_optimize_scalar_range(const RANGE_OPT_PARAM *param, + Data_type_compatibility can_optimize_scalar_range( + const RANGE_OPT_PARAM *param, const KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, - const Item *value) const; + Item *value) const; uchar *make_key_image(MEM_ROOT *mem_root, const KEY_PART *key_part); SEL_ARG *get_mm_leaf_int(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, @@ -1908,29 +1916,33 @@ class Field: public Value_source { return const_item; } - virtual bool can_optimize_keypart_ref(const Item_bool_func *cond, + virtual Data_type_compatibility can_optimize_keypart_ref( + const Item_bool_func *cond, const Item *item) const; - virtual bool can_optimize_hash_join(const Item_bool_func *cond, + virtual Data_type_compatibility can_optimize_hash_join( + const Item_bool_func *cond, const Item *item) const { return can_optimize_keypart_ref(cond, item); } - virtual bool can_optimize_group_min_max(const Item_bool_func *cond, + virtual Data_type_compatibility can_optimize_group_min_max( + const Item_bool_func *cond, const Item *const_item) const; /** Test if Field can use range optimizer for a standard comparison operation: <=, <, =, <=>, >, >= Note, this method does not cover spatial operations. */ - virtual bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const; + virtual Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const; virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value)= 0; - bool can_optimize_outer_join_table_elimination(const Item_bool_func *cond, + Data_type_compatibility can_optimize_outer_join_table_elimination( + const Item_bool_func *cond, const Item *item) const { // Exactly the same rules with REF access @@ -2216,9 +2228,11 @@ class Field_longstr :public Field_str return check_conversion_status(&copier, from + from_length, from_cs, count_spaces); } - bool cmp_to_string_with_same_collation(const Item_bool_func *cond, + Data_type_compatibility cmp_to_string_with_same_collation( + const Item_bool_func *cond, const Item *item) const; - bool cmp_to_string_with_stricter_collation(const Item_bool_func *cond, + Data_type_compatibility cmp_to_string_with_stricter_collation( + const Item_bool_func *cond, const Item *item) const; int compress(char *to, uint to_length, const char *from, uint length, @@ -2250,15 +2264,18 @@ class Field_longstr :public Field_str } bool match_collation_to_optimize_range() const { return true; } - bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const override; - bool can_optimize_hash_join(const Item_bool_func *cond, - const Item *item) const override; - bool can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const override; - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const override; + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) + const override; + Data_type_compatibility can_optimize_hash_join(const Item_bool_func *cond, + const Item *item) + const override; + Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) + const override; + Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const override; bool is_packable() const override { return true; } uint make_packed_sort_key_part(uchar *buff, const SORT_FIELD_ATTR *sort_field)override; @@ -2839,21 +2856,24 @@ class Field_vers_trx_id :public Field_longlong { return get_date(ltime, fuzzydate, (ulonglong) val_int()); } bool test_if_equality_guarantees_uniqueness(const Item *item) const override; - bool can_optimize_keypart_ref(const Item_bool_func *, const Item *) + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *, + const Item *) const override { - return true; + return Data_type_compatibility::OK; } - bool can_optimize_group_min_max(const Item_bool_func *, const Item *) + Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *, + const Item *) const override { - return true; + return Data_type_compatibility::OK; } - bool can_optimize_range(const Item_bool_func *, const Item *, bool) + Data_type_compatibility can_optimize_range(const Item_bool_func *, + const Item *, bool is_eq_func) const override { - return true; + return Data_type_compatibility::OK; } /* cmp_type() cannot be TIME_RESULT, because we want to compare this field against integers. But in all other cases we treat it as TIME_RESULT! */ @@ -3016,15 +3036,17 @@ class Field_null :public Field_str { uint size_of() const override final { return sizeof *this; } uint32 max_display_length() const override final { return 4; } void move_field_offset(my_ptrdiff_t ptr_diff) override final {} - bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const override final + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) + const override final { - return false; + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } - bool can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const override final + Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) + const override final { - return false; + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } }; @@ -3123,15 +3145,17 @@ class Field_temporal :public Field { { return pos_in_interval_val_real(min, max); } - bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const override; - bool can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const override; - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const override + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) + const override; + Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) + const override; + Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const override { - return true; + return Data_type_compatibility::OK; } SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, @@ -4487,6 +4511,8 @@ class Field_blob :public Field_longstr { } bool make_empty_rec_store_default_value(THD *thd, Item *item) override; int store(const char *to, size_t length, CHARSET_INFO *charset) override; + int store_from_statistical_minmax_field(Field *stat_field, String *str, + MEM_ROOT *mem) override; using Field_str::store; void hash_not_null(Hasher *hasher) override; double val_real() override; @@ -4736,7 +4762,8 @@ class Field_blob_compressed final :public Field_blob { class Field_enum :public Field_str { static void do_field_enum(Copy_field *copy_field); longlong val_int(const uchar *) const; - bool can_optimize_range_or_keypart_ref(const Item_bool_func *cond, + Data_type_compatibility can_optimize_range_or_keypart_ref( + const Item_bool_func *cond, const Item *item) const; protected: uint packlength; @@ -4829,13 +4856,15 @@ class Field_enum :public Field_str { const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; - bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const override + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) + const override { return can_optimize_range_or_keypart_ref(cond, item); } - bool can_optimize_group_min_max(const Item_bool_func *cond, - const Item *const_item) const override + Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) + const override { /* Can't use GROUP_MIN_MAX optimization for ENUM and SET, @@ -4844,11 +4873,11 @@ class Field_enum :public Field_str { It would return the records with min and max enum numeric indexes. "Bug#45300 MAX() and ENUM type" should be fixed first. */ - return false; + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const override + Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const override { return can_optimize_range_or_keypart_ref(cond, item); } diff --git a/sql/handler.cc b/sql/handler.cc index 9ac0a11a674ba..c732b7461b14f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1846,6 +1846,7 @@ int ha_commit_trans(THD *thd, bool all) (void) trans_rollback_stmt(thd); goto err; } + trt.table->file->extra(HA_EXTRA_RESET_STATE); // Here, the call will not commit inside InnoDB. It is only working // around closing thd->transaction.stmt open by TR_table::open(). if (all) @@ -7431,6 +7432,7 @@ int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no) KEY *key_info= table->key_info + key_no; Field *hash_field= key_info->key_part->field; uchar ptr[HA_HASH_KEY_LENGTH_WITH_NULL]; + String *blob_storage; DBUG_ENTER("handler::check_duplicate_long_entry_key"); DBUG_ASSERT((key_info->flags & HA_NULL_PART_KEY && @@ -7445,9 +7447,11 @@ int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no) result= lookup_handler->ha_index_init(key_no, 0); if (result) DBUG_RETURN(result); + blob_storage= (String*)alloca(sizeof(String)*table->s->virtual_not_stored_blob_fields); + table->remember_blob_values(blob_storage); store_record(table, file->lookup_buffer); - result= lookup_handler->ha_index_read_map(table->record[0], - ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT); + result= lookup_handler->ha_index_read_map(table->record[0], ptr, + HA_WHOLE_KEY, HA_READ_KEY_EXACT); if (!result) { bool is_same; @@ -7455,6 +7459,13 @@ int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no) Item_func_hash * temp= (Item_func_hash *)hash_field->vcol_info->expr; Item ** arguments= temp->arguments(); uint arg_count= temp->argument_count(); + // restore pointers after swap_values in TABLE::update_virtual_fields() + for (Field **vf= table->vfield; *vf; vf++) + { + if (!(*vf)->stored_in_db() && (*vf)->flags & BLOB_FLAG && + bitmap_is_set(table->read_set, (*vf)->field_index)) + ((Field_blob*)*vf)->swap_value_and_read_value(); + } do { my_ptrdiff_t diff= table->file->lookup_buffer - new_rec; @@ -7502,6 +7513,7 @@ int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no) } } restore_record(table, file->lookup_buffer); + table->restore_blob_values(blob_storage); lookup_handler->ha_index_end(); DBUG_RETURN(error); } diff --git a/sql/hostname.cc b/sql/hostname.cc index 18164b3251732..d5f342b9216f6 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -151,7 +151,7 @@ bool hostname_cache_init() if (!(hostname_cache= new Hash_filo(key_memory_host_cache_hostname, host_cache_size, key_offset, HOST_ENTRY_KEY_SIZE, - NULL, (my_hash_free_key) free, &my_charset_bin))) + NULL, (my_hash_free_key) my_free, &my_charset_bin))) return 1; hostname_cache->clear(); @@ -204,7 +204,8 @@ static void add_hostname_impl(const char *ip_key, const char *hostname, if (likely(entry == NULL)) { - entry= (Host_entry *) malloc(sizeof (Host_entry)); + entry= (Host_entry *) my_malloc(key_memory_host_cache_hostname, + sizeof (Host_entry), 0); if (entry == NULL) return; diff --git a/sql/item.cc b/sql/item.cc index 59b076483c45b..a55a4fedebf47 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2908,7 +2908,7 @@ Item_sp::execute_impl(THD *thd, Item **args, uint arg_count) init_sql_alloc(key_memory_sp_head_call_root, &sp_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); *sp_query_arena= Query_arena(&sp_mem_root, - Query_arena::STMT_INITIALIZED_FOR_SP); + Query_arena::STMT_SP_QUERY_ARGUMENTS); } bool err_status= m_sp->execute_function(thd, args, arg_count, @@ -8197,7 +8197,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) if (from_field != not_found_field) { Item_field* fld; - if (!(fld= new (thd->mem_root) Item_field(thd, from_field))) + if (!(fld= new (thd->mem_root) Item_field(thd, context, from_field))) goto error; thd->change_item_tree(reference, fld); mark_as_dependent(thd, last_checked_context->select_lex, diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6f1640f995edf..58ef471bf8c17 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -411,6 +411,51 @@ void Item_func::convert_const_compared_to_int_field(THD *thd) } +/* + Iterate through arguments and compare them to the original arguments + in "old_args". If some argument was replaced: + - from Item_field pointing to an indexed Field + - to something else (for example, Item_func_conv_charset) + then we cannot use Field's indexes for range access any more. + Raise a note in this case. + + Note, the number of arguments in "old_args" can be smaller than arg_count. + For example, for LIKE, BETWEEN, IN we pass only args[0] in old_args. + + For a comparison predicate we pass both args[0] and args[1] to cover both: + - WHERE field=expr + - WHERE expr=field +*/ + +void Item_bool_func::raise_note_if_key_become_unused(THD *thd, const Item_args &old_args) +{ + if (!(thd->variables.note_verbosity & NOTE_VERBOSITY_UNUSABLE_KEYS)) + return; + + DBUG_ASSERT(old_args.argument_count() <= arg_count); + for (uint i= 0; i < old_args.argument_count(); i++) + { + if (args[i] != old_args.arguments()[i]) + { + DBUG_ASSERT(old_args.arguments()[i]->fixed()); + Item *real_item= old_args.arguments()[i]->real_item(); + if (real_item->type() == Item::FIELD_ITEM) + { + Field *field= static_cast(real_item)->field; + if (field->flags & PART_KEY_FLAG) + { + /* + It used to be Item_field (with indexes!) before the condition + rewrite. Now it's something else. Cannot use indexes any more. + */ + field->raise_note_key_become_unused(thd, Print(this, QT_EXPLAIN)); + } + } + } + } +} + + bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) { DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3 @@ -458,7 +503,11 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd) */ if (!args[0] || !args[1]) return FALSE; - return setup_args_and_comparator(current_thd, &cmp); + Item_args old_args(args[0], args[1]); + if (setup_args_and_comparator(thd, &cmp)) + return true; + raise_note_if_key_become_unused(thd, old_args); + return false; } @@ -2127,6 +2176,7 @@ bool Item_func_between::fix_length_and_dec(THD *thd) */ if (!args[0] || !args[1] || !args[2]) return TRUE; + Item_args old_predicant(args[0]); if (m_comparator.aggregate_for_comparison(Item_func_between:: func_name_cstring(), args, 3, false)) @@ -2134,9 +2184,10 @@ bool Item_func_between::fix_length_and_dec(THD *thd) DBUG_ASSERT(thd->is_error()); return TRUE; } - - return m_comparator.type_handler()-> - Item_func_between_fix_length_and_dec(this); + if (m_comparator.type_handler()->Item_func_between_fix_length_and_dec(this)) + return true; + raise_note_if_key_become_unused(thd, old_predicant); + return false; } @@ -4470,6 +4521,7 @@ bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types) bool Item_func_in::fix_length_and_dec(THD *thd) { + Item_args old_predicant(args[0]); uint found_types; m_comparator.set_handler(type_handler_varchar.type_handler_for_comparison()); max_length= 1; @@ -4480,6 +4532,42 @@ bool Item_func_in::fix_length_and_dec(THD *thd) return TRUE; } + if (!arg_types_compatible && comparator_count() == 2) + { + /* + Catch a special case: a mixture of signed and unsigned integer types. + in_longlong can handle such cases. + + Note, prepare_predicant_and_values() aggregates this mixture as follows: + - signed+unsigned produce &type_handler_newdecimal. + - signed+signed or unsigned+unsigned produce &type_handler_slonglong + So we have extactly two distinct handlers. + + The code below assumes that unsigned longlong is handled + by &type_handler_slonglong in comparison context, + which may change in the future to &type_handler_ulonglong. + The DBUG_ASSERT is needed to address this change here properly. + */ + DBUG_ASSERT(type_handler_ulonglong.type_handler_for_comparison() == + &type_handler_slonglong); + // Let's check if all arguments are of integer types + uint found_int_args= 0; + for (uint i= 0; i < arg_count; i++, found_int_args++) + { + if (args[i]->type_handler_for_comparison() != &type_handler_slonglong) + break; + } + if (found_int_args == arg_count) + { + // All arguments are integers. Switch to integer comparison. + arg_types_compatible= true; + DBUG_EXECUTE_IF("Item_func_in", + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "DBUG: found a mix of UINT and SINT");); + m_comparator.set_handler(&type_handler_slonglong); + } + } + if (arg_types_compatible) // Bisection condition #1 { if (m_comparator.type_handler()-> @@ -4489,7 +4577,7 @@ bool Item_func_in::fix_length_and_dec(THD *thd) else { DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT); - if ( fix_for_scalar_comparison_using_cmp_items(thd, found_types)) + if (fix_for_scalar_comparison_using_cmp_items(thd, found_types)) return TRUE; } @@ -4498,6 +4586,7 @@ bool Item_func_in::fix_length_and_dec(THD *thd) ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s", arg_types_compatible ? "yes" : "no", array != NULL ? "yes" : "no");); + raise_note_if_key_become_unused(thd, old_predicant); return FALSE; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 13e12af750b3b..a1de330e97f0e 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -216,6 +216,7 @@ class Item_bool_func :public Item_int_func, virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value); + void raise_note_if_key_become_unused(THD *thd, const Item_args &old_args); public: Item_bool_func(THD *thd): Item_int_func(thd) {} Item_bool_func(THD *thd, Item *a): Item_int_func(thd, a) {} @@ -2974,7 +2975,11 @@ class Item_func_like :public Item_bool_func2 bool fix_length_and_dec(THD *thd) override { max_length= 1; - return agg_arg_charsets_for_comparison(cmp_collation, args, 2); + Item_args old_predicant(args[0]); + if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) + return true; + raise_note_if_key_become_unused(current_thd, old_predicant); + return false; } void cleanup() override; diff --git a/sql/log.cc b/sql/log.cc index 2da159cf44e27..66e83a5a0c08d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3439,6 +3439,23 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, goto err; thd->free_items(); } + if ((log_slow_verbosity & LOG_SLOW_VERBOSITY_WARNINGS) && + thd->get_stmt_da()->unsafe_statement_warn_count()) + { + Diagnostics_area::Sql_condition_iterator it= + thd->get_stmt_da()->sql_conditions(); + ulong idx, max_warnings= thd->variables.log_slow_max_warnings; + const Sql_condition *err; + my_b_printf(&log_file, "# Warnings\n"); + for (idx= 0; (err= it++) && idx < max_warnings; idx++) + { + my_b_printf(&log_file, "# %-15s %4u %.*s\n", + warning_level_names[err->get_level()].str, + (uint) err->get_sql_errno(), + (int) err->get_message_octet_length(), + err->get_message_text()); + } + } if (thd->db.str && strcmp(thd->db.str, db)) { // Database changed if (my_b_printf(&log_file,"use %s;\n",thd->db.str)) @@ -3463,7 +3480,6 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, end, -10); } } - /* This info used to show up randomly, depending on whether the query checked the query start time or not. now we always write current diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index dece441984960..038bee34f5bc1 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5127,7 +5127,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) ignored_error_code(actual_error) : 0); #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_ignored_error_code(this, actual_error)) + if (WSREP(thd) && thd->wsrep_applier && + wsrep_ignored_error_code(this, actual_error)) { idempotent_error= true; thd->wsrep_has_ignored_error= true; @@ -6668,7 +6669,7 @@ Rows_log_event::write_row(rpl_group_info *rgi, DBUG_RETURN(error); } - if (m_curr_row == m_rows_buf && !invoke_triggers) + if (m_curr_row == m_rows_buf && !invoke_triggers && !table->s->long_unique_table) { /* This table has no triggers so we can do bulk insert. @@ -6701,6 +6702,9 @@ Rows_log_event::write_row(rpl_group_info *rgi, DBUG_PRINT_BITSET("debug", "rpl_write_set: %s", table->rpl_write_set); DBUG_PRINT_BITSET("debug", "read_set: %s", table->read_set); + if (table->s->long_unique_table) + table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE); + if (invoke_triggers && unlikely(process_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE, TRUE))) { @@ -6810,7 +6814,14 @@ Rows_log_event::write_row(rpl_group_info *rgi, Now, record[1] should contain the offending row. That will enable us to update it or, alternatively, delete it (so that we can insert the new row afterwards). - */ + */ + if (table->s->long_unique_table) + { + /* same as for REPLACE/ODKU */ + table->move_fields(table->field, table->record[1], table->record[0]); + table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); + table->move_fields(table->field, table->record[0], table->record[1]); + } /* If row is incomplete we will use the record found to fill @@ -6820,6 +6831,8 @@ Rows_log_event::write_row(rpl_group_info *rgi, { restore_record(table,record[1]); error= unpack_current_row(rgi); + if (table->s->long_unique_table) + table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE); } DBUG_PRINT("debug",("preparing for update: before and after image")); @@ -7827,6 +7840,8 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi) thd_proc_info(thd, message); if (unlikely((error= unpack_current_row(rgi, &m_cols_ai)))) goto err; + if (m_table->s->long_unique_table) + m_table->update_virtual_fields(m_table->file, VCOL_UPDATE_FOR_WRITE); /* Now we have the right row to update. The old row (the one we're diff --git a/sql/log_slow.h b/sql/log_slow.h index 366906d7cb340..eb6895b973d23 100644 --- a/sql/log_slow.h +++ b/sql/log_slow.h @@ -23,7 +23,8 @@ #define LOG_SLOW_VERBOSITY_QUERY_PLAN (1U << 1) #define LOG_SLOW_VERBOSITY_EXPLAIN (1U << 2) #define LOG_SLOW_VERBOSITY_STORAGE_ENGINE (1U << 3) /* Replaces InnoDB */ -#define LOG_SLOW_VERBOSITY_FULL (1U << 4) +#define LOG_SLOW_VERBOSITY_WARNINGS (1U << 4) +#define LOG_SLOW_VERBOSITY_FULL (1U << 5) #define LOG_SLOW_VERBOSITY_ENGINE (LOG_SLOW_VERBOSITY_FULL | \ LOG_SLOW_VERBOSITY_INNODB | \ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dd671173b40aa..02268d8277cc0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -946,6 +946,7 @@ PSI_mutex_key key_LOCK_gtid_waiting; PSI_mutex_key key_LOCK_after_binlog_sync; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; PSI_mutex_key key_TABLE_SHARE_LOCK_share; +PSI_mutex_key key_TABLE_SHARE_LOCK_statistics; PSI_mutex_key key_LOCK_ack_receiver; PSI_mutex_key key_TABLE_SHARE_LOCK_rotation; @@ -1017,6 +1018,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0}, { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0}, { &key_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0}, + { &key_TABLE_SHARE_LOCK_statistics, "TABLE_SHARE::LOCK_statistics", 0}, { &key_TABLE_SHARE_LOCK_rotation, "TABLE_SHARE::LOCK_rotation", 0}, { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL}, { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL}, @@ -4456,6 +4458,9 @@ static int init_common_variables() return 1; } + if (tls_version & (VIO_TLSv1_0 + VIO_TLSv1_1)) + sql_print_warning("TLSv1.0 and TLSv1.1 are insecure and should not be used for tls_version"); + #ifdef WITH_WSREP /* We need to initialize auxiliary variables, that will be @@ -9145,7 +9150,7 @@ static int test_if_case_insensitive(const char *dir_name) buff, 0666, O_RDWR, MYF(0))) < 0) { if (!opt_abort) - sql_print_warning("Can't create test file %s", buff); + sql_print_warning("Can't create test file '%s' (Errcode: %M)", buff, my_errno); DBUG_RETURN(-1); } mysql_file_close(file, MYF(0)); @@ -9518,8 +9523,8 @@ PSI_memory_key key_memory_thd_transactions; PSI_memory_key key_memory_user_conn; PSI_memory_key key_memory_user_var_entry; PSI_memory_key key_memory_user_var_entry_value; - PSI_memory_key key_memory_String_value; +PSI_memory_key key_memory_WSREP; #ifdef HAVE_PSI_INTERFACE @@ -9814,6 +9819,7 @@ static PSI_memory_info all_server_memory[]= // { &key_memory_get_all_tables, "get_all_tables", 0}, // { &key_memory_fill_schema_schemata, "fill_schema_schemata", 0}, { &key_memory_native_functions, "native_functions", PSI_FLAG_GLOBAL}, + { &key_memory_WSREP, "wsrep", 0 } }; /** diff --git a/sql/mysqld.h b/sql/mysqld.h index 646e6cbf19596..756d99e2cb826 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -341,6 +341,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_rpl_group_info_sleep_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, + key_TABLE_SHARE_LOCK_statistics, key_LOCK_start_thread, key_LOCK_error_messages, key_PARTITION_LOCK_auto_inc; @@ -543,6 +544,7 @@ extern PSI_memory_key key_memory_get_all_tables; extern PSI_memory_key key_memory_fill_schema_schemata; extern PSI_memory_key key_memory_native_functions; extern PSI_memory_key key_memory_JSON; +extern PSI_memory_key key_memory_WSREP; /* MAINTAINER: Please keep this list in order, to limit merge collisions. diff --git a/sql/opt_histogram_json.cc b/sql/opt_histogram_json.cc index bea18050a59f6..1aec9e53917f2 100644 --- a/sql/opt_histogram_json.cc +++ b/sql/opt_histogram_json.cc @@ -743,7 +743,6 @@ int Histogram_json_hb::parse_bucket(json_engine_t *je, Field *field, bool Histogram_json_hb::parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, Field *field, - Histogram_type type_arg, const char *hist_data, size_t hist_data_len) { json_engine_t je; @@ -753,7 +752,6 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, const char *db_name, int end_element; bool end_assigned; DBUG_ENTER("Histogram_json_hb::parse"); - DBUG_ASSERT(type_arg == JSON_HB); json_scan_start(&je, &my_charset_utf8mb4_bin, (const uchar*)hist_data, diff --git a/sql/opt_histogram_json.h b/sql/opt_histogram_json.h index e9b69869f4b80..248467928fd85 100644 --- a/sql/opt_histogram_json.h +++ b/sql/opt_histogram_json.h @@ -64,7 +64,7 @@ are not mapped to any UTF8 character. */ -class Histogram_json_hb : public Histogram_base +class Histogram_json_hb final : public Histogram_base { size_t size; /* Number of elements in the histogram */ @@ -93,8 +93,8 @@ class Histogram_json_hb : public Histogram_base static constexpr const char* JSON_NAME="histogram_hb"; bool parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, - Field *field, Histogram_type type_arg, - const char *hist_data, size_t hist_data_len) override; + Field *field, const char *hist_data, + size_t hist_data_len) override; void serialize(Field *field) override; @@ -121,7 +121,6 @@ class Histogram_json_hb : public Histogram_base { return (uint)size; } - void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, ulonglong size) override; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 62c66159bc667..cd8c249c331b2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -728,7 +728,8 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param, result_keys.set_bit(key_no); #ifdef EXTRA_DEBUG - if (param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) + if (param->alloced_sel_args < + param->thd->variables.optimizer_max_sel_args) { key1= result->keys[key_no]; (key1)->test_use_count(key1); @@ -2058,7 +2059,7 @@ SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG *tmp; /* Bail out if we have already generated too many SEL_ARGs */ - if (++param->alloced_sel_args > MAX_SEL_ARGS) + if (++param->alloced_sel_args > param->thd->variables.optimizer_max_sel_args) return 0; if (type != KEY_RANGE) @@ -2714,7 +2715,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ha_rows limit, bool force_quick_range, bool ordered_output, bool remove_false_parts_of_where, - bool only_single_index_range_scan) + bool only_single_index_range_scan, + bool suppress_unusable_key_notes) { uint idx; Item *notnull_cond= NULL; @@ -2782,6 +2784,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, DBUG_RETURN(0); // Fatal error flag is set /* set up parameter that is passed to all functions */ + bzero((void*) ¶m, sizeof(param)); param.thd= thd; param.baseflag= file->ha_table_flags(); param.prev_tables=prev_tables | const_tables; @@ -2798,6 +2801,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.max_key_parts= 0; param.remove_false_where_parts= remove_false_parts_of_where; param.force_default_mrr= ordered_output; + param.note_unusable_keys= (!suppress_unusable_key_notes && + thd->give_notes_for_unusable_keys()); + param.possible_keys.clear_all(); thd->no_errors=1; // Don't warn about NULL @@ -2930,7 +2936,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, if (notnull_cond_tree) tree= tree_and(¶m, tree, notnull_cond_tree); if (thd->trace_started() && - param.alloced_sel_args >= SEL_ARG::MAX_SEL_ARGS) + param.alloced_sel_args >= thd->variables.optimizer_max_sel_args) { Json_writer_object wrapper(thd); Json_writer_object obj(thd, "sel_arg_alloc_limit_hit"); @@ -4074,6 +4080,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) prune_param.part_info= part_info; init_sql_alloc(key_memory_quick_range_select_root, &alloc, thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC)); + bzero((void*) range_par, sizeof(*range_par)); range_par->mem_root= &alloc; range_par->old_root= thd->mem_root; @@ -4099,6 +4106,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) range_par->remove_jump_scans= FALSE; range_par->real_keynr[0]= 0; range_par->alloced_sel_args= 0; + range_par->note_unusable_keys= 0; thd->no_errors=1; // Don't warn about NULL thd->mem_root=&alloc; @@ -9009,14 +9017,21 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, if (key_part->image_type != Field::itRAW) DBUG_RETURN(0); + uint keynr= param->real_keynr[key_part->key]; if (param->using_real_indexes && - !field->optimize_range(param->real_keynr[key_part->key], - key_part->part)) + !field->optimize_range(keynr, key_part->part)) DBUG_RETURN(0); if (field->result_type() == STRING_RESULT && field->charset() != compare_collation()) + { + if (param->note_unusable_keys) + field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, + func_name_cstring(), value, + Data_type_compatibility:: + INCOMPATIBLE_COLLATION); DBUG_RETURN(0); + } StringBuffer tmp(value->collation.collation); String *res; @@ -9027,7 +9042,14 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, if (field->cmp_type() != STRING_RESULT || field->type_handler() == &type_handler_enum || field->type_handler() == &type_handler_set) + { + if (param->note_unusable_keys) + field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, + func_name_cstring(), value, + Data_type_compatibility:: + INCOMPATIBLE_DATA_TYPE); DBUG_RETURN(0); + } /* TODO: @@ -9107,19 +9129,44 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param, } -bool Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, - const KEY_PART *key_part, - const Item_bool_func *cond, - scalar_comparison_op op, - const Item *value) const +Data_type_compatibility +Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, + const KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, + Item *value) const { bool is_eq_func= op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL; - if ((param->using_real_indexes && - !optimize_range(param->real_keynr[key_part->key], - key_part->part) && !is_eq_func) || - !can_optimize_range(cond, value, is_eq_func)) - return false; - return true; + uint keynr= param->real_keynr[key_part->key]; + if (param->using_real_indexes && + !optimize_range(keynr, key_part->part) && !is_eq_func) + return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; + Data_type_compatibility compat= can_optimize_range(cond, value, is_eq_func); + if (compat == Data_type_compatibility::OK) + return compat; + /* + Raise a note that the index part could not be used. + + TODO: Perhaps we also need to raise a similar note when + a partition could not be used (when using_real_indexes==false). + */ + if (param->using_real_indexes && param->note_unusable_keys) + { + DBUG_ASSERT(keynr < table->s->keys); + /* + Here "cond" can be any sargable predicate, e.g.: + 1. field=value (and other scalar comparison predicates: <, <=, <=>, =>, >) + 2. field [NOT] BETWEEN value1 AND value2 + 3. field [NOT] IN (value1, value2...) + Don't print the entire "cond" as in case of BETWEEN and IN + it would list all values. + Let's only print the current field/value pair. + */ + raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, + scalar_comparison_op_to_lex_cstring(op), + value, compat); + } + return compat; } @@ -9159,7 +9206,8 @@ SEL_ARG *Field_num::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, scalar_comparison_op op, Item *value) { DBUG_ENTER("Field_num::get_mm_leaf"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -9175,7 +9223,8 @@ SEL_ARG *Field_temporal::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, scalar_comparison_op op, Item *value) { DBUG_ENTER("Field_temporal::get_mm_leaf"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -9193,7 +9242,8 @@ SEL_ARG *Field_date_common::get_mm_leaf(RANGE_OPT_PARAM *prm, Item *value) { DBUG_ENTER("Field_date_common::get_mm_leaf"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -9235,7 +9285,8 @@ SEL_ARG *Field_str::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, scalar_comparison_op op, Item *value) { DBUG_ENTER("Field_str::get_mm_leaf"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -9256,7 +9307,8 @@ SEL_ARG *Field::get_mm_leaf_int(RANGE_OPT_PARAM *prm, KEY_PART *key_part, bool unsigned_field) { DBUG_ENTER("Field::get_mm_leaf_int"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -9524,7 +9576,8 @@ int and_range_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree1, SEL_TREE *tree2, } result_keys.set_bit(key_no); #ifdef EXTRA_DEBUG - if (param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) + if (param->alloced_sel_args < + param->thd->variables.optimizer_max_sel_args) key->test_use_count(key); #endif } @@ -10177,7 +10230,8 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, key1->weight+= (tmp? tmp->weight: 0) - old_weight; if (use_count) next->increment_use_count(use_count); - if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS) + if (param->alloced_sel_args > + param->thd->variables.optimizer_max_sel_args) break; } else @@ -14888,13 +14942,16 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, Field *field= min_max_arg_item->field; if (!args[2]) // this is a binary function { - if (!field->can_optimize_group_min_max(bool_func, args[1])) + if (field->can_optimize_group_min_max(bool_func, args[1]) != + Data_type_compatibility::OK) DBUG_RETURN(FALSE); } else // this is BETWEEN { - if (!field->can_optimize_group_min_max(bool_func, args[1]) || - !field->can_optimize_group_min_max(bool_func, args[2])) + if (field->can_optimize_group_min_max(bool_func, args[1]) != + Data_type_compatibility::OK || + field->can_optimize_group_min_max(bool_func, args[2]) != + Data_type_compatibility::OK) DBUG_RETURN(FALSE); } } diff --git a/sql/opt_range.h b/sql/opt_range.h index a8515f4861806..69f556334b845 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -352,7 +352,7 @@ class SEL_ARG :public Sql_alloc #endif /* See RANGE_OPT_PARAM::alloced_sel_args */ - enum { MAX_SEL_ARGS = 16000 }; + enum { DEFAULT_MAX_SEL_ARGS = 16000 }; SEL_ARG() = default; SEL_ARG(SEL_ARG &); @@ -891,6 +891,8 @@ class RANGE_OPT_PARAM */ bool remove_false_where_parts; + bool note_unusable_keys; // Give SQL notes for unusable keys + /* used_key_no -> table_key_no translation table. Only makes sense if using_real_indexes==TRUE @@ -916,7 +918,7 @@ class RANGE_OPT_PARAM thd->killed || thd->is_fatal_error || thd->is_error() || - alloced_sel_args > SEL_ARG::MAX_SEL_ARGS; + alloced_sel_args > thd->variables.optimizer_max_sel_args; } }; @@ -1919,7 +1921,8 @@ class SQL_SELECT :public Sql_alloc { int test_quick_select(THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range, bool ordered_output, bool remove_false_parts_of_where, - bool only_single_index_range_scan); + bool only_single_index_range_scan, + bool suppress_unusable_key_notes = 0); }; diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index 99e25a5338a12..ae73eb75a1cf2 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -1593,7 +1593,8 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod, left->real_item()->type() == Item::FIELD_ITEM) { Field *field= ((Item_field*)left->real_item())->field; - if (!field->can_optimize_outer_join_table_elimination(cond, right)) + if (field->can_optimize_outer_join_table_elimination(cond, right) != + Data_type_compatibility::OK) return; Dep_value_field *field_val; if ((field_val= ctx->get_field_value(field))) diff --git a/sql/protocol.cc b/sql/protocol.cc index 26bc94c146320..6667129d8bb67 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -324,6 +324,8 @@ Protocol::net_send_eof(THD *thd, uint server_status, uint statement_warn_count) NET *net= &thd->net; bool error= FALSE; DBUG_ENTER("Protocol::net_send_eof"); + DBUG_PRINT("enter", ("status: %u warn_count: %u", + server_status, statement_warn_count)); /* Check if client understand new format packets (OK instead of EOF) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 417c57def93fe..95a1234ec9a0a 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -221,6 +221,7 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id, waiting for this). In most cases (normal DML), it will be a no-op. */ rgi->mark_start_commit_no_lock(); + rgi->commit_orderer.wakeup_blocked= false; if (entry->last_committed_sub_id < sub_id) { @@ -852,6 +853,10 @@ retry_event_group(rpl_group_info *rgi, rpl_parallel_thread *rpt, event_count= 0; err= 0; errmsg= NULL; +#ifdef WITH_WSREP + thd->wsrep_cs().reset_error(); + WSREP_DEBUG("retrying async replication event"); +#endif /* WITH_WSREP */ /* If we already started committing before getting the deadlock (or other @@ -949,6 +954,7 @@ retry_event_group(rpl_group_info *rgi, rpl_parallel_thread *rpt, err= rgi->worker_error= 1; my_error(ER_PRIOR_COMMIT_FAILED, MYF(0)); mysql_mutex_unlock(&entry->LOCK_parallel_entry); + goto err; } mysql_mutex_unlock(&entry->LOCK_parallel_entry); @@ -990,7 +996,17 @@ retry_event_group(rpl_group_info *rgi, rpl_parallel_thread *rpt, possibility of an old deadlock kill lingering on beyond this point. */ thd->reset_killed(); +#ifdef WITH_WSREP + if (wsrep_before_command(thd)) + { + WSREP_WARN("Parallel slave worker failed at wsrep_before_command() hook"); + err= 1; + goto err; + } + wsrep_start_trx_if_not_started(thd); + WSREP_DEBUG("parallel slave retry, after trx start"); +#endif /* WITH_WSREP */ strmake_buf(log_name, ir->name); if ((fd= open_binlog(&rlog, log_name, &errmsg)) <0) { @@ -1472,7 +1488,22 @@ handle_rpl_parallel_thread(void *arg) if (!thd->killed) { DEBUG_SYNC(thd, "rpl_parallel_before_mark_start_commit"); - rgi->mark_start_commit(); + if (thd->lex->stmt_accessed_temp_table()) + { + /* + Temporary tables are special, they require strict + single-threaded use as they have no locks protecting concurrent + access. Therefore, we cannot safely use the optimization of + overlapping the commit of this transaction with the start of the + following. + So we skip the early mark_start_commit() and also block any + wakeup_subsequent_commits() until this event group is fully + done, inside finish_event_group(). + */ + rgi->commit_orderer.wakeup_blocked= true; + } + else + rgi->mark_start_commit(); DEBUG_SYNC(thd, "rpl_parallel_after_mark_start_commit"); } } @@ -2548,21 +2579,6 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, /* The thread is ready to queue into. */ break; } - else if (unlikely(rli->sql_driver_thd->check_killed(1))) - { - unlock_or_exit_cond(rli->sql_driver_thd, &thr->LOCK_rpl_thread, - did_enter_cond, old_stage); - my_error(ER_CONNECTION_KILLED, MYF(0)); -#ifdef ENABLED_DEBUG_SYNC - DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", - { - debug_sync_set_action(rli->sql_driver_thd, - STRING_WITH_LEN("now SIGNAL wait_queue_killed")); - };); -#endif - slave_output_error_info(rgi, rli->sql_driver_thd); - return NULL; - } else { /* @@ -2590,6 +2606,23 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, old_stage); *did_enter_cond= true; } + + if (unlikely(rli->sql_driver_thd->check_killed(1))) + { + unlock_or_exit_cond(rli->sql_driver_thd, &thr->LOCK_rpl_thread, + did_enter_cond, old_stage); + my_error(ER_CONNECTION_KILLED, MYF(0)); +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", + { + debug_sync_set_action(rli->sql_driver_thd, + STRING_WITH_LEN("now SIGNAL wait_queue_killed")); + };); +#endif + slave_output_error_info(rgi, rli->sql_driver_thd); + return NULL; + } + mysql_cond_wait(&thr->COND_rpl_thread_queue, &thr->LOCK_rpl_thread); } } diff --git a/sql/slave.cc b/sql/slave.cc index 588b73b551136..12d57a56db4cd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3903,9 +3903,19 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, default: WSREP_DEBUG("SQL apply failed, res %d conflict state: %s", exec_res, wsrep_thd_transaction_state_str(thd)); - rli->abort_slave= 1; - rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR, rgi->gtid_info(), - "Node has dropped from cluster"); + /* + async replication thread should be stopped, if failure was + not due to optimistic parallel applying or if node + has dropped from cluster + */ + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + ((rli->mi->using_parallel() && + rli->mi->parallel_mode <= SLAVE_PARALLEL_CONSERVATIVE) || + wsrep_ready == 0)) { + rli->abort_slave= 1; + rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR, rgi->gtid_info(), + "Node has dropped from cluster"); + } break; } mysql_mutex_unlock(&thd->LOCK_thd_data); @@ -5357,6 +5367,19 @@ pthread_handler_t handle_slave_sql(void *arg) DBUG_ASSERT(rli->inited); DBUG_ASSERT(rli->mi == mi); + + /* + Reset errors for a clean start (otherwise, if the master is idle, the SQL + thread may execute no Query_log_event, so the error will remain even + though there's no problem anymore). Do not reset the master timestamp + (imagine the slave has caught everything, the STOP SLAVE and START SLAVE: + as we are not sure that we are going to receive a query, we want to + remember the last master timestamp (to say how many seconds behind we are + now. + But the master timestamp is reset by RESET SLAVE & CHANGE MASTER. + */ + rli->clear_error(); + mysql_mutex_lock(&rli->run_lock); DBUG_ASSERT(!rli->slave_running); errmsg= 0; @@ -5433,17 +5456,16 @@ pthread_handler_t handle_slave_sql(void *arg) mysql_mutex_unlock(&rli->run_lock); mysql_cond_broadcast(&rli->start_cond); - /* - Reset errors for a clean start (otherwise, if the master is idle, the SQL - thread may execute no Query_log_event, so the error will remain even - though there's no problem anymore). Do not reset the master timestamp - (imagine the slave has caught everything, the STOP SLAVE and START SLAVE: - as we are not sure that we are going to receive a query, we want to - remember the last master timestamp (to say how many seconds behind we are - now. - But the master timestamp is reset by RESET SLAVE & CHANGE MASTER. - */ - rli->clear_error(); +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("delay_sql_thread_after_release_run_lock", { + const char act[]= "now " + "signal sql_thread_run_lock_released " + "wait_for sql_thread_continue"; + DBUG_ASSERT(debug_sync_service); + DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); + };); +#endif + rli->parallel.reset(); //tell the I/O thread to take relay_log_space_limit into account from now on diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fec9946bdbb35..5fd6ab5210caa 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -555,6 +555,9 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent, :Query_arena(NULL, STMT_INITIALIZED_FOR_SP), Database_qualified_name(&null_clex_str, &null_clex_str), main_mem_root(*mem_root_arg), +#ifdef PROTECT_STATEMENT_MEMROOT + executed_counter(0), +#endif m_parent(parent), m_handler(sph), m_flags(0), @@ -812,6 +815,10 @@ sp_head::init(LEX *lex) */ lex->trg_table_fields.empty(); +#ifdef PROTECT_STATEMENT_MEMROOT + executed_counter= 0; +#endif + DBUG_VOID_RETURN; } @@ -1455,6 +1462,11 @@ sp_head::execute(THD *thd, bool merge_da_on_success) err_status= i->execute(thd, &ip); +#ifdef PROTECT_STATEMENT_MEMROOT + if (!err_status) + i->mark_as_run(); +#endif + #ifdef HAVE_PSI_STATEMENT_INTERFACE MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); thd->m_statement_psi= parent_locker; @@ -1558,6 +1570,16 @@ sp_head::execute(THD *thd, bool merge_da_on_success) /* Reset sp_rcontext::end_partial_result_set flag. */ ctx->end_partial_result_set= FALSE; +#ifdef PROTECT_STATEMENT_MEMROOT + if (thd->is_error()) + { + // Don't count a call ended with an error as normal run + executed_counter= 0; + main_mem_root.read_only= 0; + reset_instrs_executed_counter(); + } +#endif + } while (!err_status && likely(!thd->killed) && likely(!thd->is_fatal_error) && !thd->spcont->pause_state); @@ -1670,6 +1692,20 @@ sp_head::execute(THD *thd, bool merge_da_on_success) err_status|= mysql_change_db(thd, (LEX_CSTRING*)&saved_cur_db_name, TRUE) != 0; } + +#ifdef PROTECT_STATEMENT_MEMROOT + if (!err_status) + { + if (!main_mem_root.read_only && + has_all_instrs_executed()) + { + main_mem_root.read_only= 1; + } + ++executed_counter; + DBUG_PRINT("info", ("execute counter: %lu", executed_counter)); + } +#endif + m_flags&= ~IS_INVOKED; if (m_parent) m_parent->m_invoked_subroutine_count--; @@ -3370,6 +3406,37 @@ void sp_head::add_mark_lead(uint ip, List *leads) leads->push_front(i); } +#ifdef PROTECT_STATEMENT_MEMROOT + +int sp_head::has_all_instrs_executed() +{ + sp_instr *ip; + uint count= 0; + + for (uint i= 0; i < m_instr.elements; ++i) + { + get_dynamic(&m_instr, (uchar*)&ip, i); + if (ip->has_been_run()) + ++count; + } + + return count == m_instr.elements; +} + + +void sp_head::reset_instrs_executed_counter() +{ + sp_instr *ip; + + for (uint i= 0; i < m_instr.elements; ++i) + { + get_dynamic(&m_instr, (uchar*)&ip, i); + ip->mark_as_not_run(); + } +} + +#endif + void sp_head::opt_mark() { diff --git a/sql/sp_head.h b/sql/sp_head.h index 23566b5805f68..da4e5763a4848 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -140,6 +140,16 @@ class sp_head :private Query_arena, protected: MEM_ROOT main_mem_root; +#ifdef PROTECT_STATEMENT_MEMROOT + /* + The following data member is wholly for debugging purpose. + It can be used for possible crash analysis to determine how many times + the stored routine was executed before the mem_root marked read_only + was requested for a memory chunk. Additionally, a value of this data + member is output to the log with DBUG_PRINT. + */ + ulong executed_counter; +#endif public: /** Possible values of m_flags */ enum { @@ -835,6 +845,11 @@ class sp_head :private Query_arena, return ip; } +#ifdef PROTECT_STATEMENT_MEMROOT + int has_all_instrs_executed(); + void reset_instrs_executed_counter(); +#endif + /* Add tables used by routine to the table list. */ bool add_used_tables_to_table_list(THD *thd, TABLE_LIST ***query_tables_last_ptr, @@ -1122,6 +1137,9 @@ class sp_instr :public Query_arena, public Sql_alloc /// Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) :Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) +#ifdef PROTECT_STATEMENT_MEMROOT + , m_has_been_run(false) +#endif {} virtual ~sp_instr() @@ -1212,6 +1230,25 @@ class sp_instr :public Query_arena, public Sql_alloc } virtual PSI_statement_info* get_psi_info() = 0; +#ifdef PROTECT_STATEMENT_MEMROOT + bool has_been_run() const + { + return m_has_been_run; + } + + void mark_as_run() + { + m_has_been_run= true; + } + + void mark_as_not_run() + { + m_has_been_run= false; + } + +private: + bool m_has_been_run; +#endif }; // class sp_instr : public Sql_alloc diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 465145cf25f8b..e61b1d389b0aa 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -517,8 +517,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, List field_list; Protocol *protocol= thd->protocol; LEX *lex= thd->lex; - int result_code; - int compl_result_code; bool need_repair_or_alter= 0; wait_for_commit* suspended_wfc; bool is_table_modified= false; @@ -562,7 +560,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, bool collect_eis= FALSE; bool open_for_modify= org_open_for_modify; Recreate_info recreate_info; + int compl_result_code, result_code; + compl_result_code= result_code= HA_ADMIN_FAILED; storage_engine_name[0]= 0; // Marker that's not used DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str)); @@ -879,6 +879,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); } + /* Note: compl_result_code can be different from result_code here */ if (compl_result_code == HA_ADMIN_OK && collect_eis) { if (result_code == HA_ERR_TABLE_READONLY) @@ -917,15 +918,39 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, { TABLE *tab= table->table; Field **field_ptr= tab->field; + USED_MEM *memroot_block; + if (!lex->column_list) { + /* Fields we have to read from the engine */ bitmap_clear_all(tab->read_set); + /* Fields we want to have statistics for */ + bitmap_clear_all(&tab->has_value_set); + for (uint fields= 0; *field_ptr; field_ptr++, fields++) { - enum enum_field_types type= (*field_ptr)->type(); - if (type < MYSQL_TYPE_MEDIUM_BLOB || + Field *field= *field_ptr; + if (field->flags & LONG_UNIQUE_HASH_FIELD) + { + /* + No point in doing statistic for hash fields that should be + unique + */ + continue; + } + /* + Note that type() always return MYSQL_TYPE_BLOB for + all blob types. Another function needs to be added + if we in the future want to distingush between blob + types here. + */ + enum enum_field_types type= field->type(); + if (type < MYSQL_TYPE_TINY_BLOB || type > MYSQL_TYPE_BLOB) - tab->field[fields]->register_field_in_read_map(); + { + field->register_field_in_read_map(); + bitmap_set_bit(&tab->has_value_set, field->field_index); + } else push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NO_EIS_FOR_FIELD, @@ -939,9 +964,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, LEX_STRING *column_name; List_iterator_fast it(*lex->column_list); + /* Fields we have to read from the engine */ bitmap_clear_all(tab->read_set); + /* Fields we want to have statistics for */ + bitmap_clear_all(&tab->has_value_set); + while ((column_name= it++)) { + Field *field; + enum enum_field_types type; if (tab->s->fieldnames.type_names == 0 || (pos= find_type(&tab->s->fieldnames, column_name->str, column_name->length, 1)) <= 0) @@ -950,10 +981,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, break; } pos--; - enum enum_field_types type= tab->field[pos]->type(); - if (type < MYSQL_TYPE_MEDIUM_BLOB || - type > MYSQL_TYPE_BLOB) - tab->field[pos]->register_field_in_read_map(); + field= tab->field[pos]; + type= field->type(); + if (!(field->flags & LONG_UNIQUE_HASH_FIELD) && + (type < MYSQL_TYPE_TINY_BLOB || + type > MYSQL_TYPE_BLOB)) + { + field->register_field_in_read_map(); + bitmap_set_bit(&tab->has_value_set, field->field_index); + } else push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NO_EIS_FOR_FIELD, @@ -969,7 +1005,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, int pos; LEX_STRING *index_name; List_iterator_fast it(*lex->index_list); - tab->keys_in_use_for_query.clear_all(); while ((index_name= it++)) { @@ -983,17 +1018,21 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, tab->keys_in_use_for_query.set_bit(--pos); } } + /* Ensure that number of records are updated */ + tab->file->info(HA_STATUS_VARIABLE); + memroot_block= get_last_memroot_block(thd->mem_root); if (!(compl_result_code= - alloc_statistics_for_table(thd, table->table)) && + alloc_statistics_for_table(thd, tab, + &tab->has_value_set)) && !(compl_result_code= - collect_statistics_for_table(thd, table->table))) - compl_result_code= update_statistics_for_table(thd, table->table); + collect_statistics_for_table(thd, tab))) + compl_result_code= update_statistics_for_table(thd, tab); + free_statistics_for_table(tab); + free_all_new_blocks(thd->mem_root, memroot_block); } else compl_result_code= HA_ADMIN_FAILED; - if (table->table) - free_statistics_for_table(thd, table->table); if (compl_result_code) result_code= HA_ADMIN_FAILED; else @@ -1280,13 +1319,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (table->table && !table->view) { - /* - Don't skip flushing if we are collecting EITS statistics. - */ - const bool skip_flush= - (operator_func == &handler::ha_analyze) && - (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE) && - !collect_eis; + /* Skip FLUSH TABLES if we are doing analyze */ + const bool skip_flush= (operator_func == &handler::ha_analyze); if (table->table->s->tmp_table) { /* @@ -1306,6 +1340,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, table->table= 0; // For query cache query_cache_invalidate3(thd, table, 0); } + else if (collect_eis && skip_flush && compl_result_code == HA_ADMIN_OK) + { + TABLE_LIST *save_next_global= table->next_global; + table->next_global= 0; + read_statistics_for_tables(thd, table, true /* force_reload */); + table->next_global= save_next_global; + } } /* Error path, a admin command failed. */ if (thd->transaction_rollback_request || fatal_error) diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 2202cf24e1122..166b960082bd7 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -18,6 +18,7 @@ #include "sql_parse.h" // check_access #include "sql_table.h" // mysql_alter_table, // mysql_exchange_partition +#include "sql_statistics.h" // delete_statistics_for_column #include "sql_alter.h" #include "rpl_mi.h" #include "slave.h" @@ -34,6 +35,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root) check_constraint_list(rhs.check_constraint_list, mem_root), flags(rhs.flags), partition_flags(rhs.partition_flags), keys_onoff(rhs.keys_onoff), + original_table(0), partition_names(rhs.partition_names, mem_root), num_parts(rhs.num_parts), requested_algorithm(rhs.requested_algorithm), @@ -300,6 +302,79 @@ uint Alter_info::check_vcol_field(Item_field *item) const } +bool Alter_info::collect_renamed_fields(THD *thd) +{ + List_iterator_fast new_field_it; + Create_field *new_field; + DBUG_ENTER("Alter_info::collect_renamed_fields"); + + new_field_it.init(create_list); + while ((new_field= new_field_it++)) + { + Field *field= new_field->field; + + if (new_field->field && + cmp(&field->field_name, &new_field->field_name)) + { + field->flags|= FIELD_IS_RENAMED; + if (add_stat_rename_field(field, + &new_field->field_name, + thd->mem_root)) + DBUG_RETURN(true); + + } + } + DBUG_RETURN(false); +} + + +/* + Delete duplicate index found during mysql_prepare_create_table() + + Notes: + - In case of temporary generated foreign keys, the key_name may not + be set! These keys are ignored. +*/ + +bool Alter_info::add_stat_drop_index(THD *thd, const LEX_CSTRING *key_name) +{ + if (original_table && key_name->length) // If from alter table + { + KEY *key_info= original_table->key_info; + for (uint i= 0; i < original_table->s->keys; i++, key_info++) + { + if (key_info->name.length && + !lex_string_cmp(system_charset_info, &key_info->name, + key_name)) + return add_stat_drop_index(key_info, false, thd->mem_root); + } + } + return false; +} + + +void Alter_info::apply_statistics_deletes_renames(THD *thd, TABLE *table) +{ + List_iterator it_drop_field(drop_stat_fields); + List_iterator it_rename_field(rename_stat_fields); + List_iterator it_drop_index(drop_stat_indexes); + List_iterator it_rename_index(rename_stat_indexes); + + while (Field *field= it_drop_field++) + delete_statistics_for_column(thd, table, field); + + if (!rename_stat_fields.is_empty()) + (void) rename_columns_in_stat_table(thd, table, &rename_stat_fields); + + while (DROP_INDEX_STAT_PARAMS *key= it_drop_index++) + (void) delete_statistics_for_index(thd, table, key->key, + key->ext_prefixes_only); + + if (!rename_stat_indexes.is_empty()) + (void) rename_indexes_in_stat_table(thd, table, &rename_stat_indexes); +} + + Alter_table_ctx::Alter_table_ctx() : db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), new_db(null_clex_str), new_name(null_clex_str), new_alias(null_clex_str) @@ -493,6 +568,14 @@ bool Sql_cmd_alter_table::execute(THD *thd) 0, 0)) DBUG_RETURN(TRUE); /* purecov: inspected */ + if ((alter_info.partition_flags & ALTER_PARTITION_CONVERT_IN)) + { + TABLE_LIST *tl= first_table->next_local; + tl->grant.privilege= first_table->grant.privilege; + tl->grant.m_internal= first_table->grant.m_internal; + } + + /* If it is a merge table, check privileges for merge children. */ if (create_info.merge_list) { diff --git a/sql/sql_alter.h b/sql/sql_alter.h index 3b27277484c8b..1d1ad5b220aa8 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -105,10 +105,88 @@ class Alter_info ulong partition_flags; // Enable or disable keys. enum_enable_or_disable keys_onoff; + // Used only in add_stat_drop_index() + TABLE *original_table; // List of partitions. List partition_names; // Number of partitions. uint num_parts; + + /* List of fields that we should delete statistics from */ + List drop_stat_fields; + + struct DROP_INDEX_STAT_PARAMS + { + KEY *key; + bool ext_prefixes_only; + }; + + struct RENAME_COLUMN_STAT_PARAMS + { + Field *field; + LEX_CSTRING *name; + uint duplicate_counter; // For temporary names + }; + struct RENAME_INDEX_STAT_PARAMS + { + const KEY *key; + const LEX_CSTRING *name; + uint duplicate_counter; // For temporary names + uint usage_count; // How many rename entries + }; + + /* List of index that we should delete statistics from */ + List drop_stat_indexes; + + List rename_stat_fields; + + List rename_stat_indexes; + + bool add_stat_drop_index(KEY *key, bool ext_prefixes_only, + MEM_ROOT *mem_root) + { + DROP_INDEX_STAT_PARAMS *param; + if (!(param= (DROP_INDEX_STAT_PARAMS*) + alloc_root(mem_root, sizeof(*param)))) + return true; + param->key= key; + param->ext_prefixes_only= ext_prefixes_only; + return drop_stat_indexes.push_back(param, mem_root); + } + + bool add_stat_drop_index(THD *thd, const LEX_CSTRING *key_name); + + bool add_stat_rename_index(const KEY *key, const LEX_CSTRING *name, + MEM_ROOT *mem_root) + { + RENAME_INDEX_STAT_PARAMS *param; + if (!(param= (RENAME_INDEX_STAT_PARAMS*) + alloc_root(mem_root, sizeof(*param)))) + return true; + param->key= key; + param->name= name; + param->usage_count= 0; + return rename_stat_indexes.push_back(param, mem_root); + } + + bool add_stat_rename_field(Field *field, LEX_CSTRING *name, + MEM_ROOT *mem_root) + { + RENAME_COLUMN_STAT_PARAMS *param; + if (!(param= (RENAME_COLUMN_STAT_PARAMS*) + alloc_root(mem_root, sizeof(*param)))) + return true; + param->field= field; + param->name= name; + param->duplicate_counter= 0; + return rename_stat_fields.push_back(param, mem_root); + } + + bool collect_renamed_fields(THD *thd); + + /* Delete/update statistics in EITS tables */ + void apply_statistics_deletes_renames(THD *thd, TABLE *table); + private: // Type of ALTER TABLE algorithm. enum_alter_table_algorithm requested_algorithm; @@ -121,6 +199,7 @@ class Alter_info Alter_info() : flags(0), partition_flags(0), keys_onoff(LEAVE_AS_IS), + original_table(0), num_parts(0), requested_algorithm(ALTER_TABLE_ALGORITHM_NONE), requested_lock(ALTER_TABLE_LOCK_DEFAULT) @@ -135,6 +214,10 @@ class Alter_info create_list.empty(); alter_index_ignorability_list.empty(); check_constraint_list.empty(); + drop_stat_fields.empty(); + drop_stat_indexes.empty(); + rename_stat_fields.empty(); + rename_stat_indexes.empty(); flags= 0; partition_flags= 0; keys_onoff= LEAVE_AS_IS; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 70794b5752b60..c96a7847f840c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -74,6 +74,8 @@ No_such_table_error_handler::handle_condition(THD *, Sql_condition ** cond_hdl) { *cond_hdl= NULL; + if (!first_error) + first_error= sql_errno; if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE) { m_handled_errors++; @@ -96,7 +98,6 @@ bool No_such_table_error_handler::safely_trapped_errors() return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); } - /** This internal handler is used to trap ER_NO_SUCH_TABLE and ER_WRONG_MRG_TABLE errors during CHECK/REPAIR TABLE for MERGE @@ -2126,10 +2127,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) goto err_lock; } - /* Open view */ - if (mysql_make_view(thd, share, table_list, false)) - goto err_lock; - /* This table is a view. Validate its metadata version: in particular, that it was a view when the statement was prepared. @@ -2137,6 +2134,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (check_and_update_table_version(thd, table_list, share)) goto err_lock; + /* Open view */ + if (mysql_make_view(thd, share, table_list, false)) + goto err_lock; + /* TODO: Don't free this */ tdc_release_share(share); @@ -4209,6 +4210,12 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags, if (tables->open_strategy && !tables->table) goto end; + /* Check and update metadata version of a base table. */ + error= check_and_update_table_version(thd, tables, tables->table->s); + + if (unlikely(error)) + goto end; + error= extend_table_list(thd, tables, prelocking_strategy, has_prelocking_list); if (unlikely(error)) goto end; @@ -4216,11 +4223,6 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags, /* Copy grant information from TABLE_LIST instance to TABLE one. */ tables->table->grant= tables->grant; - /* Check and update metadata version of a base table. */ - error= check_and_update_table_version(thd, tables, tables->table->s); - - if (unlikely(error)) - goto end; /* After opening a MERGE table add the children to the query list of tables, so that they are opened too. @@ -5629,7 +5631,8 @@ bool open_and_lock_tables(THD *thd, const DDL_options_st &options, goto err; /* Don't read statistics tables when opening internal tables */ - if (!(flags & MYSQL_OPEN_IGNORE_LOGGING_FORMAT)) + if (!(flags & (MYSQL_OPEN_IGNORE_LOGGING_FORMAT | + MYSQL_OPEN_IGNORE_ENGINE_STATS))) (void) read_statistics_for_tables_if_needed(thd, tables); if (derived) diff --git a/sql/sql_base.h b/sql/sql_base.h index f4a49d99125f6..f285e28e2b55b 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -131,6 +131,9 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, */ #define MYSQL_OPEN_IGNORE_LOGGING_FORMAT 0x20000 +/* Don't use statistics tables */ +#define MYSQL_OPEN_IGNORE_ENGINE_STATS 0x40000 + /** Please refer to the internals manual. */ #define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\ MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\ @@ -665,7 +668,7 @@ class No_such_table_error_handler : public Internal_error_handler { public: No_such_table_error_handler() - : m_handled_errors(0), m_unhandled_errors(0) + : m_handled_errors(0), m_unhandled_errors(0), first_error(0) {} bool handle_condition(THD *thd, @@ -680,11 +683,11 @@ class No_such_table_error_handler : public Internal_error_handler trapped and no other errors have been seen. FALSE otherwise. */ bool safely_trapped_errors(); + uint got_error() { return first_error; } private: int m_handled_errors; int m_unhandled_errors; + uint first_error; }; - - #endif /* SQL_BASE_INCLUDED */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b21e232e5a847..ec790ad8d64e0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -69,8 +69,6 @@ #include "wsrep_thd.h" #include "wsrep_trans_observer.h" #include "wsrep_server_state.h" -#else -static inline bool wsrep_is_bf_aborted(THD* thd) { return false; } #endif /* WITH_WSREP */ #include "opt_trace.h" #include @@ -1009,7 +1007,8 @@ void THD::raise_note(uint sql_errno) { DBUG_ENTER("THD::raise_note"); DBUG_PRINT("enter", ("code: %d", sql_errno)); - if (!(variables.option_bits & OPTION_SQL_NOTES)) + if (!(variables.option_bits & OPTION_SQL_NOTES) || + (variables.note_verbosity == 0)) DBUG_VOID_RETURN; const char* msg= ER_THD(this, sql_errno); (void) raise_condition(sql_errno, "\0\0\0\0\0", @@ -1023,7 +1022,8 @@ void THD::raise_note_printf(uint sql_errno, ...) char ebuff[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("THD::raise_note_printf"); DBUG_PRINT("enter",("code: %u", sql_errno)); - if (!(variables.option_bits & OPTION_SQL_NOTES)) + if (!(variables.option_bits & OPTION_SQL_NOTES) || + (variables.note_verbosity == 0)) DBUG_VOID_RETURN; const char* format= ER_THD(this, sql_errno); va_start(args, sql_errno); @@ -1046,8 +1046,9 @@ Sql_condition* THD::raise_condition(const Sql_condition *cond) DBUG_ENTER("THD::raise_condition"); DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END); - if (!(variables.option_bits & OPTION_SQL_NOTES) && - (level == Sql_condition::WARN_LEVEL_NOTE)) + if ((level == Sql_condition::WARN_LEVEL_NOTE) && + (!(variables.option_bits & OPTION_SQL_NOTES) || + (variables.note_verbosity == 0))) DBUG_RETURN(NULL); #ifdef WITH_WSREP /* @@ -1727,7 +1728,9 @@ THD::~THD() lf_hash_put_pins(tdc_hash_pins); if (xid_hash_pins) lf_hash_put_pins(xid_hash_pins); +#if defined(ENABLED_DEBUG_SYNC) debug_sync_end_thread(this); +#endif /* Ensure everything is freed */ status_var.local_memory_used-= sizeof(THD); @@ -1742,7 +1745,7 @@ THD::~THD() if (status_var.local_memory_used != 0) { DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used)); - SAFEMALLOC_REPORT_MEMORY(thread_id); + SAFEMALLOC_REPORT_MEMORY(sf_malloc_dbug_id()); DBUG_ASSERT(status_var.local_memory_used == 0 || !debug_assert_on_not_freed_memory); } @@ -5845,7 +5848,6 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) The following is added to the old values as we are interested in the total complexity of the query */ - inc_examined_row_count(backup->examined_row_count); cuted_fields+= backup->cuted_fields; DBUG_VOID_RETURN; } @@ -5928,6 +5930,8 @@ void THD::set_examined_row_count(ha_rows count) void THD::inc_sent_row_count(ha_rows count) { m_sent_row_count+= count; + DBUG_EXECUTE_IF("debug_huge_number_of_examined_rows", + m_examined_row_count= (ULONGLONG_MAX - 1000000);); MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); } @@ -7936,6 +7940,7 @@ wait_for_commit::reinit() wakeup_error= 0; wakeup_subsequent_commits_running= false; commit_started= false; + wakeup_blocked= false; #ifdef SAFE_MUTEX /* When using SAFE_MUTEX, the ordering between taking the LOCK_wait_commit @@ -8209,6 +8214,9 @@ wait_for_commit::wakeup_subsequent_commits2(int wakeup_error) { wait_for_commit *waiter; + if (unlikely(wakeup_blocked)) + return; + mysql_mutex_lock(&LOCK_wait_commit); wakeup_subsequent_commits_running= true; waiter= subsequent_commits_list; diff --git a/sql/sql_class.h b/sql/sql_class.h index 5c8815078b43c..4e4f4b7fedcb8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -446,7 +446,8 @@ class Alter_index_ignorability: public Sql_alloc class Key :public Sql_alloc, public DDL_options { public: - enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY}; + enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY, + IGNORE_KEY}; enum Keytype type; KEY_CREATE_INFO key_create_info; List columns; @@ -700,6 +701,7 @@ typedef struct system_variables ulonglong log_slow_verbosity; ulonglong log_slow_disabled_statements; ulonglong log_disabled_statements; + ulonglong note_verbosity; ulonglong bulk_insert_buff_size; ulonglong join_buff_size; ulonglong sortbuff_size; @@ -759,6 +761,8 @@ typedef struct system_variables ulong optimizer_selectivity_sampling_limit; ulong optimizer_use_condition_selectivity; ulong optimizer_trace_max_mem_size; + ulong optimizer_max_sel_arg_weight; + ulong optimizer_max_sel_args; ulong use_stat_tables; ulong histogram_size; ulong histogram_type; @@ -779,6 +783,7 @@ typedef struct system_variables ulong trans_alloc_block_size; ulong trans_prealloc_size; ulong log_warnings; + ulong log_slow_max_warnings; /* Flags for slow log filtering */ ulong log_slow_rate_limit; ulong binlog_format; ///< binlog format for this thd (see enum_binlog_format) @@ -792,7 +797,6 @@ typedef struct system_variables ulong server_id; ulong session_track_transaction_info; ulong threadpool_priority; - ulong optimizer_max_sel_arg_weight; ulong vers_alter_history; /* deadlock detection */ @@ -1177,11 +1181,21 @@ class Query_arena Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED. Stored procedure: STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED. Other statements: STMT_CONVENTIONAL_EXECUTION never changes. + + Special case for stored procedure arguments: STMT_SP_QUERY_ARGUMENTS + This state never changes and used for objects + whose lifetime is whole duration of function call + (sp_rcontext, it's tables and items. etc). Such objects + should be deallocated after every execution of a stored + routine. Caller's arena/memroot can't be used for + placing such objects since memory allocated on caller's + arena not freed until termination of user's session. */ enum enum_state { STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2, - STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_ERROR= -1 + STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, + STMT_SP_QUERY_ARGUMENTS= 5, STMT_ERROR= -1 }; enum_state state; @@ -1960,11 +1974,17 @@ class Internal_error_handler /** Implements the trivial error handler which cancels all error states and prevents an SQLSTATE to be set. + Remembers the first error */ class Dummy_error_handler : public Internal_error_handler { + uint m_unhandled_errors; + uint first_error; public: + Dummy_error_handler() + : m_unhandled_errors(0), first_error(0) + {} bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, @@ -1972,13 +1992,15 @@ class Dummy_error_handler : public Internal_error_handler const char* msg, Sql_condition ** cond_hdl) { - /* Ignore error */ - return TRUE; + m_unhandled_errors++; + if (!first_error) + first_error= sql_errno; + return TRUE; // Ignore error } - Dummy_error_handler() = default; /* Remove gcc warning */ + bool any_error() { return m_unhandled_errors != 0; } + uint got_error() { return first_error; } }; - /** Implements the trivial error handler which counts errors as they happen. */ @@ -2317,6 +2339,19 @@ struct wait_for_commit group commit as T1. */ bool commit_started; + /* + Set to temporarily ignore calls to wakeup_subsequent_commits(). The + caller must arrange that another wakeup_subsequent_commits() gets called + later after wakeup_blocked has been set back to false. + + This is used for parallel replication with temporary tables. + Temporary tables require strict single-threaded operation. The normal + optimization, of doing wakeup_subsequent_commits early and overlapping + part of the commit with the following transaction, is not safe. Thus + when temporary tables are replicated, wakeup is blocked until the + event group is fully done. + */ + bool wakeup_blocked; void register_wait_for_prior_commit(wait_for_commit *waitee); int wait_for_prior_commit(THD *thd, bool allow_kill=true) @@ -4470,6 +4505,17 @@ class THD: public THD_count, /* this must be first */ inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup) { + if (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) + /* + Caller uses the arena with state STMT_SP_QUERY_ARGUMENTS for stored + routine's parameters. Lifetime of these objects spans a lifetime of + stored routine call and freed every time the stored routine execution + has been completed. That is the reason why switching to statement's + arena is not performed for arguments, else we would observe increasing + of memory usage while a stored routine be called over and over again. + */ + return NULL; + /* Use the persistent arena if we are in a prepared statement or a stored procedure statement and we have not already changed to use this arena. @@ -5628,6 +5674,14 @@ class THD: public THD_count, /* this must be first */ lex->analyze_stmt; } + /* Return true if we should create a note when an unusable key is found */ + bool give_notes_for_unusable_keys() + { + return ((variables.note_verbosity & (NOTE_VERBOSITY_UNUSABLE_KEYS)) || + (lex->describe && // Is EXPLAIN + (variables.note_verbosity & NOTE_VERBOSITY_EXPLAIN))); + } + bool vers_insert_history_fast(const TABLE *table) { DBUG_ASSERT(table->versioned()); diff --git a/sql/sql_error.h b/sql/sql_error.h index 541b92b4531eb..846d48f22baba 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -29,6 +29,14 @@ class THD; class my_decimal; class sp_condition_value; +/* Types of LOG warnings, used by note_verbosity */ + +#define NOTE_VERBOSITY_NORMAL (1U << 0) +/* Show warnings about keys parts that cannot be used */ +#define NOTE_VERBOSITY_UNUSABLE_KEYS (1U << 1) +/* Show warnings in explain for key parts that cannot be used */ +#define NOTE_VERBOSITY_EXPLAIN (1U << 2) + /////////////////////////////////////////////////////////////////////////// class Sql_state @@ -1073,6 +1081,11 @@ class Diagnostics_area: public Sql_state_errno, return m_statement_warn_count; } + uint unsafe_statement_warn_count() const + { + return m_statement_warn_count; + } + /** Get the current errno, state and id of the user defined condition and return them as Sql_condition_identity. diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d68016a1b220c..4a497280e6337 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -591,7 +591,8 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) Open tables used for sub-selects or in stored functions, will also cache these functions. */ - if (open_and_lock_tables(thd, table_list->next_global, TRUE, 0)) + if (open_and_lock_tables(thd, table_list->next_global, TRUE, + MYSQL_OPEN_IGNORE_ENGINE_STATS)) { end_delayed_insert(thd); error= TRUE; @@ -955,7 +956,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, same table in the same connection. */ if (thd->locked_tables_mode <= LTM_LOCK_TABLES && - values_list.elements > 1) + !table->s->long_unique_table && values_list.elements > 1) { using_bulk_insert= 1; table->file->ha_start_bulk_insert(values_list.elements); @@ -2795,6 +2796,9 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) /* Ensure we don't use the table list of the original table */ copy->pos_in_table_list= 0; + /* We don't need statistics for insert delayed */ + copy->stats_cb= 0; + /* Make a copy of all fields. The copied fields need to point into the copied record. This is done @@ -3571,7 +3575,7 @@ bool Delayed_insert::handle_inserts(void) we get a crash, then binary log will contain rows that are not yet written to disk, which will cause problems in replication. */ - if (!using_bin_log) + if (!using_bin_log && !table->s->long_unique_table) table->file->extra(HA_EXTRA_WRITE_CACHE); mysql_mutex_lock(&mutex); @@ -3731,7 +3735,7 @@ bool Delayed_insert::handle_inserts(void) table->s->table_name.str); goto err; } - if (!using_bin_log) + if (!using_bin_log && !table->s->long_unique_table) table->file->extra(HA_EXTRA_WRITE_CACHE); mysql_mutex_lock(&mutex); THD_STAGE_INFO(&thd, stage_insert); @@ -4127,7 +4131,8 @@ int select_insert::prepare2(JOIN *) if (thd->lex->describe) DBUG_RETURN(0); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - thd->locked_tables_mode <= LTM_LOCK_TABLES) + thd->locked_tables_mode <= LTM_LOCK_TABLES && + !table->s->long_unique_table) table->file->ha_start_bulk_insert((ha_rows) 0); /* Same as the other variants of INSERT */ @@ -4868,17 +4873,18 @@ select_create::prepare(List &_values, SELECT_LEX_UNIT *u) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); - if (thd->locked_tables_mode <= LTM_LOCK_TABLES) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + !table->s->long_unique_table) { table->file->ha_start_bulk_insert((ha_rows) 0); if (thd->lex->duplicates == DUP_ERROR && !thd->lex->ignore) table->file->extra(HA_EXTRA_BEGIN_ALTER_COPY); + table->file->extra(HA_EXTRA_WRITE_CACHE); } thd->abort_on_warning= !info.ignore && thd->is_strict_mode(); if (check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(1); table->mark_columns_needed_for_insert(); - table->file->extra(HA_EXTRA_WRITE_CACHE); // Mark table as used table->query_id= thd->query_id; DBUG_RETURN(0); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 73924bb9d1c7a..cc6232d251718 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -654,7 +654,8 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); - if (thd->locked_tables_mode <= LTM_LOCK_TABLES) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + !table->s->long_unique_table) table->file->ha_start_bulk_insert((ha_rows) 0); table->copy_blobs=1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 801a87894aea8..ac9703a836381 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1933,6 +1933,8 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * MYSQL_QUERY_DONE(thd->is_error()); } + thd->lex->restore_set_statement_var(); + #if defined(ENABLED_PROFILING) thd->profiling.finish_current_query(); thd->profiling.start_new_query("continuing"); @@ -6076,11 +6078,6 @@ static bool __attribute__ ((noinline)) execute_show_status(THD *thd, TABLE_LIST *all_tables) { bool res; - -#if defined(__GNUC__) && (__GNUC__ >= 13) -#pragma GCC diagnostic ignored "-Wdangling-pointer" -#endif - system_status_var old_status_var= thd->status_var; thd->initial_status_var= &old_status_var; WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 22780c894f86f..a36a24f4698d6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -175,6 +175,16 @@ class Prepared_statement: public Statement Server_side_cursor *cursor; uchar *packet; uchar *packet_end; +#ifdef PROTECT_STATEMENT_MEMROOT + /* + The following data member is wholly for debugging purpose. + It can be used for possible crash analysis to determine how many times + the stored routine was executed before the mem_root marked read_only + was requested for a memory chunk. Additionally, a value of this data + member is output to the log with DBUG_PRINT. + */ + ulong executed_counter; +#endif uint param_count; uint last_errno; uint flags; @@ -3885,6 +3895,9 @@ Prepared_statement::Prepared_statement(THD *thd_arg) cursor(0), packet(0), packet_end(0), +#ifdef PROTECT_STATEMENT_MEMROOT + executed_counter(0), +#endif param_count(0), last_errno(0), flags((uint) IS_IN_USE), @@ -3959,8 +3972,13 @@ void Prepared_statement::setup_set_params() Prepared_statement::~Prepared_statement() { DBUG_ENTER("Prepared_statement::~Prepared_statement"); +#ifdef PROTECT_STATEMENT_MEMROOT + DBUG_PRINT("enter",("stmt: %p cursor: %p executed_counter: %lu", + this, cursor, executed_counter)); +#else DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor)); +#endif MYSQL_DESTROY_PS(m_prepared_stmt); @@ -4157,6 +4175,10 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) } lex->set_trg_event_type_for_tables(); +#ifdef PROTECT_STATEMENT_MEMROOT + executed_counter= 0; +#endif + /* While doing context analysis of the query (in check_prepared_statement) we allocate a lot of additional memory: for open tables, JOINs, derived @@ -4428,9 +4450,31 @@ Prepared_statement::execute_loop(String *expanded_query, error= reprepare(); if (likely(!error)) /* Success */ + { +#ifdef PROTECT_STATEMENT_MEMROOT + // There was reprepare so the counter of runs should be reset + executed_counter= 0; + mem_root->read_only= 0; +#endif goto reexecute; + } } reset_stmt_params(this); +#ifdef PROTECT_STATEMENT_MEMROOT + if (!error) + { + mem_root->read_only= 1; + ++executed_counter; + + DBUG_PRINT("info", ("execute counter: %lu", executed_counter)); + } + else + { + // Error on call shouldn't be counted as a normal run + executed_counter= 0; + mem_root->read_only= 0; + } +#endif return error; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f72918815dfe0..05b788b6e1d79 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -913,8 +913,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array, ORDER *group, List &win_specs, List &win_funcs, - bool *hidden_group_fields, - uint *reserved) + bool *hidden_group_fields) { int res; enum_parsing_place save_place; @@ -929,13 +928,6 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array, thd->lex->allow_sum_func.clear_bit(select->nest_level); res= setup_conds(thd, tables, leaves, conds); - if (thd->lex->current_select->first_cond_optimization) - { - if (!res && *conds && ! thd->lex->current_select->merged_into) - (*reserved)= (*conds)->exists2in_reserved_items(); - else - (*reserved)= 0; - } /* it's not wrong to have non-aggregated columns in a WHERE */ select->set_non_agg_field_used(saved_non_agg_field_used); @@ -1504,6 +1496,15 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, DBUG_ASSERT(select_lex->hidden_bit_fields == 0); if (setup_wild(thd, tables_list, fields_list, &all_fields, select_lex, false)) DBUG_RETURN(-1); + + if (thd->lex->current_select->first_cond_optimization) + { + if ( conds && ! thd->lex->current_select->merged_into) + select_lex->select_n_reserved= conds->exists2in_reserved_items(); + else + select_lex->select_n_reserved= 0; + } + if (select_lex->setup_ref_array(thd, real_og_num)) DBUG_RETURN(-1); @@ -1533,8 +1534,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, all_fields, &conds, order, group_list, select_lex->window_specs, select_lex->window_funcs, - &hidden_group_fields, - &select_lex->select_n_reserved)) + &hidden_group_fields)) DBUG_RETURN(-1); /* @@ -2619,7 +2619,7 @@ JOIN::optimize_inner() result->prepare_to_read_rows(); if (unlikely(make_join_statistics(this, select_lex->leaf_tables, &keyuse)) || - unlikely(thd->is_fatal_error)) + unlikely(thd->is_error())) { DBUG_PRINT("error",("Error: make_join_statistics() failed")); DBUG_RETURN(1); @@ -2856,7 +2856,7 @@ int JOIN::optimize_stage2() { ref_item= substitute_for_best_equal_field(thd, tab, ref_item, equals, map2table, true); - if (unlikely(thd->is_fatal_error)) + if (unlikely(thd->is_error())) DBUG_RETURN(1); if (first_inner) @@ -3089,7 +3089,7 @@ int JOIN::optimize_stage2() else group_list= 0; } - else if (thd->is_fatal_error) // End of memory + else if (thd->is_error()) // End of memory DBUG_RETURN(1); } simple_group= rollup.state == ROLLUP::STATE_NONE; @@ -3722,7 +3722,7 @@ bool JOIN::make_aggr_tables_info() curr_tab->all_fields= &tmp_all_fields1; curr_tab->fields= &tmp_fields_list1; - DBUG_RETURN(thd->is_fatal_error); + DBUG_RETURN(thd->is_error()); } } } @@ -4043,7 +4043,7 @@ bool JOIN::make_aggr_tables_info() !join_tab || !join_tab-> is_using_agg_loose_index_scan())) DBUG_RETURN(true); - if (unlikely(setup_sum_funcs(thd, sum_funcs) || thd->is_fatal_error)) + if (unlikely(setup_sum_funcs(thd, sum_funcs) || thd->is_error())) DBUG_RETURN(true); } if (group_list || order) @@ -5297,7 +5297,7 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, (table_map) 0, limit, 0, FALSE, TRUE, /* remove_where_parts*/ - FALSE)) == + FALSE, TRUE)) == 1)) { /* @@ -6061,7 +6061,12 @@ make_join_statistics(JOIN *join, List &tables_list, goto error; records= get_quick_record_count(join->thd, select, s->table, &s->const_keys, join->row_limit); - + if (join->thd->is_error()) + { + /* get_quick_record_count generated an error */ + delete select; + goto error; + } /* Range analyzer might have modified the condition. Put it the new condition to where we got it from. @@ -6596,7 +6601,7 @@ add_key_field(JOIN *join, { /* Save info to be able check whether this predicate can be - considered as sargable for range analisis after reading const tables. + considered as sargable for range analysis after reading const tables. We do not save info about equalities as update_const_equal_items will take care of updating info on keys from sargable equalities. */ @@ -7102,11 +7107,14 @@ add_keyuse(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field, 1 - Out of memory. */ +static LEX_CSTRING equal_str= { STRING_WITH_LEN("=") }; + static bool add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field) { Field *field=key_field->field; TABLE *form= field->table; + THD *thd= form->in_use; if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS)) { @@ -7121,19 +7129,31 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field) uint key_parts= form->actual_n_key_parts(keyinfo); for (uint part=0 ; part < key_parts ; part++) { - if (field->eq(form->key_info[key].key_part[part].field) && - field->can_optimize_keypart_ref(key_field->cond, key_field->val)) - { - if (add_keyuse(keyuse_array, key_field, key, part)) - return TRUE; - } + if (field->eq(form->key_info[key].key_part[part].field)) + { + Data_type_compatibility compat= + field->can_optimize_keypart_ref(key_field->cond, key_field->val); + if (compat == Data_type_compatibility::OK) + { + if (add_keyuse(keyuse_array, key_field, key, part)) + return TRUE; + } + else if (thd->give_notes_for_unusable_keys()) + { + field->raise_note_cannot_use_key_part(thd, key, part, + equal_str, + key_field->val, + compat); + } + } } } if (field->hash_join_is_possible() && (key_field->optimize & KEY_OPTIMIZE_EQ) && key_field->val->used_tables()) { - if (!field->can_optimize_hash_join(key_field->cond, key_field->val)) + if (field->can_optimize_hash_join(key_field->cond, key_field->val) != + Data_type_compatibility::OK) return false; if (form->is_splittable()) form->add_splitting_info_for_key_field(key_field); @@ -12540,6 +12560,8 @@ bool JOIN::get_best_combination() table_map used_tables; JOIN_TAB *j; KEYUSE *keyuse; + JOIN_TAB *sjm_nest_end= NULL; + JOIN_TAB *sjm_nest_root= NULL; DBUG_ENTER("get_best_combination"); /* @@ -12594,20 +12616,17 @@ bool JOIN::get_best_combination() DBUG_RETURN(TRUE); if (inject_splitting_cond_for_all_tables_with_split_opt()) - DBUG_RETURN(TRUE); + goto error; JOIN_TAB_RANGE *root_range; if (!(root_range= new (thd->mem_root) JOIN_TAB_RANGE)) - DBUG_RETURN(TRUE); + goto error; root_range->start= join_tab; /* root_range->end will be set later */ join_tab_ranges.empty(); if (join_tab_ranges.push_back(root_range, thd->mem_root)) - DBUG_RETURN(TRUE); - - JOIN_TAB *sjm_nest_end= NULL; - JOIN_TAB *sjm_nest_root= NULL; + goto error; for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++) { @@ -12645,7 +12664,7 @@ bool JOIN::get_best_combination() JOIN_TAB_RANGE *jt_range; if (!(jt= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*sjm->tables)) || !(jt_range= new JOIN_TAB_RANGE)) - DBUG_RETURN(TRUE); + goto error; jt_range->start= jt; jt_range->end= jt + sjm->tables; join_tab_ranges.push_back(jt_range, thd->mem_root); @@ -12737,7 +12756,7 @@ bool JOIN::get_best_combination() { if ((keyuse= best_positions[tablenr].key) && create_ref_for_key(this, j, keyuse, TRUE, used_tables)) - DBUG_RETURN(TRUE); // Something went wrong + goto error; // Something went wrong } if (j->last_leaf_in_bush) j= j->bush_root_tab; @@ -12751,6 +12770,11 @@ bool JOIN::get_best_combination() update_depend_map(this); DBUG_RETURN(0); + +error: + /* join_tab was not correctly setup. Don't use it */ + join_tab= 0; + DBUG_RETURN(1); } /** @@ -13070,7 +13094,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, keyinfo->key_part[i].length, keyuse->val, FALSE); - if (unlikely(thd->is_fatal_error)) + if (unlikely(thd->is_error())) DBUG_RETURN(TRUE); tmp.copy(thd); j->ref.const_ref_part_map |= key_part_map(1) << i ; @@ -14023,7 +14047,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) OPTION_FOUND_ROWS ? HA_POS_ERROR : join->unit->lim.get_select_limit()),0, - FALSE, FALSE, FALSE) < 0) + FALSE, FALSE, FALSE, TRUE) < 0) DBUG_RETURN(1); // Impossible WHERE } else @@ -24403,7 +24427,8 @@ test_if_quick_select(JOIN_TAB *tab) int res= tab->select->test_quick_select(tab->join->thd, tab->keys, (table_map) 0, HA_POS_ERROR, 0, FALSE, /*remove where parts*/FALSE, - FALSE); + FALSE, + /* no warnings */ TRUE); if (tab->explain_plan && tab->explain_plan->range_checked_fer) tab->explain_plan->range_checked_fer->collect_data(tab->select->quick); @@ -26865,7 +26890,7 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) DBUG_ASSERT(tab->type == JT_REF || tab->type == JT_EQ_REF); // Update ref value if (unlikely(cp_buffer_from_ref(thd, table, &tab->ref) && - thd->is_fatal_error)) + thd->is_error())) goto err; // out of memory } } @@ -28745,7 +28770,7 @@ change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, itr++; itr.sublist(res_selected_fields, elements); - return thd->is_fatal_error; + return thd->is_error(); } @@ -28923,7 +28948,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) value), thd->mem_root); } - if (unlikely(thd->is_fatal_error)) + if (unlikely(thd->is_error())) DBUG_RETURN(TRUE); if (!cond->fixed()) { @@ -29535,7 +29560,7 @@ int print_explain_message_line(select_result_sink *result, else item_list.push_back(item_null, mem_root); - if (unlikely(thd->is_fatal_error) || unlikely(result->send_data(item_list))) + if (unlikely(thd->is_error()) || unlikely(result->send_data(item_list))) return 1; return 0; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9495df2f2756e..dfc7f2ebb3f1e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4992,7 +4992,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table, open_tables function for this table */ -static int fill_schema_table_from_frm(THD *thd, TABLE *table, +static int fill_schema_table_from_frm(THD *thd, MEM_ROOT *mem_root, + TABLE *table, ST_SCHEMA_TABLE *schema_table, LEX_CSTRING *db_name, LEX_CSTRING *table_name, @@ -5004,6 +5005,9 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, TABLE_LIST table_list; uint res= 0; char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1]; + Query_arena i_s_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION); + Query_arena backup_arena, *old_arena; + bool i_s_arena_active= false; bzero((char*) &table_list, sizeof(TABLE_LIST)); bzero((char*) &tbl, sizeof(TABLE)); @@ -5078,6 +5082,11 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, goto end; } + old_arena= thd->stmt_arena; + thd->stmt_arena= &i_s_arena; + thd->set_n_backup_active_arena(&i_s_arena, &backup_arena); + i_s_arena_active= true; + share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW); if (!share) { @@ -5159,7 +5168,16 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, savepoint is safe. */ DBUG_ASSERT(thd->open_tables == NULL); + thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp); + + if (i_s_arena_active) + { + thd->stmt_arena= old_arena; + thd->restore_active_arena(&i_s_arena, &backup_arena); + i_s_arena.free_items(); + } + if (!thd->is_fatal_error) thd->clear_error(); return res; @@ -5388,7 +5406,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (!(table_open_method & ~OPEN_FRM_ONLY) && db_name != &INFORMATION_SCHEMA_NAME) { - if (!fill_schema_table_from_frm(thd, table, schema_table, + if (!fill_schema_table_from_frm(thd, &tmp_mem_root, + table, schema_table, db_name, table_name, &open_tables_state_backup, can_deadlock)) @@ -6937,7 +6956,7 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, KEY *key_info=show_table->s->key_info; if (show_table->file) { - (void) read_statistics_for_tables(thd, tables); + (void) read_statistics_for_tables(thd, tables, false); show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_CONST | diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index ccf1ebb9ef972..8cddcf53abe8c 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -33,6 +33,7 @@ #include "uniques.h" #include "sql_show.h" #include "sql_partition.h" +#include "sql_alter.h" // RENAME_STAT_PARAMS #include #include @@ -63,13 +64,12 @@ equal to "never". */ -Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type, - THD *owner); +Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type); /* Currently there are only 3 persistent statistical tables */ static const uint STATISTICS_TABLES= 3; -/* +/* The names of the statistical tables in this array must correspond the definitions of the tables in the file ../scripts/mysql_system_tables.sql */ @@ -81,6 +81,33 @@ static const LEX_CSTRING stat_table_name[STATISTICS_TABLES]= }; +TABLE_STATISTICS_CB::TABLE_STATISTICS_CB(): + usage_count(0), table_stats(0), + stats_available(TABLE_STAT_NO_STATS), histograms_exists_on_disk(0) +{ + init_sql_alloc(PSI_INSTRUMENT_ME, &mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, + MYF(0)); +} + +TABLE_STATISTICS_CB::~TABLE_STATISTICS_CB() +{ + Column_statistics *column_stats= table_stats->column_stats; + Column_statistics *column_stats_end= column_stats + table_stats->columns; + DBUG_ASSERT(usage_count == 0); + + /* Free json histograms */ + for (; column_stats < column_stats_end ; column_stats++) + { + delete column_stats->histogram; + /* + Protect against possible other free in free_statistics_for_table() + */ + column_stats->histogram= 0; + } + free_root(&mem_root, MYF(0)); +} + + /** @details The function builds a list of TABLE_LIST elements for system statistical @@ -275,15 +302,27 @@ static int open_stat_tables(THD *thd, TABLE_LIST *tables, bool for_write) @details This is used by DDLs. When a column or index is dropped or renamed, stat tables need to be adjusted accordingly. + + This function should not generate any errors as the callers are not checking + the result of delete_statistics_for_table() + */ static inline int open_stat_table_for_ddl(THD *thd, TABLE_LIST *table, const LEX_CSTRING *stat_tab_name) { table->init_one_table(&MYSQL_SCHEMA_NAME, stat_tab_name, NULL, TL_WRITE); - No_such_table_error_handler nst_handler; - thd->push_internal_handler(&nst_handler); + Dummy_error_handler error_handler; + thd->push_internal_handler(&error_handler); int res= open_system_tables_for_read(thd, table); thd->pop_internal_handler(); + if (res && error_handler.any_error()) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_CHECK_NO_SUCH_TABLE, + "Got error %d when trying to open statistics " + "table %`s for updating statistics", + error_handler.got_error(), stat_table_name->str); + } return res; } @@ -356,8 +395,7 @@ class Column_statistics_collected :public Column_statistics Reading statistical data from a statistical table is performed by the following pattern. First a table dependent method sets the values of the - the fields that comprise the lookup key. Then an implementation of the - method get_stat_values() declared in Stat_table as a pure virtual method + the fields that comprise the lookup key. Then, get_stat_values(...) call finds the row from the statistical table by the set key. If the row is found the values of statistical fields are read from this row and are distributed in the internal structures. @@ -433,7 +471,7 @@ class Stat_table uint stat_key_length; /* Length of the key to access stat_table */ uchar *record[2]; /* Record buffers used to access/update stat_table */ - uint stat_key_idx; /* The number of the key to access stat_table */ + /* This is a helper function used only by the Stat_table constructors */ void common_init_stat_table() @@ -443,6 +481,7 @@ class Stat_table stat_key_idx= 0; stat_key_info= &stat_table->key_info[stat_key_idx]; stat_key_length= stat_key_info->key_length; + last_key_length= last_prefix_parts= 0; record[0]= stat_table->record[0]; record[1]= stat_table->record[1]; } @@ -454,34 +493,36 @@ class Stat_table KEY *stat_key_info; /* Structure for the index to access stat_table */ /* Table for which statistical data is read / updated */ - TABLE *table; - TABLE_SHARE *table_share; /* Table share for 'table */ + const TABLE *table; + const TABLE_SHARE *table_share; /* Table share for 'table */ const LEX_CSTRING *db_name; /* Name of the database containing 'table' */ const LEX_CSTRING *table_name; /* Name of the table 'table' */ - void store_record_for_update() - { - store_record(stat_table, record[1]); - } + uchar last_key[MAX_KEY_LENGTH]; + uint last_key_length; + uint last_prefix_parts; void store_record_for_lookup() { DBUG_ASSERT(record[0] == stat_table->record[0]); } - bool update_record() + int update_record() { int err; if ((err= stat_file->ha_update_row(record[1], record[0])) && err != HA_ERR_RECORD_IS_THE_SAME) - return TRUE; - /* Make change permanent and avoid 'table is marked as crashed' errors */ - stat_file->extra(HA_EXTRA_FLUSH); - return FALSE; + return err; + return 0; } public: + uint stat_key_idx; /* The number of the key to access stat_table */ + void store_record_for_update() + { + store_record(stat_table, record[1]); + } /** @details @@ -492,7 +533,7 @@ class Stat_table statistics has been collected. */ - Stat_table(TABLE *stat, TABLE *tab) + Stat_table(TABLE *stat, const TABLE *tab) :stat_table(stat), table(tab) { table_share= tab->s; @@ -535,7 +576,8 @@ class Stat_table The method is called by the update_table_name_key_parts function. */ - virtual void change_full_table_name(const LEX_CSTRING *db, const LEX_CSTRING *tab)= 0; + virtual void change_full_table_name(const LEX_CSTRING *db, + const LEX_CSTRING *tab)= 0; /** @@ -554,19 +596,6 @@ class Stat_table virtual void store_stat_fields()= 0; - /** - @brief - Read statistical data from fields of the statistical table - - @details - This is a purely virtual method. - The implementation for any derived read shall read the appropriate - statistical data from the corresponding fields of stat_table. - */ - - virtual void get_stat_values()= 0; - - /** @brief Find a record in the statistical table by a primary key @@ -584,13 +613,22 @@ class Stat_table bool find_stat() { - uchar key[MAX_KEY_LENGTH]; - key_copy(key, record[0], stat_key_info, stat_key_length); - return !stat_file->ha_index_read_idx_map(record[0], stat_key_idx, key, + last_key_length= stat_key_length; + key_copy(last_key, record[0], stat_key_info, stat_key_length); + return !stat_file->ha_index_read_idx_map(record[0], stat_key_idx, last_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT); } - + void create_key_for_read(uint prefix_parts) + { + last_key_length= 0; + last_prefix_parts= prefix_parts; + for (uint i= 0; i < prefix_parts; i++) + last_key_length+= stat_key_info->key_part[i].store_length; + key_copy(last_key, record[0], stat_key_info, last_key_length); + } + + /** @brief Find a record in the statistical table by a key prefix value @@ -609,16 +647,32 @@ class Stat_table bool find_next_stat_for_prefix(uint prefix_parts) { - uchar key[MAX_KEY_LENGTH]; - uint prefix_key_length= 0; - for (uint i= 0; i < prefix_parts; i++) - prefix_key_length+= stat_key_info->key_part[i].store_length; - key_copy(key, record[0], stat_key_info, prefix_key_length); + create_key_for_read(prefix_parts); key_part_map prefix_map= (key_part_map) ((1 << prefix_parts) - 1); - return !stat_file->ha_index_read_idx_map(record[0], stat_key_idx, key, - prefix_map, HA_READ_KEY_EXACT); + return !stat_file->ha_index_read_idx_map(record[0], stat_key_idx, last_key, + prefix_map, HA_READ_KEY_EXACT); } + bool find_next_stat_for_prefix_with_next(uint prefix_parts) + { + create_key_for_read(prefix_parts); + key_part_map prefix_map= (key_part_map) ((1 << prefix_parts) - 1); + return !stat_file->ha_index_read_map(record[0], last_key, + prefix_map, + HA_READ_KEY_EXACT); + } + + /* + Read row with same key parts as last find_next_stat_for_prefix_with_next() + */ + + bool find_stat_with_next() + { + key_copy(last_key, record[0], stat_key_info, last_key_length); + key_part_map prefix_map= (key_part_map) ((1 << last_prefix_parts) - 1); + return !stat_file->ha_index_read_map(record[0], last_key, + prefix_map, HA_READ_KEY_EXACT); + } /** @brief @@ -651,7 +705,7 @@ class Stat_table bool res; store_record_for_update(); store_stat_fields(); - res= update_record(); + res= update_record() != 0; DBUG_ASSERT(res == 0); return res; } @@ -664,14 +718,11 @@ class Stat_table DBUG_ASSERT(0); return TRUE; } - /* Make change permanent and avoid 'table is marked as crashed' errors */ - stat_file->extra(HA_EXTRA_FLUSH); - } + } return FALSE; } - - /** + /** @brief Update the table name fields in the current record of stat_table @@ -695,7 +746,7 @@ class Stat_table { store_record_for_update(); change_full_table_name(db, tab); - bool rc= update_record(); + bool rc= update_record() != 0; store_record_for_lookup(); return rc; } @@ -720,10 +771,13 @@ class Stat_table int err; if ((err= stat_file->ha_delete_row(record[0]))) return TRUE; - /* Make change permanent and avoid 'table is marked as crashed' errors */ - stat_file->extra(HA_EXTRA_FLUSH); return FALSE; - } + } + + void flush() + { + stat_file->extra(HA_EXTRA_FLUSH); + } friend class Stat_table_write_iter; }; @@ -753,10 +807,11 @@ class Table_stat: public Stat_table table_name_field= stat_table->field[TABLE_STAT_TABLE_NAME]; } - void change_full_table_name(const LEX_CSTRING *db, const LEX_CSTRING *tab) + void change_full_table_name(const LEX_CSTRING *db, + const LEX_CSTRING *tab) override { - db_name_field->store(db->str, db->length, system_charset_info); - table_name_field->store(tab->str, tab->length, system_charset_info); + db_name_field->store(db, system_charset_info); + table_name_field->store(tab, system_charset_info); } public: @@ -769,7 +824,7 @@ class Table_stat: public Stat_table must be passed as a value for the parameter 'stat'. */ - Table_stat(TABLE *stat, TABLE *tab) :Stat_table(stat, tab) + Table_stat(TABLE *stat, const TABLE *tab) :Stat_table(stat, tab) { common_init_table_stat(); } @@ -806,9 +861,8 @@ class Table_stat: public Stat_table void set_key_fields() { - db_name_field->store(db_name->str, db_name->length, system_charset_info); - table_name_field->store(table_name->str, table_name->length, - system_charset_info); + db_name_field->store(db_name, system_charset_info); + table_name_field->store(table_name, system_charset_info); } @@ -823,7 +877,7 @@ class Table_stat: public Stat_table the field write_stat.cardinality' from the TABLE structure for 'table'. */ - void store_stat_fields() + void store_stat_fields() override { Field *stat_field= stat_table->field[TABLE_STAT_CARDINALITY]; if (table->collected_stats->cardinality_is_null) @@ -841,21 +895,19 @@ class Table_stat: public Stat_table Read statistical data from statistical fields of table_stat @details - This implementation of a purely virtual method first looks for a record - the statistical table table_stat by its primary key set the record - buffer with the help of Table_stat::set_key_fields. Then, if the row is - found the function reads the value of the column 'cardinality' of the table - table_stat and sets the value of the flag read_stat.cardinality_is_null - and the value of the field read_stat.cardinality' from the TABLE structure - for 'table' accordingly. - */ + Find a record in mysql.table_stat that has statistics for this table. + We search for record using a PK lookup. The lookup values are in the stat + table's record buffer, they were put there by Table_stat::set_key_fields. + + The result is stored in *read_stats. + */ - void get_stat_values() + bool get_stat_values(Table_statistics *read_stats) { - Table_statistics *read_stats= table_share->stats_cb.table_stats; + bool res; read_stats->cardinality_is_null= TRUE; read_stats->cardinality= 0; - if (find_stat()) + if ((res= find_stat())) { Field *stat_field= stat_table->field[TABLE_STAT_CARDINALITY]; if (!stat_field->is_null()) @@ -864,8 +916,8 @@ class Table_stat: public Stat_table read_stats->cardinality= stat_field->val_int(); } } + return res; } - }; @@ -897,10 +949,11 @@ class Column_stat: public Stat_table column_name_field= stat_table->field[COLUMN_STAT_COLUMN_NAME]; } - void change_full_table_name(const LEX_CSTRING *db, const LEX_CSTRING *tab) + void change_full_table_name(const LEX_CSTRING *db, + const LEX_CSTRING *tab) override { - db_name_field->store(db->str, db->length, system_charset_info); - table_name_field->store(tab->str, tab->length, system_charset_info); + db_name_field->store(db, system_charset_info); + table_name_field->store(tab, system_charset_info); } public: @@ -913,7 +966,7 @@ class Column_stat: public Stat_table column_stats must be passed as a value for the parameter 'stat'. */ - Column_stat(TABLE *stat, TABLE *tab) :Stat_table(stat, tab) + Column_stat(TABLE *stat, const TABLE *tab) :Stat_table(stat, tab) { common_init_column_stat_table(); } @@ -944,9 +997,8 @@ class Column_stat: public Stat_table void set_full_table_name() { - db_name_field->store(db_name->str, db_name->length, system_charset_info); - table_name_field->store(table_name->str, table_name->length, - system_charset_info); + db_name_field->store(db_name, system_charset_info); + table_name_field->store(table_name, system_charset_info); } @@ -964,18 +1016,24 @@ class Column_stat: public Stat_table It also sets table_field to the passed parameter. @note - The function is supposed to be called before any use of the + The function is supposed to be called before any use of the method find_stat for an object of the Column_stat class. */ void set_key_fields(Field *col) { set_full_table_name(); - column_name_field->store(col->field_name.str, col->field_name.length, - system_charset_info); + column_name_field->store(&col->field_name, system_charset_info); table_field= col; } + void set_key_fields(LEX_CSTRING *field_name) + { + set_full_table_name(); + column_name_field->store(field_name, system_charset_info); + table_field= 0; // Safety + } + /** @brief @@ -985,22 +1043,27 @@ class Column_stat: public Stat_table The function updates the primary key fields containing database name, table name, and column name for the last found record in the statistical table column_stats. - + @retval - FALSE success with the update of the record + 0 success with the update of the record @retval - TRUE failure with the update of the record + # handler error in case of failure */ - bool update_column_key_part(const char *col) + int update_column_key_part(LEX_CSTRING *col) { + int rc; store_record_for_update(); - set_full_table_name(); - column_name_field->store(col, strlen(col), system_charset_info); - bool rc= update_record(); + rc= update_column(col); store_record_for_lookup(); return rc; - } + } + + int update_column(LEX_CSTRING *col) + { + column_name_field->store(col, system_charset_info); + return update_record(); + } /** @@ -1026,11 +1089,12 @@ class Column_stat: public Stat_table length of the column. */ - void store_stat_fields() + void store_stat_fields() override { StringBuffer val; - MY_BITMAP *old_map= dbug_tmp_use_all_columns(stat_table, &stat_table->read_set); + MY_BITMAP *old_map= dbug_tmp_use_all_columns(stat_table, + &stat_table->read_set); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { Field *stat_field= stat_table->field[i]; @@ -1071,10 +1135,12 @@ class Column_stat: public Stat_table stat_field->store(stats->get_avg_frequency()); break; case COLUMN_STAT_HIST_SIZE: - // Note: this is dumb. the histogram size is stored with the - // histogram! - stat_field->store(stats->histogram? - stats->histogram->get_size() : 0); + /* + This is only here so that one can see the size when selecting + from the table. It is not used. + */ + stat_field->store(stats->histogram ? + stats->histogram->get_size() : 0); break; case COLUMN_STAT_HIST_TYPE: if (stats->histogram) @@ -1100,161 +1166,145 @@ class Column_stat: public Stat_table Read statistical data from statistical fields of column_stats @details - This implementation of a purely virtual method first looks for a record - in the statistical table column_stats by its primary key set in the record - buffer with the help of Column_stat::set_key_fields. Then, if the row is + Find a record in mysql.column_stats that has statistics for this column. + We search for record using a PK lookup. The lookup values are in the stat + table's record buffer. Then, if the row is found, the function reads the values of the columns 'min_value', 'max_value', 'nulls_ratio', 'avg_length', 'avg_frequency', 'hist_size' and - 'hist_type" of the table column_stat and sets accordingly the value of - the bitmap read_stat.column_stat_nulls' and the values of the fields - min_value, max_value, nulls_ratio, avg_length, avg_frequency, hist_size and - hist_type of the structure read_stat from the Field structure for the field - 'table_field'. - */ + 'hist_type" of the table column_stat and sets the members of *read_stats + accordingly. + */ - void get_stat_values() + bool get_stat_values(Column_statistics *read_stats, MEM_ROOT *mem_root, + bool want_histograms) { - table_field->read_stats->set_all_nulls(); - // default: hist_type=NULL means there's no histogram - table_field->read_stats->histogram_type_on_disk= INVALID_HISTOGRAM; + bool res; + read_stats->set_all_nulls(); - if (table_field->read_stats->min_value) - table_field->read_stats->min_value->set_null(); - if (table_field->read_stats->max_value) - table_field->read_stats->max_value->set_null(); + if (read_stats->min_value) + read_stats->min_value->set_null(); + if (read_stats->max_value) + read_stats->max_value->set_null(); + read_stats->histogram= 0; - if (find_stat()) + if ((res= find_stat())) { char buff[MAX_FIELD_WIDTH]; String val(buff, sizeof(buff), &my_charset_bin); + Histogram_type hist_type= INVALID_HISTOGRAM; for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) - { + { Field *stat_field= stat_table->field[i]; if (!stat_field->is_null() && (i > COLUMN_STAT_MAX_VALUE || (i == COLUMN_STAT_MIN_VALUE && - table_field->read_stats->min_value) || + read_stats->min_value) || (i == COLUMN_STAT_MAX_VALUE && - table_field->read_stats->max_value))) + read_stats->max_value))) { - table_field->read_stats->set_not_null(i); + read_stats->set_not_null(i); switch (i) { case COLUMN_STAT_MIN_VALUE: { - Field *field= table_field->read_stats->min_value; + Field *field= read_stats->min_value; field->set_notnull(); if (table_field->type() == MYSQL_TYPE_BIT) field->store(stat_field->val_int(), true); else - field->store_from_statistical_minmax_field(stat_field, &val); + field->store_from_statistical_minmax_field(stat_field, &val, + mem_root); break; } case COLUMN_STAT_MAX_VALUE: { - Field *field= table_field->read_stats->max_value; + Field *field= read_stats->max_value; field->set_notnull(); if (table_field->type() == MYSQL_TYPE_BIT) field->store(stat_field->val_int(), true); else - field->store_from_statistical_minmax_field(stat_field, &val); + field->store_from_statistical_minmax_field(stat_field, &val, + mem_root); break; } case COLUMN_STAT_NULLS_RATIO: - table_field->read_stats->set_nulls_ratio(stat_field->val_real()); + read_stats->set_nulls_ratio(stat_field->val_real()); break; case COLUMN_STAT_AVG_LENGTH: - table_field->read_stats->set_avg_length(stat_field->val_real()); + read_stats->set_avg_length(stat_field->val_real()); break; case COLUMN_STAT_AVG_FREQUENCY: - table_field->read_stats->set_avg_frequency(stat_field->val_real()); + read_stats->set_avg_frequency(stat_field->val_real()); break; case COLUMN_STAT_HIST_SIZE: /* Ignore the contents of mysql.column_stats.hist_size. We take the size from the mysql.column_stats.histogram column, itself. */ - break; + break; case COLUMN_STAT_HIST_TYPE: + hist_type= (Histogram_type) (stat_field->val_int() - 1); + break; + case COLUMN_STAT_HISTOGRAM: + { + Histogram_base *hist= 0; + read_stats->histogram_exists= 0; + if (hist_type != INVALID_HISTOGRAM) { - /* - Save the histogram type. The histogram itself will be read in - read_histograms_for_table(). - */ - Histogram_type hist_type= (Histogram_type) (stat_field->val_int() - - 1); - table_field->read_stats->histogram_type_on_disk= hist_type; - break; + if (want_histograms) + { + char buff[MAX_FIELD_WIDTH]; + String val(buff, sizeof(buff), &my_charset_bin), *result; + result= stat_field->val_str(&val); + if (result->length()) + { + MY_BITMAP *old_sets[2]; + TABLE *tbl= (TABLE *) table; + dbug_tmp_use_all_columns(tbl, old_sets, + &tbl->read_set, &tbl->write_set); + + if ((hist= create_histogram(mem_root, hist_type))) + { + if (hist->parse(mem_root, db_name->str, table_name->str, + table->field[table_field->field_index], + result->ptr(), result->length())) + { + delete hist; + } + else + { + read_stats->histogram= hist; + read_stats->histogram_exists= 1; + } + } + dbug_tmp_restore_column_maps(&tbl->read_set, + &tbl->write_set, + old_sets); + } + } + else + read_stats->histogram_exists= 1; } - case COLUMN_STAT_HISTOGRAM: - /* - Do nothing here: we take the histogram length from the 'histogram' - column itself - */ + if (!hist) + read_stats->set_null(COLUMN_STAT_HISTOGRAM); break; } + } } } } - } - - - /** - @brief - Read histogram from of column_stats - - @details - This method first looks for a record in the statistical table column_stats - by its primary key set the record buffer with the help of - Column_stat::set_key_fields. Then, if the row is found, the function reads - the value of the column 'histogram' of the table column_stat and sets - accordingly the corresponding bit in the bitmap read_stat.column_stat_nulls. - The method assumes that the value of histogram size and the pointer to - the histogram location has been already set in the fields size and values - of read_stats->histogram. - */ - - Histogram_base * load_histogram(MEM_ROOT *mem_root) - { - if (find_stat()) - { - char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_bin); - uint fldno= COLUMN_STAT_HISTOGRAM; - Field *stat_field= stat_table->field[fldno]; - table_field->read_stats->set_not_null(fldno); - stat_field->val_str(&val); - Histogram_type hist_type= - table_field->read_stats->histogram_type_on_disk; - - Histogram_base *hist; - if (!(hist= create_histogram(mem_root, hist_type, NULL))) - return NULL; - Field *field= table->field[table_field->field_index]; - if (!hist->parse(mem_root, db_name->str, table_name->str, - field, hist_type, - val.ptr(), val.length())) - { - table_field->read_stats->histogram= hist; - return hist; - } - else - delete hist; - } - return NULL; + return res; } }; bool Histogram_binary::parse(MEM_ROOT *mem_root, const char*, const char*, - Field*, Histogram_type type_arg, + Field*, const char *hist_data, size_t hist_data_len) { - /* On-disk an in-memory formats are the same. Just copy the data. */ - type= type_arg; - size= (uint8) hist_data_len; // 'size' holds the size of histogram in bytes + size= hist_data_len; // 'size' holds the size of histogram in bytes if (!(values= (uchar*)alloc_root(mem_root, hist_data_len))) return true; @@ -1299,8 +1349,7 @@ class Index_stat: public Stat_table Field *table_name_field; /* Field for the column index_stats.table_name */ Field *index_name_field; /* Field for the column index_stats.table_name */ Field *prefix_arity_field; /* Field for the column index_stats.prefix_arity */ - - KEY *table_key_info; /* Info on the index to read/update statistics on */ + const KEY *table_key_info; /* Info on the index to read/update statistics on */ uint prefix_arity; /* Number of components of the index prefix of interest */ void common_init_index_stat_table() @@ -1311,10 +1360,11 @@ class Index_stat: public Stat_table prefix_arity_field= stat_table->field[INDEX_STAT_PREFIX_ARITY]; } - void change_full_table_name(const LEX_CSTRING *db, const LEX_CSTRING *tab) + void change_full_table_name(const LEX_CSTRING *db, + const LEX_CSTRING *tab) override { - db_name_field->store(db->str, db->length, system_charset_info); - table_name_field->store(tab->str, tab->length, system_charset_info); + db_name_field->store(db, system_charset_info); + table_name_field->store(tab, system_charset_info); } public: @@ -1329,7 +1379,7 @@ class Index_stat: public Stat_table for the parameter 'stat'. */ - Index_stat(TABLE *stat, TABLE*tab) :Stat_table(stat, tab) + Index_stat(TABLE *stat, const TABLE *tab) :Stat_table(stat, tab) { common_init_index_stat_table(); } @@ -1361,9 +1411,13 @@ class Index_stat: public Stat_table void set_full_table_name() { - db_name_field->store(db_name->str, db_name->length, system_charset_info); - table_name_field->store(table_name->str, table_name->length, - system_charset_info); + db_name_field->store(db_name, system_charset_info); + table_name_field->store(table_name, system_charset_info); + } + + inline void set_index_name(const LEX_CSTRING *name) + { + index_name_field->store(name, system_charset_info); } /** @@ -1383,12 +1437,10 @@ class Index_stat: public Stat_table find_next_stat_for_prefix for an object of the Index_stat class. */ - void set_index_prefix_key_fields(KEY *index_info) + void set_index_prefix_key_fields(const KEY *index_info) { set_full_table_name(); - const char *index_name= index_info->name.str; - index_name_field->store(index_name, index_info->name.length, - system_charset_info); + set_index_name(&index_info->name); table_key_info= index_info; } @@ -1420,6 +1472,20 @@ class Index_stat: public Stat_table } + int update_index_name(const LEX_CSTRING *name) + { + index_name_field->store(name, system_charset_info); + return update_record(); + } + + + int read_next() + { + return stat_table->file->ha_index_next_same(stat_table->record[0], + last_key, + last_key_length); + } + /** @brief Store statistical data into statistical fields of table index_stats @@ -1433,7 +1499,7 @@ class Index_stat: public Stat_table equal to 0, the value of the column is set to NULL. */ - void store_stat_fields() + void store_stat_fields() override { Field *stat_field= stat_table->field[INDEX_STAT_AVG_FREQUENCY]; double avg_frequency= @@ -1453,29 +1519,29 @@ class Index_stat: public Stat_table Read statistical data from statistical fields of index_stats @details - This implementation of a purely virtual method first looks for a record the - statistical table index_stats by its primary key set the record buffer with - the help of Index_stat::set_key_fields. If the row is found the function - reads the value of the column 'avg_freguency' of the table index_stat and - sets the value of read_stat.avg_frequency[Index_stat::prefix_arity] - from the KEY_INFO structure 'table_key_info' accordingly. If the value of - the column is NULL, read_stat.avg_frequency[Index_stat::prefix_arity] is - set to 0. Otherwise, read_stat.avg_frequency[Index_stat::prefix_arity] is - set to the value of the column. - */ + Find a record in mysql.index_stats that has statistics for the index prefix + of interest (the prefix length is in this->prefix_arity). + We search for record using a PK lookup. The lookup values are in the stat + table's record buffer. + + The result is stored in read_stats->avg_frequency[this->prefix_arity]. + If mysql.index_stats doesn't have the value or has SQL NULL, we store the + value of 0. + */ - void get_stat_values() + bool get_stat_values(Index_statistics *read_stats) { double avg_frequency= 0; - if(find_stat()) + bool res; + if ((res= find_stat())) { Field *stat_field= stat_table->field[INDEX_STAT_AVG_FREQUENCY]; if (!stat_field->is_null()) avg_frequency= stat_field->val_real(); } - table_key_info->read_stats->set_avg_frequency(prefix_arity-1, avg_frequency); - } - + read_stats->set_avg_frequency(prefix_arity-1, avg_frequency); + return res; + } }; @@ -1644,24 +1710,20 @@ Histogram_builder *Histogram_binary::create_builder(Field *col, uint col_len, } -Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type, - THD *owner) +Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type) { Histogram_base *res= NULL; switch (hist_type) { case SINGLE_PREC_HB: case DOUBLE_PREC_HB: - res= new Histogram_binary(); + res= new (mem_root) Histogram_binary(hist_type); break; case JSON_HB: - res= new Histogram_json_hb(); + res= new (mem_root) Histogram_json_hb(); break; default: DBUG_ASSERT(0); } - - if (res) - res->set_owner(owner); return res; } @@ -1811,7 +1873,6 @@ class Count_distinct_field: public Sql_alloc { return table_field->collected_stats->histogram; } - }; @@ -1871,8 +1932,6 @@ class Index_prefix_calc: public Sql_alloc private: - /* Table containing index specified by index_info */ - TABLE *index_table; /* Info for the index i for whose prefix 'avg_frequency' is calculated */ KEY *index_info; /* The maximum number of the components in the prefixes of interest */ @@ -1909,7 +1968,7 @@ class Index_prefix_calc: public Sql_alloc bool is_partial_fields_present; Index_prefix_calc(THD *thd, TABLE *table, KEY *key_info) - : index_table(table), index_info(key_info), prefixes(0), empty(true), + : index_info(key_info), prefixes(0), empty(true), calc_state(NULL), is_single_comp_pk(false), is_partial_fields_present(false) { uint i; @@ -1943,8 +2002,8 @@ class Index_prefix_calc: public Sql_alloc } if (!(state->last_prefix= - new (thd->mem_root) Cached_item_field(thd, - key_info->key_part[i].field))) + new (thd->mem_root) + Cached_item_field(thd, key_info->key_part[i].field))) break; state->entry_count= state->prefix_count= 0; prefixes++; @@ -2034,8 +2093,9 @@ class Index_prefix_calc: public Sql_alloc @brief Create fields for min/max values to collect column statistics - @param - table Table the fields are created for + @param thd The thread handle + @param table Table the fields are created for + @param fields Fields for which we want to have statistics @details The function first allocates record buffers to store min/max values @@ -2055,12 +2115,13 @@ class Index_prefix_calc: public Sql_alloc */ static -void create_min_max_statistical_fields_for_table(TABLE *table) +void create_min_max_statistical_fields_for_table(THD *thd, TABLE *table, + MY_BITMAP *fields) { uint rec_buff_length= table->s->rec_buff_length; if ((table->collected_stats->min_max_record_buffers= - (uchar *) alloc_root(&table->mem_root, 2*rec_buff_length))) + (uchar *) alloc_root(thd->mem_root, 2*rec_buff_length))) { uchar *record= table->collected_stats->min_max_record_buffers; memset(record, 0, 2*rec_buff_length); @@ -2072,9 +2133,9 @@ void create_min_max_statistical_fields_for_table(TABLE *table) Field *fld; Field *table_field= *field_ptr; my_ptrdiff_t diff= record-table->record[0]; - if (!bitmap_is_set(table->read_set, table_field->field_index)) + if (!bitmap_is_set(fields, table_field->field_index)) continue; - if (!(fld= table_field->clone(&table->mem_root, table, diff))) + if (!(fld= table_field->clone(thd->mem_root, table, diff))) continue; if (i == 0) table_field->collected_stats->min_value= fld; @@ -2091,22 +2152,20 @@ void create_min_max_statistical_fields_for_table(TABLE *table) Create fields for min/max values to read column statistics @param - thd Thread handler + thd Thread handler @param - table_share Table share the fields are created for + table_share Table share the fields are created for @param - is_safe TRUE <-> at any time only one thread can perform the function + stats_cb TABLE_STATISTICS_CB object whose mem_root is used for allocations @details - The function first allocates record buffers to store min/max values - for 'table_share's fields. Then for each field f it creates Field structures + The function first allocates record buffers to store min/max values for + fields in the table. For each field f it creates Field structures that points to these buffers rather that to the record buffer as the Field object for f does. The pointers of the created fields are placed in the read_stats structure of the Field object for f. - The function allocates the buffers for min/max values in the table share - memory. - If the parameter is_safe is TRUE then it is guaranteed that at any given time - only one thread is executed the code of the function. + The function allocates the buffers for min/max values in the stats_cb + memory. @note The buffers allocated when min/max values are used to collect statistics @@ -2114,14 +2173,14 @@ void create_min_max_statistical_fields_for_table(TABLE *table) are used when statistics on min/max values for column is read as they are allocated in different mem_roots. The same is true for the fields created for min/max values. -*/ +*/ -static -void create_min_max_statistical_fields_for_table_share(THD *thd, - TABLE_SHARE *table_share) +static void +create_min_max_statistical_fields(THD *thd, + const TABLE_SHARE *table_share, + TABLE_STATISTICS_CB *stats_cb) { - TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb; - Table_statistics *stats= stats_cb->table_stats; + Table_statistics *stats= stats_cb->table_stats; if (stats->min_max_record_buffers) return; @@ -2136,7 +2195,10 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, for (uint i=0; i < 2; i++, record+= rec_buff_length) { - for (Field **field_ptr= table_share->field; *field_ptr; field_ptr++) + Column_statistics *column_stats= stats_cb->table_stats->column_stats; + for (Field **field_ptr= table_share->field; + *field_ptr; + field_ptr++, column_stats++) { Field *fld; Field *table_field= *field_ptr; @@ -2144,9 +2206,9 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, if (!(fld= table_field->clone(&stats_cb->mem_root, NULL, diff))) continue; if (i == 0) - table_field->read_stats->min_value= fld; + column_stats->min_value= fld; else - table_field->read_stats->max_value= fld; + column_stats->max_value= fld; } } } @@ -2158,17 +2220,18 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, @brief Allocate memory for the table's statistical data to be collected - @param - table Table for which the memory for statistical data is allocated + @param thd The thread handle + @param table Table for which we should allocate statistical data + @param stat_fields Fields for which we want to have statistics @note The function allocates the memory for the statistical data on 'table' with the intention to collect the data there. The memory is allocated for the statistics on the table, on the table's columns, and on the table's - indexes. The memory is allocated in the table's mem_root. + indexes. The memory is allocated in the thd's mem_root. @retval - 0 If the memory for all statistical data has been successfully allocated + 0 If the memory for all statistical data has been successfully allocated @retval 1 Otherwise @@ -2178,54 +2241,51 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, of the same table in parallel. */ -int alloc_statistics_for_table(THD* thd, TABLE *table) +int alloc_statistics_for_table(THD* thd, TABLE *table, MY_BITMAP *stat_fields) { Field **field_ptr; - - DBUG_ENTER("alloc_statistics_for_table"); - - uint columns= 0; - for (field_ptr= table->field; *field_ptr; field_ptr++) - { - if (bitmap_is_set(table->read_set, (*field_ptr)->field_index)) - columns++; - } - - Table_statistics *table_stats= - (Table_statistics *) alloc_root(&table->mem_root, - sizeof(Table_statistics)); - - Column_statistics_collected *column_stats= - (Column_statistics_collected *) alloc_root(&table->mem_root, - sizeof(Column_statistics_collected) * - columns); - + uint fields= bitmap_bits_set(stat_fields); uint keys= table->s->keys; - Index_statistics *index_stats= - (Index_statistics *) alloc_root(&table->mem_root, - sizeof(Index_statistics) * keys); - uint key_parts= table->s->ext_key_parts; - ulonglong *idx_avg_frequency= (ulonglong*) alloc_root(&table->mem_root, - sizeof(ulonglong) * key_parts); + uint hist_size= thd->variables.histogram_size; + Table_statistics *table_stats; + Column_statistics_collected *column_stats; + Index_statistics *index_stats; + ulonglong *idx_avg_frequency; + uchar *histogram; + DBUG_ENTER("alloc_statistics_for_table"); - if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency) + if (!multi_alloc_root(thd->mem_root, + &table_stats, sizeof(*table_stats), + &column_stats, sizeof(*column_stats) * fields, + &index_stats, sizeof(*index_stats) * keys, + &idx_avg_frequency, + sizeof(*idx_avg_frequency) * key_parts, + &histogram, hist_size * fields, + NullS)) DBUG_RETURN(1); + if (hist_size > 0) + bzero(histogram, hist_size * fields); + else + histogram= 0; + table->collected_stats= table_stats; table_stats->column_stats= column_stats; table_stats->index_stats= index_stats; table_stats->idx_avg_frequency= idx_avg_frequency; - memset(column_stats, 0, sizeof(Column_statistics) * columns); + bzero((void*) column_stats, sizeof(Column_statistics) * fields); for (field_ptr= table->field; *field_ptr; field_ptr++) { - if (bitmap_is_set(table->read_set, (*field_ptr)->field_index)) + if (bitmap_is_set(stat_fields, (*field_ptr)->field_index)) { column_stats->histogram = NULL; (*field_ptr)->collected_stats= column_stats++; } + else + (*field_ptr)->collected_stats= 0; } memset(idx_avg_frequency, 0, sizeof(ulonglong) * key_parts); @@ -2239,29 +2299,30 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) key_info->collected_stats->init_avg_frequency(idx_avg_frequency); idx_avg_frequency+= key_info->ext_key_parts; } + /* + idx_avg_frequency can be less than + table_stats->idx_avg_frequency + key_parts + in the case of LONG_UNIQUE_HASH_FIELD as these has a hidden + ext_key_part which is counted in table_share->ext_keyparts but not + in keyinfo->ext_key_parts. + */ + DBUG_ASSERT(idx_avg_frequency <= table_stats->idx_avg_frequency + key_parts); - create_min_max_statistical_fields_for_table(table); + create_min_max_statistical_fields_for_table(thd, table, stat_fields); DBUG_RETURN(0); } /* - Free the "local" statistics for table. - We only free the statistics that is not on MEM_ROOT and needs to be - explicitly freed. + Free the "local" statistics for table allocated during getting statistics */ -void free_statistics_for_table(THD *thd, TABLE *table) + +void free_statistics_for_table(TABLE *table) { for (Field **field_ptr= table->field; *field_ptr; field_ptr++) { - // Only delete the histograms that are exclusivly owned by this thread - if ((*field_ptr)->collected_stats && - (*field_ptr)->collected_stats->histogram && - (*field_ptr)->collected_stats->histogram->get_owner() == thd) - { - delete (*field_ptr)->collected_stats->histogram; - (*field_ptr)->collected_stats->histogram= NULL; - } + delete (*field_ptr)->collected_stats; + (*field_ptr)->collected_stats= 0; } } @@ -2273,6 +2334,8 @@ void free_statistics_for_table(THD *thd, TABLE *table) thd Thread handler @param table_share Table share for which the memory for statistical data is allocated + @param + stats_cb TABLE_STATISTICS_CB object for storing the statistical data @note The function allocates the memory for the statistical data on a table in the @@ -2299,89 +2362,53 @@ void free_statistics_for_table(THD *thd, TABLE *table) Here the second and the third threads try to allocate the memory for statistical data at the same time. The precautions are taken to guarantee the correctness of the allocation. -*/ +*/ -static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share) +static int +alloc_engine_independent_statistics(THD *thd, const TABLE_SHARE *table_share, + TABLE_STATISTICS_CB *stats_cb) { - Field **field_ptr; - KEY *key_info, *end; - TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb; - - DBUG_ENTER("alloc_statistics_for_table_share"); - Table_statistics *table_stats= stats_cb->table_stats; - if (!table_stats) - { - table_stats= (Table_statistics *) alloc_root(&stats_cb->mem_root, - sizeof(Table_statistics)); - if (!table_stats) - DBUG_RETURN(1); - memset(table_stats, 0, sizeof(Table_statistics)); - stats_cb->table_stats= table_stats; - } - uint fields= table_share->fields; - Column_statistics *column_stats= table_stats->column_stats; - if (!column_stats) - { - column_stats= (Column_statistics *) alloc_root(&stats_cb->mem_root, - sizeof(Column_statistics) * - (fields+1)); - if (column_stats) - { - memset(column_stats, 0, sizeof(Column_statistics) * (fields+1)); - table_stats->column_stats= column_stats; - for (field_ptr= table_share->field; - *field_ptr; - field_ptr++, column_stats++) - { - (*field_ptr)->read_stats= column_stats; - (*field_ptr)->read_stats->min_value= NULL; - (*field_ptr)->read_stats->max_value= NULL; - } - create_min_max_statistical_fields_for_table_share(thd, table_share); - } - } - uint keys= table_share->keys; - Index_statistics *index_stats= table_stats->index_stats; - if (!index_stats) - { - index_stats= (Index_statistics *) alloc_root(&stats_cb->mem_root, - sizeof(Index_statistics) * - keys); - if (index_stats) - { - table_stats->index_stats= index_stats; - for (key_info= table_share->key_info, end= key_info + keys; - key_info < end; - key_info++, index_stats++) - { - key_info->read_stats= index_stats; - } - } - } - uint key_parts= table_share->ext_key_parts; - ulonglong *idx_avg_frequency= table_stats->idx_avg_frequency; - if (!idx_avg_frequency) + Index_statistics *index_stats; + ulonglong *idx_avg_frequency; + DBUG_ENTER("alloc_engine_independent_statistics"); + + Column_statistics *column_stats; + if (!multi_alloc_root(&stats_cb->mem_root, + &table_stats, sizeof(Table_statistics), + &column_stats, sizeof(Column_statistics) * fields, + &index_stats, sizeof(Index_statistics) * keys, + &idx_avg_frequency, + sizeof(*idx_avg_frequency) * key_parts, + NullS)) + DBUG_RETURN(1); + + /* Zero variables but not the gaps between them */ + bzero(table_stats, sizeof(Table_statistics)); + bzero((void*) column_stats, sizeof(Column_statistics) * fields); + bzero(index_stats, sizeof(Index_statistics) * keys); + bzero(idx_avg_frequency, sizeof(idx_avg_frequency) * key_parts); + + stats_cb->table_stats= table_stats; + table_stats->columns= table_share->fields; + table_stats->column_stats= column_stats; + table_stats->index_stats= index_stats; + table_stats->idx_avg_frequency= idx_avg_frequency; + + create_min_max_statistical_fields(thd, table_share, stats_cb); + + for (KEY *key_info= table_share->key_info, *end= key_info + keys; + key_info < end; + key_info++, index_stats++) { - idx_avg_frequency= (ulonglong*) alloc_root(&stats_cb->mem_root, - sizeof(ulonglong) * key_parts); - if (idx_avg_frequency) - { - memset(idx_avg_frequency, 0, sizeof(ulonglong) * key_parts); - table_stats->idx_avg_frequency= idx_avg_frequency; - for (key_info= table_share->key_info, end= key_info + keys; - key_info < end; - key_info++) - { - key_info->read_stats->init_avg_frequency(idx_avg_frequency); - idx_avg_frequency+= key_info->ext_key_parts; - } - } + index_stats->init_avg_frequency(idx_avg_frequency); + idx_avg_frequency+= key_info->ext_key_parts; } - DBUG_RETURN(column_stats && index_stats && idx_avg_frequency ? 0 : 1); + DBUG_ASSERT(idx_avg_frequency <= table_stats->idx_avg_frequency + key_parts); + DBUG_RETURN(0); } @@ -2414,19 +2441,22 @@ void Column_statistics_collected::init(THD *thd, Field *table_field) nulls= 0; column_total_length= 0; - if (is_single_pk_col) - count_distinct= NULL; - if (table_field->flags & BLOB_FLAG) - count_distinct= NULL; - else + count_distinct= NULL; + if (!is_single_pk_col && !(table_field->flags & BLOB_FLAG)) { count_distinct= table_field->type() == MYSQL_TYPE_BIT ? - new Count_distinct_field_bit(table_field, max_heap_table_size) : - new Count_distinct_field(table_field, max_heap_table_size); + new (thd->mem_root) Count_distinct_field_bit(table_field, + max_heap_table_size) : + new (thd->mem_root) Count_distinct_field(table_field, + max_heap_table_size); + if (count_distinct && !count_distinct->exists()) + { + /* Allocation failed */ + delete count_distinct; + count_distinct= NULL; + } } - if (count_distinct && !count_distinct->exists()) - count_distinct= NULL; } @@ -2495,25 +2525,23 @@ bool Column_statistics_collected::finish(MEM_ROOT *mem_root, ha_rows rows, bool have_histogram= false; if (hist_size != 0 && hist_type != INVALID_HISTOGRAM) { - have_histogram= true; - histogram= create_histogram(mem_root, hist_type, current_thd); + histogram= create_histogram(mem_root, hist_type); histogram->init_for_collection(mem_root, hist_type, hist_size); - } - /* Compute cardinality statistics and optionally histogram. */ - if (!have_histogram) - count_distinct->walk_tree(); - else - { if (count_distinct->walk_tree_with_histogram(rows - nulls)) { delete histogram; histogram= NULL; - delete count_distinct; count_distinct= NULL; return true; // Error } + have_histogram= true; + } + else + { + /* Compute cardinality statistics */ + count_distinct->walk_tree(); } ulonglong distincts= count_distinct->get_count_distinct(); @@ -2623,7 +2651,6 @@ int collect_statistics_for_index(THD *thd, TABLE *table, uint index) { int rc= 0; KEY *key_info= &table->key_info[index]; - DBUG_ENTER("collect_statistics_for_index"); /* No statistics for FULLTEXT indexes. */ @@ -2733,7 +2760,6 @@ int collect_statistics_for_table(THD *thd, TABLE *table) handler *file=table->file; double sample_fraction= thd->variables.sample_percentage / 100; const ha_rows MIN_THRESHOLD_FOR_SAMPLING= 50000; - DBUG_ENTER("collect_statistics_for_table"); table->collected_stats->cardinality_is_null= TRUE; @@ -2815,10 +2841,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) continue; bitmap_set_bit(table->write_set, table_field->field_index); if (!rc) - { - rc= table_field->collected_stats->finish(&table->mem_root, rows, + rc= table_field->collected_stats->finish(thd->mem_root, rows, sample_fraction); - } else table_field->collected_stats->cleanup(); } @@ -2851,10 +2875,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) @brief Update statistics for a table in the persistent statistical tables - @param - thd The thread handle - @param - table The table to collect statistics on + @param thd The thread handle + @param table The table to collect statistics on @details For each statistical table st the function looks for the rows from this @@ -2898,9 +2920,18 @@ int update_statistics_for_table(THD *thd, TABLE *table) start_new_trans new_trans(thd); - if ((open_stat_tables(thd, tables, TRUE))) - DBUG_RETURN(rc); + if (open_stat_tables(thd, tables, TRUE)) + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); + } + /* + Ensure that no one is reading satistics while we are writing them + This ensures that statistics is always read consistently + */ + mysql_mutex_lock(&table->s->LOCK_statistics); + save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); /* Update the statistical table table_stats */ @@ -2947,11 +2978,16 @@ int update_statistics_for_table(THD *thd, TABLE *table) } } + tables[TABLE_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[COLUMN_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[INDEX_STAT].table->file->extra(HA_EXTRA_FLUSH); + thd->restore_stmt_binlog_format(save_binlog_format); if (thd->commit_whole_transaction_and_close_tables()) rc= 1; - new_trans.restore_old_transaction(); + mysql_mutex_unlock(&table->s->LOCK_statistics); + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -2961,11 +2997,14 @@ int update_statistics_for_table(THD *thd, TABLE *table) Read statistics for a table from the persistent statistical tables @param - thd The thread handle + thd The thread handle @param - table The table to read statistics on + table The table to read statistics on. @param - stat_tables The array of TABLE_LIST objects for statistical tables + stat_tables The array of TABLE_LIST objects for statistical tables + @param + force_reload Flag to require reloading the statistics from the tables + even if it has been already loaded @details For each statistical table the function looks for the rows from this @@ -2979,9 +3018,9 @@ int update_statistics_for_table(THD *thd, TABLE *table) The function is called by read_statistics_for_tables_if_needed(). @retval - 0 If data has been successfully read for the table + pointer to object If data has been successfully read for the table @retval - 1 Otherwise + 0 Otherwise @note Objects of the helper classes Table_stat, Column_stat and Index_stat @@ -2990,7 +3029,10 @@ int update_statistics_for_table(THD *thd, TABLE *table) */ static -int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) +TABLE_STATISTICS_CB* +read_statistics_for_table(THD *thd, TABLE *table, + TABLE_LIST *stat_tables, bool force_reload, + bool want_histograms) { uint i; TABLE *stat_table; @@ -2998,92 +3040,119 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) Field **field_ptr; KEY *key_info, *key_info_end; TABLE_SHARE *table_share= table->s; - DBUG_ENTER("read_statistics_for_table"); - DEBUG_SYNC(thd, "statistics_mem_alloc_start1"); - DEBUG_SYNC(thd, "statistics_mem_alloc_start2"); - if (!table_share->stats_cb.start_stats_load()) - DBUG_RETURN(table_share->stats_cb.stats_are_ready() ? 0 : 1); + if (!force_reload && table_share->stats_cb && + (!want_histograms || !table_share->histograms_exists())) + { + if (table->stats_cb == table_share->stats_cb) + DBUG_RETURN(table->stats_cb); // Use current + table->update_engine_independent_stats(); // Copy table_share->stats_cb + DBUG_RETURN(table->stats_cb); + } - if (alloc_statistics_for_table_share(thd, table_share)) + /* + Read data into a new TABLE_STATISTICS_CB object and replace + TABLE_SHARE::stats_cb with this new one once the reading is finished + */ + TABLE_STATISTICS_CB *new_stats_cb; + if (!(new_stats_cb= new TABLE_STATISTICS_CB)) + DBUG_RETURN(0); /* purecov: inspected */ + + if (alloc_engine_independent_statistics(thd, table_share, new_stats_cb)) { - table_share->stats_cb.abort_stats_load(); - DBUG_RETURN(1); + /* purecov: begin inspected */ + delete new_stats_cb; + DBUG_RETURN(0); + /* purecov: end */ } /* Don't write warnings for internal field conversions */ Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); /* Read statistics from the statistical table table_stats */ - Table_statistics *read_stats= table_share->stats_cb.table_stats; + Table_statistics *read_stats= new_stats_cb->table_stats; stat_table= stat_tables[TABLE_STAT].table; Table_stat table_stat(stat_table, table); table_stat.set_key_fields(); - table_stat.get_stat_values(); - + if (table_stat.get_stat_values(new_stats_cb->table_stats)) + new_stats_cb->stats_available|= TABLE_STAT_TABLE; + /* Read statistics from the statistical table column_stats */ stat_table= stat_tables[COLUMN_STAT].table; - bool have_histograms= false; Column_stat column_stat(stat_table, table); - for (field_ptr= table_share->field; *field_ptr; field_ptr++) + Column_statistics *column_statistics= new_stats_cb->table_stats->column_stats; + for (field_ptr= table_share->field; + *field_ptr; + field_ptr++, column_statistics++) { table_field= *field_ptr; column_stat.set_key_fields(table_field); - column_stat.get_stat_values(); - if (table_field->read_stats->histogram_type_on_disk != INVALID_HISTOGRAM) - have_histograms= true; + if (column_stat.get_stat_values(column_statistics, + &new_stats_cb->mem_root, + want_histograms)) + new_stats_cb->stats_available|= TABLE_STAT_COLUMN; + if (column_statistics->histogram_exists) + { + new_stats_cb->histograms_exists_on_disk= 1; + if (column_statistics->histogram) + new_stats_cb->stats_available|= TABLE_STAT_HISTOGRAM; + } } - table_share->stats_cb.have_histograms= have_histograms; /* Read statistics from the statistical table index_stats */ stat_table= stat_tables[INDEX_STAT].table; Index_stat index_stat(stat_table, table); + Index_statistics *index_statistics= new_stats_cb->table_stats->index_stats; for (key_info= table_share->key_info, key_info_end= key_info + table_share->keys; - key_info < key_info_end; key_info++) + key_info < key_info_end; key_info++, index_statistics++) { uint key_parts= key_info->ext_key_parts; + bool found= 0; for (i= 0; i < key_parts; i++) { index_stat.set_key_fields(key_info, i+1); - index_stat.get_stat_values(); + found|= index_stat.get_stat_values(index_statistics); } - + if (found) + new_stats_cb->stats_available|= TABLE_STAT_INDEX; + key_part_map ext_key_part_map= key_info->ext_key_part_map; if (key_info->user_defined_key_parts != key_info->ext_key_parts && - key_info->read_stats->get_avg_frequency(key_info->user_defined_key_parts) == 0) + index_statistics->get_avg_frequency(key_info->user_defined_key_parts) == 0) { KEY *pk_key_info= table_share->key_info + table_share->primary_key; uint k= key_info->user_defined_key_parts; uint pk_parts= pk_key_info->user_defined_key_parts; ha_rows n_rows= read_stats->cardinality; - double k_dist= n_rows / key_info->read_stats->get_avg_frequency(k-1); + double k_dist= n_rows / index_statistics->get_avg_frequency(k-1); uint m= 0; + Index_statistics *pk_read_stats= (new_stats_cb->table_stats->index_stats + + table_share->primary_key); for (uint j= 0; j < pk_parts; j++) { if (!(ext_key_part_map & 1 << j)) { for (uint l= k; l < k + m; l++) { - double avg_frequency= - pk_key_info->read_stats->get_avg_frequency(j-1); + double avg_frequency= pk_read_stats->get_avg_frequency(j-1); set_if_smaller(avg_frequency, 1); - double val= pk_key_info->read_stats->get_avg_frequency(j) / - avg_frequency; - key_info->read_stats->set_avg_frequency (l, val); + double val= (pk_read_stats->get_avg_frequency(j) / + avg_frequency); + index_statistics->set_avg_frequency (l, val); } } else { - double avg_frequency= pk_key_info->read_stats->get_avg_frequency(j); - key_info->read_stats->set_avg_frequency(k + m, avg_frequency); + double avg_frequency= pk_read_stats->get_avg_frequency(j); + index_statistics->set_avg_frequency(k + m, avg_frequency); m++; } } for (uint l= k; l < k + m; l++) { - double avg_frequency= key_info->read_stats->get_avg_frequency(l); + double avg_frequency= index_statistics->get_avg_frequency(l); if (avg_frequency == 0 || read_stats->cardinality_is_null) avg_frequency= 1; else if (avg_frequency > 1) @@ -3091,119 +3160,14 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) avg_frequency/= k_dist; set_if_bigger(avg_frequency, 1); } - key_info->read_stats->set_avg_frequency(l, avg_frequency); + index_statistics->set_avg_frequency(l, avg_frequency); } } } - - table_share->stats_cb.end_stats_load(); - DBUG_RETURN(0); -} - - -/** - @breif - Cleanup of min/max statistical values for table share -*/ - -void delete_stat_values_for_table_share(TABLE_SHARE *table_share) -{ - TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb; - Table_statistics *table_stats= stats_cb->table_stats; - if (!table_stats) - return; - Column_statistics *column_stats= table_stats->column_stats; - if (!column_stats) - return; - - for (Field **field_ptr= table_share->field; - *field_ptr; - field_ptr++, column_stats++) - { - if (column_stats->min_value) - { - delete column_stats->min_value; - column_stats->min_value= NULL; - } - if (column_stats->max_value) - { - delete column_stats->max_value; - column_stats->max_value= NULL; - } - - delete column_stats->histogram; - column_stats->histogram=NULL; - } + DBUG_RETURN(new_stats_cb); } -/** - @brief - Read histogram for a table from the persistent statistical tables - - @param - thd The thread handle - @param - table The table to read histograms for - @param - stat_tables The array of TABLE_LIST objects for statistical tables - - @details - For the statistical table columns_stats the function looks for the rows - from this table that contain statistical data on 'table'. If such rows - are found the histograms from them are read into the memory allocated - for histograms of 'table'. Later at the query processing these histogram - are supposed to be used by the optimizer. - The parameter stat_tables should point to an array of TABLE_LIST - objects for all statistical tables linked into a list. All statistical - tables are supposed to be opened. - The function is called by read_statistics_for_tables_if_needed(). - - @retval - 0 If data has been successfully read for the table - @retval - 1 Otherwise - - @note - Objects of the helper Column_stat are employed read histogram - from the statistical table column_stats now. -*/ - -static -int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) -{ - TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb; - DBUG_ENTER("read_histograms_for_table"); - - if (stats_cb->start_histograms_load()) - { - Column_stat column_stat(stat_tables[COLUMN_STAT].table, table); - - /* - The process of histogram loading makes use of the field it is for. Mark - all fields as readable/writable in order to allow that. - */ - MY_BITMAP *old_sets[2]; - dbug_tmp_use_all_columns(table, old_sets, &table->read_set, &table->write_set); - - for (Field **field_ptr= table->s->field; *field_ptr; field_ptr++) - { - Field *table_field= *field_ptr; - if (table_field->read_stats->histogram_type_on_disk != INVALID_HISTOGRAM) - { - column_stat.set_key_fields(table_field); - table_field->read_stats->histogram= - column_stat.load_histogram(&stats_cb->mem_root); - } - } - stats_cb->end_histograms_load(); - - dbug_tmp_restore_column_maps(&table->read_set, &table->write_set, old_sets); - } - table->histograms_are_read= true; - DBUG_RETURN(0); -} - /** @brief Read statistics for tables from a table list if it is needed @@ -3241,65 +3205,98 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) case SQLCOM_CREATE_TABLE: case SQLCOM_SET_OPTION: case SQLCOM_DO: - return read_statistics_for_tables(thd, tables); + return read_statistics_for_tables(thd, tables, 0); default: return 0; } } -static void dump_stats_from_share_to_table(TABLE *table) +/* + Update TABLE field and key objects with pointers to + the current statistical data in table->stats_cb +*/ + + +void TABLE_STATISTICS_CB::update_stats_in_table(TABLE *table) { - TABLE_SHARE *table_share= table->s; - KEY *key_info= table_share->key_info; - KEY *key_info_end= key_info + table_share->keys; - KEY *table_key_info= table->key_info; - for ( ; key_info < key_info_end; key_info++, table_key_info++) - table_key_info->read_stats= key_info->read_stats; - - Field **field_ptr= table_share->field; - Field **table_field_ptr= table->field; - for ( ; *field_ptr; field_ptr++, table_field_ptr++) - (*table_field_ptr)->read_stats= (*field_ptr)->read_stats; + DBUG_ASSERT(table->stats_cb == this); + + /* + Table_statistics doesn't need to be updated: set_statistics_for_table() + sets TABLE::used_stat_records from table->stats_cb.table_stats.cardinality + */ + + KEY *key_info= table->key_info; + KEY *key_info_end= key_info + table->s->keys; + Index_statistics *index_stats= table_stats->index_stats; + + for ( ; key_info < key_info_end; key_info++, index_stats++) + key_info->read_stats= index_stats; + + Field **field_ptr= table->field; + Column_statistics *column_stats= table_stats->column_stats; + + for ( ; *field_ptr; field_ptr++, column_stats++) + (*field_ptr)->read_stats= column_stats; + /* Mark that stats are now usable */ table->stats_is_read= true; } -int read_statistics_for_tables(THD *thd, TABLE_LIST *tables) +int +read_statistics_for_tables(THD *thd, TABLE_LIST *tables, bool force_reload) { + int rc= 0; TABLE_LIST stat_tables[STATISTICS_TABLES]; - + bool found_stat_table= false; + bool statistics_for_tables_is_needed= false; + bool want_histograms= thd->variables.optimizer_use_condition_selectivity > 3; DBUG_ENTER("read_statistics_for_tables"); - if (thd->bootstrap || thd->variables.use_stat_tables == NEVER) + if (thd->bootstrap || thd->variables.use_stat_tables == NEVER || !tables) DBUG_RETURN(0); - bool found_stat_table= false; - bool statistics_for_tables_is_needed= false; - for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { + TABLE *table= tl->table; TABLE_SHARE *table_share; - if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) && - table_share->tmp_table == NO_TMP_TABLE) + + /* Skip tables that can't have statistics. */ + if (tl->is_view_or_derived() || !table || !(table_share= table->s)) + continue; + /* Skip temporary tables */ + if (table_share->tmp_table != NO_TMP_TABLE) + continue; + + if (table_share->table_category == TABLE_CATEGORY_USER) { - if (table_share->table_category == TABLE_CATEGORY_USER) + /* Force reloading means we always read all stats tables. */ + if (force_reload || !table_share->stats_cb) + { + statistics_for_tables_is_needed= true; + continue; + } + + /* Stats versions don't match, take a reference under a mutex. */ + if (table->stats_cb != table_share->stats_cb) + { + table->update_engine_independent_stats(); + table->stats_cb->update_stats_in_table(table); + } + /* + We need to read histograms if they exist but have not yet been + loaded into memory. + */ + if (want_histograms && + table->stats_cb->histograms_exists() && + !(table->stats_cb->stats_available & TABLE_STAT_HISTOGRAM)) { - if (table_share->stats_cb.stats_are_ready()) - { - if (!tl->table->stats_is_read) - dump_stats_from_share_to_table(tl->table); - tl->table->histograms_are_read= - table_share->stats_cb.histograms_are_ready(); - if (table_share->stats_cb.histograms_are_ready() || - thd->variables.optimizer_use_condition_selectivity <= 3) - continue; - } statistics_for_tables_is_needed= true; } - else if (is_stat_table(&tl->db, &tl->alias)) - found_stat_table= true; } + else if (is_stat_table(&tl->db, &tl->alias)) + found_stat_table= true; } DEBUG_SYNC(thd, "statistics_read_start"); @@ -3315,31 +3312,65 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables) start_new_trans new_trans(thd); if (open_stat_tables(thd, stat_tables, FALSE)) - DBUG_RETURN(1); + { + rc= 1; + goto end; + } for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { + TABLE *table= tl->table; TABLE_SHARE *table_share; - if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) && - table_share->tmp_table == NO_TMP_TABLE && - table_share->table_category == TABLE_CATEGORY_USER) + + /* Skip tables that can't have statistics. */ + if (tl->is_view_or_derived() || !table || !(table_share= table->s) || + table_share->tmp_table != NO_TMP_TABLE || + table_share->table_category != TABLE_CATEGORY_USER) + continue; + + if (force_reload || !table_share->stats_cb || + table->stats_cb != table_share->stats_cb || + (want_histograms && table->stats_cb->histograms_exists() && + !(table->stats_cb->stats_available & TABLE_STAT_HISTOGRAM))) { - if (!tl->table->stats_is_read) + TABLE_STATISTICS_CB *stats_cb; + DEBUG_SYNC(thd, "read_statistics_for_table_start1"); + DEBUG_SYNC(thd, "read_statistics_for_table_start2"); + + /* + The following lock is here to ensure that if a lot of threads are + accessing the table at the same time after a ANALYZE TABLE, + only one thread is loading the data from the the stats tables + and the others threads are reusing the loaded data. + */ + mysql_mutex_lock(&table_share->LOCK_statistics); + if (!(stats_cb= read_statistics_for_table(thd, table, stat_tables, + force_reload, want_histograms))) { - if (!read_statistics_for_table(thd, tl->table, stat_tables)) - dump_stats_from_share_to_table(tl->table); - else - continue; + /* purecov: begin inspected */ + mysql_mutex_unlock(&table_share->LOCK_statistics); + continue; + /* purecov: end */ + } + + if (stats_cb->unused()) + { + /* New object created, update share to use it */ + table_share->update_engine_independent_stats(stats_cb); + table->update_engine_independent_stats(); } - if (thd->variables.optimizer_use_condition_selectivity > 3) - (void) read_histograms_for_table(thd, tl->table, stat_tables); + mysql_mutex_unlock(&table_share->LOCK_statistics); + table->stats_cb->update_stats_in_table(table); + table->stats_is_read= (stats_cb->stats_available != + TABLE_STAT_NO_STATS); } } thd->commit_whole_transaction_and_close_tables(); - new_trans.restore_old_transaction(); - DBUG_RETURN(0); +end: + new_trans.restore_old_transaction(); + DBUG_RETURN(rc); } @@ -3379,9 +3410,12 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, DBUG_ENTER("delete_statistics_for_table"); start_new_trans new_trans(thd); - + if (open_stat_tables(thd, tables, TRUE)) + { + new_trans.restore_old_transaction(); DBUG_RETURN(0); + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3422,10 +3456,14 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, if (err & !rc) rc= 1; + tables[TABLE_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[COLUMN_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[INDEX_STAT].table->file->extra(HA_EXTRA_FLUSH); + thd->restore_stmt_binlog_format(save_binlog_format); thd->commit_whole_transaction_and_close_tables(); - new_trans.restore_old_transaction(); + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3462,7 +3500,10 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) start_new_trans new_trans(thd); if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1])) - DBUG_RETURN(0); + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); // Not an error + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3476,11 +3517,202 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) rc= 1; } + column_stat.flush(); thd->restore_stmt_binlog_format(save_binlog_format); if (thd->commit_whole_transaction_and_close_tables()) rc= 1; + new_trans.restore_old_transaction(); + DBUG_RETURN(rc); +} + + +/** + Generate tempoary column or index name for renames +*/ + +static LEX_CSTRING *generate_tmp_name(LEX_CSTRING *to, uint counter) +{ + char *res=int10_to_str(counter, strmov((char*) to->str, "#sql_tmp_name#"), + 10); + /* + Include an end zero in the tmp name to avoid any possible conflict + with existing column names. + */ + to->length= (size_t) (res - to->str) + 1; + return to; +} + + +/** + Rename a set of columns in the statistical table column_stats + + @param thd The thread handle + @param tab The table the column belongs to + @param fields List of fields and names to be renamed + + @details + The function replaces the names of the columns in fields that belongs + to the table 'tab' in the statistical table column_stats. + + @retval 0 If update was successful, tmp table or could not open stat table + @retval -1 Commit failed + @retval >0 Error number from engine + + @note + The function is called when executing any statement that renames a column, + but does not change the column definition. +*/ + +int rename_columns_in_stat_table(THD *thd, TABLE *tab, + List + *fields) +{ + int err; + enum_binlog_format save_binlog_format; + TABLE *stat_table; + TABLE_LIST tables; + int rc= 0; + uint duplicate_counter= 0; + uint org_elements= fields->elements+1; + List_iterator it(*fields); + char tmp_name_buffer[32]; + LEX_CSTRING tmp_name= {tmp_name_buffer, 0}; + DBUG_ENTER("rename_column_in_stat_tables"); + + if (tab->s->tmp_table != NO_TMP_TABLE) + DBUG_RETURN(0); + + start_new_trans new_trans(thd); + + if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1])) + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); + } + + save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); + + /* Rename column in the statistical table table_stat */ + + stat_table= tables.table; + + /* Loop until fields is empty or previous round did nothing */ + while (!fields->is_empty() && fields->elements != org_elements) + { + Alter_info::RENAME_COLUMN_STAT_PARAMS *field; + org_elements= fields->elements; + it.rewind(); + while ((field= it++)) + { + Column_stat column_stat(stat_table, tab); + LEX_CSTRING *from_name; + from_name= (!field->duplicate_counter ? + &field->field->field_name : + generate_tmp_name(&tmp_name, + field->duplicate_counter)); + column_stat.set_key_fields(from_name); + if (column_stat.find_stat()) + { + err= column_stat.update_column_key_part(field->name); + if (likely(err != HA_ERR_FOUND_DUPP_KEY)) + it.remove(); + else if (!field->duplicate_counter) + { + /* + This is probably an ALTER TABLE of type rename a->b, b->a + Rename the column to a temporary name + */ + LEX_CSTRING *new_name= + generate_tmp_name(&tmp_name, ++duplicate_counter); + field->duplicate_counter= duplicate_counter; + + if ((err= column_stat.update_column(new_name))) + { + if (likely(err != HA_ERR_FOUND_DUPP_KEY)) + { + DBUG_ASSERT(0); + it.remove(); // Unknown error, ignore column + } + else + { + /* + The only way this could happen is if the table has a column + with same name as the temporary column name, probably from a + failed alter table. + Remove the conflicting row and update it again. + */ + if (!column_stat.find_stat()) + DBUG_ASSERT(0); + else if (column_stat.delete_stat()) + DBUG_ASSERT(0); + else + { + column_stat.set_key_fields(from_name); + if (!column_stat.find_stat()) + DBUG_ASSERT(0); + else if (column_stat.update_column_key_part(&tmp_name)) + DBUG_ASSERT(0); + } + } + } + } + } + else /* column_stat.find_stat() */ + { + /* Statistics for the field did not exists */ + it.remove(); + } + } + } + + if (!fields->is_empty()) + { + /* + All unhandled renamed fields has now a temporary name. + Remove all conflicing rows and rename the temporary name to + the final name. + */ + Alter_info::RENAME_COLUMN_STAT_PARAMS *field; + it.rewind(); + while ((field= it++)) + { + Column_stat column_stat(stat_table, tab); + DBUG_ASSERT(field->duplicate_counter); + + /* Remove the conflicting row */ + column_stat.set_key_fields(field->name); + if (column_stat.find_stat()) + { + int err __attribute__((unused)); + err= column_stat.delete_stat(); + DBUG_ASSERT(err == 0); + } + + /* Restore saved row with old statistics to new name */ + column_stat. + set_key_fields(generate_tmp_name(&tmp_name, + field->duplicate_counter)); + if (column_stat.find_stat()) + { + int err __attribute__((unused)); + err= column_stat.update_column_key_part(field->name); + DBUG_ASSERT(err == 0); + } + else + { + DBUG_ASSERT(0); + } + } + } + + stat_table->file->extra(HA_EXTRA_FLUSH); + thd->restore_stmt_binlog_format(save_binlog_format); + if (thd->commit_whole_transaction_and_close_tables()) + rc= -1; + + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3491,7 +3723,8 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) @param thd The thread handle @param tab The table the index belongs to - @param key_info The descriptor of the index whose statistics is to be deleted + @param key_info The descriptor of the index whose statistics is to be + deleted @param ext_prefixes_only Delete statistics only on the index prefixes extended by the components of the primary key @@ -3499,7 +3732,8 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) The function delete statistics on the index specified by 'key_info' defined on the table 'tab' from the statistical table index_stats. - @retval 0 If all deletions are successful or we couldn't open statistics table + @retval 0 If all deletions are successful or we couldn't open statistics + table @retval 1 Otherwise @note @@ -3520,7 +3754,10 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, start_new_trans new_trans(thd); if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[2])) - DBUG_RETURN(0); + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); // Not an error + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3554,11 +3791,194 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, if (err && !rc) rc= 1; + /* Make change permanent and avoid 'table is marked as crashed' errors */ + index_stat.flush(); + thd->restore_stmt_binlog_format(save_binlog_format); if (thd->commit_whole_transaction_and_close_tables()) rc= 1; + new_trans.restore_old_transaction(); + DBUG_RETURN(rc); +} + + +/** + Rename a set of indexes in the statistical table index_stats + + @param thd The thread handle + @param tab The table the indexes belongs to + @param fields List of indexes to be renamed + + @details + The function replaces the names of the indexe in fields that belongs + to the table 'tab' in the statistical table index_stats. + + @retval 0 If update was successful, tmp table or could not open stat table + @retval -1 Commit failed + @retval >0 Error number from engine + + @note + The function is called when executing any statement that renames a column, + but does not change the column definition. +*/ + +int rename_indexes_in_stat_table(THD *thd, TABLE *tab, + List + *indexes) +{ + int err; + enum_binlog_format save_binlog_format; + TABLE *stat_table; + TABLE_LIST tables; + int rc= 0; + uint duplicate_counter= 0; + List_iterator it(*indexes); + Alter_info::RENAME_INDEX_STAT_PARAMS *index; + char tmp_name_buffer[32]; + LEX_CSTRING tmp_name= {tmp_name_buffer, 0}; + DBUG_ENTER("rename_indexes_in_stat_tables"); + + if (tab->s->tmp_table != NO_TMP_TABLE) + DBUG_RETURN(0); + + start_new_trans new_trans(thd); + + if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[2])) + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); + } + + save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); + + /* Rename index in the statistical table index_stat */ + + stat_table= tables.table; + + /* + Loop over all indexes and rename to new name or temp name in case of + conflicts + */ + + while ((index= it++)) + { + Index_stat index_stat(stat_table, tab); + uint found= 0; + /* We have to make a loop as one index may have many entries */ + for (;;) + { + index_stat.set_index_prefix_key_fields(index->key); + if (!index_stat.find_next_stat_for_prefix(3)) + break; + index_stat.store_record_for_update(); + err= index_stat.update_index_name(index->name); + + if (unlikely(err == HA_ERR_FOUND_DUPP_KEY)) + { + /* + This is probably an ALTER TABLE of type rename a->b, b->a + Rename the column to a temporary name + */ + if (!found++) + ++duplicate_counter; + index->duplicate_counter= duplicate_counter; + index->usage_count++; + if ((err= index_stat.update_index_name(generate_tmp_name(&tmp_name, duplicate_counter)))) + { + if (err != HA_ERR_FOUND_DUPP_KEY) + { + DBUG_ASSERT(0); + } + else + { + /* + The only way this could happen is if the table has an index + with same name as the temporary column index, probably from a + failed alter table. + Remove the conflicting row and update it again. + */ + if (!index_stat.find_stat()) + DBUG_ASSERT(0); + else if (index_stat.delete_stat()) + DBUG_ASSERT(0); + else + { + index_stat.set_index_prefix_key_fields(index->key); + if (!index_stat.find_stat()) + DBUG_ASSERT(0); + else + { + index_stat.store_record_for_update(); + if (index_stat.update_index_name(&tmp_name)) + DBUG_ASSERT(0); + } + } + } + } + } + } + if (!found) + it.remove(); // All renames succeded + } + + if (!indexes->is_empty()) + { + /* + All unhandled renamed index has now a temporary name. + Remove all conflicing rows and rename the temporary name to + the final name. + */ + + Alter_info::RENAME_INDEX_STAT_PARAMS *index; + it.rewind(); + Index_stat index_stat(stat_table, tab); + stat_table->file->ha_index_init(index_stat.stat_key_idx, 0); + + while ((index= it++)) + { + int err __attribute__((unused)); + + /* Remove the conflicting rows */ + index_stat.set_index_prefix_key_fields(index->key); + index_stat.set_index_name(index->name); + + if (index_stat.find_next_stat_for_prefix_with_next(3)) + { + do + { + err= index_stat.delete_stat(); + DBUG_ASSERT(err == 0); + } + while (index_stat.read_next() == 0); + } + + /* Restore saved row with old statistics to new name */ + index_stat.set_index_name(generate_tmp_name(&tmp_name, + index->duplicate_counter)); + if (!index_stat.find_stat_with_next()) + DBUG_ASSERT(0); + else + { + uint updated= 0; + do + { + index_stat.store_record_for_update(); + err= index_stat.update_index_name(index->name); + DBUG_ASSERT(err == 0); + } while (++updated < index->usage_count && index_stat.read_next() == 0); + } + } + stat_table->file->ha_index_end(); + } + + stat_table->file->extra(HA_EXTRA_FLUSH); + thd->restore_stmt_binlog_format(save_binlog_format); + if (thd->commit_whole_transaction_and_close_tables()) + rc= -1; + + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3605,7 +4025,10 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, start_new_trans new_trans(thd); if (open_stat_tables(thd, tables, TRUE)) - DBUG_RETURN(0); // not an error + { + new_trans.restore_old_transaction(); + DBUG_RETURN(0); + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3653,71 +4076,15 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, rc= 1; } - thd->restore_stmt_binlog_format(save_binlog_format); - if (thd->commit_whole_transaction_and_close_tables()) - rc= 1; - new_trans.restore_old_transaction(); - - DBUG_RETURN(rc); -} - - -/** - Rename a column in the statistical table column_stats - - @param thd The thread handle - @param tab The table the column belongs to - @param col The column to be renamed - @param new_name The new column name - - @details - The function replaces the name of the column 'col' belonging to the table - 'tab' for 'new_name' in the statistical table column_stats. - - @retval 0 If all updates of the table name are successful - @retval 1 Otherwise - - @note - The function is called when executing any statement that renames a column, - but does not change the column definition. -*/ - -int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, - const char *new_name) -{ - int err; - enum_binlog_format save_binlog_format; - TABLE *stat_table; - TABLE_LIST tables; - int rc= 0; - DBUG_ENTER("rename_column_in_stat_tables"); - - if (tab->s->tmp_table != NO_TMP_TABLE) - DBUG_RETURN(0); - - start_new_trans new_trans(thd); - - if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1])) - DBUG_RETURN(rc); - - save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); - - /* Rename column in the statistical table table_stat */ - stat_table= tables.table; - Column_stat column_stat(stat_table, tab); - column_stat.set_key_fields(col); - if (column_stat.find_stat()) - { - err= column_stat.update_column_key_part(new_name); - if (err & !rc) - rc= 1; - } + tables[TABLE_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[COLUMN_STAT].table->file->extra(HA_EXTRA_FLUSH); + tables[INDEX_STAT].table->file->extra(HA_EXTRA_FLUSH); thd->restore_stmt_binlog_format(save_binlog_format); if (thd->commit_whole_transaction_and_close_tables()) rc= 1; - new_trans.restore_old_transaction(); + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3739,8 +4106,8 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, void set_statistics_for_table(THD *thd, TABLE *table) { - TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb; - Table_statistics *read_stats= stats_cb->table_stats; + TABLE_STATISTICS_CB *stats_cb= table->s->stats_cb; + Table_statistics *read_stats= stats_cb ? stats_cb->table_stats : 0; /* The MAX below is to ensure that we don't return 0 rows for a table if it @@ -3748,7 +4115,7 @@ void set_statistics_for_table(THD *thd, TABLE *table) */ table->used_stat_records= (!check_eits_preferred(thd) || - !table->stats_is_read || read_stats->cardinality_is_null) ? + !table->stats_is_read || !read_stats || read_stats->cardinality_is_null) ? table->file->stats.records : MY_MAX(read_stats->cardinality, 1); /* @@ -4110,11 +4477,9 @@ bool is_eits_usable(Field *field) Column_statistics* col_stats= field->read_stats; // check if column_statistics was allocated for this field - if (!col_stats) + if (!col_stats || !field->orig_table->stats_is_read) return false; - DBUG_ASSERT(field->orig_table->stats_is_read); - /* (1): checks if we have EITS statistics for a particular column (2): Don't use EITS for GEOMETRY columns diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index a0e6a89a1ca6e..3ec7eb06fa69b 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -121,20 +121,25 @@ bool check_eits_preferred(THD *thd) } int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables); -int read_statistics_for_tables(THD *thd, TABLE_LIST *tables); +int read_statistics_for_tables(THD *thd, TABLE_LIST *tables, + bool force_reload); int collect_statistics_for_table(THD *thd, TABLE *table); -void delete_stat_values_for_table_share(TABLE_SHARE *table_share); -int alloc_statistics_for_table(THD *thd, TABLE *table); -void free_statistics_for_table(THD *thd, TABLE *table); +int alloc_statistics_for_table(THD *thd, TABLE *table, MY_BITMAP *stat_fields); +void free_statistics_for_table(TABLE *table); int update_statistics_for_table(THD *thd, TABLE *table); -int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab); +int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, + const LEX_CSTRING *tab); int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col); int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, bool ext_prefixes_only); -int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab, - const LEX_CSTRING *new_db, const LEX_CSTRING *new_tab); -int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, - const char *new_name); +int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, + const LEX_CSTRING *tab, + const LEX_CSTRING *new_db, + const LEX_CSTRING *new_tab); +int rename_columns_in_stat_table(THD *thd, TABLE *tab, + List *fields); +int rename_indexes_in_stat_table(THD *thd, TABLE *tab, + List *indexes); void set_statistics_for_table(THD *thd, TABLE *table); double get_column_avg_frequency(Field * field); @@ -151,13 +156,16 @@ class Histogram_builder; /* Common base for all histograms */ -class Histogram_base +class Histogram_base :public Sql_alloc { public: + Histogram_base() {} + virtual ~Histogram_base()= default; + virtual bool parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, - Field *field, Histogram_type type_arg, - const char *hist_data, size_t hist_data_len)= 0; + Field *field, const char *hist_data, + size_t hist_data_len)= 0; virtual void serialize(Field *to_field)= 0; virtual Histogram_type get_type()=0; @@ -191,7 +199,6 @@ class Histogram_base double avg_sel)=0; virtual double range_selectivity(Field *field, key_range *min_endp, key_range *max_endp, double avg_sel)=0; - /* Legacy: return the size of the histogram on disk. @@ -200,19 +207,6 @@ class Histogram_base LENGTH(mysql.column_stats.histogram) directly. */ virtual uint get_size()=0; - virtual ~Histogram_base()= default; - - Histogram_base() : owner(NULL) {} - - /* - Memory management: a histogram may be (exclusively) "owned" by a particular - thread (done for histograms that are being collected). By default, a - histogram has owner==NULL and is not owned by any particular thread. - */ - THD *get_owner() { return owner; } - void set_owner(THD *thd) { owner=thd; } -private: - THD *owner; }; @@ -220,11 +214,11 @@ class Histogram_base A Height-balanced histogram that stores numeric fractions */ -class Histogram_binary : public Histogram_base +class Histogram_binary final : public Histogram_base { private: Histogram_type type; - uint8 size; /* Size of values array, in bytes */ + size_t size; /* Size of values array, in bytes */ uchar *values; uint prec_factor() @@ -241,13 +235,16 @@ class Histogram_binary : public Histogram_base } public: + Histogram_binary(Histogram_type type_arg) : type(type_arg) + {} + uint get_width() override { switch (type) { case SINGLE_PREC_HB: - return size; + return (uint) size; case DOUBLE_PREC_HB: - return size / 2; + return (uint) (size / 2); default: DBUG_ASSERT(0); } @@ -271,7 +268,7 @@ class Histogram_binary : public Histogram_base /* Find the bucket which value 'pos' falls into. */ uint find_bucket(double pos, bool first) { - uint val= (uint) (pos * prec_factor()); + size_t val= (size_t) (pos * prec_factor()); int lp= 0; int rp= get_width() - 1; int d= get_width() / 2; @@ -313,8 +310,7 @@ class Histogram_binary : public Histogram_base Histogram_type get_type() override { return type; } bool parse(MEM_ROOT *mem_root, const char*, const char*, Field*, - Histogram_type type_arg, const char *hist_data, - size_t hist_data_len) override; + const char *hist_data, size_t hist_data_len) override; void serialize(Field *to_field) override; void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, ulonglong size) override; @@ -408,7 +404,7 @@ class Basic_stats_collector Do not create directly, call Histogram->get_builder(...); */ -class Histogram_builder +class Histogram_builder: public Sql_alloc { protected: Field *column; /* table field for which the histogram is built */ @@ -429,16 +425,16 @@ class Histogram_builder }; -class Columns_statistics; +class Column_statistics; class Index_statistics; /* Statistical data on a table */ class Table_statistics { - public: my_bool cardinality_is_null; /* TRUE if the cardinality is unknown */ + uint columns; /* Number of columns in table */ ha_rows cardinality; /* Number of rows in the table */ uchar *min_max_record_buffers; /* Record buffers for min/max values */ Column_statistics *column_stats; /* Array of statistical data for columns */ @@ -446,6 +442,7 @@ class Table_statistics /* Array of records per key for index prefixes */ ulonglong *idx_avg_frequency; + uchar *histograms; /* Sequence of histograms */ }; @@ -458,7 +455,7 @@ class Table_statistics objects are allocated in alloc_statistics_for_table[_share]. */ -class Column_statistics +class Column_statistics :public Sql_alloc { private: @@ -467,6 +464,10 @@ class Column_statistics static const uint Scale_factor_avg_frequency= 100000; public: + ~Column_statistics() + { + delete histogram; + } /* Bitmap indicating what statistical characteristics are available for the column @@ -507,10 +508,8 @@ class Column_statistics ulonglong avg_frequency; public: - /* Histogram type as specified in mysql.column_stats.hist_type */ - Histogram_type histogram_type_on_disk; - Histogram_base *histogram; + bool histogram_exists; uint32 no_values_provided_bitmap() { @@ -529,6 +528,11 @@ class Column_statistics column_stat_nulls&= ~(1 << stat_field_no); } + void set_null(uint stat_field_no) + { + column_stat_nulls|= (1 << stat_field_no); + } + bool is_null(uint stat_field_no) { return MY_TEST(column_stat_nulls & (1 << stat_field_no)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3ad74302166d8..6848243f361f4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -81,11 +81,9 @@ static bool make_unique_constraint_name(THD *, LEX_CSTRING *, const char *, List *, uint *); static const char *make_unique_invisible_field_name(THD *, const char *, List *); -static int copy_data_between_tables(THD *, TABLE *,TABLE *, - List &, bool, uint, ORDER *, - ha_rows *, ha_rows *, - Alter_info::enum_enable_or_disable, - Alter_table_ctx *); +static int copy_data_between_tables(THD *, TABLE *,TABLE *, bool, uint, + ORDER *, ha_rows *, ha_rows *, + Alter_info *, Alter_table_ctx *); static int append_system_key_parts(THD *, HA_CREATE_INFO *, Key *); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, uint *, handler *, KEY **, uint *, int); @@ -2975,8 +2973,6 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, bool primary_key=0,unique_key=0; Key *key, *key2; uint tmp, key_number; - /* special marker for keys to be ignored */ - static char ignore_key[1]; /* Calculate number of key segements */ *key_count= 0; @@ -3024,17 +3020,17 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, both, is 'generated', and a generated key is a prefix of the other key. Then we do not need the generated shorter key. */ - if (key2->type != Key::FOREIGN_KEY && key2->name.str != ignore_key && + if (key2->type != Key::FOREIGN_KEY && key2->type != Key::IGNORE_KEY && is_foreign_key_prefix(key, key2)) { /* mark that the generated key should be ignored */ if (!key2->generated || (key->generated && key->columns.elements < key2->columns.elements)) - key->name.str= ignore_key; + key->type= Key::IGNORE_KEY; else { - key2->name.str= ignore_key; + key2->type= Key::IGNORE_KEY; key_parts-= key2->columns.elements; (*key_count)--; } @@ -3042,7 +3038,7 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, } } } - if (key->name.str != ignore_key) + if (key->type != Key::IGNORE_KEY) key_parts+=key->columns.elements; else (*key_count)--; @@ -3072,7 +3068,15 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, key_iterator.rewind(); while ((key=key_iterator++)) { - if (key->name.str == ignore_key || key->type == Key::FOREIGN_KEY) + if (key->type == Key::IGNORE_KEY) + { + /* The key was replaced by another key */ + if (!create_info->tmp_table() && + alter_info->add_stat_drop_index(thd, &key->name)) + DBUG_RETURN(true); + continue; + } + if (key->type == Key::FOREIGN_KEY) continue; /* Create the key name based on the first column (if not given) */ if (key->type == Key::PRIMARY) @@ -3134,12 +3138,12 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, Key_part_spec *column; is_hash_field_needed= false; - if (key->name.str == ignore_key) + if (key->type == Key::IGNORE_KEY) { /* ignore redundant keys */ do key=key_iterator++; - while (key && key->name.str == ignore_key); + while (key && key->type == Key::IGNORE_KEY); if (!key) break; } @@ -3167,6 +3171,9 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, case Key::FOREIGN_KEY: key_number--; // Skip this key continue; + case Key::IGNORE_KEY: + DBUG_ASSERT(0); + break; default: key_info->flags = HA_NOSAME; break; @@ -3370,6 +3377,8 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, key_add_part_check_null(file, key_info, sql_field, column)) DBUG_RETURN(TRUE); break; + case Key::IGNORE_KEY: + break; } if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) @@ -6652,7 +6661,9 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, if (table->s->tmp_table == NO_TMP_TABLE) { - delete_statistics_for_column(thd, table, field); + if (alter_info->drop_stat_fields.push_back(field, thd->mem_root)) + DBUG_RETURN(true); + KEY *key_info= table->key_info; for (uint i= 0; i < table->s->keys; i++, key_info++) { @@ -6664,9 +6675,10 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, { if (key_info->key_part[j].fieldnr - 1 == field->field_index) { - delete_statistics_for_index( - thd, table, key_info, - j >= key_info->user_defined_key_parts); + if (alter_info->add_stat_drop_index(key_info, + j >= key_info->user_defined_key_parts, + thd->mem_root)) + DBUG_RETURN(true); break; } } @@ -6723,13 +6735,17 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE; } - /* Check if field was renamed (case-sensitive for detecting case change) */ + /* + Check if field was renamed (case-sensitive for detecting case change) + */ if (cmp(&field->field_name, &new_field->field_name)) { field->flags|= FIELD_IS_RENAMED; ha_alter_info->handler_flags|= ALTER_COLUMN_NAME; - rename_column_in_stat_tables(thd, table, field, - new_field->field_name.str); + if (alter_info->add_stat_rename_field(field, + &new_field->field_name, + thd->mem_root)) + DBUG_RETURN(true); } /* Check that NULL behavior is same for old and new fields */ @@ -7807,6 +7823,8 @@ static bool mysql_inplace_alter_table(THD *thd, in case of crash it should use the new one and log the query to the binary log. */ + ha_alter_info->alter_info->apply_statistics_deletes_renames(thd, table); + ddl_log_update_phase(ddl_log_state, DDL_ALTER_TABLE_PHASE_INPLACE_COPIED); debug_crash_here("ddl_log_alter_after_log"); @@ -7913,6 +7931,7 @@ static bool mysql_inplace_alter_table(THD *thd, DBUG_RETURN(true); } + /** maximum possible length for certain blob types. @@ -8167,7 +8186,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, create_info->used_fields|=HA_CREATE_USED_AUTO; } if (table->s->tmp_table == NO_TMP_TABLE) - (void) delete_statistics_for_column(thd, table, field); + { + if (alter_info->drop_stat_fields.push_back(field, thd->mem_root)) + DBUG_RETURN(true); + } dropped_sys_vers_fields|= field->flags; drop_it.remove(); dropped_fields= &table->tmp_set; @@ -8179,13 +8201,19 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { vers_system_invisible= true; } - /* invisible versioning column is dropped automatically on DROP SYSTEM VERSIONING */ + /* + invisible versioning column is dropped automatically on + DROP SYSTEM VERSIONING + */ if (!drop && field->invisible >= INVISIBLE_SYSTEM && field->flags & VERS_SYSTEM_FIELD && alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING) { if (table->s->tmp_table == NO_TMP_TABLE) - (void) delete_statistics_for_column(thd, table, field); + { + if (alter_info->drop_stat_fields.push_back(field, thd->mem_root)) + DBUG_RETURN(true); + } continue; } @@ -8548,19 +8576,24 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { if (table->s->tmp_table == NO_TMP_TABLE) { - (void) delete_statistics_for_index(thd, table, key_info, FALSE); + if (alter_info->add_stat_drop_index(key_info, FALSE, thd->mem_root)) + DBUG_RETURN(true); if (primary_key) { KEY *tab_key_info= table->key_info; for (uint j=0; j < table->s->keys; j++, tab_key_info++) { - if (tab_key_info->user_defined_key_parts != + if (tab_key_info != key_info && + tab_key_info->user_defined_key_parts != tab_key_info->ext_key_parts) - (void) delete_statistics_for_index(thd, table, tab_key_info, - TRUE); - } + { + if (alter_info->add_stat_drop_index(tab_key_info, TRUE, + thd->mem_root)) + DBUG_RETURN(true); + } + } } - } + } drop_it.remove(); continue; } @@ -8597,8 +8630,15 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, goto err; } - key_name= rename_key->new_name.str; + key_name= rename_key->new_name.str; // New name of current key_info + if (cmp(&rename_key->old_name, &rename_key->new_name)) + { + /* Key was renamed */ + alter_info->add_stat_rename_index(key_info, &rename_key->new_name, + thd->mem_root); + } rename_key_it.remove(); + /* If the user has explicitly renamed the key, we should no longer treat it as generated. Otherwise this key might be automatically @@ -8709,10 +8749,17 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (table->s->tmp_table == NO_TMP_TABLE) { if (delete_index_stat) - (void) delete_statistics_for_index(thd, table, key_info, FALSE); + { + if (alter_info->add_stat_drop_index(key_info, FALSE, thd->mem_root)) + DBUG_RETURN(true); + } else if (alter_ctx->modified_primary_key && key_info->user_defined_key_parts != key_info->ext_key_parts) - (void) delete_statistics_for_index(thd, table, key_info, TRUE); + { + if (alter_info->add_stat_drop_index(key_info, FALSE, + thd->mem_root)) + DBUG_RETURN(true); + } } if (!user_keyparts && key_parts.elements) @@ -10690,6 +10737,13 @@ do_continue:; alter_info->flags|= ALTER_INDEX_ORDER; create_info->alias= alter_ctx.table_name; thd->abort_on_warning= !ignore && thd->is_strict_mode(); + + /* + This is to be able to call Alter_info::add_stat_drop_index(thd, key_name) + from mysql_prepare_create_table() + */ + alter_info->original_table= table; + /* Create the .frm file for the new table. Storage engine table will not be created at this stage. @@ -10980,6 +11034,16 @@ do_continue:; thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; + /* + Collect fields that was renamed. + We do not do that if fill_alter_inplace_info() has + already collected renamed fields. + */ + if (alter_info->flags & (ALTER_CHANGE_COLUMN | ALTER_RENAME_COLUMN) && + alter_info->rename_stat_fields.is_empty()) + if (alter_info->collect_renamed_fields(thd)) + goto err_new_table_cleanup; + /* We do not copy data for MERGE tables. Only the children have data. MERGE tables have HA_NO_COPY_ON_ALTER set. @@ -11030,10 +11094,8 @@ do_continue:; new_table->mark_columns_needed_for_insert(); thd->binlog_write_table_map(new_table, 1); } - if (copy_data_between_tables(thd, table, new_table, - alter_info->create_list, ignore, - order_num, order, &copied, &deleted, - alter_info->keys_onoff, + if (copy_data_between_tables(thd, table, new_table, ignore, order_num, + order, &copied, &deleted, alter_info, &alter_ctx)) goto err_new_table_cleanup; } @@ -11188,6 +11250,9 @@ do_continue:; if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) goto err_new_table_cleanup; + /* Now we are the only user. Update the data in EITS tables */ + alter_info->apply_statistics_deletes_renames(thd, table); + close_all_tables_for_name(thd, table->s, alter_ctx.is_table_renamed() ? HA_EXTRA_PREPARE_FOR_RENAME: @@ -11530,11 +11595,9 @@ bool mysql_trans_commit_alter_copy_data(THD *thd) static int -copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, - List &create, bool ignore, - uint order_num, ORDER *order, - ha_rows *copied, ha_rows *deleted, - Alter_info::enum_enable_or_disable keys_onoff, +copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool ignore, + uint order_num, ORDER *order, ha_rows *copied, + ha_rows *deleted, Alter_info *alter_info, Alter_table_ctx *alter_ctx) { int error= 1; @@ -11583,7 +11646,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, backup_set_alter_copy_lock(thd, from); - alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); + alter_table_manage_keys(to, from->file->indexes_are_disabled(), + alter_info->keys_onoff); from->default_column_bitmaps(); @@ -11592,12 +11656,14 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, from->file->info(HA_STATUS_VARIABLE); to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE); - to->file->ha_start_bulk_insert(from->file->stats.records, - ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT); - bulk_insert_started= 1; + if (!to->s->long_unique_table) + { + to->file->ha_start_bulk_insert(from->file->stats.records, + ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT); + bulk_insert_started= 1; + } mysql_stage_set_work_estimated(thd->m_stage_progress_psi, from->file->stats.records); - - List_iterator it(create); + List_iterator it(alter_info->create_list); Create_field *def; copy_end=copy; to->s->default_fields= 0; @@ -11858,7 +11924,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, /* We are going to drop the temporary table */ to->file->extra(HA_EXTRA_PREPARE_FOR_DROP); } - if (unlikely(to->file->ha_end_bulk_insert()) && error <= 0) + if (bulk_insert_started && to->file->ha_end_bulk_insert() && error <= 0) { /* Give error, if not already given */ if (!thd->is_error()) @@ -11900,7 +11966,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, { /* This happens if we get an error during initialization of data */ DBUG_ASSERT(error); - to->file->ha_end_bulk_insert(); ha_enable_transaction(thd, TRUE); } diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index cb1971a17466e..9c19311c6027e 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -258,7 +258,7 @@ bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl, List_item *first_elem= li++; uint cnt= first_elem->elements; - Type_holder *holders; + Type_holder *holders= type_holders; if (cnt == 0) { @@ -269,32 +269,35 @@ bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl, if (fix_fields_for_tvc(thd, li)) DBUG_RETURN(true); - if (!(holders= new (thd->stmt_arena->mem_root) Type_holder[cnt]) || - join_type_handlers_for_tvc(thd, li, holders, cnt) || - get_type_attributes_for_tvc(thd, li, holders, - lists_of_values.elements, cnt)) - DBUG_RETURN(true); - - List_iterator_fast it(*first_elem); - Item *item; - Query_arena *arena, backup; - arena=thd->activate_stmt_arena_if_needed(&backup); - - sl->item_list.empty(); - for (uint pos= 0; (item= it++); pos++) + if (!holders) { - /* Error's in 'new' will be detected after loop */ - Item_type_holder *new_holder= new (thd->mem_root) - Item_type_holder(thd, item, holders[pos].type_handler(), - &holders[pos]/*Type_all_attributes*/, - holders[pos].get_maybe_null()); - sl->item_list.push_back(new_holder); + holders= type_holders= new (thd->stmt_arena->mem_root) Type_holder[cnt]; + if (!holders || + join_type_handlers_for_tvc(thd, li, holders, cnt) || + get_type_attributes_for_tvc(thd, li, holders, + lists_of_values.elements, cnt)) + DBUG_RETURN(true); + List_iterator_fast it(*first_elem); + Item *item; + Query_arena *arena, backup; + arena=thd->activate_stmt_arena_if_needed(&backup); + + sl->item_list.empty(); + for (uint pos= 0; (item= it++); pos++) + { + /* Error's in 'new' will be detected after loop */ + Item_type_holder *new_holder= new (thd->mem_root) + Item_type_holder(thd, item, holders[pos].type_handler(), + &holders[pos]/*Type_all_attributes*/, + holders[pos].get_maybe_null()); + sl->item_list.push_back(new_holder); + } + if (arena) + thd->restore_active_arena(arena, &backup); + + if (unlikely(thd->is_fatal_error)) + DBUG_RETURN(true); // out of memory } - if (arena) - thd->restore_active_arena(arena, &backup); - - if (unlikely(thd->is_fatal_error)) - DBUG_RETURN(true); // out of memory result= tmp_result; diff --git a/sql/sql_tvc.h b/sql/sql_tvc.h index b5b8b979f43de..710557f7aa20b 100644 --- a/sql/sql_tvc.h +++ b/sql/sql_tvc.h @@ -25,6 +25,7 @@ class Explain_query; class Item_func_in; class st_select_lex_unit; typedef class st_select_lex SELECT_LEX; +class Type_holder; /** @class table_value_constr @@ -39,6 +40,7 @@ class table_value_constr : public Sql_alloc List lists_of_values; select_result *result; SELECT_LEX *select_lex; + Type_holder *type_holders; enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE} have_query_plan; @@ -47,7 +49,7 @@ class table_value_constr : public Sql_alloc table_value_constr(List tvc_values, SELECT_LEX *sl, ulonglong select_options_arg) : - lists_of_values(tvc_values), result(0), select_lex(sl), + lists_of_values(tvc_values), result(0), select_lex(sl), type_holders(0), have_query_plan(QEP_NOT_PRESENT_YET), explain(0), select_options(select_options_arg) { }; diff --git a/sql/sql_type.h b/sql/sql_type.h index b39157c370661..6c135a4073683 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -124,6 +124,40 @@ enum scalar_comparison_op }; +/* + This enum is intentionally defined as "class" to disallow its implicit + cast as "bool". This is needed to avoid pre-MDEV-32203 constructs like: + if (field->can_optimize_range(...)) + do_optimization(); + to merge automatically as such - that would change the meaning + to the opposite. The pre-MDEV-32203 code must to be changed to: + if (field->can_optimize_range(...) == Data_type_compatibility::OK) + do_optimization(); +*/ +enum class Data_type_compatibility +{ + OK, + INCOMPATIBLE_DATA_TYPE, + INCOMPATIBLE_COLLATION +}; + + +static inline const LEX_CSTRING +scalar_comparison_op_to_lex_cstring(scalar_comparison_op op) +{ + switch (op) { + case SCALAR_CMP_EQ: return LEX_CSTRING{STRING_WITH_LEN("=")}; + case SCALAR_CMP_EQUAL: return LEX_CSTRING{STRING_WITH_LEN("<=>")}; + case SCALAR_CMP_LT: return LEX_CSTRING{STRING_WITH_LEN("<")}; + case SCALAR_CMP_LE: return LEX_CSTRING{STRING_WITH_LEN("<=")}; + case SCALAR_CMP_GE: return LEX_CSTRING{STRING_WITH_LEN(">")}; + case SCALAR_CMP_GT: return LEX_CSTRING{STRING_WITH_LEN(">=")}; + } + DBUG_ASSERT(0); + return LEX_CSTRING{STRING_WITH_LEN("")}; +} + + class Hasher { ulong m_nr1; diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index 52338ec556cb3..88c24ba07762c 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -622,8 +622,9 @@ class Type_handler_fbt: public Type_handler return NULL; return new (thd->mem_root) Item_literal_fbt(thd, tmp); } - bool can_optimize_keypart_ref(const Item_bool_func *cond, - const Item *item) const override + Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) + const override { /* Mixing of two different non-traditional types is currently prevented. @@ -633,23 +634,23 @@ class Type_handler_fbt: public Type_handler is_traditional_scalar_type() || item->type_handler()->type_collection() == type_handler()->type_collection()); - return true; + return Data_type_compatibility::OK; } /** Test if Field can use range optimizer for a standard comparison operation: <=, <, =, <=>, >, >= Note, this method does not cover spatial operations. */ - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const override + Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const override { // See the DBUG_ASSERT comment in can_optimize_keypart_ref() DBUG_ASSERT(item->type_handler()->type_handler_base_or_self()-> is_traditional_scalar_type() || item->type_handler()->type_collection() == type_handler()->type_collection()); - return true; + return Data_type_compatibility::OK; } void hash_not_null(Hasher *hasher) override { @@ -660,7 +661,8 @@ class Type_handler_fbt: public Type_handler scalar_comparison_op op, Item *value) override { DBUG_ENTER("Field_fbt::get_mm_leaf"); - if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + if (can_optimize_scalar_range(prm, key_part, cond, op, value) != + Data_type_compatibility::OK) DBUG_RETURN(0); int err= value->save_in_field_no_warnings(this, 1); if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) @@ -673,15 +675,17 @@ class Type_handler_fbt: public Type_handler } DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); } - bool can_optimize_hash_join(const Item_bool_func *cond, - const Item *item) const override + Data_type_compatibility can_optimize_hash_join(const Item_bool_func *cond, + const Item *item) + const override { return can_optimize_keypart_ref(cond, item); } - bool can_optimize_group_min_max(const Item_bool_func *cond, + Data_type_compatibility can_optimize_group_min_max( + const Item_bool_func *cond, const Item *const_item) const override { - return true; + return Data_type_compatibility::OK; } uint row_pack_length() const override { return pack_length(); } diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc index 1bdcc34422ccb..b026b5e9479b0 100644 --- a/sql/sql_type_geom.cc +++ b/sql/sql_type_geom.cc @@ -918,11 +918,14 @@ bool Field_geom::is_equal(const Column_definition &new_field) const } -bool Field_geom::can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const -{ - return item->cmp_type() == STRING_RESULT; +Data_type_compatibility +Field_geom::can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const +{ + return item->cmp_type() == STRING_RESULT ? + Data_type_compatibility::OK : + Data_type_compatibility::INCOMPATIBLE_DATA_TYPE; } diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index 735e4605be11e..d86d118118770 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -376,9 +376,9 @@ class Field_geom :public Field_blob if (tmp.length) to->set_data_type_name(tmp); } - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const override; + Data_type_compatibility can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const override; void sql_type(String &str) const override; Copy_func *get_copy_func(const Field *from) const override { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8ba993d023ce6..9d1151d41e6fe 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3980,7 +3980,7 @@ static Sys_var_set Sys_tls_version( "TLS protocol version for secure connections.", READ_ONLY GLOBAL_VAR(tls_version), CMD_LINE(REQUIRED_ARG), tls_version_names, - DEFAULT(VIO_TLSv1_1 | VIO_TLSv1_2 | VIO_TLSv1_3)); + DEFAULT(VIO_TLSv1_2 | VIO_TLSv1_3)); static Sys_var_mybool Sys_standard_compliant_cte( "standard_compliant_cte", @@ -4697,10 +4697,13 @@ static Sys_var_bit Sys_sql_warnings( DEFAULT(FALSE)); static Sys_var_bit Sys_sql_notes( - "sql_notes", "If set to 1, the default, warning_count is incremented each " - "time a Note warning is encountered. If set to 0, Note warnings are not " - "recorded. mysqldump has outputs to set this variable to 0 so that no " - "unnecessary increments occur when data is reloaded.", + "sql_notes", + "If set to 1, the default, warning_count is incremented " + "each time a Note warning is encountered. If set to 0, Note warnings " + "are not recorded. mysqldump has outputs to set this variable to 0 so " + "that no unnecessary increments occur when data is reloaded. " + "See also note_verbosity, which allows one to define with notes are " + "sent.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_SQL_NOTES, DEFAULT(TRUE)); @@ -6537,7 +6540,7 @@ static const char *log_slow_filter_names[]= static Sys_var_set Sys_log_slow_filter( "log_slow_filter", - "Log only certain types of queries to the slow log. If variable empty alll kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled", + "Log only certain types of queries to the slow log. If variable empty all kind of queries are logged. All types are bound by slow_query_time, except 'not_using_index' which is always logged if enabled", SESSION_VAR(log_slow_filter), CMD_LINE(REQUIRED_ARG), log_slow_filter_names, /* by default we log all queries except 'not_using_index' */ @@ -6629,8 +6632,12 @@ static Sys_var_ulong Sys_log_slow_rate_limit( SESSION_VAR(log_slow_rate_limit), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, UINT_MAX), DEFAULT(1), BLOCK_SIZE(1)); +/* + Full is not needed below anymore as one can set all bits with '= ALL', but + we need it for compatiblity with earlier versions. +*/ static const char *log_slow_verbosity_names[]= -{ "innodb", "query_plan", "explain", "engine", "full", 0}; +{ "innodb", "query_plan", "explain", "engine", "warnings", "full", 0}; static Sys_var_set Sys_log_slow_verbosity( "log_slow_verbosity", @@ -6638,6 +6645,23 @@ static Sys_var_set Sys_log_slow_verbosity( SESSION_VAR(log_slow_verbosity), CMD_LINE(REQUIRED_ARG), log_slow_verbosity_names, DEFAULT(LOG_SLOW_VERBOSITY_INIT)); +static Sys_var_ulong Sys_log_slow_max_warnings( + "log_slow_max_warnings", + "Max numbers of warnings printed to slow query log per statement", + SESSION_VAR(log_slow_max_warnings), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1000), DEFAULT(10), BLOCK_SIZE(1)); + +static const char *note_verbosity_names[]= +{ "basic", "unusable_keys", "explain", 0}; + +static Sys_var_set Sys_note_verbosity( + "note_verbosity", + "Verbosity level for note-warnings given to the user. " + "See also @@sql_notes.", + SESSION_VAR(note_verbosity), CMD_LINE(REQUIRED_ARG), + note_verbosity_names, DEFAULT(NOTE_VERBOSITY_NORMAL | + NOTE_VERBOSITY_EXPLAIN)); + static Sys_var_ulong Sys_join_cache_level( "join_cache_level", "Controls what join operations can be executed with join buffers. Odd " @@ -7030,8 +7054,15 @@ static Sys_var_ulong Sys_optimizer_max_sel_arg_weight( "optimizer_max_sel_arg_weight", "The maximum weight of the SEL_ARG graph. Set to 0 for no limit", SESSION_VAR(optimizer_max_sel_arg_weight), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, ULONG_MAX), DEFAULT(SEL_ARG::MAX_WEIGHT), BLOCK_SIZE(1)); - + VALID_RANGE(0, UINT_MAX), DEFAULT(SEL_ARG::MAX_WEIGHT), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_optimizer_max_sel_args( + "optimizer_max_sel_args", + "The maximum number of SEL_ARG objects created when optimizing a range. " + "If more objects would be needed, the range will not be used by the " + "optimizer.", + SESSION_VAR(optimizer_max_sel_args), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(SEL_ARG::DEFAULT_MAX_SEL_ARGS), BLOCK_SIZE(1)); static Sys_var_engine_optimizer_cost Sys_optimizer_disk_read_ratio( "optimizer_disk_read_ratio", diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl index a07a1db163e98..a988c3a492b91 100644 --- a/sql/sys_vars.inl +++ b/sql/sys_vars.inl @@ -1524,6 +1524,10 @@ public: Backing store: ulonglong */ + +static const LEX_CSTRING all_clex_str= {STRING_WITH_LEN("all")}; + + class Sys_var_set: public Sys_var_typelib { public: @@ -1583,6 +1587,12 @@ public: var->save_result.ulonglong_value= find_set(&typelib, res->ptr(), res->length(), NULL, &error, &error_len, ¬_used); + if (error_len && + !my_charset_latin1.strnncollsp(res->to_lex_cstring(), all_clex_str)) + { + var->save_result.ulonglong_value= ((1ULL << (typelib.count)) -1); + error_len= 0; + } /* note, we only issue an error if error_len > 0. That is even while empty (zero-length) values are considered diff --git a/sql/table.cc b/sql/table.cc index b50dc2b12191c..5392c5d7d1080 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -378,14 +378,13 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, table_alias_charset->strnncoll(key, 6, "mysql", 6) == 0) share->not_usable_by_query_cache= 1; - init_sql_alloc(PSI_INSTRUMENT_ME, &share->stats_cb.mem_root, - TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); - memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); mysql_mutex_init(key_TABLE_SHARE_LOCK_share, &share->LOCK_share, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, &share->LOCK_ha_data, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_TABLE_SHARE_LOCK_statistics, + &share->LOCK_statistics, MY_MUTEX_INIT_SLOW); DBUG_EXECUTE_IF("simulate_big_table_id", if (last_table_id < UINT_MAX32) @@ -486,15 +485,19 @@ void TABLE_SHARE::destroy() ha_share= NULL; // Safety } - delete_stat_values_for_table_share(this); + if (stats_cb) + { + stats_cb->usage_count--; + delete stats_cb; + } delete sequence; - free_root(&stats_cb.mem_root, MYF(0)); /* The mutexes are initialized only for shares that are part of the TDC */ if (tmp_table == NO_TMP_TABLE) { mysql_mutex_destroy(&LOCK_share); mysql_mutex_destroy(&LOCK_ha_data); + mysql_mutex_destroy(&LOCK_statistics); } my_hash_free(&name_hash); @@ -4658,6 +4661,88 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } +/** + Free engine stats + + This is only called from closefrm() when the TABLE object is destroyed +**/ + +void TABLE::free_engine_stats() +{ + bool free_stats= 0; + TABLE_STATISTICS_CB *stats= stats_cb; + mysql_mutex_lock(&s->LOCK_share); + free_stats= --stats->usage_count == 0; + mysql_mutex_unlock(&s->LOCK_share); + if (free_stats) + delete stats; +} + + +/* + Use engine stats from table_share if table_share has been updated +*/ + +void TABLE::update_engine_independent_stats() +{ + bool free_stats= 0; + TABLE_STATISTICS_CB *org_stats= stats_cb; + DBUG_ASSERT(stats_cb != s->stats_cb); + + if (stats_cb != s->stats_cb) + { + mysql_mutex_lock(&s->LOCK_share); + if (org_stats) + free_stats= --org_stats->usage_count == 0; + if ((stats_cb= s->stats_cb)) + stats_cb->usage_count++; + mysql_mutex_unlock(&s->LOCK_share); + if (free_stats) + delete org_stats; + } +} + + +/* + Update engine stats in table share to use new stats +*/ + +void +TABLE_SHARE::update_engine_independent_stats(TABLE_STATISTICS_CB *new_stats) +{ + TABLE_STATISTICS_CB *free_stats= 0; + DBUG_ASSERT(new_stats->usage_count == 0); + + mysql_mutex_lock(&LOCK_share); + if (stats_cb) + { + if (!--stats_cb->usage_count) + free_stats= stats_cb; + } + stats_cb= new_stats; + new_stats->usage_count++; + mysql_mutex_unlock(&LOCK_share); + if (free_stats) + delete free_stats; +} + + +/* Check if we have statistics for histograms */ + +bool TABLE_SHARE::histograms_exists() +{ + bool res= 0; + if (stats_cb) + { + mysql_mutex_lock(&LOCK_share); + if (stats_cb) + res= stats_cb->histograms_exists(); + mysql_mutex_unlock(&LOCK_share); + } + return res; +} + + /* Free information allocated by openfrm @@ -4696,6 +4781,12 @@ int closefrm(TABLE *table) table->part_info= 0; } #endif + if (table->stats_cb) + { + DBUG_ASSERT(table->s->tmp_table == NO_TMP_TABLE); + table->free_engine_stats(); + } + free_root(&table->mem_root, MYF(0)); DBUG_RETURN(error); } diff --git a/sql/table.h b/sql/table.h index 149e477270f2b..93ff20d789603 100644 --- a/sql/table.h +++ b/sql/table.h @@ -635,99 +635,55 @@ enum open_frm_error { from persistent statistical tables */ -class TABLE_STATISTICS_CB -{ - class Statistics_state - { - enum state_codes - { - EMPTY, /** data is not loaded */ - LOADING, /** data is being loaded in some connection */ - READY /** data is loaded and available for use */ - }; - int32 state; - - public: - /** No state copy */ - Statistics_state &operator=(const Statistics_state &) { return *this; } - - /** Checks if data loading have been completed */ - bool is_ready() const - { - return my_atomic_load32_explicit(const_cast(&state), - MY_MEMORY_ORDER_ACQUIRE) == READY; - } - /** - Sets mutual exclusion for data loading +#define TABLE_STAT_NO_STATS 0 +#define TABLE_STAT_TABLE 1 +#define TABLE_STAT_COLUMN 2 +#define TABLE_STAT_INDEX 4 +#define TABLE_STAT_HISTOGRAM 8 - If stats are in LOADING state, waits until state change. +/* + EITS statistics information for a table. - @return - @retval true atomic EMPTY -> LOADING transfer completed, ok to load - @retval false stats are in READY state, no need to load - */ - bool start_load() - { - for (;;) - { - int32 expected= EMPTY; - if (my_atomic_cas32_weak_explicit(&state, &expected, LOADING, - MY_MEMORY_ORDER_RELAXED, - MY_MEMORY_ORDER_RELAXED)) - return true; - if (expected == READY) - return false; - (void) LF_BACKOFF(); - } - } + This data is loaded from mysql.{table|index|column}_stats tables and + then most of the time is owned by table's TABLE_SHARE object. - /** Marks data available for subsequent use */ - void end_load() - { - DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) == - LOADING); - my_atomic_store32_explicit(&state, READY, MY_MEMORY_ORDER_RELEASE); - } + Individual TABLE objects also have pointer to this object, and we do + reference counting to know when to free it. See + TABLE::update_engine_stats(), TABLE::free_engine_stats(), + TABLE_SHARE::update_engine_stats(), TABLE_SHARE::destroy(). + These implement a "shared pointer"-like functionality. - /** Restores empty state on error (e.g. OOM) */ - void abort_load() - { - DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) == - LOADING); - my_atomic_store32_explicit(&state, EMPTY, MY_MEMORY_ORDER_RELAXED); - } - }; + When new statistics is loaded, we create new TABLE_STATISTICS_CB and make + the TABLE_SHARE point to it. Some TABLE object may still be using older + TABLE_STATISTICS_CB objects. Reference counting allows to free + TABLE_STATISTICS_CB when it is no longer used. +*/ - class Statistics_state stats_state; - class Statistics_state hist_state; +class TABLE_STATISTICS_CB +{ + uint usage_count; // Instances of this stat public: + TABLE_STATISTICS_CB(); + ~TABLE_STATISTICS_CB(); MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */ Table_statistics *table_stats; /* Structure to access the statistical data */ + uint stats_available; + bool histograms_exists_on_disk; - /* - Whether the table has histograms. - (If the table has none, histograms_are_ready() can finish sooner) - */ - bool have_histograms; - - bool histograms_are_ready() const + bool histograms_exists() const { - return !have_histograms || hist_state.is_ready(); + return histograms_exists_on_disk; } - - bool start_histograms_load() + bool unused() { - return have_histograms && hist_state.start_load(); + return usage_count == 0; } - - void end_histograms_load() { hist_state.end_load(); } - void abort_histograms_load() { hist_state.abort_load(); } - bool stats_are_ready() const { return stats_state.is_ready(); } - bool start_stats_load() { return stats_state.start_load(); } - void end_stats_load() { stats_state.end_load(); } - void abort_stats_load() { stats_state.abort_load(); } + /* Copy (latest) state from TABLE_SHARE to TABLE */ + void update_stats_in_table(TABLE *table); + friend struct TABLE; + friend struct TABLE_SHARE; }; /** @@ -750,6 +706,7 @@ struct TABLE_SHARE TYPELIB *intervals; /* pointer to interval info */ mysql_mutex_t LOCK_ha_data; /* To protect access to ha_data */ mysql_mutex_t LOCK_share; /* To protect TABLE_SHARE */ + mysql_mutex_t LOCK_statistics; /* To protect against concurrent load */ TDC_element *tdc; @@ -766,7 +723,17 @@ struct TABLE_SHARE uint *blob_field; /* Index to blobs in Field arrray*/ LEX_CUSTRING vcol_defs; /* definitions of generated columns */ - TABLE_STATISTICS_CB stats_cb; + /* + EITS statistics data from the last time the table was opened or ANALYZE + table was run. + This is typically same as any related TABLE::stats_cb until ANALYZE + table is run. + This pointer is only to be de-referenced under LOCK_share as the + pointer can change by another thread running ANALYZE TABLE. + Without using a LOCK_share one can check if the statistics has been + updated by checking if TABLE::stats_cb != TABLE_SHARE::stats_cb. + */ + TABLE_STATISTICS_CB *stats_cb; uchar *default_values; /* row with default values */ LEX_CSTRING comment; /* Comment about table */ @@ -1210,7 +1177,6 @@ struct TABLE_SHARE void set_overlapped_keys(); void set_ignored_indexes(); key_map usable_indexes(THD *thd); - bool old_long_hash_function() const { return mysql_version < 100428 || @@ -1225,8 +1191,9 @@ struct TABLE_SHARE Item_func_hash *make_long_hash_func(THD *thd, MEM_ROOT *mem_root, List *field_list) const; - void update_optimizer_costs(handlerton *hton); + void update_engine_independent_stats(TABLE_STATISTICS_CB *stat); + bool histograms_exists(); }; /* not NULL, but cannot be dereferenced */ @@ -1623,6 +1590,7 @@ struct TABLE and can be useful for range optimizer. */ Item *notnull_cond; + TABLE_STATISTICS_CB *stats_cb; inline void reset() { bzero((void*)this, sizeof(*this)); } void init(THD *thd, TABLE_LIST *tl); @@ -1652,6 +1620,8 @@ struct TABLE void mark_columns_used_by_virtual_fields(void); void mark_check_constraint_columns_for_read(void); int verify_constraints(bool ignore_failure); + void free_engine_stats(); + void update_engine_independent_stats(); inline void column_bitmaps_set(MY_BITMAP *read_set_arg) { read_set= read_set_arg; diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 789d0c87e02ea..0039c96a00186 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -57,6 +57,7 @@ ulong tdc_size; /**< Table definition cache threshold for LRU eviction. */ ulong tc_size; /**< Table cache threshold for LRU eviction. */ uint32 tc_instances; +static size_t tc_allocated_size; static std::atomic tc_active_instances(1); static std::atomic tc_contention_warning_reported; @@ -150,6 +151,10 @@ struct Table_cache_instance static void *operator new[](size_t size) { return aligned_malloc(size, CPU_LEVEL1_DCACHE_LINESIZE); } static void operator delete[](void *ptr) { aligned_free(ptr); } + static void mark_memory_freed() + { + update_malloc_size(-(longlong) tc_allocated_size, 0); + } /** Lock table cache mutex and check contention. @@ -601,6 +606,8 @@ bool tdc_init(void) /* Extra instance is allocated to avoid false sharing */ if (!(tc= new Table_cache_instance[tc_instances + 1])) DBUG_RETURN(true); + tc_allocated_size= (tc_instances + 1) * sizeof *tc; + update_malloc_size(tc_allocated_size, 0); tdc_inited= true; mysql_mutex_init(key_LOCK_unused_shares, &LOCK_unused_shares, MY_MUTEX_INIT_FAST); @@ -654,7 +661,12 @@ void tdc_deinit(void) tdc_inited= false; lf_hash_destroy(&tdc_hash); mysql_mutex_destroy(&LOCK_unused_shares); - delete [] tc; + if (tc) + { + tc->mark_memory_freed(); + delete [] tc; + tc= 0; + } } DBUG_VOID_RETURN; } diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 78f9eaf8792f1..10b7db4eb7ed6 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -199,7 +199,6 @@ static void thread_attach(THD* thd) DBUG_ASSERT(thd->mysys_var == my_thread_var); thd->mysys_var->stack_ends_here= thd->thread_stack + tinfo->stack_size; PSI_CALL_set_thread(thd->get_psi()); - mysql_socket_set_thread_owner(thd->net.vio->mysql_socket); } /* @@ -313,6 +312,7 @@ static THD *threadpool_add_connection(CONNECT *connect, TP_connection *c) /* Login. */ thread_attach(thd); + mysql_socket_set_thread_owner(thd->net.vio->mysql_socket); re_init_net_server_extension(thd); ulonglong now= microsecond_interval_timer(); thd->prior_thr_create_utime= now; diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index 5e1fa137fedb8..84392facba326 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -198,7 +198,7 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) to alloc and pass as an argument to snprintf. */ - char *filename= (char *)malloc(len+1); + char *filename= (char *) my_malloc(key_memory_WSREP, len+1, 0); int len1= snprintf(filename, len+1, "%s/GRA_%lld_%lld.log", wsrep_data_home_dir, (longlong) thd->thread_id, (long long)wsrep_thd_trx_seqno(thd)); @@ -206,7 +206,7 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) if (len > len1) { WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len); - free(filename); + my_free(filename); return; } @@ -225,7 +225,7 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) WSREP_ERROR("Failed to open file '%s': %d (%s)", filename, errno, strerror(errno)); } - free(filename); + my_free(filename); } /* Dump replication buffer along with header to a file. */ @@ -248,7 +248,7 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, to alloc and pass as an argument to snprintf. */ char *filename; - if (len < 0 || !(filename= (char*)malloc(len+1))) + if (len < 0 || !(filename= (char*) my_malloc(key_memory_WSREP, len+1, 0))) { WSREP_ERROR("snprintf error: %d, skipping dump.", len); DBUG_VOID_RETURN; @@ -261,7 +261,7 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, if (len > len1) { WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len); - free(filename); + my_free(filename); DBUG_VOID_RETURN; } @@ -301,7 +301,7 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, end_io_cache(&cache); cleanup1: - free(filename); + my_free(filename); mysql_file_close(file, MYF(MY_WME)); if (!thd->wsrep_applier) delete ev; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9fb0e2fe0f2c9..7c74cb894b18a 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -859,6 +859,7 @@ void wsrep_deinit_server() wsrep_deinit_schema(); Wsrep_server_state::destroy(); Wsrep_status::destroy(); + wsrep_free_status_vars(); } int wsrep_init() diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index 8446f11a34f4e..6cf4fc4c1a2fc 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -22,8 +22,16 @@ void wsrep_notify_status(enum wsrep::server_state::state status, const wsrep::view* view) { + Wsrep_status::report_state(status); + if (!view) + { + WSREP_DEBUG("wsrep_notify_status server not yet ready : wsrep_ready=%d status %d", + wsrep_ready, (int)status); + return; + } + if (!wsrep_notify_cmd || 0 == strlen(wsrep_notify_cmd)) { WSREP_INFO("wsrep_notify_cmd is not defined, skipping notification."); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index b11a828ae7174..33f2088c26025 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1737,9 +1737,9 @@ static int sst_flush_tables(THD* thd) const char base_name[]= "tables_flushed"; ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; - char *real_name= (char*) malloc(full_len); + char *real_name= (char*) my_malloc(key_memory_WSREP, full_len, 0); sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); - char *tmp_name= (char*) malloc(full_len + 4); + char *tmp_name= (char*) my_malloc(key_memory_WSREP, full_len + 4, 0); sprintf(tmp_name, "%s.tmp", real_name); FILE* file= fopen(tmp_name, "w+"); @@ -1767,8 +1767,8 @@ static int sst_flush_tables(THD* thd) tmp_name, real_name, err,strerror(err)); } } - free(real_name); - free(tmp_name); + my_free(real_name); + my_free(tmp_name); if (err) ha_disable_internal_writes(false); } diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 854c11c1eea71..0e4e263805a91 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -96,14 +96,16 @@ namespace wsp bool env::ctor_common(char** e) { - env_= static_cast(malloc((len_ + 1) * sizeof(char*))); + env_= static_cast(my_malloc(key_memory_WSREP, + (len_ + 1) * sizeof(char*), + 0)); if (env_) { for (size_t i(0); i < len_; ++i) { assert(e[i]); // caller should make sure about len_ - env_[i]= strdup(e[i]); + env_[i]= my_strdup(key_memory_WSREP, e[i], MYF(0)); if (!env_[i]) { errno_= errno; @@ -129,8 +131,8 @@ env::dtor() if (env_) { /* don't need to go beyond the first NULL */ - for (size_t i(0); env_[i] != NULL; ++i) { free(env_[i]); } - free(env_); + for (size_t i(0); env_[i] != NULL; ++i) { my_free(env_[i]); } + my_free(env_); env_= NULL; } len_= 0; @@ -157,12 +159,13 @@ env::~env() { dtor(); } int env::append(const char* val) { - char** tmp= static_cast(realloc(env_, (len_ + 2)*sizeof(char*))); - + char** tmp= static_cast(my_realloc(key_memory_WSREP, + env_, (len_ + 2)*sizeof(char*), + 0)); if (tmp) { env_= tmp; - env_[len_]= strdup(val); + env_[len_]= my_strdup(key_memory_WSREP, val, 0); if (env_[len_]) { diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index c5959b8174b45..a1629b03e80c9 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -210,7 +210,11 @@ class Config_state void set(enum wsrep::server_state::state status) { - wsrep_notify_status(status); + if (status == wsrep::server_state::s_donor || + status == wsrep::server_state::s_synced) + wsrep_notify_status(status, &view_); + else + wsrep_notify_status(status); lock(); status_= status; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3343fcd2445f2..6862db42375f4 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -1079,8 +1079,10 @@ static void export_wsrep_status_to_mysql(THD* thd) #if DYNAMIC if (wsrep_status_len != mysql_status_len) { - void* tmp= realloc (mysql_status_vars, - (wsrep_status_len + 1) * sizeof(SHOW_VAR)); + void* tmp= my_realloc(key_memory_WSREP, + mysql_status_vars, + (wsrep_status_len + 1) * sizeof(SHOW_VAR), + MYF(MY_ALLOW_ZERO_PTR)); if (!tmp) { sql_print_error ("Out of memory for wsrep status variables." @@ -1132,6 +1134,15 @@ void wsrep_free_status (THD* thd) thd->wsrep_status_vars.clear(); } +void wsrep_free_status_vars() +{ +#if DYNAMIC + my_free(mysql_status_vars); + mysql_status_vars= NULL; + mysql_status_len= 0; +#endif +} + bool wsrep_gtid_domain_id_update(sys_var* self, THD *thd, enum_var_type) { WSREP_DEBUG("wsrep_gtid_domain_id_update: %llu", diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 3bebae7fb7992..94fbcfb39ee1e 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -37,6 +37,7 @@ class THD; int wsrep_init_vars(); void wsrep_set_wsrep_on(THD *thd); +void wsrep_free_status_vars(); bool wsrep_refresh_provider_options(); #define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) diff --git a/sql/xa.cc b/sql/xa.cc index 234d2a6dcccef..49be7fb5347cd 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -1141,6 +1141,11 @@ static bool slave_applier_reset_xa_trans(THD *thd) ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); + if (thd->variables.pseudo_slave_mode && + !thd->transaction->all.is_trx_read_write()) + { + thd->transaction->xid_state.set_error(ER_XA_RBROLLBACK); + } thd->transaction->xid_state.xid_cache_element->acquired_to_recovered(); thd->transaction->xid_state.xid_cache_element= 0; diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 5c4f17acc27a1..e2f9069498950 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -643,7 +643,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) { char c; int rc; - int len; + int len= 0; MODE mode = Tdbp->GetMode(); Buflen = Blksize; diff --git a/storage/connect/mysql-test/connect/r/zip.result b/storage/connect/mysql-test/connect/r/zip.result index c696252ca436c..3505add9adde6 100644 --- a/storage/connect/mysql-test/connect/r/zip.result +++ b/storage/connect/mysql-test/connect/r/zip.result @@ -70,10 +70,10 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newdos.zip'; -SELECT * FROM t4; -fn cmpsize uncsize method -new1.dos 67 79 8 -new2.dos 77 112 8 +SELECT fn, uncsize, method FROM t4; +fn uncsize method +new1.dos 79 8 +new2.dos 112 8 DROP TABLE t1,t2,t3,t4; # # Testing zipped CSV tables @@ -161,10 +161,10 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newcsv.zip'; -SELECT * FROM t4; -fn cmpsize uncsize method -new1.csv 79 83 8 -new2.csv 94 125 8 +SELECT fn,uncsize,method FROM t4; +fn uncsize method +new1.csv 83 8 +new2.csv 125 8 DROP TABLE t1,t2,t3,t4; # # Testing zipped JSON tables @@ -234,7 +234,7 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='bios.zip'; -SELECT * FROM t4; -fn cmpsize uncsize method -bios.json 1096 6848 8 +SELECT fn,uncsize,method FROM t4; +fn uncsize method +bios.json 6848 8 DROP TABLE t1,t2,t3,t4; diff --git a/storage/connect/mysql-test/connect/t/zip.test b/storage/connect/mysql-test/connect/t/zip.test index 1f0a4eedee961..abef98498a099 100644 --- a/storage/connect/mysql-test/connect/t/zip.test +++ b/storage/connect/mysql-test/connect/t/zip.test @@ -35,7 +35,7 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newdos.zip'; -SELECT * FROM t4; +SELECT fn, uncsize, method FROM t4; DROP TABLE t1,t2,t3,t4; --echo # @@ -75,7 +75,7 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newcsv.zip'; -SELECT * FROM t4; +SELECT fn,uncsize,method FROM t4; DROP TABLE t1,t2,t3,t4; --echo # @@ -123,7 +123,7 @@ cmpsize BIGINT NOT NULL FLAG=1, uncsize BIGINT NOT NULL FLAG=2, method INT NOT NULL FLAG=3) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='bios.zip'; -SELECT * FROM t4; +SELECT fn,uncsize,method FROM t4; DROP TABLE t1,t2,t3,t4; # @@ -133,4 +133,3 @@ DROP TABLE t1,t2,t3,t4; --remove_file $MYSQLD_DATADIR/test/newcsv.zip --remove_file $MYSQLD_DATADIR/test/bios.zip --remove_file $MYSQLD_DATADIR/test/bios.json - diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index c64fe95c71b59..ee9f128e6c9b9 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -495,8 +495,9 @@ IF(MSVC) # on generated file. TARGET_COMPILE_OPTIONS(innobase PRIVATE "/wd4065") ENDIF() -IF(CMAKE_C_COMPILER_ID MATCHES "Clang" AND - NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.0.0") + +MY_CHECK_CXX_COMPILER_FLAG(-Wno-unused-but-set-variable) +IF(have_CXX__Wno_unused_but_set_variable) ADD_COMPILE_FLAGS(pars/pars0grm.cc fts/fts0pars.cc COMPILE_FLAGS "-Wno-unused-but-set-variable") ENDIF() diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 14adc575a1cbc..b483e8657b009 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1,16 +1,9 @@ /***************************************************************************** Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. Copyright (c) 2015, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. @@ -51,6 +44,7 @@ Created 10/16/1994 Heikki Tuuri #include "rem0rec.h" #include "rem0cmp.h" #include "buf0lru.h" +#include "buf0rea.h" #include "btr0btr.h" #include "btr0sea.h" #include "row0log.h" diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index c88db8477ea58..a510766db5c45 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2017, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index f12fe1807ebad..0cb2a397902f5 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1995, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2013, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. @@ -34,19 +27,21 @@ Created 11/5/1995 Heikki Tuuri #include "assume_aligned.h" #include "mtr0types.h" #include "mach0data.h" -#include "buf0buf.h" #include "buf0checksum.h" #include "mariadb_stats.h" #include #ifdef UNIV_INNOCHECKSUM -#include "my_sys.h" +# include "my_sys.h" +# include "buf0buf.h" #else #include "my_cpu.h" #include "mem0mem.h" #include "btr0btr.h" #include "fil0fil.h" #include "fil0crypt.h" +#include "buf0rea.h" +#include "buf0flu.h" #include "buf0buddy.h" #include "buf0dblwr.h" #include "lock0lock.h" diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 510ad02256df6..6d84ff7a242ba 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -25,7 +25,7 @@ Created 2011/12/19 *******************************************************/ #include "buf0dblwr.h" -#include "buf0buf.h" +#include "buf0flu.h" #include "buf0checksum.h" #include "srv0start.h" #include "srv0srv.h" diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index bb705ec56516c..957632db94052 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -31,7 +31,7 @@ Created April 08, 2011 Vasil Dimov #include "mysql/psi/mysql_stage.h" #include "mysql/psi/psi.h" -#include "buf0buf.h" +#include "buf0rea.h" #include "buf0dump.h" #include "dict0dict.h" #include "os0file.h" @@ -698,7 +698,9 @@ static void buf_dump_load_func(void *) #ifdef WITH_WSREP if (!get_wsrep_recovery()) { #endif /* WITH_WSREP */ + srv_thread_pool->set_concurrency(srv_n_read_io_threads); buf_load(); + srv_thread_pool->set_concurrency(); #ifdef WITH_WSREP } #endif /* WITH_WSREP */ diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 625b1b5e28043..ddfd7403cc721 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -318,6 +318,13 @@ inline void buf_pool_t::n_flush_dec() mysql_mutex_unlock(&flush_list_mutex); } +inline void buf_pool_t::n_flush_dec_holding_mutex() +{ + mysql_mutex_assert_owner(&flush_list_mutex); + ut_ad(page_cleaner_status >= LRU_FLUSH); + page_cleaner_status-= LRU_FLUSH; +} + /** Complete write of a file page from buf_pool. @param request write request @param error whether the write may have failed */ @@ -1037,6 +1044,8 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, bool contiguous, bool evict, ulint n_flushed, ulint n_to_flush) { + mysql_mutex_unlock(&buf_pool.mutex); + ut_ad(space->id == page_id.space()); ut_ad(bpage->id() == page_id); @@ -1297,24 +1306,22 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, continue; } - if (neighbors && space->is_rotational()) - { - mysql_mutex_unlock(&buf_pool.mutex); - n->flushed+= buf_flush_try_neighbors(space, page_id, bpage, - neighbors == 1, - do_evict, n->flushed, max); - goto reacquire_mutex; - } - else if (n->flushed >= max && !recv_recovery_is_on()) + if (n->flushed >= max && !recv_recovery_is_on()) { bpage->lock.u_unlock(true); break; } + + if (neighbors && space->is_rotational()) + n->flushed+= buf_flush_try_neighbors(space, page_id, bpage, + neighbors == 1, + do_evict, n->flushed, max); else if (bpage->flush(do_evict, space)) - { ++n->flushed; - goto reacquire_mutex; - } + else + continue; + + goto reacquire_mutex; } else /* Can't evict or dispatch this block. Go to previous. */ @@ -1452,19 +1459,18 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) else { mysql_mutex_unlock(&buf_pool.flush_list_mutex); - if (neighbors && space->is_rotational()) + do { - mysql_mutex_unlock(&buf_pool.mutex); - count+= buf_flush_try_neighbors(space, page_id, bpage, neighbors == 1, - false, count, max_n); - reacquire_mutex: + if (neighbors && space->is_rotational()) + count+= buf_flush_try_neighbors(space, page_id, bpage, + neighbors == 1, false, count, max_n); + else if (bpage->flush(false, space)) + ++count; + else + continue; mysql_mutex_lock(&buf_pool.mutex); } - else if (bpage->flush(false, space)) - { - ++count; - goto reacquire_mutex; - } + while (0); } mysql_mutex_lock(&buf_pool.flush_list_mutex); @@ -1683,8 +1689,7 @@ The caller must invoke buf_dblwr.flush_buffered_writes() after releasing buf_pool.mutex. @param max_n wished maximum mumber of blocks flushed @param evict whether to evict pages after flushing -@return evict ? number of processed pages : number of pages written -@retval 0 if a buf_pool.LRU batch is already running */ +@return evict ? number of processed pages : number of pages written */ ulint buf_flush_LRU(ulint max_n, bool evict) { mysql_mutex_assert_owner(&buf_pool.mutex); @@ -1968,7 +1973,9 @@ static void buf_flush_wait(lsn_t lsn) { ut_ad(lsn <= log_sys.get_lsn()); - while (buf_pool.get_oldest_modification(lsn) < lsn) + lsn_t oldest_lsn; + + while ((oldest_lsn= buf_pool.get_oldest_modification(lsn)) < lsn) { if (buf_flush_sync_lsn < lsn) { @@ -1977,13 +1984,20 @@ static void buf_flush_wait(lsn_t lsn) pthread_cond_signal(&buf_pool.do_flush_list); my_cond_wait(&buf_pool.done_flush_list, &buf_pool.flush_list_mutex.m_mutex); - if (buf_pool.get_oldest_modification(lsn) >= lsn) + oldest_lsn= buf_pool.get_oldest_modification(lsn); + if (oldest_lsn >= lsn) break; } mysql_mutex_unlock(&buf_pool.flush_list_mutex); os_aio_wait_until_no_pending_writes(false); mysql_mutex_lock(&buf_pool.flush_list_mutex); } + + if (oldest_lsn >= buf_flush_sync_lsn) + { + buf_flush_sync_lsn= 0; + pthread_cond_broadcast(&buf_pool.done_flush_list); + } } /** Wait until all persistent pages are flushed up to a limit. @@ -2366,24 +2380,20 @@ static void buf_flush_page_cleaner() set_timespec(abstime, 1); lsn_limit= buf_flush_sync_lsn; - const lsn_t oldest_lsn= buf_pool.get_oldest_modification(0); + lsn_t oldest_lsn= buf_pool.get_oldest_modification(0); if (!oldest_lsn) { - if (UNIV_UNLIKELY(lsn_limit != 0)) - { - buf_flush_sync_lsn= 0; - /* wake up buf_flush_wait() */ - pthread_cond_broadcast(&buf_pool.done_flush_list); - } - unemployed: - buf_flush_async_lsn= 0; + fully_unemployed: + buf_flush_sync_lsn= 0; set_idle: buf_pool.page_cleaner_set_idle(true); + set_almost_idle: + pthread_cond_broadcast(&buf_pool.done_flush_LRU); + pthread_cond_broadcast(&buf_pool.done_flush_list); if (UNIV_UNLIKELY(srv_shutdown_state > SRV_SHUTDOWN_INITIATED)) break; mysql_mutex_unlock(&buf_pool.flush_list_mutex); - end_of_batch: buf_dblwr.flush_buffered_writes(); do @@ -2401,6 +2411,7 @@ static void buf_flush_page_cleaner() if (!buf_pool.ran_out()) continue; mysql_mutex_lock(&buf_pool.flush_list_mutex); + oldest_lsn= buf_pool.get_oldest_modification(0); } lsn_t soft_lsn_limit= buf_flush_async_lsn; @@ -2429,7 +2440,17 @@ static void buf_flush_page_cleaner() else if (buf_pool.ran_out()) { buf_pool.page_cleaner_set_idle(false); - buf_pool.get_oldest_modification(0); + buf_pool.n_flush_inc(); + /* Remove clean blocks from buf_pool.flush_list before the LRU scan. */ + for (buf_page_t *p= UT_LIST_GET_FIRST(buf_pool.flush_list); p; ) + { + const lsn_t lsn{p->oldest_modification()}; + ut_ad(lsn > 2 || lsn == 1); + buf_page_t *n= UT_LIST_GET_NEXT(list, p); + if (lsn <= 1) + buf_pool.delete_from_flush_list(p); + p= n; + } mysql_mutex_unlock(&buf_pool.flush_list_mutex); n= srv_max_io_capacity; mysql_mutex_lock(&buf_pool.mutex); @@ -2437,15 +2458,16 @@ static void buf_flush_page_cleaner() n= buf_flush_LRU(n, false); mysql_mutex_unlock(&buf_pool.mutex); last_pages+= n; - - if (pct_lwm == 0.0) - goto end_of_batch; - - /* when idle flushing kicks in page_cleaner is marked active. - reset it back to idle since the it was made active as part of - idle flushing stage. */ + check_oldest_and_set_idle: mysql_mutex_lock(&buf_pool.flush_list_mutex); - goto set_idle; + buf_pool.n_flush_dec_holding_mutex(); + oldest_lsn= buf_pool.get_oldest_modification(0); + if (!oldest_lsn) + goto fully_unemployed; + if (oldest_lsn >= buf_flush_async_lsn) + buf_flush_async_lsn= 0; + buf_pool.page_cleaner_set_idle(false); + goto set_almost_idle; } else if (UNIV_UNLIKELY(srv_shutdown_state > SRV_SHUTDOWN_INITIATED)) break; @@ -2473,6 +2495,7 @@ static void buf_flush_page_cleaner() - page cleaner is idle (dirty_pct < srv_max_dirty_pages_pct_lwm) - there are no pending reads but there are dirty pages to flush */ buf_pool.update_last_activity_count(activity_count); + buf_pool.n_flush_inc(); mysql_mutex_unlock(&buf_pool.flush_list_mutex); goto idle_flush; } @@ -2488,9 +2511,10 @@ static void buf_flush_page_cleaner() else if (dirty_pct < srv_max_buf_pool_modified_pct) possibly_unemployed: if (!soft_lsn_limit && !af_needed_for_redo(oldest_lsn)) - goto unemployed; + goto set_idle; buf_pool.page_cleaner_set_idle(false); + buf_pool.n_flush_inc(); mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (UNIV_UNLIKELY(soft_lsn_limit != 0)) @@ -2528,10 +2552,7 @@ static void buf_flush_page_cleaner() n_flushed); } else if (buf_flush_async_lsn <= oldest_lsn) - { - mysql_mutex_lock(&buf_pool.flush_list_mutex); - goto unemployed; - } + goto check_oldest_and_set_idle; n= n >= n_flushed ? n - n_flushed : 0; goto LRU_flush; diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index e9caf5e334f7f..3e556c7df3743 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1089,59 +1089,57 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id, buf_pool.freed_page_clock += 1; - if (UNIV_LIKELY(bpage->frame != nullptr)) { + if (UNIV_LIKELY(!bpage->zip.data)) { MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t)); MEM_CHECK_ADDRESSABLE(bpage->frame, srv_page_size); buf_block_modify_clock_inc((buf_block_t*) bpage); - if (UNIV_LIKELY_NULL(bpage->zip.data)) { - const page_t* page = bpage->frame; - - ut_a(!zip || !bpage->oldest_modification()); - ut_ad(bpage->zip_size()); - /* Skip consistency checks if the page was freed. - In recovery, we could get a sole FREE_PAGE record - and nothing else, for a ROW_FORMAT=COMPRESSED page. - Its contents would be garbage. */ - if (!bpage->is_freed()) - switch (fil_page_get_type(page)) { - case FIL_PAGE_TYPE_ALLOCATED: - case FIL_PAGE_INODE: - case FIL_PAGE_IBUF_BITMAP: - case FIL_PAGE_TYPE_FSP_HDR: - case FIL_PAGE_TYPE_XDES: - /* These are essentially uncompressed pages. */ - if (!zip) { - /* InnoDB writes the data to the - uncompressed page frame. Copy it - to the compressed page, which will - be preserved. */ - memcpy(bpage->zip.data, page, - bpage->zip_size()); - } - break; - case FIL_PAGE_TYPE_ZBLOB: - case FIL_PAGE_TYPE_ZBLOB2: - case FIL_PAGE_INDEX: - case FIL_PAGE_RTREE: - break; - default: - ib::error() << "The compressed page to be" - " evicted seems corrupt:"; - ut_print_buf(stderr, page, srv_page_size); - - ib::error() << "Possibly older version of" - " the page:"; - - ut_print_buf(stderr, bpage->zip.data, - bpage->zip_size()); - putc('\n', stderr); - ut_error; + } else if (const page_t *page = bpage->frame) { + MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t)); + MEM_CHECK_ADDRESSABLE(bpage->frame, srv_page_size); + buf_block_modify_clock_inc((buf_block_t*) bpage); + + ut_a(!zip || !bpage->oldest_modification()); + ut_ad(bpage->zip_size()); + /* Skip consistency checks if the page was freed. + In recovery, we could get a sole FREE_PAGE record + and nothing else, for a ROW_FORMAT=COMPRESSED page. + Its contents would be garbage. */ + if (!bpage->is_freed()) + switch (fil_page_get_type(page)) { + case FIL_PAGE_TYPE_ALLOCATED: + case FIL_PAGE_INODE: + case FIL_PAGE_IBUF_BITMAP: + case FIL_PAGE_TYPE_FSP_HDR: + case FIL_PAGE_TYPE_XDES: + /* These are essentially uncompressed pages. */ + if (!zip) { + /* InnoDB writes the data to the + uncompressed page frame. Copy it + to the compressed page, which will + be preserved. */ + memcpy(bpage->zip.data, page, + bpage->zip_size()); } - } else { - goto evict_zip; + break; + case FIL_PAGE_TYPE_ZBLOB: + case FIL_PAGE_TYPE_ZBLOB2: + case FIL_PAGE_INDEX: + case FIL_PAGE_RTREE: + break; + default: + ib::error() << "The compressed page to be" + " evicted seems corrupt:"; + ut_print_buf(stderr, page, srv_page_size); + + ib::error() << "Possibly older version of" + " the page:"; + + ut_print_buf(stderr, bpage->zip.data, + bpage->zip_size()); + putc('\n', stderr); + ut_error; } } else { -evict_zip: ut_a(!bpage->oldest_modification()); MEM_CHECK_ADDRESSABLE(bpage->zip.data, bpage->zip_size()); } @@ -1181,25 +1179,6 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id, return true; } - /* Question: If we release hash_lock here - then what protects us against: - 1) Some other thread buffer fixing this page - 2) Some other thread trying to read this page and - not finding it in buffer pool attempting to read it - from the disk. - Answer: - 1) Cannot happen because the page is no longer in the - page_hash. Only possibility is when while invalidating - a tablespace we buffer fix the prev_page in LRU to - avoid relocation during the scan. But that is not - possible because we are holding buf_pool mutex. - - 2) Not possible because in buf_page_init_for_read() - we do a look up of page_hash while holding buf_pool - mutex and since we are holding buf_pool mutex here - and by the time we'll release it in the caller we'd - have inserted the compressed only descriptor in the - page_hash. */ hash_lock.unlock(); if (bpage->zip.data) { diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index ccf8b615b44e1..17c640d5ea086 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -253,7 +253,8 @@ buf_read_page_low( auto fio = space->io(IORequest(sync ? IORequest::READ_SYNC : IORequest::READ_ASYNC), - page_id.page_no() * len, len, dst, bpage); + os_offset_t{page_id.page_no()} * len, len, + dst, bpage); if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) { buf_pool.corrupted_evict(bpage, buf_page_t::READ_FIX); @@ -302,7 +303,8 @@ wants to access TRANSACTIONAL_TARGET ulint buf_read_ahead_random(const page_id_t page_id, ulint zip_size) { - if (!srv_random_read_ahead) + if (!srv_random_read_ahead || page_id.space() >= SRV_TMP_SPACE_ID) + /* Disable the read-ahead for temporary tablespace */ return 0; if (srv_startup_is_before_trx_rollback_phase) @@ -508,8 +510,9 @@ latches! TRANSACTIONAL_TARGET ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size) { - /* check if readahead is disabled */ - if (!srv_read_ahead_threshold) + /* check if readahead is disabled. + Disable the read ahead logic for temporary tablespace */ + if (!srv_read_ahead_threshold || page_id.space() >= SRV_TMP_SPACE_ID) return 0; if (srv_startup_is_before_trx_rollback_phase) @@ -554,11 +557,16 @@ ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size) for (page_id_t i= low; i <= high_1; ++i) { buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(i.fold()); - transactional_shared_lock_guard g - {buf_pool.page_hash.lock_get(chain)}; + page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain); + /* It does not make sense to use transactional_lock_guard here, + because we would have many complex conditions inside the memory + transaction. */ + hash_lock.lock_shared(); + const buf_page_t* bpage= buf_pool.page_hash.get(i, chain); if (!bpage) { + hash_lock.unlock_shared(); if (i == page_id) goto fail; failed: @@ -566,6 +574,7 @@ ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size) continue; goto fail; } + const unsigned accessed= bpage->is_accessed(); if (i == page_id) { /* Read the natural predecessor and successor page addresses from @@ -576,6 +585,7 @@ ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size) const byte *f= bpage->frame ? bpage->frame : bpage->zip.data; uint32_t prev= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_PREV)); uint32_t next= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_NEXT)); + hash_lock.unlock_shared(); if (prev == FIL_NULL || next == FIL_NULL) goto fail; page_id_t id= page_id; @@ -605,8 +615,9 @@ ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size) /* The area is not whole */ goto fail; } + else + hash_lock.unlock_shared(); - const unsigned accessed= bpage->is_accessed(); if (!accessed) goto failed; /* Note that buf_page_t::is_accessed() returns the time of the diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 1780fb04d07dd..df69e313f0922 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -34,6 +34,8 @@ Created Jan 06, 2010 Vasil Dimov #include "log.h" #include "btr0btr.h" #include "que0que.h" +#include "scope.h" +#include "debug_sync.h" #include #include @@ -3183,6 +3185,15 @@ dict_stats_save( char db_utf8[MAX_DB_UTF8_LEN]; char table_utf8[MAX_TABLE_UTF8_LEN]; +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("dict_stats_save_exit_notify", + SCOPE_EXIT([] { + debug_sync_set_action(current_thd, + STRING_WITH_LEN("now SIGNAL dict_stats_save_finished")); + }); + ); +#endif /* ENABLED_DEBUG_SYNC */ + if (high_level_read_only) { return DB_READ_ONLY; } diff --git a/storage/innobase/dict/drop.cc b/storage/innobase/dict/drop.cc index d92c2e1240912..fcda4ad008ece 100644 --- a/storage/innobase/dict/drop.cc +++ b/storage/innobase/dict/drop.cc @@ -233,7 +233,9 @@ dberr_t trx_t::drop_table(const dict_table_t &table) void trx_t::commit(std::vector &deleted) { ut_ad(dict_operation); + flush_log_later= true; commit_persist(); + flush_log_later= false; if (dict_operation) { ut_ad(dict_sys.locked()); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 0d1560a29c081..83435867b046a 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -24,13 +24,13 @@ Modified Jan Lindström jan.lindstrom@mariadb.com *******************************************************/ #include "fil0crypt.h" -#include "mtr0types.h" #include "mach0data.h" #include "page0zip.h" #include "buf0checksum.h" #ifdef UNIV_INNOCHECKSUM # include "buf0buf.h" #else +#include "buf0flu.h" #include "buf0dblwr.h" #include "srv0srv.h" #include "srv0start.h" diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 7a1db800aa290..6ed0393f09177 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -334,6 +334,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, return node; } +__attribute__((warn_unused_result, nonnull)) /** Open a tablespace file. @param node data file @return whether the file was successfully opened */ @@ -362,9 +363,9 @@ static bool fil_node_open_file_low(fil_node_t *node) : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_AIO, type, srv_read_only_mode, &success); - if (node->is_open()) + + if (success && node->is_open()) { - ut_ad(success); #ifndef _WIN32 if (!node->space->id && !srv_read_only_mode && my_disable_locking && os_file_lock(node->handle, node->name)) @@ -2496,6 +2497,17 @@ fil_ibd_discover( /* A datafile was not discovered for the filename given. */ return(false); } + +bool fil_crypt_check(fil_space_crypt_t *crypt_data, const char *f_name) +{ + if (crypt_data->is_key_found()) + return true; + sql_print_error("InnoDB: Encryption key is not found for %s", f_name); + crypt_data->~fil_space_crypt_t(); + ut_free(crypt_data); + return false; +} + /** Open an ibd tablespace and add it to the InnoDB data structures. This is similar to fil_ibd_open() except that it is used while processing the REDO log, so the data dictionary is not available and very little @@ -2641,9 +2653,7 @@ fil_ibd_load(uint32_t space_id, const char *filename, fil_space_t *&space) first_page) : NULL; - if (crypt_data && !crypt_data->is_key_found()) { - crypt_data->~fil_space_crypt_t(); - ut_free(crypt_data); + if (crypt_data && !fil_crypt_check(crypt_data, filename)) { return FIL_LOAD_INVALID; } @@ -2907,6 +2917,7 @@ void IORequest::write_complete(int io_error) const ut_ad(fil_validate_skip()); ut_ad(node); ut_ad(is_write()); + node->complete_write(); if (!bpage) { @@ -2919,7 +2930,6 @@ void IORequest::write_complete(int io_error) const else buf_page_write_complete(*this, io_error); - node->complete_write(); node->space->release(); } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 6a4d86f7aead2..2be781adc6598 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -2764,17 +2764,25 @@ fseg_free_extent( not_full_n_used - descr_n_used); } - err = fsp_free_extent(space, page, mtr); - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { - return err; - } + std::vector going_to_free; + static_assert(FSP_EXTENT_SIZE_MIN == 256, "compatibility"); + static_assert(FSP_EXTENT_SIZE_MAX == 64, "compatibility"); for (uint32_t i = 0; i < FSP_EXTENT_SIZE; i++) { if (!xdes_is_free(descr, i)) { - buf_page_free(space, first_page_in_extent + i, mtr); + going_to_free.emplace_back(uint8_t(i)); } } + if (dberr_t err = fsp_free_extent(space, page, mtr)) { + return err; + } + + for (uint32_t i : going_to_free) { + mtr->free(*space, first_page_in_extent + i); + buf_page_free(space, first_page_in_extent + i, mtr); + } + return DB_SUCCESS; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f52a8d5fa91bd..aca5ec7624623 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,17 +1,10 @@ /***************************************************************************** Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. Copyright (c) 2013, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are gratefully acknowledged and are described briefly in the InnoDB @@ -230,6 +223,8 @@ static uint innodb_max_purge_lag_wait; static void innodb_max_purge_lag_wait_update(THD *thd, st_mysql_sys_var *, void *, const void *limit) { + if (high_level_read_only) + return; const uint l= *static_cast(limit); if (!trx_sys.history_exceeds(l)) return; @@ -4340,9 +4335,7 @@ innobase_commit_ordered_2( { DBUG_ENTER("innobase_commit_ordered_2"); - const bool read_only = trx->read_only || trx->id == 0; - - if (!read_only) { + if (trx->id) { /* The following call reads the binary log position of the transaction being committed. @@ -4372,11 +4365,8 @@ innobase_commit_ordered_2( #endif /* WITH_WSREP */ innobase_commit_low(trx); - - if (!read_only) { - trx->mysql_log_file_name = NULL; - trx->flush_log_later = false; - } + trx->mysql_log_file_name = NULL; + trx->flush_log_later = false; DBUG_VOID_RETURN; } @@ -4923,7 +4913,11 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) if (trx_t* trx= thd_to_trx(thd)) { ut_ad(trx->mysql_thd == thd); - if (!trx->lock.wait_lock); + mysql_mutex_lock(&lock_sys.wait_mutex); + lock_t *lock= trx->lock.wait_lock; + + if (!lock) + /* The transaction is not waiting for any lock. */; #ifdef WITH_WSREP else if (trx->is_wsrep() && wsrep_thd_is_aborting(thd)) /* if victim has been signaled by BF thread and/or aborting is already @@ -4931,7 +4925,18 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) Also, BF thread should own trx mutex for the victim. */; #endif /* WITH_WSREP */ else - lock_sys_t::cancel(trx); + { + if (!trx->dict_operation) + { + /* Dictionary transactions must be immune to KILL, because they + may be executed as part of a multi-transaction DDL operation, such + as rollback_inplace_alter_table() or ha_innobase::delete_table(). */; + trx->error_state= DB_INTERRUPTED; + lock_sys_t::cancel(trx, lock); + } + lock_sys.deadlock_check(); + } + mysql_mutex_unlock(&lock_sys.wait_mutex); } DBUG_VOID_RETURN; @@ -13066,7 +13071,8 @@ bool create_table_info_t::row_size_is_acceptable( eow << "Cannot add field " << field->name << " in table "; else eow << "Cannot add an instantly dropped column in table "; - eow << index.table->name << " because after adding it, the row size is " + eow << "`" << m_form->s->db.str << "`.`" << m_form->s->table_name.str + << "`" " because after adding it, the row size is " << info.get_overrun_size() << " which is greater than maximum allowed size (" << info.max_leaf_size << " bytes) for a record on index leaf page."; @@ -14144,6 +14150,7 @@ ha_innobase::rename_table( } if (error == DB_SUCCESS) { + trx->flush_log_later = true; innobase_commit_low(trx); } else { trx->rollback(); @@ -14159,6 +14166,7 @@ ha_innobase::rename_table( if (error == DB_SUCCESS) { log_write_up_to(trx->commit_lsn, true); } + trx->flush_log_later = false; trx->free(); if (error == DB_DUPLICATE_KEY) { @@ -17652,13 +17660,7 @@ innodb_monitor_validate_wildcard_name( Validate the passed in monitor name, find and save the corresponding monitor name in the function parameter "save". @return 0 if monitor name is valid */ -static -int -innodb_monitor_valid_byname( -/*========================*/ - void* save, /*!< out: immediate result - for update function */ - const char* name) /*!< in: incoming monitor name */ +static int innodb_monitor_valid_byname(const char *name) { ulint use; monitor_info_t* monitor_info; @@ -17706,9 +17708,6 @@ innodb_monitor_valid_byname( } } - /* Save the configure name for innodb_monitor_update() */ - *static_cast(save) = name; - return(0); } /*************************************************************//** @@ -17724,41 +17723,18 @@ innodb_monitor_validate( for update function */ struct st_mysql_value* value) /*!< in: incoming string */ { - const char* name; - char* monitor_name; - char buff[STRING_BUFFER_USUAL_SIZE]; - int len = sizeof(buff); - int ret; + int ret= 0; - ut_a(save != NULL); - ut_a(value != NULL); - - name = value->val_str(value, buff, &len); - - /* monitor_name could point to memory from MySQL - or buff[]. Always dup the name to memory allocated - by InnoDB, so we can access it in another callback - function innodb_monitor_update() and free it appropriately */ - if (name) { - monitor_name = my_strdup(PSI_INSTRUMENT_ME, - name, MYF(0)); - } else { - return(1); - } - - ret = innodb_monitor_valid_byname(save, monitor_name); - - if (ret) { - /* Validation failed */ - my_free(monitor_name); - } else { - /* monitor_name will be freed in separate callback function - innodb_monitor_update(). Assert "save" point to - the "monitor_name" variable */ - ut_ad(*static_cast(save) == monitor_name); - } + if (const char *name= value->val_str(value, nullptr, &ret)) + { + ret= innodb_monitor_valid_byname(name); + if (!ret) + *static_cast(save)= name; + } + else + ret= 1; - return(ret); + return ret; } /****************************************************************//** @@ -17774,11 +17750,9 @@ innodb_monitor_update( formal string goes */ const void* save, /*!< in: immediate result from check function */ - mon_option_t set_option, /*!< in: the set option, + mon_option_t set_option) /*!< in: the set option, whether to turn on/off or reset the counter */ - ibool free_mem) /*!< in: whether we will - need to free the memory */ { monitor_info_t* monitor_info; ulint monitor_id; @@ -17862,12 +17836,6 @@ innodb_monitor_update( sql_print_warning("InnoDB: Monitor %s is already enabled.", srv_mon_get_name((monitor_id_t) err_monitor)); } - - if (free_mem && name) { - my_free((void*) name); - } - - return; } #ifdef UNIV_DEBUG @@ -17952,7 +17920,7 @@ innodb_enable_monitor_update( const void* save) /*!< in: immediate result from check function */ { - innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, TRUE); + innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON); } /****************************************************************//** @@ -17969,7 +17937,7 @@ innodb_disable_monitor_update( const void* save) /*!< in: immediate result from check function */ { - innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, TRUE); + innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF); } /****************************************************************//** @@ -17987,7 +17955,7 @@ innodb_reset_monitor_update( const void* save) /*!< in: immediate result from check function */ { - innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, TRUE); + innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE); } /****************************************************************//** @@ -18005,8 +17973,7 @@ innodb_reset_all_monitor_update( const void* save) /*!< in: immediate result from check function */ { - innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE, - TRUE); + innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE); } static inline char *my_strtok_r(char *str, const char *delim, char **saveptr) @@ -18042,10 +18009,9 @@ innodb_enable_monitor_at_startup( for (char* option = my_strtok_r(str, sep, &last); option; option = my_strtok_r(NULL, sep, &last)) { - char* option_name; - if (!innodb_monitor_valid_byname(&option_name, option)) { + if (!innodb_monitor_valid_byname(option)) { innodb_monitor_update(NULL, NULL, &option, - MONITOR_TURN_ON, FALSE); + MONITOR_TURN_ON); } else { sql_print_warning("Invalid monitor counter" " name: '%s'", option); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index bed0aa337f7d4..e08f4757ad306 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7792,6 +7792,8 @@ bool check_col_is_in_fk_indexes( { for (ulint i= 0; i < f->n_fields; i++) { + if (!f->referenced_index) + continue; if (f->referenced_index->fields[i].col == col) { my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), @@ -11519,7 +11521,7 @@ ha_innobase::commit_inplace_alter_table( DEBUG_SYNC(m_user_thd, "innodb_alter_inplace_before_commit"); if (new_clustered) { - ut_ad(trx->has_logged()); + ut_ad(trx->has_logged_persistent()); for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) { auto ctx= static_cast(*pctx); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 2aaf748d7ae7c..0628faf844e42 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1658,6 +1658,10 @@ class buf_pool_t /** Decrement the number of pending LRU flush */ inline void n_flush_dec(); + /** Decrement the number of pending LRU flush + while holding flush_list_mutex */ + inline void n_flush_dec_holding_mutex(); + /** @return whether flush_list flushing is active */ bool flush_list_active() const { @@ -1682,6 +1686,15 @@ class buf_pool_t mysql_mutex_assert_owner(&flush_list_mutex); return page_cleaner_status & PAGE_CLEANER_IDLE; } + + /** @return whether the page cleaner may be initiating writes */ + bool page_cleaner_active() const + { + mysql_mutex_assert_owner(&flush_list_mutex); + static_assert(PAGE_CLEANER_IDLE == 1, "efficiency"); + return page_cleaner_status > PAGE_CLEANER_IDLE; + } + /** Wake up the page cleaner if needed. @param for_LRU whether to wake up for LRU eviction */ void page_cleaner_wakeup(bool for_LRU= false); diff --git a/storage/innobase/include/buf0buf.inl b/storage/innobase/include/buf0buf.inl index 24f7352ca4cd1..1fc463a834148 100644 --- a/storage/innobase/include/buf0buf.inl +++ b/storage/innobase/include/buf0buf.inl @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2014, 2022, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. @@ -31,11 +24,7 @@ The database buffer buf_pool Created 11/5/1995 Heikki Tuuri *******************************************************/ -#include "mtr0mtr.h" -#include "buf0flu.h" #include "buf0lru.h" -#include "buf0rea.h" -#include "fsp0types.h" /** Determine if a block is still close enough to the MRU end of the LRU list meaning that it is not in danger of getting evicted and also implying diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index c1927bec916e2..3159349c1dffd 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -43,6 +43,7 @@ Created 1/8/1996 Heikki Tuuri #include "trx0types.h" #include "fts0fts.h" #include "buf0buf.h" +#include "mtr0mtr.h" #include "gis0type.h" #include "fil0fil.h" #include "fil0crypt.h" @@ -1037,7 +1038,8 @@ struct dict_index_t { unsigned uncommitted:1; /*!< a flag that is set for secondary indexes that have not been committed to the - data dictionary yet */ + data dictionary yet. Protected by + MDL */ #ifdef UNIV_DEBUG /** whether this is a dummy index object */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index aa52169e6bbd7..2d1dc4ba8739c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1803,4 +1803,10 @@ void test_make_filepath(); @return block size */ ulint fil_space_get_block_size(const fil_space_t* space, unsigned offset); +/** Check whether encryption key found +@param crypt_data Encryption data +@param f_name File name +@return encryption key found */ +bool fil_crypt_check(fil_space_crypt_t *crypt_data, const char *f_name); + #endif /* UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 6eb5bb3f18394..867ad9e010931 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -47,25 +47,6 @@ struct hash_cell_t insert.*next= nullptr; *after= &insert; } - - /** Insert an element after another. - @tparam T type of the element - @param after the element after which to insert - @param insert the being-inserted element - @param next the next-element pointer in T */ - template - void insert_after(T &after, T &insert, T *T::*next) - { -#ifdef UNIV_DEBUG - for (const T *c= static_cast(node); c; c= c->*next) - if (c == &after) - goto found; - ut_error; - found: -#endif - insert.*next= after.*next; - after.*next= &insert; - } }; /*******************************************************************//** diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index fd91fa23d61b7..eca8c2cb61495 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -891,8 +891,6 @@ class lock_sys_t @retval DB_LOCK_WAIT if the lock was canceled */ template static dberr_t cancel(trx_t *trx, lock_t *lock); - /** Cancel a waiting lock request (if any) when killing a transaction */ - static void cancel(trx_t *trx); /** Note that a record lock wait started */ inline void wait_start(); diff --git a/storage/innobase/include/lock0types.h b/storage/innobase/include/lock0types.h index 995fd273481b9..0d00b4b360d2d 100644 --- a/storage/innobase/include/lock0types.h +++ b/storage/innobase/include/lock0types.h @@ -232,6 +232,11 @@ struct ib_lock_t return(static_cast(type_mode & LOCK_MODE_MASK)); } + bool is_rec_granted_exclusive_not_gap() const + { + return (type_mode & (LOCK_MODE_MASK | LOCK_GAP)) == LOCK_X; + } + /** Print the lock object into the given output stream. @param[in,out] out the output stream @return the given output stream. */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index cd596b4db4665..bfbc7c91615a1 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. -Copyright (c) 2009, Google Inc. Copyright (c) 2017, 2022, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. @@ -358,6 +351,24 @@ typedef srw_lock log_rwlock_t; /** @return end of resize_buf */ inline const byte *resize_buf_end() const noexcept { return resize_buf + resize_target; } + + /** Initialise the redo log subsystem. */ + void create_low(); + /** Initialise the redo log subsystem. + @return whether the initialisation succeeded */ + bool create() { create_low(); return true; } + + /** Attach a log file. + @return whether the memory allocation succeeded */ + bool attach(log_file_t file, os_offset_t size); +#else + /** Initialise the redo log subsystem. + @return whether the initialisation succeeded */ + bool create(); + /** Attach a log file. */ + void attach_low(log_file_t file, os_offset_t size); + bool attach(log_file_t file, os_offset_t size) + { attach_low(file, size); return true; } #endif #if defined __linux__ || defined _WIN32 @@ -367,8 +378,6 @@ typedef srw_lock log_rwlock_t; /** Try to enable or disable durable writes (update log_write_through) */ void set_write_through(bool write_through); - void attach(log_file_t file, os_offset_t size); - void close_file(); /** Calculate the checkpoint safety margins. */ @@ -425,9 +434,6 @@ typedef srw_lock log_rwlock_t; /** Make previous write_buf() durable and update flushed_to_disk_lsn. */ bool flush(lsn_t lsn) noexcept; - /** Initialise the redo log subsystem. */ - void create(); - /** Shut down the redo log subsystem. */ void close(); diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 2c4e92a6deea7..f1b2862f9f665 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -241,9 +241,10 @@ struct recv_sys_t /** The contents of the doublewrite buffer */ recv_dblwr_t dblwr; - inline void read(os_offset_t offset, span buf); + __attribute__((warn_unused_result)) + inline dberr_t read(os_offset_t offset, span buf); inline size_t files_size(); - void close_files() { files.clear(); files.shrink_to_fit(); } + void close_files(); /** Advance pages_it if it matches the iterator */ void pages_it_invalidate(const map::iterator &p) diff --git a/storage/innobase/include/log0types.h b/storage/innobase/include/log0types.h index 337fcd3179355..df87968d8f258 100644 --- a/storage/innobase/include/log0types.h +++ b/storage/innobase/include/log0types.h @@ -2,12 +2,6 @@ Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index c0790f2de91ae..1da8b340e0d63 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -182,13 +182,9 @@ note that the trx may have been committed before the caller acquires trx_t::mutex @retval NULL if no match */ trx_t* trx_get_trx_by_xid(const XID* xid); -/**********************************************************************//** -If required, flushes the log to disk if we called trx_commit_for_mysql() -with trx->flush_log_later == TRUE. */ -void -trx_commit_complete_for_mysql( -/*==========================*/ - trx_t* trx); /*!< in/out: transaction */ +/** Durably write log until trx->commit_lsn +(if trx_t::commit_in_memory() was invoked with flush_log_later=true). */ +void trx_commit_complete_for_mysql(trx_t *trx); /**********************************************************************//** Marks the latest SQL statement ended. */ void @@ -341,7 +337,10 @@ struct trx_lock_t #if defined(UNIV_DEBUG) || !defined(DBUG_OFF) /** 2=high priority WSREP thread has marked this trx to abort; - 1=another transaction chose this as a victim in deadlock resolution. */ + 1=another transaction chose this as a victim in deadlock resolution. + + Other threads than the one that is executing the transaction may set + flags in this while holding lock_sys.wait_mutex. */ Atomic_relaxed was_chosen_as_deadlock_victim; /** Flag the lock owner as a victim in Galera conflict resolution. */ @@ -360,13 +359,14 @@ struct trx_lock_t #else /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ /** High priority WSREP thread has marked this trx to abort or - another transaction chose this as a victim in deadlock resolution. */ + another transaction chose this as a victim in deadlock resolution. + + Other threads than the one that is executing the transaction may set + this while holding lock_sys.wait_mutex. */ Atomic_relaxed was_chosen_as_deadlock_victim; /** Flag the lock owner as a victim in Galera conflict resolution. */ - void set_wsrep_victim() { - was_chosen_as_deadlock_victim= true; - } + void set_wsrep_victim() { was_chosen_as_deadlock_victim= true; } #endif /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ /** Next available rec_pool[] entry */ @@ -815,12 +815,6 @@ struct trx_t : ilist_node<> defer flush of the logs to disk until after we release the mutex. */ - bool must_flush_log_later;/*!< set in commit() - if flush_log_later was - set and redo log was written; - in that case we will - flush the log in - trx_commit_complete_for_mysql() */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ /** whether this modifies InnoDB dictionary tables */ bool dict_operation; @@ -859,11 +853,13 @@ struct trx_t : ilist_node<> /*!< how many tables the current SQL statement uses, except those in consistent read */ - dberr_t error_state; /*!< 0 if no error, otherwise error - number; NOTE That ONLY the thread - doing the transaction is allowed to - set this field: this is NOT protected - by any mutex */ + + /** DB_SUCCESS or error code; usually only the thread that is running + the transaction is allowed to modify this field. The only exception is + when a thread invokes lock_sys_t::cancel() in order to abort a + lock_wait(). That is protected by lock_sys.wait_mutex and lock.wait_lock. */ + dberr_t error_state; + const dict_index_t*error_info; /*!< if the error number indicates a duplicate key error, a pointer to the problematic index is stored here */ @@ -1012,11 +1008,19 @@ struct trx_t : ilist_node<> /** Commit the transaction in a mini-transaction. @param mtr mini-transaction (if there are any persistent modifications) */ void commit_low(mtr_t *mtr= nullptr); + /** Commit an empty transaction. + @param mtr mini-transaction */ + void commit_empty(mtr_t *mtr); + /** Commit an empty transaction. + @param mtr mini-transaction */ + /** Assign the transaction its history serialisation number and write the + UNDO log to the assigned rollback segment. + @param mtr mini-transaction */ + inline void write_serialisation_history(mtr_t *mtr); public: /** Commit the transaction. */ void commit(); - /** Try to drop a persistent table. @param table persistent table @param fk whether to drop FOREIGN KEY metadata diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 45ed1f4a0fdc3..37ca85b28d338 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -226,12 +226,6 @@ void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback, mtr_t *mtr) MY_ATTRIBUTE((nonnull)); -/** Free temporary undo log after commit or rollback. -The information is not needed after a commit or rollback, therefore -the data can be discarded. -@param undo temporary undo log */ -void trx_undo_commit_cleanup(trx_undo_t *undo); - /** At shutdown, frees the undo logs of a transaction. */ void trx_undo_free_at_shutdown(trx_t *trx); diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 93352b279b114..8ef01bc0353ea 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -2,13 +2,6 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2023, MariaDB Corporation. -Copyright (c) 2008, Google Inc. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. 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 diff --git a/storage/innobase/include/ut0byte.h b/storage/innobase/include/ut0byte.h index 7ed64c61c4bc9..2b70fac3c96e7 100644 --- a/storage/innobase/include/ut0byte.h +++ b/storage/innobase/include/ut0byte.h @@ -101,16 +101,6 @@ ut_bit_get_nth( /*===========*/ ulint a, /*!< in: ulint */ ulint n); /*!< in: nth bit requested */ -/*****************************************************************//** -Sets the nth bit of a ulint. -@return the ulint with the bit set as requested */ -UNIV_INLINE -ulint -ut_bit_set_nth( -/*===========*/ - ulint a, /*!< in: ulint */ - ulint n, /*!< in: nth bit requested */ - ibool val); /*!< in: value for the bit to set */ #include "ut0byte.inl" diff --git a/storage/innobase/include/ut0byte.inl b/storage/innobase/include/ut0byte.inl index a4b5d4a7d8f44..dfa069c27324f 100644 --- a/storage/innobase/include/ut0byte.inl +++ b/storage/innobase/include/ut0byte.inl @@ -88,22 +88,3 @@ ut_bit_get_nth( ut_ad(n < 8 * sizeof(ulint)); return(1 & (a >> n)); } - -/*****************************************************************//** -Sets the nth bit of a ulint. -@return the ulint with the bit set as requested */ -UNIV_INLINE -ulint -ut_bit_set_nth( -/*===========*/ - ulint a, /*!< in: ulint */ - ulint n, /*!< in: nth bit requested */ - ibool val) /*!< in: value for the bit to set */ -{ - ut_ad(n < 8 * sizeof(ulint)); - if (val) { - return(((ulint) 1 << n) | a); - } else { - return(~((ulint) 1 << n) & a); - } -} diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 0e9cef669d456..e2b338fa106fa 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -275,9 +275,12 @@ namespace Deadlock MY_ATTRIBUTE((nonnull, warn_unused_result)) /** Check if a lock request results in a deadlock. Resolve a deadlock by choosing a transaction that will be rolled back. - @param trx transaction requesting a lock - @return whether trx must report DB_DEADLOCK */ - static bool check_and_resolve(trx_t *trx); + @param trx transaction requesting a lock + @param wait_lock the lock being requested + @return the lock that trx is or was waiting for + @retval nullptr if the lock wait was resolved + @retval -1 if trx must report DB_DEADLOCK */ + static lock_t *check_and_resolve(trx_t *trx, lock_t *wait_lock); /** Quickly detect a deadlock using Brent's cycle detection algorithm. @param trx transaction that is waiting for another transaction @@ -929,6 +932,21 @@ lock_rec_other_has_expl_req( #ifdef WITH_WSREP void lock_wait_wsrep_kill(trx_t *bf_trx, ulong thd_id, trx_id_t trx_id); +#ifdef UNIV_DEBUG +void wsrep_report_error(const lock_t* victim_lock, const trx_t *bf_trx) +{ + // We have conflicting BF-BF case, these threads + // should not execute concurrently + mtr_t mtr; + WSREP_ERROR("BF request is not compatible with victim"); + WSREP_ERROR("BF requesting lock: "); + lock_rec_print(stderr, bf_trx->lock.wait_lock, mtr); + WSREP_ERROR("victim holding lock: "); + lock_rec_print(stderr, victim_lock, mtr); + wsrep_assert_no_bf_bf_wait(victim_lock, bf_trx); +} +#endif /* WITH_DEBUG */ + /** Kill the holders of conflicting locks. @param trx brute-force applier transaction running in the current thread */ ATTRIBUTE_COLD ATTRIBUTE_NOINLINE @@ -957,13 +975,26 @@ static void lock_wait_wsrep(trx_t *trx) dict_table_t *table= wait_lock->un_member.tab_lock.table; for (lock_t *lock= UT_LIST_GET_FIRST(table->locks); lock; lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) + { /* if victim has also BF status, but has earlier seqno, we have to wait */ if (lock->trx != trx && !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) { + if (wsrep_thd_is_BF(lock->trx->mysql_thd, false)) + { + // There is no need to kill victim with compatible lock + if (!lock_has_to_wait(trx->lock.wait_lock, lock)) + continue; + +#ifdef UNIV_DEBUG + wsrep_report_error(lock, trx); +#endif + } + victims.emplace(lock->trx); } + } } else { @@ -977,14 +1008,26 @@ static void lock_wait_wsrep(trx_t *trx) if (!lock_rec_get_nth_bit(lock, heap_no)) lock= lock_rec_get_next(heap_no, lock); do + { /* if victim has also BF status, but has earlier seqno, we have to wait */ if (lock->trx != trx && !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) { + if (wsrep_thd_is_BF(lock->trx->mysql_thd, false)) + { + // There is no need to kill victim with compatible lock + if (!lock_has_to_wait(trx->lock.wait_lock, lock)) + continue; + +#ifdef UNIV_DEBUG + wsrep_report_error(lock, trx); +#endif + } + victims.emplace(lock->trx); } - while ((lock= lock_rec_get_next(heap_no, lock))); + } while ((lock= lock_rec_get_next(heap_no, lock))); } } @@ -1554,6 +1597,10 @@ lock_rec_lock( ut_ad(~mode & (LOCK_GAP | LOCK_REC_NOT_GAP)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); DBUG_EXECUTE_IF("innodb_report_deadlock", return DB_DEADLOCK;); +#ifdef ENABLED_DEBUG_SYNC + if (trx->mysql_thd) + DEBUG_SYNC_C("lock_rec"); +#endif ut_ad((LOCK_MODE_MASK & mode) != LOCK_S || lock_table_has(trx, index->table, LOCK_IS)); @@ -1725,24 +1772,26 @@ void lock_sys_t::wait_resume(THD *thd, my_hrtime_t start, my_hrtime_t now) } #ifdef HAVE_REPLICATION -ATTRIBUTE_NOINLINE MY_ATTRIBUTE((nonnull)) +ATTRIBUTE_NOINLINE MY_ATTRIBUTE((nonnull, warn_unused_result)) /** Report lock waits to parallel replication. Sets trx->error_state= DB_DEADLOCK if trx->lock.was_chosen_as_deadlock_victim was set when lock_sys.wait_mutex was unlocked. @param trx transaction that may be waiting for a lock -@param wait_lock lock that is being waited for */ -static void lock_wait_rpl_report(trx_t *trx) +@param wait_lock lock that is being waited for +@return lock being waited for (may have been replaced by an equivalent one) +@retval nullptr if no lock is being waited for */ +static lock_t *lock_wait_rpl_report(trx_t *trx) { mysql_mutex_assert_owner(&lock_sys.wait_mutex); ut_ad(trx->state == TRX_STATE_ACTIVE); THD *const thd= trx->mysql_thd; ut_ad(thd); - const lock_t *wait_lock= trx->lock.wait_lock; + lock_t *wait_lock= trx->lock.wait_lock; if (!wait_lock) - return; + return nullptr; /* This would likely be too large to attempt to use a memory transaction, even for wait_lock->is_table(). */ - const bool nowait= lock_sys.wr_lock_try(); + const bool nowait= lock_sys.wr_lock_try(); if (!nowait) { mysql_mutex_unlock(&lock_sys.wait_mutex); @@ -1757,12 +1806,15 @@ static void lock_wait_rpl_report(trx_t *trx) lock_sys.wait_mutex was unlocked, let's check it. */ if (!nowait && trx->lock.was_chosen_as_deadlock_victim) trx->error_state= DB_DEADLOCK; - return; + return wait_lock; } ut_ad(wait_lock->is_waiting()); } else if (!wait_lock->is_waiting()) + { + wait_lock= nullptr; goto func_exit; + } if (wait_lock->is_table()) { @@ -1803,14 +1855,16 @@ dberr_t lock_wait(que_thr_t *thr) { trx_t *trx= thr_get_trx(thr); +#ifdef ENABLED_DEBUG_SYNC if (trx->mysql_thd) DEBUG_SYNC_C("lock_wait_start"); /* Create the sync point for any quit from the function. */ - ut_d(SCOPE_EXIT([trx]() { + SCOPE_EXIT([trx]() { if (trx->mysql_thd) DEBUG_SYNC_C("lock_wait_end"); - })); + }); +#endif /* InnoDB system transactions may use the global value of innodb_lock_wait_timeout, because trx->mysql_thd == NULL. */ @@ -1819,8 +1873,10 @@ dberr_t lock_wait(que_thr_t *thr) ut_ad(!trx->dict_operation_lock_mode); /* The wait_lock can be cleared by another thread in lock_grant(), - lock_rec_cancel(), or lock_cancel_waiting_and_release(). But, a wait - can only be initiated by the current thread which owns the transaction. + lock_rec_cancel(), lock_cancel_waiting_and_release(), which could be + invoked from the high-level function lock_sys_t::cancel(). + But, a wait can only be initiated by the current thread which owns + the transaction. Even if trx->lock.wait_lock were changed, the object that it used to point to it will remain valid memory (remain allocated from @@ -1835,17 +1891,26 @@ dberr_t lock_wait(que_thr_t *thr) wait_lock->type_mode & (LOCK_TABLE | LOCK_AUTO_INC), which will be unaffected by any page split or merge operation. (Furthermore, table lock objects will never be cloned or moved.) */ - const lock_t *const wait_lock= trx->lock.wait_lock; + lock_t *wait_lock= trx->lock.wait_lock; if (!wait_lock) { /* The lock has already been released or this transaction was chosen as a deadlock victim: no need to wait */ - trx->error_state= - trx->lock.was_chosen_as_deadlock_victim ? DB_DEADLOCK : DB_SUCCESS; + if (trx->lock.was_chosen_as_deadlock_victim) + trx->error_state= DB_DEADLOCK; + else if (trx->error_state == DB_LOCK_WAIT) + trx->error_state= DB_SUCCESS; return trx->error_state; } + /* Because we are not holding exclusive lock_sys.latch, the + wait_lock may be changed by other threads during a page split or + merge in case it is a record lock. + + Because at this point we are not holding lock_sys.wait_mutex either, + another thread may set trx->lock.wait_lock == nullptr at any time. */ + trx->lock.suspend_time= suspend_time; ut_ad(!trx->dict_operation_lock_mode); @@ -1861,7 +1926,7 @@ dberr_t lock_wait(que_thr_t *thr) is not being used. We want to be allow the user to skip lock_wait_rpl_report(). */ const bool rpl= trx->mysql_thd && innodb_deadlock_detect && - thd_need_wait_reports(trx->mysql_thd); + thd_need_wait_reports(trx->mysql_thd); #endif const bool row_lock_wait= thr->lock_state == QUE_THR_LOCK_ROW; timespec abstime; @@ -1878,13 +1943,36 @@ dberr_t lock_wait(que_thr_t *thr) thd_wait_begin(trx->mysql_thd, (type_mode & LOCK_TABLE) ? THD_WAIT_TABLE_LOCK : THD_WAIT_ROW_LOCK); - int err= 0; mysql_mutex_lock(&lock_sys.wait_mutex); - if (trx->lock.wait_lock) + /* Now that we are holding lock_sys.wait_mutex, we must reload + trx->lock.wait_mutex. It cannot be cleared as long as we are holding + lock_sys.wait_mutex, but as long as we do not hold exclusive + lock_sys.latch, a waiting record lock can be replaced with an + equivalent waiting record lock during a page split or merge by + another thread. See lock_sys_t::cancel(). */ + wait_lock= trx->lock.wait_lock; + + if (wait_lock) { - if (Deadlock::check_and_resolve(trx)) + /* Dictionary transactions must ignore KILL, because they could + be executed as part of a multi-transaction DDL operation, + such as rollback_inplace_alter_table() or ha_innobase::delete_table(). */ + if (!trx->dict_operation && trx_is_interrupted(trx)) + { + /* innobase_kill_query() can only set trx->error_state=DB_INTERRUPTED + for any transaction that is attached to a connection. + + Furthermore, innobase_kill_query() could have been invoked before + this thread entered a lock wait. The thd_kill_level() or thd::killed + is only being checked every now and then. */ + trx->error_state= DB_INTERRUPTED; + goto abort_wait; + } + + wait_lock= Deadlock::check_and_resolve(trx, wait_lock); + + if (wait_lock == reinterpret_cast(-1)) { - ut_ad(!trx->lock.wait_lock); trx->error_state= DB_DEADLOCK; goto end_wait; } @@ -1893,8 +1981,10 @@ dberr_t lock_wait(que_thr_t *thr) { /* trx->lock.was_chosen_as_deadlock_victim can be changed before lock_sys.wait_mutex is acquired, so let's check it once more. */ - trx->error_state= - trx->lock.was_chosen_as_deadlock_victim ? DB_DEADLOCK : DB_SUCCESS; + if (trx->lock.was_chosen_as_deadlock_victim) + trx->error_state= DB_DEADLOCK; + else if (trx->error_state == DB_LOCK_WAIT) + trx->error_state= DB_SUCCESS; goto end_wait; } if (row_lock_wait) @@ -1902,28 +1992,54 @@ dberr_t lock_wait(que_thr_t *thr) #ifdef HAVE_REPLICATION if (rpl) - lock_wait_rpl_report(trx); + wait_lock= lock_wait_rpl_report(trx); #endif - if (trx->error_state != DB_SUCCESS) - goto check_trx_error; + switch (trx->error_state) { + case DB_SUCCESS: + break; + case DB_LOCK_WAIT: + trx->error_state= DB_SUCCESS; + break; + default: +#ifdef UNIV_DEBUG + ut_ad("invalid state" == 0); + break; + case DB_DEADLOCK: + case DB_INTERRUPTED: +#endif + goto end_loop; + } - while (trx->lock.wait_lock) + while (wait_lock) { + int err; + ut_ad(trx->lock.wait_lock); + DEBUG_SYNC_C("lock_wait_before_suspend"); if (no_timeout) + { my_cond_wait(&trx->lock.cond, &lock_sys.wait_mutex.m_mutex); + err= 0; + } else err= my_cond_timedwait(&trx->lock.cond, &lock_sys.wait_mutex.m_mutex, &abstime); -check_trx_error: + + wait_lock= trx->lock.wait_lock; + switch (trx->error_state) { case DB_DEADLOCK: case DB_INTERRUPTED: break; +#ifdef UNIV_DEBUG + case DB_LOCK_WAIT_TIMEOUT: + case DB_LOCK_WAIT: + ut_ad("invalid state" == 0); + break; +#endif default: - ut_ad(trx->error_state != DB_LOCK_WAIT_TIMEOUT); /* Dictionary transactions must ignore KILL, because they could be executed as part of a multi-transaction DDL operation, such as rollback_inplace_alter_table() or ha_innobase::delete_table(). */ @@ -1945,13 +2061,16 @@ dberr_t lock_wait(que_thr_t *thr) break; } +end_loop: if (row_lock_wait) lock_sys.wait_resume(trx->mysql_thd, suspend_time, my_hrtime_coarse()); - /* Cache trx->lock.wait_lock to avoid unnecessary atomic variable load */ - if (lock_t *lock= trx->lock.wait_lock) + ut_ad(!wait_lock == !trx->lock.wait_lock); + + if (wait_lock) { - lock_sys_t::cancel(trx, lock); + abort_wait: + lock_sys_t::cancel(trx, wait_lock); lock_sys.deadlock_check(); } @@ -1967,6 +2086,18 @@ dberr_t lock_wait(que_thr_t *thr) }); thd_wait_end(trx->mysql_thd); +#ifdef UNIV_DEBUG + switch (trx->error_state) { + case DB_SUCCESS: + case DB_DEADLOCK: + case DB_INTERRUPTED: + case DB_LOCK_WAIT_TIMEOUT: + break; + default: + ut_ad("invalid state" == 0); + } +#endif + return trx->error_state; } @@ -3274,8 +3405,9 @@ lock_rec_store_on_page_infimum( ut_ad(block->page.frame == page_align(rec)); const page_id_t id{block->page.id()}; - ut_d(SCOPE_EXIT( - []() { DEBUG_SYNC_C("lock_rec_store_on_page_infimum_end"); })); +#ifdef ENABLED_DEBUG_SYNC + SCOPE_EXIT([]() { DEBUG_SYNC_C("lock_rec_store_on_page_infimum_end"); }); +#endif LockGuard g{lock_sys.rec_hash, id}; lock_rec_move(g.cell(), *block, id, g.cell(), id, @@ -3860,6 +3992,42 @@ dberr_t lock_sys_tables(trx_t *trx) return err; } +/** Rebuild waiting queue after first_lock for heap_no. The queue is rebuilt +close to the way lock_rec_dequeue_from_page() does it. +@param trx transaction that has set a lock, which caused the queue + rebuild +@param cell rec hash cell of first_lock +@param first_lock the lock after which waiting queue will be rebuilt +@param heap_no heap no of the record for which waiting queue to rebuild */ +static void lock_rec_rebuild_waiting_queue( +#if defined(UNIV_DEBUG) || !defined(DBUG_OFF) + trx_t *trx, +#endif /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ + hash_cell_t &cell, lock_t *first_lock, ulint heap_no) +{ + lock_sys.assert_locked(cell); + + for (lock_t *lock= first_lock; lock != NULL; + lock= lock_rec_get_next(heap_no, lock)) + { + if (!lock->is_waiting()) + continue; + mysql_mutex_lock(&lock_sys.wait_mutex); + ut_ad(lock->trx->lock.wait_trx); + ut_ad(lock->trx->lock.wait_lock); + + if (const lock_t *c= lock_rec_has_to_wait_in_queue(cell, lock)) + lock->trx->lock.wait_trx= c->trx; + else + { + /* Grant the lock */ + ut_ad(trx != lock->trx); + lock_grant(lock); + } + mysql_mutex_unlock(&lock_sys.wait_mutex); + } +} + /*=========================== LOCK RELEASE ==============================*/ /*************************************************************//** @@ -3923,26 +4091,11 @@ lock_rec_unlock( } /* Check if we can now grant waiting lock requests */ - - for (lock = first_lock; lock != NULL; - lock = lock_rec_get_next(heap_no, lock)) { - if (!lock->is_waiting()) { - continue; - } - mysql_mutex_lock(&lock_sys.wait_mutex); - ut_ad(lock->trx->lock.wait_trx); - ut_ad(lock->trx->lock.wait_lock); - - if (const lock_t* c = lock_rec_has_to_wait_in_queue(g.cell(), - lock)) { - lock->trx->lock.wait_trx = c->trx; - } else { - /* Grant the lock */ - ut_ad(trx != lock->trx); - lock_grant(lock); - } - mysql_mutex_unlock(&lock_sys.wait_mutex); - } + lock_rec_rebuild_waiting_queue( +#if defined(UNIV_DEBUG) || !defined(DBUG_OFF) + trx, +#endif /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ + g.cell(), first_lock, heap_no); } /** Release the explicit locks of a committing transaction, @@ -4136,6 +4289,30 @@ void lock_release_on_drop(trx_t *trx) } } +/** Reset lock bit for supremum and rebuild waiting queue. +@param cell rec hash cell of in_lock +@param lock the lock with supemum bit set */ +static void lock_rec_unlock_supremum(hash_cell_t &cell, lock_t *lock) +{ + ut_ad(lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)); +#ifdef SAFE_MUTEX + ut_ad(!mysql_mutex_is_owner(&lock_sys.wait_mutex)); +#endif /* SAFE_MUTEX */ + ut_ad(!lock->is_table()); + ut_ad(lock_sys.is_writer() || lock->trx->mutex_is_owner()); + + lock_rec_reset_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM); + + lock_t *first_lock= lock_sys_t::get_first( + cell, lock->un_member.rec_lock.page_id, PAGE_HEAP_NO_SUPREMUM); + + lock_rec_rebuild_waiting_queue( +#if defined(UNIV_DEBUG) || !defined(DBUG_OFF) + lock->trx, +#endif /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ + cell, first_lock, PAGE_HEAP_NO_SUPREMUM); +} + /** Release non-exclusive locks on XA PREPARE, and wake up possible other transactions waiting because of these locks. @param trx transaction in XA PREPARE state @@ -4167,20 +4344,20 @@ static bool lock_release_on_prepare_try(trx_t *trx) if (!lock->is_table()) { ut_ad(!lock->index->table->is_temporary()); - if (lock->mode() == LOCK_X && !lock->is_gap()) { - ut_ad(lock->trx->isolation_level > TRX_ISO_READ_COMMITTED || - /* Insert-intention lock is valid for supremum for isolation - level > TRX_ISO_READ_COMMITTED */ - lock->mode() == LOCK_X || - !lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)); + bool supremum_bit = lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM); + bool rec_granted_exclusive_not_gap = + lock->is_rec_granted_exclusive_not_gap(); + if (!supremum_bit && rec_granted_exclusive_not_gap) continue; - } auto &lock_hash= lock_sys.hash_get(lock->type_mode); auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold()); auto latch= lock_sys_t::hash_table::latch(cell); if (latch->try_acquire()) { - lock_rec_dequeue_from_page(lock, false); + if (!rec_granted_exclusive_not_gap) + lock_rec_dequeue_from_page(lock, false); + else if (supremum_bit) + lock_rec_unlock_supremum(*cell, lock); latch->release(); } else @@ -4220,7 +4397,7 @@ static bool lock_release_on_prepare_try(trx_t *trx) and release possible other transactions waiting because of these locks. */ void lock_release_on_prepare(trx_t *trx) { - auto _ = make_scope_exit([trx]() { trx->set_skip_lock_inheritance(); }); + trx->set_skip_lock_inheritance(); for (ulint count= 5; count--; ) if (lock_release_on_prepare_try(trx)) @@ -4237,8 +4414,14 @@ void lock_release_on_prepare(trx_t *trx) if (!lock->is_table()) { ut_ad(!lock->index->table->is_temporary()); - if (lock->mode() != LOCK_X || lock->is_gap()) + if (!lock->is_rec_granted_exclusive_not_gap()) lock_rec_dequeue_from_page(lock, false); + else if (lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)) + { + auto &lock_hash= lock_sys.hash_get(lock->type_mode); + auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold()); + lock_rec_unlock_supremum(*cell, lock); + } else ut_ad(lock->trx->isolation_level > TRX_ISO_READ_COMMITTED || /* Insert-intention lock is valid for supremum for isolation @@ -6002,25 +6185,7 @@ dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) return err; } -/** Cancel a waiting lock request (if any) when killing a transaction */ -void lock_sys_t::cancel(trx_t *trx) -{ - mysql_mutex_lock(&lock_sys.wait_mutex); - /* Cache trx->lock.wait_lock to avoid unnecessary atomic variable load */ - if (lock_t *lock= trx->lock.wait_lock) - { - /* Dictionary transactions must be immune to KILL, because they - may be executed as part of a multi-transaction DDL operation, such - as rollback_inplace_alter_table() or ha_innobase::delete_table(). */ - if (!trx->dict_operation) - { - trx->error_state= DB_INTERRUPTED; - cancel(trx, lock); - } - } - lock_sys.deadlock_check(); - mysql_mutex_unlock(&lock_sys.wait_mutex); -} +template dberr_t lock_sys_t::cancel(trx_t *, lock_t *); /*********************************************************************//** Unlocks AUTO_INC type locks that were possibly reserved by a trx. This @@ -6507,30 +6672,40 @@ and less modified rows. Bit 0 is used to prefer orig_trx in case of a tie. /** Check if a lock request results in a deadlock. Resolve a deadlock by choosing a transaction that will be rolled back. -@param trx transaction requesting a lock -@return whether trx must report DB_DEADLOCK */ -static bool Deadlock::check_and_resolve(trx_t *trx) +@param trx transaction requesting a lock +@param wait_lock the lock being requested +@return the lock that trx is or was waiting for +@retval nullptr if the lock wait was resolved +@retval -1 if trx must report DB_DEADLOCK */ +static lock_t *Deadlock::check_and_resolve(trx_t *trx, lock_t *wait_lock) { mysql_mutex_assert_owner(&lock_sys.wait_mutex); ut_ad(!trx->mutex_is_owner()); ut_ad(trx->state == TRX_STATE_ACTIVE); ut_ad(!srv_read_only_mode); + ut_ad(wait_lock); if (!innodb_deadlock_detect) - return false; + return wait_lock; - if (UNIV_LIKELY_NULL(find_cycle(trx)) && report(trx, true) == trx) - return true; + if (UNIV_LIKELY_NULL(find_cycle(trx))) + { + if (report(trx, true) == trx) + return reinterpret_cast(-1); + /* Because report() released and reacquired lock_sys.wait_mutex, + another thread may have cleared trx->lock.wait_lock meanwhile. */ + wait_lock= trx->lock.wait_lock; + } if (UNIV_LIKELY(!trx->lock.was_chosen_as_deadlock_victim)) - return false; + return wait_lock; - if (lock_t *wait_lock= trx->lock.wait_lock) + if (wait_lock) lock_sys_t::cancel(trx, wait_lock); lock_sys.deadlock_check(); - return true; + return reinterpret_cast(-1); } /** Check for deadlocks while holding only lock_sys.wait_mutex. */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 160577504005c..635054870b71f 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2009, Google Inc. Copyright (c) 2014, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. @@ -94,15 +87,15 @@ void log_t::set_capacity() log_sys.max_checkpoint_age = margin; } -/** Initialize the redo log subsystem. */ -void log_t::create() +#ifdef HAVE_PMEM +void log_t::create_low() +#else +bool log_t::create() +#endif { ut_ad(this == &log_sys); ut_ad(!is_initialised()); - latch.SRW_LOCK_INIT(log_latch_key); - init_lsn_lock(); - /* LSN 0 and 1 are reserved; @see buf_page_t::oldest_modification_ */ lsn.store(FIRST_LSN, std::memory_order_relaxed); flushed_to_disk_lsn.store(FIRST_LSN, std::memory_order_relaxed); @@ -110,9 +103,23 @@ void log_t::create() #ifndef HAVE_PMEM buf= static_cast(ut_malloc_dontdump(buf_size, PSI_INSTRUMENT_ME)); - TRASH_ALLOC(buf, buf_size); + if (!buf) + { + alloc_fail: + sql_print_error("InnoDB: Cannot allocate memory;" + " too large innodb_log_buffer_size?"); + return false; + } flush_buf= static_cast(ut_malloc_dontdump(buf_size, PSI_INSTRUMENT_ME)); + if (!flush_buf) + { + ut_free_dodump(buf, buf_size); + buf= nullptr; + goto alloc_fail; + } + + TRASH_ALLOC(buf, buf_size); TRASH_ALLOC(flush_buf, buf_size); checkpoint_buf= static_cast(aligned_malloc(4096, 4096)); memset_aligned<4096>(checkpoint_buf, 0, 4096); @@ -122,6 +129,9 @@ void log_t::create() ut_ad(!flush_buf); #endif + latch.SRW_LOCK_INIT(log_latch_key); + init_lsn_lock(); + max_buf_free= buf_size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; set_check_flush_or_checkpoint(); @@ -135,6 +145,9 @@ void log_t::create() buf_free= 0; ut_ad(is_initialised()); +#ifndef HAVE_PMEM + return true; +#endif } dberr_t log_file_t::close() noexcept @@ -148,6 +161,7 @@ dberr_t log_file_t::close() noexcept return DB_SUCCESS; } +__attribute__((warn_unused_result)) dberr_t log_file_t::read(os_offset_t offset, span buf) noexcept { ut_ad(is_opened()); @@ -200,7 +214,11 @@ static void *log_mmap(os_file_t file, os_offset_t size) } #endif -void log_t::attach(log_file_t file, os_offset_t size) +#ifdef HAVE_PMEM +bool log_t::attach(log_file_t file, os_offset_t size) +#else +void log_t::attach_low(log_file_t file, os_offset_t size) +#endif { log= file; ut_ad(!size || size >= START_OFFSET + SIZE_OF_FILE_CHECKPOINT); @@ -217,18 +235,33 @@ void log_t::attach(log_file_t file, os_offset_t size) log.close(); mprotect(ptr, size_t(size), PROT_READ); buf= static_cast(ptr); -#if defined __linux__ || defined _WIN32 +# if defined __linux__ || defined _WIN32 set_block_size(CPU_LEVEL1_DCACHE_LINESIZE); -#endif +# endif log_maybe_unbuffered= true; log_buffered= false; - return; + return true; } } buf= static_cast(ut_malloc_dontdump(buf_size, PSI_INSTRUMENT_ME)); - TRASH_ALLOC(buf, buf_size); + if (!buf) + { + alloc_fail: + max_buf_free= 0; + sql_print_error("InnoDB: Cannot allocate memory;" + " too large innodb_log_buffer_size?"); + return false; + } flush_buf= static_cast(ut_malloc_dontdump(buf_size, PSI_INSTRUMENT_ME)); + if (!flush_buf) + { + ut_free_dodump(buf, buf_size); + buf= nullptr; + goto alloc_fail; + } + + TRASH_ALLOC(buf, buf_size); TRASH_ALLOC(flush_buf, buf_size); #endif @@ -243,6 +276,7 @@ void log_t::attach(log_file_t file, os_offset_t size) #ifdef HAVE_PMEM checkpoint_buf= static_cast(aligned_malloc(block_size, block_size)); memset_aligned<64>(checkpoint_buf, 0, block_size); + return true; #endif } diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 0aa71c753d5cc..3795057217724 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -805,12 +805,8 @@ static struct const std::string &name, uint32_t flags, fil_space_crypt_t *crypt_data, uint32_t size) { - if (crypt_data && !crypt_data->is_key_found()) - { - crypt_data->~fil_space_crypt_t(); - ut_free(crypt_data); + if (crypt_data && !fil_crypt_check(crypt_data, name.c_str())) return nullptr; - } mysql_mutex_lock(&fil_system.mutex); fil_space_t *space= fil_space_t::create(it->first, flags, FIL_TYPE_TABLESPACE, crypt_data); @@ -1109,12 +1105,13 @@ inline void recv_sys_t::trim(const page_id_t page_id, lsn_t lsn) DBUG_VOID_RETURN; } -inline void recv_sys_t::read(os_offset_t total_offset, span buf) +inline dberr_t recv_sys_t::read(os_offset_t total_offset, span buf) { size_t file_idx= static_cast(total_offset / log_sys.file_size); os_offset_t offset= total_offset % log_sys.file_size; - dberr_t err= recv_sys.files[file_idx].read(offset, buf); - ut_a(err == DB_SUCCESS); + return file_idx + ? recv_sys.files[file_idx].read(offset, buf) + : log_sys.log.read(offset, buf); } inline size_t recv_sys_t::files_size() @@ -1273,6 +1270,15 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, } } +void recv_sys_t::close_files() +{ + for (auto &file : files) + if (file.is_opened()) + file.close(); + files.clear(); + files.shrink_to_fit(); +} + /** Clean up after recv_sys_t::create() */ void recv_sys_t::close() { @@ -1509,7 +1515,8 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() if (source_offset < (log_sys.is_pmem() ? log_sys.file_size : 4096)) memcpy_aligned<512>(buf, &log_sys.buf[source_offset & ~511], 512); else - recv_sys.read(source_offset & ~511, {buf, 512}); + if (dberr_t err= recv_sys.read(source_offset & ~511, {buf, 512})) + return err; if (log_block_calc_checksum_format_0(buf) != mach_read_from_4(my_assume_aligned<4>(buf + 508)) && @@ -1548,7 +1555,8 @@ static dberr_t recv_log_recover_10_5(lsn_t lsn_offset) memcpy_aligned<512>(buf, &log_sys.buf[lsn_offset & ~511], 512); else { - recv_sys.read(lsn_offset & ~lsn_t{4095}, {buf, 4096}); + if (dberr_t err= recv_sys.read(lsn_offset & ~lsn_t{4095}, {buf, 4096})) + return err; buf+= lsn_offset & 0xe00; } @@ -1599,13 +1607,17 @@ dberr_t recv_sys_t::find_checkpoint() else if (size < log_t::START_OFFSET + SIZE_OF_FILE_CHECKPOINT) { too_small: - os_file_close(file); sql_print_error("InnoDB: File %.*s is too small", int(path.size()), path.data()); + err_exit: + os_file_close(file); return DB_ERROR; } + else if (!log_sys.attach(file, size)) + goto err_exit; + else + file= OS_FILE_CLOSED; - log_sys.attach(file, size); recv_sys.files.emplace_back(file); for (int i= 1; i < 101; i++) { @@ -3679,16 +3691,24 @@ inline fil_space_t *fil_system_t::find(const char *path) const static void log_sort_flush_list() { /* Ensure that oldest_modification() cannot change during std::sort() */ - for (;;) { - os_aio_wait_until_no_pending_writes(false); - mysql_mutex_lock(&buf_pool.flush_list_mutex); - if (buf_pool.flush_list_active()) - my_cond_wait(&buf_pool.done_flush_list, - &buf_pool.flush_list_mutex.m_mutex); - else if (!os_aio_pending_writes()) - break; - mysql_mutex_unlock(&buf_pool.flush_list_mutex); + const double pct_lwm= srv_max_dirty_pages_pct_lwm; + /* Disable "idle" flushing in order to minimize the wait time below. */ + srv_max_dirty_pages_pct_lwm= 0.0; + + for (;;) + { + os_aio_wait_until_no_pending_writes(false); + mysql_mutex_lock(&buf_pool.flush_list_mutex); + if (buf_pool.page_cleaner_active()) + my_cond_wait(&buf_pool.done_flush_list, + &buf_pool.flush_list_mutex.m_mutex); + else if (!os_aio_pending_writes()) + break; + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + } + + srv_max_dirty_pages_pct_lwm= pct_lwm; } const size_t size= UT_LIST_GET_LEN(buf_pool.flush_list); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index de20bc68ed3df..a84218a68d9f5 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -31,6 +31,8 @@ Created 11/26/1995 Heikki Tuuri #include "log0crypt.h" #ifdef BTR_CUR_HASH_ADAPT # include "btr0sea.h" +#else +# include "btr0cur.h" #endif #include "srv0start.h" #include "log.h" @@ -1624,62 +1626,60 @@ void mtr_t::free(const fil_space_t &space, uint32_t offset) ut_ad(is_named_space(&space)); ut_ad(!m_freed_space || m_freed_space == &space); - if (is_logged()) - { - buf_block_t *freed= nullptr; - const page_id_t id{space.id, offset}; + buf_block_t *freed= nullptr; + const page_id_t id{space.id, offset}; - for (auto it= m_memo.end(); it != m_memo.begin(); ) + for (auto it= m_memo.end(); it != m_memo.begin(); ) + { + it--; + next: + mtr_memo_slot_t &slot= *it; + buf_block_t *block= static_cast(slot.object); + ut_ad(block); + if (block == freed) { - it--; - next: - mtr_memo_slot_t &slot= *it; - buf_block_t *block= static_cast(slot.object); - ut_ad(block); - if (block == freed) + if (slot.type & (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX)) + slot.type= MTR_MEMO_PAGE_X_FIX; + else { - if (slot.type & (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX)) - slot.type= MTR_MEMO_PAGE_X_FIX; - else - { - ut_ad(slot.type == MTR_MEMO_BUF_FIX); - block->page.unfix(); - m_memo.erase(it, it + 1); - goto next; - } + ut_ad(slot.type == MTR_MEMO_BUF_FIX); + block->page.unfix(); + m_memo.erase(it, it + 1); + goto next; } - else if (slot.type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX) && + } + else if (slot.type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX) && block->page.id() == id) + { + ut_ad(!block->page.is_freed()); + ut_ad(!freed); + freed= block; + if (!(slot.type & MTR_MEMO_PAGE_X_FIX)) { - ut_ad(!block->page.is_freed()); - ut_ad(!freed); - freed= block; - if (!(slot.type & MTR_MEMO_PAGE_X_FIX)) - { - ut_d(bool upgraded=) block->page.lock.x_lock_upgraded(); - ut_ad(upgraded); - } - if (id.space() >= SRV_TMP_SPACE_ID) - { - block->page.set_temp_modified(); - slot.type= MTR_MEMO_PAGE_X_FIX; - } - else - { - slot.type= MTR_MEMO_PAGE_X_MODIFY; - if (!m_made_dirty) - m_made_dirty= block->page.oldest_modification() <= 1; - } + ut_d(bool upgraded=) block->page.lock.x_lock_upgraded(); + ut_ad(upgraded); + } + if (id.space() >= SRV_TMP_SPACE_ID) + { + block->page.set_temp_modified(); + slot.type= MTR_MEMO_PAGE_X_FIX; + } + else + { + slot.type= MTR_MEMO_PAGE_X_MODIFY; + if (!m_made_dirty) + m_made_dirty= block->page.oldest_modification() <= 1; + } #ifdef BTR_CUR_HASH_ADAPT - if (block->index) - btr_search_drop_page_hash_index(block, false); + if (block->index) + btr_search_drop_page_hash_index(block, false); #endif /* BTR_CUR_HASH_ADAPT */ - block->page.set_freed(block->page.state()); - } + block->page.set_freed(block->page.state()); } + } + if (is_logged()) m_log.close(log_write(id, nullptr)); - } } void small_vector_base::grow_by_1(void *small, size_t element_size) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 1e0d5fad13fd2..46f7ceecf6534 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4037,36 +4037,40 @@ static bool is_volume_on_ssd(const char *volume_mount_point) } #include -static bool is_file_on_ssd(char *file_path) +static bool is_path_on_ssd(char *file_path) { - /* Cache of volume_path => volume_info, protected by rwlock.*/ - static std::unordered_map cache; - static SRWLOCK lock= SRWLOCK_INIT; - /* Preset result, in case something fails, e.g we're on network drive.*/ char volume_path[MAX_PATH]; if (!GetVolumePathName(file_path, volume_path, array_elements(volume_path))) return false; + return is_volume_on_ssd(volume_path); +} + +static bool is_file_on_ssd(HANDLE handle, char *file_path) +{ + ULONGLONG volume_serial_number; + FILE_ID_INFO info; + if(!GetFileInformationByHandleEx(handle, FileIdInfo, &info, sizeof(info))) + return false; + volume_serial_number= info.VolumeSerialNumber; - /* Try cached volume info first.*/ - std::string volume_path_str(volume_path); + static std::unordered_map cache; + static SRWLOCK lock= SRWLOCK_INIT; bool found; bool result; AcquireSRWLockShared(&lock); - auto e= cache.find(volume_path_str); + auto e= cache.find(volume_serial_number); if ((found= e != cache.end())) result= e->second; ReleaseSRWLockShared(&lock); - - if (found) - return result; - - result= is_volume_on_ssd(volume_path); - - /* Update cache */ - AcquireSRWLockExclusive(&lock); - cache[volume_path_str]= result; - ReleaseSRWLockExclusive(&lock); + if (!found) + { + result= is_path_on_ssd(file_path); + /* Update cache */ + AcquireSRWLockExclusive(&lock); + cache[volume_serial_number]= result; + ReleaseSRWLockExclusive(&lock); + } return result; } @@ -4092,7 +4096,7 @@ void fil_node_t::find_metadata(os_file_t file punch_hole= IF_WIN(, !create ||) os_is_sparse_file_supported(file); #ifdef _WIN32 - on_ssd= is_file_on_ssd(name); + on_ssd= is_file_on_ssd(file, name); FILE_STORAGE_INFO info; if (GetFileInformationByHandleEx(file, FileStorageInfo, &info, sizeof info)) block_size= info.PhysicalBytesPerSectorForAtomicity; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 40fd8c75be228..3ff46bf76fe94 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -29,6 +29,7 @@ Created 2012-02-08 by Sunny Bains. #ifdef BTR_CUR_HASH_ADAPT # include "btr0sea.h" #endif +#include "buf0flu.h" #include "que0que.h" #include "dict0boot.h" #include "dict0load.h" diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 010b347c003c8..cb11deeb6782d 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -2131,6 +2131,11 @@ row_log_table_apply_op( *error = DB_SUCCESS; + /* 3 = 1 (op type) + 1 (extra_size) + at least 1 byte payload */ + if (mrec + 3 >= mrec_end) { + return(NULL); + } + const bool is_instant = log->is_instant(dup->index); const mrec_t* const mrec_start = mrec; @@ -2178,11 +2183,6 @@ row_log_table_apply_op( break; case ROW_T_DELETE: - /* 1 (extra_size) + at least 1 (payload) */ - if (mrec + 2 >= mrec_end) { - return(NULL); - } - extra_size = *mrec++; ut_ad(mrec < mrec_end); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 89599c5b69fe5..f63eb0ec63ba1 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -31,6 +31,7 @@ Created 9/17/2000 Heikki Tuuri #include #include "row0mysql.h" +#include "buf0flu.h" #include "btr0sea.h" #include "dict0boot.h" #include "dict0crea.h" diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index cc9a45ddc696b..c4198a332a063 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -566,13 +566,9 @@ bool row_purge_del_mark(purge_node_t *node) do { - const auto type= node->index->type; - if (type & (DICT_FTS | DICT_CORRUPT)) + if (node->index->type & (DICT_FTS | DICT_CORRUPT)) continue; - if (node->index->online_status > ONLINE_INDEX_CREATION) - continue; - if (UNIV_UNLIKELY(DICT_VIRTUAL & type) && !node->index->is_committed() && - node->index->has_new_v_col()) + if (!node->index->is_committed()) continue; dtuple_t* entry= row_build_index_entry_low(node->row, nullptr, node->index, heap, @@ -721,20 +717,11 @@ row_purge_upd_exist_or_extern_func( heap = mem_heap_create(1024); do { - const auto type = node->index->type; - - if (type & (DICT_FTS | DICT_CORRUPT)) { - continue; - } - - if (UNIV_UNLIKELY(DICT_VIRTUAL & type) - && !node->index->is_committed() - && node->index->has_new_v_col()) { + if (node->index->type & (DICT_FTS | DICT_CORRUPT)) { continue; } - if (node->index->online_status - > ONLINE_INDEX_CREATION) { + if (!node->index->is_committed()) { continue; } diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 5b0676a3e0d30..f28953f5bb6c5 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -26,6 +26,7 @@ Created 2012-02-08 by Sunny Bains. #include "row0quiesce.h" #include "row0mysql.h" +#include "buf0flu.h" #include "srv0start.h" #include "trx0purge.h" diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index d4cb5068ca2cf..ffafd0437cc7d 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1,15 +1,8 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2015, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - 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. diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 9b11b7fbc3f46..c3acf325f5c16 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -734,9 +734,16 @@ row_vers_vc_matches_cluster( && (!compare[v_col->v_pos])) { if (ind_field->prefix_len != 0 - && !dfield_is_null(field2) - && field2->len > ind_field->prefix_len) { - field2->len = ind_field->prefix_len; + && !dfield_is_null(field2)) { + field2->len = unsigned( + dtype_get_at_most_n_mbchars( + field2->type.prtype, + field2->type.mbminlen, + field2->type.mbmaxlen, + ind_field->prefix_len, + field2->len, + static_cast + (field2->data))); } /* The index field mismatch */ diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index c818a555e2891..c30ffeeb297cf 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -25,7 +25,7 @@ Database monitor counter interfaces Created 12/9/2009 Jimmy Yang *******************************************************/ -#include "buf0buf.h" +#include "buf0flu.h" #include "dict0mem.h" #include "lock0lock.h" #include "mach0data.h" diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 5607237484a1a..c71222a7be71d 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1124,8 +1124,6 @@ static tpool::timer *purge_coordinator_timer; /** Wake up the purge threads if there is work to do. */ void srv_wake_purge_thread_if_not_active() { - ut_ad(!srv_read_only_mode); - if (purge_sys.enabled() && !purge_sys.paused() && (srv_undo_log_truncate || trx_sys.history_exists()) && ++purge_state.m_running == 1) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index d14754df0324a..0347a1379e0fb 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1,16 +1,9 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. -Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2013, 2023, MariaDB Corporation. -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are gratefully acknowledged and are described briefly in the InnoDB @@ -189,10 +182,16 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn) delete_log_files(); ut_ad(!os_aio_pending_reads()); - ut_ad(!os_aio_pending_writes()); ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex)); ut_ad(!buf_pool.get_oldest_modification(0)); ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex)); + /* os_aio_pending_writes() may hold here if some + write_io_callback() did not release the slot yet. However, + the page write itself must have completed, because the + buf_pool.flush_list is empty. In debug builds, we wait for + this to happen, hoping to get a hung process if this + assumption does not hold. */ + ut_d(os_aio_wait_until_no_pending_writes(false)); log_sys.latch.wr_lock(SRW_LOCK_CALL); log_sys.set_capacity(); @@ -215,14 +214,17 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn) ret = os_file_set_size(logfile0.c_str(), file, srv_log_file_size); if (!ret) { - os_file_close_func(file); ib::error() << "Cannot set log file " << logfile0 << " size to " << ib::bytes_iec{srv_log_file_size}; +close_and_exit: + os_file_close_func(file); goto err_exit; } log_sys.set_latest_format(srv_encrypt_log); - log_sys.attach(file, srv_log_file_size); + if (!log_sys.attach(file, srv_log_file_size)) { + goto close_and_exit; + } if (!fil_system.sys_space->open(create_new_db)) { goto err_exit; } @@ -1115,10 +1117,15 @@ ATTRIBUTE_COLD static dberr_t srv_log_rebuild() log checkpoint at the end of create_log_file(). */ ut_d(recv_no_log_write= true); ut_ad(!os_aio_pending_reads()); - ut_ad(!os_aio_pending_writes()); ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex)); ut_ad(!buf_pool.get_oldest_modification(0)); ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex)); + /* os_aio_pending_writes() may hold here if some write_io_callback() + did not release the slot yet. However, the page write itself must + have completed, because the buf_pool.flush_list is empty. In debug + builds, we wait for this to happen, hoping to get a hung process if + this assumption does not hold. */ + ut_d(os_aio_wait_until_no_pending_writes(false)); /* Close the redo log file, so that we can replace it */ log_sys.close_file(); @@ -1346,7 +1353,10 @@ dberr_t srv_start(bool create_new_db) } #endif /* UNIV_DEBUG */ - log_sys.create(); + if (!log_sys.create()) { + return srv_init_abort(DB_ERROR); + } + recv_sys.create(); lock_sys.create(srv_lock_table_size); @@ -1571,12 +1581,19 @@ dberr_t srv_start(bool create_new_db) if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { /* Apply the hashed log records to the respective file pages, for the last batch of - recv_group_scan_log_recs(). */ + recv_group_scan_log_recs(). + Since it may generate huge batch of threadpool tasks, + for read io task group, scale down thread creation rate + by temporarily restricting tpool concurrency. + */ + srv_thread_pool->set_concurrency(srv_n_read_io_threads); mysql_mutex_lock(&recv_sys.mutex); recv_sys.apply(true); mysql_mutex_unlock(&recv_sys.mutex); + srv_thread_pool->set_concurrency(); + if (recv_sys.is_corrupt_log() || recv_sys.is_corrupt_fs()) { return(srv_init_abort(DB_CORRUPTION)); diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index 05445f1a68c6c..e41451d80035b 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -117,8 +117,13 @@ bool transactional_lock_enabled() __attribute__((target("htm"),hot)) bool xtest() { +# ifdef __s390x__ + return have_transactional_memory && + __builtin_tx_nesting_depth() > 0; +# else return have_transactional_memory && _HTM_STATE (__builtin_ttest ()) == _HTM_TRANSACTIONAL; +# endif } # endif #endif diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index d601f30eb04eb..fa447c5ed55e5 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -267,12 +267,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) trx_ulogf_t *undo_header= undo_page->page.frame + undo->hdr_offset; ut_ad(rseg->needs_purge > trx->id); - - if (rseg->last_page_no == FIL_NULL) - { - rseg->last_page_no= undo->hdr_page_no; - rseg->set_last_commit(undo->hdr_offset, trx->rw_trx_hash_element->no); - } + ut_ad(rseg->last_page_no != FIL_NULL); rseg->history_size++; @@ -311,11 +306,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) undo= nullptr; - /* After the purge thread has been given permission to exit, - we may roll back transactions (trx->undo_no==0) - in THD::cleanup() invoked from unlink_thd() in fast shutdown, - or in trx_rollback_recovered() in slow shutdown. - + /* Before any transaction-generating background threads or the purge have been started, we can start transactions in row_merge_drop_temp_indexes(), and roll back recovered transactions. @@ -327,12 +318,10 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) During fast shutdown, we may also continue to execute user transactions. */ - ut_ad(srv_undo_sources || trx->undo_no == 0 || + ut_ad(srv_undo_sources || srv_fast_shutdown || (!purge_sys.enabled() && (srv_is_being_started || - trx_rollback_is_active || - srv_force_recovery >= SRV_FORCE_NO_BACKGROUND)) || - srv_fast_shutdown); + srv_force_recovery >= SRV_FORCE_NO_BACKGROUND))); #ifdef WITH_WSREP if (wsrep_is_wsrep_xid(&trx->xid)) @@ -379,7 +368,6 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr) This does not matter when using multiple innodb_undo_tablespaces; innodb_undo_log_truncate=ON will be able to reclaim the space. */ - log_free_check(); mtr.start(); block->page.lock.x_lock(); ut_ad(block->page.id() == id); @@ -402,7 +390,6 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, fil_addr_t hdr_addr; mtr_t mtr; - log_free_check(); mtr.start(); dberr_t err; @@ -504,7 +491,6 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, mtr.commit(); ut_ad(rseg.history_size > 0); rseg.history_size--; - log_free_check(); mtr.start(); rseg_hdr->page.lock.x_lock(); ut_ad(rseg_hdr->page.id() == rseg.page_id()); @@ -580,6 +566,7 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() if (rseg.space) { ut_ad(rseg.is_persistent()); + log_free_check(); rseg.latch.wr_lock(SRW_LOCK_CALL); if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head, @@ -789,7 +776,9 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() continue; ut_ad(!rseg.is_referenced()); - ut_ad(!head.trx_no || rseg.needs_purge <= head.trx_no); + /* We may actually have rseg.needs_purge > head.trx_no here + if trx_t::commit_empty() had been executed in the past, + possibly before this server had been started up. */ buf_block_t *rblock= trx_rseg_header_create(&space, &rseg - trx_sys.rseg_array, diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 0f85aec540f55..f56f0d5ce6ff4 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -419,7 +419,6 @@ void trx_t::free() MEM_NOACCESS(&is_registered, sizeof is_registered); MEM_NOACCESS(&active_commit_ordered, sizeof active_commit_ordered); MEM_NOACCESS(&flush_log_later, sizeof flush_log_later); - MEM_NOACCESS(&must_flush_log_later, sizeof must_flush_log_later); MEM_NOACCESS(&duplicates, sizeof duplicates); MEM_NOACCESS(&dict_operation, sizeof dict_operation); MEM_NOACCESS(&dict_operation_lock_mode, sizeof dict_operation_lock_mode); @@ -973,93 +972,193 @@ trx_start_low( ut_a(trx->error_state == DB_SUCCESS); } -/** Set the serialisation number for a persistent committed transaction. -@param[in,out] trx committed transaction with persistent changes */ -static -void -trx_serialise(trx_t* trx) -{ - trx_rseg_t *rseg = trx->rsegs.m_redo.rseg; - ut_ad(rseg); - - if (rseg->last_page_no == FIL_NULL) { - mysql_mutex_lock(&purge_sys.pq_mutex); - } - - trx_sys.assign_new_trx_no(trx); - - /* If the rollback segment is not empty then the - new trx_t::no can't be less than any trx_t::no - already in the rollback segment. User threads only - produce events when a rollback segment is empty. */ - if (rseg->last_page_no == FIL_NULL) { - purge_sys.purge_queue.push(TrxUndoRsegs(trx->rw_trx_hash_element->no, - *rseg)); - mysql_mutex_unlock(&purge_sys.pq_mutex); - } -} - -/****************************************************************//** -Assign the transaction its history serialisation number and write the -update UNDO log record to the assigned rollback segment. */ -static -void -trx_write_serialisation_history( -/*============================*/ - trx_t* trx, /*!< in/out: transaction */ - mtr_t* mtr) /*!< in/out: mini-transaction */ +/** Release an empty undo log that was associated with a transaction. */ +ATTRIBUTE_COLD +void trx_t::commit_empty(mtr_t *mtr) { - /* Change the undo log segment states from TRX_UNDO_ACTIVE to some - other state: these modifications to the file data structure define - the transaction as committed in the file based domain, at the - serialization point of the log sequence number lsn obtained below. */ + trx_rseg_t *rseg= rsegs.m_redo.rseg; + trx_undo_t *&undo= rsegs.m_redo.undo; - /* We have to hold the rseg mutex because update log headers have - to be put to the history list in the (serialisation) order of the - UNDO trx number. This is required for the purge in-memory data - structures too. */ + ut_ad(undo->state == TRX_UNDO_ACTIVE || undo->state == TRX_UNDO_PREPARED); + ut_ad(undo->size == 1); - if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) { - /* Undo log for temporary tables is discarded at transaction - commit. There is no purge for temporary tables, and also no - MVCC, because they are private to a session. */ - - mtr_t temp_mtr; - temp_mtr.start(); - temp_mtr.set_log_mode(MTR_LOG_NO_REDO); - buf_block_t* block= buf_page_get(page_id_t(SRV_TMP_SPACE_ID, - undo->hdr_page_no), - 0, RW_X_LATCH, mtr); - ut_a(block); - temp_mtr.write<2>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE - + block->page.frame, TRX_UNDO_TO_PURGE); - undo->state = TRX_UNDO_TO_PURGE; - temp_mtr.commit(); - } + if (buf_block_t *u= + buf_page_get(page_id_t(rseg->space->id, undo->hdr_page_no), 0, + RW_X_LATCH, mtr)) + { + ut_d(const uint16_t state= + mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + u->page.frame)); + ut_ad(state == undo->state || state == TRX_UNDO_ACTIVE); + static_assert(TRX_UNDO_PAGE_START + 2 == TRX_UNDO_PAGE_FREE, + "compatibility"); + ut_ad(!memcmp(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START + u->page.frame, + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + u->page.frame, 2)); + ut_ad(mach_read_from_4(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + FLST_PREV + + FIL_ADDR_PAGE + u->page.frame) == FIL_NULL); + ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + FLST_PREV + + FIL_ADDR_BYTE + u->page.frame) == 0); + ut_ad(!memcmp(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + FLST_PREV + + u->page.frame, + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + FLST_NEXT + + u->page.frame, FIL_ADDR_SIZE)); + + /* Delete the last undo log header, which must be for this transaction. + + An undo segment can be reused (TRX_UNDO_CACHED) only if it + comprises of one page and that single page contains enough space + for the undo log header of a subsequent transaction. See + trx_purge_add_undo_to_history(), which is executed when committing + a nonempty transaction. + + If we simply changed the undo page state to TRX_UNDO_CACHED, + then trx_undo_reuse_cached() could run out of space. We will + release the space consumed by our empty undo log to avoid that. */ + for (byte *last= &u->page.frame[TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE], + *prev= nullptr;;) + { + /* TRX_UNDO_PREV_LOG is only being read in debug assertions, and + written in trx_undo_header_create(). To remain compatible with + possibly corrupted old data files, we will not read the field + TRX_UNDO_PREV_LOG but instead rely on TRX_UNDO_NEXT_LOG. */ + ut_ad(mach_read_from_2(TRX_UNDO_PREV_LOG + last) == + (reinterpret_cast(prev) & (srv_page_size - 1))); + + if (uint16_t next= mach_read_from_2(TRX_UNDO_NEXT_LOG + last)) + { + ut_ad(ulint{next} + TRX_UNDO_LOG_XA_HDR_SIZE < srv_page_size - 100); + ut_ad(&u->page.frame[next] > last); + ut_ad(mach_read_from_2(TRX_UNDO_LOG_START + last) <= next); + prev= last; + last= &u->page.frame[next]; + continue; + } - trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; - if (!rseg) { - ut_ad(!trx->rsegs.m_redo.undo); - return; - } + ut_ad(mach_read_from_8(TRX_UNDO_TRX_ID + last) == id); + ut_ad(!mach_read_from_8(TRX_UNDO_TRX_NO + last)); + ut_ad(!memcmp(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START + u->page.frame, + TRX_UNDO_LOG_START + last, 2)); - trx_undo_t*& undo = trx->rsegs.m_redo.undo; + if (prev) + { + mtr->memcpy(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START + + u->page.frame, prev + TRX_UNDO_LOG_START, 2); + const ulint free= page_offset(last); + mtr->write<2>(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + + u->page.frame, free); + mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + u->page.frame, + TRX_UNDO_CACHED); + mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG + u->page.frame, + page_offset(prev)); + mtr->write<2>(*u, prev + TRX_UNDO_NEXT_LOG, 0U); + mtr->memset(u, free, srv_page_size - FIL_PAGE_DATA_END - free, 0); + + /* We may have updated PAGE_MAX_TRX_ID on secondary index pages + to this->id. Ensure that trx_sys.m_max_trx_id will be recovered + correctly, even though we removed our undo log record along + with the TRX_UNDO_TRX_ID above. */ + + /* Below, we are acquiring rseg_header->page.lock after + u->page.lock (the opposite of trx_purge_add_undo_to_history()). + This is fine, because both functions are holding exclusive + rseg->latch. */ + + if (mach_read_from_8(prev + TRX_UNDO_TRX_NO) >= id); + else if (buf_block_t *rseg_header= rseg->get(mtr, nullptr)) + { + byte *m= TRX_RSEG + TRX_RSEG_MAX_TRX_ID + rseg_header->page.frame; + + do + { + if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT + + rseg_header->page.frame))) + /* This must have been upgraded from before MariaDB 10.3.5. */ + trx_rseg_format_upgrade(rseg_header, mtr); + else if (mach_read_from_8(m) >= id) + continue; + mtr->write<8>(*rseg_header, m, id); + } + while (0); + } + } + else + /* Our undo log header was right after the undo log segment header. + This page should have been created by trx_undo_create(), not + returned by trx_undo_reuse_cached(). + + We retain the dummy empty log in order to remain compatible with + trx_undo_mem_create_at_db_start(). This page will remain available + to trx_undo_reuse_cached(), and it will eventually be freed by + trx_purge_truncate_rseg_history(). */ + mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + u->page.frame, + TRX_UNDO_CACHED); + break; + } + } + else + ut_ad("undo log page was not found" == 0); - ut_ad(!trx->read_only); + UT_LIST_REMOVE(rseg->undo_list, undo); + UT_LIST_ADD_FIRST(rseg->undo_cached, undo); + undo->state= TRX_UNDO_CACHED; + undo= nullptr; - /* Assign the transaction serialisation number and add any - undo log to the purge queue. */ - if (undo) { - rseg->latch.wr_lock(SRW_LOCK_CALL); - ut_ad(undo->rseg == rseg); - trx_serialise(trx); - UT_LIST_REMOVE(rseg->undo_list, undo); - trx_purge_add_undo_to_history(trx, undo, mtr); - MONITOR_INC(MONITOR_TRX_COMMIT_UNDO); - rseg->latch.wr_unlock(); - } + /* We must assign an "end" identifier even though we are not going + to persistently write it anywhere, to make sure that the purge of + history will not be stuck. */ + trx_sys.assign_new_trx_no(this); +} - rseg->release(); +/** Assign the transaction its history serialisation number and write the +UNDO log to the assigned rollback segment. +@param mtr mini-transaction */ +inline void trx_t::write_serialisation_history(mtr_t *mtr) +{ + ut_ad(!read_only); + trx_rseg_t *rseg= rsegs.m_redo.rseg; + trx_undo_t *&undo= rsegs.m_redo.undo; + if (UNIV_LIKELY(undo != nullptr)) + { + MONITOR_INC(MONITOR_TRX_COMMIT_UNDO); + + /* We have to hold exclusive rseg->latch because undo log headers have + to be put to the history list in the (serialisation) order of the + UNDO trx number. This is required for purge_sys too. */ + rseg->latch.wr_lock(SRW_LOCK_CALL); + ut_ad(undo->rseg == rseg); + /* Assign the transaction serialisation number and add any + undo log to the purge queue. */ + if (UNIV_UNLIKELY(!undo_no)) + { + /* The transaction was rolled back. */ + commit_empty(mtr); + goto done; + } + else if (rseg->last_page_no == FIL_NULL) + { + mysql_mutex_lock(&purge_sys.pq_mutex); + trx_sys.assign_new_trx_no(this); + const trx_id_t end{rw_trx_hash_element->no}; + /* end cannot be less than anything in rseg. User threads only + produce events when a rollback segment is empty. */ + purge_sys.purge_queue.push(TrxUndoRsegs{end, *rseg}); + mysql_mutex_unlock(&purge_sys.pq_mutex); + rseg->last_page_no= undo->hdr_page_no; + rseg->set_last_commit(undo->hdr_offset, end); + } + else + trx_sys.assign_new_trx_no(this); + UT_LIST_REMOVE(rseg->undo_list, undo); + /* Change the undo log segment state from TRX_UNDO_ACTIVE, to + define the transaction as committed in the file based domain, + at mtr->commit_lsn() obtained in mtr->commit() below. */ + trx_purge_add_undo_to_history(this, undo, mtr); + done: + rseg->release(); + rseg->latch.wr_unlock(); + } + else + rseg->release(); + mtr->commit(); } /******************************************************************** @@ -1133,41 +1232,31 @@ extern "C" void thd_decrement_pending_ops(MYSQL_THD); @param trx transaction; if trx->state is PREPARED, the function will also wait for the flush to complete. */ -static void trx_flush_log_if_needed_low(lsn_t lsn, const trx_t *trx) +static void trx_flush_log_if_needed(lsn_t lsn, trx_t *trx) { - if (!srv_flush_log_at_trx_commit) - return; + ut_ad(srv_flush_log_at_trx_commit); + ut_ad(trx->state != TRX_STATE_PREPARED); if (log_sys.get_flushed_lsn(std::memory_order_relaxed) >= lsn) return; - completion_callback cb, *callback= nullptr; + const bool flush= + (!my_disable_sync && + (srv_flush_log_at_trx_commit & 1)); - if (trx->state != TRX_STATE_PREPARED && !log_sys.is_pmem() && + completion_callback cb; + if (!log_sys.is_pmem() && (cb.m_param= thd_increment_pending_ops(trx->mysql_thd))) { - cb.m_callback= (void (*)(void *)) thd_decrement_pending_ops; - callback= &cb; + cb.m_callback = (void (*)(void *)) thd_decrement_pending_ops; + log_write_up_to(lsn, flush, &cb); + } + else + { + trx->op_info= "flushing log"; + log_write_up_to(lsn, flush); + trx->op_info= ""; } - - log_write_up_to(lsn, !my_disable_sync && - (srv_flush_log_at_trx_commit & 1), callback); -} - -/**********************************************************************//** -If required, flushes the log to disk based on the value of -innodb_flush_log_at_trx_commit. */ -static -void -trx_flush_log_if_needed( -/*====================*/ - lsn_t lsn, /*!< in: lsn up to which logs are to be - flushed. */ - trx_t* trx) /*!< in/out: transaction */ -{ - trx->op_info = "flushing log"; - trx_flush_log_if_needed_low(lsn, trx); - trx->op_info = ""; } /** Process tables that were modified by the committing transaction. */ @@ -1224,11 +1313,59 @@ void trx_t::evict_table(table_id_t table_id, bool reset_only) } } +/** Free temporary undo log after commit or rollback. +@param undo temporary undo log */ +ATTRIBUTE_NOINLINE static void trx_commit_cleanup(trx_undo_t *&undo) +{ + trx_rseg_t *const rseg= undo->rseg; + ut_ad(rseg->space == fil_system.temp_space); + rseg->latch.wr_lock(SRW_LOCK_CALL); + UT_LIST_REMOVE(rseg->undo_list, undo); + ut_ad(undo->state == TRX_UNDO_ACTIVE || undo->state == TRX_UNDO_PREPARED); + ut_ad(undo->id < TRX_RSEG_N_SLOTS); + /* Delete first the undo log segment in the file */ + bool finished; + mtr_t mtr; + do + { + mtr.start(); + mtr.set_log_mode(MTR_LOG_NO_REDO); + + finished= true; + + if (buf_block_t *block= + buf_page_get(page_id_t(SRV_TMP_SPACE_ID, undo->hdr_page_no), 0, + RW_X_LATCH, &mtr)) + { + fseg_header_t *file_seg= TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + + block->page.frame; + + finished= fseg_free_step(file_seg, &mtr); + + if (!finished); + else if (buf_block_t *rseg_header= rseg->get(&mtr, nullptr)) + { + static_assert(FIL_NULL == 0xffffffff, "compatibility"); + memset(rseg_header->page.frame + TRX_RSEG + TRX_RSEG_UNDO_SLOTS + + undo->id * TRX_RSEG_SLOT_SIZE, 0xff, 4); + } + } + + mtr.commit(); + } + while (!finished); + + ut_ad(rseg->curr_size > undo->size); + rseg->curr_size-= undo->size; + rseg->latch.wr_unlock(); + ut_free(undo); + undo= nullptr; +} + TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr) { - /* We already detached from rseg in trx_write_serialisation_history() */ + /* We already detached from rseg in write_serialisation_history() */ ut_ad(!rsegs.m_redo.undo); - must_flush_log_later= false; read_view.close(); if (is_autocommit_non_locking()) @@ -1295,15 +1432,14 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr) release_locks(); } - if (mtr) + if (trx_undo_t *&undo= rsegs.m_noredo.undo) { - if (trx_undo_t *&undo= rsegs.m_noredo.undo) - { - ut_ad(undo->rseg == rsegs.m_noredo.rseg); - trx_undo_commit_cleanup(undo); - undo= nullptr; - } + ut_ad(undo->rseg == rsegs.m_noredo.rseg); + trx_commit_cleanup(undo); + } + if (mtr) + { /* NOTE that we could possibly make a group commit more efficient here: call std::this_thread::yield() here to allow also other trxs to come to commit! */ @@ -1332,17 +1468,13 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr) gathering. */ commit_lsn= undo_no || !xid.is_null() ? mtr->commit_lsn() : 0; - if (!commit_lsn) - /* Nothing to be done. */; - else if (flush_log_later) - /* Do nothing yet */ - must_flush_log_later= true; - else if (srv_flush_log_at_trx_commit) + if (commit_lsn && !flush_log_later && srv_flush_log_at_trx_commit) + { trx_flush_log_if_needed(commit_lsn, this); + commit_lsn= 0; + } } - ut_ad(!rsegs.m_noredo.undo); - savepoints_discard(); if (fts_trx) @@ -1389,7 +1521,7 @@ TRANSACTIONAL_TARGET void trx_t::commit_low(mtr_t *mtr) { ut_ad(!mtr || mtr->is_active()); ut_d(bool aborted= in_rollback && error_state == DB_DEADLOCK); - ut_ad(!mtr == (aborted || !has_logged())); + ut_ad(!mtr == (aborted || !has_logged_persistent())); ut_ad(!mtr || !aborted); if (fts_trx && undo_no) @@ -1415,7 +1547,6 @@ TRANSACTIONAL_TARGET void trx_t::commit_low(mtr_t *mtr) { if (UNIV_UNLIKELY(apply_online_log)) apply_log(); - trx_write_serialisation_history(this, mtr); /* The following call commits the mini-transaction, making the whole transaction committed in the file-based world, at this log @@ -1423,16 +1554,12 @@ TRANSACTIONAL_TARGET void trx_t::commit_low(mtr_t *mtr) the log to disk, but in the logical sense the commit in the file-based data structures (undo logs etc.) happens here. - NOTE that transaction numbers, which are assigned only to - transactions with an update undo log, do not necessarily come in + NOTE that transaction numbers do not necessarily come in exactly the same order as commit lsn's, if the transactions have - different rollback segments. To get exactly the same order we - should hold the kernel mutex up to this point, adding to the - contention of the kernel mutex. However, if a transaction T2 is + different rollback segments. However, if a transaction T2 is able to see modifications made by a transaction T1, T2 will always get a bigger transaction number and a bigger commit lsn than T1. */ - - mtr->commit(); + write_serialisation_history(mtr); } else if (trx_rseg_t *rseg= rsegs.m_redo.rseg) { @@ -1455,7 +1582,7 @@ void trx_t::commit_persist() mtr_t *mtr= nullptr; mtr_t local_mtr; - if (has_logged()) + if (has_logged_persistent()) { mtr= &local_mtr; local_mtr.start(); @@ -1599,24 +1726,21 @@ trx_commit_for_mysql( return(DB_CORRUPTION); } -/**********************************************************************//** -If required, flushes the log to disk if we called trx_commit_for_mysql() -with trx->flush_log_later == TRUE. */ -void -trx_commit_complete_for_mysql( -/*==========================*/ - trx_t* trx) /*!< in/out: transaction */ +/** Durably write log until trx->commit_lsn +(if trx_t::commit_in_memory() was invoked with flush_log_later=true). */ +void trx_commit_complete_for_mysql(trx_t *trx) { - if (trx->id != 0 - || !trx->must_flush_log_later - || (srv_flush_log_at_trx_commit == 1 && trx->active_commit_ordered)) { - - return; - } - - trx_flush_log_if_needed(trx->commit_lsn, trx); - - trx->must_flush_log_later = false; + const lsn_t lsn= trx->commit_lsn; + if (!lsn) + return; + switch (srv_flush_log_at_trx_commit) { + case 0: + return; + case 1: + if (trx->active_commit_ordered) + return; + } + trx_flush_log_if_needed(lsn, trx); } /**********************************************************************//** @@ -1878,8 +2002,9 @@ trx_prepare( gather behind one doing the physical log write to disk. We must not be holding any mutexes or latches here. */ - - trx_flush_log_if_needed(lsn, trx); + if (auto f = srv_flush_log_at_trx_commit) { + log_write_up_to(lsn, (f & 1) && !my_disable_sync); + } if (!UT_LIST_GET_LEN(trx->lock.trx_locks) || trx->isolation_level == TRX_ISO_SERIALIZABLE) { diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 6404a8d80a146..345a8362ec72c 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -497,8 +497,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id, ut_ad(slot_no < TRX_RSEG_N_SLOTS); - *err = fsp_reserve_free_extents(&n_reserved, space, 2, FSP_UNDO, - mtr); + *err = fsp_reserve_free_extents(&n_reserved, space, 2, FSP_UNDO, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return NULL; } @@ -569,14 +568,15 @@ static uint16_t trx_undo_header_create(buf_block_t *undo_page, trx_id_t trx_id, start, 2); uint16_t prev_log= mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG + undo_page->page.frame); + ut_ad(prev_log < free); alignas(4) byte buf[4]; mach_write_to_2(buf, TRX_UNDO_ACTIVE); mach_write_to_2(buf + 2, free); static_assert(TRX_UNDO_STATE + 2 == TRX_UNDO_LAST_LOG, "compatibility"); static_assert(!((TRX_UNDO_SEG_HDR + TRX_UNDO_STATE) % 4), "alignment"); - mtr->memcpy(*undo_page, my_assume_aligned<4> - (TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + undo_page->page.frame), - buf, 4); + mtr->memcpy + (*undo_page, my_assume_aligned<4> + (TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + undo_page->page.frame), buf, 4); if (prev_log) mtr->write<2>(*undo_page, prev_log + TRX_UNDO_NEXT_LOG + undo_page->page.frame, free); @@ -956,47 +956,6 @@ trx_undo_truncate_start( goto loop; } -/** Frees an undo log segment which is not in the history list. -@param undo temporary undo log */ -static void trx_undo_seg_free(const trx_undo_t *undo) -{ - ut_ad(undo->id < TRX_RSEG_N_SLOTS); - - trx_rseg_t *const rseg= undo->rseg; - bool finished; - mtr_t mtr; - ut_ad(rseg->space == fil_system.temp_space); - - do - { - mtr.start(); - mtr.set_log_mode(MTR_LOG_NO_REDO); - - finished= true; - - if (buf_block_t *block= - buf_page_get(page_id_t(SRV_TMP_SPACE_ID, undo->hdr_page_no), 0, - RW_X_LATCH, &mtr)) - { - fseg_header_t *file_seg= TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + - block->page.frame; - - finished= fseg_free_step(file_seg, &mtr); - - if (!finished); - else if (buf_block_t* rseg_header = rseg->get(&mtr, nullptr)) - { - static_assert(FIL_NULL == 0xffffffff, "compatibility"); - mtr.memset(rseg_header, TRX_RSEG + TRX_RSEG_UNDO_SLOTS + - undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff); - } - } - - mtr.commit(); - } - while (!finished); -} - /*========== UNDO LOG MEMORY COPY INITIALIZATION =====================*/ /** Read an undo log when starting up the database. @@ -1058,7 +1017,6 @@ trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no) case TRX_UNDO_ACTIVE: case TRX_UNDO_PREPARED: if (UNIV_LIKELY(type != 1)) { - trx_no = trx_id + 1; break; } sql_print_error("InnoDB: upgrade from older version than" @@ -1295,6 +1253,8 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, { ut_ad(rseg->is_persistent()); ut_ad(rseg->is_referenced()); + ut_ad(rseg == trx->rsegs.m_redo.rseg); + if (rseg->needs_purge <= trx->id) { /* trx_purge_truncate_history() compares rseg->needs_purge <= head.trx_no @@ -1330,10 +1290,6 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, trx_undo_mem_init_for_reuse(undo, trx->id, &trx->xid, offset); - if (rseg != trx->rsegs.m_redo.rseg) { - return block; - } - if (trx->dict_operation) { undo->dict_operation = TRUE; mtr->write<1,mtr_t::MAYBE_NOP>(*block, @@ -1503,27 +1459,6 @@ void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback, trx_undo_write_xid(block, offset, undo->xid, mtr); } -/** Free temporary undo log after commit or rollback. -The information is not needed after a commit or rollback, therefore -the data can be discarded. -@param undo temporary undo log */ -void trx_undo_commit_cleanup(trx_undo_t *undo) -{ - trx_rseg_t *rseg= undo->rseg; - ut_ad(rseg->space == fil_system.temp_space); - rseg->latch.wr_lock(SRW_LOCK_CALL); - - UT_LIST_REMOVE(rseg->undo_list, undo); - ut_ad(undo->state == TRX_UNDO_TO_PURGE); - /* Delete first the undo log segment in the file */ - trx_undo_seg_free(undo); - ut_ad(rseg->curr_size > undo->size); - rseg->curr_size-= undo->size; - - rseg->latch.wr_unlock(); - ut_free(undo); -} - /** At shutdown, frees the undo logs of a transaction. */ void trx_undo_free_at_shutdown(trx_t *trx) { diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index c8e6394179c12..9084be1d29df1 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -395,7 +395,15 @@ int _ma_mark_file_changed(register MARIA_SHARE *share) if (!share->base.born_transactional) { if (!_MA_ALREADY_MARKED_FILE_CHANGED) - return _ma_mark_file_changed_now(share); + { + int res= _ma_mark_file_changed_now(share); + /* + Ensure that STATE_NOT_ANALYZED is reset on table changes + */ + share->state.changed|= (STATE_CHANGED | STATE_NOT_ANALYZED | + STATE_NOT_OPTIMIZED_KEYS); + return res; + } } else { @@ -409,10 +417,10 @@ int _ma_mark_file_changed(register MARIA_SHARE *share) (STATE_CHANGED | STATE_NOT_ANALYZED | STATE_NOT_OPTIMIZED_KEYS))) { - mysql_mutex_lock(&share->intern_lock); + mysql_mutex_lock(&share->intern_lock); share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED | - STATE_NOT_OPTIMIZED_KEYS); - mysql_mutex_unlock(&share->intern_lock); + STATE_NOT_OPTIMIZED_KEYS); + mysql_mutex_unlock(&share->intern_lock); } } return 0; @@ -430,7 +438,7 @@ int _ma_mark_file_changed_now(register MARIA_SHARE *share) if (! _MA_ALREADY_MARKED_FILE_CHANGED) { share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED | - STATE_NOT_OPTIMIZED_KEYS); + STATE_NOT_OPTIMIZED_KEYS); if (!share->global_changed) { share->changed= share->global_changed= 1; diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 54962814faab6..027b0dbd67815 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -10347,13 +10347,13 @@ int ha_mroonga::generic_store_bulk_variable_size_string(Field *field, { MRN_DBUG_ENTER_METHOD(); int error = 0; - String value; - field->val_str(NULL, &value); + StringBuffer buffer(field->charset()); + auto value = field->val_str(&buffer, &buffer); grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0); DBUG_PRINT("info", ("mroonga: length=%" MRN_FORMAT_STRING_LENGTH, - value.length())); - DBUG_PRINT("info", ("mroonga: value=%s", value.c_ptr_safe())); - GRN_TEXT_SET(ctx, buf, value.ptr(), value.length()); + value->length())); + DBUG_PRINT("info", ("mroonga: value=%s", value->c_ptr_safe())); + GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); DBUG_RETURN(error); } @@ -10720,9 +10720,8 @@ int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf) { MRN_DBUG_ENTER_METHOD(); int error = 0; - String buffer; - Field_blob *blob = (Field_blob *)field; - String *value = blob->val_str(0, &buffer); + StringBuffer buffer(field->charset()); + auto value = field->val_str(&buffer, &buffer); grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0); GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); DBUG_RETURN(error); @@ -14677,10 +14676,14 @@ enum_alter_inplace_result ha_mroonga::storage_check_if_supported_inplace_alter( MRN_ALTER_INPLACE_INFO_ADD_VIRTUAL_COLUMN | MRN_ALTER_INPLACE_INFO_ADD_STORED_BASE_COLUMN | ALTER_DROP_COLUMN | + ALTER_INDEX_ORDER | + ALTER_INDEX_IGNORABILITY | ALTER_COLUMN_NAME; + ; if (ha_alter_info->handler_flags & explicitly_unsupported_flags) { DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } else if (ha_alter_info->handler_flags & supported_flags) { + } else if ((ha_alter_info->handler_flags & supported_flags) == + ha_alter_info->handler_flags) { DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); } else { DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); diff --git a/storage/mroonga/vendor/groonga/examples/Makefile.am b/storage/mroonga/vendor/groonga/examples/Makefile.am deleted file mode 100644 index f436342d0535f..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = dictionary diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am deleted file mode 100644 index ee618a213bda2..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -SUBDIRS = \ - edict \ - eijiro \ - gene95 \ - jmdict - -dist_examples_dictionary_SCRIPTS = \ - init-db.sh - -nobase_dist_examples_dictionary_DATA = \ - readme.txt \ - $(html_files) - -# find html -type f | sort | sed -e 's,^,\t,g' -html_files = \ - html/css/dictionary.css \ - html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png \ - html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png \ - html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png \ - html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png \ - html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png \ - html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png \ - html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png \ - html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png \ - html/css/smoothness/images/ui-icons_222222_256x240.png \ - html/css/smoothness/images/ui-icons_2e83ff_256x240.png \ - html/css/smoothness/images/ui-icons_454545_256x240.png \ - html/css/smoothness/images/ui-icons_888888_256x240.png \ - html/css/smoothness/images/ui-icons_cd0a0a_256x240.png \ - html/css/smoothness/jquery-ui-1.8.12.custom.css \ - html/index.html \ - html/js/dictionary.js \ - html/js/jquery-1.7.2.js \ - html/js/jquery-ui-1.8.18.custom.js diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am deleted file mode 100644 index 376f9d520ab1d..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -edictdir = $(examples_dictionarydir)/edict -dist_edict_SCRIPTS = \ - edict2grn.rb \ - edict-import.sh diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh deleted file mode 100755 index e48700af07be0..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -base_dir=$(dirname $0) - -if [ 1 != $# -a 2 != $# ]; then - echo "usage: $0 db_path [edict.gz_path]" - exit 1 -fi - -if [ -z $2 ]; then - edict_gz=edict.gz - if [ ! -f $edict_gz ]; then - wget -O $edict_gz http://ftp.monash.edu.au/pub/nihongo/edict.gz - fi -else - edict_gz=$2 -fi - -if type gzcat > /dev/null 2>&1; then - zcat="gzcat" -else - zcat="zcat" -fi - -if $zcat $edict_gz | ${base_dir}/edict2grn.rb | groonga $1 > /dev/null; then - echo "edict data loaded." -fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb deleted file mode 100755 index b795e25a50b49..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env ruby - -require "English" -require "nkf" -require "json" - -print(< /dev/null; then - echo "eijiro data loaded." -fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb deleted file mode 100755 index 62c1e1309bfd6..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: utf-8 -*- - -$KCODE = 'u' - -require 'rubygems' -require 'fastercsv' - -class String - def to_json - a = split(//).map {|char| - case char - when '"' then '\\"' - when '\\' then '\\\\' - when "\b" then '\b' - when "\f" then '\f' - when "\n" then '\n' - when "\r" then '' - when "\t" then '\t' - else char - end - } - "\"#{a.join('')}\"" - end -end - -class Array - def to_json - '[' + map {|element| - element.to_json - }.join(',') + ']' - end -end - -puts < "\r\n").each {|l| - if n > 0 - keyword,word,trans,exp,level,memory,modify,pron,filelink = l - kana = '' - if trans =~ /【@】(.*?)(【|$)/ - kana = $1.split("、") - end - puts [word,keyword,trans,exp,level,memory,modify,pron,filelink,kana].map{|e| e || ''}.to_json - end - n += 1 -} - -puts "]" diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am deleted file mode 100644 index e89f13f595c2b..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -gene95dir = $(examples_dictionarydir)/gene95 -dist_gene95_SCRIPTS = \ - gene2grn.rb \ - gene-import.sh diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh deleted file mode 100755 index 488d6c83adc39..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -base_dir=$(dirname $0) - -if [ 1 != $# -a 2 != $# ]; then - echo "usage: $0 db_path [gene.txt_path]" - exit 1 -fi - -if [ -z $2 ]; then - dictionary_dir=gene95-dictionary - gene_txt=${dictionary_dir}/gene.txt - if [ ! -f $gene_txt ]; then - gene95_tar_gz=gene95.tar.gz - wget -O $gene95_tar_gz \ - http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz - mkdir -p ${dictionary_dir} - tar xvzf ${gene95_tar_gz} -C ${dictionary_dir} - fi -else - gene_txt=$2 -fi - -if cat $gene_txt | ${base_dir}/gene2grn.rb | groonga $1 > /dev/null; then - echo "gene95 data loaded." -fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb deleted file mode 100755 index c9d9a593b1167..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env ruby - -require "json" - -print(<") - $stderr.puts(" body: <#{raw_body}>") - next - end - puts(",") - print([key, body].to_json) -end -puts -puts("]") diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css deleted file mode 100644 index 72b5a6749b33f..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css +++ /dev/null @@ -1,3 +0,0 @@ -#result { - margin-top: 7em; -} diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png deleted file mode 100644 index 5b5dab2ab7b1c..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png deleted file mode 100644 index ac8b229af950c..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png deleted file mode 100644 index ad3d6346e00f2..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png deleted file mode 100644 index 42ccba269b6e9..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png deleted file mode 100644 index 5a46b47cb1663..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png deleted file mode 100644 index 86c2baa655eac..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png deleted file mode 100644 index 4443fdc1a156b..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png deleted file mode 100644 index 7c9fa6c6edcfc..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png deleted file mode 100644 index b273ff111d219..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png deleted file mode 100644 index 09d1cdc856c29..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png deleted file mode 100644 index 59bd45b907c4f..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png deleted file mode 100644 index 6d02426c114be..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png deleted file mode 100644 index 2ab019b73ec11..0000000000000 Binary files a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png and /dev/null differ diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css deleted file mode 100644 index c85aabaec064e..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css +++ /dev/null @@ -1,578 +0,0 @@ -/* - * jQuery UI CSS Framework 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } -.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } -.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.ui-helper-clearfix { display: inline-block; } -/* required comment for clearfix to work in Opera \*/ -* html .ui-helper-clearfix { height:1%; } -.ui-helper-clearfix { display:block; } -/* end clearfix */ -.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { cursor: default !important; } - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - - -/* - * jQuery UI CSS Framework 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } -.ui-widget .ui-widget { font-size: 1em; } -.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } -.ui-widget-content a { color: #222222; } -.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } -.ui-widget-header a { color: #222222; } - -/* Interaction states -----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } -.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } -.ui-widget :active { outline: none; } - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } -.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } -.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } -.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } -.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } -.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } -.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } - -/* positioning */ -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } -.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } -.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } -.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } -.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } -.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } - -/* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* - * jQuery UI Resizable 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Resizable#theming - */ -.ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; - /* http://bugs.jqueryui.com/ticket/7233 - - Resizable: resizable handles fail to work in IE if transparent and content overlaps - */ - background-image:url(data:); -} -.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } -.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } -.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } -.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* - * jQuery UI Selectable 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectable#theming - */ -.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } -/* - * jQuery UI Accordion 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion#theming - */ -/* IE/Win - Fix animation bug - #4615 */ -.ui-accordion { width: 100%; } -.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } -.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } -.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } -.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } -.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } -.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } -.ui-accordion .ui-accordion-content-active { display: block; } -/* - * jQuery UI Autocomplete 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete#theming - */ -.ui-autocomplete { position: absolute; cursor: default; } - -/* workarounds */ -* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ - -/* - * jQuery UI Menu 1.8.12 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Menu#theming - */ -.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - float: left; -} -.ui-menu .ui-menu { - margin-top: -3px; -} -.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - float: left; - clear: left; - width: 100%; -} -.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding:.2em .4em; - line-height:1.5; - zoom:1; -} -.ui-menu .ui-menu-item a.ui-state-hover, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} -/* - * jQuery UI Button 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button#theming - */ -.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ -.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ -button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ -.ui-button-icons-only { width: 3.4em; } -button.ui-button-icons-only { width: 3.7em; } - -/*button text element */ -.ui-button .ui-button-text { display: block; line-height: 1.4; } -.ui-button-text-only .ui-button-text { padding: .4em 1em; } -.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } -.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } -.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } -.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } -/* no icon support for input elements, provide padding by default */ -input.ui-button { padding: .4em 1em; } - -/*button icon element(s) */ -.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } -.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } -.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } -.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } -.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } - -/*button sets*/ -.ui-buttonset { margin-right: 7px; } -.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } - -/* workarounds */ -button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ -/* - * jQuery UI Dialog 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog#theming - */ -.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } -.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } -.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } -.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } -.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } -.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } -.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } -.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } -.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } -.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } -.ui-draggable .ui-dialog-titlebar { cursor: move; } -/* - * jQuery UI Slider 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider#theming - */ -.ui-slider { position: relative; text-align: left; } -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } - -.ui-slider-horizontal { height: .8em; } -.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; }/* - * jQuery UI Tabs 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs#theming - */ -.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ -.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } -.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } -.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ -.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } -.ui-tabs .ui-tabs-hide { display: none !important; } -/* - * jQuery UI Datepicker 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker#theming - */ -.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } -.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } -.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } -.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } -.ui-datepicker .ui-datepicker-prev { left:2px; } -.ui-datepicker .ui-datepicker-next { right:2px; } -.ui-datepicker .ui-datepicker-prev-hover { left:1px; } -.ui-datepicker .ui-datepicker-next-hover { right:1px; } -.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } -.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } -.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } -.ui-datepicker select.ui-datepicker-month-year {width: 100%;} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { width: 49%;} -.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } -.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } -.ui-datepicker td { border: 0; padding: 1px; } -.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } -.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } -.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { width:auto; } -.ui-datepicker-multi .ui-datepicker-group { float:left; } -.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } -.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } -.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } -.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; } - -/* RTL support */ -.ui-datepicker-rtl { direction: rtl; } -.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } -.ui-datepicker-rtl .ui-datepicker-group { float:right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } - -/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ -.ui-datepicker-cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 200px; /*must have*/ - height: 200px; /*must have*/ -}/* - * jQuery UI Progressbar 1.8.12 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar#theming - */ -.ui-progressbar { height:2em; text-align: left; } -.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html b/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html deleted file mode 100644 index 47e81754094c9..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - -groonga dictionary search - - - - - - - - - - - -
- - diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js deleted file mode 100644 index 850c64cc667cb..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js +++ /dev/null @@ -1,82 +0,0 @@ -function dictionarySource(url) { - function displayItems(items) { - var results = $("
"); - $.each(items, - function(i, val) { - results.append($("
") - .append($("") - .text(val[0]) - .click(function() { - $(".search").val($(this).text()); - $("#search").submit(); - }))); - results.append($("
") - .append($("").text(val[1])) - .append($("").text(val[2])) - ); - }); - $("#result") - .empty() - .append(results); - }; - - var request_index = 0; - var columns = "_key,gene95_desc,edict_desc"; - var xhr; - function source(request, response) { - function onSuccess(data, status) { - if (this.autocomplete_request != request_index) { - return; - } - var completions = data[1]["complete"]; - var items = []; - if (completions && completions.length > 2) { - completions.shift(); - completions.shift(); - $.each(completions, - function(i, item) { - var key = item[0]; - items.push(key); - if (items.length >= 3) { - return false; - } - return true; - }); - } - if (completions.length > 0) { - displayItems(completions); - } - response(items); - } - - function onError() { - if (this.autocomplete_request != request_index) { - return; - } - response([]); - } - - if (xhr) { - xhr.abort(); - } - xhr = $.ajax(url, - { - data: { - query: request.term, - types: 'complete', - table: 'item_dictionary', - column: 'kana', - limit: 25, - output_columns: columns, - frequency_threshold: 1, - prefix_search: "yes" - }, - dataType: "jsonp", - autocomplete_request: ++request_index, - success: onSuccess, - error: onError - }); - }; - - return source; -} diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js deleted file mode 100644 index b6624f31b0d7a..0000000000000 --- a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js +++ /dev/null @@ -1,9404 +0,0 @@ -/*! - * jQuery JavaScript Library v1.7.2 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Mar 21 12:46:34 2012 -0700 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document, - navigator = window.navigator, - location = window.location; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Matches dashed string for camelizing - rdashAlpha = /-([a-z]|[0-9])/ig, - rmsPrefix = /^-ms-/, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // The deferred used on DOM ready - readyList, - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = quickExpr.exec( selector ); - } - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = ( context ? context.ownerDocument || context : document ); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.7.2", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.add( fn ); - - return this; - }, - - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - // Either a released hold or an DOMready/load event and not yet ready - if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.fireWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).off( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = jQuery.Callbacks( "once memory" ); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function( obj ) { - return obj != null && obj == obj.window; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - - } - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - var xml, tmp; - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction( object ); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { - break; - } - } - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array, i ) { - var len; - - if ( array ) { - if ( indexOf ) { - return indexOf.call( array, elem, i ); - } - - len = array.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in array && array[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - if ( typeof context === "string" ) { - var tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - var args = slice.call( arguments, 2 ), - proxy = function() { - return fn.apply( context, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can optionally be executed if it's a function - access: function( elems, fn, key, value, chainable, emptyGet, pass ) { - var exec, - bulk = key == null, - i = 0, - length = elems.length; - - // Sets many values - if ( key && typeof key === "object" ) { - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); - } - chainable = 1; - - // Sets one value - } else if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = pass === undefined && jQuery.isFunction( value ); - - if ( bulk ) { - // Bulk operations only iterate when executing function values - if ( exec ) { - exec = fn; - fn = function( elem, key, value ) { - return exec.call( jQuery( elem ), value ); - }; - - // Otherwise they run against the entire set - } else { - fn.call( elems, value ); - fn = null; - } - } - - if ( fn ) { - for (; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - } - - chainable = 1; - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; - }, - - now: function() { - return ( new Date() ).getTime(); - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; - }, - - browser: {} -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -return jQuery; - -})(); - - -// String to Object flags format cache -var flagsCache = {}; - -// Convert String-formatted flags into Object-formatted ones and store in cache -function createFlags( flags ) { - var object = flagsCache[ flags ] = {}, - i, length; - flags = flags.split( /\s+/ ); - for ( i = 0, length = flags.length; i < length; i++ ) { - object[ flags[i] ] = true; - } - return object; -} - -/* - * Create a callback list using the following parameters: - * - * flags: an optional list of space-separated flags that will change how - * the callback list behaves - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible flags: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( flags ) { - - // Convert flags from String-formatted to Object-formatted - // (we check in cache first) - flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; - - var // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = [], - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Add one or several callbacks to the list - add = function( args ) { - var i, - length, - elem, - type, - actual; - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - // Inspect recursively - add( elem ); - } else if ( type === "function" ) { - // Add if not in unique mode and callback is not in - if ( !flags.unique || !self.has( elem ) ) { - list.push( elem ); - } - } - } - }, - // Fire callbacks - fire = function( context, args ) { - args = args || []; - memory = !flags.memory || [ context, args ]; - fired = true; - firing = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { - memory = true; // Mark as halted - break; - } - } - firing = false; - if ( list ) { - if ( !flags.once ) { - if ( stack && stack.length ) { - memory = stack.shift(); - self.fireWith( memory[ 0 ], memory[ 1 ] ); - } - } else if ( memory === true ) { - self.disable(); - } else { - list = []; - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - var length = list.length; - add( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away, unless previous - // firing was halted (stopOnFalse) - } else if ( memory && memory !== true ) { - firingStart = length; - fire( memory[ 0 ], memory[ 1 ] ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - var args = arguments, - argIndex = 0, - argLength = args.length; - for ( ; argIndex < argLength ; argIndex++ ) { - for ( var i = 0; i < list.length; i++ ) { - if ( args[ argIndex ] === list[ i ] ) { - // Handle firingIndex and firingLength - if ( firing ) { - if ( i <= firingLength ) { - firingLength--; - if ( i <= firingIndex ) { - firingIndex--; - } - } - } - // Remove the element - list.splice( i--, 1 ); - // If we have some unicity property then - // we only need to do this once - if ( flags.unique ) { - break; - } - } - } - } - } - return this; - }, - // Control if a given callback is in the list - has: function( fn ) { - if ( list ) { - var i = 0, - length = list.length; - for ( ; i < length; i++ ) { - if ( fn === list[ i ] ) { - return true; - } - } - } - return false; - }, - // Remove all callbacks from the list - empty: function() { - list = []; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory || memory === true ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( stack ) { - if ( firing ) { - if ( !flags.once ) { - stack.push( [ context, args ] ); - } - } else if ( !( flags.once && memory ) ) { - fire( context, args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - - - -var // Static reference to slice - sliceDeferred = [].slice; - -jQuery.extend({ - - Deferred: function( func ) { - var doneList = jQuery.Callbacks( "once memory" ), - failList = jQuery.Callbacks( "once memory" ), - progressList = jQuery.Callbacks( "memory" ), - state = "pending", - lists = { - resolve: doneList, - reject: failList, - notify: progressList - }, - promise = { - done: doneList.add, - fail: failList.add, - progress: progressList.add, - - state: function() { - return state; - }, - - // Deprecated - isResolved: doneList.fired, - isRejected: failList.fired, - - then: function( doneCallbacks, failCallbacks, progressCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); - return this; - }, - always: function() { - deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); - return this; - }, - pipe: function( fnDone, fnFail, fnProgress ) { - return jQuery.Deferred(function( newDefer ) { - jQuery.each( { - done: [ fnDone, "resolve" ], - fail: [ fnFail, "reject" ], - progress: [ fnProgress, "notify" ] - }, function( handler, data ) { - var fn = data[ 0 ], - action = data[ 1 ], - returned; - if ( jQuery.isFunction( fn ) ) { - deferred[ handler ](function() { - returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - }); - } else { - deferred[ handler ]( newDefer[ action ] ); - } - }); - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - obj = promise; - } else { - for ( var key in promise ) { - obj[ key ] = promise[ key ]; - } - } - return obj; - } - }, - deferred = promise.promise({}), - key; - - for ( key in lists ) { - deferred[ key ] = lists[ key ].fire; - deferred[ key + "With" ] = lists[ key ].fireWith; - } - - // Handle state - deferred.done( function() { - state = "resolved"; - }, failList.disable, progressList.lock ).fail( function() { - state = "rejected"; - }, doneList.disable, progressList.lock ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( firstParam ) { - var args = sliceDeferred.call( arguments, 0 ), - i = 0, - length = args.length, - pValues = new Array( length ), - count = length, - pCount = length, - deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? - firstParam : - jQuery.Deferred(), - promise = deferred.promise(); - function resolveFunc( i ) { - return function( value ) { - args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( deferred, args ); - } - }; - } - function progressFunc( i ) { - return function( value ) { - pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - deferred.notifyWith( promise, pValues ); - }; - } - if ( length > 1 ) { - for ( ; i < length; i++ ) { - if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { - args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( deferred, args ); - } - } else if ( deferred !== firstParam ) { - deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); - } - return promise; - } -}); - - - - -jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - fragment, - tds, - events, - eventName, - i, - isSupported, - div = document.createElement( "div" ), - documentElement = document.documentElement; - - // Preliminary tests - div.setAttribute("className", "t"); - div.innerHTML = "
a"; - - all = div.getElementsByTagName( "*" ); - a = div.getElementsByTagName( "a" )[ 0 ]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return {}; - } - - // First batch of supports tests - select = document.createElement( "select" ); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName( "input" )[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form(#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true, - pixelMargin: true - }; - - // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead - jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent( "onclick" ); - } - - // Check if a radio maintains its value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute("type", "radio"); - support.radioValue = input.value === "t"; - - input.setAttribute("checked", "checked"); - - // #11217 - WebKit loses check when the name is after the checked attribute - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - fragment.removeChild( input ); - fragment.appendChild( div ); - - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for ( i in { - submit: 1, - change: 1, - focusin: 1 - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - fragment.removeChild( div ); - - // Null elements to avoid leaks in IE - fragment = select = opt = div = input = null; - - // Run tests that need a body at doc ready - jQuery(function() { - var container, outer, inner, table, td, offsetSupport, - marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, - paddingMarginBorderVisibility, paddingMarginBorder, - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - conMarginTop = 1; - paddingMarginBorder = "padding:0;margin:0;border:"; - positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; - paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; - style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; - html = "
" + - "" + - "
"; - - container = document.createElement("div"); - container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; - body.insertBefore( container, body.firstChild ); - - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - div.innerHTML = "
t
"; - tds = div.getElementsByTagName( "td" ); - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - if ( window.getComputedStyle ) { - div.innerHTML = ""; - marginDiv = document.createElement( "div" ); - marginDiv.style.width = "0"; - marginDiv.style.marginRight = "0"; - div.style.width = "2px"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; - } - - if ( typeof div.style.zoom !== "undefined" ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.innerHTML = ""; - div.style.width = div.style.padding = "1px"; - div.style.border = 0; - div.style.overflow = "hidden"; - div.style.display = "inline"; - div.style.zoom = 1; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = "block"; - div.style.overflow = "visible"; - div.innerHTML = "
"; - support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); - } - - div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; - div.innerHTML = html; - - outer = div.firstChild; - inner = outer.firstChild; - td = outer.nextSibling.firstChild.firstChild; - - offsetSupport = { - doesNotAddBorder: ( inner.offsetTop !== 5 ), - doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) - }; - - inner.style.position = "fixed"; - inner.style.top = "20px"; - - // safari subtracts parent border width here which is 5px - offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); - inner.style.position = inner.style.top = ""; - - outer.style.overflow = "hidden"; - outer.style.position = "relative"; - - offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); - offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); - - if ( window.getComputedStyle ) { - div.style.marginTop = "1%"; - support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; - } - - if ( typeof container.style.zoom !== "undefined" ) { - container.style.zoom = 1; - } - - body.removeChild( container ); - marginDiv = div = container = null; - - jQuery.extend( support, offsetSupport ); - }); - - return support; -})(); - - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/, - rmultiDash = /([A-Z])/g; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var privateCache, thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, - isEvents = name === "events"; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = ++jQuery.uuid; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - privateCache = thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Users should not attempt to inspect the internal events object using jQuery.data, - // it is undocumented and subject to change. But does anyone listen? No. - if ( isEvents && !thisCache[ name ] ) { - return privateCache.events; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, l, - - // Reference to internal data cache key - internalKey = jQuery.expando, - - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ internalKey ] : internalKey; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split( " " ); - } - } - } - - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - // Ensure that `cache` is not a window object #10080 - if ( jQuery.support.deleteExpando || !cache.setInterval ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the cache and need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ internalKey ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - } else { - elem[ internalKey ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var parts, part, attr, name, l, - elem = this[0], - i = 0, - data = null; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); - - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - attr = elem.attributes; - for ( l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( elem, name, data[ name ] ); - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - parts = key.split( ".", 2 ); - parts[1] = parts[1] ? "." + parts[1] : ""; - part = parts[1] + "!"; - - return jQuery.access( this, function( value ) { - - if ( value === undefined ) { - data = this.triggerHandler( "getData" + part, [ parts[0] ] ); - - // Try to fetch any internally stored data first - if ( data === undefined && elem ) { - data = jQuery.data( elem, key ); - data = dataAttr( elem, key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - } - - parts[1] = value; - this.each(function() { - var self = jQuery( this ); - - self.triggerHandler( "setData" + part, parts ); - jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + part, parts ); - }); - }, null, value, arguments.length > 1, null, false ); - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - jQuery.isNumeric( data ) ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -function handleQueueMarkDefer( elem, type, src ) { - var deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - defer = jQuery._data( elem, deferDataKey ); - if ( defer && - ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && - ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { - // Give room for hard-coded callbacks to fire first - // and eventually mark/queue something else on the element - setTimeout( function() { - if ( !jQuery._data( elem, queueDataKey ) && - !jQuery._data( elem, markDataKey ) ) { - jQuery.removeData( elem, deferDataKey, true ); - defer.fire(); - } - }, 0 ); - } -} - -jQuery.extend({ - - _mark: function( elem, type ) { - if ( elem ) { - type = ( type || "fx" ) + "mark"; - jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); - } - }, - - _unmark: function( force, elem, type ) { - if ( force !== true ) { - type = elem; - elem = force; - force = false; - } - if ( elem ) { - type = type || "fx"; - var key = type + "mark", - count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); - if ( count ) { - jQuery._data( elem, key, count ); - } else { - jQuery.removeData( elem, key, true ); - handleQueueMarkDefer( elem, type, "mark" ); - } - } - }, - - queue: function( elem, type, data ) { - var q; - if ( elem ) { - type = ( type || "fx" ) + "queue"; - q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - q.push( data ); - } - } - return q || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(), - hooks = {}; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - jQuery._data( elem, type + ".run", hooks ); - fn.call( elem, function() { - jQuery.dequeue( elem, type ); - }, hooks ); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue " + type + ".run", true ); - handleQueueMarkDefer( elem, type, "queue" ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, object ) { - if ( typeof type !== "string" ) { - object = type; - type = undefined; - } - type = type || "fx"; - var defer = jQuery.Deferred(), - elements = this, - i = elements.length, - count = 1, - deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - tmp; - function resolve() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - } - while( i-- ) { - if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || - ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || - jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && - jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { - count++; - tmp.add( resolve ); - } - } - resolve(); - return defer.promise( object ); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspace = /\s+/, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute, - nodeHook, boolHook, fixSpecified; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classNames, i, l, elem, className, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - classNames = ( value || "" ).split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - className = (" " + elem.className + " ").replace( rclass, " " ); - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[ c ] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var self = jQuery(this), val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = jQuery.makeArray( value ); - - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( notxml ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, "" + value ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var propName, attrNames, name, l, isBool, - i = 0; - - if ( value && elem.nodeType === 1 ) { - attrNames = value.toLowerCase().split( rspace ); - l = attrNames.length; - - for ( ; i < l; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = jQuery.propFix[ name ] || name; - isBool = rboolean.test( name ); - - // See #9699 for explanation of this approach (setting first, then removal) - // Do not do this for boolean attributes (see #10870) - if ( !isBool ) { - jQuery.attr( elem, name, "" ); - } - elem.removeAttribute( getSetAttribute ? name : propName ); - - // Set corresponding property to false for boolean attributes - if ( isBool && propName in elem ) { - elem[ propName ] = false; - } - } - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) -jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - fixSpecified = { - name: true, - id: true, - coords: true - }; - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? - ret.nodeValue : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return ( ret.nodeValue = value + "" ); - } - }; - - // Apply the nodeHook to tabindex - jQuery.attrHooks.tabindex.set = nodeHook.set; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; -} - - -// Some attributes require a special call on IE -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = "" + value ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }); -}); - - - - -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, - rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, - quickParse = function( selector ) { - var quick = rquickIs.exec( selector ); - if ( quick ) { - // 0 1 2 3 - // [ _, tag, id, class ] - quick[1] = ( quick[1] || "" ).toLowerCase(); - quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); - } - return quick; - }, - quickIs = function( elem, m ) { - var attrs = elem.attributes || {}; - return ( - (!m[1] || elem.nodeName.toLowerCase() === m[1]) && - (!m[2] || (attrs.id || {}).value === m[2]) && - (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) - ); - }, - hoverHack = function( events ) { - return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - add: function( elem, types, handler, data, selector ) { - - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, quick, handlers, special; - - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; - } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: tns[1], - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - quick: selector && quickParse( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - t, tns, type, origType, namespaces, origCount, - j, events, special, handle, eventType, handleObj; - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - - // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); - - if ( handleObj.selector ) { - eventType.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery.removeData( elem, [ "events", "handle" ], true ); - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { - return; - } - - // Event object or event type - var type = event.type || event, - namespaces = [], - cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { - - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - old = null; - for ( ; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old && old === elem.ownerDocument ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); - } - } - - // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { - - cur = eventPath[i][0]; - event.type = eventPath[i][1]; - - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - // Note that this is a bare JS function and not a jQuery handler - handle = ontype && cur[ ontype ]; - if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( old ) { - elem[ ontype ] = old; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event || window.event ); - - var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, - args = [].slice.call( arguments, 0 ), - run_all = !event.exclusive && !event.namespace, - special = jQuery.event.special[ event.type ] || {}, - handlerQueue = [], - i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers that should run if there are delegated events - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !(event.button && event.type === "click") ) { - - // Pregenerate a single jQuery object for reuse with .is() - jqcur = jQuery(this); - jqcur.context = this.ownerDocument || this; - - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { - - // Don't process events on disabled elements (#6911, #8165) - if ( cur.disabled !== true ) { - selMatch = {}; - matches = []; - jqcur[0] = cur; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - sel = handleObj.selector; - - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = ( - handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) - ); - } - if ( selMatch[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); - } - - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; - - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; - - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - - event.data = handleObj.data; - event.handleObj = handleObj; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) - if ( event.metaKey === undefined ) { - event.metaKey = event.ctrlKey; - } - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady - }, - - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - - focus: { - delegateType: "focusin" - }, - blur: { - delegateType: "focusout" - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -jQuery.event.handle = jQuery.event.dispatch; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var target = this, - related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector, - ret; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !form._submit_attached ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submit_bubble = true; - }); - form._submit_attached = true; - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( event._submit_bubble ) { - delete event._submit_bubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - } - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !jQuery.support.changeBubbles ) { - - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - jQuery.event.simulate( "change", this, event, true ); - } - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - elem._change_attached = true; - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { // && selector != null - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - var handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( var type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } - - if ( rkeyEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; - } -}); - - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - expando = "sizcache" + (Math.random() + '').replace('.', ''), - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rReturn = /\r\n/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context, seed ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set, seed ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set, i, len, match, type, left; - - if ( !expr ) { - return []; - } - - for ( i = 0, len = Expr.order.length; i < len; i++ ) { - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - type, found, item, filter, left, - i, pass, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - filter = Expr.filter[ type ]; - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - pass = not ^ found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Utility function for retreiving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -var getText = Sizzle.getText = function( elem ) { - var i, node, - nodeType = elem.nodeType, - ret = ""; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent || innerText for elements - if ( typeof elem.textContent === 'string' ) { - return elem.textContent; - } else if ( typeof elem.innerText === 'string' ) { - // Replace IE's carriage returns - return elem.innerText.replace( rReturn, '' ); - } else { - // Traverse it's children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - } else { - - // If no nodeType, this is expected to be an array - for ( i = 0; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - if ( node.nodeType !== 8 ) { - ret += getText( node ); - } - } - } - return ret; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var first, last, - doneName, parent, cache, - count, diff, - type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - first = match[2]; - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - doneName = match[0]; - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { - count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent[ expando ] = doneName; - } - - diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Sizzle.attr ? - Sizzle.attr( elem, name ) : - Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - !type && Sizzle.attr ? - result != null : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} -// Expose origPOS -// "global" as in regardless of relation to brackets/parens -Expr.match.globalPOS = origPOS; - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

"; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || !disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
"; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context, seed ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet, seed ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -// Override sizzle attribute retrieval -Sizzle.attr = jQuery.attr; -Sizzle.selectors.attrMap = {}; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.globalPOS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var self = this, - i, l; - - if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - var ret = this.pushStack( "", "find", selector ), - length, n, r; - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - POS.test( selector ) ? - jQuery( selector, this.context ).index( this[0] ) >= 0 : - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - // Array (deprecated as of jQuery 1.7) - if ( jQuery.isArray( selectors ) ) { - var level = 1; - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( i = 0; i < selectors.length; i++ ) { - - if ( jQuery( cur ).is( selectors[ i ] ) ) { - ret.push({ selector: selectors[ i ], elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - - return ret; - } - - // String - var pos = POS.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, slice.call( arguments ).join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); -} - - - - -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /]", "i"), - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /\/(java|ecma)script/i, - rcleanScript = /^\s*", "" ], - legend: [ 1, "
", "
" ], - thead: [ 1, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - col: [ 2, "", "
" ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }, - safeFragment = createSafeFragment( document ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and