From 10cd281820cdcbef2fd9bc68c97325659f84de4a Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Wed, 19 May 2021 15:46:57 +0100 Subject: [PATCH 01/28] MDEV-25444 mysql --binary-mode is not able to replay some mysqlbinlog outputs Problem:- Some binary data is inserted into the table using Jconnector. When binlog dump of the data is applied using mysql cleint it gives syntax error. Reason:- After investigating it turns out to be a issue of mysql client not able to properly handle \\\0 <0 in binary>. In all binary files where mysql client fails to insert these 2 bytes are commom (0x5c00) Solution:- I have changed mysql.cc to include for the possibility that binary string can have \\\0 in it --- client/mysql.cc | 8 ++++++-- mysql-test/main/binary_zero_insert.result | 6 ++++++ mysql-test/main/binary_zero_insert.test | 15 +++++++++++++++ mysql-test/std_data/binary_zero_insert.bin | Bin 0 -> 87 bytes 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 mysql-test/main/binary_zero_insert.result create mode 100644 mysql-test/main/binary_zero_insert.test create mode 100644 mysql-test/std_data/binary_zero_insert.bin diff --git a/client/mysql.cc b/client/mysql.cc index 2a7c4eaf3e5..8530c105820 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2319,8 +2319,12 @@ static bool add_line(String &buffer, char *line, size_t line_length, { // Found possbile one character command like \c - if (!(inchar = (uchar) *++pos)) - break; // readline adds one '\' + inchar = (uchar) *++pos; + // In Binary mode , when in_string is not null \0 should not be treated as + // end statement. This can happen when we are in middle of binary data which + // can contain \0 and its quoted with ' '. + if (!real_binary_mode && !*in_string && !inchar) + break; // readline adds one '\' if (*in_string || inchar == 'N') // \N is short for NULL { // Don't allow commands in string *out++='\\'; diff --git a/mysql-test/main/binary_zero_insert.result b/mysql-test/main/binary_zero_insert.result new file mode 100644 index 00000000000..c46dc74f019 --- /dev/null +++ b/mysql-test/main/binary_zero_insert.result @@ -0,0 +1,6 @@ +CREATE TABLE `tb` (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, +PRIMARY KEY (`id`)) ENGINE=myisam AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; +select count(*)=2 from tb; +count(*)=2 +1 +drop table tb; diff --git a/mysql-test/main/binary_zero_insert.test b/mysql-test/main/binary_zero_insert.test new file mode 100644 index 00000000000..a8769199859 --- /dev/null +++ b/mysql-test/main/binary_zero_insert.test @@ -0,0 +1,15 @@ +# +# MDEV-25444 mysql --binary-mode is not able to replay some mysqlbinlog outputs +# +# After investigating it turns out to be a issue of mysql client not able to properly +# handle \\\0 <0 in binary>. +# In this test case we will be pipelining binary_zero_insert.bin into mysql client. +# binary_zero_insert.bin contains insert stmt with \\\0 + +CREATE TABLE `tb` (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, +PRIMARY KEY (`id`)) ENGINE=myisam AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; + +--exec $MYSQL --binary-mode test < $MYSQL_TEST_DIR/std_data/binary_zero_insert.bin +select count(*)=2 from tb; + +drop table tb; diff --git a/mysql-test/std_data/binary_zero_insert.bin b/mysql-test/std_data/binary_zero_insert.bin new file mode 100644 index 0000000000000000000000000000000000000000..8a91ae5d3e135917b216c360def25018d3a5564a GIT binary patch literal 87 zcmebD3w8|(QSkH&@mDBG(nwCyR0wnQ33UzDh)>GQODw8XP>+d;VNln!=JF({G(z3f J*}wp#7645{7;69k literal 0 HcmV?d00001 From 1755ea4b4903489e1e53375bc1f26fa5f42a7a12 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Thu, 30 Sep 2021 15:03:44 -0600 Subject: [PATCH 02/28] MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes on top of Sachin’s patch. Specifically: 1) Refined the parsing break condition to only change the parser’s behavior for parsing strings in binary mode (behavior of \0 outside of strings is unchanged). 2) Prefixed binary_zero_insert.test with ‘mysql_’ to more clearly associate the purpose of the test. 3) As the input of the test contains binary zeros (0x5c00), different text editors can visualize this sequence differently, and Github would not display it at all. Therefore, the input itself was consolidated into the test and created out of hex sequences to make it easier to understand what is happening. 4) Extended test to validate that the rows which correspond to the INSERTS with 0x5c00 have the correct binary zero data. Reviewed By: =========== Andrei Elkin --- client/mysql.cc | 13 +- mysql-test/main/binary_zero_insert.result | 6 - mysql-test/main/binary_zero_insert.test | 15 -- .../main/mysql_binary_zero_insert.result | 54 ++++++ mysql-test/main/mysql_binary_zero_insert.test | 170 ++++++++++++++++++ mysql-test/std_data/binary_zero_insert.bin | Bin 87 -> 0 bytes 6 files changed, 232 insertions(+), 26 deletions(-) delete mode 100644 mysql-test/main/binary_zero_insert.result delete mode 100644 mysql-test/main/binary_zero_insert.test create mode 100644 mysql-test/main/mysql_binary_zero_insert.result create mode 100644 mysql-test/main/mysql_binary_zero_insert.test delete mode 100644 mysql-test/std_data/binary_zero_insert.bin diff --git a/client/mysql.cc b/client/mysql.cc index 8530c105820..21060013c75 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2319,11 +2319,14 @@ static bool add_line(String &buffer, char *line, size_t line_length, { // Found possbile one character command like \c - inchar = (uchar) *++pos; - // In Binary mode , when in_string is not null \0 should not be treated as - // end statement. This can happen when we are in middle of binary data which - // can contain \0 and its quoted with ' '. - if (!real_binary_mode && !*in_string && !inchar) + /* + The null-terminating character (ASCII '\0') marks the end of user + input. Then, by default, upon encountering a '\0' while parsing, it + should stop. However, some data naturally contains binary zeros + (e.g., zipped files). Real_binary_mode signals the parser to expect + '\0' within the data and not to end parsing if found. + */ + if (!(inchar = (uchar) *++pos) && (!real_binary_mode || !*in_string)) break; // readline adds one '\' if (*in_string || inchar == 'N') // \N is short for NULL { // Don't allow commands in string diff --git a/mysql-test/main/binary_zero_insert.result b/mysql-test/main/binary_zero_insert.result deleted file mode 100644 index c46dc74f019..00000000000 --- a/mysql-test/main/binary_zero_insert.result +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE `tb` (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, -PRIMARY KEY (`id`)) ENGINE=myisam AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; -select count(*)=2 from tb; -count(*)=2 -1 -drop table tb; diff --git a/mysql-test/main/binary_zero_insert.test b/mysql-test/main/binary_zero_insert.test deleted file mode 100644 index a8769199859..00000000000 --- a/mysql-test/main/binary_zero_insert.test +++ /dev/null @@ -1,15 +0,0 @@ -# -# MDEV-25444 mysql --binary-mode is not able to replay some mysqlbinlog outputs -# -# After investigating it turns out to be a issue of mysql client not able to properly -# handle \\\0 <0 in binary>. -# In this test case we will be pipelining binary_zero_insert.bin into mysql client. -# binary_zero_insert.bin contains insert stmt with \\\0 - -CREATE TABLE `tb` (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, -PRIMARY KEY (`id`)) ENGINE=myisam AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; - ---exec $MYSQL --binary-mode test < $MYSQL_TEST_DIR/std_data/binary_zero_insert.bin -select count(*)=2 from tb; - -drop table tb; diff --git a/mysql-test/main/mysql_binary_zero_insert.result b/mysql-test/main/mysql_binary_zero_insert.result new file mode 100644 index 00000000000..0bed7487b3e --- /dev/null +++ b/mysql-test/main/mysql_binary_zero_insert.result @@ -0,0 +1,54 @@ +# Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE. +############################## +# Setup +############################## +# +# Saving old state +# +set @old_sql_mode= @@global.SQL_MODE; +set @@global.SQL_MODE= ""; +# +# Create table for data entry +# +CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; +RESET MASTER; +############################## +# Test Case +############################## +# +# \0 (0x5c00 in binary) should be allowed in data strings if +# --binary-mode is enabled. +# +FOUND 10 /\x5c\x00/ in binary_zero_inserts.sql +# MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql +# +# Ensure a row exists from each insert statement with a \0 +# +SELECT COUNT(*)=8 from tb; +COUNT(*)=8 +1 +# +# Ensure that the binary zero was parsed and exists in the row data +# Note: We only look for 00 because the 5c only served as an escape +# in parsing. +# +# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql +FOUND 10 /00/ in dump.sql +# +# Ensure data consistency on mysqlbinlog replay +# +FLUSH LOGS; +# MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql +FOUND 10 /\x5c\x00/ in binlog_zeros.sql +# MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql +# Table checksum is equivalent before and after binlog replay +# +# A \0 should still be treated as end-of-query in binary mode. +# +# MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql +############################## +# Cleanup +############################## +SET @@global.sql_mode= @old_sql_mode; +drop table tb; +RESET MASTER; diff --git a/mysql-test/main/mysql_binary_zero_insert.test b/mysql-test/main/mysql_binary_zero_insert.test new file mode 100644 index 00000000000..b327c8a4d1e --- /dev/null +++ b/mysql-test/main/mysql_binary_zero_insert.test @@ -0,0 +1,170 @@ +# +# Purpose: +# This test ensures that the mysql client is able to properly handle the +# binary data sequence 0x5c00, i.e. the null-terminating character \0, in a +# string when --binary-mode is enabled. Specifically, this sequence is valid to +# appear anywhere within a binary data string, and it should not end the string +# or SQL command. Additionally, \0 outside of a string should still end the +# query. +# +# Methodology: +# This test initially inserts data with binary strings containing \0. To +# ensure the mysql client is able to process this data correctly, perl is used +# to create a SQL file that contains \0 in strings, and this file is used as +# input into the client. The row data is then validated by searching for binary +# zeros in mysqldump output. +# +# +# References: +# MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog +# outputs + +--echo # Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE. + +--source include/have_log_bin.inc + +--echo ############################## +--echo # Setup +--echo ############################## + +--echo # +--echo # Saving old state +--echo # +set @old_sql_mode= @@global.SQL_MODE; +set @@global.SQL_MODE= ""; + +--echo # +--echo # Create table for data entry +--echo # +CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; + +# Will replay binlog later and we don't want to recreate the table +RESET MASTER; + + +--echo ############################## +--echo # Test Case +--echo ############################## + +--echo # +--echo # \0 (0x5c00 in binary) should be allowed in data strings if +--echo # --binary-mode is enabled. +--echo # +--perl + my $dir= $ENV{'MYSQL_TMP_DIR'}; + open (my $FILE, '>', "$dir/binary_zero_inserts.sql") or die "open(): $!"; + + print $FILE "TRUNCATE TABLE tb;\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0A'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c0041"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary 'A\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","415c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary 'A\0B'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","415c0042"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0A\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c00415c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\\\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c5c5c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c005c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c5c00"; + print $FILE "');\n"; + + close ($FILE); +EOF +--let SEARCH_PATTERN= \x5c\x00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/binary_zero_inserts.sql +--source include/search_pattern_in_file.inc +--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql +--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binary_zero_inserts.sql + +--echo # +--echo # Ensure a row exists from each insert statement with a \0 +--echo # +SELECT COUNT(*)=8 from tb; + +--echo # +--echo # Ensure that the binary zero was parsed and exists in the row data +--echo # Note: We only look for 00 because the 5c only served as an escape +--echo # in parsing. +--echo # +--echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql +--exec $MYSQL_DUMP test tb --hex-blob | grep INSERT > $MYSQL_TMP_DIR/dump.sql +--let SEARCH_PATTERN= 00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql +--source include/search_pattern_in_file.inc + +--echo # +--echo # Ensure data consistency on mysqlbinlog replay +--echo # +--let $good_checksum= `CHECKSUM TABLE tb` +let $MYSQLD_DATADIR= `SELECT @@datadir`; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +FLUSH LOGS; +--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQL_TMP_DIR/binlog_zeros.sql +--let SEARCH_PATTERN= \x5c\x00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/binlog_zeros.sql +--source include/search_pattern_in_file.inc +--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql +--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binlog_zeros.sql +if ($good_checksum != `CHECKSUM TABLE tb`) +{ + die "Blob with binary zero data changed after binary log replay"; +} +--echo # Table checksum is equivalent before and after binlog replay + +--echo # +--echo # A \0 should still be treated as end-of-query in binary mode. +--echo # +--perl + my $dir= $ENV{'MYSQL_TMP_DIR'}; + open (my $FILE, '>', "$dir/binary_zero_eoq.sql") or die "open(): $!"; + + # INSERT INTO tb(cb) VALUES(_binary 'text')\0 + print $FILE "INSERT INTO tb(cb) VALUES (_binary 'text')"; + print $FILE pack "H*","5c00"; + + close ($FILE); +EOF +--echo # MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql +--exec $MYSQL --binary-mode -B test < $MYSQL_TMP_DIR/binary_zero_eoq.sql + + +--echo ############################## +--echo # Cleanup +--echo ############################## + +--remove_file $MYSQL_TMP_DIR/binary_zero_inserts.sql +--remove_file $MYSQL_TMP_DIR/binary_zero_eoq.sql +--remove_file $MYSQL_TMP_DIR/binlog_zeros.sql +--remove_file $MYSQL_TMP_DIR/dump.sql +SET @@global.sql_mode= @old_sql_mode; +drop table tb; +RESET MASTER; diff --git a/mysql-test/std_data/binary_zero_insert.bin b/mysql-test/std_data/binary_zero_insert.bin deleted file mode 100644 index 8a91ae5d3e135917b216c360def25018d3a5564a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87 zcmebD3w8|(QSkH&@mDBG(nwCyR0wnQ33UzDh)>GQODw8XP>+d;VNln!=JF({G(z3f J*}wp#7645{7;69k From 1ce35c327ed90fa67da53a3f9d470f195d879417 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 6 Oct 2021 07:42:03 -0600 Subject: [PATCH 03/28] MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: This patch backports commits 10cd281 and 1755ea4 from 10.3. 10cd281: Problem:- Some binary data is inserted into the table using Jconnector. When binlog dump of the data is applied using mysql client it gives syntax error. Reason:- After investigating it turns out to be a issue of mysql client not able to properly handle \\0 <0 in binary>. In all binary files where mysql client fails to insert these 2 bytes are common (0x5c00) Solution:- I have changed mysql.cc to include for the possibility that binary string can have \\0 in it 1755ea4: Changes on top of Sachin’s patch. Specifically: 1) Refined the parsing break condition to only change the parser’s behavior for parsing strings in binary mode (behavior of \0 outside of strings is unchanged). 2) Prefixed binary_zero_insert.test with ‘mysql_’ to more clearly associate the purpose of the test. 3) As the input of the test contains binary zeros (0x5c00), different text editors can visualize this sequence differently, and Github would not display it at all. Therefore, the input itself was consolidated into the test and created out of hex sequences to make it easier to understand what is happening. 4) Extended test to validate that the rows which correspond to the INSERTS with 0x5c00 have the correct binary zero data. Reviewed By: ============ Andrei Elkin --- client/mysql.cc | 9 +- mysql-test/r/mysql_binary_zero_insert.result | 54 ++++++ mysql-test/t/mysql_binary_zero_insert.test | 170 +++++++++++++++++++ 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/mysql_binary_zero_insert.result create mode 100644 mysql-test/t/mysql_binary_zero_insert.test diff --git a/client/mysql.cc b/client/mysql.cc index 2eb44d46512..2baac7b92b8 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2335,7 +2335,14 @@ static bool add_line(String &buffer, char *line, ulong line_length, { // Found possbile one character command like \c - if (!(inchar = (uchar) *++pos)) + /* + The null-terminating character (ASCII '\0') marks the end of user + input. Then, by default, upon encountering a '\0' while parsing, it + should stop. However, some data naturally contains binary zeros + (e.g., zipped files). Real_binary_mode signals the parser to expect + '\0' within the data and not to end parsing if found. + */ + if (!(inchar = (uchar) *++pos) && (!real_binary_mode || !*in_string)) break; // readline adds one '\' if (*in_string || inchar == 'N') // \N is short for NULL { // Don't allow commands in string diff --git a/mysql-test/r/mysql_binary_zero_insert.result b/mysql-test/r/mysql_binary_zero_insert.result new file mode 100644 index 00000000000..0bed7487b3e --- /dev/null +++ b/mysql-test/r/mysql_binary_zero_insert.result @@ -0,0 +1,54 @@ +# Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE. +############################## +# Setup +############################## +# +# Saving old state +# +set @old_sql_mode= @@global.SQL_MODE; +set @@global.SQL_MODE= ""; +# +# Create table for data entry +# +CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; +RESET MASTER; +############################## +# Test Case +############################## +# +# \0 (0x5c00 in binary) should be allowed in data strings if +# --binary-mode is enabled. +# +FOUND 10 /\x5c\x00/ in binary_zero_inserts.sql +# MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql +# +# Ensure a row exists from each insert statement with a \0 +# +SELECT COUNT(*)=8 from tb; +COUNT(*)=8 +1 +# +# Ensure that the binary zero was parsed and exists in the row data +# Note: We only look for 00 because the 5c only served as an escape +# in parsing. +# +# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql +FOUND 10 /00/ in dump.sql +# +# Ensure data consistency on mysqlbinlog replay +# +FLUSH LOGS; +# MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql +FOUND 10 /\x5c\x00/ in binlog_zeros.sql +# MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql +# Table checksum is equivalent before and after binlog replay +# +# A \0 should still be treated as end-of-query in binary mode. +# +# MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql +############################## +# Cleanup +############################## +SET @@global.sql_mode= @old_sql_mode; +drop table tb; +RESET MASTER; diff --git a/mysql-test/t/mysql_binary_zero_insert.test b/mysql-test/t/mysql_binary_zero_insert.test new file mode 100644 index 00000000000..b327c8a4d1e --- /dev/null +++ b/mysql-test/t/mysql_binary_zero_insert.test @@ -0,0 +1,170 @@ +# +# Purpose: +# This test ensures that the mysql client is able to properly handle the +# binary data sequence 0x5c00, i.e. the null-terminating character \0, in a +# string when --binary-mode is enabled. Specifically, this sequence is valid to +# appear anywhere within a binary data string, and it should not end the string +# or SQL command. Additionally, \0 outside of a string should still end the +# query. +# +# Methodology: +# This test initially inserts data with binary strings containing \0. To +# ensure the mysql client is able to process this data correctly, perl is used +# to create a SQL file that contains \0 in strings, and this file is used as +# input into the client. The row data is then validated by searching for binary +# zeros in mysqldump output. +# +# +# References: +# MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog +# outputs + +--echo # Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE. + +--source include/have_log_bin.inc + +--echo ############################## +--echo # Setup +--echo ############################## + +--echo # +--echo # Saving old state +--echo # +set @old_sql_mode= @@global.SQL_MODE; +set @@global.SQL_MODE= ""; + +--echo # +--echo # Create table for data entry +--echo # +CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; + +# Will replay binlog later and we don't want to recreate the table +RESET MASTER; + + +--echo ############################## +--echo # Test Case +--echo ############################## + +--echo # +--echo # \0 (0x5c00 in binary) should be allowed in data strings if +--echo # --binary-mode is enabled. +--echo # +--perl + my $dir= $ENV{'MYSQL_TMP_DIR'}; + open (my $FILE, '>', "$dir/binary_zero_inserts.sql") or die "open(): $!"; + + print $FILE "TRUNCATE TABLE tb;\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0A'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c0041"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary 'A\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","415c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary 'A\0B'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","415c0042"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0A\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c00415c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\\\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c5c5c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\0\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c005c00"; + print $FILE "');\n"; + + # INSERT INTO tb(cb) VALUES(_binary '\\0'); + print $FILE "INSERT INTO tb(cb) VALUES (_binary '"; + print $FILE pack "H*","5c5c00"; + print $FILE "');\n"; + + close ($FILE); +EOF +--let SEARCH_PATTERN= \x5c\x00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/binary_zero_inserts.sql +--source include/search_pattern_in_file.inc +--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql +--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binary_zero_inserts.sql + +--echo # +--echo # Ensure a row exists from each insert statement with a \0 +--echo # +SELECT COUNT(*)=8 from tb; + +--echo # +--echo # Ensure that the binary zero was parsed and exists in the row data +--echo # Note: We only look for 00 because the 5c only served as an escape +--echo # in parsing. +--echo # +--echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql +--exec $MYSQL_DUMP test tb --hex-blob | grep INSERT > $MYSQL_TMP_DIR/dump.sql +--let SEARCH_PATTERN= 00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql +--source include/search_pattern_in_file.inc + +--echo # +--echo # Ensure data consistency on mysqlbinlog replay +--echo # +--let $good_checksum= `CHECKSUM TABLE tb` +let $MYSQLD_DATADIR= `SELECT @@datadir`; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +FLUSH LOGS; +--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQL_TMP_DIR/binlog_zeros.sql +--let SEARCH_PATTERN= \x5c\x00 +--let SEARCH_FILE= $MYSQL_TMP_DIR/binlog_zeros.sql +--source include/search_pattern_in_file.inc +--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql +--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binlog_zeros.sql +if ($good_checksum != `CHECKSUM TABLE tb`) +{ + die "Blob with binary zero data changed after binary log replay"; +} +--echo # Table checksum is equivalent before and after binlog replay + +--echo # +--echo # A \0 should still be treated as end-of-query in binary mode. +--echo # +--perl + my $dir= $ENV{'MYSQL_TMP_DIR'}; + open (my $FILE, '>', "$dir/binary_zero_eoq.sql") or die "open(): $!"; + + # INSERT INTO tb(cb) VALUES(_binary 'text')\0 + print $FILE "INSERT INTO tb(cb) VALUES (_binary 'text')"; + print $FILE pack "H*","5c00"; + + close ($FILE); +EOF +--echo # MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql +--exec $MYSQL --binary-mode -B test < $MYSQL_TMP_DIR/binary_zero_eoq.sql + + +--echo ############################## +--echo # Cleanup +--echo ############################## + +--remove_file $MYSQL_TMP_DIR/binary_zero_inserts.sql +--remove_file $MYSQL_TMP_DIR/binary_zero_eoq.sql +--remove_file $MYSQL_TMP_DIR/binlog_zeros.sql +--remove_file $MYSQL_TMP_DIR/dump.sql +SET @@global.sql_mode= @old_sql_mode; +drop table tb; +RESET MASTER; From 96b4a5a6484148778facf95cd8b2be17f47c4da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 6 Oct 2021 13:49:07 +0300 Subject: [PATCH 04/28] Fix galera_var_reject_queries test case --- .../suite/galera/r/galera_var_reject_queries.result | 11 +++-------- .../suite/galera/t/galera_var_reject_queries.test | 6 ++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result index 1b2bc1c5e16..33ee9262638 100644 --- a/mysql-test/suite/galera/r/galera_var_reject_queries.result +++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result @@ -1,11 +1,6 @@ -<<<<<<< HEAD connection node_2; connection node_1; -||||||| merged common ancestors -======= -call mtr.add_suppression("WSREP has not yet prepared node for application use"); ->>>>>>> 10.3 -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; SET SESSION wsrep_reject_queries = ALL; @@ -27,7 +22,7 @@ VARIABLE_VALUE = 2 INSERT INTO t1 VALUES (1); connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET GLOBAL wsrep_reject_queries = NONE; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_reject_queries.test b/mysql-test/suite/galera/t/galera_var_reject_queries.test index aa31b94d6e0..60aabe9bc17 100644 --- a/mysql-test/suite/galera/t/galera_var_reject_queries.test +++ b/mysql-test/suite/galera/t/galera_var_reject_queries.test @@ -5,9 +5,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc -call mtr.add_suppression("WSREP has not yet prepared node for application use"); - -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 @@ -44,6 +42,6 @@ INSERT INTO t1 VALUES (1); --connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 SET GLOBAL wsrep_reject_queries = NONE; -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; From d9b933bec6061758c5d7b34f55afcae32a85c110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 6 Oct 2021 13:49:27 +0300 Subject: [PATCH 05/28] MDEV-24062 : Galera test failure on galera_var_replicate_myisam_on We should do after_statement only for local transactions. --- .../r/galera_var_replicate_myisam_on.result | 17 +++++++++++++---- .../t/galera_var_replicate_myisam_on.test | 16 +++++++++++++--- sql/wsrep_trans_observer.h | 9 ++++++++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result index ad28f5a426e..314da703e58 100644 --- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result +++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result @@ -53,8 +53,8 @@ COUNT(*) = 0 1 DROP TABLE t1; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; -CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES (1); @@ -100,7 +100,7 @@ DROP TABLE t2; # MDEV-11152: wsrep_replicate_myisam: SELECT gets replicated using TO # connection node_1; -CREATE TABLE t1 (i INT) ENGINE=INNODB; +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE=INNODB; INSERT INTO t1 VALUES(1); SELECT * FROM t1; i @@ -237,5 +237,14 @@ DROP TRIGGER tr1; DROP TRIGGER tr2; DROP TRIGGER tr3; DROP TABLE t1,t2; -connection node_1; +CREATE TABLE t1 (a INT, b INT, UNIQUE(a)) ENGINE=MyISAM; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=1; +SET GLOBAL wsrep_replicate_myisam=ON; +INSERT INTO t1 (a,b) VALUES (10,20); +connection node_2; +SELECT * from t1; +a b +1 20 +connection node_1; +DROP TABLE t1; connection node_2; diff --git a/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test b/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test index adb5cb04273..acebe4cccdc 100644 --- a/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test +++ b/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test @@ -80,8 +80,8 @@ DROP TABLE t1; # --connection node_1 -CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; -CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES (1); @@ -136,7 +136,7 @@ DROP TABLE t2; --echo # MDEV-11152: wsrep_replicate_myisam: SELECT gets replicated using TO --echo # --connection node_1 -CREATE TABLE t1 (i INT) ENGINE=INNODB; +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE=INNODB; INSERT INTO t1 VALUES(1); # This command should not get replicated. SELECT * FROM t1; @@ -218,7 +218,16 @@ DROP TRIGGER tr2; DROP TRIGGER tr3; DROP TABLE t1,t2; +CREATE TABLE t1 (a INT, b INT, UNIQUE(a)) ENGINE=MyISAM; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=1; +SET GLOBAL wsrep_replicate_myisam=ON; +INSERT INTO t1 (a,b) VALUES (10,20); + +--connection node_2 +SELECT * from t1; --connection node_1 +DROP TABLE t1; + --disable_query_log --eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig --enable_query_log @@ -227,3 +236,4 @@ DROP TABLE t1,t2; --disable_query_log --eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig --enable_query_log + diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index 8157c14fcdf..55beb6ebe7c 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -396,7 +396,14 @@ static inline int wsrep_after_statement(THD* thd) { DBUG_ENTER("wsrep_after_statement"); - DBUG_RETURN(thd->wsrep_cs().state() != wsrep::client_state::s_none ? + WSREP_DEBUG("wsrep_after_statement for %lu client_state %s " + " client_mode %s trans_state %s", + thd_get_thread_id(thd), + wsrep::to_c_string(thd->wsrep_cs().state()), + wsrep::to_c_string(thd->wsrep_cs().mode()), + wsrep::to_c_string(thd->wsrep_cs().transaction().state())); + DBUG_RETURN((thd->wsrep_cs().state() != wsrep::client_state::s_none && + thd->wsrep_cs().mode() == Wsrep_client_state::m_local) ? thd->wsrep_cs().after_statement() : 0); } From a1b6f776da032e83c9ed8e20c541981e02cc6e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 7 Oct 2021 11:03:55 +0300 Subject: [PATCH 06/28] MDEV-22996 : Hang on galera_toi_truncate test case Actual problem was earlier fixed. This contains only test case change. We use debug_sync to force concurrent DML and TRUNCATE. --- .../suite/galera/r/galera_toi_truncate.result | 23 +++++++--- .../suite/galera/t/galera_toi_truncate.test | 44 ++++++++++++++----- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result index a02487ac347..bd3ee0dd75e 100644 --- a/mysql-test/suite/galera/r/galera_toi_truncate.result +++ b/mysql-test/suite/galera/r/galera_toi_truncate.result @@ -3,16 +3,24 @@ connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (id int not null primary key auto_increment, f1 INTEGER) ENGINE=InnoDB; connection node_2; -SET SESSION wsrep_retry_autocommit = 0; -INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8; -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; -connection node_2a; +set session wsrep_sync_wait=0; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1b; +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; +connection node_2; +INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1; +connection node_1b; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_1; +TRUNCATE TABLE t1;; +connection node_1b; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; connection node_1; -TRUNCATE TABLE t1; connection node_2; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT COUNT(*) AS EXPECT_0 FROM t1; EXPECT_0 0 @@ -20,5 +28,6 @@ connection node_1; SELECT COUNT(*) AS EXPECT_0 FROM t1; EXPECT_0 0 +disconnect node_1b; DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_toi_truncate.test b/mysql-test/suite/galera/t/galera_toi_truncate.test index 5b23a8c3f3e..ab94d9397ce 100644 --- a/mysql-test/suite/galera/t/galera_toi_truncate.test +++ b/mysql-test/suite/galera/t/galera_toi_truncate.test @@ -6,6 +6,7 @@ --source include/galera_cluster.inc --source include/have_debug_sync.inc --source include/have_debug.inc +--source include/galera_have_debug_sync.inc # # INSERT and TRUNCATE on different nodes @@ -15,32 +16,51 @@ CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (id int not null primary key auto_increment, f1 INTEGER) ENGINE=InnoDB; --connection node_2 +set session wsrep_sync_wait=0; --let $wait_condition = SELECT COUNT(*) = 10 FROM ten; --source include/wait_condition.inc -# Prevent autocommit retring from masking the deadlock error we expect to get -SET SESSION wsrep_retry_autocommit = 0; ---send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8 +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 ---connection node_2a ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Sending data%' AND INFO LIKE 'INSERT INTO t1 (f1)%'; ---source include/wait_condition.inc - ---connection node_1 -TRUNCATE TABLE t1; +# block applier before applying +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; --connection node_2 ---error ER_LOCK_DEADLOCK +--send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1 + +--connection node_1b +# wait until applier has reached the sync point +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + +--connection node_1 +--send TRUNCATE TABLE t1; + +--connection node_1b +# release the applier +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; + +--connection node_1 --reap +--connection node_2 +--reap + +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc SELECT COUNT(*) AS EXPECT_0 FROM t1; --connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc SELECT COUNT(*) AS EXPECT_0 FROM t1; +--disconnect node_1b + DROP TABLE t1; DROP TABLE ten; From 3067ffc58e2ada6591e3d823b31841ea685da6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 6 Oct 2021 13:48:22 +0300 Subject: [PATCH 07/28] Update galera disabled.def --- mysql-test/suite/galera/disabled.def | 9 +-- .../r/galera_wsrep_provider_unset_set.result | 23 ------- mysql-test/suite/galera/r/pxc-421.result | 46 ------------- .../t/galera_wsrep_provider_unset_set.test | 50 -------------- mysql-test/suite/galera/t/pxc-421.test | 67 ------------------- 5 files changed, 1 insertion(+), 194 deletions(-) delete mode 100644 mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result delete mode 100644 mysql-test/suite/galera/r/pxc-421.result delete mode 100644 mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test delete mode 100644 mysql-test/suite/galera/t/pxc-421.test diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 96005fccf54..e4210734f5e 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -16,9 +16,7 @@ MDEV-20225 : MDEV-20886 galera.MDEV-20225 MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-329 : MDEV-19962 Galera test failure on MW-329 -galera_FK_duplicate_client_insert : MDEV-24473: galera.galera_FK_duplicate_client_insert MTR failed: SIGABRT. InnoDB: Conflicting lock on table. Assertion failure in lock0lock.cc galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() -galera_bf_abort_at_after_statement : MDEV-21557: galera_bf_abort_at_after_statement MTR failed: query 'reap' succeeded - should have failed with errno 1213 galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit galera_bf_lock_wait : MDEV-21597 wsrep::transaction::start_transaction(): Assertion `active() == false' failed galera_encrypt_tmp_files : Get error failed to enable encryption of temporary files @@ -31,16 +29,11 @@ galera_parallel_simple : MDEV-20318 galera.galera_parallel_simple fails galera_pc_ignore_sb : MDEV-20888 galera.galera_pc_ignore_sb galera_pc_recovery : MDEV-25199 cluster fails to start up galera_shutdown_nonprim : MDEV-21493 galera.galera_shutdown_nonprim -galera_toi_ddl_nonconflicting : MDEV-21518 galera.galera_toi_ddl_nonconflicting -galera_toi_truncate : MDEV-22996 Hang on galera_toi_truncate test case +galera_var_ignore_apply_errors : MDEV-26770 galera_var_ignore_apply_errors fails Server did not transition to READY state galera_var_node_address : MDEV-20485 Galera test failure galera_var_notify_cmd : MDEV-21905 Galera test galera_var_notify_cmd causes hang -galera_var_reject_queries : assertion in inline_mysql_socket_send -galera_var_replicate_myisam_on : MDEV-24062 Galera test failure on galera_var_replicate_myisam_on galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit mysql-wsrep#198 : MDEV-24446: galera.mysql-wsrep#198 MTR failed: query 'reap' failed: 2000: Unknown MySQL error partition : MDEV-19958 Galera test failure on galera.partition query_cache: MDEV-15805 Test failure on galera.query_cache versioning_trx_id: MDEV-18590: galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch -galera_wsrep_provider_unset_set: wsrep_provider is read-only for security reasons -pxc-421: wsrep_provider is read-only for security reasons diff --git a/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result b/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result deleted file mode 100644 index 7a645407004..00000000000 --- a/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result +++ /dev/null @@ -1,23 +0,0 @@ -connection node_2; -connection node_1; -connection node_1; -connection node_2; -connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); -connection node_2; -SET GLOBAL wsrep_provider='none'; -INSERT INTO t1 VALUES (2); -connection node_1; -INSERT INTO t1 VALUES (3); -connection node_2; -SET SESSION wsrep_sync_wait = 0; -INSERT INTO t1 VALUES (4); -SELECT COUNT(*) = 4 FROM t1; -COUNT(*) = 4 -1 -connection node_1; -SELECT COUNT(*) = 3 FROM t1; -COUNT(*) = 3 -1 -DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/pxc-421.result b/mysql-test/suite/galera/r/pxc-421.result deleted file mode 100644 index 058af15c098..00000000000 --- a/mysql-test/suite/galera/r/pxc-421.result +++ /dev/null @@ -1,46 +0,0 @@ -connection node_2; -connection node_1; -connection node_1; -connection node_2; -connection node_1; -set GLOBAL wsrep_slave_threads=26; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); -INSERT INTO t1 (f1) SELECT * from t1 as x1; -connection node_2; -set GLOBAL wsrep_slave_threads=16; -SET GLOBAL wsrep_provider='none'; -INSERT INTO t1 VALUES (2); -connection node_1; -INSERT INTO t1 VALUES (3); -connection node_2; -INSERT INTO t1 VALUES (4); -set GLOBAL wsrep_slave_threads=5; -SELECT COUNT(*) = 5 FROM t1; -COUNT(*) = 5 -1 -connection node_1; -set GLOBAL wsrep_slave_threads=12; -SELECT COUNT(*) = 4 FROM t1; -COUNT(*) = 4 -1 -INSERT INTO t1 VALUES (100), (101), (102); -connection node_2; -set GLOBAL wsrep_slave_threads=5; -INSERT INTO t1 (f1) SELECT * from t1 as x1; -show global variables like 'wsrep_slave_threads'; -Variable_name Value -wsrep_slave_threads 5 -SET GLOBAL wsrep_slave_threads = 1; -SELECT COUNT(*) FROM t1; -COUNT(*) -16 -connection node_1; -SELECT COUNT(*) FROM t1; -COUNT(*) -15 -show global variables like 'wsrep_slave_threads'; -Variable_name Value -wsrep_slave_threads 12 -SET GLOBAL wsrep_slave_threads = 1; -DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test b/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test deleted file mode 100644 index 7f91495fcc4..00000000000 --- a/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test +++ /dev/null @@ -1,50 +0,0 @@ -# -# Test that wsrep_provider can be unset and then set back to its original value -# and replication will continue except for any updates made while the value was 'none' -# - ---source include/galera_cluster.inc ---source include/have_innodb.inc - -# Save original auto_increment_offset values. ---let $node_1=node_1 ---let $node_2=node_2 ---source include/auto_increment_offset_save.inc - ---connection node_1 -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); - ---connection node_2 ---let $wsrep_provider_orig = `SELECT @@wsrep_provider` ---let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` - -SET GLOBAL wsrep_provider='none'; -INSERT INTO t1 VALUES (2); - ---connection node_1 -INSERT INTO t1 VALUES (3); - ---connection node_2 ---disable_query_log ---eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; ---enable_query_log - -SET SESSION wsrep_sync_wait = 0; - ---source include/wait_until_connected_again.inc ---source include/galera_wait_ready.inc - -INSERT INTO t1 VALUES (4); - -# Node #2 has all the inserts -SELECT COUNT(*) = 4 FROM t1; - ---connection node_1 -# Node #1 is missing the insert made while Node #2 was not replicated -SELECT COUNT(*) = 3 FROM t1; - -DROP TABLE t1; - ---source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/pxc-421.test b/mysql-test/suite/galera/t/pxc-421.test deleted file mode 100644 index 33a2b157f18..00000000000 --- a/mysql-test/suite/galera/t/pxc-421.test +++ /dev/null @@ -1,67 +0,0 @@ -# -# PXC-421: Test deadlock involving updates of -# wsrep_provider, wsrep_cluster_address and wsrep_slave_threads. -# - ---source include/galera_cluster.inc ---source include/have_innodb.inc - -# Save original auto_increment_offset values. ---let $node_1=node_1 ---let $node_2=node_2 ---source include/auto_increment_offset_save.inc - ---connection node_1 ---let $wsrep_slave_1 = `SELECT @@wsrep_slave_threads` -set GLOBAL wsrep_slave_threads=26; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); -INSERT INTO t1 (f1) SELECT * from t1 as x1; - ---connection node_2 ---let $wsrep_slave_2 = `SELECT @@wsrep_slave_threads` -set GLOBAL wsrep_slave_threads=16; ---let $wsrep_provider_orig = `SELECT @@wsrep_provider` ---let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` - -SET GLOBAL wsrep_provider='none'; -INSERT INTO t1 VALUES (2); - ---connection node_1 -INSERT INTO t1 VALUES (3); - ---connection node_2 ---disable_query_log ---eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; ---enable_query_log - ---source include/wait_until_connected_again.inc - -INSERT INTO t1 VALUES (4); -set GLOBAL wsrep_slave_threads=5; - -# Node #2 has all the inserts -SELECT COUNT(*) = 5 FROM t1; - ---connection node_1 -set GLOBAL wsrep_slave_threads=12; -# Node #1 is missing the insert made while Node #2 was not replicated -SELECT COUNT(*) = 4 FROM t1; -INSERT INTO t1 VALUES (100), (101), (102); - ---connection node_2 -set GLOBAL wsrep_slave_threads=5; -INSERT INTO t1 (f1) SELECT * from t1 as x1; -show global variables like 'wsrep_slave_threads'; ---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_2 -SELECT COUNT(*) FROM t1; - ---connection node_1 -SELECT COUNT(*) FROM t1; -show global variables like 'wsrep_slave_threads'; ---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_1 -DROP TABLE t1; - ---source include/auto_increment_offset_restore.inc - From 478020171dd048e2584fd774e3cb30a9c4ae690b Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Thu, 7 Oct 2021 11:28:49 -0600 Subject: [PATCH 08/28] MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog outputs This is a documentation-only patch to refine the description of binary mode for the mariadb client. Reviewed By: ============ Andrei Elkin --- client/mysql.cc | 13 ++++++++----- man/mysql.1 | 9 ++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 2baac7b92b8..cd2c37972bc 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1698,11 +1698,14 @@ static struct my_option my_long_options[] = &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binary-mode", 0, - "By default, ASCII '\\0' is disallowed and '\\r\\n' is translated to '\\n'. " - "This switch turns off both features, and also turns off parsing of all client" - "commands except \\C and DELIMITER, in non-interactive mode (for input " - "piped to mysql or loaded using the 'source' command). This is necessary " - "when processing output from mysqlbinlog that may contain blobs.", + "Binary mode allows certain character sequences to be processed as data " + "that would otherwise be treated with a special meaning by the parser. " + "Specifically, this switch turns off parsing of all client commands except " + "\\C and DELIMITER in non-interactive mode (i.e., when binary mode is " + "combined with either 1) piped input, 2) the --batch mysql option, or 3) " + "the 'source' command). Also, in binary mode, occurrences of '\\r\\n' and " + "ASCII '\\0' are preserved within strings, whereas by default, '\\r\\n' is " + "translated to '\\n' and '\\0' is disallowed in user input.", &opt_binary_mode, &opt_binary_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/man/mysql.1 b/man/mysql.1 index 56e753160ce..6c05bbab311 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -206,7 +206,14 @@ option\&. .\" binary-mode option: mysql \fB\-\-binary\-mode\fR .sp -By default, ASCII '\e0' is disallowed and '\er\en' is translated to '\en'\&. This switch turns off both features, and also turns off parsing of all client commands except \eC and DELIMITER, in non-interactive mode (for input piped to mysql or loaded using the 'source' command)\&. This is necessary when processing output from mysqlbinlog that may contain blobs\&. +Binary mode allows certain character sequences to be processed as data that +would otherwise be treated with a special meaning by the parser\&. +Specifically, this switch turns off parsing of all client commands except \eC +and DELIMITER in non-interactive mode (i\&.e\&., when binary mode is combined +with either 1) piped input, 2) the --batch mysql option, or 3) the 'source' +command)\&. Also, in binary mode, occurrences of '\er\en' and ASCII '\e0' are +preserved within strings, whereas by default, '\er\en' is translated to '\en' +and '\e0' is disallowed in user input\&. .RE .sp .RS 4 From 009a8d67b026a39799340b1124d29f41463bfd67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 8 Oct 2021 13:01:00 +0300 Subject: [PATCH 09/28] MDEV-21518 : galera.galera_toi_ddl_nonconflicting MTR failed: 1213: Deadlock found when trying to get lock Add wait condition. --- mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test b/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test index dbd2510cba3..d431fc0b9ed 100644 --- a/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test +++ b/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test @@ -8,6 +8,8 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); --connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1'; +--source include/wait_condition.inc --send ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123); --connection node_1 From 26eb6664636dd969e2e9c14cf0ac5d038a0c403c Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 8 Oct 2021 19:17:06 +0300 Subject: [PATCH 10/28] Make Explain_node::children protected --- sql/sql_explain.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 08af84b3562..852dc2df604 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -121,11 +121,13 @@ public: */ enum explain_connection_type connection_type; +protected: /* A node may have children nodes. When a node's explain structure is created, children nodes may not yet have QPFs. This is why we store ids. */ Dynamic_array children; +public: void add_child(int select_no) { children.append(select_no); From 9bb652062291150449cc36757d8b18642ab769c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Mon, 21 Dec 2020 20:42:52 +0200 Subject: [PATCH 11/28] Deb: Correctly install test_sql_service.so Completes the change that was attempted in 5ca14daf (MDEV-19275). --- debian/mariadb-test.install | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/mariadb-test.install b/debian/mariadb-test.install index bbcc200c368..5276e3e1bca 100644 --- a/debian/mariadb-test.install +++ b/debian/mariadb-test.install @@ -5,6 +5,7 @@ usr/bin/mariadb-test-embedded usr/lib/*/libmariadb3/plugin/auth_test_plugin.so usr/lib/*/libmariadb3/plugin/qa_auth_client.so usr/lib/*/libmariadb3/plugin/qa_auth_interface.so +usr/lib/*/libmariadb3/plugin/test_sql_service.so usr/lib/mysql/plugin/adt_null.so usr/lib/mysql/plugin/auth_0x0100.so usr/lib/mysql/plugin/auth_test_plugin.so From cda072bb4ba9e01d523d8deb995f28aa7a19fe11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Wed, 30 Dec 2020 10:08:23 +0200 Subject: [PATCH 12/28] Deb: Sync build and runtime dependencies from downstream to upstream - Go back to using $MAJOR_VER instead of hard-coded version strings where possible. - Default to 'auto' in NUMJOBS instead of just 1. Will make mysql-test-run faster. - Unify autopkgtest with latest version in Debian, use eatmydata to make mysql-test-run faster. - Salsa-CI: Remove obsolete 'artifacts: true' as that is the default value. - Salsa-CI: Clean away obsolete temporary fixes. - Salsa-CI: Unify with salsa-ci.yml in Debian, including test upgrades from Bullseye to Debian unstable. --- debian/control | 2 +- debian/mariadb-server-10.5.postinst | 2 +- debian/po/de.po | 2 +- debian/po/es.po | 2 +- debian/po/it.po | 2 +- debian/rules | 4 +- debian/salsa-ci.yml | 111 ++++++++++++++++++---------- debian/tests/control | 2 +- debian/tests/upstream | 6 +- 9 files changed, 85 insertions(+), 48 deletions(-) diff --git a/debian/control b/debian/control index 38f96c75dc6..4acf692dd28 100644 --- a/debian/control +++ b/debian/control @@ -492,7 +492,7 @@ Recommends: libhtml-template-perl Pre-Depends: adduser (>= 3.40), debconf, mariadb-common (>= ${source:Version}) -Depends: galera-4 (>=26.4), +Depends: galera-4 (>= 26.4), gawk, iproute2 [linux-any], libdbi-perl, diff --git a/debian/mariadb-server-10.5.postinst b/debian/mariadb-server-10.5.postinst index ade898ce819..13800b7bce2 100644 --- a/debian/mariadb-server-10.5.postinst +++ b/debian/mariadb-server-10.5.postinst @@ -161,7 +161,7 @@ EOF # Clean up old flags before setting new one rm -f $mysql_datadir/debian-*.flag # Flag data dir to avoid downgrades - touch $mysql_datadir/debian-10.5.flag + touch "$mysql_datadir/debian-$MAJOR_VER.flag" # initiate databases. Output is not allowed by debconf :-( # This will fail if we are upgrading an existing database; in this case diff --git a/debian/po/de.po b/debian/po/de.po index 23a0f6b3eb2..5f5e2865036 100644 --- a/debian/po/de.po +++ b/debian/po/de.po @@ -10,7 +10,7 @@ msgstr "" "POT-Creation-Date: 2019-07-23 19:16-0300\n" "PO-Revision-Date: 2016-05-12 22:39+0100\n" "Last-Translator: Chris Leick \n" -"Language-Team: german \n" +"Language-Team: German \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/debian/po/es.po b/debian/po/es.po index 32f4d830106..2f9e2be3566 100644 --- a/debian/po/es.po +++ b/debian/po/es.po @@ -1,4 +1,4 @@ -# mariadb translation to spanish +# MariaDB translation to Spanish # Copyright (C) 2005-2016 Software in the Public Interest, SPI Inc. # This file is distributed under the same license as the mariadb package. # diff --git a/debian/po/it.po b/debian/po/it.po index 9c35f834c05..e9d1cd8a63f 100644 --- a/debian/po/it.po +++ b/debian/po/it.po @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: mariadb-10.5 10.0.13 italian debconf templates\n" +"Project-Id-Version: mariadb-10.5 10.0.13 Italian debconf templates\n" "Report-Msgid-Bugs-To: mariadb-10.5@packages.debian.org\n" "POT-Creation-Date: 2019-07-23 19:16-0300\n" "PO-Revision-Date: 2017-083-20 20:29+0100\n" diff --git a/debian/rules b/debian/rules index df0ee3ee7b6..967dfe9c434 100755 --- a/debian/rules +++ b/debian/rules @@ -34,8 +34,8 @@ ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) MAKEFLAGS += -j$(NUMJOBS) else - # NUMJOBS cannot be empty as it is used as a parameter to mtr, default to 1. - NUMJOBS = 1 + # NUMJOBS cannot be empty as it is used as a parameter to mtr, default to 'auto'. + NUMJOBS = auto endif # RocksDB cannot build on 32-bit platforms diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml index 98bcab60b8f..c95efe0de3a 100644 --- a/debian/salsa-ci.yml +++ b/debian/salsa-ci.yml @@ -21,7 +21,7 @@ stages: - build - test - upgrade in Sid - - upgrade from Buster/Stretch + - upgrade from Bullseye/Buster/Stretch - upgrade extras - test extras - publish # Stage referenced by Salsa-CI template aptly stanza, so must exist even though not used @@ -46,6 +46,11 @@ build: - ccache -s # Show ccache stats to validate it worked - mv ${CCACHE_TMP_DIR} ${CCACHE_WORK_DIR} || true +build bullseye-backports: + extends: .build-package + variables: + RELEASE: bullseye-backports + build buster-backports: extends: .build-package script: @@ -121,7 +126,6 @@ blhc: stage: test extras needs: - job: build native deb - artifacts: true # In addition to Salsa-CI, also run these fully MariaDB specific build jobs @@ -148,9 +152,10 @@ blhc: dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed service mysql status || service mariadb status # Early MariaDB 10.5 only had 'mariadb' mysql --skip-column-names -e "select @@version, @@version_comment" # Show version - echo 'SHOW DATABASES;' | mysql # List databases before upgrade - mysql -e "SELECT Host, User, plugin,authentication_string FROM user;" mysql - mysql -e "SELECT * FROM plugin;" mysql + mysql --table -e 'SHOW DATABASES;' # List databases before upgrade + mysql --table -e "SELECT host,user,plugin,authentication_string FROM user;" mysql + mysql --table -e "SELECT * FROM plugin;" mysql + mysql --table -e "SHOW PLUGINS;" mysql .test-enable-sid-repos: &test-enable-sid-repos | # Replace any old repos with just Sid @@ -172,10 +177,12 @@ blhc: cp -ra /etc/mysql debug/etc-mysql cp -ra /var/log/mysql debug/var-log-mysql mariadb --skip-column-names -e "select @@version, @@version_comment" # Show version - echo 'SHOW DATABASES;' | mariadb # List databases - mariadb -e "create database test; use test; create table t(a int primary key) engine=innodb; insert into t values (1); select * from t; drop table t; drop database test;" # Test that InnoDB works - mariadb -e "SELECT Host, User, plugin,authentication_string FROM user;" mysql - mariadb -e "SELECT * FROM plugin;" mysql + mariadb --table -e 'SHOW DATABASES;' # List databases + mariadb --table -e "SELECT host,user,plugin,authentication_string FROM user;" mysql + mariadb --table -e "SELECT * FROM plugin;" mysql + mariadb --table -e "SHOW PLUGINS;" mysql + # Test that InnoDB works and that command 'mysql' is also still usable + mysql -e "CREATE DATABASE test; USE test; CREATE TABLE t(a INT PRIMARY KEY) ENGINE=INNODB; INSERT INTO t VALUEs (1); SELECT * FROM t; DROP TABLE t; DROP DATABASE test;" .test-verify-libs: &test-verify-libs # Don't use a collapsed command as Gitlab-CI would hide each command from the output @@ -193,7 +200,6 @@ fresh install: stage: test needs: - job: build - artifacts: true image: debian:${RELEASE} artifacts: when: always @@ -215,7 +221,6 @@ mariadb-10.5 Sid upgrade: stage: upgrade in Sid needs: - job: build - artifacts: true image: debian:${RELEASE} artifacts: when: always @@ -233,11 +238,36 @@ mariadb-10.5 Sid upgrade: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ -mariadb-10.3 Buster to mariadb-10.5 upgrade: - stage: upgrade from Buster/Stretch +mariadb-10.5 Bullseye to mariadb-10.5 upgrade: + stage: upgrade from Bullseye/Buster/Stretch + needs: + - job: build + image: debian:bullseye + artifacts: + when: always + name: "$CI_BUILD_NAME" + paths: + - ${WORKING_DIR}/debug + script: + - *test-prepare-container + # Install everything MariaDB currently in Debian Bullseye + - apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadb*' + # Verify installation of MariaDB from Bullseye + - *test-verify-initial + - *test-enable-sid-repos + - *test-install + - service mariadb status + - *test-verify-final + variables: + GIT_STRATEGY: none + except: + variables: + - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ + +mariadb-10.3 Buster to mariadb-10.5 upgrade: + stage: upgrade from Bullseye/Buster/Stretch needs: - job: build - artifacts: true image: debian:buster artifacts: when: always @@ -261,10 +291,9 @@ mariadb-10.3 Buster to mariadb-10.5 upgrade: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ mariadb-10.1 Stretch to mariadb-10.5 upgrade: - stage: upgrade from Buster/Stretch + stage: upgrade from Bullseye/Buster/Stretch needs: - job: build - artifacts: true image: debian:stretch artifacts: when: always @@ -278,8 +307,7 @@ mariadb-10.1 Stretch to mariadb-10.5 upgrade: - apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadbd*' 'libmariadbclient*' # Verify installation of MariaDB from Stretch - *test-verify-initial - # Remove manpages 4.10 that conflicts with manpages-dev 5.10 on console_ioctl.4.gz - - apt-get remove -y manpages + - apt-get remove -y manpages # Workaround for Bug#99375 - *test-enable-sid-repos - *test-install - service mysql status @@ -294,7 +322,6 @@ test basic features: stage: test needs: - job: build - artifacts: true image: debian:${RELEASE} artifacts: when: always @@ -378,7 +405,6 @@ build mariadbclient consumer Python-MySQLdb: stage: test needs: - job: build - artifacts: true image: debian:${RELEASE} script: - *test-prepare-container @@ -400,7 +426,6 @@ libmysql* to libmariadb* upgrade: stage: upgrade in Sid needs: - job: build - artifacts: true image: debian:${RELEASE} artifacts: when: always @@ -434,7 +459,6 @@ default-libmysqlclient-dev Sid upgrade: stage: upgrade in Sid needs: - job: build - artifacts: true image: debian:${RELEASE} artifacts: when: always @@ -452,10 +476,9 @@ default-libmysqlclient-dev Sid upgrade: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ default-libmysqlclient-dev Buster upgrade: - stage: upgrade from Buster/Stretch + stage: upgrade from Bullseye/Buster/Stretch needs: - job: build - artifacts: true image: debian:buster artifacts: when: always @@ -474,10 +497,9 @@ default-libmysqlclient-dev Buster upgrade: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ default-libmysqlclient-dev Stretch upgrade: - stage: upgrade from Buster/Stretch + stage: upgrade from Bullseye/Buster/Stretch needs: - job: build - artifacts: true image: debian:stretch artifacts: when: always @@ -488,8 +510,7 @@ default-libmysqlclient-dev Stretch upgrade: - *test-prepare-container - apt-get install -y pkg-config default-libmysqlclient-dev - pkg-config --list-all - # Remove manpages 4.10 that conflicts with manpages-dev 5.10 on console_ioctl.4.gz - - apt-get remove -y manpages + - apt-get remove -y manpages # Workaround for Bug#99375 - *test-enable-sid-repos - *test-install-all-libs - *test-verify-libs @@ -497,13 +518,36 @@ default-libmysqlclient-dev Stretch upgrade: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ +mariadb-connector-c Stretch upgrade: + stage: upgrade from Bullseye/Buster/Stretch + needs: + - job: build + image: debian:stretch + artifacts: + when: always + name: "$CI_BUILD_NAME" + paths: + - ${WORKING_DIR}/debug + script: + - *test-prepare-container + - apt-get install -y pkg-config libmariadb2 libmariadb-dev libmariadb-dev-compat + - pkg-config --list-all + - apt-get remove -y manpages # Workaround for Bug#99375 + - *test-enable-sid-repos + - *test-install-all-libs + - *test-verify-libs + except: + variables: + - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ + allow_failure: true + # Upgrading libc from Stretch to Bookworm is not possible due to Bug#993755 + # Upgrading from MySQL 8.0 with datadir in place is not possible. Users need to do a data dump. # The Debian maintainer scripts detect this situation and simply moves old datadir aside and start fresh. mysql-8.0 Sid to mariadb-10.5 upgrade: stage: upgrade in Sid needs: - job: build - artifacts: true image: debian:sid artifacts: when: always @@ -531,7 +575,6 @@ mysql-8.0 Focal to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build buster-backports - artifacts: true image: debian:buster artifacts: when: always @@ -565,7 +608,6 @@ mysql-5.7 Bionic to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build stretch-backports - artifacts: true image: debian:stretch artifacts: when: always @@ -601,7 +643,6 @@ mariadb.org-10.5 to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build - artifacts: true image: debian:sid artifacts: when: always @@ -614,7 +655,6 @@ mariadb.org-10.5 to mariadb-10.5 upgrade: - curl -sS https://mariadb.org/mariadb_release_signing_key.asc -o /etc/apt/trusted.gpg.d/mariadb.asc - echo 'deb http://mirror.one.com/mariadb/repo/10.5/debian sid main' > /etc/apt/sources.list.d/mariadb.list - apt-get update - - *test-install-readline-in-sid-for-backwards-compat # The 10.5.9 release is missing mariadb-plugin-columnstore, define all other packages but it to avoid hitting the error: # The following packages have unmet dependencies: # mariadb-plugin-columnstore : Depends: mariadb-server-10.5 (= 1:10.5.8+maria~sid) but 1:10.5.9+maria~sid is to be installed @@ -641,7 +681,6 @@ mariadb.org-10.4 to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build - artifacts: true image: debian:sid artifacts: when: always @@ -675,7 +714,6 @@ mariadb.org-10.3 to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build - artifacts: true image: debian:sid artifacts: when: always @@ -712,7 +750,6 @@ mariadb.org-10.2 to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build - artifacts: true image: debian:sid artifacts: when: always @@ -749,7 +786,6 @@ mysql.com-5.7 to mariadb-10.5 upgrade: stage: upgrade extras needs: - job: build buster-backports - artifacts: true image: debian:buster artifacts: when: always @@ -781,7 +817,6 @@ percona-xtradb-5.7 to mariadb-10.5 upgrade (MDEV-22679): stage: upgrade extras needs: - job: build buster-backports - artifacts: true image: debian:buster artifacts: when: always diff --git a/debian/tests/control b/debian/tests/control index 3706829904f..16e091cfa6b 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -7,5 +7,5 @@ Depends: mariadb-plugin-rocksdb | mariadb-server-10.5 Restrictions: allow-stderr needs-root isolation-container Tests: upstream -Depends: mariadb-test +Depends: mariadb-test, eatmydata Restrictions: allow-stderr breaks-testbed diff --git a/debian/tests/upstream b/debian/tests/upstream index 4e9b3a7cc8b..d4f31dabef4 100644 --- a/debian/tests/upstream +++ b/debian/tests/upstream @@ -60,7 +60,9 @@ fi cd /usr/share/mysql/mysql-test echo "starting mysql-test-tun.pl..." -perl -I. ./mysql-test-run.pl --suite=main --vardir="$WORKDIR/var" --tmpdir="$WORKDIR/tmp" \ +eatmydata perl -I. ./mysql-test-run.pl --suite=main \ + --vardir="$WORKDIR/var" --tmpdir="$WORKDIR/tmp" \ --parallel=auto --skip-rpl \ - --force --skip-test-list=$SKIP_TEST_LST $@ 2>&1 + --force --skip-test-list=$SKIP_TEST_LST \ + --xml-report=$AUTOPKGTEST_ARTIFACTS/mysql-test-run-junit.xml $@ 2>&1 echo "run: OK" From 1d71dacd519a8ea51e7c8a9207e0b146d794c8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Oct 2021 10:15:52 +0300 Subject: [PATCH 13/28] MDEV-24454 fixup: Fix plugins.feedback_plugin_send In commit 3690c549c6e72646ba74f6b4c83813ee4ac3aea4 this test was not adjusted. --- .../plugins/r/feedback_plugin_send.result | 20 +++++++++++++++++-- .../suite/plugins/t/feedback_plugin_send.test | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result index 70dfbcb62dc..fec42f577ad 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_send.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result @@ -24,6 +24,22 @@ VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used latin1_swedish_ci 1 Collation used utf8_bin 1 Collation used utf8_general_ci +prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME"; +execute stmt; +VARIABLE_VALUE>0 VARIABLE_NAME +1 Collation used binary +1 Collation used latin1_bin +1 Collation used latin1_swedish_ci +1 Collation used utf8_bin +1 Collation used utf8_general_ci +execute stmt; +VARIABLE_VALUE>0 VARIABLE_NAME +1 Collation used binary +1 Collation used latin1_bin +1 Collation used latin1_swedish_ci +1 Collation used utf8_bin +1 Collation used utf8_general_ci +deallocate prepare stmt; set global sql_mode=ONLY_FULL_GROUP_BY; -6: feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent -6: feedback plugin: server replied 'ok' +feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent +feedback plugin: server replied 'ok' diff --git a/mysql-test/suite/plugins/t/feedback_plugin_send.test b/mysql-test/suite/plugins/t/feedback_plugin_send.test index b28f9d4cb38..0ea1814ec29 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_send.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_send.test @@ -38,6 +38,6 @@ perl; while ($_=) { $logg{$&}++ if /feedback plugin:.*/; } - print "$logg{$_}: $_\n" for sort keys %logg; + print "$_\n" for sort keys %logg; close LOG; EOF From 53c8d559a596993cf3c7b020b19e2c345952fb71 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Fri, 8 Oct 2021 10:11:31 +0200 Subject: [PATCH 14/28] Make test galera_sr_kill_slave_before_apply deterministic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Handle the (rare) case where the ongoing transaction is aborted, if the ongoing transaction is considered orphaned. This happens if the node delivers two consecutive primary views with the * Add ignorable warning to suite.pm Reviewed-by: Jan Lindström --- .../galera_sr_kill_slave_before_apply.result | 16 +++++--- mysql-test/suite/galera_3nodes_sr/suite.pm | 1 + .../t/galera_sr_kill_slave_before_apply.test | 37 ++++++++++++++----- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result index e9dc5518e96..933038e00f1 100644 --- a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result @@ -32,14 +32,18 @@ Killing server ... # restart connection node_1; COMMIT; -SELECT COUNT(*) = 5 FROM t1; -COUNT(*) = 5 +count_match 1 +count_match +1 +connection node_1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 connection node_2; -SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; -COUNT(*) = 0 -1 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 connection node_1; DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera_3nodes_sr/suite.pm b/mysql-test/suite/galera_3nodes_sr/suite.pm index a65c2b5df30..ee651fe8984 100644 --- a/mysql-test/suite/galera_3nodes_sr/suite.pm +++ b/mysql-test/suite/galera_3nodes_sr/suite.pm @@ -37,6 +37,7 @@ push @::global_suppressions, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(JOINED\). Message ignored.|, qr(WSREP: Action message in non-primary configuration from member [0-9]*), + qr|WSREP: .*core_handle_uuid_msg.*|, qr(WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0. WSREP_SYNC_WAIT_BEFORE_READ is on), qr(WSREP: JOIN message from member .* in non-primary configuration. Ignored.), ); diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test index 92566fa6323..ea549a6bea2 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test @@ -51,20 +51,37 @@ INSERT INTO t1 VALUES (5); --source include/kill_galera.inc --source include/start_mysqld.inc -# Expect that the SR table will get some entries after the restart ---let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; ---source include/wait_condition.inc +--connection node_1 +# The following COMMIT usually succeeds. Due to timing, +# it is however possible that this node delivers the same +# view twice during configuration change. In which case +# this transaction will mistakenly be considered orphaned, +# and aborted. +--error 0, ER_LOCK_DEADLOCK +COMMIT; + + +--disable_query_log +if ($mysql_errno == 0) { + --connection node_1 + SELECT COUNT(*) = 5 AS count_match FROM t1; + --connection node_2 + SELECT COUNT(*) = 5 AS count_match FROM t1; +} + +if ($mysql_errno == 1213) { + --connection node_1 + SELECT COUNT(*) = 0 AS count_match FROM t1; + --connection node_2 + SELECT COUNT(*) = 0 AS count_match FROM t1; +} +--enable_query_log --connection node_1 -COMMIT; -SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; --connection node_2 -SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; ---let $wait_condition = SELECT COUNT(*) = 5 FROM t1; ---source include/wait_condition.inc - -SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; --connection node_1 DROP TABLE t1; From 275e7d23f73f036b31b2d67f9256008c8e5561e1 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 22 Sep 2021 19:09:37 +0300 Subject: [PATCH 15/28] MDEV-14846 InnoDB: assertion on trx->state because of deadlock error ignored On deadlock transaction is rolled back (and trx->state is cleared) but SELECT continued the loop because evaluate_join_record() ignored the error status returned from lower join evaluation. val_int() does not return error status so it is checked by thd->is_error(). Test case was created by Thirunarayanan Balathandayuthapani --- mysql-test/suite/innodb/r/mdev-14846.result | 52 +++++++++++++++ mysql-test/suite/innodb/t/mdev-14846.opt | 1 + mysql-test/suite/innodb/t/mdev-14846.test | 70 +++++++++++++++++++++ sql/sql_select.cc | 41 +++++++----- 4 files changed, 147 insertions(+), 17 deletions(-) create mode 100644 mysql-test/suite/innodb/r/mdev-14846.result create mode 100644 mysql-test/suite/innodb/t/mdev-14846.opt create mode 100644 mysql-test/suite/innodb/t/mdev-14846.test diff --git a/mysql-test/suite/innodb/r/mdev-14846.result b/mysql-test/suite/innodb/r/mdev-14846.result new file mode 100644 index 00000000000..219bd718feb --- /dev/null +++ b/mysql-test/suite/innodb/r/mdev-14846.result @@ -0,0 +1,52 @@ +CREATE TABLE t1 ( +pk INT, +f1 VARCHAR(10) NOT NULL, +f2 VARCHAR(10) NULL, +f3 INT UNSIGNED NULL, +KEY (f1), +PRIMARY KEY (pk) +) ENGINE=InnoDB; +CREATE OR REPLACE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1,'k','g',6),(2,'y','r',0),(3,'t','q',1),(4,'a','r',NULL),(5,'z','t',NULL); +CREATE TABLE t2 (f VARCHAR(10) NULL) ENGINE=InnoDB; +INSERT INTO t2 VALUES (NULL),('g'),('e'),('g'); +CREATE TABLE t3 ( +f1 VARCHAR(10) NOT NULL, +f2 VARCHAR(10) NULL, +f3 INT UNSIGNED NULL +) ENGINE=InnoDB; +INSERT INTO t3 VALUES ('k','n',9),('y','b',8),('m','w',6); +CREATE TABLE t4 (f INT NULL) ENGINE=InnoDB; +INSERT INTO t4 VALUES (8),(9); +UPDATE t1 SET t1.pk = -109 WHERE t1.f1 IN ( SELECT 'a' FROM t4 WHERE f >= 1 ); +SET DEBUG_SYNC='now SIGNAL con1_dml'; +connect con1,localhost,root,,test; +SET DEBUG_SYNC='now WAIT_FOR con1_dml'; +begin; +SELECT * FROM t1 for update; +pk f1 f2 f3 +-109 a r NULL +1 k g 6 +2 y r 0 +3 t q 1 +5 z t NULL +SET DEBUG_SYNC='now SIGNAL default_dml'; +connection default; +SET DEBUG_SYNC='now WAIT_FOR default_dml'; +UPDATE t3 AS alias1 LEFT JOIN t3 AS alias2 ON ( alias1.f1 <> alias1.f2 ) SET alias1.f3 = 59 WHERE ( EXISTS ( SELECT t1.f3 FROM t1 WHERE t1.f1 = alias1.f1 ) ) OR alias2.f1 = 'h'; +connect con2,localhost,root,,test; +set debug_sync='now WAIT_FOR default_dml'; +SET DEBUG_SYNC='now SIGNAL con1_dml2'; +disconnect con2; +connection con1; +SET DEBUG_SYNC='now WAIT_FOR con1_dml2'; +UPDATE v4, t1 SET t1.pk = 76 WHERE t1.f2 IN ( SELECT t2.f FROM t2 INNER JOIN t3 ); +connection default; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection con1; +COMMIT; +disconnect con1; +connection default; +DROP VIEW v4; +DROP TABLE t1, t2, t3, t4; +set debug_sync= reset; diff --git a/mysql-test/suite/innodb/t/mdev-14846.opt b/mysql-test/suite/innodb/t/mdev-14846.opt new file mode 100644 index 00000000000..c8fe0561390 --- /dev/null +++ b/mysql-test/suite/innodb/t/mdev-14846.opt @@ -0,0 +1 @@ +--loose-innodb_lock_waits diff --git a/mysql-test/suite/innodb/t/mdev-14846.test b/mysql-test/suite/innodb/t/mdev-14846.test new file mode 100644 index 00000000000..adcefecd52f --- /dev/null +++ b/mysql-test/suite/innodb/t/mdev-14846.test @@ -0,0 +1,70 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1 ( + pk INT, + f1 VARCHAR(10) NOT NULL, + f2 VARCHAR(10) NULL, + f3 INT UNSIGNED NULL, + KEY (f1), + PRIMARY KEY (pk) +) ENGINE=InnoDB; + +CREATE OR REPLACE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1,'k','g',6),(2,'y','r',0),(3,'t','q',1),(4,'a','r',NULL),(5,'z','t',NULL); + +CREATE TABLE t2 (f VARCHAR(10) NULL) ENGINE=InnoDB; +INSERT INTO t2 VALUES (NULL),('g'),('e'),('g'); + +CREATE TABLE t3 ( + f1 VARCHAR(10) NOT NULL, + f2 VARCHAR(10) NULL, + f3 INT UNSIGNED NULL +) ENGINE=InnoDB; + +INSERT INTO t3 VALUES ('k','n',9),('y','b',8),('m','w',6); + +CREATE TABLE t4 (f INT NULL) ENGINE=InnoDB; +INSERT INTO t4 VALUES (8),(9); +UPDATE t1 SET t1.pk = -109 WHERE t1.f1 IN ( SELECT 'a' FROM t4 WHERE f >= 1 ); +SET DEBUG_SYNC='now SIGNAL con1_dml'; + +--connect (con1,localhost,root,,test) +SET DEBUG_SYNC='now WAIT_FOR con1_dml'; +begin; +SELECT * FROM t1 for update; # Holds x lock of all records in the table t1 +SET DEBUG_SYNC='now SIGNAL default_dml'; + +--connection default +SET DEBUG_SYNC='now WAIT_FOR default_dml'; +--send UPDATE t3 AS alias1 LEFT JOIN t3 AS alias2 ON ( alias1.f1 <> alias1.f2 ) SET alias1.f3 = 59 WHERE ( EXISTS ( SELECT t1.f3 FROM t1 WHERE t1.f1 = alias1.f1 ) ) OR alias2.f1 = 'h' +# It holds the lock of all record in t3 and tries to acquire record lock for the table t1. + +--connect (con2,localhost,root,,test) +set debug_sync='now WAIT_FOR default_dml'; +let $wait_condition= +select count(*) > 0 from information_schema.innodb_lock_waits; +--source include/wait_condition.inc +SET DEBUG_SYNC='now SIGNAL con1_dml2'; +disconnect con2; + +# Cleanup +--connection con1 +SET DEBUG_SYNC='now WAIT_FOR con1_dml2'; +UPDATE v4, t1 SET t1.pk = 76 WHERE t1.f2 IN ( SELECT t2.f FROM t2 INNER JOIN t3 ); +# It holds the record lock on table t1 and tries to acquire record lock on t3. +# leads to deadlock (con1 trx is waiting for default trx and vice versa) + +--connection default +--error ER_LOCK_DEADLOCK +--reap + +connection con1; +COMMIT; +disconnect con1; + +--connection default +DROP VIEW v4; +DROP TABLE t1, t2, t3, t4; +set debug_sync= reset; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ff584e936b7..bf33623a684 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -19045,26 +19045,33 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, will be re-evaluated again. It could be fixed, but, probably, it's not worth doing now. */ - if (tab->select_cond && !tab->select_cond->val_int()) + if (tab->select_cond) { - /* The condition attached to table tab is false */ - if (tab == join_tab) + const longlong res= tab->select_cond->val_int(); + if (join->thd->is_error()) + DBUG_RETURN(NESTED_LOOP_ERROR); + + if (!res) { - found= 0; - if (not_exists_opt_is_applicable) - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); - } - else - { - /* - Set a return point if rejected predicate is attached - not to the last table of the current nest level. - */ - join->return_tab= tab; - if (not_exists_opt_is_applicable) - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + /* The condition attached to table tab is false */ + if (tab == join_tab) + { + found= 0; + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + } else - DBUG_RETURN(NESTED_LOOP_OK); + { + /* + Set a return point if rejected predicate is attached + not to the last table of the current nest level. + */ + join->return_tab= tab; + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + else + DBUG_RETURN(NESTED_LOOP_OK); + } } } } From 89936f11e965472d65fbee1e240f3d4b7726e77f Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 28 Sep 2021 16:00:41 +0300 Subject: [PATCH 16/28] MDEV-18278 Misleading error message in error log upon failed table creation If error_reported is not set upper caller open_table_from_share() throws error ER_NOT_FORM_FILE itself via open_table_error(). --- mysql-test/r/default.result | 8 ++++++++ mysql-test/t/default.test | 6 ++++++ sql/table.cc | 3 +++ 3 files changed, 17 insertions(+) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index 369734ae92a..1a35a29aa7f 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3396,4 +3396,12 @@ CREATE OR REPLACE TABLE t1(i int); ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT' DROP TABLE t1; +# +# MDEV-18278 Misleading error message in error log upon failed table creation +# +create table t1 (a int as (a)); +ERROR 01000: Expression for field `a` is referring to uninitialized field `a` +show warnings; +Level Code Message +Error 4029 Expression for field `a` is referring to uninitialized field `a` # end of 10.2 test diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index aec518d94a6..472b1fa4796 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -2109,5 +2109,11 @@ CREATE OR REPLACE TABLE t1(i int); ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; DROP TABLE t1; +--echo # +--echo # MDEV-18278 Misleading error message in error log upon failed table creation +--echo # +--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD +create table t1 (a int as (a)); +show warnings; --echo # end of 10.2 test diff --git a/sql/table.cc b/sql/table.cc index 281b8f82abc..87b3c158a67 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1157,7 +1157,10 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, if (check_vcol_forward_refs(field, field->vcol_info) || check_vcol_forward_refs(field, field->check_constraint) || check_vcol_forward_refs(field, field->default_value)) + { + *error_reported= true; goto end; + } } res=0; From 911c803db19de7ffd45c39ff3614abcf19c63536 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 11 Oct 2021 13:36:06 +0300 Subject: [PATCH 17/28] MDEV-22660 System versioning cleanups - Cleaned up Vers_parse_info::check_sys_fields(); - Renamed VERS_SYS_START_FLAG, VERS_SYS_END_FLAG to VERS_ROW_START, VERS_ROW_END. --- include/mysql_com.h | 6 ++-- sql/field.cc | 4 +-- sql/field.h | 13 +++++-- sql/handler.cc | 86 +++++++++++++++++++-------------------------- sql/item_vers.cc | 2 +- sql/sql_lex.cc | 4 +-- sql/sql_show.cc | 6 ++-- sql/sql_table.cc | 6 ++-- sql/table.cc | 4 +-- 9 files changed, 64 insertions(+), 67 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index b1534b1d746..234b6133676 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -193,13 +193,13 @@ enum enum_indicator_type #define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT) #define FIELD_IS_DROPPED (1U << 26) /* Intern: Field is being dropped */ -#define VERS_SYS_START_FLAG (1 << 27) /* autogenerated column declared with +#define VERS_ROW_START (1 << 27) /* autogenerated column declared with `generated always as row start` (see II.a SQL Standard) */ -#define VERS_SYS_END_FLAG (1 << 28) /* autogenerated column declared with +#define VERS_ROW_END (1 << 28) /* autogenerated column declared with `generated always as row end` (see II.a SQL Standard).*/ -#define VERS_SYSTEM_FIELD (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG) +#define VERS_SYSTEM_FIELD (VERS_ROW_START | VERS_ROW_END) #define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support system versioning when table itself supports it*/ diff --git a/sql/field.cc b/sql/field.cc index cba6df52b62..ddb309c3262 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2360,7 +2360,7 @@ Field *Field::make_new_field(MEM_ROOT *root, TABLE *new_table, tmp->unireg_check= Field::NONE; tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG | - VERS_SYS_START_FLAG | VERS_SYS_END_FLAG | + VERS_ROW_START | VERS_ROW_END | VERS_UPDATE_UNVERSIONED_FLAG); tmp->reset_fields(); tmp->invisible= VISIBLE; @@ -10967,7 +10967,7 @@ Field *make_field(TABLE_SHARE *share, f_is_zerofill(pack_flag) != 0, f_is_dec(pack_flag) == 0); case MYSQL_TYPE_LONGLONG: - if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) + if (flags & (VERS_ROW_START|VERS_ROW_END)) { return new (mem_root) Field_vers_trx_id(ptr, field_length, null_pos, null_bit, diff --git a/sql/field.h b/sql/field.h index 825a0dae7aa..7d60e0953f8 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1499,7 +1499,7 @@ public: bool vers_sys_field() const { - return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG); + return flags & (VERS_ROW_START | VERS_ROW_END); } bool vers_update_unversioned() const @@ -4469,7 +4469,7 @@ public: } bool vers_sys_field() const { - return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG); + return flags & (VERS_ROW_START | VERS_ROW_END); } void create_length_to_internal_length_bit(); void create_length_to_internal_length_newdecimal(); @@ -4813,6 +4813,15 @@ public: } /* Used to make a clone of this object for ALTER/CREATE TABLE */ Create_field *clone(MEM_ROOT *mem_root) const; + + bool is_some_bigint() const + { + return type_handler() == &type_handler_longlong || + type_handler() == &type_handler_vers_trx_id; + } + + bool vers_check_timestamp(const Lex_table_name &table_name) const; + bool vers_check_bigint(const Lex_table_name &table_name) const; }; diff --git a/sql/handler.cc b/sql/handler.cc index c0a810a72bc..f46e51a34ce 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7122,11 +7122,11 @@ bool Vers_parse_info::is_end(const char *name) const } bool Vers_parse_info::is_start(const Create_field &f) const { - return f.flags & VERS_SYS_START_FLAG; + return f.flags & VERS_ROW_START; } bool Vers_parse_info::is_end(const Create_field &f) const { - return f.flags & VERS_SYS_END_FLAG; + return f.flags & VERS_ROW_END; } static Create_field *vers_init_sys_field(THD *thd, const char *field_name, int flags, bool integer) @@ -7186,8 +7186,8 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info) system_time= start_end_t(default_start, default_end); as_row= system_time; - if (vers_create_sys_field(thd, default_start, alter_info, VERS_SYS_START_FLAG) || - vers_create_sys_field(thd, default_end, alter_info, VERS_SYS_END_FLAG)) + if (vers_create_sys_field(thd, default_start, alter_info, VERS_ROW_START) || + vers_create_sys_field(thd, default_end, alter_info, VERS_ROW_END)) { return true; } @@ -7346,7 +7346,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info, return true; } my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0), - f->flags & VERS_SYS_START_FLAG ? "START" : "END", f->field_name.str); + f->flags & VERS_ROW_START ? "START" : "END", f->field_name.str); return true; } } @@ -7451,13 +7451,13 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_ while ((f= it++)) { - if (f->flags & VERS_SYS_START_FLAG) + if (f->flags & VERS_ROW_START) { f_start= f; if (f_end) break; } - else if (f->flags & VERS_SYS_END_FLAG) + else if (f->flags & VERS_ROW_END) { f_end= f; if (f_start) @@ -7519,37 +7519,31 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name, return false; } -static bool is_versioning_timestamp(const Create_field *f) -{ - return f->type_handler() == &type_handler_timestamp2 && - f->length == MAX_DATETIME_FULL_WIDTH; -} -static bool is_some_bigint(const Create_field *f) +bool Create_field::vers_check_timestamp(const Lex_table_name &table_name) const { - return f->type_handler() == &type_handler_longlong || - f->type_handler() == &type_handler_vers_trx_id; -} + if (type_handler() == &type_handler_timestamp2 && + length == MAX_DATETIME_FULL_WIDTH) + return false; -static bool is_versioning_bigint(const Create_field *f) -{ - return is_some_bigint(f) && f->flags & UNSIGNED_FLAG && - f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1; -} - -static bool require_timestamp(const Create_field *f, Lex_table_name table_name) -{ - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, "TIMESTAMP(6)", + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), field_name.str, "TIMESTAMP(6)", table_name.str); return true; } -static bool require_bigint(const Create_field *f, Lex_table_name table_name) + + +bool Create_field::vers_check_bigint(const Lex_table_name &table_name) const { - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, + if (is_some_bigint() && flags & UNSIGNED_FLAG && + length == MY_INT64_NUM_DECIMAL_DIGITS - 1) + return false; + + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), field_name.str, "BIGINT(20) UNSIGNED", table_name.str); return true; } + bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, const Lex_table_name &db, Alter_info *alter_info, @@ -7564,37 +7558,31 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, List_iterator it(alter_info->create_list); while (Create_field *f= it++) { - if (!row_start && f->flags & VERS_SYS_START_FLAG) + if (!row_start && f->flags & VERS_ROW_START) row_start= f; - else if (!row_end && f->flags & VERS_SYS_END_FLAG) + else if (!row_end && f->flags & VERS_ROW_END) row_end= f; } - const bool expect_timestamp= - !can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end); - - if (expect_timestamp) + if (!can_native || + !row_start->is_some_bigint() || + !row_end->is_some_bigint()) { - if (!is_versioning_timestamp(row_start)) - return require_timestamp(row_start, table_name); - - if (!is_versioning_timestamp(row_end)) - return require_timestamp(row_end, table_name); + if (row_start->vers_check_timestamp(table_name) || + row_end->vers_check_timestamp(table_name)) + return true; } else { - if (!is_versioning_bigint(row_start)) - return require_bigint(row_start, table_name); + if (row_start->vers_check_bigint(table_name) || + row_end->vers_check_bigint(table_name)) + return true; - if (!is_versioning_bigint(row_end)) - return require_bigint(row_end, table_name); - } - - if (is_versioning_bigint(row_start) && is_versioning_bigint(row_end) && - !TR_table::use_transaction_registry) - { - my_error(ER_VERS_TRT_IS_DISABLED, MYF(0)); - return true; + if (!TR_table::use_transaction_registry) + { + my_error(ER_VERS_TRT_IS_DISABLED, MYF(0)); + return true; + } } return false; diff --git a/sql/item_vers.cc b/sql/item_vers.cc index 76cda6a5ea2..6103c53fd51 100644 --- a/sql/item_vers.cc +++ b/sql/item_vers.cc @@ -30,7 +30,7 @@ bool Item_func_history::val_bool() { Item_field *f= static_cast(args[0]); DBUG_ASSERT(f->fixed); - DBUG_ASSERT(f->field->flags & VERS_SYS_END_FLAG); + DBUG_ASSERT(f->field->flags & VERS_ROW_END); return !f->field->is_max(); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4fc8ebb5a60..00e1d30f209 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -8322,7 +8322,7 @@ bool LEX::last_field_generated_always_as_row_start() Vers_parse_info &info= vers_get_info(); Lex_ident *p= &info.as_row.start; return last_field_generated_always_as_row_start_or_end(p, "START", - VERS_SYS_START_FLAG); + VERS_ROW_START); } @@ -8331,7 +8331,7 @@ bool LEX::last_field_generated_always_as_row_end() Vers_parse_info &info= vers_get_info(); Lex_ident *p= &info.as_row.end; return last_field_generated_always_as_row_start_or_end(p, "END", - VERS_SYS_END_FLAG); + VERS_ROW_END); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 35e0c7364f5..5a3c27832ac 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2288,11 +2288,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } else { - if (field->flags & VERS_SYS_START_FLAG) + if (field->flags & VERS_ROW_START) { packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW START")); } - else if (field->flags & VERS_SYS_END_FLAG) + else if (field->flags & VERS_ROW_END) { packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW END")); } @@ -6080,7 +6080,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, } else if (field->flags & VERS_SYSTEM_FIELD) { - if (field->flags & VERS_SYS_START_FLAG) + if (field->flags & VERS_ROW_START) { table->field[21]->store(STRING_WITH_LEN("ROW START"), cs); buf.set(STRING_WITH_LEN("STORED GENERATED"), cs); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9aae74a613d..2b796403dc8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8209,7 +8209,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, def= new (thd->mem_root) Create_field(thd, field, field); def->invisible= INVISIBLE_SYSTEM; alter_info->flags|= ALTER_CHANGE_COLUMN; - if (field->flags & VERS_SYS_START_FLAG) + if (field->flags & VERS_ROW_START) create_info->vers_info.as_row.start= def->field_name= Vers_parse_info::default_start; else create_info->vers_info.as_row.end= def->field_name= Vers_parse_info::default_end; @@ -8250,9 +8250,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, !vers_system_invisible) { StringBuffer tmp; - if (!(dropped_sys_vers_fields & VERS_SYS_START_FLAG)) + if (!(dropped_sys_vers_fields & VERS_ROW_START)) append_drop_column(thd, &tmp, table->vers_start_field()); - if (!(dropped_sys_vers_fields & VERS_SYS_END_FLAG)) + if (!(dropped_sys_vers_fields & VERS_ROW_END)) 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; diff --git a/sql/table.cc b/sql/table.cc index 18bb28e0863..0bef0fc29a1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2059,9 +2059,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (versioned) { if (i == row_start_field) - flags|= VERS_SYS_START_FLAG; + flags|= VERS_ROW_START; else if (i == row_end_field) - flags|= VERS_SYS_END_FLAG; + flags|= VERS_ROW_END; if (flags & VERS_SYSTEM_FIELD) { From d31f953789def34f20d29b31add847a3c30a8ecc Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 11 Oct 2021 13:36:07 +0300 Subject: [PATCH 18/28] MDEV-22660 SIGSEGV on adding system versioning and modifying system column Second alter subcommand correctly removed VERS_ROW_END flag. We throw ER_VERS_PERIOD_COLUMNS in such case. --- mysql-test/suite/versioning/r/alter.result | 19 +++++++++++++++++++ mysql-test/suite/versioning/t/alter.test | 22 ++++++++++++++++++++++ sql/handler.cc | 6 ++++++ 3 files changed, 47 insertions(+) diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index 5092adc2b11..9af25d2f858 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -759,3 +759,22 @@ delete from t1; set system_versioning_alter_history= keep; alter ignore table t1 drop pk; drop table t1; +# +# MDEV-22660 SIGSEGV on adding system versioning and modifying system column +# +create or replace table t1 (a int); +alter table t1 +add row_start timestamp(6) as row start, +add row_end timestamp(6) as row end, +add period for system_time(row_start, row_end), +with system versioning, +modify row_end varchar(8); +ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end` +alter table t1 +add row_start timestamp(6) as row start, +add row_end timestamp(6) as row end, +add period for system_time(row_start, row_end), +with system versioning, +modify row_start varchar(8); +ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end` +drop table t1; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 3ce87817e06..0900e424bd0 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -652,3 +652,25 @@ set system_versioning_alter_history= keep; alter ignore table t1 drop pk; # cleanup drop table t1; + + +--echo # +--echo # MDEV-22660 SIGSEGV on adding system versioning and modifying system column +--echo # +create or replace table t1 (a int); +--error ER_VERS_PERIOD_COLUMNS +alter table t1 + add row_start timestamp(6) as row start, + add row_end timestamp(6) as row end, + add period for system_time(row_start, row_end), + with system versioning, + modify row_end varchar(8); +--error ER_VERS_PERIOD_COLUMNS +alter table t1 + add row_start timestamp(6) as row start, + add row_end timestamp(6) as row end, + add period for system_time(row_start, row_end), + with system versioning, + modify row_start varchar(8); +# cleanup +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index f46e51a34ce..bbd0f3bf515 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7564,6 +7564,12 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, row_end= f; } + if (!row_start || !row_end) + { + my_error(ER_VERS_PERIOD_COLUMNS, MYF(0), as_row.start.str, as_row.end.str); + return true; + } + if (!can_native || !row_start->is_some_bigint() || !row_end->is_some_bigint()) From 1e70b287e702b7ff9191454d1316d9137b9be0c1 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 11 Oct 2021 13:36:07 +0300 Subject: [PATCH 19/28] MDEV-25891 Computed default for INVISIBLE column is ignored in INSERT There are two fill_record() functions (lines 8343 and 8618). First one is used when there are some explicit values, the second one is used for all implicit values. First one does update_default_fields(), the second one did not. Added update_default_fields() call to the implicit version of fill_record(). --- mysql-test/main/invisible_field.result | 17 ++++++++++++++++- mysql-test/main/invisible_field.test | 13 +++++++++++++ sql/sql_base.cc | 5 ++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result index ee45567d212..cd1bb77be71 100644 --- a/mysql-test/main/invisible_field.result +++ b/mysql-test/main/invisible_field.result @@ -538,7 +538,7 @@ a b insert into t2 values(1); select a,b from t2; a b -NULL 1 +12 1 drop table t1,t2; create table t1 (a int invisible, b int, c int); create table t2 (a int, b int, d int); @@ -623,3 +623,18 @@ drop table t1; create table t1 (a int, b int invisible); insert delayed into t1 values (1); drop table t1; +# +# MDEV-25891 Computed default for INVISIBLE column is ignored in INSERT +# +create table t1( +a int, +x int default (a), +y int default (a) invisible, +z int default (33) invisible); +insert into t1 values (1, default); +insert into t1 (a) values (2); +select a, x, y, z from t1; +a x y z +1 1 1 33 +2 2 2 33 +drop table t1; diff --git a/mysql-test/main/invisible_field.test b/mysql-test/main/invisible_field.test index 7a48347ec29..558ca7aa3a2 100644 --- a/mysql-test/main/invisible_field.test +++ b/mysql-test/main/invisible_field.test @@ -279,3 +279,16 @@ create table t1 (a int, b int invisible); insert delayed into t1 values (1); # cleanup drop table t1; + +--echo # +--echo # MDEV-25891 Computed default for INVISIBLE column is ignored in INSERT +--echo # +create table t1( + a int, + x int default (a), + y int default (a) invisible, + z int default (33) invisible); +insert into t1 values (1, default); +insert into t1 (a) values (2); +select a, x, y, z from t1; +drop table t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b65737bfb02..a1f3f6116b9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8699,8 +8699,11 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List &values, goto err; field->set_has_explicit_value(); } - /* Update virtual fields */ thd->abort_on_warning= FALSE; + if (table->default_field && + table->update_default_fields(ignore_errors)) + goto err; + /* Update virtual fields */ if (table->vfield && table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE)) goto err; From ff77a09bda884fe6bf3917eb29b9d3a2f53f919b Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 11 Oct 2021 13:36:07 +0300 Subject: [PATCH 20/28] MDEV-22464 Server crash on UPDATE with nested subquery Uninitialized ref_pointer_array[] because setup_fields() got empty fields list. mysql_multi_update() for some reason does that by substituting the fields list with empty total_list for the mysql_select() call (looks like wrong merge since total_list is not used anywhere else and is always empty). The fix would be to return back the original fields list. But this fails update_use_source.test case: --error ER_BAD_FIELD_ERROR update v1 set t1c1=2 order by 1; Actually not failing the above seems to be ok. The other fix would be to keep resolve_in_select_list false (and that keeps outer context from being resolved in Item_ref::fix_fields()). This fix is more consistent with how SELECT behaves: --error ER_SUBQUERY_NO_1_ROW select a from t1 where a= (select 2 from t1 having (a = 3)); So this patch implements this fix. --- mysql-test/main/multi_update.result | 10 ++++++++++ mysql-test/main/multi_update.test | 11 +++++++++++ sql/sql_select.cc | 3 ++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result index 520199d562c..71eafbf7e17 100644 --- a/mysql-test/main/multi_update.result +++ b/mysql-test/main/multi_update.result @@ -1151,3 +1151,13 @@ b 1 3 drop tables t1, t2; +# +# MDEV-22464 Server crash on UPDATE with nested subquery +# +create table t1 (a int) ; +insert into t1 (a) values (1),(2),(3) ; +select a from t1 where a= (select 2 from t1 having (a = 3)); +ERROR 21000: Subquery returns more than 1 row +update t1 set a= (select 2 from t1 having (a = 3)); +ERROR 21000: Subquery returns more than 1 row +drop tables t1; diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test index 84f06a7c165..3ee36f97fc5 100644 --- a/mysql-test/main/multi_update.test +++ b/mysql-test/main/multi_update.test @@ -1087,3 +1087,14 @@ update t1 left join t2 on a = b set b= 3 order by b; select * from t2; drop tables t1, t2; + +--echo # +--echo # MDEV-22464 Server crash on UPDATE with nested subquery +--echo # +create table t1 (a int) ; +insert into t1 (a) values (1),(2),(3) ; +--error ER_SUBQUERY_NO_1_ROW +select a from t1 where a= (select 2 from t1 having (a = 3)); +--error ER_SUBQUERY_NO_1_ROW +update t1 set a= (select 2 from t1 having (a = 3)); +drop tables t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 09d890161f6..e44ba4b59e1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4268,7 +4268,8 @@ mysql_select(THD *thd, bool free_join= 1; DBUG_ENTER("mysql_select"); - select_lex->context.resolve_in_select_list= TRUE; + if (!fields.is_empty()) + select_lex->context.resolve_in_select_list= true; JOIN *join; if (select_lex->join != 0) { From 5e3e5ccbea2ab90548fc82c5d730dea2c9315a16 Mon Sep 17 00:00:00 2001 From: SergMariaDB <91733807+SergMariaDB@users.noreply.github.com> Date: Mon, 11 Oct 2021 08:26:33 -0400 Subject: [PATCH 21/28] Apple Silicon is a 64-bit platform (#1922) Co-authored-by: FX Coudert --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 5e96400eac1..dba63e75097 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -164,7 +164,7 @@ # if defined(__i386__) || defined(__ppc__) # define SIZEOF_CHARP 4 # define SIZEOF_LONG 4 -# elif defined(__x86_64__) || defined(__ppc64__) +# elif defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__) # define SIZEOF_CHARP 8 # define SIZEOF_LONG 8 # else From 9300b6657752e566a3c72da7ca6eaa8ee052e4e1 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sun, 10 Oct 2021 18:42:32 +0400 Subject: [PATCH 22/28] MDEV-24742 Server crashes in Charset::numchars / String::numchars The crash happened because Item_aes_crypt::val_str() did not set the character set of the result. --- mysql-test/r/func_str.result | 12 ++++++++++++ mysql-test/t/func_str.test | 16 ++++++++++++++++ sql/item_strfunc.cc | 2 ++ 3 files changed, 30 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 798b4f9ff09..f9346a25151 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -4835,3 +4835,15 @@ DROP TABLE t1; # # End of 10.1 tests # +# +# Start of 10.2 tests +# +# +# MDEV-24742 Server crashes in Charset::numchars / String::numchars +# +SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux'); +NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux') +NULL +# +# End of 10.2 tests +# diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 1a59946e97e..366aacb1945 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1932,3 +1932,19 @@ DROP TABLE t1; --echo # --echo # End of 10.1 tests --echo # + + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-24742 Server crashes in Charset::numchars / String::numchars +--echo # + +SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux'); + + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 26a23b0cb55..e5935178f10 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -338,6 +338,8 @@ String *Item_aes_crypt::val_str(String *str2) rkey, AES_KEY_LENGTH / 8, 0, 0)) { str2->length((uint) aes_length); + DBUG_ASSERT(collation.collation == &my_charset_bin); + str2->set_charset(&my_charset_bin); return str2; } } From eadd87880887e6ca73e6f292c9d856df7e56c3c0 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 8 Oct 2021 20:44:38 +0400 Subject: [PATCH 23/28] MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax The crash happened because my_isalnum() does not support character sets with mbminlen>1. The value of "ft_boolean_syntax" is converted to utf8 in do_string_check(). So calling my_isalnum() is combination with "default_charset_info" was wrong. Adding new parameters (size_t length, CHARSET_INFO *cs) to ft_boolean_check_syntax_string() and passing self->charset(thd) as the character set. --- include/ft_global.h | 3 ++- mysql-test/r/ctype_utf16_def.result | 5 +++++ mysql-test/r/ctype_utf32_def.result | 6 ++++++ mysql-test/t/ctype_utf16_def.test | 7 +++++++ mysql-test/t/ctype_utf32_def-master.opt | 1 + mysql-test/t/ctype_utf32_def.test | 9 +++++++++ sql/mysqld.cc | 4 +++- sql/sys_vars.cc | 4 +++- storage/myisam/ft_parser.c | 13 ++++++++++--- 9 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 mysql-test/r/ctype_utf32_def.result create mode 100644 mysql-test/t/ctype_utf32_def-master.opt create mode 100644 mysql-test/t/ctype_utf32_def.test diff --git a/include/ft_global.h b/include/ft_global.h index 725363c3aa8..9f2d52610ba 100644 --- a/include/ft_global.h +++ b/include/ft_global.h @@ -90,7 +90,8 @@ void ft_free_stopwords(void); FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t, CHARSET_INFO *, uchar *); -my_bool ft_boolean_check_syntax_string(const uchar *); +my_bool ft_boolean_check_syntax_string(const uchar *, size_t length, + CHARSET_INFO *cs); /* Internal symbols for fulltext between maria and MyISAM */ diff --git a/mysql-test/r/ctype_utf16_def.result b/mysql-test/r/ctype_utf16_def.result index 98b6f7d913d..b5827d45619 100644 --- a/mysql-test/r/ctype_utf16_def.result +++ b/mysql-test/r/ctype_utf16_def.result @@ -8,3 +8,8 @@ character_set_server utf16 SHOW VARIABLES LIKE 'ft_stopword_file'; Variable_name Value ft_stopword_file (built-in) +# +# MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax +# +SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|'; +SET GLOBAL ft_boolean_syntax=DEFAULT; diff --git a/mysql-test/r/ctype_utf32_def.result b/mysql-test/r/ctype_utf32_def.result new file mode 100644 index 00000000000..611072eb75b --- /dev/null +++ b/mysql-test/r/ctype_utf32_def.result @@ -0,0 +1,6 @@ +call mtr.add_suppression("'utf32' can not be used as client character set"); +# +# MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax +# +SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|'; +SET GLOBAL ft_boolean_syntax=DEFAULT; diff --git a/mysql-test/t/ctype_utf16_def.test b/mysql-test/t/ctype_utf16_def.test index 0829cd53285..c6de842f618 100644 --- a/mysql-test/t/ctype_utf16_def.test +++ b/mysql-test/t/ctype_utf16_def.test @@ -7,3 +7,10 @@ call mtr.add_suppression("'utf16' can not be used as client character set"); SHOW VARIABLES LIKE 'collation_server'; SHOW VARIABLES LIKE 'character_set_server'; SHOW VARIABLES LIKE 'ft_stopword_file'; + +--echo # +--echo # MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax +--echo # + +SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|'; +SET GLOBAL ft_boolean_syntax=DEFAULT; diff --git a/mysql-test/t/ctype_utf32_def-master.opt b/mysql-test/t/ctype_utf32_def-master.opt new file mode 100644 index 00000000000..3b0880cbff3 --- /dev/null +++ b/mysql-test/t/ctype_utf32_def-master.opt @@ -0,0 +1 @@ +--character-set-server=utf32,latin1 --collation-server=utf32_general_ci diff --git a/mysql-test/t/ctype_utf32_def.test b/mysql-test/t/ctype_utf32_def.test new file mode 100644 index 00000000000..e23f96052d3 --- /dev/null +++ b/mysql-test/t/ctype_utf32_def.test @@ -0,0 +1,9 @@ +--source include/have_utf32.inc +call mtr.add_suppression("'utf32' can not be used as client character set"); + +--echo # +--echo # MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax +--echo # + +SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|'; +SET GLOBAL ft_boolean_syntax=DEFAULT; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9afc701c6ba..d723c36e4cb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9666,7 +9666,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) if (global_system_variables.low_priority_updates) thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY; - if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax)) + if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax, + strlen(ft_boolean_syntax), + system_charset_info)) { sql_print_error("Invalid ft-boolean-syntax string: %s\n", ft_boolean_syntax); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e4de3d8d0aa..f231f49a667 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1022,7 +1022,9 @@ static Sys_var_ulong Sys_flush_time( static bool check_ftb_syntax(sys_var *self, THD *thd, set_var *var) { return ft_boolean_check_syntax_string((uchar*) - (var->save_result.string_value.str)); + (var->save_result.string_value.str), + var->save_result.string_value.length, + self->charset(thd)); } static bool query_cache_flush(sys_var *self, THD *thd, enum_var_type type) { diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index f6930e91e6e..b2170a93cde 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -78,18 +78,25 @@ FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root) DBUG_RETURN(wlist); } -my_bool ft_boolean_check_syntax_string(const uchar *str) +my_bool ft_boolean_check_syntax_string(const uchar *str, size_t length, + CHARSET_INFO *cs) { uint i, j; + if (cs->mbminlen != 1) + { + DBUG_ASSERT(0); + return 1; + } + if (!str || - (strlen((char*) str)+1 != sizeof(DEFAULT_FTB_SYNTAX)) || + (length + 1 != sizeof(DEFAULT_FTB_SYNTAX)) || (str[0] != ' ' && str[1] != ' ')) return 1; for (i=0; i 127 || my_isalnum(default_charset_info, str[i])) + if ((unsigned char)(str[i]) > 127 || my_isalnum(cs, str[i])) return 1; for (j=0; j Date: Sat, 9 Oct 2021 22:27:31 +0400 Subject: [PATCH 24/28] MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED Also fixes MDEV-24467 Memory not freed after failed INSERT DELAYED Description: In case of an error (e.g. data truncation) during mysql_insert() handling an INSERT DELAYED, the data type specific data in fields (e.g. Field_blob::value) is not taken over by the delayed writer thread. All fields in table_list->table are freed by free_root() immediately after mysql_insert(). To avoid a memory leak, we need to free the specific data before exiting mysql_insert() on error. --- mysql-test/r/delayed_blob.result | 17 +++++++++++++++++ mysql-test/t/delayed_blob-master.opt | 1 + mysql-test/t/delayed_blob.test | 21 +++++++++++++++++++++ sql/sql_insert.cc | 11 +++++++++++ 4 files changed, 50 insertions(+) create mode 100644 mysql-test/r/delayed_blob.result create mode 100644 mysql-test/t/delayed_blob-master.opt create mode 100644 mysql-test/t/delayed_blob.test diff --git a/mysql-test/r/delayed_blob.result b/mysql-test/r/delayed_blob.result new file mode 100644 index 00000000000..caa2e3ae5fe --- /dev/null +++ b/mysql-test/r/delayed_blob.result @@ -0,0 +1,17 @@ +# +# MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED +# +SET sql_mode='TRADITIONAL'; +CREATE TABLE t1 (c BLOB) ENGINE=MyISAM; +INSERT DELAYED INTO t1 VALUES (''||''); +ERROR 22007: Truncated incorrect DOUBLE value: '' +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-24467 Memory not freed after failed INSERT DELAYED +# +CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM; +ALTER TABLE t1 ADD b BLOB DEFAULT 'x'; +INSERT DELAYED INTO t1 (a) VALUES ('foo'); +ERROR 22001: Data too long for column 'a' at row 1 +DROP TABLE t1; diff --git a/mysql-test/t/delayed_blob-master.opt b/mysql-test/t/delayed_blob-master.opt new file mode 100644 index 00000000000..e442a822046 --- /dev/null +++ b/mysql-test/t/delayed_blob-master.opt @@ -0,0 +1 @@ +--init_connect="set @a='something unique to have MTR start a dedicated mariadbd for this test and shutdown it after the test'" diff --git a/mysql-test/t/delayed_blob.test b/mysql-test/t/delayed_blob.test new file mode 100644 index 00000000000..bf3e01a8825 --- /dev/null +++ b/mysql-test/t/delayed_blob.test @@ -0,0 +1,21 @@ +--echo # +--echo # MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED +--echo # + +SET sql_mode='TRADITIONAL'; +CREATE TABLE t1 (c BLOB) ENGINE=MyISAM; +--error ER_TRUNCATED_WRONG_VALUE +INSERT DELAYED INTO t1 VALUES (''||''); +DROP TABLE t1; +SET sql_mode=DEFAULT; + + +--echo # +--echo # MDEV-24467 Memory not freed after failed INSERT DELAYED +--echo # + +CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM; +ALTER TABLE t1 ADD b BLOB DEFAULT 'x'; +--error ER_DATA_TOO_LONG +INSERT DELAYED INTO t1 (a) VALUES ('foo'); +DROP TABLE t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 51b2c84cfea..718682f767e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1257,7 +1257,18 @@ values_loop_end: abort: #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) + { end_delayed_insert(thd); + /* + In case of an error (e.g. data truncation), the data type specific data + in fields (e.g. Field_blob::value) was not taken over + by the delayed writer thread. All fields in table_list->table + will be freed by free_root() soon. We need to free the specific + data before free_root() to avoid a memory leak. + */ + for (Field **ptr= table_list->table->field ; *ptr ; ptr++) + (*ptr)->free(); + } #endif if (table != NULL) table->file->ha_release_auto_increment(); From b44e12fef176bfc0884fb2c5f4ba7f42bf054f44 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 30 Sep 2021 10:36:26 +0200 Subject: [PATCH 25/28] MDEV-26707 SR transaction rolls back locally, but not in cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update wsrep-lib, and add MTR test case for MDEV-26707 Reviewed-by: Jan Lindström --- .../galera_3nodes_sr/r/MDEV-26707.result | 86 ++++++++++ mysql-test/suite/galera_3nodes_sr/suite.pm | 1 + .../suite/galera_3nodes_sr/t/MDEV-26707.test | 162 ++++++++++++++++++ wsrep-lib | 2 +- 4 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera_3nodes_sr/r/MDEV-26707.result create mode 100644 mysql-test/suite/galera_3nodes_sr/t/MDEV-26707.test diff --git a/mysql-test/suite/galera_3nodes_sr/r/MDEV-26707.result b/mysql-test/suite/galera_3nodes_sr/r/MDEV-26707.result new file mode 100644 index 00000000000..8de724c1576 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/MDEV-26707.result @@ -0,0 +1,86 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +connection node_2; +SET SESSION wsrep_trx_fragment_size=1; +BEGIN; +INSERT INTO t1 VALUES (21); +connection node_1; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +EXPECT_1 +1 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +EXPECT_1 +1 +connection node_3; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +EXPECT_1 +1 +connection node_3a; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_2a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_2; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; +COMMIT; +connection node_2a; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +SET DEBUG_SYNC = 'now SIGNAL continue'; +connection node_2; +ERROR HY000: Got error 6 "No such device or address" during COMMIT +connection node_2a; +SET DEBUG_SYNC = 'RESET'; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_3a; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +EXPECT_1 +1 +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +EXPECT_1 +1 +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_2a; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_3a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_1a; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 +0 +connection node_2a; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 +0 +connection node_3a; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 +0 +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/suite.pm b/mysql-test/suite/galera_3nodes_sr/suite.pm index ee651fe8984..becc764733a 100644 --- a/mysql-test/suite/galera_3nodes_sr/suite.pm +++ b/mysql-test/suite/galera_3nodes_sr/suite.pm @@ -37,6 +37,7 @@ push @::global_suppressions, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(JOINED\). Message ignored.|, qr(WSREP: Action message in non-primary configuration from member [0-9]*), + qr(WSREP: Last Applied Action message in non-primary configuration from member [0-9]*), qr|WSREP: .*core_handle_uuid_msg.*|, qr(WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0. WSREP_SYNC_WAIT_BEFORE_READ is on), qr(WSREP: JOIN message from member .* in non-primary configuration. Ignored.), diff --git a/mysql-test/suite/galera_3nodes_sr/t/MDEV-26707.test b/mysql-test/suite/galera_3nodes_sr/t/MDEV-26707.test new file mode 100644 index 00000000000..ed7adc8313a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/MDEV-26707.test @@ -0,0 +1,162 @@ +# +# MDEV-26707: SR transaction rolls back locally, but not in cluster +# +# This test excercises the following scenario: +# Initially we have a three node cluster where node 2 has an active +# SR transaction that has replicated one fragment. +# Node 3 disconnects from the cluster, followed by disconnect of node 2. +# Node 2 attempts to COMMIT its transaction, but fails because node 2 is +# non-primary. This failure causes the transaction to rolled back locally +# (node 2 can't communicate with the cluster at this point, so rollback +# fragment cannot be sent successfully) +# Node 3 joins back creating non-primary view (node 1, node 3). +# Then node 2 joins back creating primary view (node 1, node 1, node 3). +# If bug is present, we have that node 2 has rolled back locally, while +# the same transaction is still active nodes 1 and 3, leaving entries +# in their wsrep_streaming_log tables. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3 + + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); + +--connection node_2 +SET SESSION wsrep_trx_fragment_size=1; +BEGIN; +INSERT INTO t1 VALUES (21); + +--connection node_1 +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; + +--connection node_3 +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; + +# +# Disconnect node 3 from cluster +# +--connection node_3a +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_2a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +# +# Issue commit block COMMIT before certification on node 2 +# +--connection node_2 +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; +--send COMMIT + +--connection node_2a +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; + +# +# Disconnect node 2 +# +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + + +# +# Unblock COMMIT and expect it to fail +# +SET DEBUG_SYNC = 'now SIGNAL continue'; + +--connection node_2 +--error ER_ERROR_DURING_COMMIT +--reap + +--connection node_2a +SET DEBUG_SYNC = 'RESET'; + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + + +# +# Reconnect node 3 +# +--connection node_3a +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_streaming_log; +SET SESSION wsrep_sync_wait = DEFAULT; + + +# +# Reconnect node 2 +# +--connection node_2a +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/galera_wait_ready.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/galera_wait_ready.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_3a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/galera_wait_ready.inc +SET SESSION wsrep_sync_wait = DEFAULT; + + +# +# Expect no entries in wsrep_streaming_log +# +--connection node_1a +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +--connection node_2a +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +--connection node_3a +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; + + +--connection node_1 +DROP TABLE t1; diff --git a/wsrep-lib b/wsrep-lib index efb4aab090c..22921e7082d 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit efb4aab090cb9c1b57b9e7f9988ae1c41f48344f +Subproject commit 22921e7082ddfb45222f21a585aa8b877e62aa8b From 6f32b28be511e96d9265ce727aa4a38810b41f96 Mon Sep 17 00:00:00 2001 From: Sergei Krivonos Date: Wed, 6 Oct 2021 11:31:08 +0300 Subject: [PATCH 26/28] Xcode compatibility update --- .gitignore | 2 ++ include/my_context.h | 3 +++ mysys/my_context.c | 7 +++++++ storage/connect/bsonudf.cpp | 9 +++++---- storage/connect/inihandl.cpp | 10 +++++----- storage/connect/tabbson.cpp | 2 +- storage/innobase/row/row0upd.cc | 12 ++++++------ 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index dc8f6940fdf..c1a80c15aa6 100644 --- a/.gitignore +++ b/.gitignore @@ -338,6 +338,7 @@ x86/ build/ bld/ [Bb]in/ +/cmake-build-debug/ [Oo]bj/ # Roslyn cache directories @@ -518,4 +519,5 @@ compile_commands.json # Visual Studio Code workspace .vscode/ +/.idea/ .cache/clangd diff --git a/include/my_context.h b/include/my_context.h index ea0e3496887..45d2a7d7ffa 100644 --- a/include/my_context.h +++ b/include/my_context.h @@ -52,6 +52,9 @@ struct my_context { #ifdef MY_CONTEXT_USE_UCONTEXT +#if defined(__APPLE__) && !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE +#endif #include struct my_context { diff --git a/mysys/my_context.c b/mysys/my_context.c index cf10738bdbd..f3aef23e07a 100644 --- a/mysys/my_context.c +++ b/mysys/my_context.c @@ -29,6 +29,10 @@ #endif #ifdef MY_CONTEXT_USE_UCONTEXT +#ifdef __APPLE__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif /* The makecontext() only allows to pass integers into the created context :-( We want to pass pointers, so we do it this kinda hackish way. @@ -154,6 +158,9 @@ my_context_destroy(struct my_context *c) DBUG_FREE_CODE_STATE(&c->dbug_state); } +#ifdef __APPLE__ +#pragma GCC diagnostic pop +#endif #endif /* MY_CONTEXT_USE_UCONTEXT */ diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index 783be52602a..ed795edb363 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "bsonudf.h" @@ -621,7 +622,7 @@ PVAL BJNX::GetCalcValue(PGLOBAL g, PBVAL bap, int n) { // For calculated arrays, a local Value must be used int lng = 0; - short type, prec = 0; + short type = 0, prec = 0; bool b = n < Nod - 1; PVAL valp; PBVAL vlp, vp; @@ -690,7 +691,7 @@ PVAL BJNX::GetCalcValue(PGLOBAL g, PBVAL bap, int n) break; default: - break; + DBUG_ASSERT(!"Implement new op type support."); } // endswitch Op return valp = AllocateValue(g, type, lng, prec); @@ -4978,7 +4979,7 @@ char *bbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, uint n = 2; int* x = GetIntArgPtr(g, args, n); BJNX bnx(g, NULL, TYPE_STRING); - PBVAL jarp, top, jvp = NULL; + PBVAL jarp = NULL, top = NULL, jvp = NULL; PBVAL jsp = bnx.MakeValue(args, 0, true, &top); if (bnx.CheckPath(g, args, jsp, jvp, 2)) @@ -5611,7 +5612,7 @@ char *bbin_object_values(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!bsp) { if (!CheckMemory(g, initid, args, 1, true, true)) { BJNX bnx(g); - PBVAL top, jarp; + PBVAL top, jarp = NULL; PBVAL jvp = bnx.MakeValue(args, 0, true, &top); if (jvp->Type == TYPE_JOB) { diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp index 8e79aeac7ef..7d8741ebfa3 100644 --- a/storage/connect/inihandl.cpp +++ b/storage/connect/inihandl.cpp @@ -193,17 +193,17 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section ) secno++; } - for (key = section->key; key; key = key->next) - if (key->name && key->name[0]) { + for (key= section->key; key; key= key->next) { + if (key->name[0]) { fprintf(file, "%s", SVP(key->name)); if (key->value) fprintf(file, "=%s", SVP(key->value)); fprintf(file, "\n"); - } // endif key->name - - } // endfor section + } // endif key->name + } + } // endfor section } // end of PROFILE_Save diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 3b1f1c84d1a..a7c561318c7 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -871,7 +871,7 @@ PBVAL BCUTIL::MakeBson(PGLOBAL g, PBVAL jsp, int n) /***********************************************************************/ PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i) { - int nod = Cp->Nod, n = nod - 1; + int nod = Cp->Nod; JNODE *nodes = Cp->Nodes; PBVAL arp; PBVAL bvp = NULL; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 1f3e34d493a..a58c3993e90 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2470,13 +2470,13 @@ row_upd_sec_index_entry( case DB_LOCK_WAIT_TIMEOUT: WSREP_DEBUG("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name, index->table->name, + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; default: WSREP_ERROR("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name, index->table->name, + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; } @@ -2806,14 +2806,14 @@ check_fk: case DB_LOCK_WAIT_TIMEOUT: WSREP_DEBUG("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name, index->table->name, + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); goto err_exit; default: WSREP_ERROR("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name, index->table->name, + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); goto err_exit; @@ -3037,13 +3037,13 @@ row_upd_del_mark_clust_rec( case DB_LOCK_WAIT_TIMEOUT: WSREP_DEBUG("Foreign key check fail: " "%d on table %s index %s query %s", - err, index->name, index->table->name, + err, index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; default: WSREP_ERROR("Foreign key check fail: " "%d on table %s index %s query %s", - err, index->name, index->table->name, + err, index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; } From 2bb8d7c2f36439ab6a3944476665eb1218c36f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Oct 2021 10:38:41 +0300 Subject: [PATCH 27/28] MDEV-26811: Assertion "log_sys->n_pending_flushes == 1" fails In commit 1cb218c37cc3fe01a1ff2fe9b1cbfb591e90d5ce (MDEV-26450) we introduced the function log_write_and_flush(), which may compete with log_checkpoint() invoking log_write_flush_to_disk_low() from another thread. The assertion n_pending_flushes==1 is too strict. There is no possibility of a race condition here, because fil_flush() is protected by fil_system->mutex and the rest will be protected by log_sys->mutex. log_write_flush_to_disk_low(), log_write_and_flush(): Relax the assertions to test for a nonzero count. --- storage/innobase/log/log0log.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 945c97daf4a..8dc29e302dd 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -983,13 +983,9 @@ loop: /** Flush the recently written changes to the log file. and invoke log_mutex_enter(). */ -static -void -log_write_flush_to_disk_low() +static void log_write_flush_to_disk_low() { - /* FIXME: This is not holding log_sys->mutex while - calling os_event_set()! */ - ut_a(log_sys->n_pending_flushes == 1); /* No other threads here */ + ut_a(log_sys->n_pending_flushes); bool do_flush = srv_file_flush_method != SRV_O_DSYNC; @@ -997,7 +993,6 @@ log_write_flush_to_disk_low() fil_flush(SRV_LOG_SPACE_FIRST_ID); } - log_mutex_enter(); if (do_flush) { log_sys->flushed_to_disk_lsn = log_sys->current_flush_lsn; @@ -1329,7 +1324,7 @@ ATTRIBUTE_COLD void log_write_and_flush() /* Code adapted from log_write_flush_to_disk_low() */ - ut_a(log_sys->n_pending_flushes == 1); /* No other threads here */ + ut_a(log_sys->n_pending_flushes); if (srv_file_flush_method != SRV_O_DSYNC) fil_flush(SRV_LOG_SPACE_FIRST_ID); From aae72f821abbee4d63a0925c06b18422d4c08ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Oct 2021 12:49:52 +0300 Subject: [PATCH 28/28] MDEV-24062: Re-disable the test after merge The test galera.galera_var_replicate_myisam_on would trigger an assertion failure "mode() == m_local" in wsrep-lib/src/client_state.cpp after the merge of commit 3067ffc58e2ada6591e3d823b31841ea685da6c7 enabled it. --- mysql-test/suite/galera/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 8a6fe8e16c1..472c0a80f75 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -34,6 +34,7 @@ galera_trigger : MDEV-24048 galera.galera_trigger MTR fails: Result content mism galera_var_ignore_apply_errors : MDEV-26770 galera_var_ignore_apply_errors fails Server did not transition to READY state galera_var_node_address : MDEV-20485 Galera test failure galera_var_notify_cmd : MDEV-21905 Galera test galera_var_notify_cmd causes hang +galera_var_replicate_myisam_on : MDEV-24062 Galera test failure on galera_var_replicate_myisam_on galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit mysql-wsrep#198 : MDEV-24446: galera.mysql-wsrep#198 MTR failed: query 'reap' failed: 2000: Unknown MySQL error partition : MDEV-19958 Galera test failure on galera.partition