diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2020-09-02 14:36:14 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2020-09-02 14:36:14 +0200 |
commit | 5edf3e03887142f83044ee9fcc8fcf65386c43c7 (patch) | |
tree | 179e1f56be501aeb8ed2a975ee49efad5e5144dd | |
parent | 32a29afea777d8bbfcea7a2b5e6e5ee674013cb5 (diff) | |
parent | c58e184b14ccdf0b0eaeeeb7947e23b8b5fff7a7 (diff) | |
download | mariadb-git-5edf3e03887142f83044ee9fcc8fcf65386c43c7.tar.gz |
Merge branch '10.5' into 10.6
185 files changed, 2859 insertions, 1536 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..538007ed62d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +/debian @ottok + diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 94e21df15a1..0fd3ee7597a 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -313,10 +313,11 @@ gcov_configs="--with-gcov" # gprof -gprof_compile_flags="-O2 -pg -g" +gprof_compile_flags="-O2" +# Rest of the flags are set in CmakeFile.txt gprof_link_flags="--disable-shared $static_link" -disable_gprof_plugins="--with-zlib-dir=bundled --without-plugin-oqgraph --without-plugin-mroonga" +disable_gprof_plugins="--with-zlib-dir=bundled --without-plugin-oqgraph --without-plugin-mroonga --with-gprof" disable_asan_plugins="--without-plugin-rocksdb" diff --git a/CMakeLists.txt b/CMakeLists.txt index 80fac4b2ccc..36922e04368 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,13 +242,18 @@ IF (WITH_MSAN) MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=memory -fsanitize-memory-track-origins -U_FORTIFY_SOURCE" DEBUG RELWITHDEBINFO) ENDIF() +OPTION(WITH_GPROF "Enable profilingg with gprof" OFF) +IF (WITH_GPROF) + MY_CHECK_AND_SET_COMPILER_FLAG("-pg -g -no-pie -fPIC") +ENDIF() + # Be nice to profilers etc MY_CHECK_AND_SET_COMPILER_FLAG("-fno-omit-frame-pointer" RELWITHDEBINFO) # enable security hardening features, like most distributions do # in our benchmarks that costs about ~1% of performance, depending on the load OPTION(SECURITY_HARDENED "Use security-enhancing compiler features (stack protector, relro, etc)" ON) -IF(SECURITY_HARDENED AND NOT WITH_ASAN AND NOT WITH_UBSAN AND NOT WITH_TSAN) +IF(SECURITY_HARDENED AND NOT WITH_ASAN AND NOT WITH_UBSAN AND NOT WITH_TSAN AND NOT WITH_GPROF) # security-enhancing flags MY_CHECK_AND_SET_COMPILER_FLAG("-pie -fPIC") MY_CHECK_AND_SET_LINKER_FLAG("-Wl,-z,relro,-z,now") diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 6b829ccb8be..f8238cbb26d 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -184,7 +184,7 @@ static uint opt_tail_lines= 0; static uint opt_connect_timeout= 0; static uint opt_wait_for_pos_timeout= 0; - +static const uint default_wait_for_pos_timeout= 300; static char delimiter[MAX_DELIMITER_LENGTH]= ";"; static size_t delimiter_length= 1; @@ -5079,6 +5079,8 @@ void do_shutdown_server(struct st_command *command) }; DBUG_ENTER("do_shutdown_server"); + /* the wait-for-pos' default based value of 'timeout' must fit to MDEV-23511 */ + compile_time_assert(default_wait_for_pos_timeout / 5 >= 60); check_command_args(command, command->first_argument, shutdown_args, sizeof(shutdown_args)/sizeof(struct command_arg), ' '); @@ -7058,7 +7060,7 @@ static struct my_option my_long_options[] = {"wait_for_pos_timeout", 0, "Number of seconds to wait for master_pos_wait", &opt_wait_for_pos_timeout, &opt_wait_for_pos_timeout, 0, GET_UINT, - REQUIRED_ARG, 300, 0, 3600 * 12, 0, 0, 0}, + REQUIRED_ARG, default_wait_for_pos_timeout, 0, 3600 * 12, 0, 0, 0}, {"plugin_dir", 0, "Directory for client-side plugins.", &opt_plugin_dir, &opt_plugin_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -9085,10 +9087,6 @@ static void init_signal_handling(void) struct sigaction sa; DBUG_ENTER("init_signal_handling"); -#ifdef HAVE_STACKTRACE - my_init_stacktrace(0); -#endif - sa.sa_flags = SA_RESETHAND | SA_NODEFER; sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 9cba5600849..c4dee56edd1 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1721,7 +1721,7 @@ apply_log_finish() bool copy_back() { - bool ret; + bool ret = false; datadir_iter_t *it = NULL; datadir_node_t node; char *dst_dir; diff --git a/include/ilist.h b/include/ilist.h index 822f0334022..92812ba8f5d 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -19,6 +19,8 @@ #ifndef ILIST_H #define ILIST_H +#include "my_dbug.h" + #include <cstddef> #include <iterator> @@ -73,11 +75,13 @@ public: typedef T *pointer; typedef T &reference; - Iterator(ListNode *node) noexcept : node_(node) {} + Iterator(ListNode *node) noexcept : node_(node) + { DBUG_ASSERT(node_ != nullptr); } Iterator &operator++() noexcept { node_= node_->next; + DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator++(int) noexcept @@ -90,6 +94,7 @@ public: Iterator &operator--() noexcept { node_= node_->prev; + DBUG_ASSERT(node_ != nullptr); return *this; } Iterator operator--(int) noexcept @@ -184,8 +189,8 @@ public: #ifndef DBUG_OFF ListNode *curr= pos.node_; - curr->prev= NULL; - curr->next= NULL; + curr->prev= nullptr; + curr->next= nullptr; #endif return next; diff --git a/include/my_dbug.h b/include/my_dbug.h index f0c74ab485c..fa5b4c126d1 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -106,6 +106,9 @@ extern int (*dbug_sanity)(void); (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) #define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0) + +#define DBUG_PUSH_EMPTY if (_dbug_on_) { DBUG_PUSH(""); } +#define DBUG_POP_EMPTY if (_dbug_on_) { DBUG_POP(); } #define DBUG_PUSH(a1) _db_push_ (a1) #define DBUG_POP() _db_pop_ () #define DBUG_SET(a1) _db_set_ (a1) @@ -172,6 +175,8 @@ extern void _db_suicide_(void); #define DBUG_EVALUATE(keyword,a1,a2) (a2) #define DBUG_EVALUATE_IF(keyword,a1,a2) (a2) #define DBUG_PRINT(keyword,arglist) do { } while(0) +#define DBUG_PUSH_EMPTY do { } while(0) +#define DBUG_POP_EMPTY do { } while(0) #define DBUG_PUSH(a1) do { } while(0) #define DBUG_SET(a1) do { } while(0) #define DBUG_SET_INITIAL(a1) do { } while(0) diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h index 63e97dbc4f2..20b86f45232 100644 --- a/include/my_stacktrace.h +++ b/include/my_stacktrace.h @@ -1,5 +1,6 @@ /* Copyright (c) 2001, 2011, Oracle and/or its affiliates. + Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,19 +42,21 @@ C_MODE_START #if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) -void my_init_stacktrace(int setup_handlers); void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack, my_bool silent); int my_safe_print_str(const char* val, size_t max_len); void my_write_core(int sig); -#if BACKTRACE_DEMANGLE +# if BACKTRACE_DEMANGLE char *my_demangle(const char *mangled_name, int *status); -#endif /* BACKTRACE_DEMANGLE */ -#ifdef __WIN__ +# endif /* BACKTRACE_DEMANGLE */ +# ifdef __WIN__ +# define my_setup_stacktrace() void my_set_exception_pointers(EXCEPTION_POINTERS *ep); -#endif /* __WIN__ */ +# else +void my_setup_stacktrace(void); +# endif /* __WIN__ */ #else -#define my_init_stacktrace(A) do { } while(0) +# define my_setup_stacktrace() #endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */ #ifndef _WIN32 diff --git a/include/my_sys.h b/include/my_sys.h index 9e26aa4f8f4..68e52d13fff 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -915,9 +915,7 @@ extern MYSQL_PLUGIN_IMPORT my_crc32_t my_checksum; #if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) int crc32_aarch64_available(void); -#if defined(HAVE_ARMV8_CRYPTO) -int crc32c_aarch64_available(void); -#endif +const char *crc32c_aarch64_available(void); #endif #ifdef DBUG_ASSERT_EXISTS diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc index 33de60e92ac..31f4cf111ee 100644 --- a/libmysqld/emb_qcache.cc +++ b/libmysqld/emb_qcache.cc @@ -491,8 +491,8 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) *prev_row= NULL; data->embedded_info->prev_ptr= prev_row; return_ok: - net_send_eof(thd, thd->server_status, - thd->get_stmt_da()->current_statement_warn_count()); + thd->protocol->net_send_eof(thd, thd->server_status, + thd->get_stmt_da()->current_statement_warn_count()); DBUG_RETURN(0); err: DBUG_RETURN(1); diff --git a/libmysqld/emb_qcache.h b/libmysqld/emb_qcache.h index c4268752f9a..e3b6339ba3a 100644 --- a/libmysqld/emb_qcache.h +++ b/libmysqld/emb_qcache.h @@ -81,4 +81,3 @@ public: uint emb_count_querycache_size(THD *thd); int emb_load_querycache_result(THD *thd, Querycache_stream *src); void emb_store_querycache_result(Querycache_stream *dst, THD* thd); -bool net_send_eof(THD *thd, uint server_status, uint total_warn_count); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index eb3cf9cd8e3..21227e78a39 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -1138,7 +1138,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags) for (uint pos= 0 ; (item= it++); pos++) { - if (prot.store_field_metadata(thd, item, pos)) + if (prot.store_item_metadata(thd, item, pos)) goto err; } @@ -1253,8 +1253,7 @@ bool Protocol_binary::write() @retval FALSE Success */ -bool -net_send_ok(THD *thd, +bool Protocol::net_send_ok(THD *thd, uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong id, const char *message, bool) @@ -1289,7 +1288,7 @@ net_send_ok(THD *thd, */ bool -net_send_eof(THD *thd, uint server_status, uint statement_warn_count) +Protocol::net_send_eof(THD *thd, uint server_status, uint statement_warn_count) { bool error= write_eof_packet(thd, server_status, statement_warn_count); thd->cur_data= 0; @@ -1297,8 +1296,8 @@ net_send_eof(THD *thd, uint server_status, uint statement_warn_count) } -bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, - const char *sqlstate) +bool Protocol::net_send_error_packet(THD *thd, uint sql_errno, const char *err, + const char *sqlstate) { uint error; char converted_err[MYSQL_ERRMSG_SIZE]; diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c index e269840d674..9a17b9b4f09 100644 --- a/libmysqld/libmysql.c +++ b/libmysqld/libmysql.c @@ -1087,11 +1087,6 @@ unsigned int STDCALL mysql_field_count(MYSQL *mysql) return mysql->field_count; } -my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) -{ - return mysql->affected_rows; -} - my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { return mysql->insert_id; diff --git a/mysql-test/include/restart_mysqld.inc b/mysql-test/include/restart_mysqld.inc index 3d3e55db4ac..689f3b8cc1f 100644 --- a/mysql-test/include/restart_mysqld.inc +++ b/mysql-test/include/restart_mysqld.inc @@ -1,6 +1,6 @@ # ==== Usage ==== # -# [--let $shutdown_timeout= 30] +# [--let $shutdown_timeout= 60] # [--let $allow_rpl_inited= 1] # --source include/restart_mysqld.inc diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc index 978cfec1885..049c3d5bbd2 100644 --- a/mysql-test/include/rpl_stop_server.inc +++ b/mysql-test/include/rpl_stop_server.inc @@ -47,8 +47,8 @@ if ($rpl_debug) --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect # Send shutdown to the connected server and give -# it 60 seconds to die before zapping it -shutdown_server 60; +# it 60 seconds (of mysqltest's default) to die before zapping it +shutdown_server; --source include/wait_until_disconnected.inc diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index 6cd725c3698..a899a9294cc 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -39,7 +39,7 @@ # # Stop the server # let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; # --exec echo "wait" > $restart_file -# --shutdown_server 10 +# --shutdown_server # --source include/wait_until_disconnected.inc # # --error 1 diff --git a/mysql-test/include/shutdown_mysqld.inc b/mysql-test/include/shutdown_mysqld.inc index c787c2b8c3f..db0cfb82c68 100644 --- a/mysql-test/include/shutdown_mysqld.inc +++ b/mysql-test/include/shutdown_mysqld.inc @@ -1,6 +1,6 @@ # ==== Usage ==== # -# [--let $shutdown_timeout= 30] +# [--let $shutdown_timeout= 60] # [--let $allow_rpl_inited= 1] # --source include/shutdown_mysqld.inc diff --git a/mysql-test/main/empty_server_name-8224.test b/mysql-test/main/empty_server_name-8224.test index b15e9d82eb8..5c5140be2e0 100644 --- a/mysql-test/main/empty_server_name-8224.test +++ b/mysql-test/main/empty_server_name-8224.test @@ -4,7 +4,7 @@ --source include/not_embedded.inc create server '' foreign data wrapper w2 options (host '127.0.0.1'); --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect diff --git a/mysql-test/main/host_cache_size_functionality.test b/mysql-test/main/host_cache_size_functionality.test index db4f64fd493..9ec26010ab6 100644 --- a/mysql-test/main/host_cache_size_functionality.test +++ b/mysql-test/main/host_cache_size_functionality.test @@ -44,7 +44,7 @@ select @@global.Host_Cache_Size > 0; let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart:--host_cache_size=1 " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect @@ -143,7 +143,7 @@ SELECT Host_Cache_Size = @@SESSION.Host_Cache_Size; #let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; #--exec echo "wait" > $restart_file -#--shutdown_server 10 +#--shutdown_server #--source include/wait_until_disconnected.inc #-- exec echo "restart:--bind-address=$bind_ip " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect #-- enable_reconnect diff --git a/mysql-test/main/init_file_set_password-7656.test b/mysql-test/main/init_file_set_password-7656.test index c695d01b675..5e7a24fcf7f 100644 --- a/mysql-test/main/init_file_set_password-7656.test +++ b/mysql-test/main/init_file_set_password-7656.test @@ -15,7 +15,7 @@ EOF --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc --exec echo "restart:--init-file=$MYSQLTEST_VARDIR/init.file " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect diff --git a/mysql-test/main/log_errchk.test b/mysql-test/main/log_errchk.test index 2808458e9f1..1afc0e29f3a 100644 --- a/mysql-test/main/log_errchk.test +++ b/mysql-test/main/log_errchk.test @@ -31,7 +31,7 @@ --echo # and slow query log file. # Restart server with fifo file as general log file. --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---shutdown_server 60 +--shutdown_server --source include/wait_until_disconnected.inc --enable_reconnect # Write file to make mysql-test-run.pl start up the server again diff --git a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result index 9de067b0e3f..a7426327ecf 100644 --- a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result @@ -15,6 +15,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -32,6 +33,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; \d | @@ -57,6 +59,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -71,6 +74,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, (@time_zone_id, 0, 0, 0, 'GMT') ; Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; \d | @@ -160,6 +164,8 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; \d | diff --git a/mysql-test/main/type_datetime.result b/mysql-test/main/type_datetime.result index 5b27d02d28f..3c1baf82167 100644 --- a/mysql-test/main/type_datetime.result +++ b/mysql-test/main/type_datetime.result @@ -57,6 +57,7 @@ select * from t1; t 0000-00-00 00:00:00 drop table t1; +SET TIMESTAMP=UNIX_TIMESTAMP('2020-08-11 00:00:01'); CREATE TABLE t1 (a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); Warnings: @@ -65,6 +66,7 @@ select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1; date_format(a,"%Y-%m-%d")=b right(a+0,6)=c+0 a=d+0 1 1 1 drop table t1; +SET TIMESTAMP=DEFAULT; CREATE TABLE t1 (a datetime not null); insert into t1 values (0); select * from t1 where a is null; @@ -298,8 +300,10 @@ f2 f3 select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15"; f2 2001-04-15 00:00:00 +SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:01'); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); 1 +SET timestamp=DEFAULT; drop table t1; create table t1 (f1 date); insert into t1 values('01-01-01'),('01-01-02'),('01-01-03'); diff --git a/mysql-test/main/type_datetime.test b/mysql-test/main/type_datetime.test index c8ad240d817..4fddf1c1a74 100644 --- a/mysql-test/main/type_datetime.test +++ b/mysql-test/main/type_datetime.test @@ -32,10 +32,12 @@ drop table t1; # Test insert of now() and curtime() # +SET TIMESTAMP=UNIX_TIMESTAMP('2020-08-11 00:00:01'); CREATE TABLE t1 (a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1; drop table t1; +SET TIMESTAMP=DEFAULT; # # Test of datetime and not null @@ -201,6 +203,7 @@ drop table t1; # # Bug#16377: Wrong DATE/DATETIME comparison in BETWEEN function. # + create table t1 (f1 date, f2 datetime, f3 timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); insert into t1 values('2001-01-01','2001-01-01 01:01:01','2001-01-01 01:01:01'); insert into t1 values('2001-02-05','2001-02-05 00:00:00','2001-02-05 01:01:01'); @@ -214,7 +217,9 @@ select f1, f2, f3 from t1 where cast(f1 as datetime) between f2 and select f2 from t1 where '2001-04-10 12:34:56' between f2 and '01-05-01'; select f2, f3 from t1 where '01-03-10' between f2 and f3; select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15"; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:01'); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); +SET timestamp=DEFAULT; drop table t1; # diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index 8ef8e981f57..ead494e3ace 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -2286,5 +2286,127 @@ SELECT '1972-11-06 16:58:58' < TIME'20:31:05'; '1972-11-06 16:58:58' < TIME'20:31:05' 1 # +# MDEV-23525 Wrong result of MIN(time_expr) and MAX(time_expr) with GROUP BY +# +SET timestamp=UNIX_TIMESTAMP('2020-08-21 18:19:20'); +CREATE PROCEDURE p1() +BEGIN +SELECT MIN(t), MAX(t) FROM t1; +SELECT i, MIN(t), MAX(t) FROM t1 GROUP BY i; +SELECT i, MIN(COALESCE(t)), MAX(COALESCE(t)) FROM t1 GROUP BY i; +SELECT i, MIN(t+INTERVAL 1 SECOND), MAX(t+INTERVAL 1 SECOND) FROM t1 GROUP BY i; +SELECT i, MIN(TIME'10:20:30'+INTERVAL 1 SECOND) FROM t1 GROUP BY i; +SELECT i, MIN(CURRENT_TIME), MAX(CURRENT_TIME) FROM t1 GROUP BY i; +SELECT +i, +MIN((SELECT MAX(CURRENT_TIME) FROM t1)), +MAX((SELECT MAX(CURRENT_TIME) FROM t1)) +FROM t1 GROUP BY i; +SELECT +i, +MIN(NAME_CONST('name',TIME'10:20:30')), +MAX(NAME_CONST('name',TIME'10:20:30')) +FROM t1 GROUP BY i; +EXECUTE IMMEDIATE "SELECT i, MIN(?),MAX(?) FROM t1 GROUP BY i" + USING TIME'10:20:30', TIME'10:20:30'; +END; +$$ +CREATE TABLE t1 (i INT, t TIME); +INSERT INTO t1 VALUES (1,'10:20:30'); +INSERT INTO t1 VALUES (1,'100:20:20'); +CALL p1; +MIN(t) MAX(t) +10:20:30 100:20:20 +i MIN(t) MAX(t) +1 10:20:30 100:20:20 +i MIN(COALESCE(t)) MAX(COALESCE(t)) +1 10:20:30 100:20:20 +i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND) +1 10:20:31 100:20:21 +i MIN(TIME'10:20:30'+INTERVAL 1 SECOND) +1 10:20:31 +i MIN(CURRENT_TIME) MAX(CURRENT_TIME) +1 18:19:20 18:19:20 +i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1)) +1 18:19:20 18:19:20 +i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30')) +1 10:20:30 10:20:30 +i MIN(?) MAX(?) +1 10:20:30 10:20:30 +DROP TABLE t1; +CREATE TABLE t1 (i INT, t TIME(3)); +INSERT INTO t1 VALUES (1,'10:20:30.123'); +INSERT INTO t1 VALUES (1,'100:20:20.123'); +CALL p1; +MIN(t) MAX(t) +10:20:30.123 100:20:20.123 +i MIN(t) MAX(t) +1 10:20:30.123 100:20:20.123 +i MIN(COALESCE(t)) MAX(COALESCE(t)) +1 10:20:30.123 100:20:20.123 +i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND) +1 10:20:31.123 100:20:21.123 +i MIN(TIME'10:20:30'+INTERVAL 1 SECOND) +1 10:20:31 +i MIN(CURRENT_TIME) MAX(CURRENT_TIME) +1 18:19:20 18:19:20 +i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1)) +1 18:19:20 18:19:20 +i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30')) +1 10:20:30 10:20:30 +i MIN(?) MAX(?) +1 10:20:30 10:20:30 +DROP TABLE t1; +CREATE TABLE t1 (i INT, t TIME(6)); +INSERT INTO t1 VALUES (1,'10:20:30.123456'); +INSERT INTO t1 VALUES (1,'100:20:20.123456'); +CALL p1; +MIN(t) MAX(t) +10:20:30.123456 100:20:20.123456 +i MIN(t) MAX(t) +1 10:20:30.123456 100:20:20.123456 +i MIN(COALESCE(t)) MAX(COALESCE(t)) +1 10:20:30.123456 100:20:20.123456 +i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND) +1 10:20:31.123456 100:20:21.123456 +i MIN(TIME'10:20:30'+INTERVAL 1 SECOND) +1 10:20:31 +i MIN(CURRENT_TIME) MAX(CURRENT_TIME) +1 18:19:20 18:19:20 +i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1)) +1 18:19:20 18:19:20 +i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30')) +1 10:20:30 10:20:30 +i MIN(?) MAX(?) +1 10:20:30 10:20:30 +DROP TABLE t1; +SET @@global.mysql56_temporal_format=false; +CREATE TABLE t1 (i INT, t TIME(6)); +INSERT INTO t1 VALUES (1,'10:20:30.123456'); +INSERT INTO t1 VALUES (1,'100:20:20.123456'); +CALL p1; +MIN(t) MAX(t) +10:20:30.123456 100:20:20.123456 +i MIN(t) MAX(t) +1 10:20:30.123456 100:20:20.123456 +i MIN(COALESCE(t)) MAX(COALESCE(t)) +1 10:20:30.123456 100:20:20.123456 +i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND) +1 10:20:31.123456 100:20:21.123456 +i MIN(TIME'10:20:30'+INTERVAL 1 SECOND) +1 10:20:31 +i MIN(CURRENT_TIME) MAX(CURRENT_TIME) +1 18:19:20 18:19:20 +i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1)) +1 18:19:20 18:19:20 +i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30')) +1 10:20:30 10:20:30 +i MIN(?) MAX(?) +1 10:20:30 10:20:30 +DROP TABLE t1; +SET @@global.mysql56_temporal_format=default; +DROP PROCEDURE p1; +SET timestamp=DEFAULT; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index 521953a5078..1d4d157b976 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -1491,5 +1491,65 @@ DROP TABLE t1; SELECT '1972-11-06 16:58:58' < TIME'20:31:05'; --echo # +--echo # MDEV-23525 Wrong result of MIN(time_expr) and MAX(time_expr) with GROUP BY +--echo # + +SET timestamp=UNIX_TIMESTAMP('2020-08-21 18:19:20'); + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + SELECT MIN(t), MAX(t) FROM t1; + SELECT i, MIN(t), MAX(t) FROM t1 GROUP BY i; + SELECT i, MIN(COALESCE(t)), MAX(COALESCE(t)) FROM t1 GROUP BY i; + SELECT i, MIN(t+INTERVAL 1 SECOND), MAX(t+INTERVAL 1 SECOND) FROM t1 GROUP BY i; + SELECT i, MIN(TIME'10:20:30'+INTERVAL 1 SECOND) FROM t1 GROUP BY i; + SELECT i, MIN(CURRENT_TIME), MAX(CURRENT_TIME) FROM t1 GROUP BY i; + SELECT + i, + MIN((SELECT MAX(CURRENT_TIME) FROM t1)), + MAX((SELECT MAX(CURRENT_TIME) FROM t1)) + FROM t1 GROUP BY i; + SELECT + i, + MIN(NAME_CONST('name',TIME'10:20:30')), + MAX(NAME_CONST('name',TIME'10:20:30')) + FROM t1 GROUP BY i; + EXECUTE IMMEDIATE "SELECT i, MIN(?),MAX(?) FROM t1 GROUP BY i" + USING TIME'10:20:30', TIME'10:20:30'; +END; +$$ +DELIMITER ;$$ + +CREATE TABLE t1 (i INT, t TIME); +INSERT INTO t1 VALUES (1,'10:20:30'); +INSERT INTO t1 VALUES (1,'100:20:20'); +CALL p1; +DROP TABLE t1; + +CREATE TABLE t1 (i INT, t TIME(3)); +INSERT INTO t1 VALUES (1,'10:20:30.123'); +INSERT INTO t1 VALUES (1,'100:20:20.123'); +CALL p1; +DROP TABLE t1; + +CREATE TABLE t1 (i INT, t TIME(6)); +INSERT INTO t1 VALUES (1,'10:20:30.123456'); +INSERT INTO t1 VALUES (1,'100:20:20.123456'); +CALL p1; +DROP TABLE t1; + +SET @@global.mysql56_temporal_format=false; +CREATE TABLE t1 (i INT, t TIME(6)); +INSERT INTO t1 VALUES (1,'10:20:30.123456'); +INSERT INTO t1 VALUES (1,'100:20:20.123456'); +CALL p1; +DROP TABLE t1; +SET @@global.mysql56_temporal_format=default; + +DROP PROCEDURE p1; +SET timestamp=DEFAULT; + +--echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/binlog/t/binlog_max_extension.test b/mysql-test/suite/binlog/t/binlog_max_extension.test index 199a31ea05c..81e357448f6 100644 --- a/mysql-test/suite/binlog/t/binlog_max_extension.test +++ b/mysql-test/suite/binlog/t/binlog_max_extension.test @@ -41,7 +41,7 @@ RESET MASTER; # 1. Stop master server -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server 10 +-- shutdown_server -- source include/wait_until_disconnected.inc # 2. Prepare log and index file @@ -70,7 +70,7 @@ FLUSH LOGS; # 1. Stop the server -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server 10 +-- shutdown_server -- source include/wait_until_disconnected.inc # 2. Undo changes to index and log files diff --git a/mysql-test/suite/binlog_encryption/restart_server.inc b/mysql-test/suite/binlog_encryption/restart_server.inc index 6cd0788cf43..8f0fe7d8970 100644 --- a/mysql-test/suite/binlog_encryption/restart_server.inc +++ b/mysql-test/suite/binlog_encryption/restart_server.inc @@ -22,7 +22,7 @@ --enable_reconnect --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect -shutdown_server 10; +shutdown_server; --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/galera/r/galera_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result index 9fc7febbea5..9233d95b970 100644 --- a/mysql-test/suite/galera/r/galera_ist_progress.result +++ b/mysql-test/suite/galera/r/galera_ist_progress.result @@ -1,6 +1,12 @@ +connection node_2; +connection node_1; +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +connection node_1; +connection node_2; SET SESSION wsrep_on = OFF; SET SESSION wsrep_on = ON; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); @@ -12,8 +18,13 @@ INSERT INTO t1 VALUES (7); INSERT INTO t1 VALUES (8); INSERT INTO t1 VALUES (9); INSERT INTO t1 VALUES (10); +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; -include/assert_grep.inc [Receiving IST: 11 writesets, seqnos] -include/assert_grep.inc [Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete] -include/assert_grep.inc [Receiving IST\.\.\.100\.0% \(11/11 events\) complete] +connection node_1; +connection node_2; +connection node_1; +include/assert_grep.inc [Receiving IST: 13 writesets, seqnos 3-15] +include/assert_grep.inc [Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete] +include/assert_grep.inc [Receiving IST\.\.\.100\.0% \(13/13 events\) complete] +connection node_1; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/mdev-22543.result b/mysql-test/suite/galera/r/mdev-22543.result new file mode 100644 index 00000000000..9386b7405d4 --- /dev/null +++ b/mysql-test/suite/galera/r/mdev-22543.result @@ -0,0 +1,19 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT); +INSERT INTO t1 VALUES (1, 1); +SET DEBUG_SYNC = "before_lock_tables_takes_lock SIGNAL sync_point_reached WAIT_FOR sync_point_continue"; +UPDATE t1 SET f2 = 2 WHERE f1 = 1; +connection node_1_ctrl; +SET DEBUG_SYNC = "now WAIT_FOR sync_point_reached"; +connection node_2; +connection node_1_ctrl; +SET DEBUG_SYNC = "now SIGNAL sync_point_continue"; +connection node_1; +SET DEBUG_SYNC = "RESET"; +connection node_2; +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ist_progress.test b/mysql-test/suite/galera/t/galera_ist_progress.test index dd93161eab8..3d7c53bd1eb 100644 --- a/mysql-test/suite/galera/t/galera_ist_progress.test +++ b/mysql-test/suite/galera/t/galera_ist_progress.test @@ -5,6 +5,7 @@ --source include/galera_cluster.inc # This could cause out of storage if run /dev/shm --source include/big_test.inc +--source include/force_restart.inc # Isolate node #2 --connection node_2 @@ -58,16 +59,16 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err --let $assert_only_after = Need state transfer ---let $assert_text = Receiving IST: 1[13] writesets ---let $assert_select = Receiving IST: 1[13] writesets +--let $assert_text = Receiving IST: 13 writesets, seqnos 3-15 +--let $assert_select = Receiving IST: 13 writesets, seqnos 3-15 --source include/assert_grep.inc ---let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete ---let $assert_select = Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete +--let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete +--let $assert_select = Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete --source include/assert_grep.inc ---let $assert_text = Receiving IST\.\.\.100\.0% \(11/11 events\) complete ---let $assert_select = Receiving IST\.\.\.100\.0% \(11/11 events\) complete +--let $assert_text = Receiving IST\.\.\.100\.0% \(13/13 events\) complete +--let $assert_select = Receiving IST\.\.\.100\.0% \(13/13 events\) complete --source include/assert_grep.inc # Cleanup diff --git a/mysql-test/suite/galera/t/mdev-22543.test b/mysql-test/suite/galera/t/mdev-22543.test new file mode 100644 index 00000000000..53662e36942 --- /dev/null +++ b/mysql-test/suite/galera/t/mdev-22543.test @@ -0,0 +1,58 @@ +# The test verifies that the FLUSH TABLES WITH READ LOCK does not +# time out if it needs to wait for another MDL lock for short duration +# during SST donation. + +--source include/galera_cluster.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--let $node_1 = node_1 +--let $node_2 = node_2 +--source include/auto_increment_offset_save.inc + +--let $galera_connection_name = node_1_ctrl +--let $galera_server_number = 1 +--source include/galera_connect.inc + +# +# Run UPDATE on node_1 and make it block before table locks are taken. +# This should block FTWRL. +# +--connection node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT); +INSERT INTO t1 VALUES (1, 1); +SET DEBUG_SYNC = "before_lock_tables_takes_lock SIGNAL sync_point_reached WAIT_FOR sync_point_continue"; +--send UPDATE t1 SET f2 = 2 WHERE f1 = 1 + +--connection node_1_ctrl +SET DEBUG_SYNC = "now WAIT_FOR sync_point_reached"; + +# +# Restart node_2, force SST. +# +--connection node_2 +--source include/shutdown_mysqld.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat +# Restart without waiting. The UPDATE should block FTWRL on node_1, +# so the SST cannot be completed and node_2 cannot join before +# UPDATE connection is signalled to continue. +--exec echo "restart:$start_mysqld_params" > $_expect_file_name +# If the bug is present, FTWRL times out on node_1 in couple of +# seconds and node_2 fails to join. +--sleep 10 + +--connection node_1_ctrl +SET DEBUG_SYNC = "now SIGNAL sync_point_continue"; + +--connection node_1 +--reap +SET DEBUG_SYNC = "RESET"; + +--connection node_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection node_1 +DROP TABLE t1; + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera_3nodes/r/GCF-354.result b/mysql-test/suite/galera_3nodes/r/GCF-354.result index b7ab3014ff5..dad57fe15ec 100644 --- a/mysql-test/suite/galera_3nodes/r/GCF-354.result +++ b/mysql-test/suite/galera_3nodes/r/GCF-354.result @@ -5,6 +5,9 @@ SET wsrep_on=OFF; DROP SCHEMA test; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; +connection node_1; +connection node_2; +connection node_3; SET wsrep_on=OFF; CREATE TABLE test.t1 (f1 INTEGER); connection node_1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result index 0461f1f1feb..a60e2bbb6cc 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result @@ -1,40 +1,81 @@ +connection node_2; +connection node_1; +connection node_1; CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; INSERT INTO t1 VALUES (1, 1); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (2, 3); +connection node_2; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET wsrep_sync_wait = 0; SET wsrep_on = OFF; SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (3, 2); +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_3; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (4, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (5, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (6, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (7, 2); +connection node_3; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (8, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; SET GLOBAL wsrep_provider_options = 'signal=before_send_state_request'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_2; INSERT INTO t1 VALUES (9, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; DROP TABLE t1; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_2; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_3; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result index d878f60ca6b..7e75bc4b08a 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result @@ -1,18 +1,39 @@ +connection node_2; +connection node_1; +connection node_1; CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; INSERT INTO t1 VALUES (1, 1); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (2, 3); +connection node_2; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET wsrep_sync_wait = 0; SET wsrep_on = OFF; SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (3, 2); +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_3; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (4, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (5, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; SET SESSION wsrep_on = 0; @@ -24,18 +45,35 @@ SET SESSION wsrep_on = 0; SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; VARIABLE_NAME VARIABLE_VALUE WSREP_DEBUG_SYNC_WAITERS after_shift_to_joining +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (6, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (7, 2); +connection node_3; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (8, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_2; INSERT INTO t1 VALUES (9, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; @@ -44,7 +82,10 @@ VARIABLE_NAME VARIABLE_VALUE WSREP_DEBUG_SYNC_WAITERS process_primary_configuration SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; DROP TABLE t1; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_2; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_3; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result index df0a924029c..ea10edfc62c 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result @@ -1,44 +1,85 @@ +connection node_2; +connection node_1; +connection node_1; CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; INSERT INTO t1 VALUES (1, 1); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (2, 3); +connection node_2; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET wsrep_sync_wait = 0; SET wsrep_on = OFF; SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (3, 2); +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_3; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (4, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (5, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; SET GLOBAL wsrep_provider_options = 'signal=before_send_state_request'; 4 SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; VARIABLE_NAME VARIABLE_VALUE WSREP_DEBUG_SYNC_WAITERS +connection node_3; INSERT INTO t1 VALUES (6, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; INSERT INTO t1 VALUES (7, 2); +connection node_3; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; SET GLOBAL wsrep_provider_options = 'dbug='; SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_2; +connection node_3; INSERT INTO t1 VALUES (8, 3); +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; +connection node_2; INSERT INTO t1 VALUES (9, 2); +connection node_3; +connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; @@ -48,8 +89,11 @@ SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 0; SET GLOBAL wsrep_provider_options = 'dbug='; SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +connection node_1; DROP TABLE t1; call mtr.add_suppression("WSREP: Send action {\(.*\), STATE_REQUEST} returned -107 \\(Transport endpoint is not connected\\)"); call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_2; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +connection node_3; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc index 6a2fcd15be0..61e304a7626 100644 --- a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc +++ b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc @@ -263,3 +263,10 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; + +# pk(o1,o2) to pk(o1,o2,autoinc) must not sort +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index 6e8f4d721ae..b1de6be804a 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -53,6 +53,13 @@ ALTER TABLE t1 DROP a; ERROR HY000: Cannot drop index 'a': needed in a foreign key constraint ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; +# +# MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +# +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; create table t1 (a int) transactional=1 engine=aria; create table t2 (a int) transactional=1 engine=innodb; show create table t1; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 00563d397f3..854b53b3083 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -655,6 +655,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # MDEV-17187 table doesn't exist in engine after ALTER other tables # with CONSTRAINTs # +call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`\\.`t2` has or is referenced in foreign key constraints which are not compatible with the new table definition."); set foreign_key_checks=on; create table t1 (id int not null primary key) engine=innodb; create table t2 (id int not null primary key, fid int not null, @@ -710,6 +711,32 @@ drop table t1,t2; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails drop table t1,t2; ERROR 42S02: Unknown table 'test.t2' +# +# MDEV-22934 Table disappear after two alter table command +# +CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT, +f2 INT NOT NULL, +PRIMARY KEY (f1), INDEX (f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL, +f2 INT NOT NULL, f3 INT NOT NULL, +PRIMARY KEY(f1, f2), UNIQUE KEY(f2), +CONSTRAINT `t2_ibfk_1` FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE CASCADE, +CONSTRAINT `t2_ibfk_2` FOREIGN KEY (f1) REFERENCES t1(f1) ON DELETE CASCADE +) ENGINE=InnoDB; +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 DROP PRIMARY KEY, ADD PRIMARY KEY(f3), ALGORITHM=INPLACE; +ALTER TABLE t2 DROP INDEX `f2`, ALGORITHM=COPY; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + `f2` int(11) NOT NULL, + `f3` int(11) NOT NULL, + PRIMARY KEY (`f3`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB; +ERROR 42S01: Table 't2' already exists +DROP TABLE t2, t1; # End of 10.2 tests CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; @@ -761,11 +788,12 @@ set default_storage_engine= default; # # MDEV-21690 LeakSanitizer: detected memory leaks in mem_heap_create_block_func # +SET FOREIGN_KEY_CHECKS=1; CREATE TABLE t1 (a TEXT, b TEXT) ENGINE=InnoDB; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (b); ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +SET FOREIGN_KEY_CHECKS=DEFAULT; DROP TABLE t1; -# End of 10.5 tests # # MDEV-22602 Disable UPDATE CASCADE for SQL constraints # @@ -784,3 +812,4 @@ create or replace table t1 (a varchar(4096) unique) engine=innodb; create or replace table t2 (pk int primary key, a varchar(4096) unique, foreign key(a) references t1(a) on update cascade) engine=innodb; ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") drop table t1; +# End of 10.5 tests diff --git a/mysql-test/suite/innodb/r/innodb-64k.result b/mysql-test/suite/innodb/r/innodb-64k.result index 8f8e031bce2..f8dad893d0e 100644 --- a/mysql-test/suite/innodb/r/innodb-64k.result +++ b/mysql-test/suite/innodb/r/innodb-64k.result @@ -1081,3 +1081,10 @@ update t2 set col145=@b; COMMIT; drop table t2; DROP TABLE t1; +# +# MDEV-19526 heap number overflow +# +CREATE TABLE t1(a SMALLINT NOT NULL UNIQUE AUTO_INCREMENT, KEY(a)) +ENGINE=InnoDB; +INSERT INTO t1 (a) SELECT seq FROM seq_1_to_8191; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result index 5d161e5e6ca..daef31d2caa 100644 --- a/mysql-test/suite/innodb/r/innodb-index-debug.result +++ b/mysql-test/suite/innodb/r/innodb-index-debug.result @@ -323,4 +323,9 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; SET DEBUG_DBUG = @saved_debug_dbug; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index 4eba99950c7..7e58bfe38e5 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -1907,6 +1907,11 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; # # MDEV-15325 Incomplete validation of missing tablespace during recovery # diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 1cd62911e81..2313c415496 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2544,7 +2544,6 @@ set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; create table t1(a varchar(10) primary key) engine = innodb; alter table t1 modify column a int; -Got one of the listed errors set foreign_key_checks=1; drop table t2,t1; set foreign_key_checks=0; @@ -2553,6 +2552,7 @@ create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin alter table t1 convert to character set utf8; set foreign_key_checks=1; drop table t2,t1; +call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition."); set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index d5acc872b49..1dfc709a775 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -410,4 +410,10 @@ CREATE TABLE t (i INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t SET i=1; ALTER TABLE t ADD e CHAR(255) CHARACTER SET UTF32 FIRST, ALGORITHM=INSTANT; DROP TABLE t; +# +# MDEV-23499 Assertion c.same_type(*o) failed +# +CREATE TABLE t (pk SERIAL, b TEXT CHARACTER SET utf8) ENGINE=InnoDB; +ALTER TABLE t MODIFY b TEXT CHARACTER SET utf8mb4 FIRST; +DROP TABLE t; SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index 6d6b1d9ab11..26f3a9f013f 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc # # MDEV-11995 ALTER TABLE proceeds despite reporting ER_TOO_LONG_KEY error # @@ -60,6 +61,14 @@ ALTER TABLE t1 DROP a; ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; +--echo # +--echo # MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +--echo # +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; + # # Check that innodb supports transactional=1 # diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 4719384cd65..c595cf92690 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -657,6 +657,8 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # with CONSTRAINTs --echo # +call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`\\.`t2` has or is referenced in foreign key constraints which are not compatible with the new table definition."); + set foreign_key_checks=on; create table t1 (id int not null primary key) engine=innodb; create table t2 (id int not null primary key, fid int not null, @@ -698,6 +700,27 @@ drop table t1,t2; --error ER_BAD_TABLE_ERROR drop table t1,t2; +--echo # +--echo # MDEV-22934 Table disappear after two alter table command +--echo # +CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT, + f2 INT NOT NULL, + PRIMARY KEY (f1), INDEX (f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL, + f2 INT NOT NULL, f3 INT NOT NULL, + PRIMARY KEY(f1, f2), UNIQUE KEY(f2), +CONSTRAINT `t2_ibfk_1` FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE CASCADE, +CONSTRAINT `t2_ibfk_2` FOREIGN KEY (f1) REFERENCES t1(f1) ON DELETE CASCADE +) ENGINE=InnoDB; + +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 DROP PRIMARY KEY, ADD PRIMARY KEY(f3), ALGORITHM=INPLACE; +ALTER TABLE t2 DROP INDEX `f2`, ALGORITHM=COPY; +SHOW CREATE TABLE t2; +--error ER_TABLE_EXISTS_ERROR +CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB; +DROP TABLE t2, t1; + --echo # End of 10.2 tests # MDEV-21792 Server aborts upon attempt to create foreign key on spatial field @@ -732,15 +755,15 @@ set default_storage_engine= default; --echo # --echo # MDEV-21690 LeakSanitizer: detected memory leaks in mem_heap_create_block_func --echo # +SET FOREIGN_KEY_CHECKS=1; CREATE TABLE t1 (a TEXT, b TEXT) ENGINE=InnoDB; --error ER_CANT_CREATE_TABLE ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (b); +SET FOREIGN_KEY_CHECKS=DEFAULT; # Cleanup DROP TABLE t1; ---echo # End of 10.5 tests - --echo # --echo # MDEV-22602 Disable UPDATE CASCADE for SQL constraints --echo # @@ -764,4 +787,6 @@ create or replace table t2 (pk int primary key, a varchar(4096) unique, foreign drop table t1; +--echo # End of 10.5 tests + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-64k.test b/mysql-test/suite/innodb/t/innodb-64k.test index b091eee6d57..62d7b929ba1 100644 --- a/mysql-test/suite/innodb/t/innodb-64k.test +++ b/mysql-test/suite/innodb/t/innodb-64k.test @@ -2,6 +2,7 @@ # Tests for setting innodb-page-size=64k; --source include/have_innodb.inc --source include/have_innodb_64k.inc +--source include/have_sequence.inc call mtr.add_suppression('InnoDB: Cannot add field.*because after adding it, the row size is'); @@ -638,3 +639,11 @@ COMMIT; drop table t2; DROP TABLE t1; + +--echo # +--echo # MDEV-19526 heap number overflow +--echo # +CREATE TABLE t1(a SMALLINT NOT NULL UNIQUE AUTO_INCREMENT, KEY(a)) +ENGINE=InnoDB; +INSERT INTO t1 (a) SELECT seq FROM seq_1_to_8191; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-corrupted-table.test b/mysql-test/suite/innodb/t/innodb-corrupted-table.test index d1384d20c7b..a064f08d677 100644 --- a/mysql-test/suite/innodb/t/innodb-corrupted-table.test +++ b/mysql-test/suite/innodb/t/innodb-corrupted-table.test @@ -24,7 +24,7 @@ alter table t1 add primary key (pk); --echo # Stop the server, replace the frm with the old one and restart the server --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc --remove_file $datadir/test/t1.frm diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index dfb4da3a63d..5a718265624 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1622,7 +1622,6 @@ drop table t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; create table t1(a varchar(10) primary key) engine = innodb; --- error 1025,1025 alter table t1 modify column a int; set foreign_key_checks=1; drop table t2,t1; @@ -1638,6 +1637,7 @@ drop table t2,t1; # test that RENAME does not allow invalid charsets when f_k_c is 0 +call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition."); set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; diff --git a/mysql-test/suite/innodb/t/innodb_bug60196.test b/mysql-test/suite/innodb/t/innodb_bug60196.test index e479b8d6b82..7f1f5c40585 100644 --- a/mysql-test/suite/innodb/t/innodb_bug60196.test +++ b/mysql-test/suite/innodb/t/innodb_bug60196.test @@ -50,7 +50,7 @@ SELECT * FROM bug_60196; -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Send a shutdown request to the server --- shutdown_server 10 +-- shutdown_server # Call script that will poll the server waiting for it to disapear -- source include/wait_until_disconnected.inc @@ -124,7 +124,7 @@ SELECT * FROM Bug_60309; -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Send a shutdown request to the server --- shutdown_server 10 +-- shutdown_server # Call script that will poll the server waiting for it to disapear -- source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 3dd0bedbbb6..4548e978f86 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -430,4 +430,11 @@ INSERT INTO t SET i=1; ALTER TABLE t ADD e CHAR(255) CHARACTER SET UTF32 FIRST, ALGORITHM=INSTANT; DROP TABLE t; +--echo # +--echo # MDEV-23499 Assertion c.same_type(*o) failed +--echo # +CREATE TABLE t (pk SERIAL, b TEXT CHARACTER SET utf8) ENGINE=InnoDB; +ALTER TABLE t MODIFY b TEXT CHARACTER SET utf8mb4 FIRST; +DROP TABLE t; + SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/maria/maria-connect.result b/mysql-test/suite/maria/maria-connect.result index 5c8b5524d69..84195780cf8 100644 --- a/mysql-test/suite/maria/maria-connect.result +++ b/mysql-test/suite/maria/maria-connect.result @@ -11,7 +11,7 @@ ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show warnings; Level Code Message Error 1062 Duplicate entry '2' for key 'PRIMARY' -Note 4173 Engine Aria does not support rollback. Changes where committed during rollback call +Note 4173 Engine Aria does not support rollback. Changes were committed during rollback call Warning 1196 Some non-transactional changed tables couldn't be rolled back select * from t1; a diff --git a/mysql-test/suite/multi_source/info_logs.test b/mysql-test/suite/multi_source/info_logs.test index ef504e06a2f..234e317e5ce 100644 --- a/mysql-test/suite/multi_source/info_logs.test +++ b/mysql-test/suite/multi_source/info_logs.test @@ -150,7 +150,7 @@ show all slaves status; --append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect restart EOF ---shutdown_server 60 +--shutdown_server --source include/wait_until_connected_again.inc --source include/wait_for_slave_to_start.inc set default_master_connection = 'MASTER 2.2'; diff --git a/mysql-test/suite/roles/acl_load_mutex-5170.test b/mysql-test/suite/roles/acl_load_mutex-5170.test index 22b9dffb5fd..76d817be055 100644 --- a/mysql-test/suite/roles/acl_load_mutex-5170.test +++ b/mysql-test/suite/roles/acl_load_mutex-5170.test @@ -10,7 +10,7 @@ flush tables; --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF ---shutdown_server 60 +--shutdown_server --source include/wait_until_disconnected.inc --enable_reconnect --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect diff --git a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc index 17720e94dc8..4726bbe1889 100644 --- a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc +++ b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc @@ -40,7 +40,7 @@ SET @@GLOBAL.debug_dbug="+d,simulate_delay_at_shutdown"; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF -# --shutdown_server 60 +# --shutdown_server --send SHUTDOWN WAIT FOR ALL SLAVES --reap --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test index 3c5542f4b2f..e72d1c3ef47 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test @@ -626,7 +626,7 @@ SELECT * FROM t1 WHERE a >= 30 ORDER BY a; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF -shutdown_server 10; +shutdown_server; --source include/wait_until_disconnected.inc --remove_file $datadir/master-bin.state diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 53d62805c58..fd4cdf71f6f 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -29,7 +29,7 @@ CHANGE MASTER TO master_use_gtid=current_pos; wait EOF FLUSH LOGS; ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection server_1 @@ -70,7 +70,7 @@ SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect @@ -103,7 +103,7 @@ SELECT * FROM t1 ORDER BY a; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -148,7 +148,7 @@ SELECT * FROM t1 ORDER BY a; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -191,7 +191,7 @@ SET sql_log_bin= 1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -221,7 +221,7 @@ SELECT * FROM t1 ORDER BY a; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -237,7 +237,7 @@ SET sql_log_bin= 1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -273,7 +273,7 @@ SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -305,7 +305,7 @@ SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc # Let the slave mysqld server start again. diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test index db1ec3d4d22..e3caccde6b4 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev12179.test +++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test @@ -57,7 +57,7 @@ SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection server_1 @@ -96,7 +96,7 @@ SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection server_1 @@ -134,7 +134,7 @@ SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection server_1 @@ -178,7 +178,7 @@ SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection server_1 @@ -275,7 +275,7 @@ while (!$done) wait EOF --connection server_2 ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --echo *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test index 1d951cc7456..093b7b92413 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev382.test +++ b/mysql-test/suite/rpl/t/rpl_mdev382.test @@ -208,7 +208,7 @@ SELECT * FROM `db1``; select 'oops!'`.`t``1` ORDER BY 1; wait-rpl_mdev382.test EOF ---shutdown_server 30 +--shutdown_server --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect restart-rpl_mdev382.test diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partition.test b/mysql-test/suite/rpl/t/rpl_parallel_partition.test index 37dce9fef80..ea6c5dca6be 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_partition.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_partition.test @@ -42,7 +42,7 @@ ALTER TABLE `E` REMOVE PARTITIONING; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc --connection default --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/storage_engine/alter_tablespace.test b/mysql-test/suite/storage_engine/alter_tablespace.test index 3c4910069a0..1899da28320 100644 --- a/mysql-test/suite/storage_engine/alter_tablespace.test +++ b/mysql-test/suite/storage_engine/alter_tablespace.test @@ -46,7 +46,7 @@ wait EOF --enable_reconnect - --shutdown_server 60 + --shutdown_server --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/storage_engine/trx/xa_recovery.test b/mysql-test/suite/storage_engine/trx/xa_recovery.test index e17bb9d2ea4..f53640578cd 100644 --- a/mysql-test/suite/storage_engine/trx/xa_recovery.test +++ b/mysql-test/suite/storage_engine/trx/xa_recovery.test @@ -12,7 +12,7 @@ --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect restart EOF ---shutdown_server 60 +--shutdown_server --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index b8a566a27cb..2ef79a39b7a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -314,7 +314,7 @@ SESSION_VALUE NULL DEFAULT_VALUE zlib VARIABLE_SCOPE GLOBAL VARIABLE_TYPE ENUM -VARIABLE_COMMENT Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, or bzip2 +VARIABLE_COMMENT Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, bzip2, or snappy NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/wsrep/r/MDEV-22443.result b/mysql-test/suite/wsrep/r/MDEV-22443.result new file mode 100644 index 00000000000..ea07cbec5a0 --- /dev/null +++ b/mysql-test/suite/wsrep/r/MDEV-22443.result @@ -0,0 +1,3 @@ +SET SESSION wsrep_sync_wait=15; +SET SESSION wsrep_on=1; +START TRANSACTION READ WRITE; diff --git a/mysql-test/suite/wsrep/r/MDEV-23092.result b/mysql-test/suite/wsrep/r/MDEV-23092.result new file mode 100644 index 00000000000..d88aacf7d5c --- /dev/null +++ b/mysql-test/suite/wsrep/r/MDEV-23092.result @@ -0,0 +1,13 @@ +SET COLLATION_CONNECTION='utf16le_bin'; +SET GLOBAL wsrep_provider='/invalid/path/libgalera_smm.so'; +ERROR 42000: Variable 'wsrep_provider' can't be set to the value of '/' +SET GLOBAL wsrep_cluster_address='OFF'; +SET GLOBAL wsrep_slave_threads=10; +SELECT 1; +1 +1 +SET GLOBAL wsrep_cluster_address='gcomm://'; +SET GLOBAL wsrep_slave_threads=DEFAULT; +CALL mtr.add_suppression("wsrep_load()"); +CALL mtr.add_suppression("Failed to create a new provider"); +CALL mtr.add_suppression("Failed to load provider"); diff --git a/mysql-test/suite/wsrep/r/MDEV-23466.result b/mysql-test/suite/wsrep/r/MDEV-23466.result new file mode 100644 index 00000000000..a019704d7d3 --- /dev/null +++ b/mysql-test/suite/wsrep/r/MDEV-23466.result @@ -0,0 +1,3 @@ +SELECT WSREP_LAST_SEEN_GTID(); +WSREP_LAST_SEEN_GTID() +0-0-0 diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result index f219625b490..d5bbecfa7c2 100644 --- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result @@ -15,6 +15,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -32,6 +33,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; \d | @@ -57,6 +59,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -71,6 +74,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, (@time_zone_id, 0, 0, 0, 'GMT') ; Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; \d | diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result index 85c4d858be2..aff02cb413e 100644 --- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result +++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result @@ -9,6 +9,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -26,6 +27,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # Silent run @@ -36,6 +38,7 @@ TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; +START TRANSACTION; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); @@ -50,6 +53,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, (@time_zone_id, 0, 0, 0, 'GMT') ; Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # diff --git a/mysql-test/suite/wsrep/t/MDEV-22443.cnf b/mysql-test/suite/wsrep/t/MDEV-22443.cnf new file mode 100644 index 00000000000..851f2999a83 --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-22443.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=OFF +binlog-format=ROW +wsrep-provider=none +wsrep-cluster-address='gcomm://' +innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/wsrep/t/MDEV-22443.test b/mysql-test/suite/wsrep/t/MDEV-22443.test new file mode 100644 index 00000000000..674cb5ae2d8 --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-22443.test @@ -0,0 +1,12 @@ +# +# MDEV-22443: terminate called after throwing an instance of +# 'wsrep::runtime_error' in std::terminate on START TRANSACTION +# + +--source include/have_innodb.inc +--source include/have_wsrep.inc +--source include/have_binlog_format_row.inc + +SET SESSION wsrep_sync_wait=15; +SET SESSION wsrep_on=1; +START TRANSACTION READ WRITE; diff --git a/mysql-test/suite/wsrep/t/MDEV-23092.cnf b/mysql-test/suite/wsrep/t/MDEV-23092.cnf new file mode 100644 index 00000000000..851f2999a83 --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-23092.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=OFF +binlog-format=ROW +wsrep-provider=none +wsrep-cluster-address='gcomm://' +innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/wsrep/t/MDEV-23092.test b/mysql-test/suite/wsrep/t/MDEV-23092.test new file mode 100644 index 00000000000..92a6e392013 --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-23092.test @@ -0,0 +1,22 @@ +# +# MDEV-23092: SIGABRT in wsrep::server_state::provider when setting +# invalid wsrep_provider (on optimized builds) +# + +--source include/have_innodb.inc +--source include/have_wsrep.inc +--source include/have_binlog_format_row.inc + +SET COLLATION_CONNECTION='utf16le_bin'; +--error 1231 +SET GLOBAL wsrep_provider='/invalid/path/libgalera_smm.so'; +SET GLOBAL wsrep_cluster_address='OFF'; +SET GLOBAL wsrep_slave_threads=10; +SELECT 1; + +SET GLOBAL wsrep_cluster_address='gcomm://'; +SET GLOBAL wsrep_slave_threads=DEFAULT; + +CALL mtr.add_suppression("wsrep_load()"); +CALL mtr.add_suppression("Failed to create a new provider"); +CALL mtr.add_suppression("Failed to load provider"); diff --git a/mysql-test/suite/wsrep/t/MDEV-23466.cnf b/mysql-test/suite/wsrep/t/MDEV-23466.cnf new file mode 100644 index 00000000000..851f2999a83 --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-23466.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=OFF +binlog-format=ROW +wsrep-provider=none +wsrep-cluster-address='gcomm://' +innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/wsrep/t/MDEV-23466.test b/mysql-test/suite/wsrep/t/MDEV-23466.test new file mode 100644 index 00000000000..2615298226e --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-23466.test @@ -0,0 +1,10 @@ +# +# MDEV-23466: SIGABRT in wsrep::server_state::provider on +# SELECT WSREP_LAST_SEEN_GTID() on optimized builds +# + +--source include/have_innodb.inc +--source include/have_wsrep.inc +--source include/have_binlog_format_row.inc + +SELECT WSREP_LAST_SEEN_GTID(); diff --git a/mysys/crc32/crc32_arm64.c b/mysys/crc32/crc32_arm64.c index aae6f769002..a7eb2a47442 100644 --- a/mysys/crc32/crc32_arm64.c +++ b/mysys/crc32/crc32_arm64.c @@ -8,40 +8,49 @@ #include <asm/hwcap.h> #ifndef HWCAP_CRC32 -#define HWCAP_CRC32 (1 << 7) +# define HWCAP_CRC32 (1 << 7) #endif +#ifndef HWCAP_PMULL +# define HWCAP_PMULL (1 << 4) +#endif + +static int pmull_supported; + /* ARM made crc32 default from ARMv8.1 but optional in ARMv8A -so the runtime check. */ + * Runtime check API. + */ int crc32_aarch64_available(void) { unsigned long auxv= getauxval(AT_HWCAP); return (auxv & HWCAP_CRC32) != 0; } -#if defined(HAVE_ARMV8_CRYPTO) +const char *crc32c_aarch64_available(void) +{ + unsigned long auxv= getauxval(AT_HWCAP); -#ifndef HWCAP_PMULL -#define HWCAP_PMULL (1 << 4) -#endif + if (!(auxv & HWCAP_CRC32)) + return NULL; -/* Check if target ARM machine support crc32 + pmull for computing crc32c */ -int crc32c_aarch64_available(void) -{ - return !(~getauxval(AT_HWCAP) & (HWCAP_CRC32 | HWCAP_PMULL)); + pmull_supported= (auxv & HWCAP_PMULL) != 0; + if (pmull_supported) + return "Using ARMv8 crc32 + pmull instructions"; + else + return "Using ARMv8 crc32 instructions"; } -#endif /* HAVE_ARMV8_CRYPTO */ -#endif /* HAVE_ARMV8_CRC */ + +#endif /* __GNUC__ && HAVE_ARMV8_CRC */ #ifndef HAVE_ARMV8_CRC_CRYPTO_INTRINSICS /* Request crc extension capabilities from the assembler */ asm(".arch_extension crc"); -#ifdef HAVE_ARMV8_CRYPTO +# ifdef HAVE_ARMV8_CRYPTO /* crypto extension */ asm(".arch_extension crypto"); -#endif +# endif #define CRC32CX(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value)) #define CRC32CW(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) @@ -49,12 +58,9 @@ asm(".arch_extension crypto"); #define CRC32CB(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) #define CRC32C3X8(buffer, ITR) \ - __asm__("crc32cx %w[c1], %w[c1], %x[v]":[c1]"+r"(crc1):[v]"r"(*((const uint64_t *)buffer + 42*1 + (ITR))));\ - __asm__("crc32cx %w[c2], %w[c2], %x[v]":[c2]"+r"(crc2):[v]"r"(*((const uint64_t *)buffer + 42*2 + (ITR))));\ - __asm__("crc32cx %w[c0], %w[c0], %x[v]":[c0]"+r"(crc0):[v]"r"(*((const uint64_t *)buffer + 42*0 + (ITR)))); - -#define CRC32C3X8_ZERO \ - __asm__("crc32cx %w[c0], %w[c0], xzr":[c0]"+r"(crc0)); + __asm__("crc32cx %w[c1], %w[c1], %x[v]":[c1]"+r"(crc1):[v]"r"(*((const uint64_t *)buffer + 42*1 + (ITR))));\ + __asm__("crc32cx %w[c2], %w[c2], %x[v]":[c2]"+r"(crc2):[v]"r"(*((const uint64_t *)buffer + 42*2 + (ITR))));\ + __asm__("crc32cx %w[c0], %w[c0], %x[v]":[c0]"+r"(crc0):[v]"r"(*((const uint64_t *)buffer + 42*0 + (ITR)))); #else /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ @@ -68,250 +74,194 @@ asm(".arch_extension crypto"); #define CRC32CB(crc, value) (crc) = __crc32cb((crc), (value)) #define CRC32C3X8(buffer, ITR) \ - crc1 = __crc32cd(crc1, *((const uint64_t *)buffer + 42*1 + (ITR)));\ - crc2 = __crc32cd(crc2, *((const uint64_t *)buffer + 42*2 + (ITR)));\ - crc0 = __crc32cd(crc0, *((const uint64_t *)buffer + 42*0 + (ITR))); - -#define CRC32C3X8_ZERO \ - crc0 = __crc32cd(crc0, (const uint64_t)0); + crc1 = __crc32cd(crc1, *((const uint64_t *)buffer + 42*1 + (ITR)));\ + crc2 = __crc32cd(crc2, *((const uint64_t *)buffer + 42*2 + (ITR)));\ + crc0 = __crc32cd(crc0, *((const uint64_t *)buffer + 42*0 + (ITR))); #endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ #define CRC32C7X3X8(buffer, ITR) do {\ - CRC32C3X8(buffer, ((ITR) * 7 + 0)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 1)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 2)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 3)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 4)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 5)) \ - CRC32C3X8(buffer, ((ITR) * 7 + 6)) \ - } while(0) - -#define CRC32C7X3X8_ZERO do {\ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - CRC32C3X8_ZERO \ - } while(0) + CRC32C3X8(buffer, ((ITR) * 7 + 0)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 1)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 2)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 3)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 4)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 5)) \ + CRC32C3X8(buffer, ((ITR) * 7 + 6)) \ +} while(0) #define PREF4X64L1(buffer, PREF_OFFSET, ITR) \ - __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 0)*64));\ - __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 1)*64));\ - __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 2)*64));\ - __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 3)*64)); + __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 0)*64));\ + __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 1)*64));\ + __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 2)*64));\ + __asm__("PRFM PLDL1KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 3)*64)); #define PREF1KL1(buffer, PREF_OFFSET) \ - PREF4X64L1(buffer,(PREF_OFFSET), 0) \ - PREF4X64L1(buffer,(PREF_OFFSET), 4) \ - PREF4X64L1(buffer,(PREF_OFFSET), 8) \ - PREF4X64L1(buffer,(PREF_OFFSET), 12) + PREF4X64L1(buffer,(PREF_OFFSET), 0) \ + PREF4X64L1(buffer,(PREF_OFFSET), 4) \ + PREF4X64L1(buffer,(PREF_OFFSET), 8) \ + PREF4X64L1(buffer,(PREF_OFFSET), 12) #define PREF4X64L2(buffer, PREF_OFFSET, ITR) \ - __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 0)*64));\ - __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 1)*64));\ - __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 2)*64));\ - __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 3)*64)); + __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 0)*64));\ + __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 1)*64));\ + __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 2)*64));\ + __asm__("PRFM PLDL2KEEP, [%x[v],%[c]]"::[v]"r"(buffer), [c]"I"((PREF_OFFSET) + ((ITR) + 3)*64)); #define PREF1KL2(buffer, PREF_OFFSET) \ - PREF4X64L2(buffer,(PREF_OFFSET), 0) \ - PREF4X64L2(buffer,(PREF_OFFSET), 4) \ - PREF4X64L2(buffer,(PREF_OFFSET), 8) \ - PREF4X64L2(buffer,(PREF_OFFSET), 12) - + PREF4X64L2(buffer,(PREF_OFFSET), 0) \ + PREF4X64L2(buffer,(PREF_OFFSET), 4) \ + PREF4X64L2(buffer,(PREF_OFFSET), 8) \ + PREF4X64L2(buffer,(PREF_OFFSET), 12) uint32_t crc32c_aarch64(uint32_t crc, const unsigned char *buffer, uint64_t len) { - uint32_t crc0, crc1, crc2; - int64_t length = (int64_t)len; - - crc = 0xFFFFFFFFU; - - if (buffer) { + uint32_t crc0, crc1, crc2; + int64_t length= (int64_t)len; + + crc= 0xFFFFFFFFU; + + /* Pmull runtime check here. + * Raspberry Pi 4 supports crc32 but doesn't support pmull (MDEV-23030). + * + * Consider the condition that the target platform does support hardware crc32 + * but not support PMULL. In this condition, it should leverage the aarch64 + * crc32 instruction (__crc32c) and just only skip parallel computation (pmull/vmull) + * rather than skip all hardware crc32 instruction of computation. + */ + if (pmull_supported) + { +/* The following Macro (HAVE_ARMV8_CRYPTO) is used for compiling check */ +#ifdef HAVE_ARMV8_CRYPTO /* Crypto extension Support - * Process 1024 Bytes (per block) + * Parallel computation with 1024 Bytes (per block) + * Intrinsics Support */ -#ifdef HAVE_ARMV8_CRYPTO - -/* Intrinsics Support */ -#ifdef HAVE_ARMV8_CRC_CRYPTO_INTRINSICS - const poly64_t k1 = 0xe417f38a, k2 = 0x8f158014; - uint64_t t0, t1; - - /* Process per block size of 1024 Bytes - * A block size = 8 + 42*3*sizeof(uint64_t) + 8 - */ - while ((length -= 1024) >= 0) { - /* Prefetch 3*1024 data for avoiding L2 cache miss */ - PREF1KL2(buffer, 1024*3); - /* Do first 8 bytes here for better pipelining */ - crc0 = __crc32cd(crc, *(const uint64_t *)buffer); - crc1 = 0; - crc2 = 0; - buffer += sizeof(uint64_t); - - /* Process block inline - * Process crc0 last to avoid dependency with above - */ - CRC32C7X3X8(buffer, 0); - CRC32C7X3X8(buffer, 1); - CRC32C7X3X8(buffer, 2); - CRC32C7X3X8(buffer, 3); - CRC32C7X3X8(buffer, 4); - CRC32C7X3X8(buffer, 5); - - buffer += 42*3*sizeof(uint64_t); - /* Prefetch data for following block to avoid L1 cache miss */ - PREF1KL1(buffer, 1024); - - /* Last 8 bytes - * Merge crc0 and crc1 into crc2 - * crc1 multiply by K2 - * crc0 multiply by K1 - */ - t1 = (uint64_t)vmull_p64(crc1, k2); - t0 = (uint64_t)vmull_p64(crc0, k1); - crc = __crc32cd(crc2, *(const uint64_t *)buffer); - crc1 = __crc32cd(0, t1); - crc ^= crc1; - crc0 = __crc32cd(0, t0); - crc ^= crc0; - - buffer += sizeof(uint64_t); - } - -#else /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ - - /*No intrinsics*/ - __asm__("mov x16, #0xf38a \n\t" - "movk x16, #0xe417, lsl 16 \n\t" - "mov v1.2d[0], x16 \n\t" - "mov x16, #0x8014 \n\t" - "movk x16, #0x8f15, lsl 16 \n\t" - "mov v0.2d[0], x16 \n\t" - :::"x16"); - - while ((length -= 1024) >= 0) { - PREF1KL2(buffer, 1024*3); - __asm__("crc32cx %w[c0], %w[c], %x[v]\n\t" - :[c0]"=r"(crc0):[c]"r"(crc), [v]"r"(*(const uint64_t *)buffer):); - crc1 = 0; - crc2 = 0; - buffer += sizeof(uint64_t); - - CRC32C7X3X8(buffer, 0); - CRC32C7X3X8(buffer, 1); - CRC32C7X3X8(buffer, 2); - CRC32C7X3X8(buffer, 3); - CRC32C7X3X8(buffer, 4); - CRC32C7X3X8(buffer, 5); - - buffer += 42*3*sizeof(uint64_t); - PREF1KL1(buffer, 1024); - __asm__("mov v2.2d[0], %x[c1] \n\t" - "pmull v2.1q, v2.1d, v0.1d \n\t" - "mov v3.2d[0], %x[c0] \n\t" - "pmull v3.1q, v3.1d, v1.1d \n\t" - "crc32cx %w[c], %w[c2], %x[v] \n\t" - "mov %x[c1], v2.2d[0] \n\t" - "crc32cx %w[c1], wzr, %x[c1] \n\t" - "eor %w[c], %w[c], %w[c1] \n\t" - "mov %x[c0], v3.2d[0] \n\t" - "crc32cx %w[c0], wzr, %x[c0] \n\t" - "eor %w[c], %w[c], %w[c0] \n\t" - :[c1]"+r"(crc1), [c0]"+r"(crc0), [c2]"+r"(crc2), [c]"+r"(crc) - :[v]"r"(*((const uint64_t *)buffer))); - buffer += sizeof(uint64_t); - } -#endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ - - /* Done if Input data size is aligned with 1024 */ - if(!(length += 1024)) - return (~crc); +# ifdef HAVE_ARMV8_CRC_CRYPTO_INTRINSICS + const poly64_t k1= 0xe417f38a, k2= 0x8f158014; + uint64_t t0, t1; + + /* Process per block size of 1024 Bytes + * A block size = 8 + 42*3*sizeof(uint64_t) + 8 + */ + while ((length-= 1024) >= 0) + { + /* Prefetch 3*1024 data for avoiding L2 cache miss */ + PREF1KL2(buffer, 1024*3); + /* Do first 8 bytes here for better pipelining */ + crc0= __crc32cd(crc, *(const uint64_t *)buffer); + crc1= 0; + crc2= 0; + buffer+= sizeof(uint64_t); + + /* Process block inline + * Process crc0 last to avoid dependency with above + */ + CRC32C7X3X8(buffer, 0); + CRC32C7X3X8(buffer, 1); + CRC32C7X3X8(buffer, 2); + CRC32C7X3X8(buffer, 3); + CRC32C7X3X8(buffer, 4); + CRC32C7X3X8(buffer, 5); + + buffer+= 42*3*sizeof(uint64_t); + /* Prefetch data for following block to avoid L1 cache miss */ + PREF1KL1(buffer, 1024); + + /* Last 8 bytes + * Merge crc0 and crc1 into crc2 + * crc1 multiply by K2 + * crc0 multiply by K1 + */ + t1= (uint64_t)vmull_p64(crc1, k2); + t0= (uint64_t)vmull_p64(crc0, k1); + crc= __crc32cd(crc2, *(const uint64_t *)buffer); + crc1= __crc32cd(0, t1); + crc^= crc1; + crc0= __crc32cd(0, t0); + crc^= crc0; + + buffer+= sizeof(uint64_t); + } + +# else /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ + + /*No intrinsics*/ + __asm__("mov x16, #0xf38a \n\t" + "movk x16, #0xe417, lsl 16 \n\t" + "mov v1.2d[0], x16 \n\t" + "mov x16, #0x8014 \n\t" + "movk x16, #0x8f15, lsl 16 \n\t" + "mov v0.2d[0], x16 \n\t" + :::"x16"); + + while ((length-= 1024) >= 0) + { + PREF1KL2(buffer, 1024*3); + __asm__("crc32cx %w[c0], %w[c], %x[v]\n\t" + :[c0]"=r"(crc0):[c]"r"(crc), [v]"r"(*(const uint64_t *)buffer):); + crc1= 0; + crc2= 0; + buffer+= sizeof(uint64_t); + + CRC32C7X3X8(buffer, 0); + CRC32C7X3X8(buffer, 1); + CRC32C7X3X8(buffer, 2); + CRC32C7X3X8(buffer, 3); + CRC32C7X3X8(buffer, 4); + CRC32C7X3X8(buffer, 5); + + buffer+= 42*3*sizeof(uint64_t); + PREF1KL1(buffer, 1024); + __asm__("mov v2.2d[0], %x[c1] \n\t" + "pmull v2.1q, v2.1d, v0.1d \n\t" + "mov v3.2d[0], %x[c0] \n\t" + "pmull v3.1q, v3.1d, v1.1d \n\t" + "crc32cx %w[c], %w[c2], %x[v] \n\t" + "mov %x[c1], v2.2d[0] \n\t" + "crc32cx %w[c1], wzr, %x[c1] \n\t" + "eor %w[c], %w[c], %w[c1] \n\t" + "mov %x[c0], v3.2d[0] \n\t" + "crc32cx %w[c0], wzr, %x[c0] \n\t" + "eor %w[c], %w[c], %w[c0] \n\t" + :[c1]"+r"(crc1), [c0]"+r"(crc0), [c2]"+r"(crc2), [c]"+r"(crc) + :[v]"r"(*((const uint64_t *)buffer))); + buffer+= sizeof(uint64_t); + } +# endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ + + /* Done if Input data size is aligned with 1024 */ + if (!(length+= 1024)) + return ~crc; #endif /* HAVE_ARMV8_CRYPTO */ - while ((length -= sizeof(uint64_t)) >= 0) { - CRC32CX(crc, *(uint64_t *)buffer); - buffer += sizeof(uint64_t); - } - /* The following is more efficient than the straight loop */ - if (length & sizeof(uint32_t)) { - CRC32CW(crc, *(uint32_t *)buffer); - buffer += sizeof(uint32_t); - } - if (length & sizeof(uint16_t)) { - CRC32CH(crc, *(uint16_t *)buffer); - buffer += sizeof(uint16_t); - } - if (length & sizeof(uint8_t)) - CRC32CB(crc, *buffer); - - } else { -#ifdef HAVE_ARMV8_CRYPTO -#ifdef HAVE_ARMV8_CRC_CRYPTO_INTRINSICS - const poly64_t k1 = 0xe417f38a; - uint64_t t0; - while ((length -= 1024) >= 0) { - crc0 = __crc32cd(crc, 0); - - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - - /* Merge crc0 into crc: crc0 multiply by K1 */ - t0 = (uint64_t)vmull_p64(crc0, k1); - crc = __crc32cd(0, t0); - } -#else /* !HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ - __asm__("mov x16, #0xf38a \n\t" - "movk x16, #0xe417, lsl 16 \n\t" - "mov v1.2d[0], x16 \n\t" - :::"x16"); - - while ((length -= 1024) >= 0) { - __asm__("crc32cx %w[c0], %w[c], xzr\n\t" - :[c0]"=r"(crc0):[c]"r"(crc)); - - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - CRC32C7X3X8_ZERO; - - __asm__("mov v3.2d[0], %x[c0] \n\t" - "pmull v3.1q, v3.1d, v1.1d \n\t" - "mov %x[c0], v3.2d[0] \n\t" - "crc32cx %w[c], wzr, %x[c0] \n\t" - :[c]"=r"(crc) - :[c0]"r"(crc0)); - } -#endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ - if(!(length += 1024)) - return (~crc); -#endif /* HAVE_ARMV8_CRYPTO */ - while ((length -= sizeof(uint64_t)) >= 0) - CRC32CX(crc, 0); + } // end if pmull_supported - /* The following is more efficient than the straight loop */ - if (length & sizeof(uint32_t)) - CRC32CW(crc, 0); + while ((length-= sizeof(uint64_t)) >= 0) + { + CRC32CX(crc, *(uint64_t *)buffer); + buffer+= sizeof(uint64_t); + } - if (length & sizeof(uint16_t)) - CRC32CH(crc, 0); + /* The following is more efficient than the straight loop */ + if (length & sizeof(uint32_t)) + { + CRC32CW(crc, *(uint32_t *)buffer); + buffer+= sizeof(uint32_t); + } - if (length & sizeof(uint8_t)) - CRC32CB(crc, 0); - } + if (length & sizeof(uint16_t)) + { + CRC32CH(crc, *(uint16_t *)buffer); + buffer+= sizeof(uint16_t); + } - return (~crc); + if (length & sizeof(uint8_t)) + CRC32CB(crc, *buffer); + + return ~crc; } /* There are multiple approaches to calculate crc. diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 36731e14a58..5718b2e762d 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -1,5 +1,6 @@ /* Copyright (c) 2001, 2011, Oracle and/or its affiliates + Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,15 +34,6 @@ #include <execinfo.h> #endif -#ifdef __linux__ -#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) -static char *heap_start; -char *__bss_start; -#else -#define PTR_SANE(p) (p) -#endif /* __linux */ - - /** Default handler for printing stacktrace */ @@ -61,111 +53,23 @@ static sig_handler default_handle_fatal_signal(int sig) /** Initialize priting off stacktrace at signal - - @param setup_handlers 0 only initialize variables - 1 setup signal handlers for stacktrace printing */ -void my_init_stacktrace(int setup_handlers) +void my_setup_stacktrace(void) { -#ifdef __linux__ - heap_start = (char*) &__bss_start; -#endif /* __linux */ - if (setup_handlers) - { - struct sigaction sa; - sa.sa_flags = SA_RESETHAND | SA_NODEFER; - sigemptyset(&sa.sa_mask); - sa.sa_handler= default_handle_fatal_signal; - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGABRT, &sa, NULL); + struct sigaction sa; + sa.sa_flags = SA_RESETHAND | SA_NODEFER; + sigemptyset(&sa.sa_mask); + sa.sa_handler= default_handle_fatal_signal; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); #ifdef SIGBUS - sigaction(SIGBUS, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); #endif - sigaction(SIGILL, &sa, NULL); - sigaction(SIGFPE, &sa, NULL); - } -} - -#ifdef __linux__ - -static void print_buffer(char *buffer, size_t count) -{ - const char s[]= " "; - for (; count && *buffer; --count) - { - my_write_stderr(isprint(*buffer) ? buffer : s, 1); - ++buffer; - } -} - -/** - Access the pages of this process through /proc/self/task/<tid>/mem - in order to safely print the contents of a memory address range. - - @param addr The address at the start of the memory region. - @param max_len The length of the memory region. - - @return Zero on success. -*/ -static int safe_print_str(const char *addr, size_t max_len) -{ - int fd; - pid_t tid; - off_t offset; - ssize_t nbytes= 0; - size_t total, count; - char buf[256]; - - tid= (pid_t) syscall(SYS_gettid); - - sprintf(buf, "/proc/self/task/%d/mem", tid); - - if ((fd= open(buf, O_RDONLY)) < 0) - return -1; - - /* Ensure that off_t can hold a pointer. */ - compile_time_assert(sizeof(off_t) >= sizeof(intptr)); - - total= max_len; - offset= (intptr) addr; - - /* Read up to the maximum number of bytes. */ - while (total) - { - count= MY_MIN(sizeof(buf), total); - - if ((nbytes= pread(fd, buf, count, offset)) < 0) - { - /* Just in case... */ - if (errno == EINTR) - continue; - else - break; - } - - /* Advance offset into memory. */ - total-= nbytes; - offset+= nbytes; - addr+= nbytes; - - /* Output the printable characters. */ - print_buffer(buf, nbytes); - - /* Break if less than requested... */ - if ((count - nbytes)) - break; - } - - if (nbytes == -1) - my_safe_printf_stderr("Can't read from address %p", addr); - - close(fd); - - return 0; + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); } -#endif /* Attempt to print a char * pointer as a string. @@ -187,24 +91,25 @@ static int safe_print_str(const char *addr, size_t max_len) int my_safe_print_str(const char* val, size_t max_len) { -#ifdef __linux__ - char *heap_end; - - // Try and make use of /proc filesystem to safely print memory contents. - if (!safe_print_str(val, max_len)) - return 0; - - heap_end= (char*) sbrk(0); -#endif - - if (!PTR_SANE(val)) + const char *orig_val= val; + if (!val) { - my_safe_printf_stderr("%s", "is an invalid pointer"); + my_safe_printf_stderr("%s", "(null)"); return 1; } - for (; max_len && PTR_SANE(val) && *val; --max_len) - my_write_stderr((val++), 1); + for (; max_len; --max_len) + { + if (my_write_stderr((val++), 1) != 1) + { + if ((errno == EFAULT) &&(val == orig_val + 1)) + { + // We can not read the address from very beginning + my_safe_printf_stderr("Can't access address %p", orig_val); + } + break; + } + } my_safe_printf_stderr("%s", "\n"); return 0; @@ -548,11 +453,6 @@ static EXCEPTION_POINTERS *exception_ptrs; #define MODULE64_SIZE_WINXP 576 #define STACKWALK_MAX_FRAMES 64 -void my_init_stacktrace(int setup_handlers __attribute__((unused))) -{ -} - - void my_set_exception_pointers(EXCEPTION_POINTERS *ep) { exception_ptrs = ep; diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 9db1e0efabf..2a8e54621c0 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -233,7 +233,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, int error; DBUG_PRINT("mutex", ("%s (0x%lx) locking", mp->name ? mp->name : "Null", (ulong) mp)); - DBUG_PUSH(""); + DBUG_PUSH_EMPTY; pthread_mutex_lock(&mp->global); if (!mp->file) @@ -395,7 +395,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, } end: - DBUG_POP(); + DBUG_POP_EMPTY; if (!error) DBUG_PRINT("mutex", ("%s (0x%lx) locked", mp->name, (ulong) mp)); return error; diff --git a/plugin/handler_socket/CMakeLists.txt b/plugin/handler_socket/CMakeLists.txt index 329ff58d7f2..5a1925b40e0 100644 --- a/plugin/handler_socket/CMakeLists.txt +++ b/plugin/handler_socket/CMakeLists.txt @@ -1,7 +1,8 @@ -IF(WIN32) +IF(WIN32 OR WITHOUT_SERVER) # Handlersocket does not compile on Windows, compiles but does - # not start on FreeBSD. + # not start on FreeBSD. + # It is a server plugin and disable it explicitly here. RETURN() ENDIF() diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 113a26804bf..33e4d067766 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1431,7 +1431,6 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, const char *res_start= result; const char *res_end= result + result_len - 2; size_t d_len; - char b_char; while (len) { @@ -1469,27 +1468,28 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, if (*next_s) { - memmove(result + d_len, "*****", 5); + const char b_char= *next_s++; + memset(result + d_len, '*', 5); result+= d_len + 5; - b_char= *(next_s++); - } - else - result+= d_len; - while (*next_s) - { - if (*next_s == b_char) - { - ++next_s; - break; - } - if (*next_s == '\\') + while (*next_s) { - if (next_s[1]) - next_s++; + if (*next_s == b_char) + { + ++next_s; + break; + } + if (*next_s == '\\') + { + if (next_s[1]) + next_s++; + } + next_s++; } - next_s++; } + else + result+= d_len; + len-= (uint)(next_s - str); str= next_s; continue; @@ -1497,19 +1497,23 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, no_password: if (result >= res_end) break; - if ((b_char= escaped_char(*str))) + else { - if (result+1 >= res_end) - break; - *(result++)= '\\'; - *(result++)= b_char; + const char b_char= escaped_char(*str); + if (b_char) + { + if (result+1 >= res_end) + break; + *(result++)= '\\'; + *(result++)= b_char; + } + else if (is_space(*str)) + *(result++)= ' '; + else + *(result++)= *str; + str++; + len--; } - else if (is_space(*str)) - *(result++)= ' '; - else - *(result++)= *str; - str++; - len--; } *result= 0; return result - res_start; diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 2c3578834eb..0b33f61710e 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -308,9 +308,7 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $suffix_found, $info_sent); - - $suffix_found= 0; + my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); if (!$opt_no_log) { @@ -349,10 +347,6 @@ sub start_mysqlds() $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } - elsif ("--defaults-group-suffix=" eq substr($options[$j], 0, 24)) - { - $suffix_found= 1; - } else { $options[$j]= quote_shell_word($options[$j]); @@ -369,12 +363,6 @@ sub start_mysqlds() $info_sent= 1; } - if (!$suffix_found) - { - $com.= " --defaults-group-suffix="; - $com.= substr($groups[$i],6); - } - $com.= $tmp; if ($opt_wsrep_new_cluster) { diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 1991fe4dd8d..63ff5646535 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -712,7 +712,8 @@ INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi -# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') fi @@ -951,17 +952,25 @@ then ib_home_dir=$INNODB_DATA_HOME_DIR - # Try to set ib_log_dir from the command line: - ib_log_dir=$INNODB_LOG_GROUP_HOME_ARG - if [ -z "$ib_log_dir" ]; then - ib_log_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir "") + WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} + # Try to set WSREP_LOG_DIR from the command line: + if [ ! -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then + WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG fi - if [ -z "$ib_log_dir" ]; then - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + # if no command line arg and WSREP_LOG_DIR is not set, + # try to get it from my.cnf: + if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') fi + if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') + fi + + ib_log_dir=$WSREP_LOG_DIR # Try to set ib_undo_dir from the command line: - ib_undo_dir=$INNODB_UNDO_DIR_ARG + ib_undo_dir=${INNODB_UNDO_DIR_ARG:-""} + # if no command line arg then try to get it from my.cnf: if [ -z "$ib_undo_dir" ]; then ib_undo_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-undo-directory "") fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 96e542ce844..d42cf014009 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -152,10 +152,11 @@ fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # Try to set WSREP_LOG_DIR from the command line: -if [ -z "$WSREP_LOG_DIR" ]; then +if [ ! -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG fi -# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and WSREP_LOG_DIR is not set, +# try to get it from my.cnf: if [ -z "$WSREP_LOG_DIR" ]; then WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') fi @@ -176,7 +177,8 @@ INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi -# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') fi diff --git a/sql-common/client.c b/sql-common/client.c index 5e072a8b538..42ef5e24a75 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3665,6 +3665,12 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql) } +my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) +{ + return mysql->affected_rows; +} + + /************************************************************************** Return next row of the query results **************************************************************************/ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 8a3677d7cf6..4be129ac9d0 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2014, Oracle and/or its affiliates. -# Copyright (c) 2010, 2018, MariaDB Corporation +# Copyright (c) 2010, 2020, MariaDB Corporation. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/sql/backup.cc b/sql/backup.cc index 40791e27416..02570dfd30d 100644 --- a/sql/backup.cc +++ b/sql/backup.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, MariaDB Corporation +/* Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. @@ -96,7 +96,7 @@ bool run_backup_stage(THD *thd, backup_stages stage) do { - bool res; + bool res= false; backup_stages previous_stage= thd->current_backup_stage; thd->current_backup_stage= next_stage; switch (next_stage) { @@ -120,7 +120,6 @@ bool run_backup_stage(THD *thd, backup_stages stage) break; case BACKUP_FINISHED: DBUG_ASSERT(0); - res= 0; } if (res) { diff --git a/sql/field.cc b/sql/field.cc index f50ddec1c80..491cd1b5079 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1888,7 +1888,7 @@ void Field::copy_from_tmp(int row_offset) } -bool Field::send_binary(Protocol *protocol) +bool Field::send(Protocol *protocol) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),charset()); @@ -1897,6 +1897,18 @@ bool Field::send_binary(Protocol *protocol) } +bool Field_num::send_numeric_zerofill_str(Protocol_text *protocol, + protocol_send_type_t send_type) +{ + DBUG_ASSERT(marked_for_read()); + StringBuffer<MAX_FIELD_WIDTH> tmp(&my_charset_latin1); + val_str(&tmp); + return protocol->store_numeric_zerofill_str(tmp.ptr(), + tmp.length(), + send_type); +} + + /** Check to see if field size is compatible with destination. @@ -2407,6 +2419,33 @@ bool Field::get_date(MYSQL_TIME *to, date_mode_t mode) return !t->is_valid_temporal(); } + +longlong Field::val_datetime_packed(THD *thd) +{ + MYSQL_TIME ltime, tmp; + if (get_date(<ime, Datetime::Options_cmp(thd))) + return 0; + if (ltime.time_type != MYSQL_TIMESTAMP_TIME) + return pack_time(<ime); + if (time_to_datetime_with_warn(thd, <ime, &tmp, TIME_CONV_NONE)) + return 0; + return pack_time(&tmp); +} + + +longlong Field::val_time_packed(THD *thd) +{ + MYSQL_TIME ltime; + Time::Options_cmp opt(thd); + if (get_date(<ime, opt)) + return 0; + if (ltime.time_type == MYSQL_TIMESTAMP_TIME) + return pack_time(<ime); + // Conversion from DATETIME or DATE to TIME is needed + return Time(thd, <ime, opt).to_packed(); +} + + /** This is called when storing a date in a string. @@ -3855,11 +3894,16 @@ String *Field_tiny::val_str(String *val_buffer, return val_str_from_long(val_buffer, 5, -10, nr); } -bool Field_tiny::send_binary(Protocol *protocol) +bool Field_tiny::send(Protocol *protocol) { - return protocol->store_tiny((longlong) (int8) ptr[0]); + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_TINY); + return protocol->store_tiny(Field_tiny::val_int()); } + int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr) const { signed char a,b; @@ -4015,8 +4059,12 @@ String *Field_short::val_str(String *val_buffer, } -bool Field_short::send_binary(Protocol *protocol) +bool Field_short::send(Protocol *protocol) { + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_SHORT); return protocol->store_short(Field_short::val_int()); } @@ -4198,9 +4246,12 @@ String *Field_int::val_str_from_long(String *val_buffer, } -bool Field_medium::send_binary(Protocol *protocol) +bool Field_medium::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONG); return protocol->store_long(Field_medium::val_int()); } @@ -4369,12 +4420,16 @@ String *Field_long::val_str(String *val_buffer, } -bool Field_long::send_binary(Protocol *protocol) +bool Field_long::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONG); return protocol->store_long(Field_long::val_int()); } + int Field_long::cmp(const uchar *a_ptr, const uchar *b_ptr) const { int32 a,b; @@ -4506,9 +4561,12 @@ String *Field_longlong::val_str(String *val_buffer, } -bool Field_longlong::send_binary(Protocol *protocol) +bool Field_longlong::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONGLONG); return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag); } @@ -4686,10 +4744,13 @@ void Field_float::sort_string(uchar *to,uint length __attribute__((unused))) } -bool Field_float::send_binary(Protocol *protocol) +bool Field_float::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); - return protocol->store((float) Field_float::val_real(), dec, (String*) 0); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_FLOAT); + return protocol->store_float((float) Field_float::val_real(), dec); } @@ -4980,9 +5041,13 @@ String *Field_double::val_str(String *val_buffer, return val_buffer; } -bool Field_double::send_binary(Protocol *protocol) +bool Field_double::send(Protocol *protocol) { - return protocol->store((double) Field_double::val_real(), dec, (String*) 0); + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_DOUBLE); + return protocol->store_double(Field_double::val_real(), dec); } @@ -5378,7 +5443,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) } -bool Field_timestamp0::send_binary(Protocol *protocol) +bool Field_timestamp0::send(Protocol *protocol) { MYSQL_TIME ltime; Field_timestamp0::get_date(<ime, date_mode_t(0)); @@ -5538,7 +5603,7 @@ int Field_timestamp_with_dec::set_time() return 0; } -bool Field_timestamp_with_dec::send_binary(Protocol *protocol) +bool Field_timestamp_with_dec::send(Protocol *protocol) { MYSQL_TIME ltime; Field_timestamp::get_date(<ime, date_mode_t(0)); @@ -6047,7 +6112,25 @@ bool Field_time0::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) } -bool Field_time::send_binary(Protocol *protocol) +int Field_time::store_native(const Native &value) +{ + Time t(value); + DBUG_ASSERT(t.is_valid_time()); + store_TIME(t); + return 0; +} + + +bool Field_time::val_native(Native *to) +{ + MYSQL_TIME ltime; + get_date(<ime, date_mode_t(0)); + int warn; + return Time(&warn, <ime, 0).to_native(to, decimals()); +} + + +bool Field_time::send(Protocol *protocol) { MYSQL_TIME ltime; get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); @@ -6283,6 +6366,33 @@ Binlog_type_info Field_timef::binlog_type_info() const return Binlog_type_info(Field_timef::binlog_type(), decimals(), 1); } + +longlong Field_timef::val_time_packed(THD *thd) +{ + DBUG_ASSERT(marked_for_read()); + longlong tmp= my_time_packed_from_binary(ptr, dec); + MYSQL_TIME ltime; + TIME_from_longlong_time_packed(<ime, tmp); + return pack_time(<ime); +} + + +int Field_timef::store_native(const Native &value) +{ + DBUG_ASSERT(value.length() == my_time_binary_length(dec)); + DBUG_ASSERT(Time(value).is_valid_time()); + memcpy(ptr, value.ptr(), value.length()); + return 0; +} + + +bool Field_timef::val_native(Native *to) +{ + uint32 binlen= my_time_binary_length(dec); + return to->copy((const char*) ptr, binlen); +} + + /**************************************************************************** ** year type ** Save in a byte the year 0, 1901->2155 @@ -6369,9 +6479,12 @@ int Field_year::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg) return 0; } -bool Field_year::send_binary(Protocol *protocol) +bool Field_year::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if ((txt= dynamic_cast<Protocol_text*>(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_SHORT); ulonglong tmp= Field_year::val_int(); return protocol->store_short(tmp); } @@ -6506,7 +6619,7 @@ void Field_date::store_TIME(const MYSQL_TIME *ltime) int4store(ptr,tmp); } -bool Field_date::send_binary(Protocol *protocol) +bool Field_date::send(Protocol *protocol) { longlong tmp= Field_date::val_int(); MYSQL_TIME tm; @@ -6600,7 +6713,7 @@ void Field_newdate::store_TIME(const MYSQL_TIME *ltime) } -bool Field_newdate::send_binary(Protocol *protocol) +bool Field_newdate::send(Protocol *protocol) { MYSQL_TIME tm; Field_newdate::get_date(&tm, date_mode_t(0)); @@ -6668,6 +6781,14 @@ bool Field_newdate::get_TIME(MYSQL_TIME *ltime, const uchar *pos, } +longlong Field_newdate::val_datetime_packed(THD *thd) +{ + MYSQL_TIME ltime; + Field_newdate::get_date(<ime, date_mode_t(0)); + return pack_time(<ime); +} + + int Field_newdate::cmp(const uchar *a_ptr, const uchar *b_ptr) const { uint32 a,b; @@ -6772,7 +6893,7 @@ Field_datetime::conversion_depends_on_sql_mode(THD *thd, Item *expr) const } -bool Field_datetime0::send_binary(Protocol *protocol) +bool Field_datetime0::send(Protocol *protocol) { MYSQL_TIME tm; Field_datetime0::get_date(&tm, date_mode_t(0)); @@ -6900,7 +7021,7 @@ void Field_datetime_hires::store_TIME(const MYSQL_TIME *ltime) store_bigendian(packed, ptr, Field_datetime_hires::pack_length()); } -bool Field_datetime_with_dec::send_binary(Protocol *protocol) +bool Field_datetime_with_dec::send(Protocol *protocol) { MYSQL_TIME ltime; get_date(<ime, date_mode_t(0)); @@ -6989,6 +7110,16 @@ Binlog_type_info Field_datetimef::binlog_type_info() const return Binlog_type_info(Field_datetimef::binlog_type(), decimals(), 1); } +longlong Field_datetimef::val_datetime_packed(THD *thd) +{ + DBUG_ASSERT(marked_for_read()); + longlong tmp= my_datetime_packed_from_binary(ptr, dec); + MYSQL_TIME ltime; + TIME_from_longlong_datetime_packed(<ime, tmp); + return pack_time(<ime); +} + + /**************************************************************************** ** string type ** A string may be varchar or binary @@ -7109,6 +7240,23 @@ void Field_longstr::make_send_field(Send_field *field) } } + +/* + An optimized version that uses less stack than Field::send(). +*/ +bool Field_longstr::send(Protocol *protocol) +{ + String tmp; + val_str(&tmp, &tmp); + /* + Ensure this function is only used with classes that do not allocate + memory in val_str() + */ + DBUG_ASSERT(tmp.alloced_length() == 0); + return protocol->store(tmp.ptr(), tmp.length(), tmp.charset()); +} + + /* Copy a string and fill with space */ int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs) @@ -7698,6 +7846,17 @@ my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value) } +/* + An optimized version that uses less stack and less temporary + variable initialization than Field_longstr::send() +*/ +bool Field_varstring::send(Protocol *protocol) +{ + return protocol->store((const char *) get_data(), get_length(), + field_charset()); +} + + #ifdef HAVE_valgrind void Field_varstring::mark_unused_memory_as_defined() { diff --git a/sql/field.h b/sql/field.h index 0f531564116..be4d279ce61 100644 --- a/sql/field.h +++ b/sql/field.h @@ -37,6 +37,7 @@ class Send_field; class Copy_field; class Protocol; +class Protocol_text; class Create_field; class Relay_log_info; class Field; @@ -1576,7 +1577,7 @@ public: ptr= old_ptr; return str; } - virtual bool send_binary(Protocol *protocol); + virtual bool send(Protocol *protocol); virtual uchar *pack(uchar *to, const uchar *from, uint max_length); /** @@ -1605,6 +1606,8 @@ public: void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); + virtual longlong val_datetime_packed(THD *thd); + virtual longlong val_time_packed(THD *thd); virtual const TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset() const= 0; virtual const DTCollation &dtcollation() const= 0; @@ -2005,6 +2008,9 @@ protected: return (flags & UNSIGNED_FLAG) ? Binlog_type_info::SIGN_UNSIGNED : Binlog_type_info::SIGN_SIGNED; } + bool send_numeric_zerofill_str(Protocol_text *protocol, + protocol_send_type_t send_type); + public: const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields @@ -2194,6 +2200,7 @@ public: int store_decimal(const my_decimal *d) override; uint32 max_data_length() const override; void make_send_field(Send_field *) override; + bool send(Protocol *protocol) override; bool is_varchar_and_in_write_set() const override { @@ -2520,7 +2527,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 1; } @@ -2583,7 +2590,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 2; } @@ -2630,7 +2637,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } @@ -2681,7 +2688,7 @@ public: int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real() override; longlong val_int() override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; String *val_str(String *, String *) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; @@ -2743,7 +2750,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } @@ -2843,7 +2850,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff, uint length) override; uint32 pack_length() const override { return sizeof(float); } @@ -2907,7 +2914,7 @@ public: longlong val_int() override final { return val_int_from_real(false); } ulonglong val_uint() override final { return (ulonglong) val_int_from_real(true); } String *val_str(String *, String *) override final; - bool send_binary(Protocol *protocol) override final; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override final; void sort_string(uchar *buff, uint length) override final; uint32 pack_length() const override final { return sizeof(double); } @@ -3210,7 +3217,7 @@ public: { return (double) Field_timestamp0::val_int(); } - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } @@ -3265,7 +3272,7 @@ public: DBUG_ASSERT(length == pack_length()); memcpy(to, ptr, length); } - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; double val_real() override; my_decimal* val_decimal(my_decimal*) override; int set_time() override; @@ -3403,7 +3410,7 @@ public: longlong val_int() override; String *val_str(String *, String *) override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; Information_schema_numeric_attributes information_schema_numeric_attributes() const override { @@ -3462,7 +3469,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } @@ -3501,13 +3508,14 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } void sql_type(String &str) const override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); } + longlong val_datetime_packed(THD *thd) override; uint size_of() const override { return sizeof *this; } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) override; @@ -3555,13 +3563,15 @@ public: decimals() == from->decimals(); } sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override; + int store_native(const Native &value) override; + bool val_native(Native *to) override; int store_time_dec(const MYSQL_TIME *ltime, uint dec) override; int store(const char *to,size_t length,CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; void set_curdays(THD *thd); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, @@ -3706,6 +3716,9 @@ public: } int reset() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; + longlong val_time_packed(THD *thd) override; + int store_native(const Native &value) override; + bool val_native(Native *to) override; uint size_of() const override { return sizeof *this; } Binlog_type_info binlog_type_info() const override; }; @@ -3775,7 +3788,7 @@ public: } longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } @@ -3815,7 +3828,7 @@ public: uint decimals() const override final { return dec; } enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_BINARY; } void make_send_field(Send_field *field) override final; - bool send_binary(Protocol *protocol) override final; + bool send(Protocol *protocol) override final; uchar *pack(uchar *to, const uchar *from, uint max_length) override final { return Field::pack(to, from, max_length); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, @@ -3907,6 +3920,7 @@ public: int reset() override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_datetimef::get_TIME(ltime, ptr, fuzzydate); } + longlong val_datetime_packed(THD *thd) override; uint size_of() const override { return sizeof *this; } Binlog_type_info binlog_type_info() const override; }; @@ -4153,6 +4167,7 @@ public: longlong val_int() override; String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; + bool send(Protocol *protocol) override; int cmp(const uchar *a,const uchar *b) const override; int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_len) const override; @@ -4217,6 +4232,15 @@ private: double val_real() override; longlong val_int() override; uint size_of() const override { return sizeof *this; } + /* + We use the default Field::send() implementation, + because the derived optimized version (from Field_longstr) + is not suitable for compressed fields. + */ + bool send(Protocol *protocol) override + { + return Field::send(protocol); + } enum_field_types binlog_type() const override { return MYSQL_TYPE_VARCHAR_COMPRESSED; } void sql_type(String &str) const override @@ -4614,6 +4638,15 @@ private: String *val_str(String *, String *) override; double val_real() override; longlong val_int() override; + /* + We use the default Field::send() implementation, + because the derived optimized version (from Field_longstr) + is not suitable for compressed fields. + */ + bool send(Protocol *protocol) override + { + return Field::send(protocol); + } uint size_of() const override { return sizeof *this; } enum_field_types binlog_type() const override { return MYSQL_TYPE_BLOB_COMPRESSED; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 8469e7b0fa8..2a713ecf97b 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -215,7 +215,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, DBUG_EXECUTE("info",TEST_filesort(filesort->sortorder, s_length);); #ifdef SKIP_DBUG_IN_FILESORT - DBUG_PUSH(""); /* No DBUG here */ + DBUG_PUSH_EMPTY; /* No DBUG here */ #endif SORT_INFO *sort; TABLE_LIST *tab= table->pos_in_table_list; @@ -496,7 +496,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, sort->examined_rows= param.examined_rows; sort->return_rows= num_rows; #ifdef SKIP_DBUG_IN_FILESORT - DBUG_POP(); /* Ok to DBUG */ + DBUG_POP_EMPTY; /* Ok to DBUG */ #endif DBUG_PRINT("exit", diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0a378bde0bd..921b461f15e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -9683,7 +9683,6 @@ double ha_partition::read_time(uint index, uint ranges, ha_rows rows) ha_rows ha_partition::records() { - int error; ha_rows tot_rows= 0; uint i; DBUG_ENTER("ha_partition::records"); @@ -9692,9 +9691,10 @@ ha_rows ha_partition::records() i < m_tot_parts; i= bitmap_get_next_set(&m_part_info->read_partitions, i)) { - ha_rows rows; - if (unlikely((error= m_file[i]->pre_records()) || - (rows= m_file[i]->records()) == HA_POS_ERROR)) + if (unlikely(m_file[i]->pre_records())) + DBUG_RETURN(HA_POS_ERROR); + const ha_rows rows= m_file[i]->records(); + if (unlikely(rows == HA_POS_ERROR)) DBUG_RETURN(HA_POS_ERROR); tot_rows+= rows; } diff --git a/sql/item.cc b/sql/item.cc index dbf20f31d7a..733b5d56b1b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2064,6 +2064,11 @@ bool Item_name_const::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydat return rc; } +bool Item_name_const::val_native(THD *thd, Native *to) +{ + return val_native_from_item(thd, value_item, to); +} + bool Item_name_const::is_null() { return value_item->is_null(); @@ -3193,6 +3198,12 @@ void Item_ident::print(String *str, enum_query_type query_type) use_db_name= use_table_name= false; } + if ((query_type & QT_ITEM_IDENT_DISABLE_DB_TABLE_NAMES)) + { + // Don't print db or table name irrespective of any other settings. + use_db_name= use_table_name= false; + } + if (!field_name.str || !field_name.str[0]) { append_identifier(thd, str, STRING_WITH_LEN("tmp_field")); @@ -3309,6 +3320,24 @@ bool Item_field::val_native_result(THD *thd, Native *to) } +longlong Item_field::val_datetime_packed(THD *thd) +{ + DBUG_ASSERT(fixed == 1); + if ((null_value= field->is_null())) + return 0; + return field->val_datetime_packed(thd); +} + + +longlong Item_field::val_time_packed(THD *thd) +{ + DBUG_ASSERT(fixed == 1); + if ((null_value= field->is_null())) + return 0; + return field->val_time_packed(thd); +} + + void Item_field::save_result(Field *to) { save_field_in_field(result_field, &null_value, to, TRUE); @@ -7537,7 +7566,6 @@ Item *find_producing_item(Item *item, st_select_lex *sel) DBUG_ASSERT(item->type() == Item::FIELD_ITEM || (item->type() == Item::REF_ITEM && ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); - Item *producing_item; Item_field *field_item= NULL; Item_equal *item_equal= item->get_item_equal(); table_map tab_map= sel->master_unit()->derived->table->map; @@ -7559,6 +7587,7 @@ Item *find_producing_item(Item *item, st_select_lex *sel) List_iterator_fast<Item> li(sel->item_list); if (field_item) { + Item *producing_item= NULL; uint field_no= field_item->field->field_index; for (uint i= 0; i <= field_no; i++) producing_item= li++; diff --git a/sql/item.h b/sql/item.h index c4fbf8f9c0a..e872335bb77 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1333,16 +1333,13 @@ public: { /* The default implementation for the Items that do not need native format: - - Item_basic_value + - Item_basic_value (default implementation) - Item_copy - Item_exists_subselect - Item_sum_field - Item_sum_or_func (default implementation) - Item_proc - Item_type_holder (as val_xxx() are never called for it); - - TODO: Item_name_const will need val_native() in the future, - when we add this syntax: - TIMESTAMP WITH LOCAL TIMEZONE'2001-01-01 00:00:00' These hybrid Item types override val_native(): - Item_field @@ -1353,6 +1350,8 @@ public: - Item_direct_ref - Item_direct_view_ref - Item_ref_null_helper + - Item_name_const + - Item_time_literal - Item_sum_or_func Note, these hybrid type Item_sum_or_func descendants override the default implementation: @@ -3173,6 +3172,7 @@ public: String *val_str(String *sp); my_decimal *val_decimal(my_decimal *); bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to); bool is_null(); virtual void print(String *str, enum_query_type query_type); @@ -3474,6 +3474,8 @@ public: longlong val_int_endpoint(bool left_endp, bool *incl_endp); bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_date_result(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); + longlong val_datetime_packed(THD *thd); + longlong val_time_packed(THD *thd); bool is_null() { return field->is_null(); } void update_null_value(); void update_table_bitmaps() @@ -4897,6 +4899,10 @@ public: String *val_str(String *to) { return Time(this).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to) + { + return Time(thd, this).to_native(to, decimals); + } Item *get_copy(THD *thd) { return get_item_copy<Item_time_literal>(thd, this); } }; @@ -6874,6 +6880,10 @@ public: { return has_value() ? Time(this).to_decimal(to) : NULL; } + bool val_native(THD *thd, Native *to) + { + return has_value() ? Time(thd, this).to_native(to, decimals) : true; + } }; diff --git a/sql/item_func.h b/sql/item_func.h index 5b4acdce1c6..6a4a9fa5dae 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -485,6 +485,12 @@ public: virtual longlong val_int(Item_handled_func *) const= 0; virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0; virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; + virtual bool val_native(THD *thd, Item_handled_func *, Native *to) const + { + DBUG_ASSERT(0); + to->length(0); + return true; + } virtual const Type_handler * return_type_handler(const Item_handled_func *item) const= 0; virtual const Type_handler * @@ -631,6 +637,10 @@ public: { return Time(item).to_string(to, item->decimals); } + bool val_native(THD *thd, Item_handled_func *item, Native *to) const + { + return Time(thd, item).to_native(to, item->decimals); + } }; @@ -788,6 +798,10 @@ public: { return m_func_handler->get_date(thd, this, to, fuzzydate); } + bool val_native(THD *thd, Native *to) + { + return m_func_handler->val_native(thd, this, to); + } }; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index c107c93d584..4acf1c6525b 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -2372,12 +2372,15 @@ double Item_func_distance::val_real() MBR mbr1, mbr2; const char *c_end; - - if ((null_value= (args[0]->null_value || args[1]->null_value || - !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) || - !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) || - g1->get_mbr(&mbr1, &c_end) || - g2->get_mbr(&mbr2, &c_end)))) + if (args[0]->null_value || args[1]->null_value) + goto mem_error; + g1= Geometry::construct(&buffer1, res1->ptr(), res1->length()); + if (!g1) + goto mem_error; + g2= Geometry::construct(&buffer2, res2->ptr(), res2->length()); + if (!g2) + goto mem_error; + if (g1->get_mbr(&mbr1, &c_end) || g2->get_mbr(&mbr2, &c_end)) goto mem_error; mbr1.add_mbr(&mbr2); @@ -2526,7 +2529,7 @@ String *Item_func_pointonsurface::val_str(String *str) Geometry *g; MBR mbr; const char *c_end; - double UNINIT_VAR(px), UNINIT_VAR(py), x0, y0; + double UNINIT_VAR(px), UNINIT_VAR(py), x0, UNINIT_VAR(y0); String *result= 0; const Gcalc_scan_iterator::point *pprev= NULL; uint32 srid; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 58f41ecfbbc..c2de296a109 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB Corporation + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -641,7 +641,7 @@ String *Item_func_concat_operator_oracle::val_str(String *str) { DBUG_ASSERT(fixed == 1); THD *thd= current_thd; - String *res; + String *res= NULL; uint i; null_value=0; @@ -651,7 +651,7 @@ String *Item_func_concat_operator_oracle::val_str(String *str) if ((res= args[i]->val_str(str))) break; } - if (i == arg_count) + if (!res) goto null; if (res != str) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index c9a493f8efc..35c9df533c4 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -598,6 +598,10 @@ public: double val_real() { return Time(this).to_double(); } String *val_str(String *to) { return Time(this).to_string(to, decimals); } my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } + bool val_native(THD *thd, Native *to) + { + return Time(thd, this).to_native(to, decimals); + } }; diff --git a/sql/mdl.cc b/sql/mdl.cc index 4772dc017f9..240ef97b1c4 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -25,6 +25,9 @@ #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> #include <mysql/psi/mysql_stage.h> +#ifdef WITH_WSREP +#include "wsrep_sst.h" +#endif #include <tpool.h> #include <pfs_metadata_provider.h> #include <mysql/psi/mysql_mdl.h> @@ -2332,18 +2335,26 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) wait_status= m_wait.timed_wait(m_owner, &abs_shortwait, FALSE, mdl_request->key.get_wait_state_name()); + THD* thd= m_owner->get_thd(); + if (wait_status != MDL_wait::EMPTY) break; /* Check if the client is gone while we were waiting. */ - if (! thd_is_connected(m_owner->get_thd())) + if (! thd_is_connected(thd)) { - /* - * The client is disconnected. Don't wait forever: - * assume it's the same as a wait timeout, this - * ensures all error handling is correct. - */ - wait_status= MDL_wait::TIMEOUT; - break; +#if defined(WITH_WSREP) && !defined(EMBEDDED_LIBRARY) + // During SST client might not be connected + if (!wsrep_is_sst_progress()) +#endif + { + /* + * The client is disconnected. Don't wait forever: + * assume it's the same as a wait timeout, this + * ensures all error handling is correct. + */ + wait_status= MDL_wait::TIMEOUT; + break; + } } mysql_prlock_wrlock(&lock->m_rwlock); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4d0b6af8ec9..520ffa8fa0c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2553,7 +2553,7 @@ void close_connection(THD *thd, uint sql_errno) if (sql_errno) { - net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL); + thd->protocol->net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL); thd->print_aborted_warning(lvl, ER_DEFAULT(sql_errno)); } else @@ -2873,7 +2873,6 @@ void init_signals(void) sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); - my_init_stacktrace(0); #if defined(__amiga__) sa.sa_handler=(void(*)())handle_fatal_signal; #else diff --git a/sql/mysqld.h b/sql/mysqld.h index fda3a7d2ef9..cd05a66fff3 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -872,6 +872,12 @@ enum enum_query_type QT_ITEM_SUBSELECT_ID_ONLY, QT_SHOW_SELECT_NUMBER= (1<<10), + + /// Do not print database name or table name in the identifiers (even if + /// this means the printout will be ambigous). It is assumed that the caller + /// passing this flag knows what they are doing. + QT_ITEM_IDENT_DISABLE_DB_TABLE_NAMES= (1 <<11), + /// This is used for EXPLAIN EXTENDED extra warnings / Be more detailed /// Be more detailed than QT_EXPLAIN. /// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE diff --git a/sql/protocol.cc b/sql/protocol.cc index 303c33b8fc1..d5e6a7b92bf 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -32,13 +32,6 @@ #include <stdarg.h> static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; -/* Declared non-static only because of the embedded library. */ -bool net_send_error_packet(THD *, uint, const char *, const char *); -/* Declared non-static only because of the embedded library. */ -bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, - bool); -/* Declared non-static only because of the embedded library. */ -bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); #ifndef EMBEDDED_LIBRARY static bool write_eof_packet(THD *, NET *, uint, uint); #endif @@ -152,11 +145,11 @@ bool Protocol_binary::net_store_data_cs(const uchar *from, size_t length, @retval TRUE An error occurred and the message wasn't sent properly */ -bool net_send_error(THD *thd, uint sql_errno, const char *err, - const char* sqlstate) +bool Protocol::net_send_error(THD *thd, uint sql_errno, const char *err, + const char* sqlstate) { bool error; - DBUG_ENTER("net_send_error"); + DBUG_ENTER("Protocol::net_send_error"); DBUG_ASSERT(!thd->spcont); DBUG_ASSERT(sql_errno); @@ -214,10 +207,10 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err, #ifndef EMBEDDED_LIBRARY bool -net_send_ok(THD *thd, - uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong id, const char *message, - bool is_eof) +Protocol::net_send_ok(THD *thd, + uint server_status, uint statement_warn_count, + ulonglong affected_rows, ulonglong id, + const char *message, bool is_eof) { NET *net= &thd->net; StringBuffer<MYSQL_ERRMSG_SIZE + 10> store; @@ -225,7 +218,7 @@ net_send_ok(THD *thd, bool state_changed= false; bool error= FALSE; - DBUG_ENTER("net_send_ok"); + DBUG_ENTER("Protocol::net_send_ok"); if (! net->vio) // hack for re-parsing queries { @@ -328,11 +321,11 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ */ bool -net_send_eof(THD *thd, uint server_status, uint statement_warn_count) +Protocol::net_send_eof(THD *thd, uint server_status, uint statement_warn_count) { NET *net= &thd->net; bool error= FALSE; - DBUG_ENTER("net_send_eof"); + DBUG_ENTER("Protocol::net_send_eof"); /* Check if client understand new format packets (OK instead of EOF) @@ -419,8 +412,8 @@ static bool write_eof_packet(THD *thd, NET *net, @retval TRUE An error occurred and the messages wasn't sent properly */ -bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, - const char* sqlstate) +bool Protocol::net_send_error_packet(THD *thd, uint sql_errno, const char *err, + const char* sqlstate) { NET *net= &thd->net; @@ -433,7 +426,7 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos; my_bool ret; uint8 save_compress; - DBUG_ENTER("send_error_packet"); + DBUG_ENTER("Protocol::send_error_packet"); if (net->vio == 0) { @@ -845,13 +838,12 @@ bool Protocol_text::store_field_metadata(const THD * thd, { CHARSET_INFO *thd_charset= thd->variables.character_set_results; char *pos; - CHARSET_INFO *cs= system_charset_info; DBUG_ASSERT(field.is_sane()); if (thd->client_capabilities & CLIENT_PROTOCOL_41) { const LEX_CSTRING def= {STRING_WITH_LEN("def")}; - if (store_ident(def, MY_REPERTOIRE_ASCII) || + if (store_ident(def) || store_ident(field.db_name) || store_ident(field.table_name) || store_ident(field.org_table_name) || @@ -867,8 +859,7 @@ bool Protocol_text::store_field_metadata(const THD * thd, Don't apply character set conversion: extended metadata is a binary encoded data. */ - if (store_binary_string(&metadata, cs, - MY_REPERTOIRE_UNICODE30)) + if (store_binary_string(metadata.ptr(), metadata.length())) return true; } if (packet->realloc(packet->length() + 12)) @@ -962,7 +953,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags) for (uint pos= 0; (item=it++); pos++) { prot.prepare_for_resend(); - if (prot.store_field_metadata(thd, item, pos)) + if (prot.store_item_metadata(thd, item, pos)) goto err; if (prot.write()) DBUG_RETURN(1); @@ -1042,7 +1033,7 @@ bool Protocol::write() #endif /* EMBEDDED_LIBRARY */ -bool Protocol_text::store_field_metadata(THD *thd, Item *item, uint pos) +bool Protocol_text::store_item_metadata(THD *thd, Item *item, uint pos) { Send_field field(thd, item); return store_field_metadata(thd, field, item->charset_for_protocol(), pos); @@ -1182,12 +1173,10 @@ bool Protocol_text::store_null() */ bool Protocol::store_string_aux(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { /* 'tocs' is set 0 when client issues SET character_set_results=NULL */ - if (needs_conversion(fromcs, from_repertoire, tocs)) + if (needs_conversion(fromcs, tocs)) { /* Store with conversion */ return net_store_data_cs((uchar*) from, length, fromcs, tocs); @@ -1220,9 +1209,7 @@ bool Protocol::store_warning(const char *from, size_t length) bool Protocol_text::store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { #ifndef DBUG_OFF DBUG_PRINT("info", ("Protocol_text::store field %u : %.*b", field_pos, @@ -1231,7 +1218,23 @@ bool Protocol_text::store_str(const char *from, size_t length, DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_STRING)); field_pos++; #endif - return store_string_aux(from, length, fromcs, from_repertoire, tocs); + return store_string_aux(from, length, fromcs, tocs); +} + + +bool Protocol_text::store_numeric_zerofill_str(const char *from, + size_t length, + protocol_send_type_t send_type) +{ +#ifndef DBUG_OFF + DBUG_PRINT("info", + ("Protocol_text::store_numeric_zerofill_str field %u : %.*b", + field_pos, (int) length, (length == 0 ? "" : from))); + DBUG_ASSERT(field_handlers == 0 || field_pos < field_count); + DBUG_ASSERT(valid_handler(field_pos, send_type)); + field_pos++; +#endif + return store_numeric_string_aux(from, length); } @@ -1298,25 +1301,25 @@ bool Protocol_text::store_decimal(const my_decimal *d) } -bool Protocol_text::store(float from, uint32 decimals, String *buffer) +bool Protocol_text::store_float(float from, uint32 decimals) { #ifndef DBUG_OFF DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_FLOAT)); field_pos++; #endif - Float(from).to_string(buffer, decimals); - return store_numeric_string_aux(buffer->ptr(), buffer->length()); + Float(from).to_string(&buffer, decimals); + return store_numeric_string_aux(buffer.ptr(), buffer.length()); } -bool Protocol_text::store(double from, uint32 decimals, String *buffer) +bool Protocol_text::store_double(double from, uint32 decimals) { #ifndef DBUG_OFF DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_DOUBLE)); field_pos++; #endif - buffer->set_real(from, decimals, thd->charset()); - return store_numeric_string_aux(buffer->ptr(), buffer->length()); + buffer.set_real(from, decimals, thd->charset()); + return store_numeric_string_aux(buffer.ptr(), buffer.length()); } @@ -1324,12 +1327,6 @@ bool Protocol_text::store(Field *field) { if (field->is_null()) return store_null(); -#ifndef DBUG_OFF - field_pos++; -#endif - char buff[MAX_FIELD_WIDTH]; - String str(buff,sizeof(buff), &my_charset_bin); - CHARSET_INFO *tocs= this->thd->variables.character_set_results; #ifdef DBUG_ASSERT_EXISTS TABLE *table= field->table; my_bitmap_map *old_map= 0; @@ -1337,14 +1334,14 @@ bool Protocol_text::store(Field *field) old_map= dbug_tmp_use_all_columns(table, table->read_set); #endif - field->val_str(&str); + bool rc= field->send(this); + #ifdef DBUG_ASSERT_EXISTS if (old_map) dbug_tmp_restore_column_map(table->read_set, old_map); #endif - return store_string_aux(str.ptr(), str.length(), str.charset(), - field->dtcollation().repertoire, tocs); + return rc; } @@ -1463,12 +1460,10 @@ void Protocol_binary::prepare_for_resend() bool Protocol_binary::store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { field_pos++; - return store_string_aux(from, length, fromcs, from_repertoire, tocs); + return store_string_aux(from, length, fromcs, tocs); } bool Protocol_binary::store_null() @@ -1531,11 +1526,10 @@ bool Protocol_binary::store_decimal(const my_decimal *d) StringBuffer<DECIMAL_MAX_STR_LENGTH> str; (void) d->to_string(&str); return store_str(str.ptr(), str.length(), str.charset(), - MY_REPERTOIRE_ASCII, thd->variables.character_set_results); } -bool Protocol_binary::store(float from, uint32 decimals, String *buffer) +bool Protocol_binary::store_float(float from, uint32 decimals) { field_pos++; char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC); @@ -1546,7 +1540,7 @@ bool Protocol_binary::store(float from, uint32 decimals, String *buffer) } -bool Protocol_binary::store(double from, uint32 decimals, String *buffer) +bool Protocol_binary::store_double(double from, uint32 decimals) { field_pos++; char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC); @@ -1560,12 +1554,12 @@ bool Protocol_binary::store(double from, uint32 decimals, String *buffer) bool Protocol_binary::store(Field *field) { /* - We should not increment field_pos here as send_binary() will call another + We should not increment field_pos here as send() will call another protocol function to do this for us */ if (field->is_null()) return store_null(); - return field->send_binary(this); + return field->send(this); } diff --git a/sql/protocol.h b/sql/protocol.h index 243f3ce417f..19899885599 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -50,38 +50,31 @@ protected: } #endif uint field_count; -#ifndef EMBEDDED_LIBRARY - bool net_store_data(const uchar *from, size_t length); - bool net_store_data_cs(const uchar *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); -#else virtual bool net_store_data(const uchar *from, size_t length); virtual bool net_store_data_cs(const uchar *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + virtual bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, + bool); + virtual bool net_send_error_packet(THD *, uint, const char *, const char *); +#ifdef EMBEDDED_LIBRARY char **next_field; MYSQL_FIELD *next_mysql_field; MEM_ROOT *alloc; #endif bool needs_conversion(CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, CHARSET_INFO *tocs) const { // 'tocs' is set 0 when client issues SET character_set_results=NULL return tocs && !my_charset_same(fromcs, tocs) && fromcs != &my_charset_bin && - tocs != &my_charset_bin && - (from_repertoire != MY_REPERTOIRE_ASCII || - (fromcs->state & MY_CS_NONASCII) || - (tocs->state & MY_CS_NONASCII)); + tocs != &my_charset_bin; } /* The following two are low-level functions that are invoked from higher-level store_xxx() funcs. The data is stored into this->packet. */ bool store_string_aux(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs); + CHARSET_INFO *fromcs, CHARSET_INFO *tocs); virtual bool send_ok(uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong last_insert_id, @@ -138,11 +131,9 @@ public: virtual bool store_longlong(longlong from, bool unsigned_flag)=0; virtual bool store_decimal(const my_decimal *)=0; virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs)=0; - virtual bool store(float from, uint32 decimals, String *buffer)=0; - virtual bool store(double from, uint32 decimals, String *buffer)=0; + CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0; + virtual bool store_float(float from, uint32 decimals)=0; + virtual bool store_double(double from, uint32 decimals)=0; virtual bool store(MYSQL_TIME *time, int decimals)=0; virtual bool store_date(MYSQL_TIME *time)=0; virtual bool store_time(MYSQL_TIME *time, int decimals)=0; @@ -150,30 +141,23 @@ public: // Various useful wrappers for the virtual store*() methods. // Backward wrapper for store_str() - inline bool store(const char *from, size_t length, CHARSET_INFO *cs, - my_repertoire_t repertoire= MY_REPERTOIRE_UNICODE30) + bool store(const char *from, size_t length, CHARSET_INFO *cs) { - return store_str(from, length, cs, repertoire, character_set_results()); + return store_str(from, length, cs, character_set_results()); } - inline bool store_lex_cstring(const LEX_CSTRING &s, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) + bool store_lex_cstring(const LEX_CSTRING &s, + CHARSET_INFO *fromcs, + CHARSET_INFO *tocs) { - return store_str(s.str, (uint) s.length, fromcs, from_repertoire, tocs); + return store_str(s.str, (uint) s.length, fromcs, tocs); } - inline bool store_binary_string(Binary_string *str, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire) + bool store_binary_string(const char *str, size_t length) { - return store_str(str->ptr(), (uint) str->length(), fromcs, from_repertoire, - &my_charset_bin); + return store_str(str, (uint) length, &my_charset_bin, &my_charset_bin); } - bool store_ident(const LEX_CSTRING &s, - my_repertoire_t repertoire= MY_REPERTOIRE_UNICODE30) + bool store_ident(const LEX_CSTRING &s) { - return store_lex_cstring(s, system_charset_info, repertoire, - character_set_results()); + return store_lex_cstring(s, system_charset_info, character_set_results()); } // End of wrappers @@ -196,6 +180,9 @@ public: }; virtual enum enum_protocol_type type()= 0; + virtual bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); + bool net_send_error(THD *thd, uint sql_errno, const char *err, + const char* sqlstate); void end_statement(); friend int send_answer_1(Protocol *protocol, String *s1, String *s2, @@ -206,8 +193,9 @@ public: /** Class used for the old (MySQL 4.0 protocol). */ -class Protocol_text final :public Protocol +class Protocol_text :public Protocol { + StringBuffer<FLOATING_POINT_BUFFER> buffer; bool store_numeric_string_aux(const char *from, size_t length); public: Protocol_text(THD *thd_arg, ulong prealloc= 0) @@ -224,24 +212,26 @@ public: bool store_longlong(longlong from, bool unsigned_flag) override; bool store_decimal(const my_decimal *) override; bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) override; + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) override; bool store(MYSQL_TIME *time, int decimals) override; bool store_date(MYSQL_TIME *time) override; bool store_time(MYSQL_TIME *time, int decimals) override; - bool store(float nr, uint32 decimals, String *buffer) override; - bool store(double from, uint32 decimals, String *buffer) override; + bool store_float(float nr, uint32 decimals) override; + bool store_double(double from, uint32 decimals) override; bool store(Field *field) override; bool send_out_parameters(List<Item_param> *sp_params) override; + + bool store_numeric_zerofill_str(const char *from, size_t length, + protocol_send_type_t send_type); + #ifdef EMBEDDED_LIBRARY void remove_last_row() override; #endif - bool store_field_metadata(const THD *thd, const Send_field &field, - CHARSET_INFO *charset_for_protocol, - uint pos); - bool store_field_metadata(THD *thd, Item *item, uint pos); + virtual bool store_field_metadata(const THD *thd, const Send_field &field, + CHARSET_INFO *charset_for_protocol, + uint pos); + bool store_item_metadata(THD *thd, Item *item, uint pos); bool store_field_metadata_for_list_fields(const THD *thd, Field *field, const TABLE_LIST *table_list, uint pos); @@ -270,14 +260,12 @@ public: bool store_longlong(longlong from, bool unsigned_flag) override; bool store_decimal(const my_decimal *) override; bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs) override; + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) override; bool store(MYSQL_TIME *time, int decimals) override; bool store_date(MYSQL_TIME *time) override; bool store_time(MYSQL_TIME *time, int decimals) override; - bool store(float nr, uint32 decimals, String *buffer) override; - bool store(double from, uint32 decimals, String *buffer) override; + bool store_float(float nr, uint32 decimals) override; + bool store_double(double from, uint32 decimals) override; bool store(Field *field) override; bool send_out_parameters(List<Item_param> *sp_params) override; @@ -320,24 +308,21 @@ public: bool store_long(longlong) override { return false; } bool store_longlong(longlong, bool) override { return false; } bool store_decimal(const my_decimal *) override { return false; } - bool store_str(const char *, size_t, CHARSET_INFO *, my_repertoire_t, - CHARSET_INFO *) override + bool store_str(const char *, size_t, CHARSET_INFO *, CHARSET_INFO *) override { return false; } bool store(MYSQL_TIME *, int) override { return false; } bool store_date(MYSQL_TIME *) override { return false; } bool store_time(MYSQL_TIME *, int) override { return false; } - bool store(float, uint32, String *) override { return false; } - bool store(double, uint32, String *) override { return false; } + bool store_float(float, uint32) override { return false; } + bool store_double(double, uint32) override { return false; } bool store(Field *) override { return false; } enum enum_protocol_type type() override { return PROTOCOL_DISCARD; }; }; void send_warning(THD *thd, uint sql_errno, const char *err=0); -bool net_send_error(THD *thd, uint sql_errno, const char *err, - const char* sqlstate); void net_send_progress_packet(THD *thd); uchar *net_store_data(uchar *to,const uchar *from, size_t length); uchar *net_store_data(uchar *to,int32 from); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index b2b253d0d7b..63c3ee30444 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7961,4 +7961,4 @@ ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS ER_NOT_ALLOWED_IN_THIS_CONTEXT eng "'%-.128s' is not allowed in this context" ER_DATA_WAS_COMMITED_UNDER_ROLLBACK - eng "Engine %s does not support rollback. Changes where committed during rollback call" + eng "Engine %s does not support rollback. Changes were committed during rollback call" diff --git a/sql/slave.cc b/sql/slave.cc index fba3992a820..cc50638ae5b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3477,7 +3477,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, protocol->store((ulonglong) mi->rli.max_relay_log_size); protocol->store(mi->rli.executed_entries); protocol->store((uint32) mi->received_heartbeats); - protocol->store((double) mi->heartbeat_period, 3, &tmp); + protocol->store_double(mi->heartbeat_period, 3); protocol->store(gtid_pos->ptr(), gtid_pos->length(), &my_charset_bin); } diff --git a/sql/sql_audit.h b/sql/sql_audit.h index 97317203e34..40276c86a78 100644 --- a/sql/sql_audit.h +++ b/sql/sql_audit.h @@ -254,35 +254,36 @@ void mysql_audit_notify_connection_disconnect(THD *thd, int errcode) } static inline -void mysql_audit_notify_connection_change_user(THD *thd) +void mysql_audit_notify_connection_change_user(THD *thd, + const Security_context *old_ctx) { if (mysql_audit_connection_enabled()) { - const Security_context *sctx= thd->security_ctx; mysql_event_connection event; event.event_subclass= MYSQL_AUDIT_CONNECTION_CHANGE_USER; event.status= thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0; event.thread_id= (unsigned long)thd->thread_id; - event.user= sctx->user; - event.user_length= safe_strlen_uint(sctx->user); - event.priv_user= sctx->priv_user; - event.priv_user_length= strlen_uint(sctx->priv_user); - event.external_user= sctx->external_user; - event.external_user_length= safe_strlen_uint(sctx->external_user); - event.proxy_user= sctx->proxy_user; - event.proxy_user_length= strlen_uint(sctx->proxy_user); - event.host= sctx->host; - event.host_length= safe_strlen_uint(sctx->host); - event.ip= sctx->ip; - event.ip_length= safe_strlen_uint(sctx->ip); + event.user= old_ctx->user; + event.user_length= safe_strlen_uint(old_ctx->user); + event.priv_user= old_ctx->priv_user; + event.priv_user_length= strlen_uint(old_ctx->priv_user); + event.external_user= old_ctx->external_user; + event.external_user_length= safe_strlen_uint(old_ctx->external_user); + event.proxy_user= old_ctx->proxy_user; + event.proxy_user_length= strlen_uint(old_ctx->proxy_user); + event.host= old_ctx->host; + event.host_length= safe_strlen_uint(old_ctx->host); + event.ip= old_ctx->ip; + event.ip_length= safe_strlen_uint(old_ctx->ip); event.database= thd->db; mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } + static inline void mysql_audit_external_lock_ex(THD *thd, my_thread_id thread_id, const char *user, const char *host, const char *ip, query_id_t query_id, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a01b5e400ba..ac952fffae8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -348,6 +348,12 @@ void thd_clear_errors(THD *thd) } +extern "C" unsigned long long thd_query_id(const MYSQL_THD thd) +{ + return((unsigned long long)thd->query_id); +} + + /** Get thread attributes for connection threads @@ -4983,6 +4989,55 @@ extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen) } +extern "C" const char *thd_user_name(MYSQL_THD thd) +{ + if (!thd->security_ctx) + return 0; + + return thd->security_ctx->user; +} + + +extern "C" const char *thd_client_host(MYSQL_THD thd) +{ + if (!thd->security_ctx) + return 0; + + return thd->security_ctx->host; +} + + +extern "C" const char *thd_client_ip(MYSQL_THD thd) +{ + if (!thd->security_ctx) + return 0; + + return thd->security_ctx->ip; +} + + +extern "C" LEX_CSTRING *thd_current_db(MYSQL_THD thd) +{ + return &thd->db; +} + + +extern "C" int thd_current_status(MYSQL_THD thd) +{ + Diagnostics_area *da= thd->get_stmt_da(); + if (!da) + return 0; + + return da->is_error() ? da->sql_errno() : 0; +} + + +extern "C" enum enum_server_command thd_current_command(MYSQL_THD thd) +{ + return thd->get_command(); +} + + extern "C" int thd_slave_thread(const MYSQL_THD thd) { return(thd->slave_thread); diff --git a/sql/sql_class.h b/sql/sql_class.h index 7088131f12a..b0f68aa8fab 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -195,7 +195,14 @@ extern char empty_c_string[1]; extern MYSQL_PLUGIN_IMPORT const char **errmesg; extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd); +extern "C" unsigned long long thd_query_id(const MYSQL_THD thd); extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen); +extern "C" const char *thd_user_name(MYSQL_THD thd); +extern "C" const char *thd_client_host(MYSQL_THD thd); +extern "C" const char *thd_client_ip(MYSQL_THD thd); +extern "C" LEX_CSTRING *thd_current_db(MYSQL_THD thd); +extern "C" int thd_current_status(MYSQL_THD thd); +extern "C" enum enum_server_command thd_current_command(MYSQL_THD thd); /** @class CSET_STRING diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 83f4de1b5df..479a310542b 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1494,7 +1494,7 @@ void CONNECT::close_with_error(uint sql_errno, if (thd) { if (sql_errno) - net_send_error(thd, sql_errno, message, NULL); + thd->protocol->net_send_error(thd, sql_errno, message, NULL); close_connection(thd, close_error); delete thd; set_current_thd(0); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 144b86e8fc9..8c95aa0a760 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1693,7 +1693,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, else auth_rc= acl_authenticate(thd, packet_length); - mysql_audit_notify_connection_change_user(thd); + mysql_audit_notify_connection_change_user(thd, &save_security_ctx); if (auth_rc) { /* Free user if allocated by acl_authenticate */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f6920e7420f..6753b857b54 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -243,65 +243,6 @@ private: class Ed_connection; -/** - Protocol_local: a helper class to intercept the result - of the data written to the network. -*/ - -class Protocol_local :public Protocol -{ -public: - Protocol_local(THD *thd, Ed_connection *ed_connection); - ~Protocol_local() { free_root(&m_rset_root, MYF(0)); } -protected: - virtual void prepare_for_resend(); - virtual bool write(); - virtual bool store_null(); - virtual bool store_tiny(longlong from); - virtual bool store_short(longlong from); - virtual bool store_long(longlong from); - virtual bool store_longlong(longlong from, bool unsigned_flag); - virtual bool store_decimal(const my_decimal *); - virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, - my_repertoire_t from_repertoire, - CHARSET_INFO *tocs); - virtual bool store(MYSQL_TIME *time, int decimals); - virtual bool store_date(MYSQL_TIME *time); - virtual bool store_time(MYSQL_TIME *time, int decimals); - virtual bool store(float value, uint32 decimals, String *buffer); - virtual bool store(double value, uint32 decimals, String *buffer); - virtual bool store(Field *field); - - virtual bool send_result_set_metadata(List<Item> *list, uint flags); - virtual bool send_out_parameters(List<Item_param> *sp_params); -#ifdef EMBEDDED_LIBRARY - void remove_last_row(); -#endif - virtual enum enum_protocol_type type() { return PROTOCOL_LOCAL; }; - - virtual bool send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message); - - virtual bool send_eof(uint server_status, uint statement_warn_count); - virtual bool send_error(uint sql_errno, const char *err_msg, const char* sqlstate); -private: - bool store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, - my_repertoire_t src_repertoire, - CHARSET_INFO *dst_cs); - - bool store_column(const void *data, size_t length); - void opt_add_row_to_rset(); -private: - Ed_connection *m_connection; - MEM_ROOT m_rset_root; - List<Ed_row> *m_rset; - size_t m_column_count; - Ed_column *m_current_row; - Ed_column *m_current_column; -}; /****************************************************************************** Implementation @@ -3796,6 +3737,7 @@ Execute_sql_statement::execute_server_code(THD *thd) end: thd->lex->restore_set_statement_var(); + delete_explain_query(thd->lex); lex_end(thd->lex); return error; @@ -5039,12 +4981,12 @@ Ed_connection::free_old_result() */ bool -Ed_connection::execute_direct(LEX_STRING sql_text) +Ed_connection::execute_direct(Protocol *p, LEX_STRING sql_text) { Execute_sql_statement execute_sql_statement(sql_text); DBUG_PRINT("ed_query", ("%s", sql_text.str)); - return execute_direct(&execute_sql_statement); + return execute_direct(p, &execute_sql_statement); } @@ -5061,10 +5003,9 @@ Ed_connection::execute_direct(LEX_STRING sql_text) @param server_runnable A code fragment to execute. */ -bool Ed_connection::execute_direct(Server_runnable *server_runnable) +bool Ed_connection::execute_direct(Protocol *p, Server_runnable *server_runnable) { bool rc= FALSE; - Protocol_local protocol_local(m_thd, this); Prepared_statement stmt(m_thd); Protocol *save_protocol= m_thd->protocol; Diagnostics_area *save_diagnostics_area= m_thd->get_stmt_da(); @@ -5073,7 +5014,7 @@ bool Ed_connection::execute_direct(Server_runnable *server_runnable) free_old_result(); /* Delete all data from previous execution, if any */ - m_thd->protocol= &protocol_local; + m_thd->protocol= p; m_thd->set_stmt_da(&m_diagnostics_area); rc= stmt.execute_server_runnable(server_runnable); @@ -5160,344 +5101,741 @@ Ed_connection::store_result_set() return ed_result_set; } -/************************************************************************* -* Protocol_local -**************************************************************************/ - -Protocol_local::Protocol_local(THD *thd, Ed_connection *ed_connection) - :Protocol(thd), - m_connection(ed_connection), - m_rset(NULL), - m_column_count(0), - m_current_row(NULL), - m_current_column(NULL) -{ - clear_alloc_root(&m_rset_root); -} +/* + MENT-56 + Protocol_local and service_sql for plugins to enable 'local' SQL query execution. +*/ -/** - Called between two result set rows. +#ifndef EMBEDDED_LIBRARY +// This part is mostly copied from libmysqld/lib_sql.cc +// TODO: get rid of code duplications - Prepare structures to fill result set rows. - Unfortunately, we can't return an error here. If memory allocation - fails, we'll have to return an error later. And so is done - in methods such as @sa store_column(). -*/ +#include <mysql.h> +#include "../libmysqld/embedded_priv.h" -void Protocol_local::prepare_for_resend() +class Protocol_local : public Protocol_text { - DBUG_ASSERT(alloc_root_inited(&m_rset_root)); +public: + struct st_mysql_data *cur_data; + struct st_mysql_data *first_data; + struct st_mysql_data **data_tail; + void clear_data_list(); + struct st_mysql_data *alloc_new_dataset(); + char **next_field; + MYSQL_FIELD *next_mysql_field; + MEM_ROOT *alloc; + + Protocol_local(THD *thd_arg, ulong prealloc= 0) : + Protocol_text(thd_arg, prealloc), + cur_data(0), first_data(0), data_tail(&first_data) + {} + +protected: + bool net_store_data(const uchar *from, size_t length); + bool net_store_data_cs(const uchar *from, size_t length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); + bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, + bool); + bool net_send_error_packet(THD *, uint, const char *, const char *); + bool begin_dataset(); + bool begin_dataset(THD *thd, uint numfields); + + bool write(); + bool flush(); + + bool store_field_metadata(const THD *thd, const Send_field &field, + CHARSET_INFO *charset_for_protocol, + uint pos); + bool send_result_set_metadata(List<Item> *list, uint flags); + void remove_last_row(); + bool store_null(); + void prepare_for_resend(); + bool send_list_fields(List<Field> *list, const TABLE_LIST *table_list); + + enum enum_protocol_type type() { return PROTOCOL_LOCAL; }; +}; - opt_add_row_to_rset(); - /* Start a new row. */ - m_current_row= (Ed_column *) alloc_root(&m_rset_root, - sizeof(Ed_column) * m_column_count); - m_current_column= m_current_row; +static +bool +write_eof_packet_local(THD *thd, + Protocol_local *p, uint server_status, uint statement_warn_count) +{ +// if (!thd->mysql) // bootstrap file handling +// return FALSE; + /* + The following test should never be true, but it's better to do it + because if 'is_fatal_error' is set the server is not going to execute + other queries (see the if test in dispatch_command / COM_QUERY) + */ + if (thd->is_fatal_error) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + p->cur_data->embedded_info->server_status= server_status; + /* + Don't send warn count during SP execution, as the warn_list + is cleared between substatements, and mysqltest gets confused + */ + p->cur_data->embedded_info->warning_count= + (thd->spcont ? 0 : MY_MIN(statement_warn_count, 65535)); + return FALSE; } -/** - In "real" protocols this is called to finish a result set row. - Unused in the local implementation. -*/ - -bool Protocol_local::write() +MYSQL_DATA *Protocol_local::alloc_new_dataset() { - return FALSE; + MYSQL_DATA *data; + struct embedded_query_result *emb_data; + if (!my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME | MY_ZEROFILL), + &data, sizeof(*data), + &emb_data, sizeof(*emb_data), + NULL)) + return NULL; + + emb_data->prev_ptr= &data->data; + cur_data= data; + *data_tail= data; + data_tail= &emb_data->next; + data->embedded_info= emb_data; + return data; } -/** - A helper function to add the current row to the current result - set. Called in @sa prepare_for_resend(), when a new row is started, - and in send_eof(), when the result set is finished. -*/ -void Protocol_local::opt_add_row_to_rset() +static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { - if (m_current_row) + uint32 dummy32; + uint dummy_err; + char *result; + + /* 'tocs' is set 0 when client issues SET character_set_results=NULL */ + if (tocs && String::needs_conversion(0, fromcs, tocs, &dummy32)) { - /* Add the old row to the result set */ - Ed_row *ed_row= new (&m_rset_root) Ed_row(m_current_row, m_column_count); - if (ed_row) - m_rset->push_back(ed_row, &m_rset_root); + uint new_len= (tocs->mbmaxlen * length) / fromcs->mbminlen + 1; + result= (char *)alloc_root(root, new_len); + length= copy_and_convert(result, new_len, + tocs, from, length, fromcs, &dummy_err); } + else + { + result= (char *)alloc_root(root, length + 1); + memcpy(result, from, length); + } + + result[length]= 0; + return result; } -/** - Add a NULL column to the current row. -*/ +static char *dup_str_aux(MEM_ROOT *root, const LEX_CSTRING &from, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) +{ + return dup_str_aux(root, from.str, (uint) from.length, fromcs, tocs); +} -bool Protocol_local::store_null() + +bool Protocol_local::net_store_data(const uchar *from, size_t length) { - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ + char *field_buf; +// if (!thd->mysql) // bootstrap file handling +// return FALSE; - bzero(m_current_column, sizeof(*m_current_column)); - ++m_current_column; + if (!(field_buf= (char*) alloc_root(alloc, length + sizeof(uint) + 1))) + return TRUE; + *(uint *)field_buf= (uint) length; + *next_field= field_buf + sizeof(uint); + memcpy((uchar*) *next_field, from, length); + (*next_field)[length]= 0; + if (next_mysql_field->max_length < length) + next_mysql_field->max_length= (unsigned long) length; + ++next_field; + ++next_mysql_field; return FALSE; } +bool Protocol_local::net_store_data_cs(const uchar *from, size_t length, + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) +{ + uint conv_length= (uint) (to_cs->mbmaxlen * length / from_cs->mbminlen); + uint dummy_error; + char *field_buf; +// if (!thd->mysql) // bootstrap file handling +// return false; + + if (!(field_buf= (char*) alloc_root(alloc, conv_length + sizeof(uint) + 1))) + return true; + *next_field= field_buf + sizeof(uint); + length= copy_and_convert(*next_field, conv_length, to_cs, + (const char*) from, length, from_cs, &dummy_error); + *(uint *) field_buf= (uint) length; + (*next_field)[length]= 0; + if (next_mysql_field->max_length < length) + next_mysql_field->max_length= (unsigned long) length; + ++next_field; + ++next_mysql_field; + return false; +} + + /** - A helper method to add any column to the current row - in its binary form. + Embedded library implementation of OK response. + + This function is used by the server to write 'OK' packet to + the "network" when the server is compiled as an embedded library. + Since there is no network in the embedded configuration, + a different implementation is necessary. + Instead of marshalling response parameters to a network representation + and then writing it to the socket, here we simply copy the data to the + corresponding client-side connection structures. + + @sa Server implementation of net_send_ok in protocol.cc for + description of the arguments. - Allocates memory for the data in the result set memory root. + @return + @retval TRUE An error occurred + @retval FALSE Success */ -bool Protocol_local::store_column(const void *data, size_t length) +bool +Protocol_local::net_send_ok(THD *thd, + uint server_status, uint statement_warn_count, + ulonglong affected_rows, ulonglong id, const char *message, bool) { - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ - /* - alloc_root() automatically aligns memory, so we don't need to - do any extra alignment if we're pointing to, say, an integer. - */ - m_current_column->str= (char*) memdup_root(&m_rset_root, - data, - length + 1 /* Safety */); - if (! m_current_column->str) - return TRUE; - m_current_column->str[length]= '\0'; /* Safety */ - m_current_column->length= length; - ++m_current_column; - return FALSE; + DBUG_ENTER("emb_net_send_ok"); + MYSQL_DATA *data; +// MYSQL *mysql= thd->mysql; + +// if (!mysql) // bootstrap file handling +// DBUG_RETURN(FALSE); + if (!(data= alloc_new_dataset())) + DBUG_RETURN(TRUE); + data->embedded_info->affected_rows= affected_rows; + data->embedded_info->insert_id= id; + if (message) + strmake_buf(data->embedded_info->info, message); + + bool error= write_eof_packet_local(thd, this, + server_status, statement_warn_count); + cur_data= 0; + DBUG_RETURN(error); } /** - Store a string value in a result set column, optionally - having converted it to character_set_results. + Embedded library implementation of EOF response. + + @sa net_send_ok + + @return + @retval TRUE An error occurred + @retval FALSE Success */ bool -Protocol_local::store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, - my_repertoire_t src_repertoire, - CHARSET_INFO *dst_cs) +Protocol_local::net_send_eof(THD *thd, uint server_status, + uint statement_warn_count) { - /* Store with conversion */ - uint error_unused; - - if (needs_conversion(src_cs, src_repertoire, dst_cs)) - { - if (unlikely(convert->copy(str, length, src_cs, dst_cs, &error_unused))) - return TRUE; - str= convert->ptr(); - length= convert->length(); - } - return store_column(str, length); + bool error= write_eof_packet_local(thd, this, server_status, + statement_warn_count); + cur_data= 0; + return error; } -/** Store a tiny int as is (1 byte) in a result set column. */ +bool Protocol_local::net_send_error_packet(THD *thd, uint sql_errno, + const char *err, const char *sqlstate) +{ + uint error; + char converted_err[MYSQL_ERRMSG_SIZE]; + MYSQL_DATA *data= cur_data; + struct embedded_query_result *ei; + +// if (!thd->mysql) // bootstrap file handling +// { +// fprintf(stderr, "ERROR: %d %s\n", sql_errno, err); +// return TRUE; +// } + if (!data) + data= alloc_new_dataset(); + + ei= data->embedded_info; + ei->last_errno= sql_errno; + convert_error_message(converted_err, sizeof(converted_err), + thd->variables.character_set_results, + err, strlen(err), + system_charset_info, &error); + /* Converted error message is always null-terminated. */ + strmake_buf(ei->info, converted_err); + strmov(ei->sqlstate, sqlstate); + ei->server_status= thd->server_status; + cur_data= 0; + return FALSE; +} + -bool Protocol_local::store_tiny(longlong value) +bool Protocol_local::begin_dataset() { - char v= (char) value; - return store_column(&v, 1); + MYSQL_DATA *data= alloc_new_dataset(); + if (!data) + return 1; + alloc= &data->alloc; + /* Assume rowlength < 8192 */ + init_alloc_root(PSI_INSTRUMENT_ME, alloc, 8192, 0, MYF(0)); + alloc->min_malloc= sizeof(MYSQL_ROWS); + return 0; } -/** Store a short as is (2 bytes, host order) in a result set column. */ - -bool Protocol_local::store_short(longlong value) +bool Protocol_local::begin_dataset(THD *thd, uint numfields) { - int16 v= (int16) value; - return store_column(&v, 2); + if (begin_dataset()) + return true; + MYSQL_DATA *data= cur_data; + data->fields= field_count= numfields; + if (!(data->embedded_info->fields_list= + (MYSQL_FIELD*)alloc_root(&data->alloc, sizeof(MYSQL_FIELD)*field_count))) + return true; + return false; } -/** Store a "long" as is (4 bytes, host order) in a result set column. */ - -bool Protocol_local::store_long(longlong value) +bool Protocol_local::write() { - int32 v= (int32) value; - return store_column(&v, 4); -} +// if (!thd->mysql) // bootstrap file handling +// return false; + *next_field= 0; + return false; +} -/** Store a "longlong" as is (8 bytes, host order) in a result set column. */ -bool Protocol_local::store_longlong(longlong value, bool unsigned_flag) +bool Protocol_local::flush() { - int64 v= (int64) value; - return store_column(&v, 8); + return 0; } -/** Store a decimal in string format in a result set column */ +bool Protocol_local::store_field_metadata(const THD * thd, + const Send_field &server_field, + CHARSET_INFO *charset_for_protocol, + uint pos) +{ + CHARSET_INFO *cs= system_charset_info; + CHARSET_INFO *thd_cs= thd->variables.character_set_results; + MYSQL_DATA *data= cur_data; + MEM_ROOT *field_alloc= &data->alloc; + MYSQL_FIELD *client_field= &cur_data->embedded_info->fields_list[pos]; + DBUG_ASSERT(server_field.is_sane()); + + client_field->db= dup_str_aux(field_alloc, server_field.db_name, + cs, thd_cs); + client_field->table= dup_str_aux(field_alloc, server_field.table_name, + cs, thd_cs); + client_field->name= dup_str_aux(field_alloc, server_field.col_name, + cs, thd_cs); + client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name, + cs, thd_cs); + client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name, + cs, thd_cs); + if (charset_for_protocol == &my_charset_bin || thd_cs == NULL) + { + /* No conversion */ + client_field->charsetnr= charset_for_protocol->number; + client_field->length= server_field.length; + } + else + { + /* With conversion */ + client_field->charsetnr= thd_cs->number; + client_field->length= server_field.max_octet_length(charset_for_protocol, + thd_cs); + } + client_field->type= server_field.type_handler()->type_code_for_protocol(); + client_field->flags= (uint16) server_field.flags; + client_field->decimals= server_field.decimals; -bool Protocol_local::store_decimal(const my_decimal *value) -{ - DBUG_ASSERT(0); // This method is not used yet - StringBuffer<DECIMAL_MAX_STR_LENGTH> str; - return value->to_string(&str) ? store_column(str.ptr(), str.length()) : true; -} + client_field->db_length= (unsigned int) strlen(client_field->db); + client_field->table_length= (unsigned int) strlen(client_field->table); + client_field->name_length= (unsigned int) strlen(client_field->name); + client_field->org_name_length= (unsigned int) strlen(client_field->org_name); + client_field->org_table_length= (unsigned int) strlen(client_field->org_table); + client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs); + client_field->catalog_length= 3; -/** Store a string. */ + if (IS_NUM(client_field->type)) + client_field->flags|= NUM_FLAG; -bool Protocol_local::store_str(const char *str, size_t length, - CHARSET_INFO *src_cs, - my_repertoire_t from_repertoire, - CHARSET_INFO *dst_cs) -{ - return store_string(str, length, src_cs, from_repertoire, dst_cs); + client_field->max_length= 0; + client_field->def= 0; + return false; } -/* Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store(MYSQL_TIME *time, int decimals) +void Protocol_local::remove_last_row() { - if (decimals != AUTO_SEC_PART_DIGITS) - my_datetime_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); -} + MYSQL_DATA *data= cur_data; + MYSQL_ROWS **last_row_hook= &data->data; + my_ulonglong count= data->rows; + DBUG_ENTER("Protocol_text::remove_last_row"); + while (--count) + last_row_hook= &(*last_row_hook)->next; + + *last_row_hook= 0; + data->embedded_info->prev_ptr= last_row_hook; + data->rows--; + DBUG_VOID_RETURN; +} -/** Store MYSQL_TIME (in binary format) */ -bool Protocol_local::store_date(MYSQL_TIME *time) +bool Protocol_local::send_result_set_metadata(List<Item> *list, uint flags) { - return store_column(time, sizeof(MYSQL_TIME)); -} + List_iterator_fast<Item> it(*list); + Item *item; +// Protocol_local prot(thd); + DBUG_ENTER("send_result_set_metadata"); + +// if (!thd->mysql) // bootstrap file handling +// DBUG_RETURN(0); + if (begin_dataset(thd, list->elements)) + goto err; + + for (uint pos= 0 ; (item= it++); pos++) + { + if (/*prot.*/store_item_metadata(thd, item, pos)) + goto err; + } -/** Store MYSQL_TIME (in binary format) */ + if (flags & SEND_EOF) + write_eof_packet_local(thd, this, thd->server_status, + thd->get_stmt_da()->current_statement_warn_count()); -bool Protocol_local::store_time(MYSQL_TIME *time, int decimals) -{ - if (decimals != AUTO_SEC_PART_DIGITS) - my_time_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); + DBUG_RETURN(prepare_for_send(list->elements)); + err: + my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ } +static void +list_fields_send_default(THD *thd, Protocol_local *p, Field *fld, uint pos) +{ + char buff[80]; + String tmp(buff, sizeof(buff), default_charset_info), *res; + MYSQL_FIELD *client_field= &p->cur_data->embedded_info->fields_list[pos]; + + if (fld->is_null() || !(res= fld->val_str(&tmp))) + { + client_field->def_length= 0; + client_field->def= strmake_root(&p->cur_data->alloc, "", 0); + } + else + { + client_field->def_length= res->length(); + client_field->def= strmake_root(&p->cur_data->alloc, res->ptr(), + client_field->def_length); + } +} -/* Store a floating point number, as is. */ -bool Protocol_local::store(float value, uint32 decimals, String *buffer) +bool Protocol_local::send_list_fields(List<Field> *list, const TABLE_LIST *table_list) { - return store_column(&value, sizeof(float)); + DBUG_ENTER("send_result_set_metadata"); + Protocol_text prot(thd); + List_iterator_fast<Field> it(*list); + Field *fld; + +// if (!thd->mysql) // bootstrap file handling +// DBUG_RETURN(0); + + if (begin_dataset(thd, list->elements)) + goto err; + + for (uint pos= 0 ; (fld= it++); pos++) + { + if (prot.store_field_metadata_for_list_fields(thd, fld, table_list, pos)) + goto err; + list_fields_send_default(thd, this, fld, pos); + } + + DBUG_RETURN(prepare_for_send(list->elements)); +err: + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + DBUG_RETURN(1); } -/* Store a double precision number, as is. */ +void Protocol_local::prepare_for_resend() +{ + MYSQL_ROWS *cur; + MYSQL_DATA *data= cur_data; + DBUG_ENTER("send_data"); + +// if (!thd->mysql) // bootstrap file handling +// DBUG_VOID_RETURN; + + data->rows++; + if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) + { + my_error(ER_OUT_OF_RESOURCES,MYF(0)); + DBUG_VOID_RETURN; + } + cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); + + *data->embedded_info->prev_ptr= cur; + data->embedded_info->prev_ptr= &cur->next; + next_field=cur->data; + next_mysql_field= data->embedded_info->fields_list; +#ifndef DBUG_OFF + field_pos= 0; +#endif -bool Protocol_local::store(double value, uint32 decimals, String *buffer) + DBUG_VOID_RETURN; +} + +bool Protocol_local::store_null() { - return store_column(&value, sizeof (double)); + *(next_field++)= NULL; + ++next_mysql_field; + return false; } -/* Store a Field. */ +#include <sql_common.h> +#include <errmsg.h> -bool Protocol_local::store(Field *field) +struct local_results { - if (field->is_null()) - return store_null(); - return field->send_binary(this); -} + struct st_mysql_data *cur_data; + struct st_mysql_data *first_data; + struct st_mysql_data **data_tail; + void clear_data_list(); + struct st_mysql_data *alloc_new_dataset(); + char **next_field; + MYSQL_FIELD *next_mysql_field; + MEM_ROOT *alloc; +}; -/** Called to start a new result set. */ +static void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data) +{ + NET *net= &mysql->net; + struct embedded_query_result *ei= data->embedded_info; + net->last_errno= ei->last_errno; + strmake_buf(net->last_error, ei->info); + memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate)); + mysql->server_status= ei->server_status; + my_free(data); +} + -bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint) +static my_bool loc_read_query_result(MYSQL *mysql) { - DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root)); + local_results *thd= (local_results *) mysql->thd; - init_sql_alloc(PSI_INSTRUMENT_ME, &m_rset_root, MEM_ROOT_BLOCK_SIZE, 0, - MYF(MY_THREAD_SPECIFIC)); + MYSQL_DATA *res= thd->first_data; + DBUG_ASSERT(!thd->cur_data); + thd->first_data= res->embedded_info->next; + if (res->embedded_info->last_errno && + !res->embedded_info->fields_list) + { + embedded_get_error(mysql, res); + return 1; + } - if (! (m_rset= new (&m_rset_root) List<Ed_row>)) - return TRUE; + mysql->warning_count= res->embedded_info->warning_count; + mysql->server_status= res->embedded_info->server_status; + mysql->field_count= res->fields; + if (!(mysql->fields= res->embedded_info->fields_list)) + { + mysql->affected_rows= res->embedded_info->affected_rows; + mysql->insert_id= res->embedded_info->insert_id; + } + net_clear_error(&mysql->net); + mysql->info= 0; + + if (res->embedded_info->info[0]) + { + strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1); + mysql->info= mysql->info_buffer; + } - m_column_count= columns->elements; + if (res->embedded_info->fields_list) + { + mysql->status=MYSQL_STATUS_GET_RESULT; + thd->cur_data= res; + } + else + my_free(res); - return FALSE; + return 0; } -/** - Normally this is a separate result set with OUT parameters - of stored procedures. Currently unsupported for the local - version. -*/ +static MYSQL_METHODS local_methods= +{ + loc_read_query_result, /* read_query_result */ + NULL/*loc_advanced_command*/, /* advanced_command */ + NULL/*loc_read_rows*/, /* read_rows */ + NULL/*loc_use_result*/, /* use_result */ + NULL/*loc_fetch_lengths*/, /* fetch_lengths */ + NULL/*loc_flush_use_result*/, /* flush_use_result */ + NULL/*loc_read_change_user_result*/ /* read_change_user_result */ +}; + -bool Protocol_local::send_out_parameters(List<Item_param> *sp_params) +extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql, + const char *host, const char *user, const char *passwd, const char *db) { - return FALSE; -} + //char name_buff[USERNAME_LENGTH]; + DBUG_ENTER("mysql_real_connect_local"); -/** Called for statements that don't have a result set, at statement end. */ + /* Test whether we're already connected */ + if (mysql->server_version) + { + set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate); + DBUG_RETURN(0); + } -bool -Protocol_local::send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message) -{ - /* - Just make sure nothing is sent to the client, we have grabbed - the status information in the connection diagnostics area. - */ - return FALSE; -} + if (!host || !host[0]) + host= mysql->options.host; + mysql->methods= &local_methods; -/** - Called at the end of a result set. Append a complete - result set to the list in Ed_connection. + if (!db || !db[0]) + db=mysql->options.db; - Don't send anything to the client, but instead finish - building of the result set at hand. -*/ + if (!user || !user[0]) + user=mysql->options.user; -bool Protocol_local::send_eof(uint server_status, uint statement_warn_count) -{ - Ed_result_set *ed_result_set; + mysql->user= my_strdup(PSI_INSTRUMENT_ME, user, MYF(0)); - DBUG_ASSERT(m_rset); - opt_add_row_to_rset(); - m_current_row= 0; + mysql->info_buffer= (char *) my_malloc(PSI_INSTRUMENT_ME, + MYSQL_ERRMSG_SIZE, MYF(0)); + //mysql->thd= create_embedded_thd(client_flag); - ed_result_set= new (&m_rset_root) Ed_result_set(m_rset, m_column_count, - &m_rset_root); + //init_embedded_mysql(mysql, client_flag); - m_rset= NULL; + //if (mysql_init_character_set(mysql)) + // goto error; - if (! ed_result_set) - return TRUE; + //if (check_embedded_connection(mysql, db)) + // goto error; - /* In case of successful allocation memory ownership was transferred. */ - DBUG_ASSERT(!alloc_root_inited(&m_rset_root)); + mysql->server_status= SERVER_STATUS_AUTOCOMMIT; - /* - Link the created Ed_result_set instance into the list of connection - result sets. Never fails. - */ - m_connection->add_result_set(ed_result_set); - return FALSE; -} + //if (mysql->options.init_commands) + //{ + // DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; + // char **ptr= (char**)init_commands->buffer; + // char **end= ptr + init_commands->elements; +// + // for (; ptr<end; ptr++) + // { + // MYSQL_RES *res; + // if (mysql_query(mysql,*ptr)) + // goto error; + // if (mysql->fields) + // { + // if (!(res= (*mysql->methods->use_result)(mysql))) + // goto error; + // mysql_free_result(res); + // } + // } + //} + DBUG_PRINT("exit",("Mysql handler: %p", mysql)); + DBUG_RETURN(mysql); -/** Called to send an error to the client at the end of a statement. */ +//error: + DBUG_PRINT("error",("message: %u (%s)", + mysql->net.last_errno, + mysql->net.last_error)); + { + /* Free alloced memory */ + my_bool free_me=mysql->free_me; + free_old_query(mysql); + mysql->free_me=0; + mysql_close(mysql); + mysql->free_me=free_me; + } + DBUG_RETURN(0); +} -bool -Protocol_local::send_error(uint sql_errno, const char *err_msg, const char*) + +extern "C" int execute_sql_command(const char *command, + char *hosts, char *names, char *filters) { - /* - Just make sure that nothing is sent to the client (default - implementation). - */ - return FALSE; + MYSQL_LEX_STRING sql_text; + THD *thd= current_thd; + THD *new_thd= 0; + int result; + my_bool qc_save= 0; + + if (!thd) + { + new_thd= new THD(0); + new_thd->thread_stack= (char*) &sql_text; + new_thd->store_globals(); + new_thd->security_ctx->skip_grants(); + new_thd->query_cache_is_applicable= 0; + bzero((char*) &new_thd->net, sizeof(new_thd->net)); + thd= new_thd; + } + else + { + if (thd->lock) + /* Doesn't work if the thread opened/locked tables already. */ + return 2; + + qc_save= thd->query_cache_is_applicable; + thd->query_cache_is_applicable= 0; + } + sql_text.str= (char *) command; + sql_text.length= strlen(command); + { + Protocol_local p(thd); + Ed_connection con(thd); + result= con.execute_direct(&p, sql_text); + if (!result && p.first_data) + { + int nr= (int) p.first_data->rows; + MYSQL_ROWS *rows= p.first_data->data; + + while (nr--) + { + strcpy(hosts, rows->data[0]); + hosts+= strlen(hosts) + 1; + strcpy(names, rows->data[1]); + names+= strlen(names) + 1; + if (filters) + { + strcpy(filters, rows->data[2]); + filters+= strlen(filters) + 1; + } + rows= rows->next; + } + } + if (p.first_data) + { + if (p.alloc) + free_root(p.alloc, MYF(0)); + my_free(p.first_data); + } + } + + if (new_thd) + delete new_thd; + else + thd->query_cache_is_applicable= qc_save; + + *hosts= 0; + return result; } +#endif /*!EMBEDDED_LIBRARY*/ + -#ifdef EMBEDDED_LIBRARY -void Protocol_local::remove_last_row() -{ } -#endif diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h index f1c4e5e4be9..166be95eb89 100644 --- a/sql/sql_prepare.h +++ b/sql/sql_prepare.h @@ -200,7 +200,7 @@ public: @retval TRUE error, use get_last_error() to see the error number. */ - bool execute_direct(LEX_STRING sql_text); + bool execute_direct(Protocol *p, LEX_STRING sql_text); /** Same as the previous, but takes an instance of Server_runnable @@ -213,7 +213,7 @@ public: return a result set @retval TRUE failure */ - bool execute_direct(Server_runnable *server_runnable); + bool execute_direct(Protocol *p, Server_runnable *server_runnable); /** Get the number of affected (deleted, updated) @@ -309,7 +309,6 @@ private: THD *m_thd; Ed_result_set *m_rsets; Ed_result_set *m_current_rset; - friend class Protocol_local; private: void free_old_result(); void add_result_set(Ed_result_set *ed_result_set); diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 2a47aa846eb..d8ecd2abee7 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -433,8 +433,6 @@ bool PROFILING::show_profiles() { prof= history.iterator_value(iterator); - String elapsed; - double query_time_usecs= prof->m_end_time_usecs - prof->m_start_time_usecs; if (unit->lim.check_offset(idx)) @@ -444,8 +442,8 @@ bool PROFILING::show_profiles() protocol->prepare_for_resend(); protocol->store((uint32)(prof->profiling_query_id)); - protocol->store((double)(query_time_usecs/(1000.0*1000)), - (uint32) TIME_FLOAT_DIGITS-1, &elapsed); + protocol->store_double(query_time_usecs/(1000.0*1000), + (uint32) TIME_FLOAT_DIGITS-1); if (prof->query_source != NULL) protocol->store(prof->query_source, strlen(prof->query_source), system_charset_info); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 3ed0e288870..4a1484df2c2 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -374,11 +374,15 @@ static int send_file(THD *thd) We need net_flush here because the client will not know it needs to send us the file name until it has processed the load event entry */ - if (unlikely(net_flush(net) || (packet_len = my_net_read(net)) == packet_error)) + if (unlikely(net_flush(net))) { + read_error: errmsg = "while reading file name"; goto err; } + packet_len= my_net_read(net); + if (unlikely(packet_len == packet_error)) + goto read_error; // terminate with \0 for fn_format *((char*)net->read_pos + packet_len) = 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 22bf2eb37b5..b0869e15289 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11597,11 +11597,16 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) HA_CAN_TABLE_CONDITION_PUSHDOWN) && !first_inner_tab) { + Json_writer_object wrap(thd); + Json_writer_object trace_cp(thd, "table_condition_pushdown"); + trace_cp.add_table_name(tab->table); + COND *push_cond= make_cond_for_table(thd, tmp_cond, current_map, current_map, -1, FALSE, FALSE); if (push_cond) { + trace_cp.add("push_cond", push_cond); /* Push condition to handler */ if (!tab->table->file->cond_push(push_cond)) tab->table->file->pushed_cond= push_cond; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 0d41857aaf5..452690f3237 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2891,8 +2891,6 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) server_threads.iterate(list_callback, &arg); ulonglong now= microsecond_interval_timer(); - char buff[20]; // For progress - String store_buffer(buff, sizeof(buff), system_charset_info); while (auto thd_info= arg.thread_infos.get()) { @@ -2918,7 +2916,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) protocol->store_null(); if (!thd->variables.old_mode && !(thd->variables.old_behavior & OLD_MODE_NO_PROGRESS_INFO)) - protocol->store(thd_info->progress, 3, &store_buffer); + protocol->store_double(thd_info->progress, 3); if (protocol->write()) break; /* purecov: inspected */ } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 9e0f9b013c0..fdd92d3d7bb 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -734,6 +734,23 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item) } +bool Time::to_native(Native *to, uint decimals) const +{ + if (!is_valid_time()) + { + to->length(0); + return true; + } + uint len= my_time_binary_length(decimals); + if (to->reserve(len)) + return true; + longlong tmp= TIME_to_longlong_time_packed(get_mysql_time()); + my_time_packed_to_binary(tmp, (uchar*) to->ptr(), decimals); + to->length(len); + return false; +} + + void Time::make_from_item(THD *thd, int *warn, Item *item, const Options opt) { *warn= 0; @@ -918,6 +935,28 @@ void Time::make_from_time(int *warn, const MYSQL_TIME *from) } +uint Time::binary_length_to_precision(uint length) +{ + switch (length) { + case 3: return 0; + case 4: return 2; + case 5: return 4; + case 6: return 6; + } + DBUG_ASSERT(0); + return 0; +} + + +Time::Time(const Native &native) +{ + uint dec= binary_length_to_precision(native.length()); + longlong tmp= my_time_packed_from_binary((const uchar *) native.ptr(), dec); + TIME_from_longlong_time_packed(this, tmp); + DBUG_ASSERT(is_valid_time()); +} + + Time::Time(int *warn, const MYSQL_TIME *from, long curdays) { switch (from->time_type) { @@ -1685,6 +1724,13 @@ Type_handler_timestamp_common::type_handler_for_native_format() const } +const Type_handler * +Type_handler_time_common::type_handler_for_native_format() const +{ + return &type_handler_time2; +} + + /***************************************************************************/ const Type_handler *Type_handler_typelib::type_handler_for_item_field() const @@ -7348,7 +7394,7 @@ bool Type_handler:: { float nr= (float) item->val_real(); if (!item->null_value) - return protocol->store(nr, item->decimals, &buf->m_string); + return protocol->store_float(nr, item->decimals); return protocol->store_null(); } @@ -7358,7 +7404,7 @@ bool Type_handler:: { double nr= item->val_real(); if (!item->null_value) - return protocol->store(nr, item->decimals, &buf->m_string); + return protocol->store_double(nr, item->decimals); return protocol->store_null(); } @@ -8820,6 +8866,51 @@ Type_handler_time_common::create_literal_item(THD *thd, } +bool +Type_handler_time_common::Item_val_native_with_conversion(THD *thd, + Item *item, + Native *to) const +{ + if (item->type_handler()->type_handler_for_native_format() == + &type_handler_time2) + return item->val_native(thd, to); + return Time(thd, item).to_native(to, item->time_precision(thd)); +} + + +bool +Type_handler_time_common::Item_val_native_with_conversion_result(THD *thd, + Item *item, + Native *to) + const +{ + if (item->type_handler()->type_handler_for_native_format() == + &type_handler_time2) + return item->val_native_result(thd, to); + MYSQL_TIME ltime; + if (item->get_date_result(thd, <ime, Time::Options(thd))) + return true; + int warn; + return Time(&warn, <ime, 0).to_native(to, item->time_precision(thd)); +} + + +int Type_handler_time_common::cmp_native(const Native &a, + const Native &b) const +{ + // Optimize a simple case: equal fractional precision: + if (a.length() == b.length()) + return memcmp(a.ptr(), b.ptr(), a.length()); + longlong lla= Time(a).to_packed(); + longlong llb= Time(b).to_packed(); + if (lla < llb) + return -1; + if (lla> llb) + return 1; + return 0; +} + + bool Type_handler_timestamp_common::TIME_to_native(THD *thd, const MYSQL_TIME *ltime, Native *to, @@ -8930,6 +9021,15 @@ Type_handler_timestamp_common::Item_param_val_native(THD *thd, } +bool +Type_handler_time_common::Item_param_val_native(THD *thd, + Item_param *item, + Native *to) const +{ + return Time(thd, item).to_native(to, item->decimals); +} + + /***************************************************************************/ bool Type_handler::validate_implicit_default_value(THD *thd, diff --git a/sql/sql_type.h b/sql/sql_type.h index a6d85b5bb47..f94d17541a4 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1453,6 +1453,7 @@ class Schema; */ class Time: public Temporal { + static uint binary_length_to_precision(uint length); public: enum datetime_to_time_mode_t { @@ -1685,6 +1686,14 @@ public: */ Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second); Time() { time_type= MYSQL_TIMESTAMP_NONE; } + Time(const Native &native); + Time(THD *thd, const MYSQL_TIME *ltime, const Options opt) + { + *(static_cast<MYSQL_TIME*>(this))= *ltime; + DBUG_ASSERT(is_valid_temporal()); + int warn= 0; + valid_MYSQL_TIME_to_valid_value(thd, &warn, opt); + } Time(Item *item) :Time(current_thd, item) { } @@ -1840,6 +1849,7 @@ public: return !is_valid_time() ? 0 : Temporal::to_double(neg, TIME_to_ulonglong_time(this), second_part); } + bool to_native(Native *to, uint decimals) const; String *to_string(String *str, uint dec) const { if (!is_valid_time()) @@ -5897,6 +5907,15 @@ public: { return MYSQL_TIMESTAMP_TIME; } + bool is_val_native_ready() const override { return true; } + const Type_handler *type_handler_for_native_format() const override; + int cmp_native(const Native &a, const Native &b) const override; + bool Item_val_native_with_conversion(THD *thd, Item *, Native *to) + const override; + bool Item_val_native_with_conversion_result(THD *thd, Item *, Native *to) + const override; + bool Item_param_val_native(THD *thd, Item_param *item, Native *to) + const override; bool partition_field_check(const LEX_CSTRING &field_name, Item *item_expr) const override { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b472dfd4939..3fa54a3bf54 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3877,9 +3877,11 @@ sp_fetch_list: LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *spc= lex->spcont; - sp_variable *spv; + sp_variable *spv= likely(spc != NULL) + ? spc->find_variable(&$1, false) + : NULL; - if (unlikely(!spc || !(spv = spc->find_variable(&$1, false)))) + if (unlikely(!spv)) my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str)); /* An SP local variable */ @@ -3891,9 +3893,11 @@ sp_fetch_list: LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *spc= lex->spcont; - sp_variable *spv; + sp_variable *spv= likely(spc != NULL) + ? spc->find_variable(&$3, false) + : NULL; - if (unlikely(!spc || !(spv = spc->find_variable(&$3, false)))) + if (unlikely(!spv)) my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str)); /* An SP local variable */ diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc index 7895431bc13..709bb95eb98 100644 --- a/sql/threadpool_generic.cc +++ b/sql/threadpool_generic.cc @@ -1009,7 +1009,10 @@ void thread_group_destroy(thread_group_t *thread_group) #endif if (!--shutdown_group_count) + { my_free(all_groups); + all_groups= 0; + } } /** @@ -1614,6 +1617,14 @@ TP_pool_generic::~TP_pool_generic() { thread_group_close(&all_groups[i]); } + + /* + Wait until memory occupied by all_groups is freed. + */ + int timeout_ms=5000; + while(all_groups && timeout_ms--) + my_sleep(1000); + threadpool_started= false; DBUG_VOID_RETURN; } diff --git a/sql/tztime.cc b/sql/tztime.cc index 4546f2291cd..8e08a201e88 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2753,9 +2753,11 @@ main(int argc, char **argv) printf("TRUNCATE TABLE time_zone_name;\n"); printf("TRUNCATE TABLE time_zone_transition;\n"); printf("TRUNCATE TABLE time_zone_transition_type;\n"); + printf("START TRANSACTION;\n"); if (scan_tz_dir(root_name_end, 0, opt_verbose)) { + printf("ROLLBACK;\n"); fflush(stdout); fprintf(stderr, "There were fatal errors during processing " @@ -2763,6 +2765,7 @@ main(int argc, char **argv) return 1; } + printf("COMMIT;\n"); printf("ALTER TABLE time_zone_transition " "ORDER BY Time_zone_id, Transition_time;\n"); printf("ALTER TABLE time_zone_transition_type " diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9a2d5e635a5..d0155f27d6d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1171,7 +1171,7 @@ bool wsrep_must_sync_wait (THD* thd, uint mask) mysql_mutex_lock(&thd->LOCK_thd_data); ret= (thd->variables.wsrep_sync_wait & mask) && thd->wsrep_client_thread && - thd->variables.wsrep_on && + WSREP_ON && !(thd->variables.wsrep_dirty_reads && !is_update_query(thd->lex->sql_command)) && !thd->in_active_multi_stmt_transaction() && diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 54bb9aa9889..610e864593e 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -54,6 +54,7 @@ my_bool wsrep_sst_donor_rejects_queries= FALSE; bool sst_joiner_completed = false; bool sst_donor_completed = false; +bool sst_needed = false; struct sst_thread_arg { @@ -307,6 +308,7 @@ bool wsrep_before_SE() && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } +static bool sst_in_progress = false; // Signal end of SST static void wsrep_sst_complete (THD* thd, int const rcode) @@ -1625,7 +1627,10 @@ static void* sst_donor_thread (void* a) char out_buf[out_len]; wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; - wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST + // seqno of complete SST + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; + // SST is now in progress + sst_in_progress= true; wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can // operate with wsrep_ready == OFF @@ -1731,6 +1736,8 @@ wait_signal: proc.wait(); wsrep_donor_monitor_end(); + sst_in_progress= false; + return NULL; } @@ -1884,3 +1891,8 @@ int wsrep_sst_donate(const std::string& msg, return (ret >= 0 ? 0 : 1); } + +bool wsrep_is_sst_progress() +{ + return (sst_in_progress); +} diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 2389db4abe7..50f2d362c5a 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -77,6 +77,7 @@ extern void wsrep_SE_init_grab(); /*! grab init critical section */ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ +extern bool wsrep_is_sst_progress(); /** Return a string containing the state transfer request string. @@ -102,5 +103,6 @@ int wsrep_sst_donate(const std::string& request, #define wsrep_SE_init_grab() do { } while(0) #define wsrep_SE_init_done() do { } while(0) #define wsrep_sst_continue() (0) +#define wsrep_is_sst_progress() (0) #endif /* WSREP_SST_H */ diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 4fffc3ddc8a..40689b7cf88 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -360,6 +360,12 @@ static int wsrep_provider_verify (const char* provider_str) { return 1; } + + if (MY_S_ISDIR(f_stat.st_mode)) + { + return 1; + } + return 0; } @@ -942,6 +948,11 @@ int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) var->type= SHOW_ARRAY; var->value= (char *) &mysql_status_vars; } + else + { + var->type= SHOW_CHAR; + var->value= (char*) "0"; + } return 0; } diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 126f873569f..40684e95615 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -5072,7 +5072,6 @@ btr_validate_index( if (!btr_validate_level(index, trx, n - i, lockout)) { err = DB_CORRUPTION; - break; } } diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index daa1901181e..9c627ecd145 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3442,7 +3442,7 @@ fail: /* prefetch siblings of the leaf for the pessimistic operation, if the page is leaf. */ - if (page_is_leaf(page)) { + if (page_is_leaf(page) && !index->is_ibuf()) { btr_cur_prefetch_siblings(block); } fail_err: @@ -3455,17 +3455,23 @@ fail_err: } ulint max_size = page_get_max_insert_size_after_reorganize(page, 1); + if (max_size < rec_size) { + goto fail; + } + + const ulint n_recs = page_get_n_recs(page); + if (UNIV_UNLIKELY(n_recs >= 8189)) { + ut_ad(srv_page_size == 65536); + goto fail; + } if (page_has_garbage(page)) { - if ((max_size < rec_size - || max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT) - && page_get_n_recs(page) > 1 + if (max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT + && n_recs > 1 && page_get_max_insert_size(page, 1) < rec_size) { goto fail; } - } else if (max_size < rec_size) { - goto fail; } /* If there have been many consecutive inserts to the @@ -4569,6 +4575,7 @@ btr_cur_optimistic_update( if (rec_offs_any_extern(*offsets)) { any_extern: + ut_ad(!index->is_ibuf()); /* Externally stored fields are treated in pessimistic update */ @@ -4765,7 +4772,7 @@ func_exit: } } - if (err != DB_SUCCESS) { + if (err != DB_SUCCESS && !index->is_ibuf()) { /* prefetch siblings of the leaf for the pessimistic operation. */ btr_cur_prefetch_siblings(block); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 6a8c4869659..5977271dc20 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3840,7 +3840,7 @@ buf_page_create(fil_space_t *space, uint32_t offset, const bool drop_hash_entry= block->page.state() == BUF_BLOCK_FILE_PAGE && UNIV_LIKELY_NULL(block->index); if (UNIV_UNLIKELY(drop_hash_entry)) - block->page.set_io_fix(BUF_IO_PIN); + rw_lock_x_lock(&block->lock); #endif /* BTR_CUR_HASH_ADAPT */ /* Page can be found in buf_pool */ @@ -3851,7 +3851,7 @@ buf_page_create(fil_space_t *space, uint32_t offset, if (UNIV_UNLIKELY(drop_hash_entry)) { btr_search_drop_page_hash_index(block); - block->page.io_unfix(); + rw_lock_x_unlock(&block->lock); } #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index e00e59f79c4..7a27160ccd5 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1511,7 +1511,7 @@ dict_create_or_check_foreign_constraint_tables(void) row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); srv_file_per_table = srv_file_per_table_backup; @@ -1612,7 +1612,7 @@ dict_create_or_check_sys_virtual() row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); srv_file_per_table = srv_file_per_table_backup; @@ -2146,7 +2146,7 @@ dict_create_or_check_sys_tablespace(void) row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); srv_file_per_table = srv_file_per_table_backup; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 0f1b3b461a8..097c907a826 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -262,7 +262,7 @@ dict_table_try_drop_aborted( } row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); } /**********************************************************************//** @@ -1975,7 +1975,7 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep) row_merge_drop_indexes_dict(trx, table->id); trx_commit_for_mysql(trx); trx->dict_operation_lock_mode = 0; - trx_free(trx); + trx->free(); } /* Free virtual column template if any */ diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index b8fdff89545..b135e042dc7 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -897,7 +897,7 @@ dict_update_filepath( trx_commit_for_mysql(trx); trx->dict_operation_lock_mode = 0; - trx_free(trx); + trx->free(); if (UNIV_LIKELY(err == DB_SUCCESS)) { /* We just updated SYS_DATAFILES due to the contents in @@ -958,7 +958,7 @@ dict_replace_tablespace_and_filepath( trx_commit_for_mysql(trx); trx->dict_operation_lock_mode = 0; - trx_free(trx); + trx->free(); return(err); } diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 1e8c9ec2131..5b79406fb18 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -120,7 +120,7 @@ bool dict_col_t::same_encoding(uint16_t a, uint16_t b) { if (const CHARSET_INFO *acs= get_charset(a, MYF(MY_WME))) if (const CHARSET_INFO *bcs= get_charset(b, MYF(MY_WME))) - return Charset(acs).same_encoding(bcs); + return Charset(bcs).encoding_allows_reinterpret_as(acs); return false; } diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 797f76862fa..03330664264 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -326,7 +326,7 @@ dict_stats_exec_sql( } if (trx_started) { - trx_free(trx); + trx->free(); } return(err); @@ -2569,7 +2569,7 @@ func_exit: trx_commit_for_mysql(trx); end: - trx_free(trx); + trx->free(); goto func_exit; } @@ -3039,7 +3039,7 @@ dict_stats_fetch_from_ps( trx_commit_for_mysql(trx); - trx_free(trx); + trx->free(); if (!index_fetch_arg.stats_were_modified) { return(DB_STATS_DO_NOT_EXIST); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 6f9f1c2c17c..9fdd5f6b457 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1462,28 +1462,31 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, ut_ad(mutex_own(&mutex)); sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= - space ? space : rotation_list.begin(); + space && space->is_in_rotation_list ? space : rotation_list.begin(); const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end= rotation_list.end(); if (space) { - while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + const bool released= !space->release(); - /* If one of the encryption threads already started the encryption - of the table then don't remove the unencrypted spaces from rotation list - - If there is a change in innodb_encrypt_tables variables value then - don't remove the last processed tablespace from the rotation list. */ - space->release(); - - if (!space->referenced() && - (!recheck || space->crypt_data) && !encrypt == !srv_encrypt_tables && - space->is_in_rotation_list) + if (space->is_in_rotation_list) { - ut_a(!rotation_list.empty()); - rotation_list.remove(*space); - space->is_in_rotation_list= false; + while (++it != end && + (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + + /* If one of the encryption threads already started the encryption + of the table then don't remove the unencrypted spaces from rotation list + + If there is a change in innodb_encrypt_tables variables value then + don't remove the last processed tablespace from the rotation list. */ + if (released && (!recheck || space->crypt_data) && + !encrypt == !srv_encrypt_tables) + { + ut_a(!rotation_list.empty()); + rotation_list.remove(*space); + space->is_in_rotation_list= false; + } } } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 5e6bd9575b1..3874616e230 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1496,21 +1496,27 @@ void fil_system_t::create(ulint hash_size) void fil_system_t::close() { - ut_ad(this == &fil_system); - ut_a(!UT_LIST_GET_LEN(LRU)); - ut_a(unflushed_spaces.empty()); - ut_a(!UT_LIST_GET_LEN(space_list)); - ut_ad(!sys_space); - ut_ad(!temp_space); + ut_ad(this == &fil_system); + ut_a(!UT_LIST_GET_LEN(LRU)); + ut_a(unflushed_spaces.empty()); + ut_a(!UT_LIST_GET_LEN(space_list)); + ut_ad(!sys_space); + ut_ad(!temp_space); + + if (is_initialised()) + { + m_initialised= false; + spaces.free(); + mutex_free(&mutex); + fil_space_crypt_cleanup(); + } - if (is_initialised()) { - m_initialised = false; - spaces.free(); - mutex_free(&mutex); - fil_space_crypt_cleanup(); - } + ut_ad(!spaces.array); - ut_ad(!spaces.array); +#ifdef UNIV_LINUX + ssd.clear(); + ssd.shrink_to_fit(); +#endif /* UNIV_LINUX */ } /** Opens all system tablespace data files. They stay open until the @@ -1995,7 +2001,7 @@ fil_check_pending_io( /* Give a warning every 10 second, starting after 1 second */ if ((count % 500) == 50) { - ib::warn() << "Trying to delete" + ib::info() << "Trying to delete" " tablespace '" << space->name << "' but there are " << space->n_pending_flushes diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index d3f6a9af72f..909e8092f99 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -253,15 +253,6 @@ fail: memset(out_buf + tmp, 0, write_size - tmp); } -#ifdef UNIV_DEBUG - /* Verify that page can be decompressed */ - { - page_t tmp_buf[UNIV_PAGE_SIZE_MAX]; - page_t page[UNIV_PAGE_SIZE_MAX]; - memcpy(page, out_buf, write_size); - ut_ad(fil_page_decompress(tmp_buf, page, flags)); - } -#endif srv_stats.page_compression_saved.add(srv_page_size - write_size); srv_stats.pages_page_compressed.inc(); @@ -332,23 +323,13 @@ static ulint fil_page_compress_for_non_full_crc32( mach_write_to_2(out_buf + FIL_PAGE_DATA + FIL_PAGE_COMP_SIZE, write_size); -#ifdef UNIV_DEBUG - /* Verify */ - switch (fil_page_get_type(out_buf)) { - case FIL_PAGE_PAGE_COMPRESSED: - case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: - break; - default: - ut_ad("wrong page type" == 0); - break; - } - ut_ad(mach_read_from_4(out_buf + FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC); ut_ad(mach_read_from_2(out_buf + FIL_PAGE_DATA + FIL_PAGE_COMP_SIZE) == write_size); +#ifdef UNIV_DEBUG bool is_compressed = (mach_read_from_8(out_buf + FIL_PAGE_COMP_ALGO) == (ulint) comp_algo); @@ -356,19 +337,10 @@ static ulint fil_page_compress_for_non_full_crc32( (mach_read_from_2(out_buf + FIL_PAGE_DATA + FIL_PAGE_ENCRYPT_COMP_ALGO) == (ulint) comp_algo); +#endif /* UNIV_DEBUG */ ut_ad(is_compressed || is_encrypted_compressed); - /* Verify that page can be decompressed */ - { - page_t tmp_buf[UNIV_PAGE_SIZE_MAX]; - page_t page[UNIV_PAGE_SIZE_MAX]; - memcpy(page, out_buf, srv_page_size); - ut_ad(fil_page_decompress(tmp_buf, page, flags)); - ut_ad(!buf_page_is_corrupted(false, page, flags)); - } -#endif /* UNIV_DEBUG */ - write_size+=header_len; if (block_size <= 0) { diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index b5083b51061..cc69863f54b 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -532,7 +532,7 @@ cleanup: } que_graph_free(graph); - trx_free(trx); + trx->free(); ret = true; goto cleanup; } @@ -2711,7 +2711,7 @@ func_exit: } } - trx_free(trx); + trx->free(); return(error); } @@ -2786,7 +2786,7 @@ fts_update_sync_doc_id( fts_sql_rollback(trx); } - trx_free(trx); + trx->free(); } return(error); @@ -3016,7 +3016,7 @@ fts_commit_table( fts_sql_commit(trx); - trx_free(trx); + trx->free(); return(error); } @@ -3781,7 +3781,7 @@ fts_doc_fetch_by_doc_id( error = fts_eval_sql(trx, graph); fts_sql_commit(trx); - trx_free(trx); + trx->free(); if (!get_doc) { fts_que_graph_free(graph); @@ -4175,9 +4175,9 @@ fts_sync_commit( << " ins/sec"; } - /* Avoid assertion in trx_free(). */ + /* Avoid assertion in trx_t::free(). */ trx->dict_operation_lock_mode = 0; - trx_free(trx); + trx->free(); return(error); } @@ -4229,9 +4229,9 @@ fts_sync_rollback( fts_sql_rollback(trx); - /* Avoid assertion in trx_free(). */ + /* Avoid assertion in trx_t::free(). */ trx->dict_operation_lock_mode = 0; - trx_free(trx); + trx->free(); } /** Run SYNC on the table, i.e., write out data from the cache to the @@ -4934,7 +4934,7 @@ fts_get_rows_count( fts_que_graph_free(graph); - trx_free(trx); + trx->free(); return(count); } @@ -4960,7 +4960,7 @@ fts_update_max_cache_size( fts_sql_commit(trx); - trx_free(trx); + trx->free(); } #endif /* FTS_CACHE_SIZE_DEBUG */ @@ -6150,14 +6150,12 @@ fts_rename_aux_tables_to_hex_format_low( << table->name << ". Please revert" " manually."; fts_sql_rollback(trx_bg); - trx_free(trx_bg); /* Continue to clear aux tables' flags2 */ not_rename = true; - continue; + } else { + fts_sql_commit(trx_bg); } - - fts_sql_commit(trx_bg); - trx_free(trx_bg); + trx_bg->free(); } DICT_TF2_FLAG_UNSET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME); @@ -6400,7 +6398,7 @@ fts_rename_aux_tables_to_hex_format( } fts_sql_commit(trx_rename); - trx_free(trx_rename); + trx_rename->free(); ib_vector_reset(aux_tables); } @@ -6479,7 +6477,7 @@ fts_drop_obsolete_aux_table_from_vector( fts_sql_commit(trx_drop); } - trx_free(trx_drop); + trx_drop->free(); } } @@ -6973,7 +6971,7 @@ fts_drop_orphaned_tables(void) row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); if (heap != NULL) { mem_heap_free(heap); @@ -7146,7 +7144,7 @@ cleanup: fts_sql_rollback(trx); } - trx_free(trx); + trx->free(); } if (!cache->stopword_info.cached_stopword) { diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 490cbcd4546..419fc6e0011 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1014,7 +1014,7 @@ fts_table_fetch_doc_ids( } if (alloc_bk_trx) { - trx_free(trx); + trx->free(); } return(error); @@ -1716,7 +1716,8 @@ fts_optimize_free( mem_heap_t* heap = static_cast<mem_heap_t*>(optim->self_heap->arg); trx_commit_for_mysql(optim->trx); - trx_free(optim->trx); + optim->trx->free(); + optim->trx = NULL; fts_doc_ids_free(optim->to_delete); fts_optimize_graph_free(&optim->graph); diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index db972b5dbff..4baba419ff7 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -2743,7 +2743,7 @@ fts_query_phrase_search( /* Ignore empty strings. */ if (num_token > 0) { - fts_string_t* token; + fts_string_t* token = NULL; fts_fetch_t fetch; trx_t* trx = query->trx; fts_ast_oper_t oper = query->oper; @@ -4123,7 +4123,7 @@ fts_query( func_exit: fts_query_free(&query); - trx_free(query_trx); + query_trx->free(); return(error); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0471923fe60..6c40a7690f3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2373,18 +2373,6 @@ trx_is_registered_for_2pc( } /*********************************************************************//** -Note that innobase_commit_ordered() was run. */ -static inline -void -trx_set_active_commit_ordered( -/*==========================*/ - trx_t* trx) /* in: transaction */ -{ - ut_a(trx_is_registered_for_2pc(trx)); - trx->active_commit_ordered = 1; -} - -/*********************************************************************//** Note that a transaction has been registered with MySQL 2PC coordinator. */ static inline void @@ -2393,7 +2381,7 @@ trx_register_for_2pc( trx_t* trx) /* in: transaction */ { trx->is_registered = 1; - ut_ad(trx->active_commit_ordered == 0); + ut_ad(!trx->active_commit_ordered); } /*********************************************************************//** @@ -2404,19 +2392,8 @@ trx_deregister_from_2pc( /*====================*/ trx_t* trx) /* in: transaction */ { - trx->is_registered = 0; - trx->active_commit_ordered = 0; -} - -/*********************************************************************//** -Check whether a transaction has active_commit_ordered set */ -static inline -bool -trx_is_active_commit_ordered( -/*=========================*/ - const trx_t* trx) /* in: transaction */ -{ - return(trx->active_commit_ordered == 1); + trx->is_registered= false; + trx->active_commit_ordered= false; } /*********************************************************************//** @@ -3787,9 +3764,8 @@ innobase_end(handlerton*, ha_panic_function) if (srv_was_started) { THD *thd= current_thd; if (thd) { // may be UNINSTALL PLUGIN statement - trx_t* trx = thd_to_trx(thd); - if (trx) { - trx_free(trx); + if (trx_t* trx = thd_to_trx(thd)) { + trx->free(); } } @@ -3975,8 +3951,7 @@ innobase_commit_ordered( (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))); innobase_commit_ordered_2(trx, thd); - - trx_set_active_commit_ordered(trx); + trx->active_commit_ordered = true; DBUG_VOID_RETURN; } @@ -4029,7 +4004,7 @@ innobase_commit( DBUG_SUICIDE();); /* Run the fast part of commit if we did not already. */ - if (!trx_is_active_commit_ordered(trx)) { + if (!trx->active_commit_ordered) { innobase_commit_ordered_2(trx, thd); } @@ -4458,7 +4433,7 @@ static int innobase_close_connection(handlerton *hton, THD *thd) return 0; } innobase_rollback_trx(trx); - trx_free(trx); + trx->free(); } return 0; } @@ -12624,7 +12599,7 @@ create_table_info_t::create_table_update_dict() if (m_flags2 & DICT_TF2_FTS) { if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) { dict_table_close(innobase_table, FALSE, FALSE); - trx_free(m_trx); + m_trx->free(); DBUG_RETURN(-1); } @@ -12755,7 +12730,7 @@ ha_innobase::create( trx_rollback_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); if (own_trx) { - trx_free(trx); + trx->free(); } DBUG_RETURN(error); } @@ -12764,7 +12739,7 @@ ha_innobase::create( row_mysql_unlock_data_dictionary(trx); if (own_trx) { - trx_free(trx); + trx->free(); } /* Flush the log to reduce probability that the .frm files and @@ -13117,7 +13092,7 @@ inline int ha_innobase::delete_table(const char* name, enum_sql_command sqlcom) innobase_commit_low(trx); - trx_free(trx); + trx->free(); DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL)); } @@ -13217,7 +13192,7 @@ innobase_drop_database( innobase_commit_low(trx); - trx_free(trx); + trx->free(); } /** Rename an InnoDB table. @@ -13394,7 +13369,7 @@ int ha_innobase::truncate() || dict_table_is_file_per_table(ib_table), trx); } - trx_free(trx); + trx->free(); if (!err) { /* Reopen the newly created table, and drop the @@ -13457,7 +13432,7 @@ ha_innobase::rename_table( innobase_commit_low(trx); - trx_free(trx); + trx->free(); if (error == DB_SUCCESS) { char norm_from[MAX_FULL_NAME_LEN]; @@ -16876,7 +16851,7 @@ innobase_commit_by_xid( ut_ad(trx->mysql_thd == NULL); trx_deregister_from_2pc(trx); ut_ad(!trx->will_lock); /* trx cache requirement */ - trx_free(trx); + trx->free(); return(XA_OK); } else { @@ -16913,7 +16888,7 @@ int innobase_rollback_by_xid(handlerton* hton, XID* xid) #endif /* WITH_WSREP */ int ret = innobase_rollback_trx(trx); ut_ad(!trx->will_lock); - trx_free(trx); + trx->free(); return(ret); } else { @@ -19542,7 +19517,7 @@ static TYPELIB page_compression_algorithms_typelib= }; static MYSQL_SYSVAR_ENUM(compression_algorithm, innodb_compression_algorithm, PLUGIN_VAR_OPCMDARG, - "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, or bzip2", + "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, bzip2, or snappy", innodb_compression_algorithm_validate, NULL, /* We use here the largest number of supported compression method to enable all those methods that are available. Availability of compression diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 95f3b52d41e..ceda6187374 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4054,7 +4054,7 @@ online_retry_drop_indexes( online_retry_drop_indexes_low(table, trx); trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); } ut_d(mutex_enter(&dict_sys.mutex)); @@ -4693,7 +4693,11 @@ innobase_pk_order_preserved( if (old_pk_column) { new_field_order = lint(old_field); } else if (innobase_pk_col_is_existing(new_col_no, col_map, - old_n_cols)) { + old_n_cols) + || new_clust_index->table->persistent_autoinc + == new_field + 1) { + /* Adding an existing column or an AUTO_INCREMENT + column may change the existing ordering. */ new_field_order = lint(old_n_uniq + existing_field_count++); } else { @@ -6828,12 +6832,6 @@ error_handling_drop_uncached_1: user_table); dict_index_t* new_clust_index = dict_table_get_first_index( ctx->new_table); - ctx->skip_pk_sort = innobase_pk_order_preserved( - ctx->col_map, clust_index, new_clust_index); - - DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", - DBUG_ASSERT(ctx->skip_pk_sort);); - ut_ad(!new_clust_index->is_instant()); /* row_merge_build_index() depends on the correct value */ ut_ad(new_clust_index->n_core_null_bytes @@ -6857,6 +6855,12 @@ error_handling_drop_uncached_1: } } + ctx->skip_pk_sort = innobase_pk_order_preserved( + ctx->col_map, clust_index, new_clust_index); + + DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", + DBUG_ASSERT(ctx->skip_pk_sort);); + if (ctx->online) { /* Allocate a log for online table rebuild. */ rw_lock_x_lock(&clust_index->lock); @@ -7159,7 +7163,7 @@ err_exit: if (ctx->trx) { row_mysql_unlock_data_dictionary(ctx->trx); - trx_free(ctx->trx); + ctx->trx->free(); } trx_commit_for_mysql(ctx->prebuilt->trx); @@ -8726,7 +8730,8 @@ rollback_inplace_alter_table( trx_commit_for_mysql(ctx->trx); row_mysql_unlock_data_dictionary(ctx->trx); - trx_free(ctx->trx); + ctx->trx->free(); + ctx->trx = NULL; func_exit: #ifndef DBUG_OFF @@ -10792,11 +10797,11 @@ ha_innobase::commit_inplace_alter_table( /* Exclusively lock the table, to ensure that no other transaction is holding locks on the table while we - change the table definition. The MySQL meta-data lock + change the table definition. The meta-data lock (MDL) should normally guarantee that no conflicting locks exist. However, FOREIGN KEY constraints checks and any transactions collected during crash recovery could be - holding InnoDB locks only, not MySQL locks. */ + holding InnoDB locks only, not MDL. */ dberr_t error = row_merge_lock_table( m_prebuilt->trx, ctx->old_table, LOCK_X); @@ -11097,7 +11102,7 @@ foreign_fail: row_mysql_unlock_data_dictionary(trx); if (trx != ctx0->trx) { - trx_free(trx); + trx->free(); } DBUG_RETURN(true); } @@ -11116,7 +11121,8 @@ foreign_fail: = static_cast<ha_innobase_inplace_ctx*>(*pctx); if (ctx->trx) { - trx_free(ctx->trx); + ctx->trx->free(); + ctx->trx = NULL; } } @@ -11164,7 +11170,7 @@ foreign_fail: } row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); DBUG_RETURN(false); } @@ -11285,7 +11291,7 @@ foreign_fail: } row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); /* TODO: The following code could be executed while allowing concurrent access to the table diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 897bda85d9b..125456c1ad4 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -2446,7 +2446,7 @@ i_s_fts_deleted_generic_fill( rw_lock_s_unlock(&dict_sys.latch); - trx_free(trx); + trx->free(); fields = table->field; @@ -2992,7 +2992,7 @@ i_s_fts_index_table_fill_selected( que_graph_free(graph); mutex_exit(&dict_sys.mutex); - trx_free(trx); + trx->free(); if (fetch.total_memory >= fts_result_cache_limit) { error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT; @@ -3470,7 +3470,7 @@ no_fts: rw_lock_s_unlock(&dict_sys.latch); - trx_free(trx); + trx->free(); DBUG_RETURN(ret); } diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 81a76ac8bab..0c42c5ffe6f 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -728,7 +728,7 @@ public: bool same_format(const dict_col_t &other) const { return same_type(other) && len >= other.len && - mbminlen == other.mbminlen && mbmaxlen == other.mbmaxlen && + mbminlen == other.mbminlen && mbmaxlen >= other.mbmaxlen && !((prtype ^ other.prtype) & ~(DATA_NOT_NULL | DATA_VERSIONED | CHAR_COLL_MASK << 16 | DATA_LONG_TRUE_VARCHAR)); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 9ea5de0a125..3a2f78fa25f 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -504,8 +504,9 @@ struct fil_space_t /** Acquire a tablespace reference. */ void acquire() { n_pending_ops++; } - /** Release a tablespace reference. */ - void release() { ut_ad(referenced()); n_pending_ops--; } + /** Release a tablespace reference. + @return whether this was the last reference */ + bool release() { auto n= n_pending_ops--; ut_ad(n); return n == 1; } /** @return whether references are being held */ bool referenced() const { return n_pending_ops; } diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h index bad040fdcda..3dca92235c7 100644 --- a/storage/innobase/include/fts0ast.h +++ b/storage/innobase/include/fts0ast.h @@ -29,14 +29,6 @@ Created 2007/03/16/03 Sunny Bains #include "mem0mem.h" -#ifdef UNIV_PFS_MEMORY - -#define malloc(A) ut_malloc_nokey(A) -#define free(A) ut_free(A) -#define realloc(P, A) ut_realloc(P, A) - -#endif /* UNIV_PFS_MEMORY */ - /* The type of AST Node */ enum fts_ast_type_t { FTS_AST_OPER, /*!< Operator */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 8a4953d7533..9eae5369d48 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -480,6 +480,11 @@ public: bool writes_are_durable() const noexcept; dberr_t write(os_offset_t offset, span<const byte> buf) noexcept; dberr_t flush() noexcept; + void free() + { + m_path.clear(); + m_path.shrink_to_fit(); + } private: std::unique_ptr<file_io> m_file; diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index fe36b3a5c83..b8d7e40246c 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -302,7 +302,7 @@ public: void read(os_offset_t offset, span<byte> buf); inline size_t files_size(); - void close_files() { files.clear(); } + void close_files() { files.clear(); files.shrink_to_fit(); } private: /** Attempt to initialize a page based on redo log records. diff --git a/storage/innobase/include/read0types.h b/storage/innobase/include/read0types.h index de3ff927520..21143ab609d 100644 --- a/storage/innobase/include/read0types.h +++ b/storage/innobase/include/read0types.h @@ -279,22 +279,15 @@ public: /** - Make the memory accessible by innodb_monitor_set_option; - It is operating also on freed transaction objects. + Declare the object mostly unaccessible. + innodb_monitor_set_option is operating also on freed transaction objects. */ - void mem_valid() const + void mem_noaccess() const { - /* Cancel the effect of MEM_NOACCESS(). */ -#ifdef __SANITIZE_ADDRESS__ - MEM_MAKE_ADDRESSABLE(&m_mutex, sizeof m_mutex); -#endif -#if defined HAVE_valgrind && !__has_feature(memory_sanitizer) - /* In Valgrind, we cannot cancel MEM_NOACCESS() without changing - the state of the V bits (indicating which bits are initialized). - We will declare the contents as initialized. - We did invoke MEM_CHECK_DEFINED() in trx_pools->mem_free(). */ - MEM_MAKE_DEFINED(&m_mutex, sizeof m_mutex); -#endif + MEM_NOACCESS(&m_open, sizeof m_open); + /* m_mutex is accessed by innodb_show_mutex_status() + and innodb_monitor_update() even after trx_t::free() */ + MEM_NOACCESS(&m_creator_trx_id, sizeof m_creator_trx_id); } }; #endif diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index d91e77f9a52..acb10428108 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -572,7 +572,7 @@ public: Releases LF_HASH pins. Must be called by thread that owns trx_t object when the latter is being - "detached" from thread (e.g. released to the pool by trx_free()). Can be + "detached" from thread (e.g. released to the pool by trx_t::free()). Can be called earlier if thread is expected not to use rw_trx_hash. Since pins are not allowed to be transferred to another thread, diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 20043a6c4a4..2294025a1aa 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -68,27 +68,18 @@ trx_get_error_info( /*===============*/ const trx_t* trx); /*!< in: trx object */ -/** @return a trx_t instance from trx_pools. */ +/** @return an allocated transaction */ trx_t *trx_create(); -/** - Release a trx_t instance back to the pool. - @param trx the instance to release. -*/ -void trx_free(trx_t*& trx); - /** At shutdown, frees a transaction object. */ -void -trx_free_at_shutdown(trx_t *trx); +void trx_free_at_shutdown(trx_t *trx); /** Disconnect a prepared transaction from MySQL. @param[in,out] trx transaction */ -void -trx_disconnect_prepared(trx_t* trx); +void trx_disconnect_prepared(trx_t *trx); /** Initialize (resurrect) transactions at startup. */ -void -trx_lists_init_at_db_start(); +void trx_lists_init_at_db_start(); /*************************************************************//** Starts the transaction if it is not yet started. */ @@ -840,7 +831,8 @@ public: the coordinator using the XA API, and is set to false after commit or rollback. */ - unsigned active_commit_ordered:1;/* 1 if owns prepare mutex */ + /** whether this is holding the prepare mutex */ + bool active_commit_ordered; /*------------------------------*/ bool check_unique_secondary; /*!< normally TRUE, but if the user @@ -1095,6 +1087,9 @@ public: ut_ad(old_n_ref > 0); } + /** Free the memory to trx_pools */ + void free(); + void assert_freed() const { diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index c31633e7f4c..e0a1f7c04ca 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -87,19 +87,6 @@ struct Pool { for (Element* elem = m_start; elem != m_last; ++elem) { ut_ad(elem->m_pool == this); -#ifdef __SANITIZE_ADDRESS__ - /* Unpoison the memory for AddressSanitizer */ - MEM_MAKE_ADDRESSABLE(&elem->m_type, - sizeof elem->m_type); -#endif -#if defined HAVE_valgrind && !__has_feature(memory_sanitizer) - /* In Valgrind, we cannot cancel MEM_NOACCESS() without - changing the state of the V bits (which indicate - which bits are initialized). - We will declare the contents as initialized. - We did invoke MEM_CHECK_DEFINED() in mem_free(). */ - MEM_MAKE_DEFINED(&elem->m_type, sizeof elem->m_type); -#endif Factory::destroy(&elem->m_type); } @@ -134,24 +121,6 @@ struct Pool { elem = NULL; } -#if defined HAVE_valgrind || defined __SANITIZE_ADDRESS__ - if (elem) { -# ifdef __SANITIZE_ADDRESS__ - /* Unpoison the memory for AddressSanitizer */ - MEM_MAKE_ADDRESSABLE(&elem->m_type, - sizeof elem->m_type); -# endif -# if defined HAVE_valgrind && !__has_feature(memory_sanitizer) - /* In Valgrind, we cannot cancel MEM_NOACCESS() without - changing the state of the V bits (which indicate - which bits are initialized). - We will declare the contents as initialized. - We did invoke MEM_CHECK_DEFINED() in mem_free(). */ - MEM_MAKE_DEFINED(&elem->m_type, sizeof elem->m_type); -# endif - } -#endif - m_lock_strategy.exit(); return elem ? &elem->m_type : NULL; } @@ -164,12 +133,10 @@ struct Pool { byte* p = reinterpret_cast<byte*>(ptr + 1); elem = reinterpret_cast<Element*>(p - sizeof(*elem)); - MEM_CHECK_DEFINED(&elem->m_type, sizeof elem->m_type); elem->m_pool->m_lock_strategy.enter(); elem->m_pool->putl(elem); - MEM_NOACCESS(&elem->m_type, sizeof elem->m_type); elem->m_pool->m_lock_strategy.exit(); } @@ -192,9 +159,6 @@ private: void putl(Element* elem) { ut_ad(elem >= m_start && elem < m_last); - - ut_ad(Factory::debug(&elem->m_type)); - m_pqueue.push(elem); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 1cf8d5fb5ad..e8a7a5aa88c 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -821,11 +821,12 @@ void log_t::file::flush() void log_t::file::close_file() { - if (!fd.is_opened()) - return; - - if (const dberr_t err= fd.close()) - ib::fatal() << "close(" << fd.get_path() << ") returned " << err; + if (fd.is_opened()) + { + if (const dberr_t err= fd.close()) + ib::fatal() << "close(" << fd.get_path() << ") returned " << err; + } + fd.free(); // Free path } /** Initialize the redo log. */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 791e13e014e..46830db1323 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -907,37 +907,34 @@ fil_name_process(char* name, ulint len, ulint space_id, bool deleted) /** Clean up after recv_sys_t::create() */ void recv_sys_t::close() { - ut_ad(this == &recv_sys); - ut_ad(!recv_writer_thread_active); - - if (is_initialised()) { - dblwr.pages.clear(); - ut_d(mutex_enter(&mutex)); - clear(); - ut_d(mutex_exit(&mutex)); + ut_ad(this == &recv_sys); + ut_ad(!recv_writer_thread_active); - if (flush_start) { - os_event_destroy(flush_start); - } + if (is_initialised()) + { + dblwr.pages.clear(); + ut_d(mutex_enter(&mutex)); + clear(); + ut_d(mutex_exit(&mutex)); - if (flush_end) { - os_event_destroy(flush_end); - } + os_event_destroy(flush_start); + os_event_destroy(flush_end); - if (buf) { - ut_free_dodump(buf, RECV_PARSING_BUF_SIZE); - buf = NULL; - } + if (buf) + { + ut_free_dodump(buf, RECV_PARSING_BUF_SIZE); + buf= nullptr; + } - last_stored_lsn = 0; - mutex_free(&writer_mutex); - mutex_free(&mutex); - } + last_stored_lsn= 0; + mutex_free(&writer_mutex); + mutex_free(&mutex); + } - recv_spaces.clear(); - mlog_init.clear(); + recv_spaces.clear(); + mlog_init.clear(); - files.clear(); + close_files(); } /******************************************************************//** @@ -1060,24 +1057,25 @@ inline void recv_sys_t::clear() /** Free most recovery data structures. */ void recv_sys_t::debug_free() { - ut_ad(this == &recv_sys); - ut_ad(is_initialised()); - mutex_enter(&mutex); + ut_ad(this == &recv_sys); + ut_ad(is_initialised()); + mutex_enter(&mutex); - pages.clear(); - ut_free_dodump(buf, RECV_PARSING_BUF_SIZE); + pages.clear(); + ut_free_dodump(buf, RECV_PARSING_BUF_SIZE); - buf = NULL; + buf= nullptr; - /* wake page cleaner up to progress */ - if (!srv_read_only_mode) { - ut_ad(!recv_recovery_is_on()); - ut_ad(!recv_writer_thread_active); - os_event_reset(buf_flush_event); - os_event_set(flush_start); - } + /* wake page cleaner up to progress */ + if (!srv_read_only_mode) + { + ut_ad(!recv_recovery_is_on()); + ut_ad(!recv_writer_thread_active); + os_event_reset(buf_flush_event); + os_event_set(flush_start); + } - mutex_exit(&mutex); + mutex_exit(&mutex); } inline void *recv_sys_t::alloc(size_t len) diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 5f42deaaf8e..5ca0d120a10 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -1053,6 +1053,15 @@ static byte* page_mem_alloc_heap(buf_block_t *block, ulint need, byte *n_heap= my_assume_aligned<2>(PAGE_N_HEAP + PAGE_HEADER + block->frame); const uint16_t h= mach_read_from_2(n_heap); + if (UNIV_UNLIKELY((h + 1) & 0x6000)) + { + /* At the minimum record size of 5+2 bytes, we can only reach this + condition when using innodb_page_size=64k. */ + ut_ad((h & 0x7fff) == 8191); + ut_ad(srv_page_size == 65536); + return NULL; + } + *heap_no= h & 0x7fff; ut_ad(*heap_no < srv_page_size / REC_N_NEW_EXTRA_BYTES); compile_time_assert(UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES < 0x3fff); diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index a04537ea6c3..5fe029d5b4d 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2098,6 +2098,7 @@ wrong_page_type: /* Validate the record list in a loop checking also that it is consistent with the directory. */ ulint count = 0, data_size = 0, own_count = 1, slot_no = 0; + ulint info_bits; slot_no = 0; slot = page_dir_get_nth_slot(page, slot_no); @@ -2121,9 +2122,16 @@ wrong_page_type: goto next_rec; } + info_bits = rec_get_info_bits(rec, page_is_comp(page)); + if (info_bits + & ~(REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) { + ib::error() << "info_bits has an incorrect value " + << info_bits; + ret = false; + } + if (rec == first_rec) { - if ((rec_get_info_bits(rec, page_is_comp(page)) - & REC_INFO_MIN_REC_FLAG)) { + if (info_bits & REC_INFO_MIN_REC_FLAG) { if (page_has_prev(page)) { ib::error() << "REC_INFO_MIN_REC_FLAG " "is set on non-left page"; @@ -2134,8 +2142,7 @@ wrong_page_type: ib::error() << "REC_INFO_MIN_REC_FLAG " "is set in a leaf-page record"; ret = false; - } else if (!rec_get_deleted_flag( - rec, page_is_comp(page)) + } else if (!(info_bits & REC_INFO_DELETED_FLAG) != !index->table->instant) { ib::error() << (index->table->instant ? "Metadata record " @@ -2149,13 +2156,51 @@ wrong_page_type: ib::error() << "Metadata record is missing"; ret = false; } - } else if (rec_get_info_bits(rec, page_is_comp(page)) - & REC_INFO_MIN_REC_FLAG) { + } else if (info_bits & REC_INFO_MIN_REC_FLAG) { ib::error() << "REC_INFO_MIN_REC_FLAG record is not " "first in page"; ret = false; } + if (page_is_comp(page)) { + const rec_comp_status_t status = rec_get_status(rec); + if (status != REC_STATUS_ORDINARY + && status != REC_STATUS_NODE_PTR + && status != REC_STATUS_INFIMUM + && status != REC_STATUS_SUPREMUM + && status != REC_STATUS_INSTANT) { + ib::error() << "impossible record status " + << status; + ret = false; + } else if (page_rec_is_infimum(rec)) { + if (status != REC_STATUS_INFIMUM) { + ib::error() + << "infimum record has status " + << status; + ret = false; + } + } else if (page_rec_is_supremum(rec)) { + if (status != REC_STATUS_SUPREMUM) { + ib::error() << "supremum record has " + "status " + << status; + ret = false; + } + } else if (!page_is_leaf(page)) { + if (status != REC_STATUS_NODE_PTR) { + ib::error() << "node ptr record has " + "status " + << status; + ret = false; + } + } else if (!index->is_instant() + && status == REC_STATUS_INSTANT) { + ib::error() << "instantly added record in a " + "non-instant index"; + ret = false; + } + } + /* Check that the records are in the ascending order */ if (count >= PAGE_HEAP_NO_USER_LOW && !page_rec_is_supremum(rec)) { diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 29197fde46b..baf63650347 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1769,7 +1769,7 @@ exit: error = ins_ctx.btr_bulk->finish(error); UT_DELETE(ins_ctx.btr_bulk); - trx_free(trx); + trx->free(); mem_heap_free(heap); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 9fc7425957a..2ec0a06709e 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2200,7 +2200,7 @@ row_import_cleanup( row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); prebuilt->trx->op_info = ""; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 3e0ffcf28b9..4f4329082fe 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -4030,7 +4030,7 @@ row_merge_drop_temp_indexes(void) trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index f7868135a94..42ed2aaf415 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2568,7 +2568,7 @@ row_drop_table_for_mysql_in_background( trx_commit_for_mysql(trx); - trx_free(trx); + trx->free(); return(error); } @@ -2752,7 +2752,7 @@ row_mysql_drop_garbage_tables() btr_pcur_close(&pcur); mtr.commit(); row_mysql_unlock_data_dictionary(trx); - trx_free(trx); + trx->free(); mem_heap_free(heap); } @@ -3807,8 +3807,6 @@ funct_exit_all_freed: trx->op_info = ""; - srv_inc_activity_count(); - DBUG_RETURN(err); } @@ -4521,12 +4519,20 @@ end: if (err != DB_SUCCESS) { if (old_is_tmp) { - ib::error() << "In ALTER TABLE " + /* In case of copy alter, ignore the + loading of foreign key constraint + when foreign_key_check is disabled */ + ib::error_or_warn(trx->check_foreigns) + << "In ALTER TABLE " << ut_get_name(trx, new_name) << " has or is referenced in foreign" " key constraints which are not" " compatible with the new table" " definition."; + if (!trx->check_foreigns) { + err = DB_SUCCESS; + goto funct_exit; + } } else { ib::error() << "In RENAME TABLE table " << ut_get_name(trx, new_name) @@ -4596,7 +4602,7 @@ funct_exit: trx_bg->dict_operation_lock_mode = 0; trx_commit_for_mysql(trx_bg); - trx_free(trx_bg); + trx_bg->free(); } if (table != NULL) { diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 63edbd9b86d..68856d47b5e 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -84,11 +84,11 @@ row_undo_ins_remove_clust_rec( online = false; } else { index->set_modified(mtr); + ut_ad(lock_table_has_locks(index->table)); online = dict_index_is_online_ddl(index); if (online) { ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - ut_ad(node->trx->dict_operation_lock_mode - != RW_X_LATCH); + ut_ad(!node->trx->dict_operation_lock_mode); ut_ad(node->table->id != DICT_INDEXES_ID); ut_ad(node->table->id != DICT_COLUMNS_ID); mtr_s_lock_index(index, &mtr); @@ -529,6 +529,9 @@ row_undo_ins( return DB_SUCCESS; } + ut_ad(node->table->is_temporary() + || lock_table_has_locks(node->table)); + /* Iterate over all the indexes and undo the insert.*/ node->index = dict_table_get_first_index(node->table); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 39f7ddbd79a..d32c6cd2510 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -244,10 +244,7 @@ row_undo_mod_clust( bool online; ut_ad(thr_get_trx(thr) == node->trx); - ut_ad(node->trx->dict_operation_lock_mode); ut_ad(node->trx->in_rollback); - ut_ad(rw_lock_own_flagged(&dict_sys.latch, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); log_free_check(); pcur = &node->pcur; @@ -259,11 +256,12 @@ row_undo_mod_clust( mtr.set_log_mode(MTR_LOG_NO_REDO); } else { index->set_modified(mtr); + ut_ad(lock_table_has_locks(index->table)); } online = dict_index_is_online_ddl(index); if (online) { - ut_ad(node->trx->dict_operation_lock_mode != RW_X_LATCH); + ut_ad(!node->trx->dict_operation_lock_mode); mtr_s_lock_index(index, &mtr); } @@ -302,17 +300,7 @@ row_undo_mod_clust( ut_ad(err == DB_SUCCESS || err == DB_OUT_OF_FILE_SPACE); } - /* Online rebuild cannot be initiated while we are holding - dict_sys.latch and index->lock. (It can be aborted.) */ - ut_ad(online || !dict_index_is_online_ddl(index)); - - if (err == DB_SUCCESS && online) { - - ut_ad(rw_lock_own_flagged( - &index->lock, - RW_LOCK_FLAG_S | RW_LOCK_FLAG_X - | RW_LOCK_FLAG_SX)); - + if (err == DB_SUCCESS && online && dict_index_is_online_ddl(index)) { switch (node->rec_type) { case TRX_UNDO_DEL_MARK_REC: row_log_table_insert( @@ -887,37 +875,6 @@ func_exit_no_pcur: } /***********************************************************//** -Flags a secondary index corrupted. */ -static MY_ATTRIBUTE((nonnull)) -void -row_undo_mod_sec_flag_corrupted( -/*============================*/ - trx_t* trx, /*!< in/out: transaction */ - dict_index_t* index) /*!< in: secondary index */ -{ - ut_ad(!dict_index_is_clust(index)); - - switch (trx->dict_operation_lock_mode) { - case RW_S_LATCH: - /* Because row_undo() is holding an S-latch - on the data dictionary during normal rollback, - we can only mark the index corrupted in the - data dictionary cache. TODO: fix this somehow.*/ - mutex_enter(&dict_sys.mutex); - dict_set_corrupted_index_cache_only(index); - mutex_exit(&dict_sys.mutex); - break; - default: - ut_ad(0); - /* fall through */ - case RW_X_LATCH: - /* This should be the rollback of a data dictionary - transaction. */ - dict_set_corrupted(index, trx, "rollback"); - } -} - -/***********************************************************//** Undoes a modify in secondary indexes when undo record type is UPD_DEL. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -1030,8 +987,7 @@ row_undo_mod_del_mark_sec( } if (err == DB_DUPLICATE_KEY) { - row_undo_mod_sec_flag_corrupted( - thr_get_trx(thr), index); + index->type |= DICT_CORRUPT; err = DB_SUCCESS; /* Do not return any error to the caller. The duplicate will be reported by ALTER TABLE or @@ -1176,8 +1132,7 @@ row_undo_mod_upd_exist_sec( } if (err == DB_DUPLICATE_KEY) { - row_undo_mod_sec_flag_corrupted( - thr_get_trx(thr), index); + index->type |= DICT_CORRUPT; err = DB_SUCCESS; } else if (err != DB_SUCCESS) { break; @@ -1340,6 +1295,8 @@ row_undo_mod( return DB_SUCCESS; } + ut_ad(node->table->is_temporary() + || lock_table_has_locks(node->table)); node->index = dict_table_get_first_index(node->table); ut_ad(dict_index_is_clust(node->index)); diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 20bf53e3f91..2fe1135b894 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -411,15 +411,17 @@ row_undo( return DB_SUCCESS; } - /* Prevent DROP TABLE etc. while we are rolling back this row. - If we are doing a TABLE CREATE or some other dictionary operation, - then we already have dict_sys.latch locked in x-mode. Do not - try to lock again, because that would cause a hang. */ - + /* Prevent prepare_inplace_alter_table_dict() from adding + dict_table_t::indexes while we are processing the record. + Recovered transactions are not protected by MDL, and the + secondary index creation is not protected by table locks + for online operation. (A table lock would only be acquired + when committing the ALTER TABLE operation.) */ trx_t* trx = node->trx; - const bool locked_data_dict = (trx->dict_operation_lock_mode == 0); + const bool locked_data_dict = UNIV_UNLIKELY(trx->is_recovered) + && !trx->dict_operation_lock_mode; - if (locked_data_dict) { + if (UNIV_UNLIKELY(locked_data_dict)) { row_mysql_freeze_data_dictionary(trx); } @@ -439,7 +441,7 @@ row_undo( err = DB_CORRUPTION; } - if (locked_data_dict) { + if (UNIV_UNLIKELY(locked_data_dict)) { row_mysql_unfreeze_data_dictionary(trx); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index aa8a5ea2d14..ceb9245f659 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -73,7 +73,7 @@ Created 10/8/1995 Heikki Tuuri #include "fil0crypt.h" #include "fil0pagecompress.h" #include "trx0types.h" - +#include <list> #include <my_service_manager.h> /* The following is the maximum allowed duration of a lock wait. */ @@ -2110,7 +2110,7 @@ static uint32_t srv_do_purge(ulint* n_total_purged) } -static std::queue<THD*> purge_thds; +static std::list<THD*> purge_thds; static std::mutex purge_thd_mutex; extern void* thd_attach_thd(THD*); extern void thd_detach_thd(void *); @@ -2120,11 +2120,11 @@ THD* acquire_thd(void **ctx) std::unique_lock<std::mutex> lk(purge_thd_mutex); if (purge_thds.empty()) { THD* thd = current_thd; - purge_thds.push(innobase_create_background_thd("InnoDB purge worker")); + purge_thds.push_back(innobase_create_background_thd("InnoDB purge worker")); set_current_thd(thd); } THD* thd = purge_thds.front(); - purge_thds.pop(); + purge_thds.pop_front(); lk.unlock(); /* Set current thd, and thd->mysys_var as well, @@ -2137,7 +2137,7 @@ void release_thd(THD *thd, void *ctx) { thd_detach_thd(ctx); std::unique_lock<std::mutex> lk(purge_thd_mutex); - purge_thds.push(thd); + purge_thds.push_back(thd); lk.unlock(); set_current_thd(0); } @@ -2236,7 +2236,7 @@ static void srv_shutdown_purge_tasks() while (!purge_thds.empty()) { innobase_destroy_background_thd(purge_thds.front()); - purge_thds.pop(); + purge_thds.pop_front(); } } diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 6747ada6de4..3f1d4258484 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -192,7 +192,7 @@ void purge_sys_t::close() ut_ad(!trx->id); ut_ad(trx->state == TRX_STATE_ACTIVE); trx->state= TRX_STATE_NOT_STARTED; - trx_free(trx); + trx->free(); rw_lock_free(&latch); mutex_free(&pq_mutex); mem_heap_free(heap); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index a16ee95dc83..dc3dd51bb89 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -807,7 +807,7 @@ discard: trx_free_at_shutdown(trx); } else - trx_free(trx); + trx->free(); } } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index a9ba8cd7786..d1f6a66f09b 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -110,7 +110,7 @@ trx_init( trx->op_info = ""; - trx->active_commit_ordered = 0; + trx->active_commit_ordered = false; trx->isolation_level = TRX_ISO_REPEATABLE_READ; @@ -210,6 +210,18 @@ struct TrxFactory { @param trx the transaction for which to release resources */ static void destroy(trx_t* trx) { +#ifdef __SANITIZE_ADDRESS__ + /* Unpoison the memory for AddressSanitizer */ + MEM_MAKE_ADDRESSABLE(trx, sizeof *trx); +#elif !__has_feature(memory_sanitizer) + /* In Valgrind, we cannot cancel MEM_NOACCESS() without + changing the state of the V bits (which indicate + which bits are initialized). + We will declare the contents as initialized. + We did invoke MEM_CHECK_DEFINED() in trx_t::free(). */ + MEM_MAKE_DEFINED(trx, sizeof *trx); +#endif + ut_a(trx->magic_n == TRX_MAGIC_N); ut_ad(!trx->mysql_thd); @@ -238,36 +250,6 @@ struct TrxFactory { trx->read_view.~ReadView(); } - - /** Enforce any invariants here, this is called before the transaction - is added to the pool. - @return true if all OK */ - static bool debug(const trx_t* trx) - { - ut_a(trx->error_state == DB_SUCCESS); - - ut_a(trx->magic_n == TRX_MAGIC_N); - - ut_ad(!trx->read_only); - - ut_ad(trx->state == TRX_STATE_NOT_STARTED); - - ut_ad(trx->dict_operation == TRX_DICT_OP_NONE); - - ut_ad(trx->mysql_thd == 0); - - ut_a(trx->lock.wait_thr == NULL); - ut_a(trx->lock.wait_lock == NULL); - ut_a(trx->dict_operation_lock_mode == 0); - - ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); - - ut_ad(trx->autoinc_locks == NULL); - - ut_ad(trx->lock.table_locks.empty()); - - return(true); - } }; /** The lock strategy for TrxPool */ @@ -344,11 +326,24 @@ trx_pool_close() trx_pools = 0; } -/** @return a trx_t instance from trx_pools. */ +/** @return an allocated transaction */ trx_t *trx_create() { trx_t* trx = trx_pools->get(); +#ifdef __SANITIZE_ADDRESS__ + /* Unpoison the memory for AddressSanitizer. + It may have been poisoned in trx_t::free().*/ + MEM_MAKE_ADDRESSABLE(trx, sizeof *trx); +#elif !__has_feature(memory_sanitizer) + /* In Valgrind, we cannot cancel MEM_NOACCESS() without + changing the state of the V bits (which indicate + which bits are initialized). + We will declare the contents as initialized. + We did invoke MEM_CHECK_DEFINED() in trx_t::free(). */ + MEM_MAKE_DEFINED(trx, sizeof *trx); +#endif + trx->assert_freed(); mem_heap_t* heap; @@ -364,14 +359,9 @@ trx_t *trx_create() alloc = ib_heap_allocator_create(heap); - /* Remember to free the vector explicitly in trx_free(). */ trx->autoinc_locks = ib_vector_create(alloc, sizeof(void**), 4); - /* Should have been either just initialized or .clear()ed by - trx_free(). */ ut_ad(trx->mod_tables.empty()); - ut_ad(trx->lock.table_locks.empty()); - ut_ad(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); ut_ad(trx->lock.n_rec_locks == 0); ut_ad(trx->lock.table_cached == 0); ut_ad(trx->lock.rec_cached == 0); @@ -382,83 +372,101 @@ trx_t *trx_create() return(trx); } -/** - Release a trx_t instance back to the pool. - @param trx the instance to release. -*/ -void trx_free(trx_t*& trx) +/** Free the memory to trx_pools */ +void trx_t::free() { - ut_ad(!trx->n_mysql_tables_in_use); - ut_ad(!trx->mysql_n_tables_locked); - ut_ad(!trx->internal); - ut_ad(!trx->mysql_log_file_name); - - if (trx->n_mysql_tables_in_use != 0 - || trx->mysql_n_tables_locked != 0) { - - ib::error() << "MySQL is freeing a thd though" - " trx->n_mysql_tables_in_use is " - << trx->n_mysql_tables_in_use - << " and trx->mysql_n_tables_locked is " - << trx->mysql_n_tables_locked << "."; - - trx_print(stderr, trx, 600); - ut_print_buf(stderr, trx, sizeof(trx_t)); - putc('\n', stderr); - } - - trx->dict_operation = TRX_DICT_OP_NONE; - ut_ad(!trx->dict_operation_lock_mode); - - trx_sys.deregister_trx(trx); - - trx->assert_freed(); + MEM_CHECK_DEFINED(this, sizeof *this); + + ut_ad(!n_mysql_tables_in_use); + ut_ad(!mysql_log_file_name); + ut_ad(!mysql_n_tables_locked); + ut_ad(!internal); + ut_ad(!will_lock); + ut_ad(error_state == DB_SUCCESS); + ut_ad(magic_n == TRX_MAGIC_N); + ut_ad(!read_only); + ut_ad(!lock.wait_lock); - trx_sys.rw_trx_hash.put_pins(trx); - trx->mysql_thd = 0; - - // FIXME: We need to avoid this heap free/alloc for each commit. - if (trx->autoinc_locks != NULL) { - ut_ad(ib_vector_is_empty(trx->autoinc_locks)); - /* We allocated a dedicated heap for the vector. */ - ib_vector_free(trx->autoinc_locks); - trx->autoinc_locks = NULL; - } + dict_operation= TRX_DICT_OP_NONE; + trx_sys.deregister_trx(this); + assert_freed(); + trx_sys.rw_trx_hash.put_pins(this); - trx->mod_tables.clear(); + mysql_thd= nullptr; - /* trx locking state should have been reset before returning trx - to pool */ - ut_ad(trx->will_lock == 0); - - trx_pools->mem_free(trx); - trx->read_view.mem_valid(); -#ifdef __SANITIZE_ADDRESS__ - /* Unpoison the memory for innodb_monitor_set_option; - it is operating also on the freed transaction objects. */ - MEM_MAKE_ADDRESSABLE(&trx->mutex, sizeof trx->mutex); -# ifdef WITH_WSREP - MEM_MAKE_ADDRESSABLE(&trx->wsrep, sizeof trx->wsrep); -# endif - /* For innobase_kill_connection() */ - MEM_MAKE_ADDRESSABLE(&trx->state, sizeof trx->state); - MEM_MAKE_ADDRESSABLE(&trx->mysql_thd, sizeof trx->mysql_thd); -#endif -#if defined HAVE_valgrind && !__has_feature(memory_sanitizer) - /* In Valgrind, we cannot cancel the effect of MEM_NOACCESS() - without changing the state of the V bits (indicating which - bits are initialized). We did invoke MEM_CHECK_DEFINED() in - trx_pools->mem_free(). */ - MEM_MAKE_DEFINED(&trx->mutex, sizeof trx->mutex); - /* For innobase_kill_connection() */ -# ifdef WITH_WSREP - MEM_MAKE_DEFINED(&trx->wsrep, sizeof trx->wsrep); -# endif - MEM_MAKE_DEFINED(&trx->state, sizeof trx->state); - MEM_MAKE_DEFINED(&trx->mysql_thd, sizeof trx->mysql_thd); -#endif + // FIXME: We need to avoid this heap free/alloc for each commit. + if (autoinc_locks) + { + ut_ad(ib_vector_is_empty(autoinc_locks)); + /* We allocated a dedicated heap for the vector. */ + ib_vector_free(autoinc_locks); + autoinc_locks= NULL; + } - trx = NULL; + mod_tables.clear(); + + MEM_NOACCESS(&n_ref, sizeof n_ref); + /* do not poison mutex */ + MEM_NOACCESS(&id, sizeof id); + /* state is accessed by innobase_kill_connection() */ + MEM_NOACCESS(&is_recovered, sizeof is_recovered); + /* wsrep is accessed by innobase_kill_connection() */ + read_view.mem_noaccess(); + MEM_NOACCESS(&lock, sizeof lock); + MEM_NOACCESS(&op_info, sizeof op_info); + MEM_NOACCESS(&isolation_level, sizeof isolation_level); + MEM_NOACCESS(&check_foreigns, sizeof check_foreigns); + MEM_NOACCESS(&is_registered, sizeof is_registered); + MEM_NOACCESS(&active_commit_ordered, sizeof active_commit_ordered); + MEM_NOACCESS(&check_unique_secondary, sizeof check_unique_secondary); + 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); + MEM_NOACCESS(&start_time, sizeof start_time); + MEM_NOACCESS(&start_time_micro, sizeof start_time_micro); + MEM_NOACCESS(&commit_lsn, sizeof commit_lsn); + MEM_NOACCESS(&table_id, sizeof table_id); + /* mysql_thd is accessed by innobase_kill_connection() */ + MEM_NOACCESS(&mysql_log_file_name, sizeof mysql_log_file_name); + MEM_NOACCESS(&mysql_log_offset, sizeof mysql_log_offset); + MEM_NOACCESS(&n_mysql_tables_in_use, sizeof n_mysql_tables_in_use); + MEM_NOACCESS(&mysql_n_tables_locked, sizeof mysql_n_tables_locked); + MEM_NOACCESS(&error_state, sizeof error_state); + MEM_NOACCESS(&error_info, sizeof error_info); + MEM_NOACCESS(&error_key_num, sizeof error_key_num); + MEM_NOACCESS(&graph, sizeof graph); + MEM_NOACCESS(&trx_savepoints, sizeof trx_savepoints); + MEM_NOACCESS(&undo_no, sizeof undo_no); + MEM_NOACCESS(&last_sql_stat_start, sizeof last_sql_stat_start); + MEM_NOACCESS(&rsegs, sizeof rsegs); + MEM_NOACCESS(&roll_limit, sizeof roll_limit); + MEM_NOACCESS(&in_rollback, sizeof in_rollback); + MEM_NOACCESS(&pages_undone, sizeof pages_undone); + MEM_NOACCESS(&n_autoinc_rows, sizeof n_autoinc_rows); + MEM_NOACCESS(&autoinc_locks, sizeof autoinc_locks); + MEM_NOACCESS(&read_only, sizeof read_only); + MEM_NOACCESS(&auto_commit, sizeof auto_commit); + MEM_NOACCESS(&will_lock, sizeof will_lock); + MEM_NOACCESS(&fts_trx, sizeof fts_trx); + MEM_NOACCESS(&fts_next_doc_id, sizeof fts_next_doc_id); + MEM_NOACCESS(&flush_tables, sizeof flush_tables); + MEM_NOACCESS(&ddl, sizeof ddl); + MEM_NOACCESS(&internal, sizeof internal); +#ifdef UNIV_DEBUG + MEM_NOACCESS(&start_line, sizeof start_line); + MEM_NOACCESS(&start_file, sizeof start_file); +#endif /* UNIV_DEBUG */ + MEM_NOACCESS(&xid, sizeof xid); + MEM_NOACCESS(&mod_tables, sizeof mod_tables); + MEM_NOACCESS(&detailed_error, sizeof detailed_error); + MEM_NOACCESS(&n_rec_lock_waits, sizeof n_rec_lock_waits); + MEM_NOACCESS(&n_table_lock_waits, sizeof n_table_lock_waits); + MEM_NOACCESS(&total_rec_lock_wait_time, sizeof total_rec_lock_wait_time); + MEM_NOACCESS(&total_table_lock_wait_time, sizeof total_table_lock_wait_time); + MEM_NOACCESS(&magic_n, sizeof magic_n); + trx_pools->mem_free(this); } /** Transition to committed state, to release implicit locks. */ @@ -530,8 +538,7 @@ trx_free_at_shutdown(trx_t *trx) trx->state = TRX_STATE_NOT_STARTED; ut_ad(!UT_LIST_GET_LEN(trx->lock.trx_locks)); trx->id = 0; - - trx_free(trx); + trx->free(); } @@ -1188,6 +1195,7 @@ trx_flush_log_if_needed_low( case 1: /* Write the log and optionally flush it to disk */ log_write_up_to(lsn, flush); + srv_inc_activity_count(); return; case 0: /* Do nothing */ diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index 9de0ca81fe3..1ddac168d95 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -342,11 +342,11 @@ allocations, would not hurt if called twice, but would be pointless. */ void ut_crc32_init() { #ifndef HAVE_CRC32_VPMSUM -# if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) && defined(HAVE_ARMV8_CRYPTO) - if (crc32c_aarch64_available()) +# if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) + if (const char *crc32c_implementation= crc32c_aarch64_available()) { ut_crc32_low= crc32c_aarch64; - ut_crc32_implementation= "Using ARMv8 crc32 + pmull instructions"; + ut_crc32_implementation= crc32c_implementation; return; } # elif defined(TRY_SSE4_2) diff --git a/storage/maria/aria_chk.c b/storage/maria/aria_chk.c index f46fe7490d8..4f8438fb9d0 100644 --- a/storage/maria/aria_chk.c +++ b/storage/maria/aria_chk.c @@ -127,7 +127,7 @@ int main(int argc, char **argv) int error; MY_INIT(argv[0]); - my_init_stacktrace(1); + my_setup_stacktrace(); default_log_dir= opt_log_dir= maria_data_root= (char *)"."; maria_chk_init(&check_param); check_param.opt_lock_memory= 1; /* Lock memory if possible */ diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index a13190b0220..25c44f7c90e 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -897,7 +897,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, fn_format(kfilename, name, "", MARIA_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); - klinkname_ptr= NullS; /* Replace the current file. Don't sync dir now if the data file has the same path. @@ -1174,7 +1173,14 @@ int maria_create(const char *name, enum data_file_type datafile_type, FALSE, TRUE)) goto err; my_free(log_data); + + /* + We don't need to sync directory as we can use the log to recreate + the index and data files if needed. + */ + sync_dir= 0; } + DBUG_ASSERT(!internal_table || sync_dir == 0); if (!(flags & HA_DONT_TOUCH_DATA)) { @@ -1212,7 +1218,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, if ((dfile= mysql_file_create_with_symlink(key_file_dfile, dlinkname_ptr, dfilename, 0, create_mode, - MYF(MY_WME | create_flag | sync_dir))) < 0) + MYF(MY_WME | create_flag))) < 0) goto err; errpos=3; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 0ec0e58f8a8..1413b708bbc 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -3618,7 +3618,8 @@ my_bool translog_init_with_table(const char *directory, int old_log_was_recovered= 0, logs_found= 0; uint old_flags= flags; uint32 start_file_num= 1; - TRANSLOG_ADDRESS sure_page, last_page, last_valid_page, checkpoint_lsn; + TRANSLOG_ADDRESS UNINIT_VAR(sure_page), last_page, last_valid_page, + checkpoint_lsn; my_bool version_changed= 0; DBUG_ENTER("translog_init_with_table"); diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index fcdb4569f4c..6f2825a3319 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -623,7 +623,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, fn_format(kfilename, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); - klinkname_ptr= 0; /* Replace the current file */ create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD; } diff --git a/storage/rocksdb/mysql-test/rocksdb/include/restart_mysqld_with_option.inc b/storage/rocksdb/mysql-test/rocksdb/include/restart_mysqld_with_option.inc index 4250b368b1a..81cd2200ae0 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/restart_mysqld_with_option.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/restart_mysqld_with_option.inc @@ -15,7 +15,7 @@ if ($rpl_inited) # Send shutdown to the connected server and give # it 10 seconds to die before zapping it -shutdown_server 10; +shutdown_server; # Write file to make mysql-test-run.pl start up the server again --exec echo "restart:$_mysqld_option" > $_expect_file_name diff --git a/storage/rocksdb/mysql-test/rocksdb/t/check_ignore_unknown_options.test b/storage/rocksdb/mysql-test/rocksdb/t/check_ignore_unknown_options.test index c8c12626139..15a7d319c04 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/check_ignore_unknown_options.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/check_ignore_unknown_options.test @@ -41,7 +41,7 @@ perl; EOF --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---shutdown_server 10 +--shutdown_server --error 1 --exec $MYSQLD_CMD --plugin_load=$HA_ROCKSDB_SO --rocksdb_ignore_unknown_options=0 --log-error=$error_log diff --git a/storage/rocksdb/mysql-test/rocksdb/t/insert_optimized_config.test b/storage/rocksdb/mysql-test/rocksdb/t/insert_optimized_config.test index 46ea7f0eb0a..a24851d9d8c 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/insert_optimized_config.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/insert_optimized_config.test @@ -8,7 +8,7 @@ DROP TABLE IF EXISTS t1; # reload with load optimized config let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart:--rocksdb_write_disable_wal=1 --rocksdb_flush_log_at_trx_commit=0 --rocksdb_default_cf_options=write_buffer_size=16k;target_file_size_base=16k;level0_file_num_compaction_trigger=4;level0_slowdown_writes_trigger=256;level0_stop_writes_trigger=256;max_write_buffer_number=16;compression_per_level=kNoCompression;memtable=vector:1024 --rocksdb_override_cf_options=__system__={memtable=skip_list:16} --rocksdb_compaction_sequential_deletes=0 --rocksdb_compaction_sequential_deletes_window=0 --rocksdb_allow_concurrent_memtable_write=0" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect @@ -39,7 +39,7 @@ select count(*), sum(id), sum(i1), sum(i2) from t1; # reload without load optimized config let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart:--rocksdb_write_disable_wal=0 --rocksdb_default_cf_options=write_buffer_size=64k;target_file_size_base=64k;max_bytes_for_level_base=1m;compression_per_level=kNoCompression;" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb/t/mysqldump2.test b/storage/rocksdb/mysql-test/rocksdb/t/mysqldump2.test index ca9eb5d2ecf..4f4f5ed092b 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/mysqldump2.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/mysqldump2.test @@ -21,7 +21,7 @@ optimize table t1; #wiping block cache let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart:--rocksdb_default_cf_options=write_buffer_size=64k;target_file_size_base=64k;max_bytes_for_level_base=1m;compression_per_level=kNoCompression;disable_auto_compactions=true;level0_stop_writes_trigger=1000 " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb/t/optimize_table.test b/storage/rocksdb/mysql-test/rocksdb/t/optimize_table.test index 7a8f4fc7085..50df3f9c102 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/optimize_table.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/optimize_table.test @@ -32,7 +32,7 @@ while ($t <= 6) { # Disable auto compaction so that effects of optimize table are stable let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart:--rocksdb_default_cf_options=write_buffer_size=64k;target_file_size_base=64k;max_bytes_for_level_base=1m;compression_per_level=kNoCompression;disable_auto_compactions=true;level0_stop_writes_trigger=1000 " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test b/storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test index 03d1d0a60bc..49e5e5c1172 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test @@ -10,7 +10,7 @@ DROP TABLE IF EXISTS t1; --exec echo "wait" >$_expect_file_name # restart server with correct parameters -shutdown_server 10; +shutdown_server; --exec echo "restart:--rocksdb_persistent_cache_path=$_cache_file_name --rocksdb_persistent_cache_size_mb=100" >$_expect_file_name --sleep 5 --enable_reconnect @@ -28,7 +28,7 @@ select * from t1 where a = 1; # restart server to re-read cache --exec echo "wait" >$_expect_file_name -shutdown_server 10; +shutdown_server; --exec echo "restart:--rocksdb_persistent_cache_path=$_cache_file_name --rocksdb_persistent_cache_size_mb=100" >$_expect_file_name --sleep 5 --enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb/t/shutdown.test b/storage/rocksdb/mysql-test/rocksdb/t/shutdown.test index ba625deb514..f76bc9f6153 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/shutdown.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/shutdown.test @@ -23,7 +23,7 @@ while ($i <= $max) { # Restart the server let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; --exec echo "wait" > $restart_file ---shutdown_server 10 +--shutdown_server --source include/wait_until_disconnected.inc -- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb/t/validate_datadic.test b/storage/rocksdb/mysql-test/rocksdb/t/validate_datadic.test index ec48dc03ec8..e7ab37d2658 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/validate_datadic.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/validate_datadic.test @@ -25,7 +25,7 @@ CREATE TABLE t2 (pk int primary key) ENGINE=ROCKSDB PARTITION BY KEY(pk) PARTITI # Send shutdown to the connected server and give it 10 seconds to die before # zapping it -shutdown_server 10; +shutdown_server; # Write file to make mysql-test-run.pl start up the server again --exec echo "restart" >$_expect_file_name @@ -42,7 +42,7 @@ shutdown_server 10; # Now shut down again and rename one of the .frm files --exec echo "wait" >$_expect_file_name -shutdown_server 10; +shutdown_server; # Rename the file --move_file $MYSQLTEST_VARDIR/mysqld.1/data/test/t1.frm $MYSQLTEST_VARDIR/mysqld.1/data/test/t1.frm.tmp @@ -70,7 +70,7 @@ shutdown_server 10; # Now shut down again and rename one the .frm file back and make a copy of it --exec echo "wait" >$_expect_file_name -shutdown_server 10; +shutdown_server; --remove_file $LOG # Rename the file --move_file $MYSQLTEST_VARDIR/mysqld.1/data/test/t1.frm.tmp $MYSQLTEST_VARDIR/mysqld.1/data/test/t1.frm @@ -92,7 +92,7 @@ shutdown_server 10; # Shut down an clean up --exec echo "wait" >$_expect_file_name -shutdown_server 10; +shutdown_server; --remove_file $MYSQLTEST_VARDIR/mysqld.1/data/test/t1_dummy.frm --exec echo "restart" >$_expect_file_name --enable_reconnect diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test index 631d9ca533f..845f155877a 100644 --- a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test @@ -237,7 +237,7 @@ SHOW STATUS LIKE "%transactions%engine"; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF ---shutdown_server 30 +--shutdown_server --source include/wait_until_disconnected.inc # Restart without binary log. diff --git a/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_rate_limiter_bytes_per_sec_basic.test b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_rate_limiter_bytes_per_sec_basic.test index 8277011831a..743f942af9c 100644 --- a/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_rate_limiter_bytes_per_sec_basic.test +++ b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/rocksdb_rate_limiter_bytes_per_sec_basic.test @@ -13,7 +13,7 @@ SET @@global.rocksdb_rate_limiter_bytes_per_sec = 10000; # Send shutdown to the connected server and give it 10 seconds to die before # zapping it -shutdown_server 10; +shutdown_server; # Attempt to restart the server with the rate limiter on --exec echo "restart:--rocksdb_rate_limiter_bytes_per_sec=10000" >$_expect_file_name @@ -53,7 +53,7 @@ SET @@global.rocksdb_rate_limiter_bytes_per_sec = -1; # Restart the server without the rate limiter --exec echo "wait" >$_expect_file_name -shutdown_server 10; +shutdown_server; --exec echo "restart" >$_expect_file_name --sleep 5 diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index c72fc9b6d00..9b7cea54d00 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -828,7 +828,7 @@ my_strtoll10_mb2(CHARSET_INFO *cs __attribute__((unused)), const char *nptr, char **endptr, int *error) { const uchar *s, *end, *start, *n_end, *true_end; - uchar c; + uchar UNINIT_VAR(c); unsigned long i, j, k; ulonglong li; int negative; diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index 79f347ec271..14749092103 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -100,7 +100,7 @@ # in configuration between instances. # # [Service] -# Environment=MYSQLD_MULTI_INSTANCE="--socket=/var/run/mysqld/%I.sock \ +# Environment=MYSQLD_MULTI_INSTANCE="--socket=/run/mysqld/%I.sock \ # --datadir=/var/lib/mysqld-multi/%I \ # --skip-networking" # diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index 18a9c357ff2..c60ecd28531 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -54,8 +54,8 @@ /var/log/mysql.log rw, /var/log/mysql/ r, /var/log/mysql/* rw, - /var/run/mysqld/mysqld.pid w, - /var/run/mysqld/mysqld.sock w, + /run/mysqld/mysqld.pid w, + /run/mysqld/mysqld.sock w, profile /bin/dash flags=(complain) { diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt index ec4e0b91626..984b033e7aa 100644 --- a/unittest/mysys/CMakeLists.txt +++ b/unittest/mysys/CMakeLists.txt @@ -15,7 +15,7 @@ MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring byte_order - queues LINK_LIBRARIES mysys) + queues stacktrace LINK_LIBRARIES mysys) MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys) MY_ADD_TESTS(aes LINK_LIBRARIES mysys mysys_ssl) ADD_DEFINITIONS(${SSL_DEFINES}) diff --git a/unittest/mysys/stacktrace-t.c b/unittest/mysys/stacktrace-t.c new file mode 100644 index 00000000000..8fa0db15b36 --- /dev/null +++ b/unittest/mysys/stacktrace-t.c @@ -0,0 +1,67 @@ + +/* Copyright (c) 2020, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software 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 Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <my_sys.h> +#include <stdio.h> +#include <my_stacktrace.h> +#include <tap.h> + +char b_bss[10]; + +void test_my_safe_print_str() +{ + char b_stack[10]; + char *b_heap= strdup("LEGAL"); + memcpy(b_stack, "LEGAL", 6); + memcpy(b_bss, "LEGAL", 6); + +#ifndef __SANITIZE_ADDRESS__ + fprintf(stderr, "\n===== stack =====\n"); + my_safe_print_str(b_stack, 65535); + fprintf(stderr, "\n===== heap =====\n"); + my_safe_print_str(b_heap, 65535); + fprintf(stderr, "\n===== BSS =====\n"); + my_safe_print_str(b_bss, 65535); + fprintf(stderr, "\n===== data =====\n"); + my_safe_print_str("LEGAL", 65535); + fprintf(stderr, "\n===== Above is a junk, but it is expected. =====\n"); +#endif /*__SANITIZE_ADDRESS__*/ + fprintf(stderr, "\n===== Nornal length test =====\n"); + my_safe_print_str("LEGAL", 5); + fprintf(stderr, "\n===== NULL =====\n"); + my_safe_print_str(0, 5); +#ifndef __SANITIZE_ADDRESS__ + fprintf(stderr, "\n===== (const char*) 1 =====\n"); + my_safe_print_str((const char*)1, 5); +#endif /*__SANITIZE_ADDRESS__*/ + + free(b_heap); + + ok(1, "test_my_safe_print_str"); +} + + +int main(int argc __attribute__((unused)), char **argv) +{ + MY_INIT(argv[0]); + plan(1); + + test_my_safe_print_str(); + + my_end(0); + return exit_status(); +} diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 2138c9233ad..d11053fa1dd 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -123,7 +123,7 @@ ELSE() ENDIF() SET(CPACK_WIX_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/CPackWixConfig.cmake) -IF(NOT TARGET mysql_upgrade_wizard) +IF(NOT TARGET mariadb-upgrade-wizard) SET(EXTRA_WIX_PREPROCESSOR_FLAGS "-dHaveUpgradeWizard=0") ENDIF() IF(WITH_INNOBASE_STORAGE_ENGINE) diff --git a/win/upgrade_wizard/CMakeLists.txt b/win/upgrade_wizard/CMakeLists.txt index 5a98ab15d0f..20a06a41215 100644 --- a/win/upgrade_wizard/CMakeLists.txt +++ b/win/upgrade_wizard/CMakeLists.txt @@ -35,17 +35,12 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) MYSQL_ADD_EXECUTABLE(mariadb-upgrade-wizard upgrade.cpp upgradeDlg.cpp upgrade.rc ${UPGRADE_WIZARD_SOURCES} COMPONENT Server) + + TARGET_LINK_LIBRARIES(mariadb-upgrade-wizard ${UPGRADE_WIZARD_LINK_LIBRARIES}) # upgrade_wizard is Windows executable, set WIN32_EXECUTABLE so it does not # create a console. -SET_TARGET_PROPERTIES(mariadb-upgrade-wizard PROPERTIES WIN32_EXECUTABLE 1) - -# Embed Vista "admin" manifest, since upgrade_wizard needs admin privileges -# to change service configuration. Due to a CMake bug http://www.vtk.org/Bug/view.php?id=11171 -# it is not possible currenly to do it with linker flags. Work around is to use -# manifest tool mt.exe and embed the manifest post-build. -ADD_CUSTOM_COMMAND( - TARGET mariadb-upgrade-wizard POST_BUILD - COMMAND mt.exe -manifest ${CMAKE_CURRENT_SOURCE_DIR}/upgrade_wizard.exe.manifest - "-outputresource:$<TARGET_FILE:mariadb-upgrade-wizard>;#1" +SET_TARGET_PROPERTIES(mariadb-upgrade-wizard PROPERTIES + WIN32_EXECUTABLE 1 + LINK_FLAGS "/MANIFESTUAC:level='requireAdministrator'" ) |