From 5dc9a6b4558d50298882b3d76b3249e9419e3682 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 21 Apr 2023 13:46:14 -0700 Subject: MDEV-31102 Crash when pushing condition into view defined as union This bug could manifest itself at the first execution of prepared statement created for queries using a materialized view defined as union. A crash could happen for sure if the query contained a condition pushable into the view and this condition was over the column defined via a complex string expression requiring implicit conversion from one charset to another for some of its sub-expressions. The bug could cause crashes when executing PS for some other queries whose optimization needed building clones for such expressions. This bug was introduced in the patch for MDEV-29988 where the class Item_direct_ref_to_item was added. The implementations of the virtual methods get_copy() and build_clone() were invalid for the class and this could cause crashes after the method build_clone() was called for expressions containing objects of the Item_direct_ref_to_item type. Approved by Sergei Golubchik --- mysql-test/main/derived_cond_pushdown.result | 83 ++++++++++++++++++++++++++++ mysql-test/main/derived_cond_pushdown.test | 30 ++++++++++ sql/item.h | 17 +++++- 3 files changed, 128 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 41f9ac6fca1..4b202ea7a12 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -18275,4 +18275,87 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary drop view v1; drop table t1; +# +# MDEV-31102: execution of PS for query where pushdown of condition +# into view defined as union is applied +# +create table t1 ( +n int, +lv varchar(31) charset latin1, +mv varchar(31) charset utf8mb3 +) engine=myisam; +insert into t1 values (1,'aa','xxx'), ('2','bb','yyy'), (3,'cc','zzz'); +create view v1 as +select case when n=1 then lv when n=2 then mv else NULL end as r from t1 +union +select 'a'; +select * from v1 where r < 'x'; +r +aa +a +explain extended select * from v1 where r < 'x'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select `v1`.`r` AS `r` from `test`.`v1` where `v1`.`r` < 'x' +explain format=json select * from v1 where r < 'x'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "v1.r < 'x'", + "materialized": { + "query_block": { + "union_result": { + "table_name": "", + "access_type": "ALL", + "query_specifications": [ + { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when t1.n = 1 then convert(t1.lv using utf8) when t1.n = 2 then t1.mv else NULL end < 'x'" + } + } + }, + { + "query_block": { + "select_id": 3, + "operation": "UNION", + "table": { + "message": "No tables used" + } + } + } + ] + } + } + } + } + } +} +prepare stmt from "select * from v1 where r < 'x'"; +execute stmt; +r +aa +a +execute stmt; +r +aa +a +deallocate prepare stmt; +drop view v1; +drop table t1; # End of 10.4 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 6cfe23b7866..b4e131dbe79 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -3942,4 +3942,34 @@ explain select * from v1; drop view v1; drop table t1; +--echo # +--echo # MDEV-31102: execution of PS for query where pushdown of condition +--echo # into view defined as union is applied +--echo # + +create table t1 ( + n int, + lv varchar(31) charset latin1, + mv varchar(31) charset utf8mb3 +) engine=myisam; +insert into t1 values (1,'aa','xxx'), ('2','bb','yyy'), (3,'cc','zzz'); +create view v1 as +select case when n=1 then lv when n=2 then mv else NULL end as r from t1 +union +select 'a'; + +let $q= +select * from v1 where r < 'x'; + +eval $q; +eval explain extended $q; +eval explain format=json $q; +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +drop view v1; +drop table t1; + --echo # End of 10.4 tests diff --git a/sql/item.h b/sql/item.h index 31568aafc8c..1e0caaa7c83 100644 --- a/sql/item.h +++ b/sql/item.h @@ -7647,7 +7647,7 @@ public: Item *get_tmp_table_item(THD *thd) { return m_item->get_tmp_table_item(thd); } Item *get_copy(THD *thd) - { return m_item->get_copy(thd); } + { return get_item_copy(thd, this); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, bool link_item_fields, COND_EQUAL **cond_equal_ref) @@ -7715,7 +7715,20 @@ public: bool excl_dep_on_grouping_fields(st_select_lex *sel) { return m_item->excl_dep_on_grouping_fields(sel); } bool is_expensive() { return m_item->is_expensive(); } - Item* build_clone(THD *thd) { return get_copy(thd); } + void set_item(Item *item) { m_item= item; } + Item *build_clone(THD *thd) + { + Item *clone_item= m_item->build_clone(thd); + if (clone_item) + { + Item_direct_ref_to_item *copy= (Item_direct_ref_to_item *) get_copy(thd); + if (!copy) + return 0; + copy->set_item(clone_item); + return copy; + } + return 0; + } void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List &fields, uint flags) -- cgit v1.2.1 From d3e7dba329f517072c80b81cd17e9a67e2748729 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 28 Sep 2022 12:34:44 -0600 Subject: MDEV-28798: Previously Binlog Encrypted Master Segfaults on Binlog Dump with Using_Gtid=Slave_Pos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ======== A master can segfault if it can't set up decryption for its binary log during a binlog dump with Using_Gtid=Slave_Pos. If slave connects using GTID mode, the master will call into log.cc::get_gtid_list_event(), which iterate through binlog events looking for a Gtid_list_log_event. On an encrypted binlog that the master cannot decrypt, the first event will be a START_ENCRYPTION_EVENT which will call into the following decryption branch if (fdle->start_decryption((Start_encryption_log_event*) ev)) errormsg= ‘Could not set up decryption for binlog.’; The event iteration however, does not stop in spite of this error. The master will try to read the next event, but segfault while trying to decrypt it because decryption failed to initialize. Solution: ======== Break the event iteration if decryption cannot be set up. Reviewed By: ============ Andrei Elkin --- .../encrypted_master_switch_to_unencrypted.cnf | 5 - .../encrypted_master_switch_to_unencrypted.result | 84 ----------- .../encrypted_master_switch_to_unencrypted.test | 152 -------------------- ...crypted_master_switch_to_unencrypted_coords.cnf | 5 + ...pted_master_switch_to_unencrypted_coords.result | 85 +++++++++++ ...rypted_master_switch_to_unencrypted_coords.test | 158 +++++++++++++++++++++ ...encrypted_master_switch_to_unencrypted_gtid.cnf | 8 ++ ...rypted_master_switch_to_unencrypted_gtid.result | 84 +++++++++++ ...ncrypted_master_switch_to_unencrypted_gtid.test | 154 ++++++++++++++++++++ sql/log.cc | 3 + 10 files changed, 497 insertions(+), 241 deletions(-) delete mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.cnf delete mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.result delete mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.test create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.cnf create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.cnf create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result create mode 100644 mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.cnf b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.cnf deleted file mode 100644 index 73c9ad655bf..00000000000 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.cnf +++ /dev/null @@ -1,5 +0,0 @@ -!include my.cnf - -[mysqld.1] -encrypt-binlog=0 -skip-file-key-management diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.result b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.result deleted file mode 100644 index d632c565ad2..00000000000 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.result +++ /dev/null @@ -1,84 +0,0 @@ -################# -# Initialization -################# -include/rpl_init.inc [topology=1->2] -connection server_2; -include/stop_slave.inc -##################################################### -# Part 1: unencrypted master -##################################################### -connection server_1; -call mtr.add_suppression("Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error;"); -CREATE TABLE table1_no_encryption ( -pk INT AUTO_INCREMENT PRIMARY KEY, -ts TIMESTAMP NULL, -b BLOB -) ENGINE=MyISAM; -INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; -FLUSH BINARY LOGS; -SET binlog_format=ROW; -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; -NOT FOUND /table1_no_encryption/ in master-bin.0* -##################################################### -# Part 2: restart master, now with binlog encryption -##################################################### -connection default; -connection server_1; -CREATE TABLE table2_to_encrypt ( -pk INT AUTO_INCREMENT PRIMARY KEY, -ts TIMESTAMP NULL, -b BLOB -) ENGINE=MyISAM; -INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; -FLUSH BINARY LOGS; -SET binlog_format=ROW; -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; -NOT FOUND /table2_to_encrypt/ in master-bin.0* -##################################################### -# Part 3: restart master again without encryption -##################################################### -connection default; -connection server_1; -CREATE TABLE table3_no_encryption ( -pk INT AUTO_INCREMENT PRIMARY KEY, -ts TIMESTAMP NULL, -b BLOB -) ENGINE=MyISAM; -INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); -INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; -INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; -##################################################### -# Check: resume replication and check how it goes -##################################################### -connection server_2; -start slave; -connection server_1; -connection server_2; -include/wait_for_slave_io_error.inc [errno=1236] -SHOW TABLES; -Tables_in_test -table1_no_encryption -include/stop_slave.inc -reset slave; -########## -# Cleanup -########## -connection server_1; -reset master; -SELECT COUNT(*) FROM table1_no_encryption; -COUNT(*) -8 -SELECT COUNT(*) FROM table2_to_encrypt; -COUNT(*) -8 -SELECT COUNT(*) FROM table3_no_encryption; -COUNT(*) -4 -DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; -connection server_2; -include/start_slave.inc -include/rpl_end.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.test deleted file mode 100644 index 1e1b0cbd353..00000000000 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted.test +++ /dev/null @@ -1,152 +0,0 @@ -# -# TODO: write here what the test checks after MDEV-11288 is fixed -# -# The test starts with unencrypted master. -# It stops replication, generates a few statement and row events -# on the master, then restarts the server with encrypted binlog, -# generates some more events and restarts it back without encryption -# (no encryption plugin). -# Then it resumes replication and checks what happens when the server -# tries to feed the binary logs (included the encrypted ones) -# to the slave. -# - ---source include/have_binlog_format_mixed.inc - ---echo ################# ---echo # Initialization ---echo ################# - ---let $rpl_topology= 1->2 ---source include/rpl_init.inc - ---enable_connect_log - -# We stop replication because we want it to happen after the switch - ---connection server_2 ---disable_connect_log ---source include/stop_slave.inc ---enable_connect_log - ---echo ##################################################### ---echo # Part 1: unencrypted master ---echo ##################################################### - ---connection server_1 - -call mtr.add_suppression("Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error;"); - -CREATE TABLE table1_no_encryption ( - pk INT AUTO_INCREMENT PRIMARY KEY, - ts TIMESTAMP NULL, - b BLOB -) ENGINE=MyISAM; - -INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; -FLUSH BINARY LOGS; -SET binlog_format=ROW; -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; -INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; - -# Make sure that binary logs are not encrypted - ---let SEARCH_RANGE = 500000 ---let SEARCH_FILE= master-bin.0* ---let SEARCH_PATTERN= table1_no_encryption ---source include/search_pattern_in_file.inc - -# We are storing the position now, because up to this point the slave -# should be able to synchronize with master ---save_master_pos - ---echo ##################################################### ---echo # Part 2: restart master, now with binlog encryption ---echo ##################################################### - ---let $rpl_server_parameters= --encrypt-binlog=1 --plugin-load-add=file_key_management --file-key-management --loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt - ---let $rpl_server_number= 1 ---source restart_server.inc - -CREATE TABLE table2_to_encrypt ( - pk INT AUTO_INCREMENT PRIMARY KEY, - ts TIMESTAMP NULL, - b BLOB -) ENGINE=MyISAM; - -INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; -FLUSH BINARY LOGS; -SET binlog_format=ROW; -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; -INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; - -# Make sure that binary logs are encrypted - ---let SEARCH_FILE= master-bin.0* ---let SEARCH_PATTERN= table2_to_encrypt ---source include/search_pattern_in_file.inc - ---echo ##################################################### ---echo # Part 3: restart master again without encryption ---echo ##################################################### - ---let $rpl_server_parameters= --encrypt-binlog=0 ---let $rpl_server_number= 1 ---source restart_server.inc - -CREATE TABLE table3_no_encryption ( - pk INT AUTO_INCREMENT PRIMARY KEY, - ts TIMESTAMP NULL, - b BLOB -) ENGINE=MyISAM; - -INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); -INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; -INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; - ---echo ##################################################### ---echo # Check: resume replication and check how it goes ---echo ##################################################### - ---connection server_2 -start slave; -# The slave should be able to synchronize with master up to -# the previously saved position (when the log was still unencrypted) ---sync_with_master - ---connection server_1 -# Now save the current position and make slave to try to syncrhonize. -# It shouldn't work, the slave IO thread is expected to abort with an error ---save_master_pos - ---connection server_2 ---let slave_io_errno=1236 ---source include/wait_for_slave_io_error.inc - ---sorted_result -SHOW TABLES; - ---disable_connect_log ---source include/stop_slave.inc ---enable_connect_log -reset slave; - ---echo ########## ---echo # Cleanup ---echo ########## - ---connection server_1 -reset master; - -SELECT COUNT(*) FROM table1_no_encryption; -SELECT COUNT(*) FROM table2_to_encrypt; -SELECT COUNT(*) FROM table3_no_encryption; -DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; - ---connection server_2 ---disable_connect_log ---source include/start_slave.inc ---source include/rpl_end.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.cnf b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.cnf new file mode 100644 index 00000000000..73c9ad655bf --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.cnf @@ -0,0 +1,5 @@ +!include my.cnf + +[mysqld.1] +encrypt-binlog=0 +skip-file-key-management diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result new file mode 100644 index 00000000000..33c1f1413b4 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result @@ -0,0 +1,85 @@ +################# +# Initialization +################# +include/rpl_init.inc [topology=1->2] +connection server_2; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=NO; +##################################################### +# Part 1: unencrypted master +##################################################### +connection server_1; +call mtr.add_suppression("Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error;"); +CREATE TABLE table1_no_encryption ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +NOT FOUND /table1_no_encryption/ in master-bin.0* +##################################################### +# Part 2: restart master, now with binlog encryption +##################################################### +connection default; +connection server_1; +CREATE TABLE table2_to_encrypt ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +NOT FOUND /table2_to_encrypt/ in master-bin.0* +##################################################### +# Part 3: restart master again without encryption +##################################################### +connection default; +connection server_1; +CREATE TABLE table3_no_encryption ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +##################################################### +# Check: resume replication and check how it goes +##################################################### +connection server_2; +start slave; +connection server_1; +connection server_2; +include/wait_for_slave_io_error.inc [errno=1236] +SHOW TABLES; +Tables_in_test +table1_no_encryption +include/stop_slave.inc +reset slave; +########## +# Cleanup +########## +connection server_1; +reset master; +SELECT COUNT(*) FROM table1_no_encryption; +COUNT(*) +8 +SELECT COUNT(*) FROM table2_to_encrypt; +COUNT(*) +8 +SELECT COUNT(*) FROM table3_no_encryption; +COUNT(*) +4 +DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; +connection server_2; +include/start_slave.inc +include/rpl_end.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test new file mode 100644 index 00000000000..732058c21b8 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test @@ -0,0 +1,158 @@ +# +# The test starts with unencrypted master. +# It stops replication, generates a few statement and row events +# on the master, then restarts the server with encrypted binlog, +# generates some more events and restarts it back without encryption +# (no encryption plugin). +# Then it resumes replication and should error with +# ER_MASTER_FATAL_ERROR_READING_BINLOG because the encrypted binlog is +# sent and unable to be decrypted. +# +# Note this variation of encrypted_master_switch_to_unencrypted tests +# using MASTER_USE_GTID=NO. In contrast to the GTID variant of this +# test, at part 3 (the error case), the master will scan binlogs +# starting from the first one (which is unencrypted initially, so +# replication is okay) and continue until the slave encounters the +# first encrypted event, which causes the slave to error. +# + +--source include/have_binlog_format_mixed.inc + +--echo ################# +--echo # Initialization +--echo ################# + +--let $rpl_topology= 1->2 +--source include/rpl_init.inc + +--enable_connect_log + +# We stop replication because we want it to happen after the switch + +--connection server_2 +--disable_connect_log +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=NO; +--enable_connect_log + +--echo ##################################################### +--echo # Part 1: unencrypted master +--echo ##################################################### + +--connection server_1 + +call mtr.add_suppression("Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error;"); + +CREATE TABLE table1_no_encryption ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; + +# Make sure that binary logs are not encrypted + +--let SEARCH_RANGE = 500000 +--let SEARCH_FILE= master-bin.0* +--let SEARCH_PATTERN= table1_no_encryption +--source include/search_pattern_in_file.inc + +# We are storing the position now, because up to this point the slave +# should be able to synchronize with master +--save_master_pos + +--echo ##################################################### +--echo # Part 2: restart master, now with binlog encryption +--echo ##################################################### + +--let $rpl_server_parameters= --encrypt-binlog=1 --plugin-load-add=file_key_management --file-key-management --loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt + +--let $rpl_server_number= 1 +--source restart_server.inc + +CREATE TABLE table2_to_encrypt ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; + +# Make sure that binary logs are encrypted + +--let SEARCH_FILE= master-bin.0* +--let SEARCH_PATTERN= table2_to_encrypt +--source include/search_pattern_in_file.inc + +--echo ##################################################### +--echo # Part 3: restart master again without encryption +--echo ##################################################### + +--let $rpl_server_parameters= --encrypt-binlog=0 +--let $rpl_server_number= 1 +--source restart_server.inc + +CREATE TABLE table3_no_encryption ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; + +--echo ##################################################### +--echo # Check: resume replication and check how it goes +--echo ##################################################### + +--connection server_2 +start slave; +# The slave should be able to synchronize with master up to +# the previously saved position (when the log was still unencrypted) +--sync_with_master + +--connection server_1 +# Now save the current position and make slave to try to syncrhonize. +# It shouldn't work, the slave IO thread is expected to abort with an error +--save_master_pos + +--connection server_2 +--let slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc + +--sorted_result +SHOW TABLES; + +--disable_connect_log +--source include/stop_slave.inc +--enable_connect_log +reset slave; + +--echo ########## +--echo # Cleanup +--echo ########## + +--connection server_1 +reset master; + +SELECT COUNT(*) FROM table1_no_encryption; +SELECT COUNT(*) FROM table2_to_encrypt; +SELECT COUNT(*) FROM table3_no_encryption; +DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; + +--connection server_2 +--disable_connect_log +--source include/start_slave.inc +--source include/rpl_end.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.cnf b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.cnf new file mode 100644 index 00000000000..ad1b8b44c24 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.cnf @@ -0,0 +1,8 @@ +!include my.cnf + +[mysqld.1] +encrypt-binlog=0 +skip-file-key-management + +[mysqld.2] +gtid-domain-id=1 diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result new file mode 100644 index 00000000000..16ea30557e7 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result @@ -0,0 +1,84 @@ +################# +# Initialization +################# +include/rpl_init.inc [topology=1->2] +connection server_2; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS; +call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'"); +##################################################### +# Part 1: unencrypted master +##################################################### +connection server_1; +CREATE TABLE table1_no_encryption ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +NOT FOUND /table1_no_encryption/ in master-bin.0* +##################################################### +# Part 2: restart master, now with binlog encryption +##################################################### +connection default; +connection server_1; +CREATE TABLE table2_to_encrypt ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +NOT FOUND /table2_to_encrypt/ in master-bin.0* +##################################################### +# Part 3: restart master again without encryption +##################################################### +connection default; +connection server_1; +CREATE TABLE table3_no_encryption ( +pk INT AUTO_INCREMENT PRIMARY KEY, +ts TIMESTAMP NULL, +b BLOB +) ENGINE=MyISAM; +INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +##################################################### +# Check: resume replication and check how it goes +##################################################### +connection server_2; +start slave; +include/wait_for_slave_io_error.inc [errno=1236] +# Ensuring slave was unable to replicate any transactions.. +# ..success +SHOW TABLES; +Tables_in_test +include/stop_slave.inc +reset slave; +########## +# Cleanup +########## +connection server_1; +reset master; +SELECT COUNT(*) FROM table1_no_encryption; +COUNT(*) +8 +SELECT COUNT(*) FROM table2_to_encrypt; +COUNT(*) +8 +SELECT COUNT(*) FROM table3_no_encryption; +COUNT(*) +4 +DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; +connection server_2; +include/start_slave.inc +include/rpl_end.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test new file mode 100644 index 00000000000..f882e8f3440 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test @@ -0,0 +1,154 @@ +# +# The test starts with unencrypted master. +# It stops replication, generates a few statement and row events +# on the master, then restarts the server with encrypted binlog, +# generates some more events and restarts it back without encryption +# (no encryption plugin). +# Then it resumes replication and should error with +# ER_MASTER_FATAL_ERROR_READING_BINLOG because the encrypted binlog is +# sent and unable to be decrypted. +# +# Note this variation of encrypted_master_switch_to_unencrypted tests +# using MASTER_USE_GTID=SLAVE_POS. encrypted_master_switch_to_unencrypted +# was the original test which only used binlog coordinates. When tested +# using MASTER_USE_GTID=Slave_Pos, the master optimizes the detection of +# an undecryptable binlog. I.e, the master will initially look for a +# Gtid_list_log_event, but fail to decrypt it and fail immediately in +# part 3. +# + +--source include/have_binlog_format_mixed.inc + +--echo ################# +--echo # Initialization +--echo ################# + +--let $rpl_topology= 1->2 +--source include/rpl_init.inc + +--enable_connect_log + +# We stop replication because we want it to happen after the switch + +--connection server_2 +--disable_connect_log +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS; +--enable_connect_log +call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'"); + +--echo ##################################################### +--echo # Part 1: unencrypted master +--echo ##################################################### + +--connection server_1 + +CREATE TABLE table1_no_encryption ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; +INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; + +# Make sure that binary logs are not encrypted + +--let SEARCH_RANGE = 500000 +--let SEARCH_FILE= master-bin.0* +--let SEARCH_PATTERN= table1_no_encryption +--source include/search_pattern_in_file.inc + +--echo ##################################################### +--echo # Part 2: restart master, now with binlog encryption +--echo ##################################################### + +--let $rpl_server_parameters= --encrypt-binlog=1 --plugin-load-add=$FILE_KEY_MANAGEMENT_SO --file-key-management --loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt + +--let $rpl_server_number= 1 +--source restart_server.inc + +CREATE TABLE table2_to_encrypt ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +FLUSH BINARY LOGS; +SET binlog_format=ROW; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; +INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; + +# Make sure that binary logs are encrypted + +--let SEARCH_FILE= master-bin.0* +--let SEARCH_PATTERN= table2_to_encrypt +--source include/search_pattern_in_file.inc + +--echo ##################################################### +--echo # Part 3: restart master again without encryption +--echo ##################################################### + +--let $rpl_server_parameters= --encrypt-binlog=0 +--let $rpl_server_number= 1 +--source restart_server.inc + +CREATE TABLE table3_no_encryption ( + pk INT AUTO_INCREMENT PRIMARY KEY, + ts TIMESTAMP NULL, + b BLOB +) ENGINE=MyISAM; + +INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; +INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; + +--echo ##################################################### +--echo # Check: resume replication and check how it goes +--echo ##################################################### + +--connection server_2 +start slave; +# Make slave to try to synchronize. It shouldn't work, the slave IO thread is +# expected to abort with an error +--let $slave_io_errno= 1236 +--source include/wait_for_slave_io_error.inc + +--echo # Ensuring slave was unable to replicate any transactions.. +--let $gsp= `SELECT @@global.gtid_slave_pos` +if (`SELECT strcmp("$gsp","")`) +{ + die Slave without encryption configured should fail to read encrypted binlog; +} +--echo # ..success + +--sorted_result +SHOW TABLES; + +--disable_connect_log +--source include/stop_slave.inc +--enable_connect_log +reset slave; + +--echo ########## +--echo # Cleanup +--echo ########## + +--connection server_1 +reset master; + +SELECT COUNT(*) FROM table1_no_encryption; +SELECT COUNT(*) FROM table2_to_encrypt; +SELECT COUNT(*) FROM table3_no_encryption; +DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; + +--connection server_2 +--disable_connect_log +--source include/start_slave.inc +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index 8c75ae847b3..38ab6db746c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -10786,7 +10786,10 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list) if (typ == START_ENCRYPTION_EVENT) { if (fdle->start_decryption((Start_encryption_log_event*) ev)) + { errormsg= "Could not set up decryption for binlog."; + break; + } } delete ev; if (typ == ROTATE_EVENT || typ == STOP_EVENT || -- cgit v1.2.1 From 4ec3dca34baeeeb750d4104d64cda0b022a7ef70 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Thu, 29 Sep 2022 13:40:51 -0600 Subject: MDEV-28798: Cosmetic Changes Only Removed trailing whitespaces --- .../encrypted_master_switch_to_unencrypted_coords.test | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test index 732058c21b8..a34c9715239 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test @@ -1,8 +1,8 @@ # -# The test starts with unencrypted master. +# The test starts with unencrypted master. # It stops replication, generates a few statement and row events -# on the master, then restarts the server with encrypted binlog, -# generates some more events and restarts it back without encryption +# on the master, then restarts the server with encrypted binlog, +# generates some more events and restarts it back without encryption # (no encryption plugin). # Then it resumes replication and should error with # ER_MASTER_FATAL_ERROR_READING_BINLOG because the encrypted binlog is @@ -47,7 +47,7 @@ CREATE TABLE table1_no_encryption ( pk INT AUTO_INCREMENT PRIMARY KEY, ts TIMESTAMP NULL, b BLOB -) ENGINE=MyISAM; +) ENGINE=MyISAM; INSERT INTO table1_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; @@ -80,7 +80,7 @@ CREATE TABLE table2_to_encrypt ( pk INT AUTO_INCREMENT PRIMARY KEY, ts TIMESTAMP NULL, b BLOB -) ENGINE=MyISAM; +) ENGINE=MyISAM; INSERT INTO table2_to_encrypt VALUES (NULL,NOW(),'data_to_encrypt'); INSERT INTO table2_to_encrypt SELECT NULL,NOW(),b FROM table2_to_encrypt; @@ -107,7 +107,7 @@ CREATE TABLE table3_no_encryption ( pk INT AUTO_INCREMENT PRIMARY KEY, ts TIMESTAMP NULL, b BLOB -) ENGINE=MyISAM; +) ENGINE=MyISAM; INSERT INTO table3_no_encryption VALUES (NULL,NOW(),'data_no_encryption'); INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; @@ -119,7 +119,7 @@ INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; --connection server_2 start slave; -# The slave should be able to synchronize with master up to +# The slave should be able to synchronize with master up to # the previously saved position (when the log was still unencrypted) --sync_with_master -- cgit v1.2.1 From 29fb041007285c34d9c22dbc6359a2e9b9ea32f3 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 5 Apr 2023 10:43:28 -0600 Subject: MDEV-30430: Enabling system versioning on tables without primary key breaks replication When replicating MDL events for a table that uses system versioning without primary keys, ensure that for data sets with duplicate records, the updates to these records with duplicates are enacted on the correct row. That is, there was a bug (reported in MDEV-30430) such that the function to find the row to update would stop after finding the first matching record. However, in the absence of primary keys, the version of the record is needed to compare the row to ensure we are updating the correct one. The fix, therefore, updates the record comparison functionality to use system version columns when there are no primary keys on the table. Reviewed By: ============ Andrei Elkin --- mysql-test/suite/versioning/r/rpl.result | 24 ++++++++++++++++++++++ mysql-test/suite/versioning/t/rpl.test | 34 ++++++++++++++++++++++++++++++++ sql/log_event.cc | 21 ++++++++++++++------ 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result index a6fa6b3fca7..17372c63e99 100644 --- a/mysql-test/suite/versioning/r/rpl.result +++ b/mysql-test/suite/versioning/r/rpl.result @@ -164,4 +164,28 @@ update t1 set i = 0; connection slave; connection master; drop table t1; +# check versioned -> versioned replication without any keys on duplicate records +connection master; +create table t1 (a INT) with system versioning; +insert into t1 values (1); +insert into t1 values (1); +delete from t1; +connection slave; +include/diff_tables.inc [master:test.t1,slave:test.t1] +connection master; +drop table t1; +connection slave; +# check unversioned -> versioned replication with non-unique keys on duplicate records +connection master; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)); +connection slave; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)) with system versioning; +connection master; +insert into t1 values (1,1); +insert into t1 values (1,1); +delete from t1; +connection slave; +include/diff_tables.inc [master:test.t1,slave:test.t1] +connection master; +drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl.test b/mysql-test/suite/versioning/t/rpl.test index b5be68feece..7d78b60e6fa 100644 --- a/mysql-test/suite/versioning/t/rpl.test +++ b/mysql-test/suite/versioning/t/rpl.test @@ -133,4 +133,38 @@ sync_slave_with_master; connection master; drop table t1; + +# +# MDEV-30430: Enabling system versioning on tables without primary key breaks replication +# Note that bugs are only present with row binlog format +# +--echo # check versioned -> versioned replication without any keys on duplicate records +connection master; +create table t1 (a INT) with system versioning; +insert into t1 values (1); +insert into t1 values (1); +delete from t1; +sync_slave_with_master; +--let $diff_tables= master:test.t1,slave:test.t1 +--source include/diff_tables.inc +connection master; +drop table t1; +sync_slave_with_master; + +--echo # check unversioned -> versioned replication with non-unique keys on duplicate records +connection master; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)); +connection slave; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)) with system versioning; +connection master; +insert into t1 values (1,1); +insert into t1 values (1,1); +delete from t1; +sync_slave_with_master; +--let $diff_tables= master:test.t1,slave:test.t1 +--source include/diff_tables.inc + +connection master; +drop table t1; + --source include/rpl_end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index 14cdf880d62..74b39dcadef 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -13873,7 +13873,7 @@ uint8 Write_rows_log_event::get_trg_event_map() Returns TRUE if different. */ -static bool record_compare(TABLE *table) +static bool record_compare(TABLE *table, bool vers_from_plain= false) { bool result= FALSE; /** @@ -13906,10 +13906,19 @@ static bool record_compare(TABLE *table) /* Compare fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if (table->versioned() && (*ptr)->vers_sys_field()) - { + /* + If the table is versioned, don't compare using the version if there is a + primary key. If there isn't a primary key, we need the version to + identify the correct record if there are duplicate rows in the data set. + However, if the primary server is unversioned (vers_from_plain is true), + then we implicitly use row_end as the primary key on our side. This is + because the implicit row_end value will be set to the maximum value for + the latest row update (which is what we care about). + */ + if (table->versioned() && (*ptr)->vers_sys_field() && + (table->s->primary_key < MAX_KEY || + (vers_from_plain && table->vers_start_field() == (*ptr)))) continue; - } /** We only compare field contents that are not null. NULL fields (i.e., their null bits) were compared @@ -14306,7 +14315,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) /* We use this to test that the correct key is used in test cases. */ DBUG_EXECUTE_IF("slave_crash_if_index_scan", abort();); - while (record_compare(table)) + while (record_compare(table, m_vers_from_plain)) { while ((error= table->file->ha_index_next(table->record[0]))) { @@ -14359,7 +14368,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) goto end; } } - while (record_compare(table)); + while (record_compare(table, m_vers_from_plain)); /* Note: above record_compare will take into account all record fields -- cgit v1.2.1 From a72b2c3ffb15541520de96c29ea482f80a57f46f Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 24 Apr 2023 17:57:45 +0300 Subject: MDEV-31121: ANALYZE statement produces 0 for all timings in embedded server Timers require my_timer_init() call. It was made only in mysqld_main(). Call it also from init_embedded_server(). --- libmysqld/lib_sql.cc | 2 ++ mysql-test/main/analyze_format_json_emb.result | 11 +++++++++++ mysql-test/main/analyze_format_json_emb.test | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 mysql-test/main/analyze_format_json_emb.result create mode 100644 mysql-test/main/analyze_format_json_emb.test diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 5742a8d66ef..565a722e13b 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -565,6 +565,8 @@ int init_embedded_server(int argc, char **argv, char **groups) if (ho_error != 0) return 1; + my_timer_init(&sys_timer_info); + if (init_common_variables()) { mysql_server_end(); diff --git a/mysql-test/main/analyze_format_json_emb.result b/mysql-test/main/analyze_format_json_emb.result new file mode 100644 index 00000000000..d61e205f031 --- /dev/null +++ b/mysql-test/main/analyze_format_json_emb.result @@ -0,0 +1,11 @@ +# +# MDEV-31121: ANALYZE statement produces 0 for all timings in embedded serve +# +create table t1 (a int); +insert into t1 values (0),(0); +set @js='$out'; +set @out=(select json_extract(@js,'$**.query_block.r_total_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; +cast(json_extract(@out,'$[0]') as DOUBLE) > 0 +1 +drop table t1; diff --git a/mysql-test/main/analyze_format_json_emb.test b/mysql-test/main/analyze_format_json_emb.test new file mode 100644 index 00000000000..dcf6f24dd8e --- /dev/null +++ b/mysql-test/main/analyze_format_json_emb.test @@ -0,0 +1,18 @@ +--source include/is_embedded.inc +--source include/big_test.inc + +--echo # +--echo # MDEV-31121: ANALYZE statement produces 0 for all timings in embedded serve +--echo # +create table t1 (a int); +insert into t1 values (0),(0); +let $out=` +analyze format=json select sleep(1+a) from t1 +`; + +evalp set @js='$out'; +set @out=(select json_extract(@js,'$**.query_block.r_total_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; + +drop table t1; + -- cgit v1.2.1 From e22a57da827f11f0ba9903675e4086ab9cf52a0d Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 23 Mar 2023 18:45:34 +0200 Subject: MDEV-30620 Trying to lock uninitialized LOCK_parallel_entry The error was seen by a number of mtr tests being caused by overdue initialization of rpl_parallel::LOCK_parallel_entry. Specifically, SHOW-SLAVE-STATUS might find in rpl_parallel::workers_idle() a gtid domain hash entry already inserted whose mutex had not done mysql_mutex_init(). Fixed with swapping the mutex init and the its entry's stack insertion. Tested with a generous number of `mtr --repeat` of a few of the reported to fail tests, incl rpl.parallel_backup. --- sql/rpl_parallel.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 7e70e04b857..746c923ba44 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -2312,14 +2312,16 @@ rpl_parallel::find(uint32 domain_id) e->domain_id= domain_id; e->stop_on_error_sub_id= (uint64)ULONGLONG_MAX; e->pause_sub_id= (uint64)ULONGLONG_MAX; + mysql_mutex_init(key_LOCK_parallel_entry, &e->LOCK_parallel_entry, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_parallel_entry, &e->COND_parallel_entry, NULL); if (my_hash_insert(&domain_hash, (uchar *)e)) { + mysql_cond_destroy(&e->COND_parallel_entry); + mysql_mutex_destroy(&e->LOCK_parallel_entry); my_free(e); return NULL; } - mysql_mutex_init(key_LOCK_parallel_entry, &e->LOCK_parallel_entry, - MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_parallel_entry, &e->COND_parallel_entry, NULL); } else e->force_abort= false; -- cgit v1.2.1 From b3817425d96dc24591eb2c8e634ef5143d23888a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 21 Apr 2023 14:02:56 +0200 Subject: MDEV-11356 Option skip-core-file does not work remove ancient hard-coded treatment of --core-file. This enables normal my_getopt behavior for the already existing sysvar --- mysql-test/main/mysqld--help.result | 3 ++- mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 4 ++-- mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result | 4 ++-- sql/mysqld.cc | 5 ----- sql/sys_vars.cc | 7 +++---- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index c008df32257..6ada7faeb10 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -173,7 +173,7 @@ The following specify which files/extra groups are read (specified before remain ALWAYS --console Write error output on screen; don't remove the console window on windows. - --core-file Write core on errors. + --core-file Write core on crashes -h, --datadir=name Path to the database root directory --date-format=name The DATE format (ignored) --datetime-format=name @@ -1441,6 +1441,7 @@ column-compression-zlib-wrap FALSE completion-type NO_CHAIN concurrent-insert AUTO console TRUE +core-file TRUE date-format %Y-%m-%d datetime-format %Y-%m-%d %H:%i:%s deadlock-search-depth-long 15 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 9454f1b9d96..1ed5b5ce3bd 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -645,13 +645,13 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME CORE_FILE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT write a core-file on crashes +VARIABLE_COMMENT Write core on crashes NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DATADIR VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 27e5daf7615..125d629ac87 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -645,13 +645,13 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME CORE_FILE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT write a core-file on crashes +VARIABLE_COMMENT Write core on crashes NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES -COMMAND_LINE_ARGUMENT NULL +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DATADIR VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 228a3d909e2..c110baa9634 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6754,8 +6754,6 @@ struct my_option my_long_options[]= {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.", &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG, - NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "Built in DBUG debugger. Disabled in this build.", ¤t_dbug_option, ¤t_dbug_option, 0, GET_STR, OPT_ARG, @@ -8542,9 +8540,6 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument) case (int) OPT_SKIP_HOST_CACHE: opt_specialflag|= SPECIAL_NO_HOST_CACHE; break; - case (int) OPT_WANT_CORE: - test_flags |= TEST_CORE_ON_SIGNAL; - break; case OPT_CONSOLE: if (opt_console) opt_error_log= 0; // Force logs to stdout diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 4dd45b7ce43..6cb2733feb0 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -531,10 +531,9 @@ bool check_has_super(sys_var *self, THD *thd, set_var *var) return false; } -static Sys_var_bit Sys_core_file("core_file", "write a core-file on crashes", - READ_ONLY GLOBAL_VAR(test_flags), NO_CMD_LINE, - TEST_CORE_ON_SIGNAL, DEFAULT(IF_WIN(TRUE,FALSE)), NO_MUTEX_GUARD, NOT_IN_BINLOG, - 0,0,0); +static Sys_var_bit Sys_core_file("core_file", "Write core on crashes", + READ_ONLY GLOBAL_VAR(test_flags), CMD_LINE(OPT_ARG), + TEST_CORE_ON_SIGNAL, DEFAULT(IF_WIN(TRUE,FALSE))); static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) { -- cgit v1.2.1 From b942f41438339bf6ba33d9156471b29a19fb4121 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 25 Apr 2023 12:37:13 +0200 Subject: MDEV-30218 update test result followup for d1a46c68cd4 --- mysql-test/main/selectivity_innodb.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/main/selectivity_innodb.result b/mysql-test/main/selectivity_innodb.result index 6c6811f9754..4ee2da02ec6 100644 --- a/mysql-test/main/selectivity_innodb.result +++ b/mysql-test/main/selectivity_innodb.result @@ -1671,7 +1671,7 @@ Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` # gives selectivity data explain extended select * from t1 where a in (17,51,5) and b=2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ref b,a b 5 const 59 2.90 Using where +1 SIMPLE t1 range|filter b,a a|b 5|5 NULL 29 (6%) 5.90 Using index condition; Using where; Using rowid filter Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` = 2 and `test`.`t1`.`a` in (17,51,5) drop table t1; -- cgit v1.2.1 From f99a891858ac64fb09ab23aa6d3adb78fc491f6b Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Mon, 13 Mar 2023 11:56:53 +0200 Subject: MDEV-30837: Remove usage of AWK from Debian init and postinst scripts AWK in used in Debian SysV-init and postinst scripts to determine is there enough space starting MariaDB database or create new database to target destination. These AWK scripts can be rewrited to use pure SH or help using Coreutils which is mandatory for usage of MariaDB currently. Reasoning behind this is to get rid of one very less used dependency --- debian/mariadb-server-10.6.mariadb.init | 5 ++++- debian/mariadb-server-10.6.preinst | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/debian/mariadb-server-10.6.mariadb.init b/debian/mariadb-server-10.6.mariadb.init index 0bc7a972e88..b2b7142084f 100644 --- a/debian/mariadb-server-10.6.mariadb.init +++ b/debian/mariadb-server-10.6.mariadb.init @@ -84,7 +84,10 @@ sanity_checks() { # check for diskspace shortage datadir=`mariadbd_get_param datadir` - if LC_ALL=C BLOCKSIZE= df --portability $datadir/. | tail -n 1 | awk '{ exit ($4>4096) }'; then + # As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024 + # 4096 blocks is then lower than 4 MB + df_available_blocks=`LC_ALL=C BLOCKSIZE= df --output=avail "$datadir" | tail -n 1` + if [ "$df_available_blocks" -lt "4096" ]; then log_failure_msg "$0: ERROR: The partition with $datadir is too full!" echo "ERROR: The partition with $datadir is too full!" | $ERR_LOGGER exit 1 diff --git a/debian/mariadb-server-10.6.preinst b/debian/mariadb-server-10.6.preinst index b79f20a9803..c865173e29e 100644 --- a/debian/mariadb-server-10.6.preinst +++ b/debian/mariadb-server-10.6.preinst @@ -209,8 +209,10 @@ if [ ! -d $mysql_datadir ] && [ ! -L $mysql_datadir ]; then mkdir -Z $mysql_datadir fi -# checking disc space -if LC_ALL=C BLOCKSIZE= df --portability $mysql_datadir/. | tail -n 1 | awk '{ exit ($4>1000) }'; then +# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024 +# 4096 blocks is then lower than 4 MB +df_available_blocks=`LC_ALL=C BLOCKSIZE= df --output=avail "$datadir" | tail -n 1` +if [ "$df_available_blocks" -lt "4096" ]; then echo "ERROR: There's not enough space in $mysql_datadir/" 1>&2 db_stop exit 1 -- cgit v1.2.1 From c5e50c48bba3bad2da4dab498135c4ba7da4b4aa Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Fri, 24 Mar 2023 11:42:15 +0200 Subject: MDEV-30837: Remove usage of AWK in autobake-debs.sh AWK is used in autobake-debs.sh for printing information about created DEB packages. This can be rewrite with bash inner commands read and echo. --- debian/autobake-deb.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index eed1f65fef6..5188413b40b 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -215,7 +215,11 @@ then for package in *.deb do echo "$package" | cut -d '_' -f 1 - dpkg-deb -c "$package" | awk '{print $1 " " $2 " " $6 " " $7 " " $8}' | sort -k 3 + # shellcheck disable=SC2034 + dpkg-deb -c "$package" | while IFS=" " read -r col1 col2 col3 col4 col5 col6 col7 col8 + do + echo "$col1 $col2 $col6 $col7 $col8" | sort -k 3 + done echo "------------------------------------------------" done fi -- cgit v1.2.1 From 6fccf8ba05a19e42ef7ec0e88d98fdcf165648bb Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 27 Apr 2023 16:14:05 +1000 Subject: MDEV-29644 post-merge fixup Applying b98375f instead of 9b32e4b for version 10.5-10.8. Applying 5075f4e instead of 9b32e4b for version 10.9+. --- .../spider/bugfix/r/self_reference_multi.result | 4 +- storage/spider/spd_db_mysql.cc | 60 ++++++++++++++-------- storage/spider/spd_db_mysql.h | 2 +- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result index 8ddf428b4ea..c4399ddf9d2 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result +++ b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result @@ -12,9 +12,9 @@ alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t0"'; select * from t0; ERROR HY000: An infinite loop is detected when opening table test.t0 select * from t1; -ERROR HY000: An infinite loop is detected when opening table test.t1 +ERROR HY000: An infinite loop is detected when opening table test.t0 select * from t2; -ERROR HY000: An infinite loop is detected when opening table test.t2 +ERROR HY000: An infinite loop is detected when opening table test.t0 drop table t0, t1, t2; for master_1 for child2 diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 78734640a52..bc8383017f7 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -2289,44 +2289,64 @@ bool spider_db_mbase::is_xa_nota_error( DBUG_RETURN(xa_nota); } -void spider_db_mbase::fetch_and_print_warnings(struct tm *l_time) +int spider_db_mbase::fetch_and_print_warnings(struct tm *l_time) { + int error_num = 0; DBUG_ENTER("spider_db_mbase::fetch_and_print_warnings"); + DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_dry_access() || db_conn->status != MYSQL_STATUS_READY || - db_conn->server_status & SERVER_MORE_RESULTS_EXISTS) - DBUG_VOID_RETURN; + db_conn->server_status & SERVER_MORE_RESULTS_EXISTS || + !db_conn->warning_count) + DBUG_RETURN(0); if (mysql_real_query(db_conn, SPIDER_SQL_SHOW_WARNINGS_STR, SPIDER_SQL_SHOW_WARNINGS_LEN)) - DBUG_VOID_RETURN; + DBUG_RETURN(0); MYSQL_RES *res= mysql_store_result(db_conn); if (!res) - DBUG_VOID_RETURN; + DBUG_RETURN(0); uint num_fields= mysql_num_fields(res); if (num_fields != 3) { mysql_free_result(res); - DBUG_VOID_RETURN; + DBUG_RETURN(0); } MYSQL_ROW row= mysql_fetch_row(res); - while (row) + if (l_time) { - fprintf(stderr, - "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] from [%s] %ld " - "to %ld: %s %s %s\n", - l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, - l_time->tm_hour, l_time->tm_min, l_time->tm_sec, conn->tgt_host, - (ulong) db_conn->thread_id, (ulong) current_thd->thread_id, row[0], - row[1], row[2]); - row= mysql_fetch_row(res); - } + while (row) + { + fprintf(stderr, + "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] from [%s] %ld " + "to %ld: %s %s %s\n", + l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, + l_time->tm_hour, l_time->tm_min, l_time->tm_sec, conn->tgt_host, + (ulong) db_conn->thread_id, (ulong) current_thd->thread_id, row[0], + row[1], row[2]); + row= mysql_fetch_row(res); + } + } else { + while (row) + { + DBUG_PRINT("info",("spider row[0]=%s", row[0])); + DBUG_PRINT("info",("spider row[1]=%s", row[1])); + DBUG_PRINT("info",("spider row[2]=%s", row[2])); + longlong res_num = + (longlong) my_strtoll10(row[1], (char**) NULL, &error_num); + DBUG_PRINT("info",("spider res_num=%lld", res_num)); + my_printf_error((int) res_num, row[2], MYF(0)); + error_num = (int) res_num; + row = mysql_fetch_row(res); + } + } + mysql_free_result(res); - DBUG_VOID_RETURN; + DBUG_RETURN(error_num); } spider_db_result *spider_db_mbase::store_result( @@ -14630,11 +14650,9 @@ int spider_mbase_handler::show_table_status( DBUG_RETURN(error_num); } } + if ((error_num = ((spider_db_mbase *) conn->db_conn)->fetch_and_print_warnings(NULL))) { - time_t cur_time = (time_t) time((time_t*) 0); - struct tm lt; - struct tm *l_time = localtime_r(&cur_time, <); - ((spider_db_mbase *) conn->db_conn)->fetch_and_print_warnings(l_time); + DBUG_RETURN(error_num); } if (share->static_records_for_status != -1) { diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 757484c3990..a8eada5a62e 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -442,7 +442,7 @@ public: bool is_xa_nota_error( int error_num ); - void fetch_and_print_warnings(struct tm *l_time); + int fetch_and_print_warnings(struct tm *l_time); spider_db_result *store_result( spider_db_result_buffer **spider_res_buf, st_spider_db_request_key *request_key, -- cgit v1.2.1 From d0a71e90b8065cfa4122125dce1ad7f3fc6929df Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 27 Apr 2023 16:55:47 +1000 Subject: deb: sid - debian autobake Deb-autobakes where failing with: dh_missing: warning: usr/share/mysql/mysql-test/mysql-test-run exists in debian/tmp but is not installed to anywhere dh_missing: warning: usr/share/mysql/mysql-test/mtr exists in debian/tmp but is not installed to anywhere dh_missing: warning: usr/share/mysql/mysql-test/mariadb-test-run exists in debian/tmp but is not installed to anywhere dh_missing: warning: usr/share/mysql/mysql-test/mysql-test-run.pl exists in debian/tmp but is not installed to anywhere Add all to mariadb-test.install and remove mariadb-test.links --- debian/mariadb-test.install | 4 ++++ debian/mariadb-test.links | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) delete mode 100644 debian/mariadb-test.links diff --git a/debian/mariadb-test.install b/debian/mariadb-test.install index 1cb063440c6..5dda38d665c 100644 --- a/debian/mariadb-test.install +++ b/debian/mariadb-test.install @@ -41,7 +41,11 @@ usr/share/mysql/mysql-test/README.stress usr/share/mysql/mysql-test/dgcov.pl usr/share/mysql/mysql-test/lib usr/share/mysql/mysql-test/mariadb-stress-test.pl +usr/share/mysql/mysql-test/mariadb-test-run usr/share/mysql/mysql-test/mariadb-test-run.pl +usr/share/mysql/mysql-test/mtr +usr/share/mysql/mysql-test/mysql-test-run +usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/purify.supp usr/share/mysql/mysql-test/suite.pm usr/share/mysql/mysql-test/valgrind.supp diff --git a/debian/mariadb-test.links b/debian/mariadb-test.links deleted file mode 100644 index 3939176ee96..00000000000 --- a/debian/mariadb-test.links +++ /dev/null @@ -1 +0,0 @@ -usr/share/mysql/mysql-test/mariadb-test-run.pl usr/share/mysql/mysql-test/mysql-test-run.pl -- cgit v1.2.1