diff options
141 files changed, 3167 insertions, 949 deletions
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index d128416d966..0d4d0ffb445 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -108,6 +108,7 @@ ELSEIF(DEB) SET(WITH_PCRE system CACHE STRING "") ELSE() SET(WITH_SSL bundled CACHE STRING "") + SET(WITH_PCRE bundled CACHE STRING "") SET(WITH_ZLIB bundled CACHE STRING "") SET(WITH_JEMALLOC static CACHE STRING "") SET(PLUGIN_AUTH_SOCKET STATIC CACHE STRING "") @@ -145,7 +146,7 @@ IF(UNIX) RedHat/Fedora/Oracle Linux: yum install libaio-devel SuSE: zypper install libaio-devel - If you really do not want it, pass -DIGNORE_AIO_CHECK to cmake. + If you really do not want it, pass -DIGNORE_AIO_CHECK=ON to cmake. ") ENDIF() diff --git a/cmake/cpack_source_ignore_files.cmake b/cmake/cpack_source_ignore_files.cmake index 5b103501a99..eb1ec191d17 100644 --- a/cmake/cpack_source_ignore_files.cmake +++ b/cmake/cpack_source_ignore_files.cmake @@ -15,6 +15,7 @@ SET(CPACK_SOURCE_IGNORE_FILES \\\\.git/ +\\\\.git$ \\\\.gitignore$ \\\\.gitattributes$ CMakeCache\\\\.txt$ diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake index c8f7b3cc400..0eae3e1176b 100644 --- a/cmake/submodules.cmake +++ b/cmake/submodules.cmake @@ -19,11 +19,11 @@ IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git") SET(update_result 0) ELSEIF (cmake_update_submodules MATCHES force) MESSAGE(STATUS "Updating submodules (forced)") - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive --depth=1 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSEIF (cmake_update_submodules MATCHES yes) - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSE() diff --git a/extra/comp_err.c b/extra/comp_err.c index 52353ac9eea..6fe26c4e4be 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -788,6 +788,7 @@ static ha_checksum checksum_format_specifier(const char* msg) case 'x': case 's': case 'M': + case 'T': start= 0; /* Not in format specifier anymore */ break; } diff --git a/include/intrusive_list.h b/include/ilist.h index d745c6c6c62..46e15e9998a 100644 --- a/include/intrusive_list.h +++ b/include/ilist.h @@ -21,26 +21,28 @@ #include <cstddef> #include <iterator> -namespace intrusive -{ - // Derive your class from this struct to insert to a linked list. -template <class Tag= void> struct list_node +template <class Tag= void> struct ilist_node { - list_node(list_node *next= NULL, list_node *prev= NULL) - : next(next), prev(prev) + ilist_node() +#ifndef DBUG_OFF + : + next(NULL), prev(NULL) +#endif { } - list_node *next; - list_node *prev; + ilist_node(ilist_node *next, ilist_node *prev) : next(next), prev(prev) {} + + ilist_node *next; + ilist_node *prev; }; // Modelled after std::list<T> -template <class T, class Tag= void> class list +template <class T, class Tag= void> class ilist { public: - typedef list_node<Tag> ListNode; + typedef ilist_node<Tag> ListNode; class Iterator; // All containers in C++ should define these types to implement generic @@ -103,10 +105,10 @@ public: private: ListNode *node_; - friend class list; + friend class ilist; }; - list() : sentinel_(&sentinel_, &sentinel_), size_(0) {} + ilist() : sentinel_(&sentinel_, &sentinel_) {} reference front() { return *begin(); } reference back() { return *--end(); } @@ -129,14 +131,18 @@ public: reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return reverse_iterator(begin()); } - bool empty() const { return size_ == 0; } - size_type size() const { return size_; } + bool empty() const { return sentinel_.next == &sentinel_; } + + // Not implemented because it's O(N) + // size_type size() const + // { + // return static_cast<size_type>(std::distance(begin(), end())); + // } void clear() { sentinel_.next= &sentinel_; sentinel_.prev= &sentinel_; - size_= 0; } iterator insert(iterator pos, reference value) @@ -150,7 +156,6 @@ public: static_cast<ListNode &>(value).prev= prev; static_cast<ListNode &>(value).next= curr; - ++size_; return iterator(&value); } @@ -162,13 +167,12 @@ public: prev->next= next; next->prev= prev; - // This is not required for list functioning. But maybe it'll prevent bugs - // and ease debugging. +#ifndef DBUG_OFF ListNode *curr= pos.node_; curr->prev= NULL; curr->next= NULL; +#endif - --size_; return next; } @@ -179,12 +183,63 @@ public: void pop_front() { erase(begin()); } // STL version is O(n) but this is O(1) because an element can't be inserted - // several times in the same intrusive list. + // several times in the same ilist. void remove(reference value) { erase(iterator(&value)); } private: ListNode sentinel_; - size_type size_; }; -} // namespace intrusive +// Similar to ilist but also has O(1) size() method. +template <class T, class Tag= void> class sized_ilist : public ilist<T, Tag> +{ + typedef ilist<T, Tag> BASE; + +public: + // All containers in C++ should define these types to implement generic + // container interface. + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + typedef typename BASE::Iterator iterator; + typedef const typename BASE::Iterator const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const iterator> const_reverse_iterator; + + sized_ilist() : size_(0) {} + + size_type size() const { return size_; } + + void clear() + { + BASE::clear(); + size_= 0; + } + + iterator insert(iterator pos, reference value) + { + ++size_; + return BASE::insert(pos, value); + } + + iterator erase(iterator pos) + { + --size_; + return BASE::erase(pos); + } + + void push_back(reference value) { insert(BASE::end(), value); } + void pop_back() { erase(BASE::end()); } + + void push_front(reference value) { insert(BASE::begin(), value); } + void pop_front() { erase(BASE::begin()); } + + void remove(reference value) { erase(iterator(&value)); } + +private: + size_type size_; +}; diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h index bd1f069c527..6757a658fb6 100644 --- a/include/mysql/service_my_snprintf.h +++ b/include/mysql/service_my_snprintf.h @@ -55,7 +55,8 @@ Supported formats are 's' (null pointer is accepted, printed as "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', - 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below). + 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below), + 'T' (extension, see below). Standard syntax for positional arguments $n is supported. @@ -69,6 +70,9 @@ Format 'M': takes one integer, prints this integer, space, double quote error message, double quote. In other words printf("%M", n) === printf("%d \"%s\"", n, strerror(n)) + + Format 'T': takes string and print it like s but if the strints should be + truncated puts "..." at the end. */ #ifdef __cplusplus diff --git a/libmariadb b/libmariadb -Subproject cdfecebc9932a0dd5516c10505bfe78d79132e7 +Subproject ce74fd0c4009ed9f4bcbdb4a01e96c823e961dc diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 766f5e47e95..32250802815 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -37,8 +37,20 @@ use My::Platform; use POSIX qw[ _exit ]; use IO::Handle qw[ flush ]; use mtr_results; - use Term::ANSIColor; +use English; + +my $tot_real_time= 0; +my $tests_done= 0; +my $tests_failed= 0; + +our $timestamp= 0; +our $timediff= 0; +our $name; +our $verbose; +our $verbose_restart= 0; +our $timer= 1; +our $tests_total; my %color_map = qw/pass green retry-pass green @@ -47,20 +59,39 @@ my %color_map = qw/pass green disabled bright_black skipped yellow reset reset/; -sub xterm_color { - if (-t STDOUT and defined $ENV{TERM} and $ENV{TERM} =~ /xterm/) { - syswrite STDOUT, color($color_map{$_[0]}); + +my $set_titlebar; +my $set_color= sub { }; + +if (-t STDOUT) { + if (IS_WINDOWS) { + eval { + require Win32::Console; + $set_titlebar = sub { &Win32::Console::Title($_[0]);}; + } + } elsif ($ENV{TERM} =~ /xterm/) { + $set_titlebar = sub { syswrite STDOUT, "\e]0;$_[0]\a"; }; + $set_color = sub { syswrite STDOUT, color($color_map{$_[0]}); } } } -my $tot_real_time= 0; +sub titlebar_stat($) { -our $timestamp= 0; -our $timediff= 0; -our $name; -our $verbose; -our $verbose_restart= 0; -our $timer= 1; + sub time_format($) { + sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60; + } + + $tests_done++; + $tests_failed++ if $_[0] =~ /fail/; + $tests_total++ if $_[0] =~ /retry/; + + my $spent = time - $BASETIME; + my $left = $tests_total - $tests_done; + + &$set_titlebar(sprintf "mtr: spent %s on %d tests. %s (%d tests) left, %d failed", + time_format($spent), $tests_done, + time_format($spent/$tests_done * $left), $left, $tests_failed); +} sub report_option { my ($opt, $value)= @_; @@ -321,8 +352,6 @@ sub mtr_report_stats ($$$$) { if ( $timer ) { - use English; - mtr_report("Spent", sprintf("%.3f", $tot_real_time),"of", time - $BASETIME, "seconds executing testcases"); } @@ -620,10 +649,11 @@ sub mtr_report (@) { my @s = split /\[ (\S+) \]/, _name() . "@_\n"; if (@s > 1) { print $s[0]; - xterm_color($s[1]); + &$set_color($s[1]); print "[ $s[1] ]"; - xterm_color('reset'); + &$set_color('reset'); print $s[2]; + titlebar_stat($s[1]) if $set_titlebar; } else { print $s[0]; } diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index 5999f2c43c3..6572e5c9238 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -2598,6 +2598,11 @@ alter table person_principal add column if not exists date_mask tinyint null; update person_principal set date_mask = 0; alter table person_principal modify column date_mask tinyint not null; drop tables person_principal_hist, person_principal; +CREATE OR REPLACE TABLE `t1` ( `id` varchar(64) NOT NULL, `name` varchar(255) NOT NULL, `extra` text DEFAULT NULL, `password` varchar(128) DEFAULT NULL, `enabled` tinyint(1) DEFAULT NULL, `domain_id` varchar(64) NOT NULL, `default_project_id` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT `CONSTRAINT_1` CHECK (`enabled` in (0,1)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into t1 (id,name,enabled,domain_id) values (1,"Monty",1,"domain_id"); +insert into t1 (id,name,enabled,domain_id) values (2,"Monty2",1,"domain_id2"); +ALTER TABLE t1 ADD CONSTRAINT ixu_user2_name_domain_id UNIQUE (domain_id, name); +DROP TABLE t1; # # End of 10.4 tests # @@ -3306,3 +3311,6 @@ t2 CREATE TABLE `t2` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index 8b794fcfc3e..2cf3639ae59 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2111,6 +2111,16 @@ update person_principal set date_mask = 0; alter table person_principal modify column date_mask tinyint not null; drop tables person_principal_hist, person_principal; +# +# The following ALTER TABLE caused crash in 10.4.13 (Reported on freenode) +# + +CREATE OR REPLACE TABLE `t1` ( `id` varchar(64) NOT NULL, `name` varchar(255) NOT NULL, `extra` text DEFAULT NULL, `password` varchar(128) DEFAULT NULL, `enabled` tinyint(1) DEFAULT NULL, `domain_id` varchar(64) NOT NULL, `default_project_id` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT `CONSTRAINT_1` CHECK (`enabled` in (0,1)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into t1 (id,name,enabled,domain_id) values (1,"Monty",1,"domain_id"); +insert into t1 (id,name,enabled,domain_id) values (2,"Monty2",1,"domain_id2"); +ALTER TABLE t1 ADD CONSTRAINT ixu_user2_name_domain_id UNIQUE (domain_id, name); +DROP TABLE t1; + --echo # --echo # End of 10.4 tests --echo # @@ -2506,3 +2516,7 @@ alter table if exists t9 rename t1; alter table if exists t1 rename t2; show create table t2; drop table t2; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/comment_table.result b/mysql-test/main/comment_table.result index 99ecb04a362..d0af71b4540 100644 --- a/mysql-test/main/comment_table.result +++ b/mysql-test/main/comment_table.result @@ -1,4 +1,3 @@ -DROP TABLE IF EXISTS t1; create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INTEGER COMMENT '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, INDEX i1 (c1) COMMENT 'i1 comment',INDEX i2(c2) ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcd'; SELECT table_comment,char_length(table_comment) FROM information_schema.tables WHERE table_name='t1'; @@ -125,3 +124,7 @@ SELECT table_comment,char_length(table_comment) FROM information_schema.tables W table_comment char_length(table_comment) SELECT column_comment,char_length(column_comment) FROM information_schema.columns WHERE table_name='t1'; column_comment char_length(column_comment) +set names utf8; +create table t1 (x int comment 'a'); +ERROR HY000: Invalid utf8 character string: 'a' +set names latin1; diff --git a/mysql-test/main/comment_table.test b/mysql-test/main/comment_table.test index 6ab9f23b377..ba1ab9dda33 100644 --- a/mysql-test/main/comment_table.test +++ b/mysql-test/main/comment_table.test @@ -1,6 +1,3 @@ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings #1024 bytes create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INTEGER COMMENT '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, INDEX i1 (c1) COMMENT 'i1 comment',INDEX i2(c2) ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcd'; @@ -53,3 +50,11 @@ create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INT ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcde'; SELECT table_comment,char_length(table_comment) FROM information_schema.tables WHERE table_name='t1'; SELECT column_comment,char_length(column_comment) FROM information_schema.columns WHERE table_name='t1'; + +# +# MDEV-22558 wrong error for invalid utf8 table comment +# +set names utf8; +--error ER_INVALID_CHARACTER_STRING +create table t1 (x int comment 'a'); +set names latin1; diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result index 77157a4da0a..c0bbb8ff4ff 100644 --- a/mysql-test/main/ctype_binary.result +++ b/mysql-test/main/ctype_binary.result @@ -1,7 +1,4 @@ set names binary; -# -# Start of 5.5 tests -# SET TIME_ZONE = _latin1 '+03:00'; # # Start of WL#2649 Number-to-string conversions @@ -2925,9 +2922,6 @@ SET sql_mode=default; # # End of 5.5 tests # -# -# Start of 10.0 tests -# SET NAMES binary; # # MDEV-7149 Constant condition propagation erroneously applied for LIKE @@ -3075,9 +3069,6 @@ SET optimizer_switch=@save_optimizer_switch; # End of 10.0 tests # # -# Start of 10.1 tests -# -# # MDEV-8695 Wrong result for SELECT..WHERE varchar_column='a' AND CRC32(varchar_column)=3904355907 # CREATE TABLE t1 (a VARBINARY(10)); @@ -3172,9 +3163,148 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' and weight_string(`test`.`t1`.`a`,0,0,1) = 'a' DROP TABLE t1; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# +CREATE TABLE t1(a ENUM(0x6100,0x6200,0x6300) CHARACTER SET 'Binary'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0','b\0','c\0') CHARACTER SET binary DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1),(2),(3); +SELECT HEX(a) FROM t1 ORDER BY a; +HEX(a) +6100 +6200 +6300 +DROP TABLE t1; +0x00 in the middle or in the end of a value +CREATE TABLE t1 (a ENUM(0x6100)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +HEX(a) +6100 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM(0x610062)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0b') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +HEX(a) +610062 +DROP TABLE t1; +0x00 in the beginning of the first value: +CREATE TABLE t1 (a ENUM(0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(1); +SELECT HEX(a) FROM t1; +HEX(a) +0061 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM(0x0061), b ENUM('b')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('\0a') DEFAULT NULL, + `b` enum('b') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +SELECT HEX(a), HEX(b) FROM t1; +HEX(a) HEX(b) +0061 62 +DROP TABLE t1; +# 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table: +CREATE TABLE t1 (a ENUM('a',0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a','\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1),(2); +SELECT HEX(a) FROM t1 ORDER BY a; +HEX(a) +61 +0061 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM('a'), b ENUM('b',0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a') DEFAULT NULL, + `b` enum('b','\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +INSERT INTO t1 VALUES (1,2); +SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b; +HEX(a) HEX(b) +61 62 +61 0061 +DROP TABLE t1; +0x00 in the beginning of a value of a non-last ENUM/SET causes an error: +CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b')); +ERROR HY000: Incorrect information in file: 'DIR/t1.frm' +# # End of 10.1 tests # # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES latin1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary', d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061 +DROP TABLE t1; +CREATE TABLE t1( +c ENUM(0x0061) CHARACTER SET 'Binary', +d INT DEFAULT NULL CHECK (d>0) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL, + `d` int(11) DEFAULT NULL CHECK (`d` > 0) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +SELECT HEX(c), d FROM t1; +HEX(c) d +0061 1 +DROP TABLE t1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary' CHECK (c>0)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL CHECK (`c` > 0) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061 +DROP TABLE t1; +# +# End of 10.2 tests +# +# # Start of 10.5 tests # # diff --git a/mysql-test/main/ctype_binary.test b/mysql-test/main/ctype_binary.test index a466329a48a..3cf184576b4 100644 --- a/mysql-test/main/ctype_binary.test +++ b/mysql-test/main/ctype_binary.test @@ -1,10 +1,6 @@ set names binary; ---echo # ---echo # Start of 5.5 tests ---echo # - --source include/ctype_numconv.inc --echo # @@ -12,10 +8,6 @@ set names binary; --echo # ---echo # ---echo # Start of 10.0 tests ---echo # - SET NAMES binary; --source include/ctype_like_cond_propagation.inc @@ -32,10 +24,6 @@ SET NAMES utf8, character_set_connection=binary; --echo # --echo # ---echo # Start of 10.1 tests ---echo # - ---echo # --echo # MDEV-8695 Wrong result for SELECT..WHERE varchar_column='a' AND CRC32(varchar_column)=3904355907 --echo # CREATE TABLE t1 (a VARBINARY(10)); @@ -74,11 +62,102 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE COERCIBILITY(a)=2 AND a='a'; EXPLAIN EXTENDED SELECT * FROM t1 WHERE WEIGHT_STRING(a)='a' AND a='a'; DROP TABLE t1; + +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # + +CREATE TABLE t1(a ENUM(0x6100,0x6200,0x6300) CHARACTER SET 'Binary'); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1),(2),(3); +SELECT HEX(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +--echo 0x00 in the middle or in the end of a value + +CREATE TABLE t1 (a ENUM(0x6100)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM(0x610062)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +--echo 0x00 in the beginning of the first value: + +CREATE TABLE t1 (a ENUM(0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM(0x0061), b ENUM('b')); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +SELECT HEX(a), HEX(b) FROM t1; +DROP TABLE t1; + +--echo # 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table: + +CREATE TABLE t1 (a ENUM('a',0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1),(2); +SELECT HEX(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM('a'), b ENUM('b',0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +INSERT INTO t1 VALUES (1,2); +SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b; +DROP TABLE t1; + +--echo 0x00 in the beginning of a value of a non-last ENUM/SET causes an error: +--replace_regex /'.*t1.frm'/'DIR\/t1.frm'/ +--error ER_NOT_FORM_FILE +CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b')); + + --echo # --echo # End of 10.1 tests --echo # --echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES latin1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary', d JSON); +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1( + c ENUM(0x0061) CHARACTER SET 'Binary', + d INT DEFAULT NULL CHECK (d>0) +); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +SELECT HEX(c), d FROM t1; +DROP TABLE t1; + +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary' CHECK (c>0)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.2 tests +--echo # + +--echo # --echo # Start of 10.5 tests --echo # @@ -104,4 +183,3 @@ DROP TABLE t1; --echo # --echo # End of 10.5 tests --echo # - diff --git a/mysql-test/main/ctype_utf16_uca.result b/mysql-test/main/ctype_utf16_uca.result index 1b5224e2179..d1dbd498064 100644 --- a/mysql-test/main/ctype_utf16_uca.result +++ b/mysql-test/main/ctype_utf16_uca.result @@ -7899,5 +7899,46 @@ a b DROP TABLE t1; SET NAMES utf8; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES utf8, COLLATION_CONNECTION=utf16_hungarian_ci; +CREATE TABLE t1(c ENUM('aaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +00610061006100610061006100610061 +DROP TABLE t1; +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +006100610061006100610061006100610061 +DROP TABLE t1; +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061006100610061006100610061006100610061 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/main/ctype_utf16_uca.test b/mysql-test/main/ctype_utf16_uca.test index 3b54e0deead..cb00ccc0c61 100644 --- a/mysql-test/main/ctype_utf16_uca.test +++ b/mysql-test/main/ctype_utf16_uca.test @@ -244,5 +244,30 @@ SET NAMES utf8; --echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES utf8, COLLATION_CONNECTION=utf16_hungarian_ci; +CREATE TABLE t1(c ENUM('aaaaaaaa') CHARACTER SET 'Binary',d JSON); # ERROR 1064 (42000): You have an error in your SQL syntax +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaa') CHARACTER SET 'Binary',d JSON); # ERROR 1033 (HY000): Incorrect information in file: './test/t.frm' +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaaa') CHARACTER SET 'Binary',d JSON); # Sig 11 +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + + +--echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index f98eedc2464..ee899e515dc 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -2868,5 +2868,25 @@ DROP TABLE t1; # SET DEFAULT_STORAGE_ENGINE=Default; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES utf8, COLLATION_CONNECTION=utf32_bin; +CREATE TABLE t1(c1 ENUM('a','b','ac') CHARACTER SET 'Binary',c2 JSON,c3 INT); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` enum('\0\0\0a','\0\0\0b','\0\0\0a\0\0\0c') CHARACTER SET binary DEFAULT NULL, + `c2` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)), + `c3` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c1) VALUES (1),(2),(3); +SELECT HEX(c1) FROM t1 ORDER BY c1; +HEX(c1) +00000061 +00000062 +0000006100000063 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test index 902647ec522..9464cf118aa 100644 --- a/mysql-test/main/ctype_utf32.test +++ b/mysql-test/main/ctype_utf32.test @@ -1035,6 +1035,19 @@ let $coll='utf32_nopad_bin'; let $coll_pad='utf32_bin'; --source include/ctype_pad_all_engines.inc + +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES utf8, COLLATION_CONNECTION=utf32_bin; +CREATE TABLE t1(c1 ENUM('a','b','ac') CHARACTER SET 'Binary',c2 JSON,c3 INT); +SHOW CREATE TABLE t1; +INSERT INTO t1 (c1) VALUES (1),(2),(3); +SELECT HEX(c1) FROM t1 ORDER BY c1; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/frm-debug.result b/mysql-test/main/frm-debug.result index caf344e241d..332d7e00a8f 100644 --- a/mysql-test/main/frm-debug.result +++ b/mysql-test/main/frm-debug.result @@ -13,8 +13,8 @@ CREATE TABLE t1 (c01 INT, c02 CHAR(20), c03 TEXT, c04 DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 14 Note 1105 DBUG: [0] name='c01' type_info='' -Note 1105 DBUG: [1] name='c02' type_info='xc...' -Note 1105 DBUG: [2] name='c03' type_info='xb...' +Note 1105 DBUG: [1] name='c02' type_info='xchar' +Note 1105 DBUG: [2] name='c03' type_info='xblob' Note 1105 DBUG: [3] name='c04' type_info='' SET SESSION debug_dbug="-d,frm_data_type_info_emulate"; SET SESSION debug_dbug="-d,frm_data_type_info"; diff --git a/mysql-test/main/lock.result b/mysql-test/main/lock.result index 6edb86bfa3f..e76c04520eb 100644 --- a/mysql-test/main/lock.result +++ b/mysql-test/main/lock.result @@ -506,3 +506,17 @@ disconnect con1; connection default; UNLOCK TABLES; DROP TABLE t1, t2; +# +# MDEV-21398 Deadlock (server hang) or assertion failure in +# Diagnostics_area::set_error_status upon ALTER under lock +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +LOCK TABLE t1 WRITE, t1 AS t1a READ; +ALTER TABLE t1 CHANGE COLUMN IF EXISTS x xx INT; +Warnings: +Note 1054 Unknown column 'x' in 't1' +UNLOCK TABLES; +DROP TABLE t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/main/lock.test b/mysql-test/main/lock.test index 8a59f4082b1..32e4fd47664 100644 --- a/mysql-test/main/lock.test +++ b/mysql-test/main/lock.test @@ -619,3 +619,17 @@ UNLOCK TABLES; UNLOCK TABLES; DROP TABLE t1, t2; +--echo # +--echo # MDEV-21398 Deadlock (server hang) or assertion failure in +--echo # Diagnostics_area::set_error_status upon ALTER under lock +--echo # + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +LOCK TABLE t1 WRITE, t1 AS t1a READ; +ALTER TABLE t1 CHANGE COLUMN IF EXISTS x xx INT; +UNLOCK TABLES; +DROP TABLE t1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index bacf205d72c..3b7d95f80e9 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -3759,7 +3759,7 @@ DROP TABLE t1; # CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); -mysqldump: Input filename too long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... +mysqldump: Input filename too long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DROP TABLE t1; CREATE TABLE t2 (a INT) ENGINE=MyISAM; CREATE TABLE t3 (a INT) ENGINE=MyISAM; diff --git a/mysql-test/main/partition_alter.result b/mysql-test/main/partition_alter.result index d946f2b8822..997a5cf97fa 100644 --- a/mysql-test/main/partition_alter.result +++ b/mysql-test/main/partition_alter.result @@ -122,7 +122,55 @@ t1 CREATE TABLE `t1` ( PARTITION `p02` ENGINE = MyISAM, PARTITION `p03` ENGINE = MyISAM) drop table t1; -create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +# +# MDEV-19751 Wrong partitioning by KEY() after key dropped +# +create or replace table t1 (pk int, x timestamp(6), primary key (pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP PRIMARY KEY when partitioned by default field list is denied +alter table t1 drop primary key, drop column x, add primary key (pk), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +alter table t1 drop primary key, drop column x, add primary key (pk); +select * from t1 partition (p0); +pk +1 +drop table t1; +create or replace table t1 (pk int not null, x timestamp(6), unique u(pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Same for NOT NULL UNIQUE KEY as this is actually primary key +alter table t1 drop key u, drop column x, add unique (pk), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +alter table t1 drop key u, drop column x, add unique (pk); +select * from t1 partition (p0); +pk +1 +drop table t1; +create or replace table t1 (pk int, x timestamp(6), primary key (pk)) engine innodb +partition by key(pk) partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP PRIMARY KEY when partitioned by explicit field list is allowed +alter table t1 drop primary key, add primary key (pk, x), algorithm=inplace; +select * from t1 partition (p0); +pk x +1 2000-01-01 00:00:00.000000 +drop table t1; +create or replace table t1 (k int, x timestamp(6), unique key u (x, k)) engine innodb +partition by key(k) partitions 2; +insert into t1 (k, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP KEY is allowed +alter table t1 drop key u, algorithm=inplace; +select * from t1 partition (p0); +k x +1 2000-01-01 00:00:00.000000 +drop table t1; +# End of 10.2 tests +# +# MDEV-14817 Server crashes in prep_alter_part_table() +# after table lock and multiple add partition +# +create table t1 (x int) partition by hash (x) (partition p1, partition p2); lock table t1 write; alter table t1 add partition (partition p1); ERROR HY000: Duplicate partition name p1 @@ -134,7 +182,7 @@ drop table t1; # ha_partition::update_row or `part_id == m_last_part' in # ha_partition::delete_row upon UPDATE/DELETE after dropping versioning # -create or replace table t1 (pk int, f int, primary key(pk, f)) engine=innodb +create table t1 (pk int, f int, primary key(pk, f)) engine=innodb partition by key() partitions 2; insert into t1 values (1,10),(2,11); # expected to hit same partition @@ -152,3 +200,4 @@ pk 2 delete from t1; drop table t1; +# End of 10.3 tests diff --git a/mysql-test/main/partition_alter.test b/mysql-test/main/partition_alter.test index 779f12574d5..cca25d0989f 100644 --- a/mysql-test/main/partition_alter.test +++ b/mysql-test/main/partition_alter.test @@ -120,10 +120,52 @@ alter online table t1 delay_key_write=1; show create table t1; drop table t1; -# -# MDEV-14817 Server crashes in prep_alter_part_table() after table lock and multiple add partition -# -create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +--echo # +--echo # MDEV-19751 Wrong partitioning by KEY() after key dropped +--echo # +create or replace table t1 (pk int, x timestamp(6), primary key (pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP PRIMARY KEY when partitioned by default field list is denied +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 drop primary key, drop column x, add primary key (pk), algorithm=inplace; +alter table t1 drop primary key, drop column x, add primary key (pk); +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (pk int not null, x timestamp(6), unique u(pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Same for NOT NULL UNIQUE KEY as this is actually primary key +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 drop key u, drop column x, add unique (pk), algorithm=inplace; +alter table t1 drop key u, drop column x, add unique (pk); +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (pk int, x timestamp(6), primary key (pk)) engine innodb +partition by key(pk) partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP PRIMARY KEY when partitioned by explicit field list is allowed +alter table t1 drop primary key, add primary key (pk, x), algorithm=inplace; +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (k int, x timestamp(6), unique key u (x, k)) engine innodb +partition by key(k) partitions 2; +insert into t1 (k, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP KEY is allowed +alter table t1 drop key u, algorithm=inplace; +select * from t1 partition (p0); +drop table t1; + +--echo # End of 10.2 tests + +--echo # +--echo # MDEV-14817 Server crashes in prep_alter_part_table() +--echo # after table lock and multiple add partition +--echo # +create table t1 (x int) partition by hash (x) (partition p1, partition p2); lock table t1 write; --error ER_SAME_NAME_PARTITION alter table t1 add partition (partition p1); @@ -136,7 +178,7 @@ drop table t1; --echo # ha_partition::update_row or `part_id == m_last_part' in --echo # ha_partition::delete_row upon UPDATE/DELETE after dropping versioning --echo # -create or replace table t1 (pk int, f int, primary key(pk, f)) engine=innodb +create table t1 (pk int, f int, primary key(pk, f)) engine=innodb partition by key() partitions 2; insert into t1 values (1,10),(2,11); @@ -149,3 +191,5 @@ select * from t1 partition(p0); select * from t1 partition(p1); delete from t1; drop table t1; + +--echo # End of 10.3 tests diff --git a/mysql-test/main/perror-win.result b/mysql-test/main/perror-win.result index 03d43abdb97..a0ea54f9187 100644 --- a/mysql-test/main/perror-win.result +++ b/mysql-test/main/perror-win.result @@ -2,6 +2,6 @@ MariaDB error code 150: Foreign key constraint is incorrectly formed Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system Win32 error code 23: Data error (cyclic redundancy check). -MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192T' for key %d Win32 error code 1062: The service has not been started. Illegal error code: 30000 diff --git a/mysql-test/main/perror.result b/mysql-test/main/perror.result index ad2106524e5..b95b8b8dd99 100644 --- a/mysql-test/main/perror.result +++ b/mysql-test/main/perror.result @@ -1,5 +1,5 @@ Illegal error code: 10000 -MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192T' for key %d MariaDB error code 1408 (ER_STARTUP): %s: ready for connections. Version: '%s' socket: '%s' port: %d %s MariaDB error code 1459 (ER_TABLE_NEEDS_UPGRADE): Upgrade required. Please do "REPAIR %s %`s" or dump/reload to fix it! diff --git a/mysql-test/main/processlist_notembedded.result b/mysql-test/main/processlist_notembedded.result index e663c407a1b..b622fdf32b9 100644 --- a/mysql-test/main/processlist_notembedded.result +++ b/mysql-test/main/processlist_notembedded.result @@ -8,6 +8,9 @@ connection default; SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; FOUND 1 /sleep/ in MDEV-20466.text SET DEBUG_SYNC= 'now SIGNAL go'; +connection con1; +User disconnect con1; +connection default; SET DEBUG_SYNC = 'RESET'; End of 5.5 tests diff --git a/mysql-test/main/processlist_notembedded.test b/mysql-test/main/processlist_notembedded.test index 4979e40a85a..6f269a816fc 100644 --- a/mysql-test/main/processlist_notembedded.test +++ b/mysql-test/main/processlist_notembedded.test @@ -30,7 +30,10 @@ remove_file $MYSQLTEST_VARDIR/tmp/MDEV-20466.text; SET DEBUG_SYNC= 'now SIGNAL go'; +connection con1; +reap; disconnect con1; +connection default; SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/main/repair.result b/mysql-test/main/repair.result index 84773449e92..899ca1e1a32 100644 --- a/mysql-test/main/repair.result +++ b/mysql-test/main/repair.result @@ -233,3 +233,24 @@ i UNLOCK TABLES; DROP TABLE t1; # End of 10.0 tests +create table t1 (a int, b varchar(200)); +insert t1 select seq, repeat(200, seq) from seq_1_to_30; +delete from t1 where a % 13 = 0; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 28 +test.t1 repair status OK +delete from t1 where a % 11 = 0; +repair table t1 extended use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 26 +test.t1 repair status OK +delete from t1 where a % 7 = 0; +set myisam_repair_threads = 2; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 22 +test.t1 repair status OK +set myisam_repair_threads = default; +drop table t1; +# End of 10.2 tests diff --git a/mysql-test/main/repair.test b/mysql-test/main/repair.test index 75978ac482b..435eb99683a 100644 --- a/mysql-test/main/repair.test +++ b/mysql-test/main/repair.test @@ -1,6 +1,7 @@ # # Test of repair table # +--source include/have_sequence.inc --source include/default_charset.inc call mtr.add_suppression("character set is multi-byte"); @@ -246,3 +247,23 @@ UNLOCK TABLES; DROP TABLE t1; --echo # End of 10.0 tests + +# +# MDEV-17153 server crash on repair table ... use_frm +# +# Note, this test case doesn't crash, but shows spurios warnings +# unless the bug is fixed +# +create table t1 (a int, b varchar(200)); +insert t1 select seq, repeat(200, seq) from seq_1_to_30; +delete from t1 where a % 13 = 0; +repair table t1 use_frm; +delete from t1 where a % 11 = 0; +repair table t1 extended use_frm; +delete from t1 where a % 7 = 0; +set myisam_repair_threads = 2; +repair table t1 use_frm; +set myisam_repair_threads = default; +drop table t1; + +--echo # End of 10.2 tests diff --git a/mysql-test/main/selectivity.result b/mysql-test/main/selectivity.result index f84d2eae05a..591294aff10 100644 --- a/mysql-test/main/selectivity.result +++ b/mysql-test/main/selectivity.result @@ -1866,5 +1866,20 @@ id select_type table type possible_keys key key_len ref rows Extra set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +# +# MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * from t1 WHERE a = 5 and b = 5; +a b +5 5 +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; # End of 10.1 tests set @@global.histogram_size=@save_histogram_size; diff --git a/mysql-test/main/selectivity.test b/mysql-test/main/selectivity.test index d0158fb717e..2a0cc823eb4 100644 --- a/mysql-test/main/selectivity.test +++ b/mysql-test/main/selectivity.test @@ -1267,6 +1267,18 @@ set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +--echo # +--echo # MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT * from t1 WHERE a = 5 and b = 5; +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; + --echo # End of 10.1 tests # diff --git a/mysql-test/main/selectivity_innodb.result b/mysql-test/main/selectivity_innodb.result index 0d9a55a0bdb..7a8f837d4e2 100644 --- a/mysql-test/main/selectivity_innodb.result +++ b/mysql-test/main/selectivity_innodb.result @@ -1876,6 +1876,21 @@ id select_type table type possible_keys key key_len ref rows Extra set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +# +# MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * from t1 WHERE a = 5 and b = 5; +a b +5 5 +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; # End of 10.1 tests set @@global.histogram_size=@save_histogram_size; set optimizer_switch=@save_optimizer_switch_for_selectivity_test; diff --git a/mysql-test/main/type_datetime_hires.result b/mysql-test/main/type_datetime_hires.result index ebb9c6032b9..5211515ea77 100644 --- a/mysql-test/main/type_datetime_hires.result +++ b/mysql-test/main/type_datetime_hires.result @@ -889,5 +889,16 @@ Warning 1411 Incorrect date value: '0000-02-28' for function round(datetime) Warning 1411 Incorrect date value: '0000-12-31' for function round(datetime) DROP TABLE t1; # +# MDEV-20984 Possibly wrong result or Assertion `args[0]->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATETIME' failed in Item_func_round::date_op +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1979-01-03 10:33:32'),('2012-12-12 12:12:12'); +SELECT ROUND(a) AS f FROM t1 GROUP BY a WITH ROLLUP; +f +1979-01-03 10:33:32 +2012-12-12 12:12:12 +NULL +DROP TABLE t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_datetime_hires.test b/mysql-test/main/type_datetime_hires.test index ed9a85bcda3..7b3b37560a3 100644 --- a/mysql-test/main/type_datetime_hires.test +++ b/mysql-test/main/type_datetime_hires.test @@ -147,5 +147,15 @@ SELECT a, ROUND(a,-6) FROM t1; DROP TABLE t1; --echo # +--echo # MDEV-20984 Possibly wrong result or Assertion `args[0]->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATETIME' failed in Item_func_round::date_op +--echo # + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1979-01-03 10:33:32'),('2012-12-12 12:12:12'); +SELECT ROUND(a) AS f FROM t1 GROUP BY a WITH ROLLUP; +DROP TABLE t1; + + +--echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index fd0efd917e6..8324a065b93 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -3723,6 +3723,25 @@ MAX(1) OVER () COUNT(a) abs(a) 1 0 NULL drop table t1; # +# MDEV-22461: JOIN::make_aggr_tables_info(): Assertion `select_options & (1ULL << 17)' failed. +# +CREATE TEMPORARY TABLE t0 (a INT PRIMARY KEY ) ; +INSERT INTO t0 VALUES (1),(2),(3); +SELECT a FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); +a +1 +SELECT a, ROW_NUMBER() OVER v2 +FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); +a ROW_NUMBER() OVER v2 +1 1 +drop table t0; +# # End of 10.2 tests # # diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 89a018ea374..272404e712d 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2426,6 +2426,26 @@ SELECT MAX(1) OVER (), COUNT(a), abs(a) FROM t1 WHERE FALSE; drop table t1; --echo # +--echo # MDEV-22461: JOIN::make_aggr_tables_info(): Assertion `select_options & (1ULL << 17)' failed. +--echo # + +CREATE TEMPORARY TABLE t0 (a INT PRIMARY KEY ) ; +INSERT INTO t0 VALUES (1),(2),(3); + +SELECT a FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); + +SELECT a, ROW_NUMBER() OVER v2 +FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); + +drop table t0; + +--echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/xa.result b/mysql-test/main/xa.result index e2a103a7a77..2fe8316b65b 100644 --- a/mysql-test/main/xa.result +++ b/mysql-test/main/xa.result @@ -403,6 +403,22 @@ XA ROLLBACK 'xid1'; # XA START 'gtrid', 'bqual', 0x80000000; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '0x80000000' at line 1 +XA BEGIN 'xid'; +CREATE TEMPORARY SEQUENCE s; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state +XA END 'xid'; +XA ROLLBACK 'xid'; +XA BEGIN 'xid'; +CREATE SEQUENCE s; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state +XA END 'xid'; +XA ROLLBACK 'xid'; +# +# End of 10.3 tests +# +# +# Start of 10.5 tests +# # MDEV-7974 related # Check XA state when lock_wait_timeout happens # More tests added to flush_read_lock.test @@ -461,3 +477,6 @@ formatID gtrid_length bqual_length data drop table asd; disconnect con_tmp; connection default; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/xa.test b/mysql-test/main/xa.test index 7aaa72b1645..07183feda76 100644 --- a/mysql-test/main/xa.test +++ b/mysql-test/main/xa.test @@ -544,6 +544,37 @@ XA START 'gtrid', 'bqual', 0x80000000; --source include/wait_until_count_sessions.inc +# +# MDEV-22002 Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' +# failed upon CREATE TEMPORARY SEQUENCE under XA +# + +XA BEGIN 'xid'; + +--error ER_XAER_RMFAIL +CREATE TEMPORARY SEQUENCE s; + +XA END 'xid'; + +XA ROLLBACK 'xid'; + +XA BEGIN 'xid'; + +--error ER_XAER_RMFAIL +CREATE SEQUENCE s; + +XA END 'xid'; + +XA ROLLBACK 'xid'; + +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + --echo # MDEV-7974 related --echo # Check XA state when lock_wait_timeout happens --echo # More tests added to flush_read_lock.test @@ -590,3 +621,7 @@ drop table asd; disconnect con_tmp; --source include/wait_until_disconnected.inc connection default; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 82fb3f1f136..ec13e011dae 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -377,32 +377,6 @@ my $opt_stop_keep_alive= $ENV{MTR_STOP_KEEP_ALIVE}; select(STDOUT); $| = 1; # Automatically flush STDOUT -my $set_titlebar; - - - BEGIN { - if (IS_WINDOWS) { - my $have_win32_console= 0; - eval { - require Win32::Console; - Win32::Console->import(); - $have_win32_console = 1; - }; - eval 'sub HAVE_WIN32_CONSOLE { $have_win32_console }'; - } else { - eval 'sub HAVE_WIN32_CONSOLE { 0 }'; - } -} - -if (-t STDOUT) { - if (IS_WINDOWS and HAVE_WIN32_CONSOLE) { - $set_titlebar = sub {Win32::Console::Title $_[0];}; - } elsif (defined $ENV{TERM} and $ENV{TERM} =~ /xterm/) { - $set_titlebar = sub { syswrite STDOUT, "\e];$_[0]\a"; }; - } -} - - main(); sub main { @@ -475,7 +449,7 @@ sub main { } ####################################################################### - my $num_tests= @$tests; + my $num_tests= $mtr_report::tests_total= @$tests; if ( $opt_parallel eq "auto" ) { # Try to find a suitable value for number of workers if (IS_WINDOWS) @@ -916,8 +890,6 @@ sub run_test_server ($$$) { delete $next->{reserved}; } - titlebar_stat(scalar(@$tests)) if $set_titlebar; - if ($next) { # We don't need this any more delete $next->{criteria}; @@ -6586,23 +6558,3 @@ sub list_options ($) { exit(1); } - -sub time_format($) { - sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60; -} - -our $num_tests; - -sub titlebar_stat { - my ($left) = @_; - - # 2.5 -> best by test - $num_tests = $left + 2.5 unless $num_tests; - - my $done = $num_tests - $left; - my $spent = time - $^T; - - &$set_titlebar(sprintf "mtr: spent %s on %d tests. %s (%d tests) left", - time_format($spent), $done, - time_format($spent/$done * $left), $left); -} diff --git a/mysql-test/suite/compat/oracle/r/exception.result b/mysql-test/suite/compat/oracle/r/exception.result index b61d25f36ee..3bd239808bc 100644 --- a/mysql-test/suite/compat/oracle/r/exception.result +++ b/mysql-test/suite/compat/oracle/r/exception.result @@ -106,7 +106,7 @@ RAISE dup_val_on_index; END; $$ CALL p1(); -ERROR 23000: Duplicate entry '%-.192s' for key %d +ERROR 23000: Duplicate entry '%-.192T' for key %d DROP PROCEDURE p1; CREATE PROCEDURE p1 AS diff --git a/mysql-test/suite/federated/federatedx_versioning.result b/mysql-test/suite/federated/federatedx_versioning.result index abf2658d2e2..be3b578e839 100644 --- a/mysql-test/suite/federated/federatedx_versioning.result +++ b/mysql-test/suite/federated/federatedx_versioning.result @@ -9,8 +9,8 @@ show create table tf; Table Create Table tf CREATE TABLE `tf` ( `x` int(11) DEFAULT NULL, - `row_start` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0, - `row_end` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0 + `row_start` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000', + `row_end` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000' ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:MASTER_MYPORT/test/t1' # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/federated/federatedx_versioning.test b/mysql-test/suite/federated/federatedx_versioning.test index e8db8ef9e2a..6c3247cea55 100644 --- a/mysql-test/suite/federated/federatedx_versioning.test +++ b/mysql-test/suite/federated/federatedx_versioning.test @@ -12,7 +12,7 @@ eval create or replace table t1 ( with system versioning; --replace_result $MASTER_MYPORT MASTER_MYPORT eval create or replace table tf engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1'; ---replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE "'0000-00-00 00:00:00.000000'" 0 +--replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE 19710101000000 "'1971-01-01 00:00:00.000000'" " NOT NULL" "" show create table tf; --echo # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/galera/r/galera_bf_kill.result b/mysql-test/suite/galera/r/galera_bf_kill.result index 8b620323e35..2a7bc9eac29 100644 --- a/mysql-test/suite/galera/r/galera_bf_kill.result +++ b/mysql-test/suite/galera/r/galera_bf_kill.result @@ -70,3 +70,20 @@ a b 2 1 disconnect node_2a; drop table t1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +CREATE TABLE t1 (i int primary key); +SET DEBUG_SYNC = "before_wsrep_ordered_commit SIGNAL bwoc_reached WAIT_FOR bwoc_continue"; +INSERT INTO t1 VALUES (1); +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR bwoc_reached"; +SET DEBUG_SYNC = "now SIGNAL bwoc_continue"; +SET DEBUG_SYNC='RESET'; +connection node_2a; +connection node_2; +select * from t1; +i +1 +disconnect node_2a; +connection node_2; +drop table t1; diff --git a/mysql-test/suite/galera/t/galera_bf_kill.test b/mysql-test/suite/galera/t/galera_bf_kill.test index 0748b732ead..3eb3ddc32b5 100644 --- a/mysql-test/suite/galera/t/galera_bf_kill.test +++ b/mysql-test/suite/galera/t/galera_bf_kill.test @@ -1,4 +1,7 @@ --source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc # # Test case 1: Start a transaction on node_2a and kill it @@ -140,4 +143,48 @@ select * from t1; drop table t1; +# +# Test case 7: +# run a transaction in node 2, and set a sync point to pause the transaction +# in commit phase. +# Through another connection to node 2, kill the committing transaction by +# KILL QUERY command +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +--let $connection_id = `SELECT CONNECTION_ID()` + +CREATE TABLE t1 (i int primary key); + +# Set up sync point +SET DEBUG_SYNC = "before_wsrep_ordered_commit SIGNAL bwoc_reached WAIT_FOR bwoc_continue"; + +# Send insert which will block in the sync point above +--send INSERT INTO t1 VALUES (1) + +--connection node_2 +SET DEBUG_SYNC = "now WAIT_FOR bwoc_reached"; + +--disable_query_log +--disable_result_log +# victim has passed the point of no return, kill is not possible anymore +--eval KILL QUERY $connection_id +--enable_result_log +--enable_query_log + +SET DEBUG_SYNC = "now SIGNAL bwoc_continue"; +SET DEBUG_SYNC='RESET'; +--connection node_2a +--error 0,1213 +--reap + +--connection node_2 +# victim was able to complete the INSERT +select * from t1; + +--disconnect node_2a + +--connection node_2 +drop table t1; diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.test b/mysql-test/suite/galera/t/galera_bf_lock_wait.test index a3903fd10c0..97d3b8e0710 100644 --- a/mysql-test/suite/galera/t/galera_bf_lock_wait.test +++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.test @@ -1,4 +1,5 @@ --source include/galera_cluster.inc +--source include/have_innodb.inc --source include/big_test.inc --connection node_1 diff --git a/mysql-test/suite/galera_sr/r/MDEV-22616.result b/mysql-test/suite/galera_sr/r/MDEV-22616.result new file mode 100644 index 00000000000..0c3847bd9b9 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MDEV-22616.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +START TRANSACTION; +INSERT INTO t1 VALUES (1); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/MDEV-22616.test b/mysql-test/suite/galera_sr/t/MDEV-22616.test new file mode 100644 index 00000000000..818d787703f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MDEV-22616.test @@ -0,0 +1,18 @@ +# +# MDEV-22616 +# +# CHECK TABLE fails with wsrep_trx_fragment_size > 0 +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +CHECK TABLE t1; + +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +CHECK TABLE t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/alter_crash.result b/mysql-test/suite/innodb/r/alter_crash.result index 322caa66b07..bf593c6acca 100644 --- a/mysql-test/suite/innodb/r/alter_crash.result +++ b/mysql-test/suite/innodb/r/alter_crash.result @@ -152,3 +152,41 @@ SELECT * FROM t1; a b d 1 NULL NULL DROP TABLE t1; +# +# MDEV-22637 Rollback of insert fails when column reorder happens +# +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_TRANS_TABLES', ''); +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_ALL_TABLES', ''); +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100), +f3 CHAR(100), f4 CHAR(100))ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, "This is column2", "This is column3", +"This is column4"); +set DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; +ALTER TABLE t1 ADD COLUMN f6 int after f3, add primary key(f6, f4(3), f3(3)); +connect con1,localhost,root,,; +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +BEGIN; +INSERT INTO t1(f1, f2) VALUES(2, "This is column2 value"); +ROLLBACK; +set DEBUG_SYNC = 'now SIGNAL insert_done'; +connection default; +Warnings: +Warning 1265 Data truncated for column 'f3' at row 3 +Warning 1265 Data truncated for column 'f4' at row 3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` char(100) DEFAULT NULL, + `f3` char(100) NOT NULL, + `f6` int(11) NOT NULL, + `f4` char(100) NOT NULL, + PRIMARY KEY (`f6`,`f4`(3),`f3`(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +disconnect con1; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; +SET SQL_MODE=DEFAULT; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff new file mode 100644 index 00000000000..57d87f7172f --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff @@ -0,0 +1,13 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,16k.reject 2020-05-26 20:14:38.452463919 +0530 +@@ -45,3 +45,10 @@ + instants + 502 + DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff index 5e46c66ce73..8f8cf64b7fc 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff @@ -1,9 +1,16 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result -@@ -42,5 +42,5 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,32k.reject 2020-05-26 19:59:19.743877366 +0530 +@@ -43,5 +43,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +506 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff index b40c6482d22..dad28218a02 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff @@ -1,5 +1,5 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,4k.reject 2020-05-26 20:17:53.314736548 +0530 @@ -5,6 +5,276 @@ ENGINE=InnoDB; INSERT INTO t VALUES(1,2,3,4,5); @@ -295,10 +295,19 @@ ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE SELECT variable_value-@old_instant instants -@@ -43,5 +319,5 @@ +@@ -43,5 +319,14 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +474 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++Warnings: ++Warning 139 Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline. ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff index 5e46c66ce73..d7479dbba40 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff @@ -1,9 +1,16 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result -@@ -42,5 +42,5 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,64k.reject 2020-05-26 20:00:22.499711222 +0530 +@@ -43,5 +43,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +506 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff index f7cb7238ae3..1fe3e1a56eb 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff @@ -1,5 +1,5 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,8k.reject 2020-05-26 20:19:50.881869095 +0530 @@ -5,6 +5,28 @@ ENGINE=InnoDB; INSERT INTO t VALUES(1,2,3,4,5); @@ -47,10 +47,17 @@ ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE SELECT variable_value-@old_instant instants -@@ -43,5 +71,5 @@ +@@ -43,5 +71,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +492 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/alter_crash.test b/mysql-test/suite/innodb/t/alter_crash.test index c7cd1bcfe66..72116b0ca9d 100644 --- a/mysql-test/suite/innodb/t/alter_crash.test +++ b/mysql-test/suite/innodb/t/alter_crash.test @@ -196,3 +196,30 @@ SHOW CREATE TABLE t1; UPDATE t1 SET d=NULL; SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-22637 Rollback of insert fails when column reorder happens +--echo # +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_TRANS_TABLES', ''); +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_ALL_TABLES', ''); +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100), + f3 CHAR(100), f4 CHAR(100))ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, "This is column2", "This is column3", + "This is column4"); +set DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; +--send ALTER TABLE t1 ADD COLUMN f6 int after f3, add primary key(f6, f4(3), f3(3)) +connect(con1,localhost,root,,); +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +BEGIN; +INSERT INTO t1(f1, f2) VALUES(2, "This is column2 value"); +ROLLBACK; +set DEBUG_SYNC = 'now SIGNAL insert_done'; + +connection default; +reap; +SHOW CREATE TABLE t1; +SELECT COUNT(*) FROM t1; +disconnect con1; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; +SET SQL_MODE=DEFAULT; diff --git a/mysql-test/suite/innodb/t/instant_alter_limit.test b/mysql-test/suite/innodb/t/instant_alter_limit.test index e84885f88e7..b7fb3ee55c1 100644 --- a/mysql-test/suite/innodb/t/instant_alter_limit.test +++ b/mysql-test/suite/innodb/t/instant_alter_limit.test @@ -60,3 +60,17 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; DROP TABLE t; + +--echo # +--echo # MDEV-21787 Alter table failure tries to access uninitialized column +--echo # +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; +ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); +let $error_code = 0; +let $innodb_page_size = `SELECT @@INNODB_PAGE_SIZE`; +if ($innodb_page_size == 4k) { + let $error_code= ER_TOO_BIG_ROWSIZE; +} +--error $error_code +ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; +DROP TABLE t1; diff --git a/mysql-test/suite/maria/bulk_insert_crash.opt b/mysql-test/suite/maria/bulk_insert_crash.opt new file mode 100644 index 00000000000..f85a8d9c973 --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.opt @@ -0,0 +1,2 @@ +--skip-stack-trace --skip-core-file +--default-storage-engine=Aria diff --git a/mysql-test/suite/maria/bulk_insert_crash.result b/mysql-test/suite/maria/bulk_insert_crash.result new file mode 100644 index 00000000000..fc28bf325ba --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.result @@ -0,0 +1,13 @@ +create table t1 (a int primary key, b int, c int, unique key(b), key(c)) engine=aria transactional=1; +insert into t1 values (1000,1000,1000); +insert into t1 select seq,seq+100, seq+200 from seq_1_to_10; +SET GLOBAL debug_dbug="+d,crash_end_bulk_insert"; +REPLACE into t1 select seq+20,seq+95, seq + 300 from seq_1_to_10; +ERROR HY000: Lost connection to MySQL server during query +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select sum(a),sum(b),sum(c) from t1; +sum(a) sum(b) sum(c) +1055 2055 3055 +drop table t1; diff --git a/mysql-test/suite/maria/bulk_insert_crash.test b/mysql-test/suite/maria/bulk_insert_crash.test new file mode 100644 index 00000000000..d9167c3f0d7 --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.test @@ -0,0 +1,36 @@ +--source include/not_embedded.inc +--source include/not_valgrind.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc +# Binary must be compiled with debug for crash to occur +--source include/have_debug.inc +--source include/have_sequence.inc + +# +# MDEV-20578 Got error 126 when executing undo undo_key_delete upon Aria crash +# recovery +# + +# Write file to make mysql-test-run.pl expect crash and restart +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +create table t1 (a int primary key, b int, c int, unique key(b), key(c)) engine=aria transactional=1; +insert into t1 values (1000,1000,1000); +insert into t1 select seq,seq+100, seq+200 from seq_1_to_10; + +# Insert into t1 with batch insert where we get a rows replaced after +# a few sucessful inserts + +SET GLOBAL debug_dbug="+d,crash_end_bulk_insert"; + +--error 2013 +REPLACE into t1 select seq+20,seq+95, seq + 300 from seq_1_to_10; + +# Wait until restarted +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect + +check table t1; +select sum(a),sum(b),sum(c) from t1; +drop table t1; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result new file mode 100644 index 00000000000..a83a9b61b9f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result @@ -0,0 +1,291 @@ +include/master-slave.inc +[connection master] +connection slave; +include/stop_slave.inc +RESET MASTER; +RESET SLAVE; +connection master; +RESET MASTER; +CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB; +INSERT INTO t1 SET a=25, b='trx0'; +connection slave; +include/start_slave.inc +connection master; +connection slave; +include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=2; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; +connection slave; +SET @old_max_relay_log_size = @@global.max_relay_log_size; +SET @@global.max_relay_log_size=4096; +connection master; +BEGIN; +INSERT INTO t1 SET a=1, b='trx1'; +INSERT INTO t1 SET a=2, b='trx1'; +INSERT INTO t1 SET a=3, b='trx1'; +INSERT INTO t1 SET a=4, b='trx1'; +INSERT INTO t1 SET a=5, b='trx1'; +INSERT INTO t1 SET a=6, b='trx1'; +INSERT INTO t1 SET a=7, b='trx1'; +INSERT INTO t1 SET a=8, b='trx1'; +INSERT INTO t1 SET a=9, b='trx1'; +INSERT INTO t1 SET a=10, b='trx1'; +INSERT INTO t1 SET a=11, b='trx1'; +INSERT INTO t1 SET a=12, b='trx1'; +INSERT INTO t1 SET a=13, b='trx1'; +INSERT INTO t1 SET a=14, b='trx1'; +INSERT INTO t1 SET a=15, b='trx1'; +INSERT INTO t1 SET a=16, b='trx1'; +INSERT INTO t1 SET a=17, b='trx1'; +INSERT INTO t1 SET a=18, b='trx1'; +INSERT INTO t1 SET a=19, b='trx1'; +INSERT INTO t1 SET a=20, b='trx1'; +INSERT INTO t1 SET a=21, b='trx1'; +INSERT INTO t1 SET a=22, b='trx1'; +INSERT INTO t1 SET a=23, b='trx1'; +INSERT INTO t1 SET a=24, b='trx1'; +COMMIT; +FLUSH LOGS; +BEGIN; +UPDATE t1 SET b='trx2_0' WHERE a = 25; +UPDATE t1 SET b='trx2' WHERE a = 25; +COMMIT; +INSERT INTO t1 SET a=26,b='trx3'; +*** case 1 UNTIL inside trx2 +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; +connection slave; +SELECT <pos_0> <= <pos_until> AND <pos_until> < <pos_trx2> as "pos_until < trx0 and is within trx2"; +pos_until < trx0 and is within trx2 +1 +CHANGE MASTER TO MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = <pos_until>; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'; +trx2 is committed +1 +SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'; +trx3 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 2 UNTIL inside trx2 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; +connection slave; +include/stop_slave.inc +SELECT <pos_0> <= <pos_until> AND <pos_until> < <pos_trx2> as "pos_until >= trx0 and is within trx2"; +pos_until >= trx0 and is within trx2 +1 +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = <pos_trx0>, MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = <pos_until>; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'; +trx2 is committed +1 +SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'; +trx3 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 3 UNTIL inside trx1 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; # block trx1; +connection slave; +include/stop_slave.inc +SELECT <pos_until> < <pos_0> as "pos_until before trx2 start position"; +pos_until before trx2 start position +1 +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = <pos_trx0>, MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = <pos_until>; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 25-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'; +trx1 is committed +1 +SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'; +trx2 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 4 Relay-log UNTIL inside trx1 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; # block trx1; +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = <pos_trx0>, MASTER_USE_GTID=no; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = <pos_until>; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 25-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'; +trx1 is committed +1 +SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'; +trx2 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs +connection master; +CREATE TABLE t2 (a TEXT) ENGINE=InnoDB; +FLUSH LOGS; +connection slave; +connection slave; +include/stop_slave.inc +connection master; +BEGIN; +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +COMMIT; +INSERT INTO t2 SET a='a'; +connection slave; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = <pos_until>; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +include/diff_tables.inc [master:t2,slave:t2] +*** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs +connection slave; +include/stop_slave.inc +connection master; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +COMMIT; +connection slave; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +connection master; +include/sync_slave_io_with_master.inc +connection slave; +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = <pos_until>; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +include/diff_tables.inc [master:t2,slave:t2] +connection slave; +include/stop_slave.inc +SET GLOBAL max_relay_log_size=@old_max_relay_log_size; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +include/start_slave.inc +connection master; +DROP TABLE t1, t2; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result b/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result index 4d666c6e8bf..99e7a184e1f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result +++ b/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result @@ -11,7 +11,7 @@ drop table t1; connection slave; include/wait_for_slave_sql_to_stop.inc call mtr.add_suppression("Slave SQL.*Query caused different errors on master and slave.*Error on master:.* error code=1062.*Error on slave:.* error.* 0"); -Error: "Query caused different errors on master and slave. Error on master: message (format)='Duplicate entry '%-.192s' for key %d' error code=1062 ; Error on slave: actual message='no error', error code=0. Default database: 'test'. Query: 'insert into t1 values(1),(2)'" (expected different error codes on master and slave) +Error: "Query caused different errors on master and slave. Error on master: message (format)='Duplicate entry '%-.192T' for key %d' error code=1062 ; Error on slave: actual message='no error', error code=0. Default database: 'test'. Query: 'insert into t1 values(1),(2)'" (expected different error codes on master and slave) Errno: "0" (expected 0) drop table t1; include/stop_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test new file mode 100644 index 00000000000..508213c9075 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test @@ -0,0 +1,465 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc +# Format is restricted because the test expects a specific result of +# relay-logging that splits a transaction into two different files. +--source include/have_binlog_format_row.inc + +# +# MDEV-15152 Optimistic parallel slave doesn't cope well with START SLAVE UNTIL +# +--connection slave +--source include/stop_slave.inc +RESET MASTER; +RESET SLAVE; + +--connection master +RESET MASTER; +CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB; +--let $a0 = 25 +--eval INSERT INTO t1 SET a=$a0, b='trx0' +# Memorize the position for replication restart from it +--let $pos_trx0 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +--source include/start_slave.inc + +--connection master +# --connection slave +--sync_slave_with_master +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=2; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + +# Run the slave in the following modes one by one. +# +# 1. the until position is set in the middle of trx2 +# below $pos_trx0 of the last exec position in the first file +# 2. and above $pos_trx0 +# In either case trx2 must commit before slave stops. +# 3. the until postion is inside trx1 +# 4. RELAY log until inside trx1 +# 5. RELAY log until inside a "big" trx +# 6. RELAY log until inside a trx within a sequence of relay logs +# +# Execution flaw for Until_Master_Pos cases follows as: +# create the transaction trx1, trx2 +# logged at the beginning of two subsequent binlog files. +# Set the until position to at the middle of the 2rd transaction. +# Engage the optimistic scheduler while having trx1 execution blocked. +# Lift the block after trx2 has reached waiting its order to commit. +# *Proof 1* +# Observe that the slave applier stops at a correct position. +# In the bug condition it would stop prematurely having the stop position +# in the first file, therefore trx2 not committed. +# Specifically, an internal transaction position until makes the applier to run +# beyond it to commit commit the current transaction. +# *Proof 2* +# Observe the following START SLAVE resumes OK. +# +# Auxiliary third trx3 on master is just for triggering the actual stop +# (whihc is a legacy UNTIL's property). +# trx0 is to produce a specific value of the last executed binlog file:pos +# to emulate the bug condition. +# +# Intermediate checks via SELECT are supposed to succeed +# with putting out value 1. +# +# NOTE: Relay log until tests have to use explicit log names and position +# which may require to adjust with future changes to event formats etc. +# + +--connection slave +SET @old_max_relay_log_size = @@global.max_relay_log_size; +SET @@global.max_relay_log_size=4096; + +--connection master +# trx1 +--let $a=1 +BEGIN; +while (`SELECT $a < $a0`) +{ + --eval INSERT INTO t1 SET a=$a, b='trx1' +--inc $a +} +COMMIT; +--let $fil_1 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx1 = query_get_value(SHOW MASTER STATUS, Position, 1) + +FLUSH LOGS; + +# $pos_0 the offset of the first event of trx2 in new file +--let $pos_0=query_get_value(SHOW MASTER STATUS, Position, 1) +# trx2 +--let $a=$a0 +BEGIN; +--eval UPDATE t1 SET b='trx2_0' WHERE a = $a +--eval UPDATE t1 SET b='trx2' WHERE a = $a +COMMIT; +--let $fil_2=query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx2=query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx3 +--let $a=$a0 +--inc $a +--eval INSERT INTO t1 SET a=$a,b='trx3' +--let $pos_trx3=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $a= + + +--echo *** case 1 UNTIL inside trx2 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 +--connection slave +--let $pos_until=`SELECT $pos_trx0 - 1` +--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until < trx0 and is within trx2" +CHANGE MASTER TO MASTER_USE_GTID=no; +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 2 UNTIL inside trx2 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_trx2 - 1` +--replace_result $pos_trx0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_trx0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until >= trx0 and is within trx2" +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 3 UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_0 - 1` +--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_until < $pos_0 as "pos_until before trx2 start position" +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 4 Relay-log UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# The following test sets the stop coordinate is set to inside the first event +# of a relay log that holds events of a transaction started in an earlier log. +# Peek the stop position in the middle of trx1, not even on a event boundary. +--let $pos_until=255 +--let $file_rl=slave-relay-bin.000003 +--let $binlog_file=$file_rl + +--let $pos_xid=508 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_xid LIMIT 1, Info, 1) + +if (`SELECT "$info" NOT LIKE "COMMIT /* xid=% */" OR $pos_xid < $pos_until`) +{ + --echo *** Unexpected offset. Refine it to point to the correct XID event! + --die +} + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_rl","$file_stop") > -1`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + + +--echo *** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs + +--connection master +CREATE TABLE t2 (a TEXT) ENGINE=InnoDB; +FLUSH LOGS; + +--sync_slave_with_master +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--let $records=`SELECT floor(4*@@global.max_relay_log_size / 1024) + 1` + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx4 +BEGIN; +--let $i=$records +while ($i) +{ + INSERT INTO t2 SET a=repeat('a',1024); + +--dec $i +} +COMMIT; + +# slave will stop there: +--let $file_trx4 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx4 = query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx5 +INSERT INTO t2 SET a='a'; +--let $pos_trx5 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# Set position inside the transaction though the value +# specified is beyond that relay log file. +# The coordianate may point to in a different event in future changes +# but should not move away from inside this big group of events. +# So we don't test which event in the transaction it points to. +--let $pos_until= 4500 +--let $file_rl= slave-relay-bin.000010 + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +# It's showed the actual stop occurred before trx5 +if (`SELECT strcmp("$file_trx4", "$file_stop") <> 0 OR $pos_stop >= $pos_trx5 OR count(*) <> $records FROM t2`) +{ + --echo *** ERROR: Slave stopped at *binlog* $file_stop:$pos_stop which is not $file_trx4:$pos_trx4. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + + + +--echo *** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx6 +--let $records=`SELECT count(*) FROM t2` +while ($records) +{ + BEGIN; + DELETE FROM t2 LIMIT 1; + COMMIT; +--dec $records +} +COMMIT; + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection master +--source include/sync_slave_io_with_master.inc + +--connection slave +# The relay-log coordinate is not at an event boundary and +# also may change across the server version. +# The test makes its best to check its coherance. +--let $pos_until= 3130 +--let $file_rl= slave-relay-bin.000018 + +--let $pos_gtid = 2987 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_gtid LIMIT 1, Info, 1) + +if (`SELECT "$info" != "BEGIN GTID 0-1-23"`) +{ + --echo *** Unexpected offset. Refine it to point to the correct GTID! + --die +} +--let $pos_event = 3120 +--let $type= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_event LIMIT 1, Event_type, 1) +if (`SELECT "$type" != "Delete_rows_v1"`) +{ + --echo *** Unexpected offset. Refine it to point to the expected event! + --die +} + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_stop", "$file_rl") = -1 OR + strcmp("$file_stop", "$file_rl") = 0 AND $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at *relay* $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +SET GLOBAL max_relay_log_size=@old_max_relay_log_size; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1, t2; + +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index 33375a14803..1e6c854e0d9 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -409,3 +409,12 @@ SELECT * FROM t1 WHERE d2 < d1; i d1 d2 t 1 2023-03-16 2023-03-15 1 DROP TABLE t1; +# +# MDEV-20015 Assertion `!in_use->is_error()' failed in TABLE::update_virtual_field +# +create or replace table t1 (a int); +insert into t1 (a) values (1), (1); +create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk), key(c)); +insert into t2 (pk) select a from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +drop tables t1, t2; diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test index 0856616dcc3..b8cbf9ef705 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test @@ -300,3 +300,14 @@ DROP TABLE t1; # Cleanup --let $datadir= `SELECT @@datadir` --remove_file $datadir/test/load_t1 + + +--echo # +--echo # MDEV-20015 Assertion `!in_use->is_error()' failed in TABLE::update_virtual_field +--echo # +create or replace table t1 (a int); +insert into t1 (a) values (1), (1); +create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk), key(c)); +--error ER_DUP_ENTRY +insert into t2 (pk) select a from t1; +drop tables t1, t2; diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc index 355b571e5a0..efb081a02e4 100644 --- a/mysql-test/suite/versioning/common.inc +++ b/mysql-test/suite/versioning/common.inc @@ -50,6 +50,10 @@ if ($MTR_COMBINATION_MYISAM) { --let $MTR_COMBINATION_TIMESTAMP= 1 } +if ($MTR_COMBINATION_TRADITIONAL) +{ + --let $MTR_COMBINATION_TIMESTAMP= 1 +} if ($MTR_COMBINATION_HEAP) { --let $MTR_COMBINATION_TIMESTAMP= 1 diff --git a/mysql-test/suite/versioning/engines.combinations b/mysql-test/suite/versioning/engines.combinations index 26b5bab23f1..57e2af6cd06 100644 --- a/mysql-test/suite/versioning/engines.combinations +++ b/mysql-test/suite/versioning/engines.combinations @@ -7,5 +7,10 @@ default-storage-engine=innodb [myisam] default-storage-engine=myisam +[traditional] +default-storage-engine=myisam +sql-mode=traditional + [heap] default-storage-engine=memory + diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index 874c617d049..b357ae390af 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -1021,6 +1021,88 @@ insert into t2 values (0), (2); update t1 left join t2 on a > b set b= 2 order by b; drop table t1, t2; # +# MDEV-17091 Assertion `old_part_id == m_last_part' failed in +# ha_partition::update_row or `part_id == m_last_part' in +# ha_partition::delete_row upon UPDATE/DELETE after dropping versioning +# +create or replace table t1 (pk int primary key, f int) engine=innodb +with system versioning +partition by key() partitions 2; +insert into t1 values (1,10),(2,20); +# expected to hit same partition +select * from t1 partition (p0); +pk f +1 10 +2 20 +alter table t1 drop system versioning; +# 1 and 2 are expected to be in different partitions +select * from t1 partition(p0); +pk f +1 10 +select * from t1 partition(p1); +pk f +2 20 +update t1 set f=pk; +delete from t1; +drop table t1; +# +# MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table +# +create or replace table t1 (f char(6)) engine innodb with system versioning; +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; +create or replace view v1 as select * from t1 for system_time all; +update v1 set f = ''; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +create or replace table t1 (f char(6)) engine innodb with system versioning +partition by system_time limit 1 +(partition p1 history, partition p2 history, partition pn current); +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; +create or replace view v1 as select * from t1 for system_time all; +update v1 set f= ''; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +delete from v1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop view v1; +drop table t1; +# End of 10.3 tests +# +# MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine +# +create table t1 (a int primary key) engine=aria page_checksum=0 +with system versioning +partition by system_time (partition p1 history, partition pn current); +alter table t1 add partition (partition p2 history); +Warnings: +Warning 4115 Maybe missing parameters: no rotation condition for multiple HISTORY partitions. +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary +t1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL Got error 174 "Fatal error during initialization of handler" from storage engine Aria NULL NULL +Warnings: +Warning 1030 Got error 174 "Fatal error during initialization of handler" from storage engine Aria +drop table t1; +create table t1 (b int) engine=aria row_format=dynamic with system versioning +partition by system_time (partition p1 history, partition pn current); +insert into t1 values (1); +replace into t1 values (1); +drop table t1; +# +# MDEV-18794 Assertion `!m_innodb' failed in ha_partition::cmp_ref upon SELECT from partitioned table +# +create or replace table t1 (pk int auto_increment, i int, c char(1), primary key (pk), key(i)) +engine=innodb with system versioning partition by key() partitions 2; +insert into t1 (i, c) values (1, 'a'), (2, 'b'), (null, 'c'), (null, 'b'); +alter table t1 drop system versioning; +replace into t1 select * from t1; +select * from t1 where i > 0 or pk = 1000 limit 1; +pk i c +1 1 a +drop table t1; +# End of 10.4 tests +# # MDEV-22153 ALTER add default history partitions makes table inaccessible # create or replace table t1 (x int) with system versioning partition by system_time; @@ -1056,31 +1138,6 @@ t1 CREATE TABLE `t1` ( PARTITIONS 8 drop tables t1; # -# MDEV-17091 Assertion `old_part_id == m_last_part' failed in -# ha_partition::update_row or `part_id == m_last_part' in -# ha_partition::delete_row upon UPDATE/DELETE after dropping versioning -# -create or replace table t1 (pk int primary key, f int) engine=innodb -with system versioning -partition by key() partitions 2; -insert into t1 values (1,10),(2,20); -# expected to hit same partition -select * from t1 partition (p0); -pk f -1 10 -2 20 -alter table t1 drop system versioning; -# 1 and 2 are expected to be in different partitions -select * from t1 partition(p0); -pk f -1 10 -select * from t1 partition(p1); -pk f -2 20 -update t1 set f=pk; -delete from t1; -drop table t1; -# # MDEV-22207 Drop default history partitions renders table inaccessible # create or replace table t1 (i int) with system versioning @@ -1149,3 +1206,6 @@ t1 CREATE TABLE `t1` ( PARTITION `p16` HISTORY ENGINE = DEFAULT_ENGINE, PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE) drop tables t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index d33edb50968..3489909e925 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -45,7 +45,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -57,7 +57,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -242,8 +242,7 @@ ERROR HY000: Table `t1` is not system-versioned create or replace table t1 (x int) with system versioning; insert into t1 values (1); select * from t1 for system_time all for update; -x -1 +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated create or replace table t1 (a int not null auto_increment primary key) with system versioning; select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; a @@ -284,7 +283,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/select2,trx_id.rdiff b/mysql-test/suite/versioning/r/select2,trx_id.rdiff index 89399516777..bdc20d1dc4f 100644 --- a/mysql-test/suite/versioning/r/select2,trx_id.rdiff +++ b/mysql-test/suite/versioning/r/select2,trx_id.rdiff @@ -22,7 +22,7 @@ 7 107 8 108 9 109 --select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +-select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; +select x as FROMTO2_x, y from t1 for system_time from transaction @x0 to transaction @x1; FROMTO2_x y 0 100 @@ -31,7 +31,7 @@ 7 107 8 108 9 109 --select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; +-select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; +select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; BETWAND2_x y 0 100 diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result index abe1c821172..353bdf8e696 100644 --- a/mysql-test/suite/versioning/r/select2.result +++ b/mysql-test/suite/versioning/r/select2.result @@ -48,7 +48,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -60,7 +60,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -98,7 +98,7 @@ ASOF2_x y 7 107 8 108 9 109 -select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; FROMTO2_x y 0 100 1 101 @@ -110,7 +110,7 @@ FROMTO2_x y 7 107 8 108 9 109 -select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; +select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; BETWAND2_x y 0 100 1 101 @@ -233,8 +233,7 @@ ERROR HY000: Table `t1` is not system-versioned create or replace table t1 (x int) with system versioning; insert into t1 values (1); select * from t1 for system_time as of now() for update; -x -1 +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated create or replace table t1 (a int not null auto_increment primary key) with system versioning; select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; a @@ -275,7 +274,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index 165458ef170..93d99273a40 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -134,11 +134,11 @@ select * from t for system_time all; a 2 1 -select * from t for system_time from '0-0-0' to current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); a 2 1 -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); a 2 1 diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result index 3b3fe580af4..e9e74899790 100644 --- a/mysql-test/suite/versioning/r/view.result +++ b/mysql-test/suite/versioning/r/view.result @@ -79,7 +79,7 @@ create or replace view vt12 as select * from t1 cross join t2; select * from vt12; a b 1 2 -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; a b # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index e64fc09b8e7..c6b89a23abd 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -854,21 +854,6 @@ update t1 left join t2 on a > b set b= 2 order by b; drop table t1, t2; --echo # ---echo # MDEV-22153 ALTER add default history partitions makes table inaccessible ---echo # -create or replace table t1 (x int) with system versioning partition by system_time; -alter table t1 add partition partitions 1; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -alter table t1 add partition partitions 2; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -alter table t1 add partition partitions 3; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -drop tables t1; - ---echo # --echo # MDEV-17091 Assertion `old_part_id == m_last_part' failed in --echo # ha_partition::update_row or `part_id == m_last_part' in --echo # ha_partition::delete_row upon UPDATE/DELETE after dropping versioning @@ -890,6 +875,86 @@ delete from t1; drop table t1; --echo # +--echo # MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table +--echo # +create or replace table t1 (f char(6)) engine innodb with system versioning; + +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; + +create or replace view v1 as select * from t1 for system_time all; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +update v1 set f = ''; + +create or replace table t1 (f char(6)) engine innodb with system versioning +partition by system_time limit 1 +(partition p1 history, partition p2 history, partition pn current); + +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; + +create or replace view v1 as select * from t1 for system_time all; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +update v1 set f= ''; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +delete from v1; + +# cleanup +drop view v1; +drop table t1; + +--echo # End of 10.3 tests + +--echo # +--echo # MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine +--echo # +create table t1 (a int primary key) engine=aria page_checksum=0 +with system versioning +partition by system_time (partition p1 history, partition pn current); + +alter table t1 add partition (partition p2 history); +show table status; +drop table t1; + +create table t1 (b int) engine=aria row_format=dynamic with system versioning +partition by system_time (partition p1 history, partition pn current); +insert into t1 values (1); +replace into t1 values (1); + +# cleanup +drop table t1; + +--echo # +--echo # MDEV-18794 Assertion `!m_innodb' failed in ha_partition::cmp_ref upon SELECT from partitioned table +--echo # +create or replace table t1 (pk int auto_increment, i int, c char(1), primary key (pk), key(i)) +engine=innodb with system versioning partition by key() partitions 2; +insert into t1 (i, c) values (1, 'a'), (2, 'b'), (null, 'c'), (null, 'b'); +alter table t1 drop system versioning; +replace into t1 select * from t1; +select * from t1 where i > 0 or pk = 1000 limit 1; +drop table t1; + +--echo # End of 10.4 tests + +--echo # +--echo # MDEV-22153 ALTER add default history partitions makes table inaccessible +--echo # +create or replace table t1 (x int) with system versioning partition by system_time; +alter table t1 add partition partitions 1; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +alter table t1 add partition partitions 2; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +alter table t1 add partition partitions 3; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +drop tables t1; + +--echo # --echo # MDEV-22207 Drop default history partitions renders table inaccessible --echo # create or replace table t1 (i int) with system versioning @@ -920,4 +985,8 @@ show create table t1; drop tables t1; +--echo # +--echo # End of 10.5 tests +--echo # + --source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index c8932ddf272..6c3e401e1cb 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -48,8 +48,8 @@ if ($MTR_COMBINATION_TRX_ID) select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; --disable_query_log @@ -62,8 +62,8 @@ if ($MTR_COMBINATION_TRX_ID) if ($MTR_COMBINATION_TIMESTAMP) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; - select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; + select x as FROMTO2_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; } --enable_query_log @@ -149,6 +149,7 @@ select * from t1 for system_time all; create or replace table t1 (x int) with system versioning; insert into t1 values (1); +--error ER_TABLE_NOT_LOCKED_FOR_WRITE select * from t1 for system_time all for update; create or replace table t1 (a int not null auto_increment primary key) with system versioning; @@ -186,7 +187,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/select2.test b/mysql-test/suite/versioning/t/select2.test index f624c512c87..1ab7bcf27c1 100644 --- a/mysql-test/suite/versioning/t/select2.test +++ b/mysql-test/suite/versioning/t/select2.test @@ -36,8 +36,8 @@ if($MTR_COMBINATION_TRX_ID) { select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; if($MTR_COMBINATION_TRX_ID) { @@ -47,8 +47,8 @@ if($MTR_COMBINATION_TRX_ID) { } if(!$MTR_COMBINATION_TRX_ID) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; - select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; + select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; + select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; } drop table t1; @@ -128,6 +128,7 @@ select * from t1 for system_time all; create or replace table t1 (x int) with system versioning; insert into t1 values (1); +--error ER_TABLE_NOT_LOCKED_FOR_WRITE select * from t1 for system_time as of now() for update; create or replace table t1 (a int not null auto_increment primary key) with system versioning; @@ -165,7 +166,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index e82a116f30e..ef5d97ad262 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -97,8 +97,8 @@ select * from t for system_time all; select * from t; select * from t for system_time as of timestamp current_timestamp(6); select * from t for system_time all; -select * from t for system_time from '0-0-0' to current_timestamp(6); -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); show status like "Feature_system_versioning"; diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test index 288f1eb6e21..37676a7fb50 100644 --- a/mysql-test/suite/versioning/t/view.test +++ b/mysql-test/suite/versioning/t/view.test @@ -65,7 +65,7 @@ insert into t1 values (1); insert into t2 values (2); create or replace view vt12 as select * from t1 cross join t2; select * from vt12; -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; --echo # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index b671d87a933..bf2bacd213c 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -248,7 +248,8 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); @@ -281,7 +282,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); @@ -310,8 +312,8 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) uint prefix_bytes, prefix_bits, d; uchar *m= (uchar *)map->bitmap; - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); set_if_smaller(prefix_size, map->n_bits); if ((prefix_bytes= prefix_size / 8)) memset(m, 0xff, prefix_bytes); @@ -333,7 +335,8 @@ my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) uchar *m= (uchar*) map->bitmap; uchar *end_prefix= m+(prefix_size-1)/8; uchar *end; - DBUG_ASSERT(m && prefix_size <= map->n_bits); + DBUG_ASSERT(m); + DBUG_ASSERT(prefix_size <= map->n_bits); /* Empty prefix is always true */ if (!prefix_size) @@ -386,8 +389,8 @@ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap && map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -405,8 +408,9 @@ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -424,7 +428,8 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; uint len= no_words_in_map(map), len2 = no_words_in_map(map2); - DBUG_ASSERT(map->bitmap && map2->bitmap); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); end= to+MY_MIN(len,len2); while (to < end) @@ -469,7 +474,8 @@ my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, uint i, j, start_idx, end_idx; my_bitmap_map cur_res; - DBUG_ASSERT(bitmap_count && end_bit >= start_bit); + DBUG_ASSERT(bitmap_count); + DBUG_ASSERT(end_bit >= start_bit); for (j= 0; j < bitmap_count; j++) DBUG_ASSERT(end_bit < bitmap_array[j]->n_bits); @@ -497,8 +503,9 @@ my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while ( m1 < end) if ((*m1++ | *m2++) != 0xFFFFFFFF) @@ -543,8 +550,9 @@ void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits==map2->n_bits); end= map->last_word_ptr; @@ -557,8 +565,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -569,8 +578,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); while (to <= end) *to++ ^= *from++; } @@ -607,8 +617,9 @@ void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -737,7 +748,8 @@ uint bitmap_lock_set_next(MY_BITMAP *map) void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) { bitmap_lock(map); - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result b/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result index e21fb47fea8..0e879aad58f 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result @@ -6,8 +6,8 @@ SET debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (c01 INET6, c02 INET6); Warnings: Note 1105 build_frm_image: Field data type info length: 14 -Note 1105 DBUG: [0] name='c01' type_info='in...' -Note 1105 DBUG: [1] name='c02' type_info='in...' +Note 1105 DBUG: [0] name='c01' type_info='inet6' +Note 1105 DBUG: [1] name='c02' type_info='inet6' SET debug_dbug=@old_debug_dbug; SHOW CREATE TABLE t1; Table Create Table diff --git a/plugin/type_test/mysql-test/type_test/type_test_double-debug.result b/plugin/type_test/mysql-test/type_test/type_test_double-debug.result index ba4c8ea7b6a..975decca11e 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_double-debug.result +++ b/plugin/type_test/mysql-test/type_test/type_test_double-debug.result @@ -8,14 +8,14 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 13 -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` test_double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' DROP TABLE t1; SET @@debug_dbug=@old_debug_dbug; # Testing what happens on failure to resolve a type handler by name @@ -24,7 +24,7 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 13 -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' FLUSH TABLES; SET @@debug_dbug="+d,emulate_handler_by_name_or_error_failure"; SHOW CREATE TABLE t1; diff --git a/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result b/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result index e348b5b5f18..952a63c8476 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result +++ b/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result @@ -8,14 +8,14 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_INT8); Warnings: Note 1105 build_frm_image: Field data type info length: 11 -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` test_int8(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' DROP TABLE t1; SET @@debug_dbug=@old_debug_dbug; # Testing what happens on failure to resolve a type handler by name @@ -24,7 +24,7 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_INT8); Warnings: Note 1105 build_frm_image: Field data type info length: 11 -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' FLUSH TABLES; SET @@debug_dbug="+d,emulate_handler_by_name_or_error_failure"; SHOW CREATE TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 0f5caed57f6..7a2d67876e6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10957,6 +10957,13 @@ bool Field::save_in_field_default_value(bool view_error_processing) { THD *thd= table->in_use; + /* + TODO: MDEV-19597 Refactor TABLE::vers_update_fields() via stored virtual columns + This condition will go away as well as other conditions with vers_sys_field(). + */ + if (vers_sys_field()) + return false; + if (unlikely(flags & NO_DEFAULT_VALUE_FLAG && real_type() != MYSQL_TYPE_ENUM)) { diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 18d10710e45..123e89f8846 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2270,7 +2270,8 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info) sub_elem= subpart_it++; DBUG_ASSERT(sub_elem); part= i * num_subparts + j; - DBUG_ASSERT(part < m_file_tot_parts && m_file[part]); + DBUG_ASSERT(part < m_file_tot_parts); + DBUG_ASSERT(m_file[part]); dummy_info.data_file_name= dummy_info.index_file_name = NULL; m_file[part]->update_create_info(&dummy_info); sub_elem->data_file_name = (char*) dummy_info.data_file_name; @@ -3725,11 +3726,13 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) err_handler: DEBUG_SYNC(ha_thd(), "partition_open_error"); - file= &m_file[m_tot_parts - 1]; - while (file-- != m_file) + DBUG_ASSERT(m_tot_parts > 0); + for (uint i= m_tot_parts - 1; ; --i) { - if (bitmap_is_set(&m_opened_partitions, (uint)(file - m_file))) - (*file)->ha_close(); + if (bitmap_is_set(&m_opened_partitions, i)) + m_file[i]->ha_close(); + if (!i) + break; } err_alloc: free_partition_bitmaps(); @@ -3993,7 +3996,8 @@ int ha_partition::external_lock(THD *thd, int lock_type) MY_BITMAP *used_partitions; DBUG_ENTER("ha_partition::external_lock"); - DBUG_ASSERT(!auto_increment_lock && !auto_increment_safe_stmt_log_lock); + DBUG_ASSERT(!auto_increment_lock); + DBUG_ASSERT(!auto_increment_safe_stmt_log_lock); if (lock_type == F_UNLCK) used_partitions= &m_locked_partitions; @@ -4272,8 +4276,8 @@ void ha_partition::unlock_row() bool ha_partition::was_semi_consistent_read() { DBUG_ENTER("ha_partition::was_semi_consistent_read"); - DBUG_ASSERT(m_last_part < m_tot_parts && - bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); + DBUG_ASSERT(m_last_part < m_tot_parts); + DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); DBUG_RETURN(m_file[m_last_part]->was_semi_consistent_read()); } @@ -7175,8 +7179,8 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); m_ordered_scan_ongoing= m_ordered; } - DBUG_ASSERT(m_part_spec.start_part < m_tot_parts && - m_part_spec.end_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.end_part < m_tot_parts); DBUG_RETURN(0); } @@ -10619,7 +10623,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, DBUG_PRINT("enter", ("offset: %lu inc: %lu desired_values: %lu " "first_value: %lu", (ulong) offset, (ulong) increment, (ulong) nb_desired_values, (ulong) *first_value)); - DBUG_ASSERT(increment && nb_desired_values); + DBUG_ASSERT(increment); + DBUG_ASSERT(nb_desired_values); *first_value= 0; if (table->s->next_number_keypart) { diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 71da208d775..5362dd2fc73 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2017, Aliyun and/or its affiliates. - Copyright (c) 2017, MariaDB corporation + Copyright (c) 2017, 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 @@ -115,7 +115,7 @@ int ha_sequence::open(const char *name, int mode, uint flags) file->ha_close(); } else if (!table->s->tmp_table) - table->m_needs_reopen= true; + table->internal_set_needs_reopen(true); /* The following is needed to fix comparison of rows in diff --git a/sql/handler.cc b/sql/handler.cc index 2c8a8fab82a..eac029fd5ac 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4532,6 +4532,19 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) /** + End bulk insert +*/ + +int handler::ha_end_bulk_insert() +{ + DBUG_ENTER("handler::ha_end_bulk_insert"); + DBUG_EXECUTE_IF("crash_end_bulk_insert", + { extra(HA_EXTRA_FLUSH) ; DBUG_SUICIDE();}); + estimation_rows_to_insert= 0; + DBUG_RETURN(end_bulk_insert()); +} + +/** Bulk update row: public interface. @sa handler::bulk_update_row() diff --git a/sql/handler.h b/sql/handler.h index 6eaaf0f3256..1fd9a1c6fe0 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3431,13 +3431,7 @@ public: start_bulk_insert(rows, flags); DBUG_VOID_RETURN; } - int ha_end_bulk_insert() - { - DBUG_ENTER("handler::ha_end_bulk_insert"); - estimation_rows_to_insert= 0; - int ret= end_bulk_insert(); - DBUG_RETURN(ret); - } + int ha_end_bulk_insert(); int ha_bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found); int ha_delete_all_rows(); diff --git a/sql/item.cc b/sql/item.cc index 5c9b8b3ea3f..8ea6366e6c4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6857,8 +6857,8 @@ Item_float::Item_float(THD *thd, const char *str_arg, size_t length): value= my_charset_bin.strntod((char*) str_arg, length, &end_not_used, &error); if (unlikely(error)) { - char tmp[NAME_LEN + 1]; - my_snprintf(tmp, sizeof(tmp), "%.*s", (int)length, str_arg); + char tmp[NAME_LEN + 2]; + my_snprintf(tmp, sizeof(tmp), "%.*s", static_cast<int>(length), str_arg); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp); } presentation= name.str= str_arg; diff --git a/sql/item.h b/sql/item.h index 4534e57376f..deb398299fc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3679,9 +3679,11 @@ public: Field *result_field; Item_null_result(THD *thd): Item_null(thd), result_field(0) {} bool is_result_field() { return result_field != 0; } - enum_field_types field_type() const + const Type_handler *type_handler() const { - return result_field->type(); + if (result_field) + return result_field->type_handler(); + return &type_handler_null; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index b5eda985eb2..fff8c33ac21 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -970,11 +970,16 @@ static Item *create_comparator(MY_XPATH *xpath, b->fixed_type_handler() == &type_handler_xpath_nodeset) { uint len= (uint)(xpath->query.end - context->beg); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, - "XPATH error: " - "comparison of two nodesets is not supported: '%.*s'", - MYF(0), len, context->beg); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.*s'", + MYF(0), len, context->beg); + else + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.32T'", + MYF(0), context->beg); return 0; // TODO: Comparison of two nodesets } @@ -2627,9 +2632,12 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath) xpath->item= NULL; DBUG_ASSERT(xpath->query.end > dollar_pos); uint len= (uint)(xpath->query.end - dollar_pos); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", - MYF(0), len, dollar_pos); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", + MYF(0), len, dollar_pos); + else + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.32T'", + MYF(0), dollar_pos); } } return xpath->item ? 1 : 0; @@ -2760,9 +2768,13 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) if (!rc) { uint clen= (uint)(xpath.query.end - xpath.lasttok.beg); - set_if_smaller(clen, 32); - my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", - MYF(0), clen, xpath.lasttok.beg); + if (clen <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", + MYF(0), clen, xpath.lasttok.beg); + else + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.32T'", + MYF(0), xpath.lasttok.beg); + return true; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2ed732329d2..ebac83bc00d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -327,7 +327,6 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0, opt_silent_startup= 0; -bool my_disable_leak_check= false; ulong max_used_connections; static char *mysqld_user, *mysqld_chroot; diff --git a/sql/opt_range.h b/sql/opt_range.h index a504e35bf45..664e821f8d1 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -673,6 +673,7 @@ public: bool statement_should_be_aborted() const { return + thd->killed || thd->is_fatal_error || thd->is_error() || alloced_sel_args > SEL_ARG::MAX_SEL_ARGS; diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc index 267d764bb3b..20413f5df63 100644 --- a/sql/opt_range_mrr.cc +++ b/sql/opt_range_mrr.cc @@ -79,6 +79,7 @@ range_seq_t sel_arg_range_seq_init(void *init_param, uint n_ranges, uint flags) SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param; seq->param->range_count=0; seq->at_start= TRUE; + seq->param->max_key_parts= 0; seq->stack[0].key_tree= NULL; seq->stack[0].min_key= seq->param->min_key; seq->stack[0].min_key_flag= 0; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index d33e26d2ecc..af84c9e6f18 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -93,18 +93,18 @@ handle_queued_pos_update(THD *thd, rpl_parallel_thread::queued_event *qev) /* Do not update position if an earlier event group caused an error abort. */ DBUG_ASSERT(qev->typ == rpl_parallel_thread::queued_event::QUEUED_POS_UPDATE); + rli= qev->rgi->rli; e= qev->entry_for_queued; - if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || e->force_abort) + if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || + (e->force_abort && !rli->stop_for_until)) return; - rli= qev->rgi->rli; mysql_mutex_lock(&rli->data_lock); cmp= strcmp(rli->group_relay_log_name, qev->event_relay_log_name); if (cmp < 0) { rli->group_relay_log_pos= qev->future_event_relay_log_pos; strmake_buf(rli->group_relay_log_name, qev->event_relay_log_name); - rli->notify_group_relay_log_name_update(); } else if (cmp == 0 && rli->group_relay_log_pos < qev->future_event_relay_log_pos) rli->group_relay_log_pos= qev->future_event_relay_log_pos; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index fbda0f57f74..c11889a08cd 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -62,6 +62,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), executed_entries(0), sql_delay(0), sql_delay_end(0), + until_relay_log_names_defer(false), m_flags(0) { DBUG_ENTER("Relay_log_info::Relay_log_info"); @@ -505,6 +506,8 @@ void Relay_log_info::clear_until_condition() until_condition= Relay_log_info::UNTIL_NONE; until_log_name[0]= 0; until_log_pos= 0; + until_relay_log_names_defer= false; + DBUG_VOID_RETURN; } @@ -995,7 +998,6 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, { group_relay_log_pos= rgi->future_event_relay_log_pos; strmake_buf(group_relay_log_name, rgi->event_relay_log_name); - notify_group_relay_log_name_update(); } else if (cmp == 0 && group_relay_log_pos < rgi->future_event_relay_log_pos) group_relay_log_pos= rgi->future_event_relay_log_pos; @@ -1285,29 +1287,78 @@ err: autoincrement or if we have transactions). Should be called ONLY if until_condition != UNTIL_NONE ! + + In the parallel execution mode and UNTIL_MASTER_POS the file name is + presented by future_event_master_log_name which may be ahead of + group_master_log_name. Log_event::log_pos does relate to it nevertheless + so the pair comprises a correct binlog coordinate. + Internal group events and events that have zero log_pos also + produce the zero for the local log_pos which may not lead to the + function falsely return true. + In UNTIL_RELAY_POS the original caching and notification are simplified + to straightforward files comparison when the current event can't be + a part of an event group. + RETURN VALUE true - condition met or error happened (condition seems to have bad log file name) false - condition not met */ -bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool Relay_log_info::is_until_satisfied(Log_event *ev) { const char *log_name; ulonglong log_pos; + /* Prevents stopping within transaction; needed solely for Relay UNTIL. */ + bool in_trans= false; + DBUG_ENTER("Relay_log_info::is_until_satisfied"); if (until_condition == UNTIL_MASTER_POS) { log_name= (mi->using_parallel() ? future_event_master_log_name : group_master_log_name); - log_pos= master_beg_pos; + log_pos= (get_flag(Relay_log_info::IN_TRANSACTION) || !ev || !ev->log_pos) ? + (mi->using_parallel() ? 0 : group_master_log_pos) : + ev->log_pos - ev->data_written; } else { DBUG_ASSERT(until_condition == UNTIL_RELAY_POS); - log_name= group_relay_log_name; - log_pos= group_relay_log_pos; + if (!mi->using_parallel()) + { + log_name= group_relay_log_name; + log_pos= group_relay_log_pos; + } + else + { + log_name= event_relay_log_name; + log_pos= event_relay_log_pos; + in_trans= get_flag(Relay_log_info::IN_TRANSACTION); + /* + until_log_names_cmp_result is set to UNKNOWN either + - by a non-group event *and* only when it is in the middle of a group + - or by a group event when the preceding group made the above + non-group event to defer the resetting. + */ + if ((ev && !Log_event::is_group_event(ev->get_type_code()))) + { + if (in_trans) + { + until_relay_log_names_defer= true; + } + else + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } + else if (!in_trans && until_relay_log_names_defer) + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } } DBUG_PRINT("info", ("group_master_log_name='%s', group_master_log_pos=%llu", @@ -1361,8 +1412,8 @@ bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) } DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && - log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); + (log_pos >= until_log_pos && !in_trans)) || + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); } diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fafe8ead63d..f89b40b1efc 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -219,7 +219,7 @@ public: */ char future_event_master_log_name[FN_REFLEN]; - /* + /* Original log name and position of the group we're currently executing (whose coordinates are group_relay_log_name/pos in the relay log) in the master's binlog. These concern the *group*, because in the master's @@ -419,7 +419,7 @@ public: void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t); + bool is_until_satisfied(Log_event *ev); inline ulonglong until_pos() { DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || @@ -427,7 +427,13 @@ public: return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : group_relay_log_pos); } - + inline char *until_name() + { + DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || + until_condition == UNTIL_RELAY_POS); + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_name : + group_relay_log_name); + } /** Helper function to do after statement completion. @@ -564,6 +570,15 @@ private: relay_log.info had 4 lines. Now it has 5 lines. */ static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5; + /* + Hint for when to stop event distribution by sql driver thread. + The flag is set ON by a non-group event when this event is in the middle + of a group (e.g a transaction group) so it's too early + to refresh the current-relay-log vs until-log cached comparison result. + And it is checked and to decide whether it's a right time to do so + when the being processed group has been fully scheduled. + */ + bool until_relay_log_names_defer; /* Holds the state of the data in the relay log. diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index ce18410d9af..4137454e19b 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -315,6 +315,7 @@ extern "C" void wsrep_commit_ordered(THD *thd) } if (!wsrep_commit_will_write_binlog(thd)) { + DEBUG_SYNC(thd, "before_wsrep_ordered_commit"); thd->wsrep_cs().ordered_commit(); } } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 55dc2eeea22..49cabec9916 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1197,30 +1197,30 @@ ER_TABLE_EXISTS_ERROR 42S01 swe "Tabellen '%-.192s' finns redan" ukr "Таблиця '%-.192s' вже існує" ER_BAD_TABLE_ERROR 42S02 - cze "Neznámá tabulka '%-.100s'" - dan "Ukendt tabel '%-.100s'" - nla "Onbekende tabel '%-.100s'" - eng "Unknown table '%-.100s'" - est "Tundmatu tabel '%-.100s'" - fre "Table '%-.100s' inconnue" - ger "Unbekannte Tabelle '%-.100s'" - greek "Αγνωστος πίνακας '%-.100s'" - hindi "अज्ञात टेबल '%-.100s'" - hun "Ervenytelen tabla: '%-.100s'" - ita "Tabella '%-.100s' sconosciuta" - jpn "'%-.100s' は不明な表です。" - kor "테이블 '%-.100s'는 알수 없음" - nor "Ukjent tabell '%-.100s'" - norwegian-ny "Ukjent tabell '%-.100s'" - pol "Nieznana tabela '%-.100s'" - por "Tabela '%-.100s' desconhecida" - rum "Tabela '%-.100s' este invalida" - rus "Неизвестная таблица '%-.100s'" - serbian "Nepoznata tabela '%-.100s'" - slo "Neznáma tabuľka '%-.100s'" - spa "Tabla '%-.100s' desconocida" - swe "Okänd tabell '%-.100s'" - ukr "Невідома таблиця '%-.100s'" + cze "Neznámá tabulka '%-.100T'" + dan "Ukendt tabel '%-.100T'" + nla "Onbekende tabel '%-.100T'" + eng "Unknown table '%-.100T'" + est "Tundmatu tabel '%-.100T'" + fre "Table '%-.100T' inconnue" + ger "Unbekannte Tabelle '%-.100T'" + greek "Αγνωστος πίνακας '%-.100T'" + hindi "अज्ञात टेबल '%-.100T'" + hun "Ervenytelen tabla: '%-.100T'" + ita "Tabella '%-.100T' sconosciuta" + jpn "'%-.100T' は不明な表です。" + kor "테이블 '%-.100T'는 알수 없음" + nor "Ukjent tabell '%-.100T'" + norwegian-ny "Ukjent tabell '%-.100T'" + pol "Nieznana tabela '%-.100T'" + por "Tabela '%-.100T' desconhecida" + rum "Tabela '%-.100T' este invalida" + rus "Неизвестная таблица '%-.100T'" + serbian "Nepoznata tabela '%-.100T'" + slo "Neznáma tabuľka '%-.100T'" + spa "Tabla '%-.100T' desconocida" + swe "Okänd tabell '%-.100T'" + ukr "Невідома таблиця '%-.100T'" ER_NON_UNIQ_ERROR 23000 cze "Sloupec '%-.192s' v %-.192s není zcela jasný" dan "Felt: '%-.192s' i tabel %-.192s er ikke entydigt" @@ -1394,30 +1394,30 @@ ER_WRONG_VALUE_COUNT 21S01 swe "Antalet kolumner motsvarar inte antalet värden" ukr "Кількість стовбців не співпадає з кількістю значень" ER_TOO_LONG_IDENT 42000 S1009 - cze "Jméno identifikátoru '%-.100s' je příliš dlouhé" - dan "Navnet '%-.100s' er for langt" - nla "Naam voor herkenning '%-.100s' is te lang" - eng "Identifier name '%-.100s' is too long" - est "Identifikaatori '%-.100s' nimi on liiga pikk" - fre "Le nom de l'identificateur '%-.100s' est trop long" - ger "Name des Bezeichners '%-.100s' ist zu lang" - greek "Το identifier name '%-.100s' είναι πολύ μεγάλο" - hindi "पहचानकर्ता का नाम '%-.100s' बहुत लंबा है" - hun "A(z) '%-.100s' azonositonev tul hosszu" - ita "Il nome dell'identificatore '%-.100s' e` troppo lungo" - jpn "識別子名 '%-.100s' は長すぎます。" - kor "Identifier '%-.100s'는 너무 길군요." - nor "Identifikator '%-.100s' er for lang" - norwegian-ny "Identifikator '%-.100s' er for lang" - pol "Nazwa identyfikatora '%-.100s' jest zbyt długa" - por "Nome identificador '%-.100s' é longo demais" - rum "Numele indentificatorului '%-.100s' este prea lung" - rus "Слишком длинный идентификатор '%-.100s'" - serbian "Ime '%-.100s' je predugačko" - slo "Meno identifikátora '%-.100s' je príliš dlhé" - spa "El nombre del identificador '%-.100s' es demasiado grande" - swe "Kolumnnamn '%-.100s' är för långt" - ukr "Ім'я ідентифікатора '%-.100s' задовге" + cze "Jméno identifikátoru '%-.100T' je příliš dlouhé" + dan "Navnet '%-.100T' er for langt" + nla "Naam voor herkenning '%-.100T' is te lang" + eng "Identifier name '%-.100T' is too long" + est "Identifikaatori '%-.100T' nimi on liiga pikk" + fre "Le nom de l'identificateur '%-.100T' est trop long" + ger "Name des Bezeichners '%-.100T' ist zu lang" + greek "Το identifier name '%-.100T' είναι πολύ μεγάλο" + hindi "पहचानकर्ता का नाम '%-.100T' बहुत लंबा है" + hun "A(z) '%-.100T' azonositonev tul hosszu" + ita "Il nome dell'identificatore '%-.100T' e` troppo lungo" + jpn "識別子名 '%-.100T' は長すぎます。" + kor "Identifier '%-.100T'는 너무 길군요." + nor "Identifikator '%-.100T' er for lang" + norwegian-ny "Identifikator '%-.100T' er for lang" + pol "Nazwa identyfikatora '%-.100T' jest zbyt długa" + por "Nome identificador '%-.100T' é longo demais" + rum "Numele indentificatorului '%-.100T' este prea lung" + rus "Слишком длинный идентификатор '%-.100T'" + serbian "Ime '%-.100T' je predugačko" + slo "Meno identifikátora '%-.100T' je príliš dlhé" + spa "El nombre del identificador '%-.100T' es demasiado grande" + swe "Kolumnnamn '%-.100T' är för långt" + ukr "Ім'я ідентифікатора '%-.100T' задовге" ER_DUP_FIELDNAME 42S21 S1009 cze "Zdvojené jméno sloupce '%-.192s'" dan "Feltnavnet '%-.192s' findes allerede" @@ -1471,30 +1471,30 @@ ER_DUP_KEYNAME 42000 S1009 # When using this error code, please use ER(ER_DUP_ENTRY_WITH_KEY_NAME) # for the message string. See, for example, code in handler.cc. ER_DUP_ENTRY 23000 S1009 - cze "Zdvojený klíč '%-.192s' (číslo klíče %d)" - dan "Ens værdier '%-.192s' for indeks %d" - nla "Dubbele ingang '%-.192s' voor zoeksleutel %d" - eng "Duplicate entry '%-.192s' for key %d" - est "Kattuv väärtus '%-.192s' võtmele %d" - fre "Duplicata du champ '%-.192s' pour la clef %d" - ger "Doppelter Eintrag '%-.192s' für Schlüssel %d" - greek "Διπλή εγγραφή '%-.192s' για το κλειδί %d" - hindi "सामान प्रवेश '%-.192s' KEY %d के लिए" - hun "Duplikalt bejegyzes '%-.192s' a %d kulcs szerint" - ita "Valore duplicato '%-.192s' per la chiave %d" - jpn "'%-.192s' は索引 %d で重複しています。" - kor "중복된 입력 값 '%-.192s': key %d" - nor "Like verdier '%-.192s' for nøkkel %d" - norwegian-ny "Like verdiar '%-.192s' for nykkel %d" - pol "Powtórzone wystąpienie '%-.192s' dla klucza %d" - por "Entrada '%-.192s' duplicada para a chave %d" - rum "Cimpul '%-.192s' e duplicat pentru cheia %d" - rus "Дублирующаяся запись '%-.192s' по ключу %d" - serbian "Dupliran unos '%-.192s' za ključ '%d'" - slo "Opakovaný kľúč '%-.192s' (číslo kľúča %d)" - spa "Entrada duplicada '%-.192s' para la clave %d" - swe "Dublett '%-.192s' för nyckel %d" - ukr "Дублюючий запис '%-.192s' для ключа %d" + cze "Zdvojený klíč '%-.192T' (číslo klíče %d)" + dan "Ens værdier '%-.192T' for indeks %d" + nla "Dubbele ingang '%-.192T' voor zoeksleutel %d" + eng "Duplicate entry '%-.192T' for key %d" + est "Kattuv väärtus '%-.192T' võtmele %d" + fre "Duplicata du champ '%-.192T' pour la clef %d" + ger "Doppelter Eintrag '%-.192T' für Schlüssel %d" + greek "Διπλή εγγραφή '%-.192T' για το κλειδί %d" + hindi "सामान प्रवेश '%-.192T' KEY %d के लिए" + hun "Duplikalt bejegyzes '%-.192T' a %d kulcs szerint" + ita "Valore duplicato '%-.192T' per la chiave %d" + jpn "'%-.192T' は索引 %d で重複しています。" + kor "중복된 입력 값 '%-.192T': key %d" + nor "Like verdier '%-.192T' for nøkkel %d" + norwegian-ny "Like verdiar '%-.192T' for nykkel %d" + pol "Powtórzone wystąpienie '%-.192T' dla klucza %d" + por "Entrada '%-.192T' duplicada para a chave %d" + rum "Cimpul '%-.192T' e duplicat pentru cheia %d" + rus "Дублирующаяся запись '%-.192T' по ключу %d" + serbian "Dupliran unos '%-.192T' za ključ '%d'" + slo "Opakovaný kľúč '%-.192T' (číslo kľúča %d)" + spa "Entrada duplicada '%-.192T' para la clave %d" + swe "Dublett '%-.192T' för nyckel %d" + ukr "Дублюючий запис '%-.192T' для ключа %d" ER_WRONG_FIELD_SPEC 42000 S1009 cze "Chybná specifikace sloupce '%-.192s'" dan "Forkert kolonnespecifikaton for felt '%-.192s'" @@ -1521,30 +1521,30 @@ ER_WRONG_FIELD_SPEC 42000 S1009 swe "Felaktigt kolumntyp för kolumn '%-.192s'" ukr "Невірний специфікатор стовбця '%-.192s'" ER_PARSE_ERROR 42000 s1009 - cze "%s blízko '%-.80s' na řádku %d" - dan "%s nær '%-.80s' på linje %d" - nla "%s bij '%-.80s' in regel %d" - eng "%s near '%-.80s' at line %d" - est "%s '%-.80s' ligidal real %d" - fre "%s près de '%-.80s' à la ligne %d" - ger "%s bei '%-.80s' in Zeile %d" - greek "%s πλησίον '%-.80s' στη γραμμή %d" - hindi "%s के पास '%-.80s' लाइन %d में" - hun "A %s a '%-.80s'-hez kozeli a %d sorban" - ita "%s vicino a '%-.80s' linea %d" - jpn "%s : '%-.80s' 付近 %d 行目" - kor "'%s' 에러 같읍니다. ('%-.80s' 명령어 라인 %d)" - nor "%s nær '%-.80s' på linje %d" - norwegian-ny "%s attmed '%-.80s' på line %d" - pol "%s obok '%-.80s' w linii %d" - por "%s próximo a '%-.80s' na linha %d" - rum "%s linga '%-.80s' pe linia %d" - rus "%s около '%-.80s' на строке %d" - serbian "'%s' u iskazu '%-.80s' na liniji %d" - slo "%s blízko '%-.80s' na riadku %d" - spa "%s cerca '%-.80s' en la linea %d" - swe "%s nära '%-.80s' på rad %d" - ukr "%s біля '%-.80s' в строці %d" + cze "%s blízko '%-.80T' na řádku %d" + dan "%s nær '%-.80T' på linje %d" + nla "%s bij '%-.80T' in regel %d" + eng "%s near '%-.80T' at line %d" + est "%s '%-.80T' ligidal real %d" + fre "%s près de '%-.80T' à la ligne %d" + ger "%s bei '%-.80T' in Zeile %d" + greek "%s πλησίον '%-.80T' στη γραμμή %d" + hindi "%s के पास '%-.80T' लाइन %d में" + hun "A %s a '%-.80T'-hez kozeli a %d sorban" + ita "%s vicino a '%-.80T' linea %d" + jpn "%s : '%-.80T' 付近 %d 行目" + kor "'%s' 에러 같읍니다. ('%-.80T' 명령어 라인 %d)" + nor "%s nær '%-.80T' på linje %d" + norwegian-ny "%s attmed '%-.80T' på line %d" + pol "%s obok '%-.80T' w linii %d" + por "%s próximo a '%-.80T' na linha %d" + rum "%s linga '%-.80T' pe linia %d" + rus "%s около '%-.80T' на строке %d" + serbian "'%s' u iskazu '%-.80T' na liniji %d" + slo "%s blízko '%-.80T' na riadku %d" + spa "%s cerca '%-.80T' en la linea %d" + swe "%s nära '%-.80T' på rad %d" + ukr "%s біля '%-.80T' в строці %d" ER_EMPTY_QUERY 42000 cze "Výsledek dotazu je prázdný" dan "Forespørgsel var tom" @@ -2380,30 +2380,30 @@ ER_TABLE_NOT_LOCKED ER_UNUSED_17 eng "You should never see it" ER_WRONG_DB_NAME 42000 - cze "Nepřípustné jméno databáze '%-.100s'" - dan "Ugyldigt database navn '%-.100s'" - nla "Databasenaam '%-.100s' is niet getoegestaan" - eng "Incorrect database name '%-.100s'" - est "Vigane andmebaasi nimi '%-.100s'" - fre "Nom de base de donnée illégal: '%-.100s'" - ger "Unerlaubter Datenbankname '%-.100s'" - greek "Λάθος όνομα βάσης δεδομένων '%-.100s'" - hindi "डेटाबेस नाम '%-.100s' गलत है" - hun "Hibas adatbazisnev: '%-.100s'" - ita "Nome database errato '%-.100s'" - jpn "データベース名 '%-.100s' は不正です。" - kor "'%-.100s' 데이타베이스의 이름이 부정확합니다." - nor "Ugyldig database navn '%-.100s'" - norwegian-ny "Ugyldig database namn '%-.100s'" - pol "Niedozwolona nazwa bazy danych '%-.100s'" - por "Nome de banco de dados '%-.100s' incorreto" - rum "Numele bazei de date este incorect '%-.100s'" - rus "Некорректное имя базы данных '%-.100s'" - serbian "Pogrešno ime baze '%-.100s'" - slo "Neprípustné meno databázy '%-.100s'" - spa "Nombre de base de datos ilegal '%-.100s'" - swe "Felaktigt databasnamn '%-.100s'" - ukr "Невірне ім'я бази данних '%-.100s'" + cze "Nepřípustné jméno databáze '%-.100T'" + dan "Ugyldigt database navn '%-.100T'" + nla "Databasenaam '%-.100T' is niet getoegestaan" + eng "Incorrect database name '%-.100T'" + est "Vigane andmebaasi nimi '%-.100T'" + fre "Nom de base de donnée illégal: '%-.100T'" + ger "Unerlaubter Datenbankname '%-.100T'" + greek "Λάθος όνομα βάσης δεδομένων '%-.100T'" + hindi "डेटाबेस नाम '%-.100T' गलत है" + hun "Hibas adatbazisnev: '%-.100T'" + ita "Nome database errato '%-.100T'" + jpn "データベース名 '%-.100T' は不正です。" + kor "'%-.100T' 데이타베이스의 이름이 부정확합니다." + nor "Ugyldig database navn '%-.100T'" + norwegian-ny "Ugyldig database namn '%-.100T'" + pol "Niedozwolona nazwa bazy danych '%-.100T'" + por "Nome de banco de dados '%-.100T' incorreto" + rum "Numele bazei de date este incorect '%-.100T'" + rus "Некорректное имя базы данных '%-.100T'" + serbian "Pogrešno ime baze '%-.100T'" + slo "Neprípustné meno databázy '%-.100T'" + spa "Nombre de base de datos ilegal '%-.100T'" + swe "Felaktigt databasnamn '%-.100T'" + ukr "Невірне ім'я бази данних '%-.100T'" ER_WRONG_TABLE_NAME 42000 cze "Nepřípustné jméno tabulky '%-.100s'" dan "Ugyldigt tabel navn '%-.100s'" @@ -4688,15 +4688,15 @@ ER_NO_DEFAULT 42000 spa "Variable '%-.64s' no tiene un valor patrón" swe "Variabel '%-.64s' har inte ett DEFAULT-värde" ER_WRONG_VALUE_FOR_VAR 42000 - nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200s'" - eng "Variable '%-.64s' can't be set to the value of '%-.200s'" - ger "Variable '%-.64s' kann nicht auf '%-.200s' gesetzt werden" - ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200s'" - jpn "変数 '%-.64s' に値 '%-.200s' を設定できません。" - por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200s'" - rus "Переменная '%-.64s' не может быть установлена в значение '%-.200s'" - spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200s'" - swe "Variabel '%-.64s' kan inte sättas till '%-.200s'" + nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200T'" + eng "Variable '%-.64s' can't be set to the value of '%-.200T'" + ger "Variable '%-.64s' kann nicht auf '%-.200T' gesetzt werden" + ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200T'" + jpn "変数 '%-.64s' に値 '%-.200T' を設定できません。" + por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200T'" + rus "Переменная '%-.64s' не может быть установлена в значение '%-.200T'" + spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200T'" + swe "Variabel '%-.64s' kan inte sättas till '%-.200T'" ER_WRONG_TYPE_FOR_VAR 42000 nla "Foutief argumenttype voor variabele '%-.64s'" eng "Incorrect argument type to variable '%-.64s'" @@ -5140,11 +5140,11 @@ ER_DUPLICATED_VALUE_IN_TYPE por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s" spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s" ER_TRUNCATED_WRONG_VALUE 22007 - eng "Truncated incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert gekürzt: '%-.128s'" - jpn "不正な %-.32s の値が切り捨てられました。: '%-.128s'" - por "Truncado errado %-.32s valor: '%-.128s'" - spa "Equivocado truncado %-.32s valor: '%-.128s'" + eng "Truncated incorrect %-.32T value: '%-.128T'" + ger "Falscher %-.32T-Wert gekürzt: '%-.128T'" + jpn "不正な %-.32T の値が切り捨てられました。: '%-.128T'" + por "Truncado errado %-.32T valor: '%-.128T'" + spa "Equivocado truncado %-.32T valor: '%-.128T'" ER_TOO_MUCH_AUTO_TIMESTAMP_COLS eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" ger "Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben" @@ -5181,8 +5181,8 @@ ER_WARN_INVALID_TIMESTAMP eng "Invalid TIMESTAMP value in column '%s' at row %lu" ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %lu" ER_INVALID_CHARACTER_STRING - eng "Invalid %s character string: '%.64s'" - ger "Ungültiger %s-Zeichen-String: '%.64s'" + eng "Invalid %s character string: '%.64T'" + ger "Ungültiger %s-Zeichen-String: '%.64T'" ER_WARN_ALLOWED_PACKET_OVERFLOWED eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated" ger "Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt" @@ -5426,11 +5426,11 @@ ER_DIVISION_BY_ZERO 22012 ger "Division durch 0" hindi "0 से विभाजन" ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 22007 - eng "Incorrect %-.32s value: '%-.128s' for column `%.192s`.`%.192s`.`%.192s` at row %lu" - ger "Falscher %-.32s-Wert: '%-.128s' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" + eng "Incorrect %-.32s value: '%-.128T' for column `%.192s`.`%.192s`.`%.192s` at row %lu" + ger "Falscher %-.32s-Wert: '%-.128T' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" ER_ILLEGAL_VALUE_FOR_TYPE 22007 - eng "Illegal %s '%-.192s' value found during parsing" - ger "Nicht zulässiger %s-Wert '%-.192s' beim Parsen gefunden" + eng "Illegal %s '%-.192T' value found during parsing" + ger "Nicht zulässiger %s-Wert '%-.192T' beim Parsen gefunden" ER_VIEW_NONUPD_CHECK eng "CHECK OPTION on non-updatable view %`-.192s.%`-.192s" ger "CHECK OPTION auf nicht-aktualisierbarem View %`-.192s.%`-.192s" @@ -5576,8 +5576,8 @@ ER_CANT_CREATE_USER_WITH_GRANT 42000 eng "You are not allowed to create a user with GRANT" ger "Sie dürfen keinen Benutzer mit GRANT anlegen" ER_WRONG_VALUE_FOR_TYPE - eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" - ger "Falscher %-.32s-Wert: '%-.128s' für Funktion %-.32s" + eng "Incorrect %-.32s value: '%-.128T' for function %-.32s" + ger "Falscher %-.32s-Wert: '%-.128T' für Funktion %-.32s" ER_TABLE_DEF_CHANGED eng "Table definition has changed, please retry transaction" ger "Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu" @@ -5756,8 +5756,8 @@ ER_HOSTNAME ger "Hostname" hindi "होस्ट का नाम" ER_WRONG_STRING_LENGTH - eng "String '%-.70s' is too long for %s (should be no longer than %d)" - ger "String '%-.70s' ist zu lang für %s (sollte nicht länger sein als %d)" + eng "String '%-.70T' is too long for %s (should be no longer than %d)" + ger "String '%-.70T' ist zu lang für %s (sollte nicht länger sein als %d)" ER_NON_INSERTABLE_TABLE eng "The target table %-.100s of the %s is not insertable-into" ger "Die Zieltabelle %-.100s von %s ist nicht einfügbar" @@ -5962,8 +5962,8 @@ ER_PLUGIN_IS_NOT_LOADED eng "Plugin '%-.192s' is not loaded" ger "Plugin '%-.192s' ist nicht geladen" ER_WRONG_VALUE - eng "Incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert: '%-.128s'" + eng "Incorrect %-.32s value: '%-.128T'" + ger "Falscher %-.32s-Wert: '%-.128T'" ER_NO_PARTITION_FOR_GIVEN_VALUE eng "Table has no partition for value %-.64s" ger "Tabelle hat für den Wert %-.64s keine Partition" @@ -6106,8 +6106,8 @@ ER_WRONG_PARTITION_NAME ER_CANT_CHANGE_TX_CHARACTERISTICS 25001 eng "Transaction characteristics can't be changed while a transaction is in progress" ER_DUP_ENTRY_AUTOINCREMENT_CASE - eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'" - ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192s' für Schlüssel '%-.192s' auftritt" + eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192T' for key '%-.192s'" + ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192T' für Schlüssel '%-.192s' auftritt" ER_EVENT_MODIFY_QUEUE_ERROR eng "Internal scheduler error %d" ger "Interner Scheduler-Fehler %d" @@ -6162,29 +6162,29 @@ ER_NATIVE_FCT_NAME_COLLISION # When using this error message, use the ER_DUP_ENTRY error code. See, for # example, code in handler.cc. ER_DUP_ENTRY_WITH_KEY_NAME 23000 S1009 - cze "Zvojený klíč '%-.64s' (číslo klíče '%-.192s')" - dan "Ens værdier '%-.64s' for indeks '%-.192s'" - nla "Dubbele ingang '%-.64s' voor zoeksleutel '%-.192s'" - eng "Duplicate entry '%-.64s' for key '%-.192s'" - est "Kattuv väärtus '%-.64s' võtmele '%-.192s'" - fre "Duplicata du champ '%-.64s' pour la clef '%-.192s'" - ger "Doppelter Eintrag '%-.64s' für Schlüssel '%-.192s'" - greek "Διπλή εγγραφή '%-.64s' για το κλειδί '%-.192s'" - hun "Duplikalt bejegyzes '%-.64s' a '%-.192s' kulcs szerint" - ita "Valore duplicato '%-.64s' per la chiave '%-.192s'" - jpn "'%-.64s' は索引 '%-.192s' で重複しています。" - kor "중복된 입력 값 '%-.64s': key '%-.192s'" - nor "Like verdier '%-.64s' for nøkkel '%-.192s'" - norwegian-ny "Like verdiar '%-.64s' for nykkel '%-.192s'" - pol "Powtórzone wystąpienie '%-.64s' dla klucza '%-.192s'" - por "Entrada '%-.64s' duplicada para a chave '%-.192s'" - rum "Cimpul '%-.64s' e duplicat pentru cheia '%-.192s'" - rus "Дублирующаяся запись '%-.64s' по ключу '%-.192s'" - serbian "Dupliran unos '%-.64s' za ključ '%-.192s'" - slo "Opakovaný kľúč '%-.64s' (číslo kľúča '%-.192s')" - spa "Entrada duplicada '%-.64s' para la clave '%-.192s'" - swe "Dublett '%-.64s' för nyckel '%-.192s'" - ukr "Дублюючий запис '%-.64s' для ключа '%-.192s'" + cze "Zvojený klíč '%-.64T' (číslo klíče '%-.192s')" + dan "Ens værdier '%-.64T' for indeks '%-.192s'" + nla "Dubbele ingang '%-.64T' voor zoeksleutel '%-.192s'" + eng "Duplicate entry '%-.64T' for key '%-.192s'" + est "Kattuv väärtus '%-.64T' võtmele '%-.192s'" + fre "Duplicata du champ '%-.64T' pour la clef '%-.192s'" + ger "Doppelter Eintrag '%-.64T' für Schlüssel '%-.192s'" + greek "Διπλή εγγραφή '%-.64T' για το κλειδί '%-.192s'" + hun "Duplikalt bejegyzes '%-.64T' a '%-.192s' kulcs szerint" + ita "Valore duplicato '%-.64T' per la chiave '%-.192s'" + jpn "'%-.64T' は索引 '%-.192s' で重複しています。" + kor "중복된 입력 값 '%-.64T': key '%-.192s'" + nor "Like verdier '%-.64T' for nøkkel '%-.192s'" + norwegian-ny "Like verdiar '%-.64T' for nykkel '%-.192s'" + pol "Powtórzone wystąpienie '%-.64T' dla klucza '%-.192s'" + por "Entrada '%-.64T' duplicada para a chave '%-.192s'" + rum "Cimpul '%-.64T' e duplicat pentru cheia '%-.192s'" + rus "Дублирующаяся запись '%-.64T' по ключу '%-.192s'" + serbian "Dupliran unos '%-.64T' za ključ '%-.192s'" + slo "Opakovaný kľúč '%-.64T' (číslo kľúča '%-.192s')" + spa "Entrada duplicada '%-.64T' para la clave '%-.192s'" + swe "Dublett '%-.64T' för nyckel '%-.192s'" + ukr "Дублюючий запис '%-.64T' для ключа '%-.192s'" ER_BINLOG_PURGE_EMFILE eng "Too many files opened, please execute the command again" ger "Zu viele offene Dateien, bitte führen Sie den Befehl noch einmal aus" @@ -6465,8 +6465,8 @@ ER_SLAVE_CANT_CREATE_CONVERSION ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT eng "Cannot modify @@session.binlog_format inside a transaction" ER_PATH_LENGTH - eng "The path specified for %.64s is too long" - hindi "%.64s के लिए निर्दिष्ट पथ बहुत लंबा है" + eng "The path specified for %.64T is too long" + hindi "%.64T के लिए निर्दिष्ट पथ बहुत लंबा है" ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT eng "'%s' is deprecated and will be removed in a future release" ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden" @@ -7166,8 +7166,8 @@ ER_UNKNOWN_OPTION eng "Unknown option '%-.64s'" hindi "अज्ञात विकल्प '%-.64s'" ER_BAD_OPTION_VALUE - eng "Incorrect value '%-.64s' for option '%-.64s'" - hindi "गलत मान '%-.64s' विकल्प '%-.64s' के लिए" + eng "Incorrect value '%-.64T' for option '%-.64s'" + hindi "गलत मान '%-.64T' विकल्प '%-.64s' के लिए" ER_UNUSED_6 eng "You should never see it" ER_UNUSED_7 @@ -7324,8 +7324,8 @@ ER_ROLE_DROP_EXISTS ER_CANNOT_CONVERT_CHARACTER eng "Cannot convert '%s' character 0x%-.64s to '%s'" ER_INVALID_DEFAULT_VALUE_FOR_FIELD 22007 - eng "Incorrect default value '%-.128s' for column '%.192s'" - hindi "गलत डिफ़ॉल्ट मान '%-.128s' कॉलम '%.192s' के लिए" + eng "Incorrect default value '%-.128T' for column '%.192s'" + hindi "गलत डिफ़ॉल्ट मान '%-.128T' कॉलम '%.192s' के लिए" ER_KILL_QUERY_DENIED_ERROR eng "You are not owner of query %lu" ger "Sie sind nicht Eigentümer von Abfrage %lu" diff --git a/sql/slave.cc b/sql/slave.cc index 1902a3681a5..0b5e8e912cf 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4355,12 +4355,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && (ev->server_id != global_system_variables.server_id || rli->replicate_same_server_id) && - rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) - ? rli->group_master_log_pos - : ev->log_pos - ev->data_written)) + rli->is_until_satisfied(ev)) { - sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. @@ -5607,10 +5603,14 @@ pthread_handler_t handle_slave_sql(void *arg) } if ((rli->until_condition == Relay_log_info::UNTIL_MASTER_POS || rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(NULL)) { sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); mysql_mutex_unlock(&rli->data_lock); goto err; } @@ -5689,7 +5689,24 @@ pthread_handler_t handle_slave_sql(void *arg) err: if (mi->using_parallel()) rli->parallel.wait_for_done(thd, rli); + /* Gtid_list_log_event::do_apply_event has already reported the GTID until */ + if (rli->stop_for_until && rli->until_condition != Relay_log_info::UNTIL_GTID) + { + if (global_system_variables.log_warnings > 2) + sql_print_information("Slave SQL thread UNTIL stop was requested at position " + "%llu in %s %s file", + rli->until_log_pos, rli->until_log_name, + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + sql_print_information("Slave SQL thread stopped because it reached its" + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + }; /* Thread stopped. Print the current replication position to the log */ { StringBuffer<100> tmp; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 0274a51ff26..03822acf564 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1089,7 +1089,7 @@ send_result_message: } /* Make sure this table instance is not reused after the operation. */ if (table->table) - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); } result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; table->next_local= save_next_local; @@ -1213,7 +1213,7 @@ err: trans_rollback(thd); if (table && table->table) { - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); table->table= 0; } close_thread_tables(thd); // Shouldn't be needed diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c9865394e93..39fdefbc189 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2296,9 +2296,9 @@ Locked_tables_list::init_locked_tables(THD *thd) in reopen_tables(). reopen_tables() is a critical path and we don't want to complicate it with extra allocations. */ - m_reopen_array= (TABLE**)alloc_root(&m_locked_tables_root, - sizeof(TABLE*) * - (m_locked_tables_count+1)); + m_reopen_array= (TABLE_LIST**)alloc_root(&m_locked_tables_root, + sizeof(TABLE_LIST*) * + (m_locked_tables_count+1)); if (m_reopen_array == NULL) { reset(); @@ -2411,6 +2411,7 @@ void Locked_tables_list::reset() m_locked_tables_last= &m_locked_tables; m_reopen_array= NULL; m_locked_tables_count= 0; + some_table_marked_for_reopen= 0; } @@ -2506,7 +2507,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) in reopen_tables() always links the opened table to the beginning of the open_tables list. */ - DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]); + DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]->table); thd->open_tables->pos_in_locked_tables->table= NULL; thd->open_tables->pos_in_locked_tables= NULL; @@ -2536,10 +2537,36 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) } +/* + Mark all instances of the table to be reopened + + This is only needed when LOCK TABLES is active +*/ + +void Locked_tables_list::mark_table_for_reopen(THD *thd, TABLE *table) +{ + TABLE_SHARE *share= table->s; + + for (TABLE_LIST *table_list= m_locked_tables; + table_list; table_list= table_list->next_global) + { + if (table_list->table->s == share) + table_list->table->internal_set_needs_reopen(true); + } + /* This is needed in the case where lock tables where not used */ + table->internal_set_needs_reopen(true); + some_table_marked_for_reopen= 1; +} + + /** Reopen the tables locked with LOCK TABLES and temporarily closed by a DDL statement or FLUSH TABLES. + @param need_reopen If set, reopen open tables that are marked with + for reopen. + If not set, reopen tables that where closed. + @note This function is a no-op if we're not under LOCK TABLES. @return TRUE if an error reopening the tables. May happen in @@ -2557,6 +2584,12 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) MYSQL_LOCK *merged_lock; DBUG_ENTER("Locked_tables_list::reopen_tables"); + DBUG_ASSERT(some_table_marked_for_reopen || !need_reopen); + + + /* Reset flag that some table was marked for reopen */ + some_table_marked_for_reopen= 0; + for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= table_list->next_global) { @@ -2580,24 +2613,32 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) else { if (table_list->table) /* The table was not closed */ - continue; - } - - /* Links into thd->open_tables upon success */ - if (open_table(thd, table_list, &ot_ctx)) - { - unlink_all_closed_tables(thd, 0, reopen_count); - DBUG_RETURN(TRUE); + continue; } - table_list->table->pos_in_locked_tables= table_list; - /* See also the comment on lock type in init_locked_tables(). */ - table_list->table->reginfo.lock_type= table_list->lock_type; DBUG_ASSERT(reopen_count < m_locked_tables_count); - m_reopen_array[reopen_count++]= table_list->table; + m_reopen_array[reopen_count++]= table_list; } if (reopen_count) { + TABLE **tables= (TABLE**) my_alloca(reopen_count * sizeof(TABLE*)); + + for (uint i= 0 ; i < reopen_count ; i++) + { + TABLE_LIST *table_list= m_reopen_array[i]; + /* Links into thd->open_tables upon success */ + if (open_table(thd, table_list, &ot_ctx)) + { + unlink_all_closed_tables(thd, 0, i); + my_afree((void*) tables); + DBUG_RETURN(TRUE); + } + tables[i]= table_list->table; + table_list->table->pos_in_locked_tables= table_list; + /* See also the comment on lock type in init_locked_tables(). */ + table_list->table->reginfo.lock_type= table_list->lock_type; + } + thd->in_lock_tables= 1; /* We re-lock all tables with mysql_lock_tables() at once rather @@ -2610,7 +2651,7 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) works fine. Patching legacy code of thr_lock.c is risking to break something else. */ - lock= mysql_lock_tables(thd, m_reopen_array, reopen_count, + lock= mysql_lock_tables(thd, tables, reopen_count, MYSQL_OPEN_REOPEN | MYSQL_LOCK_USE_MALLOC); thd->in_lock_tables= 0; if (lock == NULL || (merged_lock= @@ -2619,9 +2660,11 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) unlink_all_closed_tables(thd, lock, reopen_count); if (! thd->killed) my_error(ER_LOCK_DEADLOCK, MYF(0)); + my_afree((void*) tables); DBUG_RETURN(TRUE); } thd->lock= merged_lock; + my_afree((void*) tables); } DBUG_RETURN(FALSE); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3423e978a41..83ef31dc05b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5946,7 +5946,9 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ #ifdef WITH_WSREP - if (WSREP_CLIENT_NNULL(this) && wsrep_thd_is_local(this) && + if (WSREP_CLIENT_NNULL(this) && + wsrep_thd_is_local(this) && + wsrep_is_active(this) && variables.wsrep_trx_fragment_size > 0) { if (!is_current_stmt_binlog_format_row()) diff --git a/sql/sql_class.h b/sql/sql_class.h index 6f23ff52076..2b28f7ba158 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1951,20 +1951,23 @@ private: TABLE_LIST *m_locked_tables; TABLE_LIST **m_locked_tables_last; /** An auxiliary array used only in reopen_tables(). */ - TABLE **m_reopen_array; + TABLE_LIST **m_reopen_array; /** Count the number of tables in m_locked_tables list. We can't rely on thd->lock->table_count because it excludes non-transactional temporary tables. We need to know an exact number of TABLE objects. */ - size_t m_locked_tables_count; + uint m_locked_tables_count; public: + bool some_table_marked_for_reopen; + Locked_tables_list() :m_locked_tables(NULL), m_locked_tables_last(&m_locked_tables), m_reopen_array(NULL), - m_locked_tables_count(0) + m_locked_tables_count(0), + some_table_marked_for_reopen(0) { init_sql_alloc(key_memory_locked_table_list, &m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); @@ -1987,6 +1990,7 @@ public: bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table, MYSQL_LOCK *lock); void add_back_last_deleted_lock(TABLE_LIST *dst_table_list); + void mark_table_for_reopen(THD *thd, TABLE *table); }; @@ -4146,7 +4150,8 @@ public: The worst things that can happen is that we get a suboptimal error message. */ - if (likely((killed_err= (err_info*) alloc(sizeof(*killed_err))))) + killed_err= (err_info*) alloc_root(&main_mem_root, sizeof(*killed_err)); + if (likely(killed_err)) { killed_err->no= killed_errno_arg; ::strmake((char*) killed_err->msg, killed_err_msg_arg, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9d3ed11725c..86f81dd001a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5979,7 +5979,8 @@ finish: lex->unit.cleanup(); /* close/reopen tables that were marked to need reopen under LOCK TABLES */ - if (! thd->lex->requires_prelocking()) + if (unlikely(thd->locked_tables_list.some_table_marked_for_reopen) && + !thd->lex->requires_prelocking()) thd->locked_tables_list.reopen_tables(thd, true); if (! thd->in_sub_stmt) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index bf93047885e..34e4d6e8ea7 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4936,7 +4936,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, { *fast_alter_table= true; /* Force table re-open for consistency with the main case. */ - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -4984,7 +4984,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, must be reopened. */ *fast_alter_table= true; - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -5885,6 +5885,37 @@ the generated partition syntax in a correct manner. *partition_changed= TRUE; } } + /* + Prohibit inplace when partitioned by primary key and the primary key is changed. + */ + if (!*partition_changed && + tab_part_info->part_field_array && + !tab_part_info->part_field_list.elements && + table->s->primary_key != MAX_KEY) + { + + if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | + ALTER_ADD_SYSTEM_VERSIONING)) + { + *partition_changed= true; + } + else + { + KEY *primary_key= table->key_info + table->s->primary_key; + List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list); + const char *primary_name= primary_key->name.str; + const Alter_drop *drop; + drop_it.rewind(); + while ((drop= drop_it++)) + { + if (drop->type == Alter_drop::KEY && + 0 == my_strcasecmp(system_charset_info, primary_name, drop->name)) + break; + } + if (drop) + *partition_changed= TRUE; + } + } } if (thd->work_part_info) { @@ -5917,23 +5948,6 @@ the generated partition syntax in a correct manner. } } - // In case of PARTITION BY KEY(), check if primary key has changed - // System versioning also implicitly adds/removes primary key parts - if (alter_info->partition_flags == 0 && part_info->list_of_part_fields - && part_info->part_field_list.elements == 0) - { - if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | - ALTER_ADD_SYSTEM_VERSIONING)) - *partition_changed= true; - - List_iterator<Key> it(alter_info->key_list); - Key *key; - while((key= it++) && !*partition_changed) - { - if (key->type == Key::PRIMARY) - *partition_changed= true; - } - } /* Set up partition default_engine_type either from the create_info or from the previus table @@ -6834,7 +6848,7 @@ static void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, partition_info *part_info= lpt->part_info->get_clone(thd); TABLE *table= lpt->table; DBUG_ENTER("handle_alter_part_error"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); /* All instances of this table needs to be closed. @@ -7050,7 +7064,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, /* option_bits is used to mark if we should log the query with IF EXISTS */ ulonglong save_option_bits= thd->variables.option_bits; DBUG_ENTER("fast_alter_partition_table"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); part_info= table->part_info; lpt->thd= thd; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0ccabf87ff5..4750be99d30 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1897,7 +1897,7 @@ static void plugin_load(MEM_ROOT *tmp_root) sql_print_error(ER_THD(new_thd, ER_GET_ERRNO), my_errno, table->file->table_type()); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + table->mark_table_for_reopen(); close_mysql_tables(new_thd); end: new_thd->db= null_clex_str; // Avoid free on thd->db diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0774dc15ef8..2347162ff84 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1036,10 +1036,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) if (vers_conditions.is_set()) { + if (vers_conditions.was_set() && + table->lock_type > TL_READ_NO_INSERT && + !vers_conditions.delete_history) + { + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table->alias.str); + DBUG_RETURN(-1); + } + if (vers_conditions.type == SYSTEM_TIME_ALL) continue; - - lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway } bool timestamps_only= table->table->versioned(VERS_TIMESTAMP); @@ -2768,11 +2774,16 @@ int JOIN::optimize_stage2() } need_tmp= test_if_need_tmp_table(); - //TODO this could probably go in test_if_need_tmp_table. - if (this->select_lex->window_specs.elements > 0) { - need_tmp= TRUE; + + /* + If window functions are present then we can't have simple_order set to + TRUE as the window function needs a temp table for computation. + ORDER BY is computed after the window function computation is done, so + the sort will be done on the temp table. + */ + if (select_lex->have_window_funcs()) simple_order= FALSE; - } + /* If the hint FORCE INDEX FOR ORDER BY/GROUP BY is used for the table diff --git a/sql/sql_select.h b/sql/sql_select.h index 46c84b9df7b..0c832f6d1ff 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1748,6 +1748,7 @@ public: - We are using an ORDER BY or GROUP BY on fields not in the first table - We are using different ORDER BY and GROUP BY orders - The user wants us to buffer the result. + - We are using WINDOW functions. When the WITH ROLLUP modifier is present, we cannot skip temporary table creation for the DISTINCT clause just because there are only const tables. */ @@ -1757,7 +1758,8 @@ public: ((select_distinct || !simple_order || !simple_group) || (group_list && order) || MY_TEST(select_options & OPTION_BUFFER_RESULT))) || - (rollup.state != ROLLUP::STATE_NONE && select_distinct)); + (rollup.state != ROLLUP::STATE_NONE && select_distinct) || + select_lex->have_window_funcs()); } bool choose_subquery_plan(table_map join_tables); void get_partial_cost_and_fanout(int end_tab_idx, diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index dd12cb85558..e351a0332e6 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -354,8 +354,10 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list) seq->reserved_until= seq->start; error= seq->write_initial_sequence(table); - trans_commit_stmt(thd); - trans_commit_implicit(thd); + if (trans_commit_stmt(thd)) + error= 1; + if (trans_commit_implicit(thd)) + error= 1; if (!temporary_table) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c90b8699b80..d748bd959bc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4331,6 +4331,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && + !sql_field->vers_sys_field() && sql_field->is_timestamp_type() && !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && @@ -4470,6 +4471,21 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, Well_formed_prefix(system_charset_info, *comment, max_len).length(); if (tmp_len < comment->length) { + if (comment->length <= max_len) + { + if (thd->is_strict_mode()) + { + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + system_charset_info->csname, comment->str); + DBUG_RETURN(true); + } + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_INVALID_CHARACTER_STRING, + ER_THD(thd, ER_INVALID_CHARACTER_STRING), + system_charset_info->csname, comment->str); + comment->length= tmp_len; + DBUG_RETURN(false); + } if (thd->is_strict_mode()) { my_error(err_code, MYF(0), name, static_cast<ulong>(max_len)); @@ -8056,16 +8072,13 @@ blob_length_by_type(enum_field_types type) } -static void append_drop_column(THD *thd, bool dont, String *str, - Field *field) +static inline +void append_drop_column(THD *thd, String *str, Field *field) { - if (!dont) - { - if (str->length()) - str->append(STRING_WITH_LEN(", ")); - str->append(STRING_WITH_LEN("DROP COLUMN ")); - append_identifier(thd, str, &field->field_name); - } + if (str->length()) + str->append(STRING_WITH_LEN(", ")); + str->append(STRING_WITH_LEN("DROP COLUMN ")); + append_identifier(thd, str, &field->field_name); } @@ -8310,7 +8323,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->invisible < INVISIBLE_SYSTEM) { StringBuffer<NAME_LEN*3> tmp; - append_drop_column(thd, false, &tmp, field); + append_drop_column(thd, &tmp, field); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8406,7 +8419,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->default_value->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); } - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } dropped_sys_vers_fields &= VERS_SYSTEM_FIELD; @@ -8416,10 +8430,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, !vers_system_invisible) { StringBuffer<NAME_LEN*3> tmp; - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_START_FLAG, - &tmp, table->vers_start_field()); - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_END_FLAG, - &tmp, table->vers_end_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_START_FLAG)) + append_drop_column(thd, &tmp, table->vers_start_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_END_FLAG)) + append_drop_column(thd, &tmp, table->vers_end_field()); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8905,7 +8919,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { check->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } new_constraint_list.push_back(check, thd->mem_root); } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 4da85de7852..5df9e7dd47d 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -268,7 +268,9 @@ void udf_init() if (unlikely(error > 0)) sql_print_error("Got unknown error: %d", my_errno); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + + // Force close to free memory + table->mark_table_for_reopen(); end: close_mysql_tables(new_thd); diff --git a/sql/table.cc b/sql/table.cc index 98d299afb37..9273e01572e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -98,8 +98,11 @@ static std::atomic<ulong> last_table_id; /* Functions defined in this file */ -static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, - uint types, char **names); +static bool fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *names, size_t names_length); + static uint find_field(Field **fields, uchar *record, uint start, uint length); inline bool is_system_table_name(const char *name, size_t length); @@ -731,7 +734,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, uint keys, KEY *keyinfo, uint new_frm_ver, uint *ext_key_parts, TABLE_SHARE *share, uint len, - KEY *first_keyinfo, char** keynames) + KEY *first_keyinfo, + LEX_STRING *keynames) { uint i, j, n_length; KEY_PART_INFO *key_part= NULL; @@ -883,10 +887,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, share->ext_key_parts++; share->ext_key_parts+= keyinfo->ext_key_parts; } - *keynames=(char*) key_part; - strpos+= strnmov(*keynames, (char *) strpos, frm_image_end - strpos) - *keynames; + keynames->str= (char*) key_part; + keynames->length= strnmov(keynames->str, (char *) strpos, + frm_image_end - strpos) - keynames->str; + strpos+= keynames->length; if (*strpos++) // key names are \0-terminated return 1; + keynames->length++; // Include '\0', to make fix_type_pointers() happy. //reading index comments for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++) @@ -1698,11 +1705,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, TABLE_SHARE *share= this; uint new_frm_ver, field_pack_length, new_field_pack_flag; uint interval_count, interval_parts, read_length, int_length; + uint total_typelib_value_count; uint db_create_options, keys, key_parts, n_length; uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i, hash_fields= 0; bool use_hash, mysql57_null_bits= 0; - char *keynames, *names, *comment_pos; + LEX_STRING keynames= {NULL, 0}; + char *names, *comment_pos; const uchar *forminfo; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos); @@ -1714,6 +1723,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, KEY_PART_INFO *key_part= NULL; Field **field_ptr, *reg_field; const char **interval_array; + uint *typelib_value_lengths= NULL; enum legacy_db_type legacy_db_type; my_bitmap_map *bitmaps; bool null_bits_are_used; @@ -2133,11 +2143,34 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length)); + /* + We load the following things into TYPELIBs: + - One TYPELIB for field names + - interval_count TYPELIBs for ENUM/SET values + - One TYPELIB for key names + Every TYPELIB requires one extra value with a NULL pointer and zero length, + which is the end-of-values marker. + TODO-10.5+: + Note, we should eventually reuse this total_typelib_value_count + to allocate interval_array. The below code reserves less space + than total_typelib_value_count pointers. So it seems `interval_array` + and `names` overlap in the memory. Too dangerous to fix in 10.1. + */ + total_typelib_value_count= + (share->fields + 1/*end-of-values marker*/) + + (interval_parts + interval_count/*end-of-values markers*/) + + (keys + 1/*end-of-values marker*/); + if (!multi_alloc_root(&share->mem_root, &share->field, (uint)(share->fields+1)*sizeof(Field*), &share->intervals, (uint)interval_count*sizeof(TYPELIB), &share->check_constraints, (uint) share->table_check_constraints * sizeof(Virtual_column_info*), + /* + This looks wrong: shouldn't it be (+2+interval_count) + instread of (+3) ? + */ &interval_array, (uint) (share->fields+interval_parts+ keys+3)*sizeof(char *), + &typelib_value_lengths, total_typelib_value_count * sizeof(uint *), &names, (uint) (n_length+int_length), &comment_pos, (uint) com_length, &vcol_screen_pos, vcol_screen_length, @@ -2164,33 +2197,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length, vcol_screen_length); - fix_type_pointers(&interval_array, &share->fieldnames, 1, &names); - if (share->fieldnames.count != share->fields) + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->fieldnames, 1, names, n_length) || + share->fieldnames.count != share->fields) goto err; - fix_type_pointers(&interval_array, share->intervals, interval_count, &names); - { - /* Set ENUM and SET lengths */ - TYPELIB *interval; - for (interval= share->intervals; - interval < share->intervals + interval_count; - interval++) - { - uint count= (uint) (interval->count + 1) * sizeof(uint); - if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root, - count))) - goto err; - for (count= 0; count < interval->count; count++) - { - char *val= (char*) interval->type_names[count]; - interval->type_lengths[count]= (uint)strlen(val); - } - interval->type_lengths[count]= 0; - } - } + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + share->intervals, interval_count, + names + n_length, int_length)) + goto err; - if (keynames) - fix_type_pointers(&interval_array, &share->keynames, 1, &keynames); + if (keynames.length && + (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->keynames, 1, keynames.str, keynames.length) || + share->keynames.count != keys)) + goto err; /* Allocate handler */ if (!(handler_file= get_new_handler(share, thd->mem_root, @@ -4403,37 +4424,81 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error, ** with a '\0' */ -static void -fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, - char **names) +static bool +fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *ptr, size_t length) { - char *type_name, *ptr; - char chr; + const char *end= ptr + length; - ptr= *names; while (types--) { + char sep; point_to_type->name=0; - point_to_type->type_names= *array; + point_to_type->type_names= *typelib_value_names; + point_to_type->type_lengths= *typelib_value_lengths; - if ((chr= *ptr)) /* Test if empty type */ + /* + Typelib can be encoded as: + 1) 0x00 - empty typelib + 2) 0xFF 0x00 - empty typelib (index names) + 3) sep (value sep)... 0x00 - non-empty typelib (where sep is a separator) + */ + if (length == 2 && ptr[0] == (char) 0xFF && ptr[1] == '\0') + { + /* + This is a special case #2. + If there are no indexes at all, index names can be encoded + as a two byte sequence: 0xFF 0x00 + TODO: Check if it's a bug in the FRM packing routine. + It should probably write just 0x00 instead of 0xFF00. + */ + ptr+= 2; + } + else if ((sep= *ptr++)) // A non-empty typelib { - while ((type_name=strchr(ptr+1,chr)) != NullS) + for ( ; ptr < end; ) { - *((*array)++) = ptr+1; - *type_name= '\0'; /* End string */ - ptr=type_name; + // Now scan the next value+sep pair + char *vend= (char*) memchr(ptr, sep, end - ptr); + if (!vend) + return true; // Bad format + *((*typelib_value_names)++)= ptr; + *((*typelib_value_lengths)++)= (uint) (vend - ptr); + *vend= '\0'; // Change sep to '\0' + ptr= vend + 1; // Shift from sep to the next byte + /* + Now we can have either: + - the end-of-typelib marker (0x00) + - more value+sep pairs + */ + if (!*ptr) + { + /* + We have an ambiguity here. 0x00 can be an end-of-typelib marker, + but it can also be a part of the next value: + CREATE TABLE t1 (a ENUM(0x61, 0x0062) CHARACTER SET BINARY); + If this is the last ENUM/SET in the table and there is still more + packed data left after 0x00, then we know for sure that 0x00 + is a part of the next value. + TODO-10.5+: we should eventually introduce a new unambiguous + typelib encoding for FRM. + */ + if (!types && ptr + 1 < end) + continue; // A binary value starting with 0x00 + ptr++; // Consume the end-of-typelib marker + break; // End of the current typelib + } } - ptr+=2; /* Skip end mark and last 0 */ } - else - ptr++; - point_to_type->count= (uint) (*array - point_to_type->type_names); + point_to_type->count= (uint) (*typelib_value_names - + point_to_type->type_names); point_to_type++; - *((*array)++)= NullS; /* End of type */ + *((*typelib_value_names)++)= NullS; /* End of type */ + *((*typelib_value_lengths)++)= 0; /* End of type */ } - *names=ptr; /* Update end */ - return; + return ptr != end; } /* fix_type_pointers */ @@ -8523,9 +8588,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) int TABLE::update_virtual_field(Field *vf) { - DBUG_ASSERT(!in_use->is_error()); - Query_arena backup_arena; DBUG_ENTER("TABLE::update_virtual_field"); + Query_arena backup_arena; + Counting_error_handler count_errors; + in_use->push_internal_handler(&count_errors); in_use->set_n_backup_active_arena(expr_arena, &backup_arena); bitmap_clear_all(&tmp_set); vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); @@ -8533,7 +8599,8 @@ int TABLE::update_virtual_field(Field *vf) vf->vcol_info->expr->save_in_field(vf, 0); DBUG_RESTORE_WRITE_SET(vf); in_use->restore_active_arena(expr_arena, &backup_arena); - DBUG_RETURN(in_use->is_error()); + in_use->pop_internal_handler(); + DBUG_RETURN(count_errors.errors); } @@ -8858,7 +8925,7 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const for (Field **fld= field; *fld; fld++) { if (!bitmap_is_set(write_set, (*fld)->field_index) && - !((*fld)->flags & NO_DEFAULT_VALUE_FLAG)) + !((*fld)->flags & (NO_DEFAULT_VALUE_FLAG | VERS_SYSTEM_FIELD))) { if (!(*fld)->is_null_in_record(s->default_values) && (*fld)->validate_value_in_record_with_warn(thd, s->default_values) && @@ -9847,3 +9914,14 @@ void TABLE::initialize_quick_structures() bzero(quick_costs, sizeof(quick_costs)); bzero(quick_n_ranges, sizeof(quick_n_ranges)); } + +/* + Mark table to be reopened after query +*/ + +void TABLE::mark_table_for_reopen() +{ + THD *thd= in_use; + DBUG_ASSERT(thd); + thd->locked_tables_list.mark_table_for_reopen(thd, this); +} diff --git a/sql/table.h b/sql/table.h index b1c23337cce..2c7a042be69 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1395,8 +1395,8 @@ public: bool insert_or_update; /* Can be used by the handler */ bool alias_name_used; /* true if table_name is alias */ bool get_fields_in_item_tree; /* Signal to fix_field */ - bool m_needs_reopen; private: + bool m_needs_reopen; bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: #ifdef HAVE_REPLICATION @@ -1507,6 +1507,16 @@ public: /** Should this instance of the table be reopened? */ inline bool needs_reopen() { return !db_stat || m_needs_reopen; } + /* + Mark that all current connection instances of the table should be + reopen at end of statement + */ + void mark_table_for_reopen(); + /* Should only be called from Locked_tables_list::mark_table_for_reopen() */ + void internal_set_needs_reopen(bool value) + { + m_needs_reopen= value; + } bool alloc_keys(uint key_count); bool check_tmp_key(uint key, uint key_parts, diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 521b9c8973f..203571441fc 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -1070,7 +1070,7 @@ TABLE *THD::find_temporary_table(const char *key, uint key_length, case TMP_TABLE_ANY: found= true; break; } } - if (table && unlikely(table->m_needs_reopen)) + if (table && unlikely(table->needs_reopen())) { share->all_tmp_tables.remove(table); free_temporary_table(table); diff --git a/sql/tztime.cc b/sql/tztime.cc index 9797b1d4a22..b1c0c79d5d7 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1699,7 +1699,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) { tl->table->use_all_columns(); /* Force close at the end of the function to free memory. */ - tl->table->m_needs_reopen= TRUE; + tl->table->mark_table_for_reopen(); } /* diff --git a/sql/unireg.cc b/sql/unireg.cc index 6860d2c6347..fa193a7712d 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, 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 @@ -787,6 +787,18 @@ static bool pack_vcols(String *buf, List<Create_field> &create_fields, } +static uint typelib_values_packed_length(const TYPELIB *t) +{ + uint length= 0; + for (uint i= 0; t->type_names[i]; i++) + { + length+= t->type_lengths[i]; + length++; /* Separator */ + } + return length; +} + + /* Make formheader */ static bool pack_header(THD *thd, uchar *forminfo, @@ -881,9 +893,8 @@ static bool pack_header(THD *thd, uchar *forminfo, field->interval_id=get_interval_id(&int_count,create_fields,field); if (old_int_count != int_count) { - for (const char **pos=field->interval->type_names ; *pos ; pos++) - int_length+=(uint) strlen(*pos)+1; // field + suffix prefix - int_parts+=field->interval->count+1; + int_length+= typelib_values_packed_length(field->interval); + int_parts+= field->interval->count + 1; } } if (f_maybe_null(field->pack_flag)) @@ -972,11 +983,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields) { int_count= field->interval_id; length++; - for (int i=0; field->interval->type_names[i]; i++) - { - length+= field->interval->type_lengths[i]; - length++; - } + length+= typelib_values_packed_length(field->interval); length++; } @@ -1100,9 +1107,10 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, static bool make_empty_rec_store_default(THD *thd, Field *regfield, - Virtual_column_info *default_value) + Create_field *field) { - if (default_value && !default_value->flags) + Virtual_column_info *default_value= field->default_value; + if (!field->vers_sys_field() && default_value && !default_value->flags) { Item *expr= default_value->expr; // may be already fixed if ALTER TABLE @@ -1184,7 +1192,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, !f_bit_as_char(field->pack_flag)) null_count+= field->length & 7; - error= make_empty_rec_store_default(thd, regfield, field->default_value); + error= make_empty_rec_store_default(thd, regfield, field); delete regfield; // Avoid memory leaks if (error) goto err; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index fef349bbaaf..6547964cc11 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3625,6 +3625,9 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, char buf[1024]; String query(buf, sizeof(buf), cs); static LEX_CSTRING cut_clause={STRING_WITH_LEN(" WITH SYSTEM VERSIONING")}; + static LEX_CSTRING cut_start={STRING_WITH_LEN("GENERATED ALWAYS AS ROW START")}; + static LEX_CSTRING cut_end={STRING_WITH_LEN("GENERATED ALWAYS AS ROW END")}; + static LEX_CSTRING set_ts={STRING_WITH_LEN("DEFAULT TIMESTAMP'1971-01-01 00:00:00'")}; int cut_offset; MYSQL_RES *res; MYSQL_ROW rdata; @@ -3663,7 +3666,21 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, cut_offset= (int)query.length() - (int)cut_clause.length; if (cut_offset > 0 && !memcmp(query.ptr() + cut_offset, cut_clause.str, cut_clause.length)) + { query.length(cut_offset); + const char *ptr= strstr(query.ptr(), cut_start.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_start.length, + set_ts.str, (uint32) set_ts.length); + } + ptr= strstr(query.ptr(), cut_end.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_end.length, + set_ts.str, (uint32) set_ts.length); + } + } query.append(STRING_WITH_LEN(" CONNECTION='"), cs); query.append_for_single_quote(table_s->connect_string.str, table_s->connect_string.length); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index e253b692778..309eed4e597 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2164,7 +2164,7 @@ static void fil_crypt_rotation_list_fill() space != NULL; space = UT_LIST_GET_NEXT(space_list, space)) { if (space->purpose != FIL_TYPE_TABLESPACE - || space->is_in_rotation_list() + || space->is_in_rotation_list || space->is_stopping() || UT_LIST_GET_LEN(space->chain) == 0) { continue; @@ -2211,6 +2211,7 @@ static void fil_crypt_rotation_list_fill() } fil_system.rotation_list.push_back(*space); + space->is_in_rotation_list = true; } } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 4b61edaccc3..844291db939 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -682,7 +682,7 @@ static void fil_flush_low(fil_space_t* space, bool metadata = false) /* No need to flush. User has explicitly disabled buffering. */ - ut_ad(!space->is_in_unflushed_spaces()); + ut_ad(!space->is_in_unflushed_spaces); ut_ad(fil_space_is_flushed(space)); ut_ad(space->n_pending_flushes == 0); @@ -735,10 +735,11 @@ static void fil_flush_low(fil_space_t* space, bool metadata = false) skip_flush: #endif /* _WIN32 */ if (!node->needs_flush) { - if (space->is_in_unflushed_spaces() + if (space->is_in_unflushed_spaces && fil_space_is_flushed(space)) { fil_system.unflushed_spaces.remove(*space); + space->is_in_unflushed_spaces = false; } } @@ -1008,13 +1009,14 @@ fil_node_close_to_free( if (fil_buffering_disabled(space)) { - ut_ad(!space->is_in_unflushed_spaces()); + ut_ad(!space->is_in_unflushed_spaces); ut_ad(fil_space_is_flushed(space)); - } else if (space->is_in_unflushed_spaces() + } else if (space->is_in_unflushed_spaces && fil_space_is_flushed(space)) { fil_system.unflushed_spaces.remove(*space); + space->is_in_unflushed_spaces = false; } node->close(); @@ -1034,14 +1036,16 @@ fil_space_detach( HASH_DELETE(fil_space_t, hash, fil_system.spaces, space->id, space); - if (space->is_in_unflushed_spaces()) { + if (space->is_in_unflushed_spaces) { ut_ad(!fil_buffering_disabled(space)); fil_system.unflushed_spaces.remove(*space); + space->is_in_unflushed_spaces = false; } - if (space->is_in_rotation_list()) { + if (space->is_in_rotation_list) { fil_system.rotation_list.remove(*space); + space->is_in_rotation_list = false; } UT_LIST_REMOVE(fil_system.space_list, space); @@ -1256,6 +1260,7 @@ fil_space_create( /* Key rotation is not enabled, need to inform background encryption threads. */ fil_system.rotation_list.push_back(*space); + space->is_in_rotation_list = true; mutex_exit(&fil_system.mutex); os_event_set(fil_crypt_threads_event); } else { @@ -3821,13 +3826,14 @@ fil_node_complete_io(fil_node_t* node, const IORequest& type) /* We don't need to keep track of unflushed changes as user has explicitly disabled buffering. */ - ut_ad(!node->space->is_in_unflushed_spaces()); + ut_ad(!node->space->is_in_unflushed_spaces); ut_ad(node->needs_flush == false); } else { node->needs_flush = true; - if (!node->space->is_in_unflushed_spaces()) { + if (!node->space->is_in_unflushed_spaces) { + node->space->is_in_unflushed_spaces = true; fil_system.unflushed_spaces.push_front( *node->space); } @@ -4242,7 +4248,7 @@ void fil_flush_file_spaces() n_space_ids = 0; - for (intrusive::list<fil_space_t, unflushed_spaces_tag_t>::iterator it + for (sized_ilist<fil_space_t, unflushed_spaces_tag_t>::iterator it = fil_system.unflushed_spaces.begin(), end = fil_system.unflushed_spaces.end(); it != end; ++it) { @@ -4629,7 +4635,8 @@ fil_space_remove_from_keyrotation(fil_space_t* space) ut_ad(mutex_own(&fil_system.mutex)); ut_ad(space); - if (!space->referenced() && space->is_in_rotation_list()) { + if (!space->referenced() && space->is_in_rotation_list) { + space->is_in_rotation_list = false; ut_a(!fil_system.rotation_list.empty()); fil_system.rotation_list.remove(*space); } @@ -4659,8 +4666,8 @@ fil_space_t *fil_system_t::keyrotate_next(fil_space_t *prev_space, don't remove the last processed tablespace from the rotation list. */ const bool remove= (!recheck || prev_space->crypt_data) && !key_version == !srv_encrypt_tables; - intrusive::list<fil_space_t, rotation_list_tag_t>::iterator it= - prev_space == NULL ? fil_system.rotation_list.end() : prev_space; + sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= + prev_space ? prev_space : fil_system.rotation_list.end(); if (it == fil_system.rotation_list.end()) it= fil_system.rotation_list.begin(); @@ -4737,24 +4744,3 @@ fil_space_found_by_id( mutex_exit(&fil_system.mutex); return space; } - -/** Checks that this tablespace in a list of unflushed tablespaces. -@return true if in a list */ -bool fil_space_t::is_in_unflushed_spaces() const -{ - ut_ad(mutex_own(&fil_system.mutex)); - - return static_cast<const intrusive::list_node<unflushed_spaces_tag_t> *>( - this) - ->next; -} - -/** Checks that this tablespace needs key rotation. -@return true if in a rotation list */ -bool fil_space_t::is_in_rotation_list() const -{ - ut_ad(mutex_own(&fil_system.mutex)); - - return static_cast<const intrusive::list_node<rotation_list_tag_t> *>(this) - ->next; -} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 89f09ec95c3..c908b033cb5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3192,7 +3192,7 @@ ha_innobase::reset_template(void) /* Force table to be freed in close_thread_table(). */ DBUG_EXECUTE_IF("free_table_in_fts_query", if (m_prebuilt->in_fts_query) { - table->m_needs_reopen = true; + table->mark_table_for_reopen(); } ); @@ -4819,9 +4819,8 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) { DBUG_ENTER("innobase_kill_query"); - if (trx_t *trx= thd_to_trx(thd)) + if (trx_t* trx= thd_to_trx(thd)) { - ut_ad(trx->mysql_thd == thd); #ifdef WITH_WSREP if (trx->is_wsrep() && wsrep_thd_is_aborting(thd)) /* if victim has been signaled by BF thread and/or aborting is already @@ -4829,8 +4828,29 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) Also, BF thread should own trx mutex for the victim. */ DBUG_VOID_RETURN; #endif /* WITH_WSREP */ - /* Cancel a pending lock request if there are any */ - lock_trx_handle_wait(trx); + lock_mutex_enter(); + mutex_enter(&trx_sys.mutex); + trx_mutex_enter(trx); + /* It is possible that innobase_close_connection() is concurrently + being executed on our victim. Even if the trx object is later + reused for another client connection or a background transaction, + its trx->mysql_thd will differ from our thd. + + trx_t::state changes are protected by trx_t::mutex, and + trx_sys.trx_list is protected by trx_sys.mutex, in + both trx_create() and trx_free(). + + At this point, trx may have been reallocated for another client + connection, or for a background operation. In that case, either + trx_t::state or trx_t::mysql_thd should not match our expectations. */ + bool cancel= trx->mysql_thd == thd && trx->state == TRX_STATE_ACTIVE && + !trx->lock.was_chosen_as_deadlock_victim; + mutex_exit(&trx_sys.mutex); + if (!cancel); + else if (lock_t *lock= trx->lock.wait_lock) + lock_cancel_waiting_and_release(lock); + lock_mutex_exit(); + trx_mutex_exit(trx); } DBUG_VOID_RETURN; diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 0984b464049..731ff545685 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1210,7 +1210,7 @@ public: @param whether to reset fields[].col */ void detach_columns(bool clear= false) { - if (!has_virtual()) + if (!has_virtual() || !cached) return; for (unsigned i= 0; i < n_fields; i++) { diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index ffe9b5d21dc..e89733fc9ed 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -29,7 +29,7 @@ Created 2013-03-16 Sunny Bains #include "mem0mem.h" #include "dyn0types.h" -#include "intrusive_list.h" +#include "ilist.h" /** Class that manages dynamic buffers. It uses a UT_LIST of @@ -43,9 +43,9 @@ class mtr_buf_t { public: /** SIZE - sizeof(m_node) + sizeof(m_used) */ enum { MAX_DATA_SIZE = DYN_ARRAY_DATA_SIZE - - sizeof(intrusive::list_node<>) + sizeof(uint32_t) }; + - sizeof(ilist_node<>) + sizeof(uint32_t) }; - class block_t : public intrusive::list_node<> { + class block_t : public ilist_node<> { public: block_t() @@ -160,7 +160,7 @@ public: friend class mtr_buf_t; }; - typedef intrusive::list<block_t> list_t; + typedef sized_ilist<block_t> list_t; /** Default constructor */ mtr_buf_t() diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 858abaab368..1832fd18afe 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -36,7 +36,7 @@ Created 10/25/1995 Heikki Tuuri #include "hash0hash.h" #include "log0recv.h" #include "dict0types.h" -#include "intrusive_list.h" +#include "ilist.h" #ifdef UNIV_LINUX # include <set> #endif @@ -68,8 +68,8 @@ struct fil_node_t; /** Tablespace or log data space */ #ifndef UNIV_INNOCHECKSUM -struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>, - intrusive::list_node<rotation_list_tag_t> +struct fil_space_t : ilist_node<unflushed_spaces_tag_t>, + ilist_node<rotation_list_tag_t> #else struct fil_space_t #endif @@ -137,18 +137,18 @@ struct fil_space_t UT_LIST_NODE_T(fil_space_t) named_spaces; /*!< list of spaces for which FILE_MODIFY records have been issued */ - /** Checks that this tablespace in a list of unflushed tablespaces. - @return true if in a list */ - bool is_in_unflushed_spaces() const; UT_LIST_NODE_T(fil_space_t) space_list; /*!< list of all spaces */ - /** Checks that this tablespace needs key rotation. - @return true if in a rotation list */ - bool is_in_rotation_list() const; /** MariaDB encryption data */ fil_space_crypt_t* crypt_data; + /** Checks that this tablespace in a list of unflushed tablespaces. */ + bool is_in_unflushed_spaces; + + /** Checks that this tablespace needs key rotation. */ + bool is_in_rotation_list; + /** True if the device this filespace is on supports atomic writes */ bool atomic_write_supported; @@ -920,7 +920,7 @@ public: not put to this list: they are opened after the startup, and kept open until shutdown */ - intrusive::list<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces; + sized_ilist<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces; /*!< list of those tablespaces whose files contain unflushed writes; those spaces have @@ -941,7 +941,7 @@ public: record has been written since the latest redo log checkpoint. Protected only by log_sys.mutex. */ - intrusive::list<fil_space_t, rotation_list_tag_t> rotation_list; + ilist<fil_space_t, rotation_list_tag_t> rotation_list; /*!< list of all file spaces needing key rotation.*/ diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index cb8436d8f89..e18d565b565 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -355,7 +355,8 @@ rw_lock_s_unlock_func( ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S)); /* Increment lock_word to indicate 1 less reader */ - int32_t lock_word = lock->lock_word.fetch_add(1); + int32_t lock_word = lock->lock_word.fetch_add( + 1, std::memory_order_release); if (lock_word == -1 || lock_word == -X_LOCK_HALF_DECR - 1) { /* wait_ex waiter exists. It may not be asleep, but we signal diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index 02a4e16bb70..f6006144dc4 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved. +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 @@ -86,11 +87,15 @@ 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_UNDEFINED(&elem->m_type, sizeof elem->m_type); +#endif +#ifdef HAVE_valgrind /* Declare the contents as initialized for Valgrind; we checked this in mem_free(). */ UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); +#endif Factory::destroy(&elem->m_type); } @@ -127,13 +132,18 @@ struct Pool { #if defined HAVE_valgrind || defined __SANITIZE_ADDRESS__ if (elem) { +# ifdef __SANITIZE_ADDRESS__ /* Unpoison the memory for AddressSanitizer */ MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); +# endif +# ifdef HAVE_valgrind + /* Declare the memory initialized for Valgrind. The trx_t that are released to the pool are actually initialized; we checked that by UNIV_MEM_ASSERT_RW() in mem_free() below. */ UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); +# endif } #endif diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index a654f221f38..1e5362180ba 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1178,19 +1178,15 @@ row_log_table_get_pk_col( return(DB_INVALID_NULL); } - ulint new_i = dict_col_get_clust_pos(ifield->col, index); - - if (UNIV_UNLIKELY(new_i >= log->defaults->n_fields)) { - ut_ad(0); - return DB_INVALID_NULL; - } + unsigned col_no= ifield->col->ind; + ut_ad(col_no < log->defaults->n_fields); field = static_cast<const byte*>( - log->defaults->fields[new_i].data); + log->defaults->fields[col_no].data); if (!field) { return(DB_INVALID_NULL); } - len = log->defaults->fields[new_i].len; + len = log->defaults->fields[col_no].len; } if (rec_offs_nth_extern(offsets, i)) { @@ -1672,10 +1668,12 @@ blob_done: const dfield_t& default_field = log->defaults->fields[col_no]; - Field* field = log->old_table->field[col_no]; + + Field* field = log->old_table->field[col->ind]; field->set_warning(Sql_condition::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1, ulong(log->n_rows)); + WARN_DATA_TRUNCATED, 1, + ulong(log->n_rows)); if (!log->allow_not_null) { /* We got a NULL value for a NOT NULL column. */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index b48fed97872..d77de6b03e2 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -451,13 +451,31 @@ void trx_free(trx_t*& trx) 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_UNDEFINED(&trx->mutex, sizeof trx->mutex); - /* Declare the contents as initialized for Valgrind; - we checked that it was initialized in trx_pools->mem_free(trx). */ + /* For innobase_kill_connection() */ +# ifdef WITH_WSREP + MEM_UNDEFINED(&trx->wsrep, sizeof trx->wsrep); +# endif + MEM_UNDEFINED(&trx->state, sizeof trx->state); + MEM_UNDEFINED(&trx->mysql_thd, sizeof trx->mysql_thd); +#endif +#ifdef HAVE_valgrind + /* Unpoison the memory for innodb_monitor_set_option; + it is operating also on the freed transaction objects. + We checked that these were initialized in + trx_pools->mem_free(trx). */ UNIV_MEM_VALID(&trx->mutex, sizeof trx->mutex); - trx->read_view.mem_valid(); + /* For innobase_kill_connection() */ +# ifdef WITH_WSREP + UNIV_MEM_VALID(&trx->wsrep, sizeof trx->wsrep); +# endif + UNIV_MEM_VALID(&trx->state, sizeof trx->state); + UNIV_MEM_VALID(&trx->mysql_thd, sizeof trx->mysql_thd); +#endif trx = NULL; } @@ -1471,12 +1489,6 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) if (fts_trx) trx_finalize_for_fts(this, undo_no != 0); - trx_mutex_enter(this); - dict_operation= TRX_DICT_OP_NONE; - - DBUG_LOG("trx", "Commit in memory: " << this); - state= TRX_STATE_NOT_STARTED; - #ifdef WITH_WSREP /* Serialization history has been written and the transaction is committed in memory, which makes this commit ordered. Release commit @@ -1488,6 +1500,11 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) } lock.was_chosen_as_wsrep_victim= false; #endif /* WITH_WSREP */ + trx_mutex_enter(this); + dict_operation= TRX_DICT_OP_NONE; + + DBUG_LOG("trx", "Commit in memory: " << this); + state= TRX_STATE_NOT_STARTED; assert_freed(); trx_init(this); diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 746f46f76ba..aa5c598c9c9 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -967,6 +967,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) char *old_name, *new_name; int error= 1; MARIA_HA *info= NULL; + my_bool from_table_is_crashed= 0; DBUG_ENTER("exec_REDO_LOGREC_REDO_RENAME_TABLE"); if (skip_DDLs) @@ -1036,15 +1037,15 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) } if (maria_is_crashed(info)) { - tprint(tracef, ", is crashed, can't rename it"); - ALERT_USER(); - goto end; + tprint(tracef, "is crashed, can't be used for rename ; new-name table "); + from_table_is_crashed= 1; } if (close_one_table(info->s->open_file_name.str, rec->lsn) || maria_close(info)) goto end; info= NULL; - tprint(tracef, ", is ok for renaming; new-name table "); + if (!from_table_is_crashed) + tprint(tracef, "is ok for renaming; new-name table "); } else /* one or two files absent, or header corrupted... */ { @@ -1109,11 +1110,19 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) goto end; info= NULL; /* abnormal situation */ - tprint(tracef, ", exists but is older than record, can't rename it"); + tprint(tracef, "exists but is older than record, can't rename it"); goto end; } else /* one or two files absent, or header corrupted... */ - tprint(tracef, ", can't be opened, probably does not exist"); + tprint(tracef, "can't be opened, probably does not exist"); + + if (from_table_is_crashed) + { + eprint(tracef, "Aborting rename as old table was crashed"); + ALERT_USER(); + goto end; + } + tprint(tracef, ", renaming '%s'", old_name); if (maria_rename(old_name, new_name)) { diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index cdc34bb2438..58e6d5e083b 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -335,12 +335,6 @@ err: my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM) { - if (info->bulk_insert) - { - uint j; - for (j=0 ; j < share->base.keys ; j++) - maria_flush_bulk_insert(info, j); - } info->errkey= i < share->base.keys ? (int) i : -1; /* We delete keys in the reverse order of insertion. This is the order that @@ -366,6 +360,7 @@ err: { if (_ma_ft_del(info,i,buff,record,filepos)) { + fatal_error= 1; if (local_lock_tree) mysql_rwlock_unlock(&keyinfo->root_lock); break; @@ -380,6 +375,7 @@ err: filepos, info->trn->trid))) { + fatal_error= 1; if (local_lock_tree) mysql_rwlock_unlock(&keyinfo->root_lock); break; @@ -399,6 +395,13 @@ err: fatal_error= 1; } + if (info->bulk_insert) + { + uint j; + for (j=0 ; j < share->base.keys ; j++) + maria_flush_bulk_insert(info, j); + } + if (fatal_error) { maria_print_error(info->s, HA_ERR_CRASHED); diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c index 25d7d216e1e..46f3f783e59 100644 --- a/storage/mroonga/vendor/groonga/lib/db.c +++ b/storage/mroonga/vendor/groonga/lib/db.c @@ -445,6 +445,9 @@ grn_db_close(grn_ctx *ctx, grn_obj *db) ctx_used_db = ctx->impl && ctx->impl->db == db; if (ctx_used_db) { +#ifdef GRN_WITH_MECAB + grn_db_fin_mecab_tokenizer(ctx); +#endif grn_ctx_loader_clear(ctx); if (ctx->impl->parser) { grn_expr_parser_close(ctx); diff --git a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h index e90dbfc0b31..81ac2ab6c46 100644 --- a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h +++ b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h @@ -30,6 +30,7 @@ grn_rc grn_tokenizers_init(void); grn_rc grn_tokenizers_fin(void); grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx); +void grn_db_fin_mecab_tokenizer(grn_ctx *ctx); grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx); #ifdef __cplusplus diff --git a/storage/mroonga/vendor/groonga/lib/tokenizers.c b/storage/mroonga/vendor/groonga/lib/tokenizers.c index 11f274e72db..3daacce7ef9 100644 --- a/storage/mroonga/vendor/groonga/lib/tokenizers.c +++ b/storage/mroonga/vendor/groonga/lib/tokenizers.c @@ -797,6 +797,36 @@ grn_db_init_mecab_tokenizer(grn_ctx *ctx) } } +void +grn_db_fin_mecab_tokenizer(grn_ctx *ctx) +{ + switch (GRN_CTX_GET_ENCODING(ctx)) { + case GRN_ENC_EUC_JP : + case GRN_ENC_UTF8 : + case GRN_ENC_SJIS : +#if defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) + { + GRN_PLUGIN_DECLARE_FUNCTIONS(tokenizers_mecab); + GRN_PLUGIN_IMPL_NAME_TAGGED(fin, tokenizers_mecab)(ctx); + } +#else /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + { + const char *mecab_plugin_name = "tokenizers/mecab"; + char *path; + path = grn_plugin_find_path(ctx, mecab_plugin_name); + if (path) { + GRN_FREE(path); + grn_plugin_unregister(ctx, mecab_plugin_name); + } + } +#endif /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + break; + default : + break; + } + return; +} + #define DEF_TOKENIZER(name, init, next, fin, vars)\ (grn_proc_create(ctx, (name), (sizeof(name) - 1),\ GRN_PROC_TOKENIZER, (init), (next), (fin), 3, (vars))) diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c index 3dd969a89c5..cabf2c94e53 100644 --- a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c +++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c @@ -31,6 +31,7 @@ #include <string.h> #include <ctype.h> +static unsigned int sole_mecab_init_counter = 0; static mecab_t *sole_mecab = NULL; static grn_plugin_mutex *sole_mecab_mutex = NULL; static grn_encoding sole_mecab_encoding = GRN_ENC_NONE; @@ -563,6 +564,11 @@ check_mecab_dictionary_encoding(grn_ctx *ctx) grn_rc GRN_PLUGIN_INIT(grn_ctx *ctx) { + ++sole_mecab_init_counter; + if (sole_mecab_init_counter > 1) + { + return GRN_SUCCESS; + } { char env[GRN_ENV_BUFFER_SIZE]; @@ -636,6 +642,11 @@ GRN_PLUGIN_REGISTER(grn_ctx *ctx) grn_rc GRN_PLUGIN_FIN(grn_ctx *ctx) { + --sole_mecab_init_counter; + if (sole_mecab_init_counter > 0) + { + return GRN_SUCCESS; + } if (sole_mecab) { mecab_destroy(sole_mecab); sole_mecab = NULL; diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 88c6a4837e4..b2605cf5d2f 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1587,6 +1587,8 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info, sort_param.filepos=new_header_length; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; sort_info.dupp=0; sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master=1; @@ -2292,6 +2294,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, sort_info.buff=0; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(param->read_cache.file, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; sort_param.wordlist=NULL; init_alloc_root(mi_key_memory_MI_SORT_PARAM_wordroot, &sort_param.wordroot, @@ -2759,6 +2763,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, sort_info.buff=0; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(param->read_cache.file, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; if (share->data_file_type == DYNAMIC_RECORD) rec_length=MY_MAX(share->base.min_pack_length+1,share->base.min_block_length); diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake index 1a3b2076c82..2e939587811 100644 --- a/storage/rocksdb/build_rocksdb.cmake +++ b/storage/rocksdb/build_rocksdb.cmake @@ -67,7 +67,7 @@ if(SNAPPY_FOUND AND (NOT WITH_ROCKSDB_snappy STREQUAL "OFF")) endif() include(CheckFunctionExists) -if(ZSTD_FOUND AND (NOT WITH_ROCKSDB_zstd STREQUAL "OFF")) +if(ZSTD_FOUND AND (NOT WITH_ROCKSDB_ZSTD STREQUAL "OFF")) SET(CMAKE_REQUIRED_LIBRARIES zstd) CHECK_FUNCTION_EXISTS(ZDICT_trainFromBuffer ZSTD_VALID) UNSET(CMAKE_REQUIRED_LIBRARIES) diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 5d349f6fcce..49e3c8df550 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -114,7 +114,6 @@ int thd_binlog_format(const MYSQL_THD thd); bool thd_binlog_filter_ok(const MYSQL_THD thd); } -MYSQL_PLUGIN_IMPORT bool my_disable_leak_check; extern my_bool opt_core_file; // Needed in rocksdb_init_func @@ -5727,13 +5726,6 @@ static int rocksdb_init_func(void *const p) { } #endif - /** - Rocksdb does not always shutdown its threads, when - plugin is shut down. Disable server's leak check - at exit to avoid crash. - */ - my_disable_leak_check = true; - err = my_error_register(rdb_get_error_messages, HA_ERR_ROCKSDB_FIRST, HA_ERR_ROCKSDB_LAST); if (err != 0) { diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index 6b7af39d51d..b1ba00c6aca 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -224,7 +224,8 @@ err: */ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end, - size_t width, char *par, uint print_type) + size_t width, char *par, uint print_type, + my_bool nice_cut) { int well_formed_error; uint dots= 0; @@ -232,24 +233,34 @@ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end, if (!par) par = (char*) "(null)"; - plen= slen= strnlen(par, width + 1); - if (plen > width) - plen= width; - if (left_len <= plen) - plen = left_len - 1; - if ((slen > plen)) + if (nice_cut) { - if (plen < 3) + plen= slen= strnlen(par, width + 1); + if (plen > width) + plen= width; + if (left_len <= plen) + plen = left_len - 1; + if ((slen > plen)) { - dots= (uint) plen; - plen= 0; - } - else - { - dots= 3; - plen-= 3; + if (plen < 3) + { + dots= (uint) plen; + plen= 0; + } + else + { + dots= 3; + plen-= 3; + } } } + else + { + plen= slen= strnlen(par, width); + dots= 0; + if (left_len <= plen) + plen = left_len - 1; + } plen= my_well_formed_length(cs, par, par + plen, width, &well_formed_error); if (print_type & ESCAPED_ARG) @@ -446,6 +457,7 @@ start: switch (args_arr[i].arg_type) { case 's': case 'b': + case 'T': args_arr[i].str_arg= va_arg(ap, char *); break; case 'f': @@ -480,12 +492,14 @@ start: size_t width= 0, length= 0; switch (print_arr[i].arg_type) { case 's': + case 'T': { char *par= args_arr[print_arr[i].arg_idx].str_arg; width= (print_arr[i].flags & WIDTH_ARG) ? (size_t)args_arr[print_arr[i].width].longlong_arg : print_arr[i].width; - to= process_str_arg(cs, to, end, width, par, print_arr[i].flags); + to= process_str_arg(cs, to, end, width, par, print_arr[i].flags, + (print_arr[i].arg_type == 'T')); break; } case 'b': @@ -552,7 +566,7 @@ start: *to++= '"'; my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg); to= process_str_arg(cs, to, real_end, width, errmsg_buff, - print_arr[i].flags); + print_arr[i].flags, 1); if (real_end > to) *to++= '"'; } break; @@ -676,10 +690,10 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, fmt= check_longlong(fmt, &have_longlong); - if (*fmt == 's') /* String parameter */ + if (*fmt == 's' || *fmt == 'T') /* String parameter */ { reg2 char *par= va_arg(ap, char *); - to= process_str_arg(cs, to, end, width, par, print_type); + to= process_str_arg(cs, to, end, width, par, print_type, (*fmt == 'T')); continue; } else if (*fmt == 'b') /* Buffer parameter */ @@ -731,7 +745,8 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, *to++= ' '; *to++= '"'; my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg); - to= process_str_arg(cs, to, real_end, width, errmsg_buff, print_type); + to= process_str_arg(cs, to, real_end, width, errmsg_buff, + print_type, 1); if (real_end > to) *to++= '"'; } continue; diff --git a/unittest/mysys/my_vsnprintf-t.c b/unittest/mysys/my_vsnprintf-t.c index 872e88ddd7e..1a0b4080a2d 100644 --- a/unittest/mysys/my_vsnprintf-t.c +++ b/unittest/mysys/my_vsnprintf-t.c @@ -61,7 +61,7 @@ static void test_many(const char **res, const char *fmt, ...) int main(void) { - plan(43); + plan(47); test1("Constant string", "Constant string"); @@ -99,27 +99,33 @@ int main(void) test1("Width is ignored for strings <x> <y>", "Width is ignored for strings <%04s> <%5s>", "x", "y"); - test1("Precision works for strings <ab...>", + test1("Precision works for strings <abcde>", "Precision works for strings <%.5s>", "abcdef!"); + test1("Precision works for strings <ab...>", + "Precision works for strings <%.5T>", "abcdef!"); + + test1("Flag '`' (backtick) works: `abcd` `op``q` (mysql extension)", + "Flag '`' (backtick) works: %`s %`.4s (mysql extension)", + "abcd", "op`qrst"); test1("Flag '`' (backtick) works: `abcd` `op``q...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.7s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.7T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `.` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.1s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.1T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.3s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.3T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `op...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.5s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.5T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `op``...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.6s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.6T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Length modifiers work: 1 * -1 * 2 * 3", @@ -141,15 +147,21 @@ int main(void) test1("Asterisk '*' as a width works: < 4>", "Asterisk '*' as a width works: <%*d>", 5, 4); - test1("Asterisk '*' as a precision works: <qwe...>", + test1("Asterisk '*' as a precision works: <qwerty>", "Asterisk '*' as a precision works: <%.*s>", 6, "qwertyuiop"); + test1("Asterisk '*' as a precision works: <qwe...>", + "Asterisk '*' as a precision works: <%.*T>", 6, "qwertyuiop"); + test1("Positional arguments for a width: < 4>", "Positional arguments for a width: <%1$*2$d>", 4, 5); - test1("Positional arguments for a precision: <qwe...>", + test1("Positional arguments for a precision: <qwerty>", "Positional arguments for a precision: <%1$.*2$s>", "qwertyuiop", 6); + test1("Positional arguments for a precision: <qwe...>", + "Positional arguments for a precision: <%1$.*2$T>", "qwertyuiop", 6); + test1("Positional arguments and a width: <0000ab>", "Positional arguments and a width: <%1$06x>", 0xab); diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index 1a4abc754e8..761225a695c 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #undef NOMINMAX #include <winsock2.h> +#include <ws2tcpip.h> #include <windows.h> #include <winreg.h> #include <msi.h> @@ -41,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ using namespace std; + #define ONE_MB 1048576 UINT ExecRemoveDataDirectory(wchar_t *dir) { @@ -264,36 +266,89 @@ bool ExecRemoveService(const wchar_t *name) return ret; } -/* - Check if port is free by trying to bind to the port -*/ -bool IsPortFree(short port) +/* Find whether TCP port is in use by trying to bind to the port. */ +static bool IsPortInUse(unsigned short port) { - WORD wVersionRequested; - WSADATA wsaData; - - wVersionRequested = MAKEWORD(2, 2); + struct addrinfo* ai, * a; + struct addrinfo hints {}; - WSAStartup(wVersionRequested, &wsaData); + char port_buf[NI_MAXSERV]; + SOCKET ip_sock = INVALID_SOCKET; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + snprintf(port_buf, NI_MAXSERV, "%u", (unsigned)port); - struct sockaddr_in sin; - SOCKET sock; - sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock == INVALID_SOCKET) + if (getaddrinfo(NULL, port_buf, &hints, &ai)) { return false; } - sin.sin_port = htons(port); - sin.sin_addr.s_addr = 0; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_family = AF_INET; - if(bind(sock, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) == -1) + + /* + Prefer IPv6 socket to IPv4, since we'll use IPv6 dual socket, + which coveres both IP versions. + */ + for (a = ai; a; a = a->ai_next) + { + if (a->ai_family == AF_INET6 && + (ip_sock = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) != INVALID_SOCKET) + { + break; + } + } + + if (ip_sock == INVALID_SOCKET) + { + for (a = ai; a; a = a->ai_next) + { + if (ai->ai_family == AF_INET && + (ip_sock = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) != INVALID_SOCKET) + { + break; + } + } + } + + if (ip_sock == INVALID_SOCKET) { return false; } - closesocket(sock); + + /* Use SO_EXCLUSIVEADDRUSE to prevent multiple binding. */ + int arg = 1; + setsockopt(ip_sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&arg, sizeof(arg)); + + /* Allow dual socket, so that IPv4 and IPv6 are both covered.*/ + if (a->ai_family == AF_INET6) + { + arg = 0; + setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, sizeof(arg)); + } + + bool in_use = false; + if (bind(ip_sock, a->ai_addr, a->ai_addrlen) == SOCKET_ERROR) + { + DWORD last_error = WSAGetLastError(); + in_use = (last_error == WSAEADDRINUSE || last_error == WSAEACCES); + } + + freeaddrinfo(ai); + closesocket(ip_sock); + return in_use; +} + + +/* + Check if TCP port is free +*/ +bool IsPortFree(unsigned short port) +{ + WORD wVersionRequested = MAKEWORD(2, 2); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); + bool in_use = IsPortInUse(port); WSACleanup(); - return true; + return !in_use; } @@ -650,7 +705,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall) goto LExit; } - short port = (short)_wtoi(Port); + unsigned short port = (unsigned short)_wtoi(Port); if (!IsPortFree(port)) { ErrorMsg = diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index 6b9b5c04449..cb1a9654987 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -35,10 +35,12 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(Win64 " Win64='yes'") SET(Platform x64) SET(PlatformProgramFilesFolder ProgramFiles64Folder) + SET(CA_QUIET_EXEC CAQuietExec64) ELSE() SET(CANDLE_ARCH -arch x86) SET(Platform x86) SET(PlatformProgramFilesFolder ProgramFilesFolder) + SET(CA_QUIET_EXEC CAQuietExec) SET(Win64) ENDIF() diff --git a/win/packaging/custom_ui.wxs b/win/packaging/custom_ui.wxs deleted file mode 100644 index 70fa3ba3abd..00000000000 --- a/win/packaging/custom_ui.wxs +++ /dev/null @@ -1,183 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - - -<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> - <Fragment> - <Property Id="PortTemplate" Value="####" /> - <Property Id="PORT" Value="3306"></Property> - <Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable"/> - <Property Id="CREATEDBINSTANCE"><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Property> - <UI> - <Dialog Id="DatabaseCreationDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes"> - <Control Id="ServiceNameLabel" Type="Text" X="20" Y="73" Width="70" Height="15" TabSkip="no" Text="Service Name:" /> - <Control Id="ServiceName" Type="Edit" X="90" Y="73" Width="120" Height="15" Property="SERVICENAME" Text="{20}" /> - - <Control Id="RootPasswordLabel" Type="Text" X="20" Y="90" Width="120" Height="15" TabSkip="no" Text="&Root password:" /> - <Control Id="RootPassword" Type="Edit" X="20" Y="105" Width="120" Height="18" Property="ROOT_PASSWORD" Password="yes" Text="{20}" /> - - <Control Id="RootPasswordConfirmLabel" Type="Text" X="150" Y="90" Width="150" Height="15" TabSkip="no" Text="&Confirm Root password:" /> - <Control Id="RootPasswordConfirm" Type="Edit" X="150" Y="105" Width="120" Height="18" Property="ROOT_PASSWORD_CONFIRM" Password="yes" Text="{20}" /> - <Control Id="BannerLine0" Type="Line" X="0" Y="128" Width="370" Height="0" /> - - <Control Id="PortLabel" Type="Text" X="20" Y="137" Width="40" Height="15" TabSkip="no" Text="TCP port:" /> - - <Control Id="Port" Type="MaskedEdit" X="60" Y="136" Width="30" Height="15" Property="PORT" Text="[PortTemplate]"/> - <!--<Control Id="FirewallExceptionCheckBox" Type="CheckBox" X="150" Y="136" Height="15" Property="FIREWALL_EXCEPTION" Width="200" CheckBoxValue="1" - Text="Create Firewall exception for this port"/>--> - - <Control Id="BannerLine2" Type="Line" X="0" Y="155" Width="370" Height="0" /> - - <Control Id="FolderLabel" Type="Text" X="20" Y="181" Width="100" Height="15" TabSkip="no" Text="Database location:" /> - <Control Id="Folder" Type="PathEdit" X="20" Y="204" Width="200" Height="18" Property="DATABASELOCATION" Indirect="no" /> - - <!-- Navigation buttons--> - <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&Back"> - <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish> - </Control> - <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next"> - <!-- - <Publish Event="ValidateProductID" Value="0">1</Publish> - <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish> - --> - <!--<Publish Event="NewDialog" Value="SetupTypeDlg">ProductID</Publish>--> - </Control> - <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel"> - <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> - </Control> - <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" /> - <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> - <Text>Create default [ProductName] instance</Text> - </Control> - <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" /> - <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> - <Text>{\WixUI_Font_Title}Default instance properties</Text> - </Control> - <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" /> - </Dialog> - - <Dialog Id="ConfirmDataCleanupDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes"> - <Control Id="ServiceRemoveText" Type="Text" X="20" Y="73" Width="300" Height="15" TabSkip="no"> - <Text>Service '[SERVICENAME]' will be removed</Text> - </Control> - <Control Id="CleanupDataCheckBox" Type="CheckBox" X="20" Y="100" Height="15" Property="CLEANUP_DATA" Width="15" CheckBoxValue="0"/> - <Control Id="RemoveDataText" Type="Text" X="37" Y="101" Width="300" Height="200" TabSkip="no"> - <Text>Remove default database directory '[DATABASELOCATION]'</Text> - </Control> - - <!-- Navigation buttons--> - <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&Back"> - <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish> - </Control> - <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next"> - <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish> - </Control> - <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel"> - <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> - </Control> - <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" /> - <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> - <Text>Remove default [ProductName] database</Text> - </Control> - <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" /> - <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> - <Text>{\WixUI_Font_Title}Default instance properties</Text> - </Control> - <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" /> - </Dialog> - </UI> - <UI Id="MyWixUI_Mondo"> - <UIRef Id="WixUI_FeatureTree" /> - <UIRef Id="WixUI_ErrorProgressText" /> - <DialogRef Id="DatabaseCreationDlg" /> - <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="DatabaseCreationDlg" Order="999"><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Publish> - <Publish Dialog="DatabaseCreationDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="3">1</Publish> - <Publish Dialog="DatabaseCreationDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="3">1</Publish> - <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="DatabaseCreationDlg" Order="3" ><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Publish> - <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ConfirmDataCleanupDlg" Order="3" ><![CDATA[(&DBInstance=2) AND (!DBInstance=3)]]></Publish> - <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="ConfirmDataCleanupDlg" Order="999"><![CDATA[(&DBInstance=2) AND (!DBInstance=3)]]></Publish> - <Publish Dialog="ConfirmDataCleanupDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg">WixUI_InstallMode = "Change"</Publish> - <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="ConfirmDataCleanupDlg" Order="999">!DBInstance=3</Publish> - <Publish Dialog="ConfirmDataCleanupDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg">WixUI_InstallMode = "Remove"</Publish> - </UI> - - <DirectoryRef Id='TARGETDIR'> - <Directory Id="CommonAppDataFolder"> - <Directory Id="DatabasesRoot" Name="MariaDB"> - <Directory Id="DATABASELOCATION" Name="MariaDB Server 5.1"> - </Directory> - </Directory> - </Directory> - </DirectoryRef> - - <Feature Id='DBInstance' - Title='Database instance' - Description='Install database instance' - ConfigurableDirectory='DATABASELOCATION' - AllowAdvertise='no' - Level='1'> - <Component Id="C.datadir" Guid="*" Directory="DATABASELOCATION"> - <RegistryValue Root='HKLM' - Key='SOFTWARE\[Manufacturer]\[ProductName]' - Name='DatabaseLocation' Value='[DATABASELOCATION]' Type='string' KeyPath='yes'/> - <CreateFolder /> - </Component> - <Component Id="C.service" Guid="*" Directory="DATABASELOCATION"> - <Condition>SERVICENAME</Condition> - <RegistryValue Root='HKLM' - Key='SOFTWARE\[Manufacturer]\[ProductName]' - Name='ServiceName' Value='[SERVICENAME]' Type='string' KeyPath='yes'/> - <ServiceControl Id='DBInstanceServiceStop' Name='[SERVICENAME]' Stop='uninstall' Wait='yes'></ServiceControl> - <ServiceControl Id='DBInstanceServiceStart' Name='[SERVICENAME]' Start='install' Wait='no'></ServiceControl> - <ServiceControl Id='DBInstanceServiceRemove' Name='[SERVICENAME]' Remove='uninstall' Wait='yes'></ServiceControl> - </Component> - </Feature> - - <CustomAction Id="QtExecDeferredExampleWithProperty_Cmd" Property="QtExecDeferredExampleWithProperty" - Value=""[#F.bin.mysql_install_db.exe]" "--service=[SERVICENAME]" "--password=[ROOT_PASSWORD]" "--datadir=[DATABASELOCATION]"" - Execute="immediate"/> - <CustomAction Id="QtExecDeferredExampleWithProperty" BinaryKey="WixCA" DllEntry="CAQuietExec" - Execute="deferred" Return="check" Impersonate="no"/> - - <UI> - <ProgressText Action="QtExecDeferredExampleWithProperty">Running mysql_install_db.exe</ProgressText> - </UI> - - <!-- Use Wix toolset "remember property" pattern to store properties between major upgrades etc --> - <InstallExecuteSequence> - <Custom Action="QtExecDeferredExampleWithProperty_Cmd" After="CostFinalize"><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Custom> - <Custom Action="QtExecDeferredExampleWithProperty" After="InstallFiles"><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Custom> - </InstallExecuteSequence> - - <Property Id='SERVICENAME'> - <RegistrySearch Id='ServiceNameProperty' Root='HKLM' - Key='SOFTWARE\[Manufacturer]\[ProductName]' - Name='ServiceName' Type='raw' /> - </Property> - <SetProperty After='AppSearch' Id="SERVICENAME" Value="MariaDB_51"><![CDATA[NOT SERVICENAME]]></SetProperty> - <Property Id="DATABASELOCATION"> - <RegistrySearch Id='DatabaseLocationProperty' Root='HKLM' - Key='SOFTWARE\[Manufacturer]\[ProductName]' - Name='´DatabaseLocation' Type='raw' /> - </Property> - <SetProperty After='AppSearch' Id="DATABASELOCATION" Value="[CommonAppDataFolder]\MariaDB\[ProductName]"><![CDATA[NOT DATABASELOCATION]]></SetProperty> - <CustomAction Id='SaveCmdLineValue_SERVICENAME' Property='CMDLINE_SERVICENAME' - Value='[SERVICENAME]' Execute='firstSequence' /> - <CustomAction Id='SetFromCmdLineValue_SERVICENAME' Property='SERVICENAME' Value='[CMDLINE_SERVICENAME]' Execute='firstSequence' /> - <CustomAction Id='SaveCmdLineValue_DATABASELOCATION' Property='CMDLINE_DATABASELOCATION' - Value='[DATABASELOCATION]' Execute='firstSequence' /> - <CustomAction Id='SetFromCmdLineValue_DATABASELOCATION' Property='DATABASELOCATION' Value='[CMDLINE_DATABASELOCATION]' Execute='firstSequence' /> - - <InstallUISequence> - <Custom Action='SaveCmdLineValue_SERVICENAME' Before='AppSearch' /> - <Custom Action='SetFromCmdLineValue_SERVICENAME' After='AppSearch'>CMDLINE_SERVICENAME</Custom> - <Custom Action='SaveCmdLineValue_DATABASELOCATION' Before='AppSearch' /> - <Custom Action='SetFromCmdLineValue_DATABASELOCATION' After='AppSearch'>CMDLINE_DATABASELOCATION</Custom> - </InstallUISequence> - <InstallExecuteSequence> - <Custom Action='SaveCmdLineValue_SERVICENAME' Before='AppSearch' /> - <Custom Action='SetFromCmdLineValue_SERVICENAME' After='AppSearch'>CMDLINE_SERVICENAME</Custom> - <Custom Action='SaveCmdLineValue_DATABASELOCATION' Before='AppSearch' /> - <Custom Action='SetFromCmdLineValue_DATABASELOCATION' After='AppSearch'>CMDLINE_DATABASELOCATION</Custom> - </InstallExecuteSequence> - </Fragment> -</Wix>
\ No newline at end of file diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 3aa6889ac2f..11fe60719ec 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -613,7 +613,7 @@ <CustomAction Id="CreateDatabaseRollbackCommand" Property="CreateDatabaseRollback" Value="[SERVICENAME]\[DATADIR]" Execute="immediate"/> - <CustomAction Id="CreateDatabase" BinaryKey="WixCA" DllEntry="CAQuietExec" + <CustomAction Id="CreateDatabase" BinaryKey="WixCA" DllEntry="@CA_QUIET_EXEC@" Execute="deferred" Return="check" Impersonate="no" /> <CustomAction Id="CreateDatabaseRollback" BinaryKey="wixca.dll" DllEntry="CreateDatabaseRollback" Execute="rollback" Return="check" Impersonate="no"/> |