From 588e67956af5c21191189f669f11f083e8ae35f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 13 Aug 2019 19:29:59 +0300 Subject: [PATCH 01/35] Make sure histograms do not write uninitialized bytes to record A histogram size that is odd in size with DOUBLE precision will leave the last byte unwritten. When collecting histograms, this causes the last byte to be uninitialized in the record. memset the buffer to 0 first to make sure this does not happen. --- sql/sql_statistics.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 37f73adccb3..52b3811e60d 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2109,7 +2109,12 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) Histogram_type hist_type= (Histogram_type) (thd->variables.histogram_type); uchar *histogram= NULL; if (hist_size > 0) - histogram= (uchar *) alloc_root(&table->mem_root, hist_size * columns); + { + if ((histogram= (uchar *) alloc_root(&table->mem_root, + hist_size * columns))) + bzero(histogram, hist_size * columns); + + } if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency || (hist_size && !histogram)) From 1c75ad6eed744672fdce77b0752801b67edb69f8 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 15 Aug 2019 12:57:21 +0300 Subject: [PATCH 02/35] MDEV-19834 Selectivity of an equality condition discounted twice When discounting selectivity of ref access, don't discount the selectivity we've already discounted for range access. The 10.1 version of the fix. Will need to adjust condition filtering test results in 10.4 --- mysql-test/r/selectivity.result | 34 +++++++++++++++++++++++++++++++++ mysql-test/t/selectivity.test | 24 +++++++++++++++++++++++ sql/sql_select.cc | 15 +++++++++------ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/selectivity.result b/mysql-test/r/selectivity.result index ba7c9c59361..3f5db42d341 100644 --- a/mysql-test/r/selectivity.result +++ b/mysql-test/r/selectivity.result @@ -1635,3 +1635,37 @@ set @@use_stat_tables= @save_use_stat_tables; set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; drop table t1; drop function f1; +# +# MDEV-19834 Selectivity of an equality condition discounted twice +# +set @@optimizer_use_condition_selectivity=4; +set @@use_stat_tables='preferably'; +create table t1 (a int, b int, key (b), key (a)); +insert into t1 +select (rand(1)*1000)/10, (rand(1001)*1000)/50 from seq_1_to_1000; +analyze table t1 ; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +# Check what info the optimizer has about selectivities +explain extended select * from t1 use index () where a in (17,51,5); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 2.97 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`a` in (17,51,5)) +explain extended select * from t1 use index () where b=2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 4.76 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`b` = 2) +# Now, the equality is used for ref access, while the range condition +# 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 58 2.90 Using where +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; +set use_stat_tables= @save_use_stat_tables; +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +# End of 10.1 tests diff --git a/mysql-test/t/selectivity.test b/mysql-test/t/selectivity.test index 3df49456332..f1c9d6b31b8 100644 --- a/mysql-test/t/selectivity.test +++ b/mysql-test/t/selectivity.test @@ -1,4 +1,5 @@ --source include/have_stat_tables.inc +--source include/have_sequence.inc --disable_warnings drop table if exists t0,t1,t2,t3; @@ -1102,3 +1103,26 @@ set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectiv drop table t1; drop function f1; +--echo # +--echo # MDEV-19834 Selectivity of an equality condition discounted twice +--echo # +set @@optimizer_use_condition_selectivity=4; +set @@use_stat_tables='preferably'; +create table t1 (a int, b int, key (b), key (a)); +insert into t1 +select (rand(1)*1000)/10, (rand(1001)*1000)/50 from seq_1_to_1000; +analyze table t1 ; + +--echo # Check what info the optimizer has about selectivities +explain extended select * from t1 use index () where a in (17,51,5); +explain extended select * from t1 use index () where b=2; + +--echo # Now, the equality is used for ref access, while the range condition +--echo # gives selectivity data +explain extended select * from t1 where a in (17,51,5) and b=2; +drop table t1; + +set use_stat_tables= @save_use_stat_tables; +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +--echo # End of 10.1 tests + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fb8e4755b1d..29fc3f80ed0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7618,6 +7618,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, KEYUSE *keyuse= pos->key; KEYUSE *prev_ref_keyuse= keyuse; uint key= keyuse->key; + bool used_range_selectivity= false; /* Check if we have a prefix of key=const that matches a quick select. @@ -7643,6 +7644,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, keyparts++; } sel /= (double)table->quick_rows[key] / (double) table->stat_records(); + used_range_selectivity= true; } } @@ -7678,13 +7680,14 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, if (keyparts > keyuse->keypart) { /* Ok this is the keyuse that will be used for ref access */ - uint fldno; - if (is_hash_join_key_no(key)) - fldno= keyuse->keypart; - else - fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1; - if (keyuse->val->const_item()) + if (!used_range_selectivity && keyuse->val->const_item()) { + uint fldno; + if (is_hash_join_key_no(key)) + fldno= keyuse->keypart; + else + fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1; + if (table->field[fldno]->cond_selectivity > 0) { sel /= table->field[fldno]->cond_selectivity; From fa74088838c12210d782aa6c69faa5acebc1d3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 15 Aug 2019 07:46:41 +0300 Subject: [PATCH 03/35] MDEV-18778: mysql_tzinfo_to_sql does not work correctly in MariaDB Galera There were two problems: (1) If user wanted same time zone information on all nodes in the Galera cluster all updates were not replicated as time zone information was stored on MyISAM tables. This is fixed on Galera by altering time zone tables to InnoDB while they are modified. (2) If user wanted different time zone information to nodes in the Galera cluster TRUNCATE TABLE for time zone tables was replicated by Galera destroying time zone information from other nodes. This is fixed on Galera by introducing new option for mysql_tzinfo_to_sql_symlink tool --skip-write-binlog to disable Galera replication while time zone tables are modified. Changes to be committed: modified: mysql-test/r/mysql_tzinfo_to_sql_symlink.result modified: mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result new file: mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result new file: mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test modified: sql/tztime.cc --- .../r/mysql_tzinfo_to_sql_symlink.result | 104 ++++++++++++++---- .../r/mysql_tzinfo_to_sql_symlink.result | 82 +++++++++++--- .../r/mysql_tzinfo_to_sql_symlink_skip.result | 74 +++++++++++++ .../t/mysql_tzinfo_to_sql_symlink_skip.test | 40 +++++++ sql/tztime.cc | 64 +++++++++-- 5 files changed, 319 insertions(+), 45 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result create mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test diff --git a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result index 03543244105..e33a519e897 100644 --- a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result @@ -2,9 +2,15 @@ # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above # # Verbose run -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=InnoDB; +ALTER TABLE time_zone_name ENGINE=InnoDB; +ALTER TABLE time_zone_transition ENGINE=InnoDB; +ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -28,11 +34,25 @@ Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zo Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # Silent run -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=InnoDB; +ALTER TABLE time_zone_name ENGINE=InnoDB; +ALTER TABLE time_zone_transition ENGINE=InnoDB; +ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -53,39 +73,83 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # # Testing with explicit timezonefile # -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES (@time_zone_id, 0, 0, 0, 'GMT') ; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # # Testing --leap # -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone_leap_second ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone_leap_second; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone_leap_second ENGINE=MyISAM; +END IF| +\d ; ALTER TABLE time_zone_leap_second ORDER BY Transition_time; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # # MDEV-6236 - [PATCH] mysql_tzinfo_to_sql may produce invalid SQL # -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=InnoDB; +ALTER TABLE time_zone_name ENGINE=InnoDB; +ALTER TABLE time_zone_transition ENGINE=InnoDB; +ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result index c00a0c73ce3..9a0abd4460a 100644 --- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result @@ -2,9 +2,15 @@ # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above # # Verbose run -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=InnoDB; +ALTER TABLE time_zone_name ENGINE=InnoDB; +ALTER TABLE time_zone_transition ENGINE=InnoDB; +ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -28,11 +34,25 @@ Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zo Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # Silent run -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=InnoDB; +ALTER TABLE time_zone_name ENGINE=InnoDB; +ALTER TABLE time_zone_transition ENGINE=InnoDB; +ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -53,26 +73,56 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # # Testing with explicit timezonefile # -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES (@time_zone_id, 0, 0, 0, 'GMT') ; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; # # Testing --leap # -set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?'); -prepare set_wsrep_myisam from @prep; -set @toggle=1; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone_leap_second ENGINE=InnoDB; +END IF| +\d ; TRUNCATE TABLE time_zone_leap_second; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone_leap_second ENGINE=MyISAM; +END IF| +\d ; ALTER TABLE time_zone_leap_second ORDER BY Transition_time; -set @toggle=0; execute set_wsrep_myisam using @toggle; +\d | +IF (select count(*) from information_schema.global_variables where +variable_name='wsrep_on') = 1 THEN +ALTER TABLE time_zone ENGINE=MyISAM; +ALTER TABLE time_zone_name ENGINE=MyISAM; +ALTER TABLE time_zone_transition ENGINE=MyISAM; +ALTER TABLE time_zone_transition_type ENGINE=MyISAM; +END IF| +\d ; diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result new file mode 100644 index 00000000000..4ce57c641b3 --- /dev/null +++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result @@ -0,0 +1,74 @@ +# +# MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above +# +# Verbose run +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); +prepare set_wsrep_write_binlog from @prep1; +set @toggle=0; execute set_wsrep_write_binlog using @toggle; +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/ignored.tab' as time zone. Skipping it. +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. +Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. +ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; +ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; +# Silent run +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); +prepare set_wsrep_write_binlog from @prep1; +set @toggle=0; execute set_wsrep_write_binlog using @toggle; +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; +ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; +# +# Testing with explicit timezonefile +# +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); +prepare set_wsrep_write_binlog from @prep1; +set @toggle=0; execute set_wsrep_write_binlog using @toggle; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +# +# Testing --leap +# +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); +prepare set_wsrep_write_binlog from @prep1; +set @toggle=0; execute set_wsrep_write_binlog using @toggle; +TRUNCATE TABLE time_zone_leap_second; +ALTER TABLE time_zone_leap_second ORDER BY Transition_time; diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test new file mode 100644 index 00000000000..bb3009bd432 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test @@ -0,0 +1,40 @@ +--source include/have_wsrep.inc +--source include/have_symlink.inc +--source include/not_windows.inc + +--echo # +--echo # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above +--echo # + +--exec mkdir $MYSQLTEST_VARDIR/zoneinfo +--exec ln -s $MYSQLTEST_VARDIR/zoneinfo $MYSQLTEST_VARDIR/zoneinfo/posix +--copy_file std_data/zoneinfo/GMT $MYSQLTEST_VARDIR/zoneinfo/GMT +--copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/garbage +--copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/ignored.tab + +--echo # Verbose run +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --verbose --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo 2>&1 + +--echo # Silent run +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo 2>&1 + +--echo # +--echo # Testing with explicit timezonefile +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo/GMT XXX 2>&1 + +--echo # +--echo # Testing --leap +--echo # + +--exec $MYSQL_TZINFO_TO_SQL --leap --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 + +# +# Cleanup +# + +--exec rm -rf $MYSQLTEST_VARDIR/zoneinfo diff --git a/sql/tztime.cc b/sql/tztime.cc index 060f5611fdb..8f66dfa0c9e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -148,6 +148,7 @@ typedef struct st_time_zone_info static my_bool prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage); +my_bool opt_leap, opt_verbose, opt_skip_write_binlog; #if defined(TZINFO2SQL) || defined(TESTTIME) @@ -2439,6 +2440,14 @@ print_tz_leaps_as_sql(const TIME_ZONE_INFO *sp) We are assuming that there are only one list of leap seconds For all timezones. */ + if (!opt_skip_write_binlog) + printf("\\d |\n" + "IF (select count(*) from information_schema.global_variables where\n" + "variable_name='wsrep_on') = 1 THEN\n" + "ALTER TABLE time_zone_leap_second ENGINE=InnoDB;\n" + "END IF|\n" + "\\d ;\n"); + printf("TRUNCATE TABLE time_zone_leap_second;\n"); if (sp->leapcnt) @@ -2451,6 +2460,14 @@ print_tz_leaps_as_sql(const TIME_ZONE_INFO *sp) printf(";\n"); } + if (!opt_skip_write_binlog) + printf("\\d |\n" + "IF (select count(*) from information_schema.global_variables where\n" + "variable_name='wsrep_on') = 1 THEN\n" + "ALTER TABLE time_zone_leap_second ENGINE=MyISAM;\n" + "END IF|\n" + "\\d ;\n"); + printf("ALTER TABLE time_zone_leap_second ORDER BY Transition_time;\n"); } @@ -2607,8 +2624,6 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level, uint verbose) } -my_bool opt_leap, opt_verbose; - static const char *load_default_groups[]= { "mysql_tzinfo_to_sql", 0}; @@ -2629,6 +2644,8 @@ static struct my_option my_long_options[] = &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"skip-write-binlog", 'S', "Do not replicate changes to time zone tables to other nodes in a Galera cluster", + &opt_skip_write_binlog,&opt_skip_write_binlog, 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} }; @@ -2697,11 +2714,14 @@ main(int argc, char **argv) return 1; } - // Replicate MyISAM DDL for this session, cf. lp:1161432 - // timezone info unfixable in XtraDB Cluster - printf("set @prep=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET GLOBAL wsrep_replicate_myisam=?', 'do ?');\n" - "prepare set_wsrep_myisam from @prep;\n" - "set @toggle=1; execute set_wsrep_myisam using @toggle;\n"); + if (opt_skip_write_binlog) + /* If skip_write_binlog is set and wsrep is compiled in we disable + sql_log_bin and wsrep_on to avoid Galera replicating below + truncate table clauses. This will allow user to set different + time zones to nodes in Galera cluster. */ + printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n" + "prepare set_wsrep_write_binlog from @prep1;\n" + "set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n"); if (argc == 1 && !opt_leap) { @@ -2709,6 +2729,21 @@ main(int argc, char **argv) root_name_end= strmake_buf(fullname, argv[0]); + if(!opt_skip_write_binlog) + { + // Alter time zone tables to InnoDB if wsrep_on is enabled + // to allow changes to them to replicate with Galera + printf("\\d |\n" + "IF (select count(*) from information_schema.global_variables where\n" + "variable_name='wsrep_on') = 1 THEN\n" + "ALTER TABLE time_zone ENGINE=InnoDB;\n" + "ALTER TABLE time_zone_name ENGINE=InnoDB;\n" + "ALTER TABLE time_zone_transition ENGINE=InnoDB;\n" + "ALTER TABLE time_zone_transition_type ENGINE=InnoDB;\n" + "END IF|\n" + "\\d ;\n"); + } + printf("TRUNCATE TABLE time_zone;\n"); printf("TRUNCATE TABLE time_zone_name;\n"); printf("TRUNCATE TABLE time_zone_transition;\n"); @@ -2750,8 +2785,19 @@ main(int argc, char **argv) free_root(&tz_storage, MYF(0)); } - // Reset wsrep_replicate_myisam. lp:1161432 - printf("set @toggle=0; execute set_wsrep_myisam using @toggle;\n"); + if(!opt_skip_write_binlog) + { + // Fall back to MyISAM + printf("\\d |\n" + "IF (select count(*) from information_schema.global_variables where\n" + "variable_name='wsrep_on') = 1 THEN\n" + "ALTER TABLE time_zone ENGINE=MyISAM;\n" + "ALTER TABLE time_zone_name ENGINE=MyISAM;\n" + "ALTER TABLE time_zone_transition ENGINE=MyISAM;\n" + "ALTER TABLE time_zone_transition_type ENGINE=MyISAM;\n" + "END IF|\n" + "\\d ;\n"); + } free_defaults(default_argv); my_end(0); From ec1f195ecf797fc5f37b0cfdbe4ee76d71a96729 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 16 Aug 2019 14:32:44 +0400 Subject: [PATCH 04/35] MDEV-15955 Assertion `field_types == 0 || field_types[field_pos] == MYSQL_TYPE_LONGLONG' failed in Protocol_text::store_longlong --- mysql-test/r/type_int.result | 24 ++++++++++++++++++++++++ mysql-test/t/type_int.test | 19 +++++++++++++++++++ sql/sql_select.cc | 22 ++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 mysql-test/r/type_int.result create mode 100644 mysql-test/t/type_int.test diff --git a/mysql-test/r/type_int.result b/mysql-test/r/type_int.result new file mode 100644 index 00000000000..aaf35690306 --- /dev/null +++ b/mysql-test/r/type_int.result @@ -0,0 +1,24 @@ +# +# Start of 5.5 tests +# +# +# MDEV-15955 Assertion `field_types == 0 || field_types[field_pos] == MYSQL_TYPE_LONGLONG' failed in Protocol_text::store_longlong +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +SELECT @a := 1 FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +@a := 1 +1 +SELECT COALESCE(1) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +COALESCE(1) +1 +SELECT COALESCE(@a:=1) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +COALESCE(@a:=1) +1 +SELECT COALESCE(@a) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +COALESCE(@a) +1 +DROP TABLE t1; +# +# End of 5.5 tests +# diff --git a/mysql-test/t/type_int.test b/mysql-test/t/type_int.test new file mode 100644 index 00000000000..52be12bf494 --- /dev/null +++ b/mysql-test/t/type_int.test @@ -0,0 +1,19 @@ +--echo # +--echo # Start of 5.5 tests +--echo # + +--echo # +--echo # MDEV-15955 Assertion `field_types == 0 || field_types[field_pos] == MYSQL_TYPE_LONGLONG' failed in Protocol_text::store_longlong +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +SELECT @a := 1 FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +SELECT COALESCE(1) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +SELECT COALESCE(@a:=1) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +SELECT COALESCE(@a) FROM t1 ORDER BY STRCMP(STDDEV_SAMP(a), 'bar'); +DROP TABLE t1; + +--echo # +--echo # End of 5.5 tests +--echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3d78000b3d4..529ecd78836 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14762,6 +14762,28 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, if (item->cmp_type() == TIME_RESULT || item->field_type() == MYSQL_TYPE_GEOMETRY) new_field= item->tmp_table_field_from_field_type(table, 1); + else if (item->type() == Item::FUNC_ITEM && + static_cast(item)->functype() == Item_func::SUSERVAR_FUNC) + { + /* + A temporary solution for versions 5.5 .. 10.3. + This change should be null-merged to 10.4. + + Item_func_set_user_var is special. It overrides make_field(). + by adding a special branch `if (result_field)...`. + So it's important to preserve the exact data type here, + to avoid type mismatch in Protocol_text::store_longlong() + See MDEV-15955. + + Other Item_func descendants are not affected by MDEV-15955. + They don't override make_field() so they don't use result_field + when initializing Send_field. + + This is properly fixed in 10.4 in the method + Item_func_user_var::create_tmp_field_ex(). + */ + new_field= item->tmp_table_field_from_field_type(table, false); + } else switch (item->result_type()) { case REAL_RESULT: From 1639873671e85748f0dcf89ce76ef4efce9a087c Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 15 Aug 2019 22:32:59 +0300 Subject: [PATCH 05/35] MDEV-18154 Deadlock and assertion upon no-op ALTER under LOCK TABLES 1. Revert incorrect treatment of m_needs_reopen; 2. Close single instance of TABLE instead of all instances since reopened only those that are marked for reopen. --- sql/sql_base.cc | 13 ++++++++++--- sql/sql_table.cc | 3 --- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 99c8a227861..3483c9381e8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2488,9 +2488,16 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) { if (!table_list->table || !table_list->table->needs_reopen()) continue; - /* no need to remove the table from the TDC here, thus (TABLE*)1 */ - close_all_tables_for_name(thd, table_list->table->s, - HA_EXTRA_NOT_USED, (TABLE*)1); + for (TABLE **prev= &thd->open_tables; *prev; prev= &(*prev)->next) + { + if (*prev == table_list->table) + { + thd->locked_tables_list.unlink_from_list(thd, table_list, false); + mysql_lock_remove(thd, thd->lock, *prev); + close_thread_table(thd, prev); + break; + } + } DBUG_ASSERT(table_list->table == NULL); } else diff --git a/sql/sql_table.cc b/sql/sql_table.cc index be3f9b46c0f..1543a445d7b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7831,7 +7831,6 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, Create_field *def; Field **f_ptr,*field; MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields - bool save_reopen= table->m_needs_reopen; DBUG_ENTER("mysql_prepare_alter_table"); /* @@ -8511,9 +8510,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, alter_info->create_list.swap(new_create_list); alter_info->key_list.swap(new_key_list); alter_info->check_constraint_list.swap(new_constraint_list); - DBUG_RETURN(rc); err: - table->m_needs_reopen= save_reopen; DBUG_RETURN(rc); } From ecdacf7264eecb520657ef9ed42021bcc0bcad06 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 16 Aug 2019 14:36:23 +0300 Subject: [PATCH 06/35] MDEV-19834 Selectivity of an equality condition discounted twice Update test results. --- mysql-test/r/selectivity_innodb.result | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result index 9898acd1f07..1d73c2f5d50 100644 --- a/mysql-test/r/selectivity_innodb.result +++ b/mysql-test/r/selectivity_innodb.result @@ -1645,6 +1645,40 @@ set @@use_stat_tables= @save_use_stat_tables; set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; drop table t1; drop function f1; +# +# MDEV-19834 Selectivity of an equality condition discounted twice +# +set @@optimizer_use_condition_selectivity=4; +set @@use_stat_tables='preferably'; +create table t1 (a int, b int, key (b), key (a)); +insert into t1 +select (rand(1)*1000)/10, (rand(1001)*1000)/50 from seq_1_to_1000; +analyze table t1 ; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# Check what info the optimizer has about selectivities +explain extended select * from t1 use index () where a in (17,51,5); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 2.97 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`a` in (17,51,5)) +explain extended select * from t1 use index () where b=2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 4.76 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`b` = 2) +# Now, the equality is used for ref access, while the range condition +# 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.80 Using where +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; +set use_stat_tables= @save_use_stat_tables; +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +# End of 10.1 tests set optimizer_switch=@save_optimizer_switch_for_selectivity_test; set @tmp_ust= @@use_stat_tables; set @tmp_oucs= @@optimizer_use_condition_selectivity; From dc91372de3ab4b9b849a0710b4b086619d87b6cd Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 16 Aug 2019 18:11:32 +0530 Subject: [PATCH 07/35] Problem: ======== During ibd file creation, InnoDB flushes the page0 without crypt information. During recovery, InnoDB encounters encrypted page read before initialising the crypt data of the tablespace. So it leads t corruption of page and doesn't allow innodb to start. Solution: ========= Write crypt_data information in page0 while creating .ibd file creation. During recovery, crypt_data will be initialised while processing MLOG_FILE_NAME redo log record. --- .../suite/encryption/r/file_creation.result | 26 ++++++++++++ .../suite/encryption/t/file_creation.opt | 1 + .../suite/encryption/t/file_creation.test | 41 +++++++++++++++++++ storage/innobase/fil/fil0crypt.cc | 27 ++++++++++++ storage/innobase/fil/fil0fil.cc | 20 +++++---- storage/innobase/include/fil0crypt.h | 6 +++ 6 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/encryption/r/file_creation.result create mode 100644 mysql-test/suite/encryption/t/file_creation.opt create mode 100644 mysql-test/suite/encryption/t/file_creation.test diff --git a/mysql-test/suite/encryption/r/file_creation.result b/mysql-test/suite/encryption/r/file_creation.result new file mode 100644 index 00000000000..22fe271145c --- /dev/null +++ b/mysql-test/suite/encryption/r/file_creation.result @@ -0,0 +1,26 @@ +SET GLOBAL innodb_encrypt_tables = ON; +SET GLOBAL innodb_encryption_threads = 1; +SET GLOBAL innodb_max_dirty_pages_pct = 99; +SHOW VARIABLES LIKE 'innodb_encrypt%'; +Variable_name Value +innodb_encrypt_log OFF +innodb_encrypt_tables ON +innodb_encrypt_temporary_tables OFF +innodb_encryption_rotate_key_age 1 +innodb_encryption_rotation_iops 100 +innodb_encryption_threads 1 +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(255), f3 CHAR(255), +f4 CHAR(255), f5 CHAR(255))ENGINE=INNODB; +INSERT INTO t1 VALUES(1, "mysql", "mariadb", "batman", "superman"); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +# Wait max 10 min for key encryption threads to encrypt all spaces +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +ALTER TABLE t1 FORCE; +# Kill the server +DROP TABLE t1; diff --git a/mysql-test/suite/encryption/t/file_creation.opt b/mysql-test/suite/encryption/t/file_creation.opt new file mode 100644 index 00000000000..7d3f2da7971 --- /dev/null +++ b/mysql-test/suite/encryption/t/file_creation.opt @@ -0,0 +1 @@ +--innodb-tablespaces-encryption diff --git a/mysql-test/suite/encryption/t/file_creation.test b/mysql-test/suite/encryption/t/file_creation.test new file mode 100644 index 00000000000..a0c90975a37 --- /dev/null +++ b/mysql-test/suite/encryption/t/file_creation.test @@ -0,0 +1,41 @@ +--source include/have_innodb.inc +--source include/have_example_key_management_plugin.inc + +# embedded does not support restart +-- source include/not_embedded.inc + +# +# MDEV-19348 MariaBackup prepare fails with InnoDB: Database page corruption +# on disk or a failed file read +# + +SET GLOBAL innodb_encrypt_tables = ON; +SET GLOBAL innodb_encryption_threads = 1; +SET GLOBAL innodb_max_dirty_pages_pct = 99; +SHOW VARIABLES LIKE 'innodb_encrypt%'; + +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(255), f3 CHAR(255), + f4 CHAR(255), f5 CHAR(255))ENGINE=INNODB; + +INSERT INTO t1 VALUES(1, "mysql", "mariadb", "batman", "superman"); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +--let $tables_count= `select count(*) + 1 from information_schema.tables where engine = 'InnoDB'` + +--echo # Wait max 10 min for key encryption threads to encrypt all spaces +--let $wait_timeout= 600 +--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0; +--source include/wait_condition.inc + +OPTIMIZE TABLE t1; + +--source ../../suite/innodb/include/no_checkpoint_start.inc +ALTER TABLE t1 FORCE; +--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1; +--source ../../suite/innodb/include/no_checkpoint_end.inc + +--source include/start_mysqld.inc +DROP TABLE t1; diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 9b8373a4d55..90b9aba70aa 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -356,6 +356,33 @@ fil_space_destroy_crypt_data( } } +/** Fill crypt data information to the give page. +It should be called during ibd file creation. +@param[in] flags tablespace flags +@param[in,out] page first page of the tablespace */ +void +fil_space_crypt_t::fill_page0( + ulint flags, + byte* page) +{ + const uint len = sizeof(iv); + const ulint offset = FSP_HEADER_OFFSET + + fsp_header_get_encryption_offset(page_size_t(flags)); + page0_offset = offset; + + memcpy(page + offset, CRYPT_MAGIC, MAGIC_SZ); + mach_write_to_1(page + offset + MAGIC_SZ, type); + mach_write_to_1(page + offset + MAGIC_SZ + 1, len); + memcpy(page + offset + MAGIC_SZ + 2, &iv, len); + + mach_write_to_4(page + offset + MAGIC_SZ + 2 + len, + min_key_version); + mach_write_to_4(page + offset + MAGIC_SZ + 2 + len + 4, + key_id); + mach_write_to_1(page + offset + MAGIC_SZ + 2 + len + 8, + encryption); +} + /****************************************************************** Write crypt data to a page (0) @param[in] space tablespace diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index f06179bf094..e37cb963c28 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3671,6 +3671,19 @@ fil_ibd_create( fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); + /* Create crypt data if the tablespace is either encrypted or user has + requested it to remain unencrypted. */ + if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF || + srv_encrypt_tables) { + crypt_data = fil_space_create_crypt_data(mode, key_id); + } + + if (crypt_data) { + /* Write crypt data information in page0 while creating + ibd file. */ + crypt_data->fill_page0(flags, page); + } + const page_size_t page_size(flags); IORequest request(IORequest::WRITE); @@ -3732,13 +3745,6 @@ fil_ibd_create( } } - /* Create crypt data if the tablespace is either encrypted or user has - requested it to remain unencrypted. */ - if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF || - srv_encrypt_tables) { - crypt_data = fil_space_create_crypt_data(mode, key_id); - } - space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, crypt_data, mode); if (!space) { diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 9b9f0da6fdd..24108f95167 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -180,6 +180,12 @@ struct fil_space_crypt_t : st_encryption_scheme return (encryption == FIL_ENCRYPTION_OFF); } + /** Fill crypt data information to the give page. + It should be called during ibd file creation. + @param[in] flags tablespace flags + @param[in,out] page first page of the tablespace */ + void fill_page0(ulint flags, byte* page); + /** Write crypt data to a page (0) @param[in] space tablespace @param[in,out] page0 first page of the tablespace From 6626b10a7a49eb91c2fcde2e3baef788b0ebe291 Mon Sep 17 00:00:00 2001 From: Kentoku SHIBA Date: Sat, 17 Aug 2019 00:40:38 +0900 Subject: [PATCH 08/35] fix for a compiler warning (#1372) --- storage/spider/spd_db_mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 57a0c5e6573..1b62b4a9bd5 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -5282,7 +5282,7 @@ int spider_db_mbase_util::append_tables_top_down( int error_num; uint outer_join_backup; TABLE_LIST *cur_table_list, *prev_table_list = NULL, *cond_table_list = NULL; - bool first; + bool first = TRUE; DBUG_ENTER("spider_db_mbase_util::append_tables_top_down"); DBUG_PRINT("info",("spider this=%p", this)); if ( From 44150a770fd861c3837df34357c794432baf8882 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 18 Aug 2019 13:18:09 +0300 Subject: [PATCH 09/35] Updated result for rocksdb tests after merge --- storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result | 1 + storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result | 1 + .../mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result | 1 + storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result | 1 + 4 files changed, 4 insertions(+) diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result index d37c8097622..889207040b6 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result @@ -26,6 +26,7 @@ start transaction with consistent snapshot; select VALUE > 0 as 'Has opened snapshots' from information_schema.rocksdb_dbstats where stat_type='DB_NUM_SNAPSHOTS'; Has opened snapshots 1 +connection default; SET @@GLOBAL.ROCKSDB_UPDATE_CF_OPTIONS= 'cf1={write_buffer_size=8m;target_file_size_base=1m};'; set rocksdb_bulk_load=1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result index 270d372f343..2cf2bdb91a6 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result @@ -26,6 +26,7 @@ start transaction with consistent snapshot; select VALUE > 0 as 'Has opened snapshots' from information_schema.rocksdb_dbstats where stat_type='DB_NUM_SNAPSHOTS'; Has opened snapshots 1 +connection default; SET @@GLOBAL.ROCKSDB_UPDATE_CF_OPTIONS= 'cf1={write_buffer_size=8m;target_file_size_base=1m};'; set rocksdb_bulk_load=1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result index 2fe9c551fb0..1d2497dc7e4 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result @@ -26,6 +26,7 @@ start transaction with consistent snapshot; select VALUE > 0 as 'Has opened snapshots' from information_schema.rocksdb_dbstats where stat_type='DB_NUM_SNAPSHOTS'; Has opened snapshots 1 +connection default; SET @@GLOBAL.ROCKSDB_UPDATE_CF_OPTIONS= 'cf1={write_buffer_size=8m;target_file_size_base=1m};'; set rocksdb_bulk_load=1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result index e534be48921..8b5576b8f5f 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result @@ -26,6 +26,7 @@ start transaction with consistent snapshot; select VALUE > 0 as 'Has opened snapshots' from information_schema.rocksdb_dbstats where stat_type='DB_NUM_SNAPSHOTS'; Has opened snapshots 1 +connection default; SET @@GLOBAL.ROCKSDB_UPDATE_CF_OPTIONS= 'cf1={write_buffer_size=8m;target_file_size_base=1m};'; set rocksdb_bulk_load=1; From 6dd3f24090ce2d237037eb09cf7db083ebbc92f9 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 18 Aug 2019 23:18:44 +0300 Subject: [PATCH 10/35] MDEV-19740 Debug build of 10.3.15 FTBFS * Replace LINT_INIT for non-struct types with ctor initializers; * Check BUILD_DEPS list is not empty so REMOVE_DUPLICATES won't throw error. --- cmake/build_depends.cmake | 6 ++++-- sql/opt_subselect.h | 15 +++++++-------- sql/sql_explain.cc | 1 + sql/sql_select.h | 2 +- sql/sql_statistics.cc | 7 ++----- sql/sql_table.cc | 3 +-- sql/wsrep_thd.cc | 1 + storage/innobase/fil/fil0crypt.cc | 2 ++ storage/innobase/row/row0mysql.cc | 4 ++++ storage/maria/ma_ft_nlq_search.c | 2 +- storage/myisam/ft_nlq_search.c | 2 +- 11 files changed, 25 insertions(+), 20 deletions(-) diff --git a/cmake/build_depends.cmake b/cmake/build_depends.cmake index 333df580200..5adaee33740 100644 --- a/cmake/build_depends.cmake +++ b/cmake/build_depends.cmake @@ -39,6 +39,8 @@ IF(RPM) SET(BUILD_DEPS ${BUILD_DEPS} ${${V}_DEP}) ENDIF() ENDFOREACH() - LIST(REMOVE_DUPLICATES BUILD_DEPS) - STRING(REPLACE ";" " " CPACK_RPM_BUILDREQUIRES "${BUILD_DEPS}") + IF (BUILD_DEPS) + LIST(REMOVE_DUPLICATES BUILD_DEPS) + STRING(REPLACE ";" " " CPACK_RPM_BUILDREQUIRES "${BUILD_DEPS}") + ENDIF() ENDIF(RPM) diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 94ae9a35246..2b9031b1b81 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -93,15 +93,14 @@ public: Loose_scan_opt(): try_loosescan(FALSE), bound_sj_equalities(0), - quick_uses_applicable_index(FALSE) + quick_uses_applicable_index(0), + quick_max_loose_keypart(0), + best_loose_scan_key(0), + best_loose_scan_cost(0), + best_loose_scan_records(0), + best_loose_scan_start_key(NULL), + best_max_loose_keypart(0) { - /* Protected by quick_uses_applicable_index */ - LINT_INIT(quick_max_loose_keypart); - /* The following are protected by best_loose_scan_cost!= DBL_MAX */ - LINT_INIT(best_loose_scan_key); - LINT_INIT(best_loose_scan_records); - LINT_INIT(best_max_loose_keypart); - LINT_INIT(best_loose_scan_start_key); } void init(JOIN *join, JOIN_TAB *s, table_map remaining_tables) diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index ca538752627..8ded81788a2 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -444,6 +444,7 @@ uint Explain_union::make_union_table_name(char *buf) break; default: DBUG_ASSERT(0); + type= {NULL, 0}; } memcpy(buf, type.str, (len= (uint)type.length)); diff --git a/sql/sql_select.h b/sql/sql_select.h index dd823a7d7df..efb0c474c89 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -866,7 +866,7 @@ public: void set_empty() { sjm_scan_need_tables= 0; - LINT_INIT_STRUCT(sjm_scan_last_inner); + sjm_scan_last_inner= 0; is_used= FALSE; } void set_from_prev(struct st_position *prev); diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 5b8c1b63b6f..9242e3b423a 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1808,16 +1808,13 @@ public: bool is_partial_fields_present; Index_prefix_calc(THD *thd, TABLE *table, KEY *key_info) - : index_table(table), index_info(key_info) + : index_table(table), index_info(key_info), prefixes(0), empty(true), + calc_state(NULL), is_single_comp_pk(false), is_partial_fields_present(false) { uint i; Prefix_calc_state *state; uint key_parts= table->actual_n_key_parts(key_info); - empty= TRUE; - prefixes= 0; - LINT_INIT_STRUCT(calc_state); - is_partial_fields_present= is_single_comp_pk= FALSE; uint pk= table->s->primary_key; if ((uint) (table->key_info - key_info) == pk && table->key_info[pk].user_defined_key_parts == 1) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1543a445d7b..55e84cbfeb5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10863,10 +10863,9 @@ bool Sql_cmd_create_table_like::execute(THD *thd) { DBUG_ENTER("Sql_cmd_create_table::execute"); LEX *lex= thd->lex; - TABLE_LIST *all_tables= lex->query_tables; SELECT_LEX *select_lex= &lex->select_lex; TABLE_LIST *first_table= select_lex->table_list.first; - DBUG_ASSERT(first_table == all_tables && first_table != 0); + DBUG_ASSERT(first_table == lex->query_tables && first_table != 0); bool link_to_local; TABLE_LIST *create_table= first_table; TABLE_LIST *select_tables= lex->create_last_non_select_table->next_global; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index a45828beab3..32fecda1eaa 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -432,6 +432,7 @@ static bool create_wsrep_THD(wsrep_thread_args* args) break; default: assert(0); + key= 0; break; } #endif diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 5df38391e3d..35b70501002 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2268,9 +2268,11 @@ static void fil_crypt_rotation_list_fill() /* Protect the tablespace while we may release fil_system.mutex. */ space->n_pending_ops++; +#ifndef DBUG_OFF fil_space_t* s= fil_system.read_page0( space->id); ut_ad(!s || s == space); +#endif space->n_pending_ops--; if (!space->size) { /* Page 0 was not loaded. diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index aed2f87349d..43808f157d5 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1418,11 +1418,13 @@ row_insert_for_mysql( &blob_heap); if (ins_mode != ROW_INS_NORMAL) { +#ifndef DBUG_OFF ut_ad(table->vers_start != table->vers_end); const mysql_row_templ_t* t = prebuilt->get_template_by_col(table->vers_end); ut_ad(t); ut_ad(t->mysql_col_len == 8); +#endif if (ins_mode == ROW_INS_HISTORICAL) { set_tuple_col_8(node->row, table->vers_end, trx->id, @@ -1430,9 +1432,11 @@ row_insert_for_mysql( } else /* ROW_INS_VERSIONED */ { set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf); +#ifndef DBUG_OFF t = prebuilt->get_template_by_col(table->vers_start); ut_ad(t); ut_ad(t->mysql_col_len == 8); +#endif set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf); } diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index 7becf1d7136..f7aa3afec9a 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -79,13 +79,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) MARIA_KEY key; float tmp_weight; DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; _ma_ft_make_key(info, &key, aio->keynr, keybuff, word, 0); key.data_length-= HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->lock_key_trees) mysql_rwlock_rdlock(&share->keyinfo[aio->keynr].root_lock); diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 6c36c327d81..3e433b71761 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -77,13 +77,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) uint extra= HA_FT_WLEN + info->s->rec_reflength; float tmp_weight; DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; keylen=_ft_make_key(info,aio->keynr,keybuff,word,0); keylen-=HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->concurrent_insert) mysql_rwlock_rdlock(&share->key_root_lock[aio->keynr]); From e7fda5db07b686082af6f74e561600531e2486eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 19 Aug 2019 17:09:06 +0300 Subject: [PATCH 11/35] MDEV-20377: Fix uninitialized memory in mysqltest --- client/mysqltest.cc | 3 ++- mysql-test/lib/My/SafeProcess/safe_process.cc | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index ad868722dfb..60a203ccedd 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1693,6 +1693,7 @@ void abort_not_supported_test(const char *fmt, ...) cur_file->file_name, cur_file->lineno); char buff[DIE_BUFF_SIZE]; + buff[0] = '\0'; print_file_stack(buff, buff + sizeof(buff)); fprintf(stderr, "%s", buff); diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc index a63c1565228..13d09198a0c 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2008, 2012, Oracle and/or its affiliates + Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,6 +170,7 @@ int main(int argc, char* const argv[] ) sigemptyset(&sa.sa_mask); sa_abort.sa_handler= handle_abort; + sa_abort.sa_flags= 0; sigemptyset(&sa_abort.sa_mask); /* Install signal handlers */ sigaction(SIGTERM, &sa,NULL); From 938925211a6ea23b06859a875a3891810ed5e6e9 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 19 Aug 2019 19:49:45 +0300 Subject: [PATCH 12/35] MDEV-19254 Server crashes in maria_status with partitioned table Bug was that storage_engine::info() was called with not opened table in ha_partition::info(). Fixed by ensuring that we are using an opened table. --- mysql-test/suite/maria/partition.result | 4 ++++ mysql-test/suite/maria/partition.test | 11 +++++++++++ sql/ha_partition.cc | 4 +++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/maria/partition.result create mode 100644 mysql-test/suite/maria/partition.test diff --git a/mysql-test/suite/maria/partition.result b/mysql-test/suite/maria/partition.result new file mode 100644 index 00000000000..929c6bab22e --- /dev/null +++ b/mysql-test/suite/maria/partition.result @@ -0,0 +1,4 @@ +CREATE TABLE t (a INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2; +SELECT * FROM t PARTITION (p1); +a +DROP TABLE t; diff --git a/mysql-test/suite/maria/partition.test b/mysql-test/suite/maria/partition.test new file mode 100644 index 00000000000..86f976a05e7 --- /dev/null +++ b/mysql-test/suite/maria/partition.test @@ -0,0 +1,11 @@ +--source include/have_partition.inc + +# +# MDEV-19254 +# Server crashes in maria_status / ha_maria::info upon SELECT with partition +# pruning +# + +CREATE TABLE t (a INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2; +SELECT * FROM t PARTITION (p1); +DROP TABLE t; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index aa630e83ba0..5a78249644d 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -8304,6 +8304,7 @@ int ha_partition::info(uint flag) ulonglong max_records= 0; uint32 i= 0; uint32 handler_instance= 0; + bool handler_instance_set= 0; file_array= m_file; do @@ -8316,8 +8317,9 @@ int ha_partition::info(uint flag) !bitmap_is_set(&(m_part_info->read_partitions), (uint) (file_array - m_file))) file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag); - if (file->stats.records > max_records) + if (file->stats.records > max_records || !handler_instance_set) { + handler_instance_set= 1; max_records= file->stats.records; handler_instance= i; } From 68e6c2d7688101e3941ae17ea4a36c79077ed474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 19 Aug 2019 17:11:49 +0300 Subject: [PATCH 13/35] MDEV-20377: Introduce cmake -DWITH_MSAN:BOOL=ON MemorySanitizer is a compile-time instrumentation layer in clang and GCC. Together with AddressSanitizer mostly makes the run-time instrumentation of Valgrind redundant. It is a little more tricky to set up, because running with uninstrumented libraries will lead into false positives. You will need an instrumented libc++, and you should use -stdlib=libc++ instead of the default libstdc++. To build the instrumented library, you can refer to https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo or you can adapt these steps that worked for me, for clang-8 version 8.0.1: cd /mariadb sudo apt source libc++-8-dev cd llvm-toolchain-8-8.0.1 mkdir libc++msan; cd libc++msan cmake ../libcxx -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_SANITIZER=Memory \ -DCMAKE_C_COMPILER=clang-8 -DCMAKE_CXX_COMPILER=clang++-8 Then, in your MariaDB build directory, you have to compile with libc++ and bundled libraries, such as WITH_SSL=bundled, WITH_ZLIB=bundled. For uninstrumented system libraries, you will get false positives for uninitialized values. Like this: cmake -DWITH_MSAN=ON -DWITH_SSL=bundled -DWITH_ZLIB=bundled \ -DCMAKE_CXX_FLAGS='-stdlib=libc++' .. Note: you should also add -O2 to the compiler options, or you may get crashes due to stack overflow. Finally, to run tests, you must replace libc++ with the instrumented one: LD_LIBRARY_PATH=/mariadb/llvm-toolchain-8-8.0.1/libc++msan/lib \ MSAN_OPTIONS=abort_on_error=1 \ ./mtr --big-test --parallel=auto --force --retry=0 Failure to do so will report numerous false positives related to operations on std::string and the like. This is work in progress. Some issues will still have to be fixed for WITH_MSAN to be usable. See MDEV-20377 for details. --- CMakeLists.txt | 6 +++++- cmake/plugin.cmake | 4 ++-- libmariadb | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75f9d22d747..0dcc2a75587 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2017, Oracle and/or its affiliates. -# Copyright (c) 2008, 2018, MariaDB Corporation +# Copyright (c) 2008, 2019, MariaDB Corporation. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -219,6 +219,10 @@ IF (WITH_UBSAN) MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=undefined -fno-sanitize=alignment -U_FORTIFY_SOURCE" DEBUG RELWITHDEBINFO) ENDIF() +OPTION(WITH_MSAN "Enable memory sanitizer" OFF) +IF (WITH_MSAN) + MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=memory -fsanitize-memory-track-origins -U_FORTIFY_SOURCE" DEBUG RELWITHDEBINFO) +ENDIF() # enable security hardening features, like most distributions do # in our benchmarks that costs about ~1% of performance, depending on the load diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 5b97d286139..68eb715eed9 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -1,5 +1,5 @@ # Copyright (c) 2009, 2018, Oracle and/or its affiliates. -# Copyright (c) 2011, 2018, MariaDB Corporation +# Copyright (c) 2011, 2019, MariaDB Corporation. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -209,7 +209,7 @@ MACRO(MYSQL_ADD_PLUGIN) ELSEIF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") TARGET_LINK_LIBRARIES (${target} mysqld) ENDIF() - ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT WITH_ASAN AND NOT WITH_UBSAN) + ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT WITH_ASAN AND NOT WITH_TSAN AND NOT WITH_UBSAN AND NOT WITH_MSAN) TARGET_LINK_LIBRARIES (${target} "-Wl,--no-undefined") ENDIF() diff --git a/libmariadb b/libmariadb index ed3a91c1391..dc271e5a1b9 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit ed3a91c139175746c5d6903d67ca902d91228f65 +Subproject commit dc271e5a1b9d4074e2086b776a668b6b5614f2bc From e746f451d57def4be679caafc29976741b3e89f7 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 15 Aug 2019 17:27:49 -0700 Subject: [PATCH 14/35] MDEV-20265 Unknown column in field list This patch corrects the fix of the patch for mdev-19421 that resolved the problem of parsing some embedded join expressions such as t1 join t2 left join t3 on t2.a=t3.a on t1.a=t2.a. Yet the patch contained a bug that prevented proper context analysis of the queries where such expressions were used together with comma separated table references in from clauses. --- mysql-test/r/join.result | 326 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/join.test | 59 +++++++ sql/sql_parse.cc | 103 +++++++++---- 3 files changed, 460 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 6b051acc108..cb2d00664e2 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -2921,5 +2921,331 @@ NULL NULL NULL 9 NULL NULL NULL 5 drop table t1,t2,t3,t4,s1,s2; # +# MDEV-20265: Mix of comma joins with JOIN expressions +# (correction of the fix for MDEV-19421) +# MDEV-20330: duplicate +# +create table t1 (a int); +insert into t1 values (7), (5), (3); +create table t2 (a int); +insert into t2 values (5), (1), (7); +create table t3 (a int); +insert into t3 values (2), (7), (3); +create table t4 (a int); +insert into t4 values (4), (7), (9), (5); +create table t5 (a int); +insert into t5 values (3), (7), (9), (2); +explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 left join t4 on t3.a=t4.a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a` from `test`.`t1` join `test`.`t2` join `test`.`t3` left join `test`.`t4` on((`test`.`t4`.`a` = `test`.`t3`.`a`)) where 1 +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 left join t4 on t3.a=t4.a; +t1_a t2_a t3_a t4_a +7 5 7 7 +5 5 7 7 +3 5 7 7 +7 1 7 7 +5 1 7 7 +3 1 7 7 +7 7 7 7 +5 7 7 7 +3 7 7 7 +7 5 2 NULL +5 5 2 NULL +3 5 2 NULL +7 1 2 NULL +5 1 2 NULL +3 1 2 NULL +7 7 2 NULL +5 7 2 NULL +3 7 2 NULL +7 5 3 NULL +5 5 3 NULL +3 5 3 NULL +7 1 3 NULL +5 1 3 NULL +3 1 3 NULL +7 7 3 NULL +5 7 3 NULL +3 7 3 NULL +explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 right join t4 on t3.a=t4.a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join) +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a` from `test`.`t1` join `test`.`t4` left join (`test`.`t2` join `test`.`t3`) on((`test`.`t3`.`a` = `test`.`t4`.`a`)) where 1 +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 right join t4 on t3.a=t4.a; +t1_a t2_a t3_a t4_a +7 5 7 7 +5 5 7 7 +3 5 7 7 +7 1 7 7 +5 1 7 7 +3 1 7 7 +7 7 7 7 +5 7 7 7 +3 7 7 7 +7 NULL NULL 4 +5 NULL NULL 4 +3 NULL NULL 4 +7 NULL NULL 9 +5 NULL NULL 9 +3 NULL NULL 9 +7 NULL NULL 5 +5 NULL NULL 5 +3 NULL NULL 5 +explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` join `test`.`t2` join `test`.`t3` join `test`.`t4` left join `test`.`t5` on((`test`.`t5`.`a` = `test`.`t4`.`a`)) where 1 +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a; +t1_a t2_a t3_a t4_a t5_a +7 5 2 7 7 +5 5 2 7 7 +3 5 2 7 7 +7 1 2 7 7 +5 1 2 7 7 +3 1 2 7 7 +7 7 2 7 7 +5 7 2 7 7 +3 7 2 7 7 +7 5 7 7 7 +5 5 7 7 7 +3 5 7 7 7 +7 1 7 7 7 +5 1 7 7 7 +3 1 7 7 7 +7 7 7 7 7 +5 7 7 7 7 +3 7 7 7 7 +7 5 3 7 7 +5 5 3 7 7 +3 5 3 7 7 +7 1 3 7 7 +5 1 3 7 7 +3 1 3 7 7 +7 7 3 7 7 +5 7 3 7 7 +3 7 3 7 7 +7 5 2 9 9 +5 5 2 9 9 +3 5 2 9 9 +7 1 2 9 9 +5 1 2 9 9 +3 1 2 9 9 +7 7 2 9 9 +5 7 2 9 9 +3 7 2 9 9 +7 5 7 9 9 +5 5 7 9 9 +3 5 7 9 9 +7 1 7 9 9 +5 1 7 9 9 +3 1 7 9 9 +7 7 7 9 9 +5 7 7 9 9 +3 7 7 9 9 +7 5 3 9 9 +5 5 3 9 9 +3 5 3 9 9 +7 1 3 9 9 +5 1 3 9 9 +3 1 3 9 9 +7 7 3 9 9 +5 7 3 9 9 +3 7 3 9 9 +7 5 2 4 NULL +5 5 2 4 NULL +3 5 2 4 NULL +7 1 2 4 NULL +5 1 2 4 NULL +3 1 2 4 NULL +7 7 2 4 NULL +5 7 2 4 NULL +3 7 2 4 NULL +7 5 7 4 NULL +5 5 7 4 NULL +3 5 7 4 NULL +7 1 7 4 NULL +5 1 7 4 NULL +3 1 7 4 NULL +7 7 7 4 NULL +5 7 7 4 NULL +3 7 7 4 NULL +7 5 3 4 NULL +5 5 3 4 NULL +3 5 3 4 NULL +7 1 3 4 NULL +5 1 3 4 NULL +3 1 3 4 NULL +7 7 3 4 NULL +5 7 3 4 NULL +3 7 3 4 NULL +7 5 2 5 NULL +5 5 2 5 NULL +3 5 2 5 NULL +7 1 2 5 NULL +5 1 2 5 NULL +3 1 2 5 NULL +7 7 2 5 NULL +5 7 2 5 NULL +3 7 2 5 NULL +7 5 7 5 NULL +5 5 7 5 NULL +3 5 7 5 NULL +7 1 7 5 NULL +5 1 7 5 NULL +3 1 7 5 NULL +7 7 7 5 NULL +5 7 7 5 NULL +3 7 7 5 NULL +7 5 3 5 NULL +5 5 3 5 NULL +3 5 3 5 NULL +7 1 3 5 NULL +5 1 3 5 NULL +3 1 3 5 NULL +7 7 3 5 NULL +5 7 3 5 NULL +3 7 3 5 NULL +explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join) +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` join `test`.`t5` left join (`test`.`t2` join `test`.`t3` join `test`.`t4`) on((`test`.`t4`.`a` = `test`.`t5`.`a`)) where 1 +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a; +t1_a t2_a t3_a t4_a t5_a +7 5 2 7 7 +5 5 2 7 7 +3 5 2 7 7 +7 1 2 7 7 +5 1 2 7 7 +3 1 2 7 7 +7 7 2 7 7 +5 7 2 7 7 +3 7 2 7 7 +7 5 7 7 7 +5 5 7 7 7 +3 5 7 7 7 +7 1 7 7 7 +5 1 7 7 7 +3 1 7 7 7 +7 7 7 7 7 +5 7 7 7 7 +3 7 7 7 7 +7 5 3 7 7 +5 5 3 7 7 +3 5 3 7 7 +7 1 3 7 7 +5 1 3 7 7 +3 1 3 7 7 +7 7 3 7 7 +5 7 3 7 7 +3 7 3 7 7 +7 5 2 9 9 +5 5 2 9 9 +3 5 2 9 9 +7 1 2 9 9 +5 1 2 9 9 +3 1 2 9 9 +7 7 2 9 9 +5 7 2 9 9 +3 7 2 9 9 +7 5 7 9 9 +5 5 7 9 9 +3 5 7 9 9 +7 1 7 9 9 +5 1 7 9 9 +3 1 7 9 9 +7 7 7 9 9 +5 7 7 9 9 +3 7 7 9 9 +7 5 3 9 9 +5 5 3 9 9 +3 5 3 9 9 +7 1 3 9 9 +5 1 3 9 9 +3 1 3 9 9 +7 7 3 9 9 +5 7 3 9 9 +3 7 3 9 9 +7 NULL NULL NULL 3 +5 NULL NULL NULL 3 +3 NULL NULL NULL 3 +7 NULL NULL NULL 2 +5 NULL NULL NULL 2 +3 NULL NULL NULL 2 +explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join) +1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` left join `test`.`t2` on((`test`.`t2`.`a` = `test`.`t1`.`a`)) join `test`.`t5` left join (`test`.`t3` join `test`.`t4`) on((`test`.`t4`.`a` = `test`.`t5`.`a`)) where 1 +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a; +t1_a t2_a t3_a t4_a t5_a +5 5 2 7 7 +7 7 2 7 7 +3 NULL 2 7 7 +5 5 7 7 7 +7 7 7 7 7 +3 NULL 7 7 7 +5 5 3 7 7 +7 7 3 7 7 +3 NULL 3 7 7 +5 5 2 9 9 +7 7 2 9 9 +3 NULL 2 9 9 +5 5 7 9 9 +7 7 7 9 9 +3 NULL 7 9 9 +5 5 3 9 9 +7 7 3 9 9 +3 NULL 3 9 9 +5 5 NULL NULL 3 +7 7 NULL NULL 3 +3 NULL NULL NULL 3 +5 5 NULL NULL 2 +7 7 NULL NULL 2 +3 NULL NULL NULL 2 +drop table t1,t2,t3,t4,t5; +select a.a +from (select 1 as a) a, +(select 2 as b) b +cross join +(select 3 as c) c +left join +(select 4 as d) d +on 1; +a +1 +# # End of MariaDB 5.5 tests # diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 168cfe4e477..c24fe3bf577 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -1613,6 +1613,65 @@ eval $q; drop table t1,t2,t3,t4,s1,s2; +--echo # +--echo # MDEV-20265: Mix of comma joins with JOIN expressions +--echo # (correction of the fix for MDEV-19421) +--echo # MDEV-20330: duplicate +--echo # + +create table t1 (a int); +insert into t1 values (7), (5), (3); +create table t2 (a int); +insert into t2 values (5), (1), (7); +create table t3 (a int); +insert into t3 values (2), (7), (3); +create table t4 (a int); +insert into t4 values (4), (7), (9), (5); +create table t5 (a int); +insert into t5 values (3), (7), (9), (2); + + +let $q= +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 left join t4 on t3.a=t4.a; +eval explain extended $q; +eval $q; + +let $q= +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a +from t1, t2 join t3 right join t4 on t3.a=t4.a; +eval explain extended $q; +eval $q; + +let $q= +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a; +eval explain extended $q; +eval $q; + +let $q= +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a; +eval explain extended $q; +eval $q; + +let $q= +select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a +from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a; +eval explain extended $q; +eval $q; + +drop table t1,t2,t3,t4,t5; + +select a.a +from (select 1 as a) a, + (select 2 as b) b + cross join + (select 3 as c) c + left join + (select 4 as d) d + on 1; + --echo # --echo # End of MariaDB 5.5 tests --echo # diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 346f8ad5e8b..ae5a6b4cd35 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6435,10 +6435,6 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) TABLE_LIST *head= join_list->head(); if (head->nested_join && head->nested_join->nest_type & REBALANCED_NEST) { - List_iterator li(*join_list); - li++; - while (li++) - li.remove(); DBUG_RETURN(head); } @@ -6522,13 +6518,13 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) context and right-associative in another context. In this query - SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a (Q1) + SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a (Q1) JOIN is left-associative and the query Q1 is interpreted as - SELECT * FROM (t1 JOIN t2) LEFT JOIN t3 ON t2.a=t3.a. + SELECT * FROM (t1 JOIN t2) LEFT JOIN t3 ON t2.a=t3.a. While in this query - SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.b=t2.b (Q2) + SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.b=t2.b (Q2) JOIN is right-associative and the query Q2 is interpreted as - SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.b=t2.b + SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.b=t2.b JOIN is right-associative if it is used with ON clause or with USING clause. Otherwise it is left-associative. @@ -6574,9 +6570,9 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) J LJ - ON / \ / \ - t1 LJ - ON (TQ3*) => J t2 - / \ / \ - t3 t2 t1 t3 + t1 LJ - ON (TQ3*) => t3 J + / \ / \ + t3 t2 t1 t2 With several left associative JOINs SELECT * FROM t1 JOIN t2 JOIN t3 LEFT JOIN t4 ON t3.a=t4.a (Q4) @@ -6584,15 +6580,15 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) J1 LJ - ON / \ / \ - t1 LJ - ON J2 t4 + t1 J2 J2 t4 / \ => / \ - J2 t4 J1 t3 - / \ / \ - t2 t3 t1 t2 + t2 LJ - ON J1 t3 + / \ / \ + t3 t4 t1 t2 - Here's another example: - SELECT * - FROM t1 JOIN t2 LEFT JOIN t3 JOIN t4 ON t3.a=t4.a ON t2.b=t3.b (Q5) + Here's another example: + SELECT * + FROM t1 JOIN t2 LEFT JOIN t3 JOIN t4 ON t3.a=t4.a ON t2.b=t3.b (Q5) J LJ - ON / \ / \ @@ -6602,15 +6598,58 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) / \ t3 t4 - If the transformed nested join node node is a natural join node like in - the following query - SELECT * FROM t1 JOIN t2 LEFT JOIN t3 USING(a) (Q6) - the transformation additionally has to take care about setting proper - references in the field natural_join for both operands of the natural - join operation. - The function also has to change the name resolution context for ON - expressions used in the transformed join expression to take into - account the tables of the left_op node. + If the transformed nested join node node is a natural join node like in + the following query + SELECT * FROM t1 JOIN t2 LEFT JOIN t3 USING(a) (Q6) + the transformation additionally has to take care about setting proper + references in the field natural_join for both operands of the natural + join operation. + + The queries that combine comma syntax for join operation with + JOIN expression require a special care. Consider the query + SELECT * FROM t1, t2 JOIN t3 LEFT JOIN t4 ON t3.a=t4.a (Q7) + This query is equivalent to the query + SELECT * FROM (t1, t2) JOIN t3 LEFT JOIN t4 ON t3.a=t4.a + The latter is transformed in the same way as query Q1 + + J LJ - ON + / \ / \ + (t1,t2) LJ - ON => J t4 + / \ / \ + t3 t4 (t1,t2) t3 + + A transformation similar to the transformation for Q3 is done for + the following query with RIGHT JOIN + SELECT * FROM t1, t2 JOIN t3 RIGHT JOIN t4 ON t3.a=t4.a (Q8) + + J LJ - ON + / \ / \ + t3 LJ - ON => t4 J + / \ / \ + t4 (t1,t2) (t1,t2) t3 + + The function also has to change the name resolution context for ON + expressions used in the transformed join expression to take into + account the tables of the left_op node. + + TODO: + A more elegant solution would be to implement the transformation that + eliminates nests for cross join operations. For Q7 it would work like this: + + J LJ - ON + / \ / \ + (t1,t2) LJ - ON => (t1,t2,t3) t4 + / \ + t3 t4 + + For Q8 with RIGHT JOIN the transformation would work similarly: + + J LJ - ON + / \ / \ + t3 LJ - ON => t4 (t1,t2,t3) + / \ + t4 (t1,t2) + */ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op, @@ -6633,7 +6672,11 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op, } TABLE_LIST *tbl; - List *jl= &right_op->nested_join->join_list; + List *right_op_jl= right_op->join_list; + TABLE_LIST *r_tbl= right_op_jl->pop(); + DBUG_ASSERT(right_op == r_tbl); + TABLE_LIST *l_tbl= right_op_jl->pop(); + DBUG_ASSERT(left_op == l_tbl); TABLE_LIST *cj_nest; /* @@ -6650,6 +6693,8 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op, List *cjl= &cj_nest->nested_join->join_list; cjl->empty(); + List *jl= &right_op->nested_join->join_list; + DBUG_ASSERT(jl->elements == 2); /* Look for the left most node tbl of the right_op tree */ for ( ; ; ) { @@ -6721,6 +6766,8 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op, create a new top level nested join node. */ right_op->nested_join->nest_type|= REBALANCED_NEST; + if (unlikely(right_op_jl->push_front(right_op))) + DBUG_RETURN(true); DBUG_RETURN(false); } From 457dc9d64d9f044760adbeca6facc813b754d43b Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 30 Jul 2019 13:45:13 +0200 Subject: [PATCH 15/35] MDEV-18863: Galera SST scripts can't read [mysqldN] option groups Some users and some scripts (for example, mysqld_multi.sh) use special option groups with names like [mysqld1], [mysqld2], ..., [mysqldN]. But SST scripts can't currently fully support these option groups. The only option group-related value it gets from the server is --defaults-group-suffix, if that option was set for mysqld when the server was started. However, the SST scripts does not get told by the server to read these option groups, so this means that the SST script will fail to read options like innodb-data-home-dir when it is in a option group like [mysqld1]...[mysqldN]. Moreover, SST scripts ignore many parameters that can be passed to them explicitly and cannot transfer them further, for example, to the input of mariabackup utility. Ideally, we want to transfer all the parameters of the original mysqld call to utilities such as mariabackup, however the SST script does not receive these parameters from the server and therefore cannot transfer them to mariabackup. To correct these shortcomings, we need to transfer to the scripts all of the parameters of the original mysqld call, and in the SST scripts themselves provide for the transfer all of these parameters to utilities such as mariabackup. To prevent these parameters from mixing with the script's own parameters, they should be transferred to SST script after the special option "--mysqld-args", followed by the string argument with the original parameters, as it received by the mysqld call at the time of launch (further all these parameters will be passed to mariabackup, for example). In addition, the SST scripts themselves must be refined so that they can read the parameters from the user-selected group, not just from the global mysqld configuration group. And also so that they can receive the parameters (which important for their work) as command-line arguments. --- scripts/mysqld_multi.sh | 14 +++++- scripts/wsrep_sst_common.sh | 58 +++++++++++++++++++++ scripts/wsrep_sst_mariabackup.sh | 38 +++++++++++--- scripts/wsrep_sst_rsync.sh | 10 ++++ sql/wsrep_sst.cc | 86 +++++++++++++++++++++++++++++--- sql/wsrep_sst.h | 1 + 6 files changed, 192 insertions(+), 15 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 64fa76f0e97..0bd50c1974f 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -308,7 +308,9 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); + my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $suffix_found, $info_sent); + + $suffix_found= 0; if (!$opt_no_log) { @@ -347,6 +349,10 @@ sub start_mysqlds() $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } + elseif ("--defaults-group-suffix=" eq substr($options[$j], 0, 24)) + { + $suffix_found= 1; + } else { $options[$j]= quote_shell_word($options[$j]); @@ -364,6 +370,12 @@ sub start_mysqlds() } $com.= $tmp; + if (!$suffix_found) + { + $com.= " --defaults-group-suffix="; + $com.= $groups[$i]; + } + if ($opt_wsrep_new_cluster) { $com.= " --wsrep-new-cluster"; } diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 3b8cce9c467..73a026b4edc 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -28,7 +28,12 @@ WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" WSREP_SST_OPT_SUFFIX_DEFAULT="" +WSREP_SST_OPT_SUFFIX_VALUE="" +WSREP_SST_OPT_MYSQLD="" INNODB_DATA_HOME_DIR_ARG="" +INNODB_LOG_GROUP_HOME_ARG="" +INNODB_UNDO_DIR_ARG="" +LOG_BIN_ARG="" while [ $# -gt 0 ]; do case "$1" in @@ -83,6 +88,18 @@ case "$1" in readonly INNODB_DATA_HOME_DIR_ARG="$2" shift ;; + '--innodb-log-group-home-dir') + readonly INNODB_LOG_GROUP_HOME_ARG="$2" + shift + ;; + '--innodb-undo-directory') + readonly INNODB_UNDO_DIR_ARG="$2" + shift + ;; + '--log-bin') + readonly LOG_BIN_ARG="$2" + shift + ;; '--defaults-file') readonly WSREP_SST_OPT_DEFAULT="$1=$2" shift @@ -93,6 +110,7 @@ case "$1" in ;; '--defaults-group-suffix') readonly WSREP_SST_OPT_SUFFIX_DEFAULT="$1=$2" + readonly WSREP_SST_OPT_SUFFIX_VALUE="$2" shift ;; '--host') @@ -143,6 +161,46 @@ case "$1" in readonly WSREP_SST_OPT_GTID_DOMAIN_ID="$2" shift ;; + '--mysqld-args') + original_cmd="" + shift + while [ $# -gt 0 ]; do + option=${1%%=*} + if [ "$option" != "--defaults-file" ]; then + value=${1#*=} + case "$option" in + '--innodb-data-home-dir') + if [ -z "$INNODB_DATA_HOME_DIR_ARG" ]; then + readonly INNODB_DATA_HOME_DIR_ARG="$value" + fi + ;; + '--innodb-log-group-home-dir') + if [ -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then + readonly INNODB_LOG_GROUP_HOME_ARG="$value" + fi + ;; + '--innodb-undo-directory') + if [ -z "$INNODB_UNDO_DIR_ARG" ]; then + readonly INNODB_UNDO_DIR_ARG="$value" + fi + ;; + '--log-bin') + if [ -z "$LOG_BIN_ARG" ]; then + readonly LOG_BIN_ARG="$value" + fi + ;; + esac + if [ -z "$original_cmd" ]; then + original_cmd="$1" + else + original_cmd+=" $1" + fi + fi + shift + done + readonly WSREP_SST_OPT_MYSQLD="$original_cmd" + break + ;; *) # must be command # usage # exit 1 diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 45a7f32d1ac..ba04c358faa 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -699,8 +699,7 @@ if [[ ${FORCE_FTWRL:-0} -eq 1 ]];then iopts+=" --no-backup-locks " fi - -INNOEXTRA="" +INNOEXTRA=$WSREP_SST_OPT_MYSQLD INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} # Try to set INNODB_DATA_HOME_DIR from the command line: @@ -708,6 +707,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi @@ -828,7 +830,9 @@ then exit 93 fi - if [[ -z $(parse_cnf --mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then + if [[ -z $(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE tmpdir "") && \ + -z $(parse_cnf --mysqld tmpdir "") && \ + -z $(parse_cnf xtrabackup tmpdir "") ]]; then xtmpdir=$(mktemp -d) tmpopts=" --tmpdir=$xtmpdir " wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" @@ -951,8 +955,24 @@ then [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE ib_home_dir=$INNODB_DATA_HOME_DIR - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") - ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + + # Try to set ib_log_dir from the command line: + ib_log_dir=$INNODB_LOG_GROUP_HOME_ARG + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir "") + fi + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + fi + + # Try to set ib_undo_dir from the command line: + ib_undo_dir=$INNODB_UNDO_DIR_ARG + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-undo-directory "") + fi + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + fi stagemsg="Joiner-Recv" @@ -1029,7 +1049,13 @@ then find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ fi - tempdir=$(parse_cnf --mysqld log-bin "") + tempdir=$LOG_BIN_ARG + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE log-bin "") + fi + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf --mysqld log-bin "") + fi if [[ -n ${tempdir:-} ]];then binlog_dir=$(dirname $tempdir) binlog_file=$(basename $tempdir) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 0e3ef0c923c..068e92c0486 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -116,7 +116,14 @@ then fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} +# Try to set WSREP_LOG_DIR from the command line: +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG +fi # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') +fi if [ -z "$WSREP_LOG_DIR" ]; then WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') fi @@ -135,6 +142,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 033992b7bd8..c470133d1b9 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -592,17 +592,76 @@ static int sst_append_data_dir(wsp::env& env, const char* data_dir) return -env.error(); } +static size_t estimate_cmd_len (bool* extra_args) +{ + /* + The length of the area reserved for the control parameters + of the SST script (excluding the copying of the original + mysqld arguments): + */ + size_t cmd_len= 4096; + bool extra= false; + /* + If mysqld was started with arguments, add them all: + */ + if (orig_argc > 1) + { + for (int i = 1; i < orig_argc; i++) + { + cmd_len += strlen(orig_argv[i]); + } + extra = true; + cmd_len += strlen(WSREP_SST_OPT_MYSQLD); + /* + Add the separating spaces between arguments, + and one additional space before "--mysqld-args": + */ + cmd_len += orig_argc; + } + *extra_args= extra; + return cmd_len; +} + +static void copy_orig_argv (char* cmd_str) +{ + /* + If mysqld was started with arguments, copy them all: + */ + if (orig_argc > 1) + { + size_t n = strlen(WSREP_SST_OPT_MYSQLD); + *cmd_str++ = ' '; + memcpy(cmd_str, WSREP_SST_OPT_MYSQLD, n * sizeof(char)); + cmd_str += n; + for (int i = 1; i < orig_argc; i++) + { + char* arg= orig_argv[i]; + *cmd_str++ = ' '; + n = strlen(arg); + memcpy(cmd_str, arg, n * sizeof(char)); + cmd_str += n; + } + /* + Add a terminating null character (not counted in the length, + since we've overwritten the original null character which + was previously added by snprintf: + */ + *cmd_str = 0; + } +} + static ssize_t sst_prepare_other (const char* method, const char* sst_auth, const char* addr_in, const char** addr_out) { - int const cmd_len= 4096; + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); wsp::string cmd_str(cmd_len); if (!cmd_str()) { - WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %d bytes", + WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -653,6 +712,9 @@ static ssize_t sst_prepare_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + wsp::env env(NULL); if (env.error()) { @@ -916,13 +978,14 @@ static int sst_donate_mysqldump (const char* addr, } memcpy(host, address.get_address(), address.get_address_len()); int port= address.get_port(); - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_mysqldump(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -951,6 +1014,9 @@ static int sst_donate_mysqldump (const char* addr, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + WSREP_DEBUG("Running: '%s'", cmd_str()); ret= sst_run_shell (cmd_str(), env, 3); @@ -1270,13 +1336,14 @@ static int sst_donate_other (const char* method, bool bypass, char** env) // carries auth info { - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_other(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -1317,6 +1384,9 @@ static int sst_donate_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); pthread_t tmp; diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 829a567f2cf..18e159a7729 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -32,6 +32,7 @@ #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" #define WSREP_SST_OPT_BINLOG_INDEX "--binlog-index" +#define WSREP_SST_OPT_MYSQLD "--mysqld-args" // mysqldump-specific options #define WSREP_SST_OPT_USER "--user" From ff6d3075d5e66b3248b37379b44c6c6abf1ef0c3 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 30 Jul 2019 13:45:13 +0200 Subject: [PATCH 16/35] MDEV-18863: Galera SST scripts can't read [mysqldN] option groups Some users and some scripts (for example, mysqld_multi.sh) use special option groups with names like [mysqld1], [mysqld2], ..., [mysqldN]. But SST scripts can't currently fully support these option groups. The only option group-related value it gets from the server is --defaults-group-suffix, if that option was set for mysqld when the server was started. However, the SST scripts does not get told by the server to read these option groups, so this means that the SST script will fail to read options like innodb-data-home-dir when it is in a option group like [mysqld1]...[mysqldN]. Moreover, SST scripts ignore many parameters that can be passed to them explicitly and cannot transfer them further, for example, to the input of mariabackup utility. Ideally, we want to transfer all the parameters of the original mysqld call to utilities such as mariabackup, however the SST script does not receive these parameters from the server and therefore cannot transfer them to mariabackup. To correct these shortcomings, we need to transfer to the scripts all of the parameters of the original mysqld call, and in the SST scripts themselves provide for the transfer all of these parameters to utilities such as mariabackup. To prevent these parameters from mixing with the script's own parameters, they should be transferred to SST script after the special option "--mysqld-args", followed by the string argument with the original parameters, as it received by the mysqld call at the time of launch (further all these parameters will be passed to mariabackup, for example). In addition, the SST scripts themselves must be refined so that they can read the parameters from the user-selected group, not just from the global mysqld configuration group. And also so that they can receive the parameters (which important for their work) as command-line arguments. --- scripts/mysqld_multi.sh | 14 +++++- scripts/wsrep_sst_common.sh | 58 +++++++++++++++++++++ scripts/wsrep_sst_mariabackup.sh | 38 +++++++++++--- scripts/wsrep_sst_rsync.sh | 10 ++++ sql/wsrep_sst.cc | 86 +++++++++++++++++++++++++++++--- sql/wsrep_sst.h | 1 + 6 files changed, 192 insertions(+), 15 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 7add8541d7a..b8730e2624a 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -308,7 +308,9 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); + my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $suffix_found, $info_sent); + + $suffix_found= 0; if (!$opt_no_log) { @@ -347,6 +349,10 @@ sub start_mysqlds() $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } + elseif ("--defaults-group-suffix=" eq substr($options[$j], 0, 24)) + { + $suffix_found= 1; + } else { $options[$j]= quote_shell_word($options[$j]); @@ -364,6 +370,12 @@ sub start_mysqlds() } $com.= $tmp; + if (!$suffix_found) + { + $com.= " --defaults-group-suffix="; + $com.= $groups[$i]; + } + if ($opt_wsrep_new_cluster) { $com.= " --wsrep-new-cluster"; } diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 76bdfb5353f..b27261cf4b4 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -28,7 +28,12 @@ WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" WSREP_SST_OPT_SUFFIX_DEFAULT="" +WSREP_SST_OPT_SUFFIX_VALUE="" +WSREP_SST_OPT_MYSQLD="" INNODB_DATA_HOME_DIR_ARG="" +INNODB_LOG_GROUP_HOME_ARG="" +INNODB_UNDO_DIR_ARG="" +LOG_BIN_ARG="" while [ $# -gt 0 ]; do case "$1" in @@ -83,6 +88,18 @@ case "$1" in readonly INNODB_DATA_HOME_DIR_ARG="$2" shift ;; + '--innodb-log-group-home-dir') + readonly INNODB_LOG_GROUP_HOME_ARG="$2" + shift + ;; + '--innodb-undo-directory') + readonly INNODB_UNDO_DIR_ARG="$2" + shift + ;; + '--log-bin') + readonly LOG_BIN_ARG="$2" + shift + ;; '--defaults-file') readonly WSREP_SST_OPT_DEFAULT="$1=$2" shift @@ -93,6 +110,7 @@ case "$1" in ;; '--defaults-group-suffix') readonly WSREP_SST_OPT_SUFFIX_DEFAULT="$1=$2" + readonly WSREP_SST_OPT_SUFFIX_VALUE="$2" shift ;; '--host') @@ -143,6 +161,46 @@ case "$1" in readonly WSREP_SST_OPT_GTID_DOMAIN_ID="$2" shift ;; + '--mysqld-args') + original_cmd="" + shift + while [ $# -gt 0 ]; do + option=${1%%=*} + if [ "$option" != "--defaults-file" ]; then + value=${1#*=} + case "$option" in + '--innodb-data-home-dir') + if [ -z "$INNODB_DATA_HOME_DIR_ARG" ]; then + readonly INNODB_DATA_HOME_DIR_ARG="$value" + fi + ;; + '--innodb-log-group-home-dir') + if [ -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then + readonly INNODB_LOG_GROUP_HOME_ARG="$value" + fi + ;; + '--innodb-undo-directory') + if [ -z "$INNODB_UNDO_DIR_ARG" ]; then + readonly INNODB_UNDO_DIR_ARG="$value" + fi + ;; + '--log-bin') + if [ -z "$LOG_BIN_ARG" ]; then + readonly LOG_BIN_ARG="$value" + fi + ;; + esac + if [ -z "$original_cmd" ]; then + original_cmd="$1" + else + original_cmd+=" $1" + fi + fi + shift + done + readonly WSREP_SST_OPT_MYSQLD="$original_cmd" + break + ;; *) # must be command # usage # exit 1 diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 5d07380abf5..abcfa0aea35 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -698,8 +698,7 @@ if [[ ${FORCE_FTWRL:-0} -eq 1 ]];then iopts+=" --no-backup-locks " fi - -INNOEXTRA="" +INNOEXTRA=$WSREP_SST_OPT_MYSQLD INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} # Try to set INNODB_DATA_HOME_DIR from the command line: @@ -707,6 +706,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi @@ -827,7 +829,9 @@ then exit 93 fi - if [[ -z $(parse_cnf --mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then + if [[ -z $(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE tmpdir "") && \ + -z $(parse_cnf --mysqld tmpdir "") && \ + -z $(parse_cnf xtrabackup tmpdir "") ]]; then xtmpdir=$(mktemp -d) tmpopts=" --tmpdir=$xtmpdir " wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" @@ -950,8 +954,24 @@ then [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE ib_home_dir=$INNODB_DATA_HOME_DIR - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") - ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + + # Try to set ib_log_dir from the command line: + ib_log_dir=$INNODB_LOG_GROUP_HOME_ARG + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir "") + fi + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + fi + + # Try to set ib_undo_dir from the command line: + ib_undo_dir=$INNODB_UNDO_DIR_ARG + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-undo-directory "") + fi + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + fi stagemsg="Joiner-Recv" @@ -1028,7 +1048,13 @@ then find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ fi - tempdir=$(parse_cnf --mysqld log-bin "") + tempdir=$LOG_BIN_ARG + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE log-bin "") + fi + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf --mysqld log-bin "") + fi if [[ -n ${tempdir:-} ]];then binlog_dir=$(dirname $tempdir) binlog_file=$(basename $tempdir) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 0a463513e3f..2bb48f0ffd0 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -149,7 +149,14 @@ then fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} +# Try to set WSREP_LOG_DIR from the command line: +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG +fi # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') +fi if [ -z "$WSREP_LOG_DIR" ]; then WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') fi @@ -168,6 +175,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index cb8b1cab225..fe9f5650b4f 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -648,17 +648,76 @@ static int sst_append_data_dir(wsp::env& env, const char* data_dir) return -env.error(); } +static size_t estimate_cmd_len (bool* extra_args) +{ + /* + The length of the area reserved for the control parameters + of the SST script (excluding the copying of the original + mysqld arguments): + */ + size_t cmd_len= 4096; + bool extra= false; + /* + If mysqld was started with arguments, add them all: + */ + if (orig_argc > 1) + { + for (int i = 1; i < orig_argc; i++) + { + cmd_len += strlen(orig_argv[i]); + } + extra = true; + cmd_len += strlen(WSREP_SST_OPT_MYSQLD); + /* + Add the separating spaces between arguments, + and one additional space before "--mysqld-args": + */ + cmd_len += orig_argc; + } + *extra_args= extra; + return cmd_len; +} + +static void copy_orig_argv (char* cmd_str) +{ + /* + If mysqld was started with arguments, copy them all: + */ + if (orig_argc > 1) + { + size_t n = strlen(WSREP_SST_OPT_MYSQLD); + *cmd_str++ = ' '; + memcpy(cmd_str, WSREP_SST_OPT_MYSQLD, n * sizeof(char)); + cmd_str += n; + for (int i = 1; i < orig_argc; i++) + { + char* arg= orig_argv[i]; + *cmd_str++ = ' '; + n = strlen(arg); + memcpy(cmd_str, arg, n * sizeof(char)); + cmd_str += n; + } + /* + Add a terminating null character (not counted in the length, + since we've overwritten the original null character which + was previously added by snprintf: + */ + *cmd_str = 0; + } +} + static ssize_t sst_prepare_other (const char* method, const char* sst_auth, const char* addr_in, const char** addr_out) { - int const cmd_len= 4096; + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); wsp::string cmd_str(cmd_len); if (!cmd_str()) { - WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %d bytes", + WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -709,6 +768,9 @@ static ssize_t sst_prepare_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + wsp::env env(NULL); if (env.error()) { @@ -972,13 +1034,14 @@ static int sst_donate_mysqldump (const char* addr, } memcpy(host, address.get_address(), address.get_address_len()); int port= address.get_port(); - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_mysqldump(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -1007,6 +1070,9 @@ static int sst_donate_mysqldump (const char* addr, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + WSREP_DEBUG("Running: '%s'", cmd_str()); ret= sst_run_shell (cmd_str(), env, 3); @@ -1326,13 +1392,14 @@ static int sst_donate_other (const char* method, bool bypass, char** env) // carries auth info { - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_other(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -1373,6 +1440,9 @@ static int sst_donate_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); pthread_t tmp; diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index e54cc25a456..063cab5f0f1 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -32,6 +32,7 @@ #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" #define WSREP_SST_OPT_BINLOG_INDEX "--binlog-index" +#define WSREP_SST_OPT_MYSQLD "--mysqld-args" // mysqldump-specific options #define WSREP_SST_OPT_USER "--user" From 137d8ed3fee14335bd707474bd49f4e43b3bf309 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 30 Jul 2019 13:45:13 +0200 Subject: [PATCH 17/35] MDEV-18863: Galera SST scripts can't read [mysqldN] option groups Some users and some scripts (for example, mysqld_multi.sh) use special option groups with names like [mysqld1], [mysqld2], ..., [mysqldN]. But SST scripts can't currently fully support these option groups. The only option group-related value it gets from the server is --defaults-group-suffix, if that option was set for mysqld when the server was started. However, the SST scripts does not get told by the server to read these option groups, so this means that the SST script will fail to read options like innodb-data-home-dir when it is in a option group like [mysqld1]...[mysqldN]. Moreover, SST scripts ignore many parameters that can be passed to them explicitly and cannot transfer them further, for example, to the input of mariabackup utility. Ideally, we want to transfer all the parameters of the original mysqld call to utilities such as mariabackup, however the SST script does not receive these parameters from the server and therefore cannot transfer them to mariabackup. To correct these shortcomings, we need to transfer to the scripts all of the parameters of the original mysqld call, and in the SST scripts themselves provide for the transfer all of these parameters to utilities such as mariabackup. To prevent these parameters from mixing with the script's own parameters, they should be transferred to SST script after the special option "--mysqld-args", followed by the string argument with the original parameters, as it received by the mysqld call at the time of launch (further all these parameters will be passed to mariabackup, for example). In addition, the SST scripts themselves must be refined so that they can read the parameters from the user-selected group, not just from the global mysqld configuration group. And also so that they can receive the parameters (which important for their work) as command-line arguments. --- scripts/mysqld_multi.sh | 14 +++++- scripts/wsrep_sst_common.sh | 58 +++++++++++++++++++++ scripts/wsrep_sst_mariabackup.sh | 38 +++++++++++--- scripts/wsrep_sst_rsync.sh | 10 ++++ sql/wsrep_sst.cc | 86 +++++++++++++++++++++++++++++--- sql/wsrep_sst.h | 1 + 6 files changed, 192 insertions(+), 15 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 7add8541d7a..b8730e2624a 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -308,7 +308,9 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); + my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $suffix_found, $info_sent); + + $suffix_found= 0; if (!$opt_no_log) { @@ -347,6 +349,10 @@ sub start_mysqlds() $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } + elseif ("--defaults-group-suffix=" eq substr($options[$j], 0, 24)) + { + $suffix_found= 1; + } else { $options[$j]= quote_shell_word($options[$j]); @@ -364,6 +370,12 @@ sub start_mysqlds() } $com.= $tmp; + if (!$suffix_found) + { + $com.= " --defaults-group-suffix="; + $com.= $groups[$i]; + } + if ($opt_wsrep_new_cluster) { $com.= " --wsrep-new-cluster"; } diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 41c6f3370f8..b1b586868df 100755 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -28,7 +28,12 @@ WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" WSREP_SST_OPT_SUFFIX_DEFAULT="" +WSREP_SST_OPT_SUFFIX_VALUE="" +WSREP_SST_OPT_MYSQLD="" INNODB_DATA_HOME_DIR_ARG="" +INNODB_LOG_GROUP_HOME_ARG="" +INNODB_UNDO_DIR_ARG="" +LOG_BIN_ARG="" while [ $# -gt 0 ]; do case "$1" in @@ -83,6 +88,18 @@ case "$1" in readonly INNODB_DATA_HOME_DIR_ARG="$2" shift ;; + '--innodb-log-group-home-dir') + readonly INNODB_LOG_GROUP_HOME_ARG="$2" + shift + ;; + '--innodb-undo-directory') + readonly INNODB_UNDO_DIR_ARG="$2" + shift + ;; + '--log-bin') + readonly LOG_BIN_ARG="$2" + shift + ;; '--defaults-file') readonly WSREP_SST_OPT_DEFAULT="$1=$2" shift @@ -93,6 +110,7 @@ case "$1" in ;; '--defaults-group-suffix') readonly WSREP_SST_OPT_SUFFIX_DEFAULT="$1=$2" + readonly WSREP_SST_OPT_SUFFIX_VALUE="$2" shift ;; '--host') @@ -143,6 +161,46 @@ case "$1" in readonly WSREP_SST_OPT_GTID_DOMAIN_ID="$2" shift ;; + '--mysqld-args') + original_cmd="" + shift + while [ $# -gt 0 ]; do + option=${1%%=*} + if [ "$option" != "--defaults-file" ]; then + value=${1#*=} + case "$option" in + '--innodb-data-home-dir') + if [ -z "$INNODB_DATA_HOME_DIR_ARG" ]; then + readonly INNODB_DATA_HOME_DIR_ARG="$value" + fi + ;; + '--innodb-log-group-home-dir') + if [ -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then + readonly INNODB_LOG_GROUP_HOME_ARG="$value" + fi + ;; + '--innodb-undo-directory') + if [ -z "$INNODB_UNDO_DIR_ARG" ]; then + readonly INNODB_UNDO_DIR_ARG="$value" + fi + ;; + '--log-bin') + if [ -z "$LOG_BIN_ARG" ]; then + readonly LOG_BIN_ARG="$value" + fi + ;; + esac + if [ -z "$original_cmd" ]; then + original_cmd="$1" + else + original_cmd+=" $1" + fi + fi + shift + done + readonly WSREP_SST_OPT_MYSQLD="$original_cmd" + break + ;; *) # must be command # usage # exit 1 diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 6c3206a03e1..8e7b742d9ee 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -697,8 +697,7 @@ if [[ ${FORCE_FTWRL:-0} -eq 1 ]];then iopts+=" --no-backup-locks " fi - -INNOEXTRA="" +INNOEXTRA=$WSREP_SST_OPT_MYSQLD INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} # Try to set INNODB_DATA_HOME_DIR from the command line: @@ -706,6 +705,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi @@ -826,7 +828,9 @@ then exit 93 fi - if [[ -z $(parse_cnf --mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then + if [[ -z $(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE tmpdir "") && \ + -z $(parse_cnf --mysqld tmpdir "") && \ + -z $(parse_cnf xtrabackup tmpdir "") ]]; then xtmpdir=$(mktemp -d) tmpopts=" --tmpdir=$xtmpdir " wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" @@ -949,8 +953,24 @@ then [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE ib_home_dir=$INNODB_DATA_HOME_DIR - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") - ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + + # Try to set ib_log_dir from the command line: + ib_log_dir=$INNODB_LOG_GROUP_HOME_ARG + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir "") + fi + if [ -z "$ib_log_dir" ]; then + ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + fi + + # Try to set ib_undo_dir from the command line: + ib_undo_dir=$INNODB_UNDO_DIR_ARG + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-undo-directory "") + fi + if [ -z "$ib_undo_dir" ]; then + ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") + fi stagemsg="Joiner-Recv" @@ -1027,7 +1047,13 @@ then find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ fi - tempdir=$(parse_cnf --mysqld log-bin "") + tempdir=$LOG_BIN_ARG + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE log-bin "") + fi + if [ -z "$tempdir" ]; then + tempdir=$(parse_cnf --mysqld log-bin "") + fi if [[ -n ${tempdir:-} ]];then binlog_dir=$(dirname $tempdir) binlog_file=$(basename $tempdir) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 5109b9e87db..3bd2af1ad5c 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -150,7 +150,14 @@ then fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} +# Try to set WSREP_LOG_DIR from the command line: +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG +fi # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') +fi if [ -z "$WSREP_LOG_DIR" ]; then WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') fi @@ -169,6 +176,9 @@ if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi # if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir '') fi diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 5c3e5642cda..bda79ed7406 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -642,17 +642,76 @@ static int sst_append_data_dir(wsp::env& env, const char* data_dir) return -env.error(); } +static size_t estimate_cmd_len (bool* extra_args) +{ + /* + The length of the area reserved for the control parameters + of the SST script (excluding the copying of the original + mysqld arguments): + */ + size_t cmd_len= 4096; + bool extra= false; + /* + If mysqld was started with arguments, add them all: + */ + if (orig_argc > 1) + { + for (int i = 1; i < orig_argc; i++) + { + cmd_len += strlen(orig_argv[i]); + } + extra = true; + cmd_len += strlen(WSREP_SST_OPT_MYSQLD); + /* + Add the separating spaces between arguments, + and one additional space before "--mysqld-args": + */ + cmd_len += orig_argc; + } + *extra_args= extra; + return cmd_len; +} + +static void copy_orig_argv (char* cmd_str) +{ + /* + If mysqld was started with arguments, copy them all: + */ + if (orig_argc > 1) + { + size_t n = strlen(WSREP_SST_OPT_MYSQLD); + *cmd_str++ = ' '; + memcpy(cmd_str, WSREP_SST_OPT_MYSQLD, n * sizeof(char)); + cmd_str += n; + for (int i = 1; i < orig_argc; i++) + { + char* arg= orig_argv[i]; + *cmd_str++ = ' '; + n = strlen(arg); + memcpy(cmd_str, arg, n * sizeof(char)); + cmd_str += n; + } + /* + Add a terminating null character (not counted in the length, + since we've overwritten the original null character which + was previously added by snprintf: + */ + *cmd_str = 0; + } +} + static ssize_t sst_prepare_other (const char* method, const char* sst_auth, const char* addr_in, const char** addr_out) { - int const cmd_len= 4096; + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); wsp::string cmd_str(cmd_len); if (!cmd_str()) { - WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %d bytes", + WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -703,6 +762,9 @@ static ssize_t sst_prepare_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + wsp::env env(NULL); if (env.error()) { @@ -975,13 +1037,14 @@ static int sst_donate_mysqldump (const char* addr, } memcpy(host, address.get_address(), address.get_address_len()); int port= address.get_port(); - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_mysqldump(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -1010,6 +1073,9 @@ static int sst_donate_mysqldump (const char* addr, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + WSREP_DEBUG("Running: '%s'", cmd_str()); ret= sst_run_shell (cmd_str(), env, 3); @@ -1329,13 +1395,14 @@ static int sst_donate_other (const char* method, bool bypass, char** env) // carries auth info { - int const cmd_len= 4096; - wsp::string cmd_str(cmd_len); + bool extra_args; + size_t const cmd_len= estimate_cmd_len(&extra_args); + wsp::string cmd_str(cmd_len); if (!cmd_str()) { WSREP_ERROR("sst_donate_other(): " - "could not allocate cmd buffer of %d bytes", cmd_len); + "could not allocate cmd buffer of %zd bytes", cmd_len); return -ENOMEM; } @@ -1376,6 +1443,9 @@ static int sst_donate_other (const char* method, return (ret < 0 ? ret : -EMSGSIZE); } + if (extra_args) + copy_orig_argv(cmd_str() + ret); + if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); pthread_t tmp; diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 1ad8ff5b5de..38706fa4671 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -32,6 +32,7 @@ #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" #define WSREP_SST_OPT_BINLOG_INDEX "--binlog-index" +#define WSREP_SST_OPT_MYSQLD "--mysqld-args" // mysqldump-specific options #define WSREP_SST_OPT_USER "--user" From c93f96e2ec3d4beb9bd2ed2b2cf509d88a165809 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 30 Jul 2019 17:18:31 +0200 Subject: [PATCH 18/35] MDEV-20185: Windows: Use of uninitialized value $bpath in string eq The execution of mtr in the Windows environment fails due to the fact that the new code from MDEV-18565 does not take into account the need to add the ".exe" extension to the names of executable files when searching for pre-requisites that are needed to run SST scripts (especially when using mariabackup) and when searching paths to some other Galera utilities. This patch fixes this flaw. Also adding paths to the PATH environment variable is now done with the correct delimiter character. --- mysql-test/mysql-test-run.pl | 33 ++++++++++++++++++++++----------- mysql-test/suite.pm | 6 +++--- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 35fefec5e4f..add9f790dac 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -445,26 +445,36 @@ sub check_wsrep_support() { # ADD scripts to $PATH to that wsrep_sst_* can be found my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$bindir/scripts", $path_client_bindir; mtr_error("No SST scripts") unless $spath; - $ENV{PATH}="$spath:$ENV{PATH}"; + my $separator= (IS_WINDOWS) ? ';' : ':'; + $ENV{PATH}="$spath$separator$ENV{PATH}"; # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql # client for loading the tables. (Don't assume each machine has mysql install) my ($cpath) = grep { -f "$_/mysql"; } "$bindir/scripts", $path_client_bindir; mtr_error("No scritps") unless $cpath; - $ENV{PATH}="$cpath:$ENV{PATH}" unless $cpath eq $spath; + $ENV{PATH}="$cpath$separator$ENV{PATH}" unless $cpath eq $spath; # ADD my_print_defaults script path to path so that SST scripts can find it - my ($epath) = grep { -f "$_/my_print_defaults"; } "$bindir/extra", $path_client_bindir; + my $my_print_defaults_exe= + mtr_exe_maybe_exists( + "$bindir/extra/my_print_defaults", + "$path_client_bindir/my_print_defaults"); + my $epath= ""; + if ($my_print_defaults_exe ne "") { + $epath= dirname($my_print_defaults_exe); + } mtr_error("No my_print_defaults") unless $epath; - $ENV{PATH}="$epath:$ENV{PATH}" unless ($epath eq $spath) or - ($epath eq $cpath); + $ENV{PATH}="$epath$separator$ENV{PATH}" unless ($epath eq $spath) or + ($epath eq $cpath); $extra_path= $epath; - if (which("socat")) { - $ENV{MTR_GALERA_TFMT}="socat"; - } elsif (which("nc")) { - $ENV{MTR_GALERA_TFMT}="nc"; + if (!IS_WINDOWS) { + if (which("socat")) { + $ENV{MTR_GALERA_TFMT}="socat"; + } elsif (which("nc")) { + $ENV{MTR_GALERA_TFMT}="nc"; + } } # Check whether WSREP_PROVIDER environment variable is set. @@ -511,8 +521,9 @@ sub check_mariabackup_support() { "$bindir/extra/mariabackup$opt_vs_config/mariabackup", "$path_client_bindir/mariabackup"); if ($mariabackup_exe ne "") { - my ($bpath) = grep { -f "$_/mariabackup"; } "$bindir/extra/mariabackup$opt_vs_config", $path_client_bindir; - $ENV{PATH}="$bpath:$ENV{PATH}" unless $bpath eq $extra_path; + my $bpath= dirname($mariabackup_exe); + my $separator= (IS_WINDOWS) ? ';' : ':'; + $ENV{PATH}="$bpath$separator$ENV{PATH}" unless $bpath eq $extra_path; $mariabackup_path= $bpath; diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index f027898579d..70c8ef401b1 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -54,11 +54,11 @@ sub skip_combinations { $skip{'include/have_mariabackup.inc'} = 'Need mariabackup' unless ::have_mariabackup(); - $skip{'include/have_mariabackup.inc'} = 'Need ss' - unless ::which("ss"); + $skip{'include/have_mariabackup.inc'} = 'Need socket statistics utility' + unless IS_WINDOWS || ::which("ss"); $skip{'include/have_mariabackup.inc'} = 'Need socat or nc' - unless $ENV{MTR_GALERA_TFMT}; + unless IS_WINDOWS || $ENV{MTR_GALERA_TFMT}; $skip{'include/have_garbd.inc'} = 'Need garbd' unless ::have_garbd(); From 12e3ac04febe16dd3ee15cd99f9196a60261f1b4 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 30 Jul 2019 17:16:25 +0200 Subject: [PATCH 19/35] MDEV-20185: Windows: Use of uninitialized value $bpath in string eq The execution of mtr in the Windows environment fails due to the fact that the new code from MDEV-18565 does not take into account the need to add the ".exe" extension to the names of executable files when searching for pre-requisites that are needed to run SST scripts (especially when using mariabackup) and when searching paths to some other Galera utilities. This patch fixes this flaw. Also adding paths to the PATH environment variable is now done with the correct delimiter character. --- mysql-test/mysql-test-run.pl | 33 ++++++++++++------- mysql-test/suite.pm | 10 +++--- .../t/galera_ist_innodb_flush_logs.test | 1 + 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 47f697ae0de..e3fe389d4c1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -440,26 +440,36 @@ sub check_wsrep_support() { # ADD scripts to $PATH to that wsrep_sst_* can be found my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$bindir/scripts", $path_client_bindir; mtr_error("No SST scripts") unless $spath; - $ENV{PATH}="$spath:$ENV{PATH}"; + my $separator= (IS_WINDOWS) ? ';' : ':'; + $ENV{PATH}="$spath$separator$ENV{PATH}"; # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql # client for loading the tables. (Don't assume each machine has mysql install) my ($cpath) = grep { -f "$_/mysql"; } "$bindir/scripts", $path_client_bindir; mtr_error("No scritps") unless $cpath; - $ENV{PATH}="$cpath:$ENV{PATH}" unless $cpath eq $spath; + $ENV{PATH}="$cpath$separator$ENV{PATH}" unless $cpath eq $spath; # ADD my_print_defaults script path to path so that SST scripts can find it - my ($epath) = grep { -f "$_/my_print_defaults"; } "$bindir/extra", $path_client_bindir; + my $my_print_defaults_exe= + mtr_exe_maybe_exists( + "$bindir/extra/my_print_defaults", + "$path_client_bindir/my_print_defaults"); + my $epath= ""; + if ($my_print_defaults_exe ne "") { + $epath= dirname($my_print_defaults_exe); + } mtr_error("No my_print_defaults") unless $epath; - $ENV{PATH}="$epath:$ENV{PATH}" unless ($epath eq $spath) or - ($epath eq $cpath); + $ENV{PATH}="$epath$separator$ENV{PATH}" unless ($epath eq $spath) or + ($epath eq $cpath); $extra_path= $epath; - if (which("socat")) { - $ENV{MTR_GALERA_TFMT}="socat"; - } elsif (which("nc")) { - $ENV{MTR_GALERA_TFMT}="nc"; + if (!IS_WINDOWS) { + if (which("socat")) { + $ENV{MTR_GALERA_TFMT}="socat"; + } elsif (which("nc")) { + $ENV{MTR_GALERA_TFMT}="nc"; + } } # Check whether WSREP_PROVIDER environment variable is set. @@ -506,8 +516,9 @@ sub check_mariabackup_support() { "$bindir/extra/mariabackup$opt_vs_config/mariabackup", "$path_client_bindir/mariabackup"); if ($mariabackup_exe ne "") { - my ($bpath) = grep { -f "$_/mariabackup"; } "$bindir/extra/mariabackup$opt_vs_config", $path_client_bindir; - $ENV{PATH}="$bpath:$ENV{PATH}" unless $bpath eq $extra_path; + my $bpath= dirname($mariabackup_exe); + my $separator= (IS_WINDOWS) ? ';' : ':'; + $ENV{PATH}="$bpath$separator$ENV{PATH}" unless $bpath eq $extra_path; $mariabackup_path= $bpath; diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index ee1eac2794d..5fc6f00b460 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -62,17 +62,17 @@ sub skip_combinations { $skip{'include/have_mariabackup.inc'} = 'Need mariabackup' unless ::have_mariabackup(); - $skip{'include/have_mariabackup.inc'} = 'Need ss' - unless ::which("ss"); + $skip{'include/have_mariabackup.inc'} = 'Need socket statistics utility' + unless IS_WINDOWS || ::which("ss"); $skip{'include/have_mariabackup.inc'} = 'Need socat or nc' - unless $ENV{MTR_GALERA_TFMT}; + unless IS_WINDOWS || $ENV{MTR_GALERA_TFMT}; $skip{'include/have_xtrabackup.inc'} = 'Need innobackupex' - unless ::which(innobackupex); + unless IS_WINDOWS || ::which("innobackupex"); $skip{'include/have_xtrabackup.inc'} = 'Need socat or nc' - unless $ENV{MTR_GALERA_TFMT}; + unless IS_WINDOWS || $ENV{MTR_GALERA_TFMT}; $skip{'include/have_garbd.inc'} = 'Need garbd' unless ::have_garbd(); diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test index 328b6b7d4de..839383ebfc1 100644 --- a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test @@ -6,6 +6,7 @@ --source include/big_test.inc --source include/galera_cluster.inc +--source include/have_innodb.inc --source include/have_xtrabackup.inc --source suite/galera/include/galera_st_kill_slave.inc From a7e2cd55ab3e8bc1d658c3b6ac11c7834783acd5 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 19 Aug 2019 22:42:56 +0400 Subject: [PATCH 20/35] MDEV-19034 ASAN unknown-crash in get_date_time_separator with PAD_CHAR_TO_FULL_LENGTH --- mysql-test/r/type_datetime.result | 11 +++++++++++ mysql-test/t/type_datetime.test | 14 ++++++++++++++ sql-common/my_time.c | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 292c92422de..dcc7411a6f2 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -1156,5 +1156,16 @@ ExtractValue('foo','bar') i MIN(d) 3 1976-12-14 13:21:07 DROP TABLE t1; # +# MDEV-19034 ASAN unknown-crash in get_date_time_separator with PAD_CHAR_TO_FULL_LENGTH +# +SET SQL_MODE=DEFAULT; +CREATE OR REPLACE TABLE t1 (a CHAR(11)); +CREATE OR REPLACE TABLE t2 (b DATETIME); +INSERT INTO t1 VALUES ('2010-02-19') ; +SET SQL_MODE= 'PAD_CHAR_TO_FULL_LENGTH'; +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; +SET SQL_MODE=DEFAULT; +# # End of 10.1 tests # diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 726510b74e8..3c5d1dbd62c 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -710,6 +710,20 @@ INSERT INTO t1 VALUES (3,NULL),(3,'1976-12-14 13:21:07'),(NULL,'1981-09-24 01:04 SELECT ExtractValue('foo','bar'), i, MIN(d) FROM t1 GROUP BY i; DROP TABLE t1; +--echo # +--echo # MDEV-19034 ASAN unknown-crash in get_date_time_separator with PAD_CHAR_TO_FULL_LENGTH +--echo # + +SET SQL_MODE=DEFAULT; +CREATE OR REPLACE TABLE t1 (a CHAR(11)); +CREATE OR REPLACE TABLE t2 (b DATETIME); +INSERT INTO t1 VALUES ('2010-02-19') ; +SET SQL_MODE= 'PAD_CHAR_TO_FULL_LENGTH'; +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; +SET SQL_MODE=DEFAULT; + + --echo # --echo # End of 10.1 tests --echo # diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 01b4d1fc2c9..5482b6dfa5c 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -184,7 +184,7 @@ static int get_date_time_separator(uint *number_of_fields, ulonglong flags, do { s++; - } while (my_isspace(&my_charset_latin1, *s)); + } while (s < end && my_isspace(&my_charset_latin1, *s)); *str= s; return 0; } From bc89b1c5582ac4044317a84e8a73d97fd1db9041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 20 Aug 2019 07:47:11 +0300 Subject: [PATCH 21/35] MDEV-18863: Fix -Wsign-compare --- sql/wsrep_sst.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index c470133d1b9..fb1efa1d451 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -706,7 +706,7 @@ static ssize_t sst_prepare_other (const char* method, my_free(binlog_opt_val); my_free(binlog_index_opt_val); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || size_t(ret) >= cmd_len) { WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); @@ -1008,7 +1008,7 @@ static int sst_donate_mysqldump (const char* addr, (long long)seqno, wsrep_gtid_domain_id, bypass ? " " WSREP_SST_OPT_BYPASS : ""); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || size_t(ret) >= cmd_len) { WSREP_ERROR("sst_donate_mysqldump(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); @@ -1378,7 +1378,7 @@ static int sst_donate_other (const char* method, bypass ? " " WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || size_t(ret) >= cmd_len) { WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); From 64c6f2bffc321f7640ae683d0341e1bc72ee2c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 20 Aug 2019 09:50:35 +0300 Subject: [PATCH 22/35] After-merge fixes main.selectivity_innodb: Re-record the result. MDEV-18863: Make wsrep_sst_mariabackup use Bash due to the += syntax. --- mysql-test/r/selectivity_innodb.result | 8 ++++---- scripts/wsrep_sst_rsync.sh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result index 38c1883c729..b243dbbce5e 100644 --- a/mysql-test/r/selectivity_innodb.result +++ b/mysql-test/r/selectivity_innodb.result @@ -1662,19 +1662,19 @@ explain extended select * from t1 use index () where a in (17,51,5); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 2.97 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`a` in (17,51,5)) +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`a` in (17,51,5) explain extended select * from t1 use index () where b=2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 4.76 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where (`test`.`t1`.`b` = 2) +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`b` = 2 # Now, the equality is used for ref access, while the range condition # 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.80 Using where +1 SIMPLE t1 ref b,a b 5 const 59 2.90 Using where 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))) +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; set use_stat_tables= @save_use_stat_tables; set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 2bb48f0ffd0..ef32e77e20d 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -1,4 +1,4 @@ -#!/bin/sh -ue +#!/bin/bash -ue # Copyright (C) 2010-2014 Codership Oy # From 262927a9e5e49d57332e2123d667a33c5faa3f1a Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Aug 2019 12:57:52 +0300 Subject: [PATCH 23/35] Fixes a problem with heap when scanning and insert rows at the same time This causes failures in versioning.update-big in 10.3 and above --- storage/heap/hp_scan.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/storage/heap/hp_scan.c b/storage/heap/hp_scan.c index 3315cb05b3f..361a1cd7397 100644 --- a/storage/heap/hp_scan.c +++ b/storage/heap/hp_scan.c @@ -44,6 +44,12 @@ int heap_scan(register HP_INFO *info, uchar *record) DBUG_ENTER("heap_scan"); pos= ++info->current_record; + if (pos >= share->records+share->deleted) + { + info->update= 0; /* No active row */ + DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); + } + if (pos < info->next_block) { info->current_ptr+=share->block.recbuffer; @@ -51,15 +57,6 @@ int heap_scan(register HP_INFO *info, uchar *record) else { info->next_block+=share->block.records_in_block; - if (info->next_block >= share->records+share->deleted) - { - info->next_block= share->records+share->deleted; - if (pos >= info->next_block) - { - info->update= 0; - DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); - } - } hp_find_record(info, pos); } if (!info->current_ptr[share->visible]) From 6dd1d6cb90ce942de0a3648b2440d76e376bb013 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Aug 2019 15:28:01 +0300 Subject: [PATCH 24/35] MDEV-20379 Mroonga has memory leak in ha_mroonga::is_foreign_key_field --- storage/mroonga/ha_mroonga.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index f7533fd4600..06ff71c1b5a 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -8994,10 +8994,12 @@ bool ha_mroonga::is_foreign_key_field(const char *table_name, grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); if (!range) { + grn_obj_unlink(ctx, column); DBUG_RETURN(false); } if (!mrn::grn::is_table(range)) { + grn_obj_unlink(ctx, column); DBUG_RETURN(false); } @@ -9011,6 +9013,7 @@ bool ha_mroonga::is_foreign_key_field(const char *table_name, DBUG_RETURN(true); } + grn_obj_unlink(ctx, column); DBUG_RETURN(false); } From 2850b8d844dccd793415aff8af646a98e1a55064 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 20 Aug 2019 15:24:32 +0300 Subject: [PATCH 25/35] MDEV-20389 The test innodb.innodb_bug84958 fails intermittently * Ensure no background purge is done; * Better result showing actual number in case of failure; * Higher and more safe difference threshold. --- mysql-test/suite/innodb/r/innodb_bug84958.result | 12 +++++++++--- mysql-test/suite/innodb/t/innodb_bug84958.test | 8 +++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_bug84958.result b/mysql-test/suite/innodb/r/innodb_bug84958.result index 1a59a10eb2f..e0c2f913407 100644 --- a/mysql-test/suite/innodb/r/innodb_bug84958.result +++ b/mysql-test/suite/innodb/r/innodb_bug84958.result @@ -4,13 +4,18 @@ # # Set up the test with a procedure and a function. # +SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; +InnoDB 0 transactions not purged CREATE PROCEDURE insert_n(start int, end int) BEGIN DECLARE i INT DEFAULT start; +START TRANSACTION; WHILE i <= end do INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i; SET i = i + 1; END WHILE; +COMMIT; END~~ CREATE FUNCTION num_pages_get() RETURNS INT @@ -51,9 +56,9 @@ SET @num_pages_1 = num_pages_get(); SELECT * FROM t1 force index (b); a b c SET @num_pages_2= num_pages_get(); -SELECT @num_pages_2 - @num_pages_1 < 500; -@num_pages_2 - @num_pages_1 < 500 -1 +SELECT IF(@num_pages_2 - @num_pages_1 < 5000, 'OK', @num_pages_2 - @num_pages_1) num_pages_diff; +num_pages_diff +OK # # Commit and show the final record. # @@ -76,6 +81,7 @@ test.t1 check status OK # disconnect con2; disconnect con3; +SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; DROP TABLE t1; DROP PROCEDURE insert_n; DROP FUNCTION num_pages_get; diff --git a/mysql-test/suite/innodb/t/innodb_bug84958.test b/mysql-test/suite/innodb/t/innodb_bug84958.test index 4456df21cb9..417aa814411 100644 --- a/mysql-test/suite/innodb/t/innodb_bug84958.test +++ b/mysql-test/suite/innodb/t/innodb_bug84958.test @@ -6,15 +6,20 @@ --echo # --source include/have_innodb.inc +SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; +--source include/wait_all_purged.inc DELIMITER ~~; CREATE PROCEDURE insert_n(start int, end int) BEGIN DECLARE i INT DEFAULT start; + START TRANSACTION; WHILE i <= end do INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i; SET i = i + 1; END WHILE; + COMMIT; END~~ CREATE FUNCTION num_pages_get() @@ -64,7 +69,7 @@ SET @num_pages_1 = num_pages_get(); SELECT * FROM t1 force index (b); SET @num_pages_2= num_pages_get(); -SELECT @num_pages_2 - @num_pages_1 < 500; +SELECT IF(@num_pages_2 - @num_pages_1 < 5000, 'OK', @num_pages_2 - @num_pages_1) num_pages_diff; --echo # --echo # Commit and show the final record. @@ -81,6 +86,7 @@ CHECK TABLE t1; --echo # disconnect con2; disconnect con3; +SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; DROP TABLE t1; DROP PROCEDURE insert_n; DROP FUNCTION num_pages_get; From 4438ff07cda1766d08730c93f92b298e845e3df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 20 Aug 2019 16:03:43 +0300 Subject: [PATCH 26/35] MDEV-20389: Refine the test case Let us invoke wait_all_purged.inc right before the workload. Starting with MDEV-12288 in MariaDB Server 10.3, also INSERT generates purge workload. If we do not ensure that purge has run to completion, the results on 10.3 and later could be nondeterministic. --- mysql-test/suite/innodb/r/innodb_bug84958.result | 2 +- mysql-test/suite/innodb/t/innodb_bug84958.test | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_bug84958.result b/mysql-test/suite/innodb/r/innodb_bug84958.result index e0c2f913407..4076999415f 100644 --- a/mysql-test/suite/innodb/r/innodb_bug84958.result +++ b/mysql-test/suite/innodb/r/innodb_bug84958.result @@ -6,7 +6,6 @@ # SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; -InnoDB 0 transactions not purged CREATE PROCEDURE insert_n(start int, end int) BEGIN DECLARE i INT DEFAULT start; @@ -52,6 +51,7 @@ connection default; # Connect to default and record how many pages were accessed # when selecting the record using the secondary key. # +InnoDB 3 transactions not purged SET @num_pages_1 = num_pages_get(); SELECT * FROM t1 force index (b); a b c diff --git a/mysql-test/suite/innodb/t/innodb_bug84958.test b/mysql-test/suite/innodb/t/innodb_bug84958.test index 417aa814411..98904680fce 100644 --- a/mysql-test/suite/innodb/t/innodb_bug84958.test +++ b/mysql-test/suite/innodb/t/innodb_bug84958.test @@ -8,7 +8,6 @@ --source include/have_innodb.inc SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; ---source include/wait_all_purged.inc DELIMITER ~~; CREATE PROCEDURE insert_n(start int, end int) @@ -65,6 +64,8 @@ connection default; --echo # Connect to default and record how many pages were accessed --echo # when selecting the record using the secondary key. --echo # +--let $wait_all_purged=3 +--source include/wait_all_purged.inc SET @num_pages_1 = num_pages_get(); SELECT * FROM t1 force index (b); SET @num_pages_2= num_pages_get(); From 1ad70bf2fe380354ae1719d91644f2ec335e4b12 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 20 Aug 2019 13:06:53 +0200 Subject: [PATCH 27/35] Revert "Fixes a problem with heap when scanning and insert rows at the same time" This reverts commit 262927a9e5e49d57332e2123d667a33c5faa3f1a. --- storage/heap/hp_scan.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/storage/heap/hp_scan.c b/storage/heap/hp_scan.c index 361a1cd7397..3315cb05b3f 100644 --- a/storage/heap/hp_scan.c +++ b/storage/heap/hp_scan.c @@ -44,12 +44,6 @@ int heap_scan(register HP_INFO *info, uchar *record) DBUG_ENTER("heap_scan"); pos= ++info->current_record; - if (pos >= share->records+share->deleted) - { - info->update= 0; /* No active row */ - DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); - } - if (pos < info->next_block) { info->current_ptr+=share->block.recbuffer; @@ -57,6 +51,15 @@ int heap_scan(register HP_INFO *info, uchar *record) else { info->next_block+=share->block.records_in_block; + if (info->next_block >= share->records+share->deleted) + { + info->next_block= share->records+share->deleted; + if (pos >= info->next_block) + { + info->update= 0; + DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); + } + } hp_find_record(info, pos); } if (!info->current_ptr[share->visible]) From 6c06defb5f6ddccba1a3d7b03ba34dbb83c7ef69 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 19 Aug 2019 14:17:38 +0200 Subject: [PATCH 28/35] MDEV-15458 Segfault in heap_scan() upon UPDATE after ADD SYSTEM VERSIONING heap_scan() makes info->next_block to be either an integer number of share->block.records_in_block's or the total number of records in the table. So when this total number or records changes, info->next_block needs to be recalculated to take it into account. This is a different fix for "Fixes a problem with heap when scanning and insert rows at the same time" --- storage/heap/hp_scan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/heap/hp_scan.c b/storage/heap/hp_scan.c index 3315cb05b3f..f07efe6cf67 100644 --- a/storage/heap/hp_scan.c +++ b/storage/heap/hp_scan.c @@ -50,7 +50,9 @@ int heap_scan(register HP_INFO *info, uchar *record) } else { - info->next_block+=share->block.records_in_block; + /* increase next_block to the next records_in_block boundary */ + ulong rem= info->next_block % share->block.records_in_block; + info->next_block+=share->block.records_in_block - rem; if (info->next_block >= share->records+share->deleted) { info->next_block= share->records+share->deleted; From 1a3c77e524e87e8f4151d31cd9c3112df6de218f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 21 Aug 2019 09:09:26 +0300 Subject: [PATCH 29/35] MDEV-19968: Galera test failure on galera_load_data Add wait conditions and compare cardinality etc information between nodes and print something only if they differ. --- .../suite/galera/r/galera_load_data.result | 42 ++----------------- .../suite/galera/t/galera_load_data.test | 42 ++++++++++++++----- 2 files changed, 35 insertions(+), 49 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_load_data.result b/mysql-test/suite/galera/r/galera_load_data.result index f0737b944e1..8a7397c7cb5 100644 --- a/mysql-test/suite/galera/r/galera_load_data.result +++ b/mysql-test/suite/galera/r/galera_load_data.result @@ -32,49 +32,15 @@ Warnings: Note 1031 Storage engine InnoDB of the table `cardtest02`.`cardtest_tbl` doesn't have this option UNLOCK TABLES; use cardtest02; -show indexes from cardtest_tbl; -Table cardtest_tbl -Non_unique 0 -Key_name PRIMARY -Seq_in_index 1 -Column_name id -Collation A -Cardinality 301 -Sub_part NULL -Packed NULL -Null -Index_type BTREE -Comment -Index_comment -select table_rows, avg_row_length, data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; -table_rows 301 -avg_row_length 81 -data_length 24576 select count(*) from cardtest_tbl; -count(*) 301 +count(*) +301 connection node_2; set session wsrep_sync_wait=15; use cardtest02; -show indexes from cardtest_tbl; -Table cardtest_tbl -Non_unique 0 -Key_name PRIMARY -Seq_in_index 1 -Column_name id -Collation A -Cardinality 301 -Sub_part NULL -Packed NULL -Null -Index_type BTREE -Comment -Index_comment -select table_rows, avg_row_length, data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; -table_rows 301 -avg_row_length 81 -data_length 24576 select count(*) from cardtest_tbl; -count(*) 301 +count(*) +301 connection node_1; use test; drop database cardtest02; diff --git a/mysql-test/suite/galera/t/galera_load_data.test b/mysql-test/suite/galera/t/galera_load_data.test index 99f8e571ef0..d4e09582a55 100644 --- a/mysql-test/suite/galera/t/galera_load_data.test +++ b/mysql-test/suite/galera/t/galera_load_data.test @@ -1,6 +1,5 @@ --source include/galera_cluster.inc - --connection node_1 create database cardtest02; @@ -38,23 +37,44 @@ ALTER TABLE `cardtest_tbl` ENABLE KEYS; UNLOCK TABLES; use cardtest02; ---sleep 15 ---vertical_results -show indexes from cardtest_tbl; ---vertical_results -select table_rows, avg_row_length, data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +--let $wait_timeout=600 +--let $wait_condition = SELECT table_rows = 301 from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +--source include/wait_condition.inc + select count(*) from cardtest_tbl; +let $cardinality1 = `SELECT cardinality from information_schema.statistics WHERE TABLE_NAME = 'cardtest_tbl'`; +let $table_rows1 = `SELECT table_rows from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`; +let $avg_row_length1 = `SELECT avg_row_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`; +let $data_length1 = `SELECT data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`; + --connection node_2 set session wsrep_sync_wait=15; use cardtest02; ---sleep 15 ---vertical_results -show indexes from cardtest_tbl; ---vertical_results -select table_rows, avg_row_length, data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; + +--let $wait_timeout=600 +--let $wait_condition = SELECT table_rows = 301 from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +--source include/wait_condition.inc + select count(*) from cardtest_tbl; +if (`SELECT cardinality <> $cardinality1 from information_schema.statistics WHERE TABLE_NAME = 'cardtest_tbl'`) +{ +SELECT cardinality from information_schema.statistics WHERE TABLE_NAME = 'cardtest_tbl'; +} +if (`SELECT table_rows <> $table_rows1 from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`) +{ +SELECT table_rows from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +} +if (`SELECT avg_row_length <> $avg_row_length1 from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`) +{ +SELECT avg_row_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +} +if (`SELECT data_length <> $data_length1 from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'`) +{ +SELECT data_length from information_schema.tables WHERE TABLE_NAME = 'cardtest_tbl'; +} + --connection node_1 use test; drop database cardtest02; From 888f6852261c67a57f21ae80ebb0f3c3f539db7b Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Wed, 31 Jul 2019 03:28:38 -0700 Subject: [PATCH 30/35] MDEV-20210 If you have an INVISIBLE VIRTUAL column, SHOW CREATE TABLE doesn't list it as INVISIBLE --- mysql-test/main/invisible_field_debug.result | 12 ++++++++++++ mysql-test/main/invisible_field_debug.test | 9 +++++++++ sql/sql_show.cc | 4 ++++ 3 files changed, 25 insertions(+) diff --git a/mysql-test/main/invisible_field_debug.result b/mysql-test/main/invisible_field_debug.result index 0ea8ab12de8..6f85bd6dd88 100644 --- a/mysql-test/main/invisible_field_debug.result +++ b/mysql-test/main/invisible_field_debug.result @@ -376,3 +376,15 @@ SET debug_dbug="+d,test_completely_invisible,test_invisible_index"; CREATE TABLE t2 LIKE t1; SET debug_dbug= DEFAULT; DROP TABLE t1, t2; +# +# MDEV-20210 +# If you have an INVISIBLE VIRTUAL column, SHOW CREATE TABLE doesn't list it as INVISIBLE +# +CREATE TABLE t1 (i INT, v int GENERATED ALWAYS AS (1) VIRTUAL INVISIBLE); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) DEFAULT NULL, + `v` int(11) GENERATED ALWAYS AS (1) VIRTUAL INVISIBLE +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/main/invisible_field_debug.test b/mysql-test/main/invisible_field_debug.test index 86252512386..a8e20247090 100644 --- a/mysql-test/main/invisible_field_debug.test +++ b/mysql-test/main/invisible_field_debug.test @@ -278,3 +278,12 @@ SET debug_dbug="+d,test_completely_invisible,test_invisible_index"; CREATE TABLE t2 LIKE t1; SET debug_dbug= DEFAULT; DROP TABLE t1, t2; + +--echo # +--echo # MDEV-20210 +--echo # If you have an INVISIBLE VIRTUAL column, SHOW CREATE TABLE doesn't list it as INVISIBLE +--echo # + +CREATE TABLE t1 (i INT, v int GENERATED ALWAYS AS (1) VIRTUAL INVISIBLE); +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1170aead53c..77eb51f6368 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2256,6 +2256,10 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" STORED")); else packet->append(STRING_WITH_LEN(" VIRTUAL")); + if (field->invisible == INVISIBLE_USER) + { + packet->append(STRING_WITH_LEN(" INVISIBLE")); + } } else { From ddaebdd21006a6ef418a161bce919c5e850109dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 20 Aug 2019 14:55:49 +0300 Subject: [PATCH 31/35] dict_table_open_on_index_id(): Remove a redundant parameter --- storage/innobase/btr/btr0scrub.cc | 7 +------ storage/innobase/dict/dict0load.cc | 19 ++----------------- storage/innobase/include/dict0dict.h | 7 +------ 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc index 376a106bf8a..bb1e5276a12 100644 --- a/storage/innobase/btr/btr0scrub.cc +++ b/storage/innobase/btr/btr0scrub.cc @@ -632,13 +632,8 @@ btr_scrub_get_table_and_index( scrub_data->current_table = NULL; } - /* argument to dict_table_open_on_index_id */ - bool dict_locked = true; - /* open table based on index_id */ - dict_table_t* table = dict_table_open_on_index_id( - index_id, - dict_locked); + dict_table_t* table = dict_table_open_on_index_id(index_id); if (table != NULL) { /* mark table as being scrubbed */ diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index ae5bbac9118..a8ed8dd3e29 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -3810,29 +3810,14 @@ dict_load_table_id_on_index_id( return(found); } -UNIV_INTERN -dict_table_t* -dict_table_open_on_index_id( -/*========================*/ - index_id_t index_id, /*!< in: index id */ - bool dict_locked) /*!< in: dict locked */ +dict_table_t* dict_table_open_on_index_id(index_id_t index_id) { - if (!dict_locked) { - mutex_enter(&dict_sys->mutex); - } - - ut_ad(mutex_own(&dict_sys->mutex)); table_id_t table_id; dict_table_t * table = NULL; if (dict_load_table_id_on_index_id(index_id, &table_id)) { - bool local_dict_locked = true; - table = dict_table_open_on_id(table_id, - local_dict_locked, + table = dict_table_open_on_id(table_id, true, DICT_TABLE_OP_LOAD_TABLESPACE); } - if (!dict_locked) { - mutex_exit(&dict_sys->mutex); - } return table; } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index cdcdef75917..fbaef118b70 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -115,12 +115,7 @@ dict_table_open_on_id( /**********************************************************************//** Returns a table object based on table id. @return table, NULL if does not exist */ -UNIV_INTERN -dict_table_t* -dict_table_open_on_index_id( -/*==================*/ - table_id_t table_id, /*!< in: table id */ - bool dict_locked) /*!< in: TRUE=data dictionary locked */ +dict_table_t* dict_table_open_on_index_id(index_id_t index_id) __attribute__((warn_unused_result)); /********************************************************************//** Decrements the count of open handles to a table. */ From e279c0076d59fdc840931b3bfa497b38893adf93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 20 Aug 2019 12:52:57 +0300 Subject: [PATCH 32/35] MDEV-17187: Code cleanup fkerr_t: Errors for the foreign key checks. Replaces ulint, which used #define that looked like dberr_t literals. wsrep_dict_foreign_find_index(): Remove. Use dict_foreign_find_index() instead, with default parameters. dict_foreign_push_index_error(): Do not add redundant quotes around quoted table names. --- .../suite/innodb/r/innodb-fk-warnings.result | 4 +- .../suite/innodb_gis/r/point_basic.result | 6 +- storage/innobase/dict/dict0dict.cc | 104 +++++------------- storage/innobase/handler/ha_innodb.cc | 15 +-- storage/innobase/include/dict0dict.h | 23 +++- 5 files changed, 56 insertions(+), 96 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-fk-warnings.result b/mysql-test/suite/innodb/r/innodb-fk-warnings.result index 01a46c8c7bd..e3cf8f7362b 100644 --- a/mysql-test/suite/innodb/r/innodb-fk-warnings.result +++ b/mysql-test/suite/innodb/r/innodb-fk-warnings.result @@ -25,7 +25,7 @@ create table t2(a int, constraint a foreign key a (a) references t1(a)) engine=i ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message -Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key a (a) references t1(a)) engine=innodb'. +Warning 150 Create table `test`.`t2` with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key a (a) references t1(a)) engine=innodb'. Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint drop table t1; @@ -42,7 +42,7 @@ alter table t2 add constraint b foreign key (b) references t2(b); ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message -Warning 150 Alter table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key (b) references t2(b)'. +Warning 150 Alter table `test`.`t2` with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key (b) references t2(b)'. Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint drop table t2, t1; diff --git a/mysql-test/suite/innodb_gis/r/point_basic.result b/mysql-test/suite/innodb_gis/r/point_basic.result index 97328584bf7..093b63e5b02 100644 --- a/mysql-test/suite/innodb_gis/r/point_basic.result +++ b/mysql-test/suite/innodb_gis/r/point_basic.result @@ -1524,7 +1524,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p); ERROR HY000: Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message -Warning 150 Alter table '`test`.`child`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. +Warning 150 Alter table `test`.`child` with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint ALTER TABLE parent DROP INDEX idx1; @@ -1532,7 +1532,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p); Got one of the listed errors show warnings; Level Code Message -Warning 150 Alter table '`test`.`child`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. +Warning 150 Alter table `test`.`child` with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint ALTER TABLE child DROP INDEX idx2; @@ -1540,7 +1540,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p); Got one of the listed errors show warnings; Level Code Message -Warning 150 Alter table '`test`.`child`' with foreign key constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. +Warning 150 Alter table `test`.`child` with foreign key constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns near 'FOREIGN KEY(p) REFERENCES parent(p)'. Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint DROP TABLE child, parent; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 3fcc1bce177..3e5e8ca2fec 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -3211,11 +3211,6 @@ dict_index_build_internal_fts( } /*====================== FOREIGN KEY PROCESSING ========================*/ -#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200 -#define DB_FOREIGN_KEY_COL_NOT_NULL 201 -#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202 -#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203 - /** Check whether the dict_table_t is a partition. A partitioned table on the SQL level is composed of InnoDB tables, where each InnoDB table is a [sub]partition including its secondary indexes @@ -3322,7 +3317,7 @@ dict_foreign_find_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ @@ -3330,17 +3325,15 @@ dict_foreign_find_index( /*!< out: index where error happened */ { - dict_index_t* index; - ut_ad(mutex_own(&dict_sys->mutex)); if (error) { - *error = DB_FOREIGN_KEY_INDEX_NOT_FOUND; + *error = FK_INDEX_NOT_FOUND; } - index = dict_table_get_first_index(table); - - while (index != NULL) { + for (dict_index_t* index = dict_table_get_first_index(table); + index; + index = dict_table_get_next_index(index)) { if (types_idx != index && !index->to_be_dropped && !dict_index_is_online_ddl(index) @@ -3348,42 +3341,17 @@ dict_foreign_find_index( table, col_names, columns, n_cols, index, types_idx, check_charsets, check_null, - error, err_col_no,err_index)) { + error, err_col_no, err_index)) { if (error) { - *error = DB_SUCCESS; + *error = FK_SUCCESS; } return(index); } - - index = dict_table_get_next_index(index); } return(NULL); } -#ifdef WITH_WSREP -dict_index_t* -wsrep_dict_foreign_find_index( -/*====================*/ - dict_table_t* table, /*!< in: table */ - const char** col_names, /*!< in: column names, or NULL - to use table->col_names */ - const char** columns,/*!< in: array of column names */ - ulint n_cols, /*!< in: number of columns */ - dict_index_t* types_idx, /*!< in: NULL or an index to whose types the - column types must match */ - ibool check_charsets, - /*!< in: whether to check charsets. - only has an effect if types_idx != NULL */ - ulint check_null) - /*!< in: nonzero if none of the columns must - be declared NOT NULL */ -{ - return dict_foreign_find_index( - table, col_names, columns, n_cols, types_idx, check_charsets, - check_null, NULL, NULL, NULL); -} -#endif /* WITH_WSREP */ /**********************************************************************//** Report an error in a foreign key definition. */ static @@ -3480,15 +3448,11 @@ dict_foreign_add_to_cache( } if (ref_table && !for_in_cache->referenced_table) { - ulint index_error; - ulint err_col; - dict_index_t *err_index=NULL; - index = dict_foreign_find_index( ref_table, NULL, for_in_cache->referenced_col_names, for_in_cache->n_fields, for_in_cache->foreign_index, - check_charsets, false, &index_error, &err_col, &err_index); + check_charsets, false); if (index == NULL && !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) { @@ -3520,10 +3484,6 @@ dict_foreign_add_to_cache( } if (for_table && !for_in_cache->foreign_table) { - ulint index_error; - ulint err_col; - dict_index_t *err_index=NULL; - index = dict_foreign_find_index( for_table, col_names, for_in_cache->foreign_col_names, @@ -3531,8 +3491,7 @@ dict_foreign_add_to_cache( for_in_cache->referenced_index, check_charsets, for_in_cache->type & (DICT_FOREIGN_ON_DELETE_SET_NULL - | DICT_FOREIGN_ON_UPDATE_SET_NULL), - &index_error, &err_col, &err_index); + | DICT_FOREIGN_ON_UPDATE_SET_NULL)); if (index == NULL && !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) { @@ -4244,7 +4203,7 @@ dict_foreign_push_index_error( const char* latest_foreign, /*!< in: start of latest foreign key constraint name */ const char** columns, /*!< in: foreign key columns */ - ulint index_error, /*!< in: error code */ + fkerr_t index_error, /*!< in: error code */ ulint err_col, /*!< in: column where error happened */ dict_index_t* err_index, /*!< in: index where error happened @@ -4253,37 +4212,37 @@ dict_foreign_push_index_error( FILE* ef) /*!< in: output stream */ { switch (index_error) { - case DB_FOREIGN_KEY_INDEX_NOT_FOUND: { + case FK_SUCCESS: + break; + case FK_INDEX_NOT_FOUND: fprintf(ef, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.", operation, create_name, latest_foreign); - break; - } - case DB_FOREIGN_KEY_IS_PREFIX_INDEX: { + return; + case FK_IS_PREFIX_INDEX: fprintf(ef, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.", operation, create_name, latest_foreign); - break; - } - case DB_FOREIGN_KEY_COL_NOT_NULL: { + return; + case FK_COL_NOT_NULL: fprintf(ef, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " @@ -4294,9 +4253,8 @@ dict_foreign_push_index_error( " failed. You have defined a SET NULL condition but " "column '%s' on index is defined as NOT NULL near '%s'.", operation, create_name, columns[err_col], latest_foreign); - break; - } - case DB_FOREIGN_KEY_COLS_NOT_EQUAL: { + return; + case FK_COLS_NOT_EQUAL: dict_field_t* field; const char* col_name; field = dict_index_get_nth_field(err_index, err_col); @@ -4315,11 +4273,9 @@ dict_foreign_push_index_error( " failed. Field type or character set for column '%s' " "does not mach referenced column '%s' near '%s'.", operation, create_name, columns[err_col], col_name, latest_foreign); - break; - } - default: - ut_error; + return; } + DBUG_ASSERT(!"unknown error"); } /*********************************************************************//** @@ -4351,7 +4307,7 @@ dict_create_foreign_constraints_low( const char* start_of_latest_foreign = sql_string; const char* start_of_latest_set = NULL; FILE* ef = dict_foreign_err_file; - ulint index_error = DB_SUCCESS; + fkerr_t index_error = FK_SUCCESS; dict_index_t* err_index = NULL; ulint err_col; const char* constraint_name; @@ -6832,7 +6788,7 @@ dict_foreign_qualify_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ @@ -6860,7 +6816,7 @@ dict_foreign_qualify_index( /* We do not accept column prefix indexes here */ if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_IS_PREFIX_INDEX; + *error = FK_IS_PREFIX_INDEX; *err_col_no = i; *err_index = (dict_index_t*)index; } @@ -6870,7 +6826,7 @@ dict_foreign_qualify_index( if (check_null && (field->col->prtype & DATA_NOT_NULL)) { if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_COL_NOT_NULL; + *error = FK_COL_NOT_NULL; *err_col_no = i; *err_index = (dict_index_t*)index; } @@ -6900,7 +6856,7 @@ dict_foreign_qualify_index( dict_index_get_nth_col(types_idx, i), check_charsets)) { if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_COLS_NOT_EQUAL; + *error = FK_COLS_NOT_EQUAL; *err_col_no = i; *err_index = (dict_index_t*)index; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 39adcea5f9d..21639fd63b6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -10331,17 +10331,6 @@ next_record: } #ifdef WITH_WSREP -extern dict_index_t* -wsrep_dict_foreign_find_index( -/*==========================*/ - dict_table_t* table, - const char** col_names, - const char** columns, - ulint n_cols, - dict_index_t* types_idx, - ibool check_charsets, - ulint check_null); - inline const char* wsrep_key_type_to_str(wsrep_key_type type) @@ -10404,7 +10393,7 @@ wsrep_append_foreign_key( foreign->referenced_table_name_lookup); if (foreign->referenced_table) { foreign->referenced_index = - wsrep_dict_foreign_find_index( + dict_foreign_find_index( foreign->referenced_table, NULL, foreign->referenced_col_names, foreign->n_fields, @@ -10418,7 +10407,7 @@ wsrep_append_foreign_key( if (foreign->foreign_table) { foreign->foreign_index = - wsrep_dict_foreign_find_index( + dict_foreign_find_index( foreign->foreign_table, NULL, foreign->foreign_col_names, foreign->n_fields, diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index fbaef118b70..4e90c9398ba 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -527,6 +527,21 @@ dict_table_open_on_name( dict_err_ignore_t ignore_err) MY_ATTRIBUTE((warn_unused_result)); +/** Outcome of dict_foreign_find_index() or dict_foreign_qualify_index() */ +enum fkerr_t +{ + /** A backing index was found for a FOREIGN KEY constraint */ + FK_SUCCESS = 0, + /** There is no index that covers the columns in the constraint. */ + FK_INDEX_NOT_FOUND, + /** The index is for a prefix index, not a full column. */ + FK_IS_PREFIX_INDEX, + /** A condition of SET NULL conflicts with a NOT NULL column. */ + FK_COL_NOT_NULL, + /** The column types do not match */ + FK_COLS_NOT_EQUAL +}; + /*********************************************************************//** Tries to find an index whose first fields are the columns in the array, in the same order and is not marked for deletion and is not the same @@ -553,11 +568,11 @@ dict_foreign_find_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ - ulint* err_col_no, + fkerr_t* error = NULL, /*!< out: error code */ + ulint* err_col_no = NULL, /*!< out: column number where error happened */ - dict_index_t** err_index) + dict_index_t** err_index = NULL) /*!< out: index where error happened */ @@ -643,7 +658,7 @@ dict_foreign_qualify_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ From 9de2e60d7491fcf3cd1f20a4be715ef0bedc316f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 21 Aug 2019 11:38:17 +0300 Subject: [PATCH 33/35] MDEV-17187 table doesn't exist in engine after ALTER of FOREIGN KEY ha_innobase::open(): Always ignore problems with FOREIGN KEY constraints (pass DICT_ERR_IGNORE_FK_NOKEY), no matter whether foreign_key_checks is enabled. Instead, we must report errors when enforcing the FOREIGN KEY constraints. As a result of ignoring these errors, the tables will be loaded with dict_foreign_t objects whose foreign_index or referenced_index will be NULL. Also, pass DICT_ERR_IGNORE_FK_NOKEY instead of DICT_ERR_IGNORE_NONE to dict_table_open_on_id_low() in many other cases. Notably, on CREATE TABLE and ALTER TABLE, we will keep validating the FOREIGN KEY constraints as before. dict_table_open_on_name(): If no other flags than DICT_ERR_IGNORE_FK_NOKEY are set, refuse access to unreadable tables. Some encryption tests rely on this code path. For the DML code path, we used to have the problem that when one of the indexes was missing in dict_foreign_t, we would ignore the FOREIGN KEY constraint altogether. The following changes address that. row_ins_check_foreign_constraints(): Add the parameter pk. For the primary key, consider also foreign key constraints for which foreign->foreign_index=NULL (no underlying index is available). row_ins_check_foreign_constraint(): Report errors also for !check_ref. Remove a redundant check for srv_read_only_mode. row_ins_foreign_report_add_err(): Tolerate foreign->foreign_index=NULL. --- mysql-test/suite/innodb/r/foreign-keys.result | 59 +++++++++++++++ .../suite/innodb/r/innodb_bug68148.result | 1 - mysql-test/suite/innodb/t/foreign-keys.test | 46 ++++++++++++ .../suite/innodb/t/innodb_bug68148.test | 2 - storage/innobase/dict/dict0dict.cc | 6 +- storage/innobase/dict/dict0load.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 21 ++---- storage/innobase/include/dict0types.h | 8 +- storage/innobase/row/row0ins.cc | 75 ++++++++++++------- storage/innobase/row/row0mysql.cc | 8 +- 10 files changed, 173 insertions(+), 55 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign-keys.result b/mysql-test/suite/innodb/r/foreign-keys.result index c4cf3a6a72d..5cbbb5298de 100644 --- a/mysql-test/suite/innodb/r/foreign-keys.result +++ b/mysql-test/suite/innodb/r/foreign-keys.result @@ -161,3 +161,62 @@ c d 6 30 drop table t2, t1; drop user foo; +# +# MDEV-17187 table doesn't exist in engine after ALTER other tables +# with CONSTRAINTs +# +set foreign_key_checks=on; +create table t1 (id int not null primary key) engine=innodb; +create table t2 (id int not null primary key, fid int not null, +CONSTRAINT fk_fid FOREIGN KEY (fid) REFERENCES t1 (id))engine=innodb; +insert into t1 values (1), (2), (3); +insert into t2 values (1, 1), (2, 1), (3, 2); +set foreign_key_checks=off; +alter table t2 drop index fk_fid; +set foreign_key_checks=on; +delete from t1 where id=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)) +insert into t2 values(4, 99); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)) +select * from t1; +id +1 +2 +3 +select * from t2; +id fid +1 1 +2 1 +3 2 +set foreign_key_checks=off; +delete from t1 where id=2; +insert into t2 values(4, 99); +set foreign_key_checks=on; +select * from t1; +id +1 +3 +select * from t2; +id fid +1 1 +2 1 +3 2 +4 99 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(11) NOT NULL, + `fid` int(11) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1,t2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table t1,t2; +ERROR 42S02: Unknown table 'test.t2' diff --git a/mysql-test/suite/innodb/r/innodb_bug68148.result b/mysql-test/suite/innodb/r/innodb_bug68148.result index 88247053389..9da4ea80d08 100644 --- a/mysql-test/suite/innodb/r/innodb_bug68148.result +++ b/mysql-test/suite/innodb/r/innodb_bug68148.result @@ -19,7 +19,6 @@ main ref_table1 ref_table2 # restart and see if we can still access the main table -SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `main` ADD INDEX `idx_1` (`ref_id1`); SHOW CREATE TABLE `main`; Table Create Table diff --git a/mysql-test/suite/innodb/t/foreign-keys.test b/mysql-test/suite/innodb/t/foreign-keys.test index be2c891771b..58a71d11a6a 100644 --- a/mysql-test/suite/innodb/t/foreign-keys.test +++ b/mysql-test/suite/innodb/t/foreign-keys.test @@ -204,3 +204,49 @@ connection default; select * from t2; drop table t2, t1; drop user foo; + +--echo # +--echo # MDEV-17187 table doesn't exist in engine after ALTER other tables +--echo # with CONSTRAINTs +--echo # + +set foreign_key_checks=on; +create table t1 (id int not null primary key) engine=innodb; +create table t2 (id int not null primary key, fid int not null, +CONSTRAINT fk_fid FOREIGN KEY (fid) REFERENCES t1 (id))engine=innodb; + +insert into t1 values (1), (2), (3); +insert into t2 values (1, 1), (2, 1), (3, 2); + +set foreign_key_checks=off; +alter table t2 drop index fk_fid; +set foreign_key_checks=on; + +--error ER_ROW_IS_REFERENCED_2 +delete from t1 where id=2; +--error ER_NO_REFERENCED_ROW_2 +insert into t2 values(4, 99); + +select * from t1; +select * from t2; + +set foreign_key_checks=off; +delete from t1 where id=2; +insert into t2 values(4, 99); +set foreign_key_checks=on; + +select * from t1; +select * from t2; + +show create table t1; +show create table t2; + +# Optional: test DROP TABLE without any prior ha_innobase::open(). +# This was tested manually, but it would cause --embedded to skip the test, +# and the restart would significantly increase the running time. +# --source include/restart_mysqld.inc + +--error ER_ROW_IS_REFERENCED_2 +drop table t1,t2; +--error ER_BAD_TABLE_ERROR +drop table t1,t2; diff --git a/mysql-test/suite/innodb/t/innodb_bug68148.test b/mysql-test/suite/innodb/t/innodb_bug68148.test index 531baa30e48..2741c3cba3d 100644 --- a/mysql-test/suite/innodb/t/innodb_bug68148.test +++ b/mysql-test/suite/innodb/t/innodb_bug68148.test @@ -31,8 +31,6 @@ SHOW TABLES; --echo # restart and see if we can still access the main table --source include/restart_mysqld.inc -# This is required to access the table -SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `main` ADD INDEX `idx_1` (`ref_id1`); SHOW CREATE TABLE `main`; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 3e5e8ca2fec..32fcfe68d32 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -432,7 +432,7 @@ dict_table_try_drop_aborted( if (table == NULL) { table = dict_table_open_on_id_low( - table_id, DICT_ERR_IGNORE_NONE, FALSE); + table_id, DICT_ERR_IGNORE_FK_NOKEY, FALSE); } else { ut_ad(table->id == table_id); } @@ -1005,7 +1005,7 @@ dict_table_open_on_id( table_id, table_op == DICT_TABLE_OP_LOAD_TABLESPACE ? DICT_ERR_IGNORE_RECOVER_LOCK - : DICT_ERR_IGNORE_NONE, + : DICT_ERR_IGNORE_FK_NOKEY, table_op == DICT_TABLE_OP_OPEN_ONLY_IF_CACHED); if (table != NULL) { @@ -1167,7 +1167,7 @@ dict_table_open_on_name( if (table != NULL) { /* If table is encrypted or corrupted */ - if (ignore_err == DICT_ERR_IGNORE_NONE + if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) && !table->is_readable()) { /* Make life easy for drop table. */ dict_table_prevent_eviction(table); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index a8ed8dd3e29..6900d62b225 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -3121,7 +3121,7 @@ func_exit: mem_heap_free(heap); ut_ad(!table - || ignore_err != DICT_ERR_IGNORE_NONE + || (ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) || !table->is_readable() || !table->corrupted); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 21639fd63b6..7c9e4148886 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3185,7 +3185,7 @@ static bool innobase_query_caching_table_check( const char* norm_name) { dict_table_t* table = dict_table_open_on_name( - norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + norm_name, FALSE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); if (table == NULL) { return false; @@ -6209,9 +6209,7 @@ initialize_auto_increment(dict_table_t* table, const Field* field) int ha_innobase::open(const char* name, int, uint) { - dict_table_t* ib_table; char norm_name[FN_REFLEN]; - dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE; DBUG_ENTER("ha_innobase::open"); @@ -6225,15 +6223,8 @@ ha_innobase::open(const char* name, int, uint) char* is_part = is_partition(norm_name); THD* thd = ha_thd(); - - /* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table - can be opened even if some FK indexes are missing. If not, the table - can't be opened in the same situation */ - if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { - ignore_err = DICT_ERR_IGNORE_FK_NOKEY; - } - - ib_table = open_dict_table(name, norm_name, is_part, ignore_err); + dict_table_t* ib_table = open_dict_table(name, norm_name, is_part, + DICT_ERR_IGNORE_FK_NOKEY); DEBUG_SYNC(thd, "ib_open_after_dict_open"); @@ -13404,8 +13395,8 @@ innobase_rename_table( row_mysql_lock_data_dictionary(trx); } - dict_table_t* table = dict_table_open_on_name(norm_from, TRUE, FALSE, - DICT_ERR_IGNORE_NONE); + dict_table_t* table = dict_table_open_on_name( + norm_from, TRUE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); /* Since DICT_BG_YIELD has sleep for 250 milliseconds, Convert lock_wait_timeout unit from second to 250 milliseconds */ @@ -14582,7 +14573,7 @@ ha_innobase::defragment_table( normalize_table_name(norm_name, name); table = dict_table_open_on_name(norm_name, FALSE, - FALSE, DICT_ERR_IGNORE_NONE); + FALSE, DICT_ERR_IGNORE_FK_NOKEY); for (index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index 39addf697e8..93c2f570e54 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -59,11 +59,11 @@ Note: please define the IGNORE_ERR_* as bits, so their value can be or-ed together */ enum dict_err_ignore_t { DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */ - DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root - page is FIL_NULL or incorrect value */ - DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */ - DICT_ERR_IGNORE_FK_NOKEY = 4, /*!< ignore error if any foreign + DICT_ERR_IGNORE_FK_NOKEY = 1, /*!< ignore error if any foreign key is missing */ + DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root + page is FIL_NULL or incorrect value */ + DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */ DICT_ERR_IGNORE_RECOVER_LOCK = 8, /*!< Used when recovering table locks for resurrected transactions. diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index ece291378b6..2cda0e3d03c 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -875,8 +875,12 @@ row_ins_foreign_report_add_err( fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); fputs(fk_str.c_str(), ef); - fprintf(ef, " in parent table, in index %s", - foreign->foreign_index->name()); + if (foreign->foreign_index) { + fprintf(ef, " in parent table, in index %s", + foreign->foreign_index->name()); + } else { + fputs(" in parent table", ef); + } if (entry) { fputs(" tuple:\n", ef); /* TODO: DB_TRX_ID and DB_ROLL_PTR may be uninitialized. @@ -1628,34 +1632,51 @@ row_ins_check_foreign_constraint( || check_index == NULL || fil_space_get(check_table->space)->is_being_truncated) { - if (!srv_read_only_mode && check_ref) { - FILE* ef = dict_foreign_err_file; - std::string fk_str; + FILE* ef = dict_foreign_err_file; + std::string fk_str; - row_ins_set_detailed(trx, foreign); + row_ins_set_detailed(trx, foreign); + row_ins_foreign_trx_print(trx); - row_ins_foreign_trx_print(trx); - - fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, - foreign->foreign_table_name); - fputs(":\n", ef); - fk_str = dict_print_info_on_foreign_key_in_create_format( - trx, foreign, TRUE); - fputs(fk_str.c_str(), ef); - fprintf(ef, "\nTrying to add to index %s tuple:\n", - foreign->foreign_index->name()); + fputs("Foreign key constraint fails for table ", ef); + ut_print_name(ef, trx, check_ref + ? foreign->foreign_table_name + : foreign->referenced_table_name); + fputs(":\n", ef); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); + if (check_ref) { + if (foreign->foreign_index) { + fprintf(ef, "\nTrying to add to index %s" + " tuple:\n", + foreign->foreign_index->name()); + } else { + fputs("\nTrying to add tuple:\n", ef); + } dtuple_print(ef, entry); fputs("\nBut the parent table ", ef); - ut_print_name(ef, trx, - foreign->referenced_table_name); - fputs("\nor its .ibd file does" + ut_print_name(ef, trx, foreign->referenced_table_name); + fputs("\nor its .ibd file or the required index does" " not currently exist!\n", ef); - mutex_exit(&dict_foreign_err_mutex); - err = DB_NO_REFERENCED_ROW; + } else { + if (foreign->referenced_index) { + fprintf(ef, "\nTrying to modify index %s" + " tuple:\n", + foreign->referenced_index->name()); + } else { + fputs("\nTrying to modify tuple:\n", ef); + } + dtuple_print(ef, entry); + fputs("\nBut the referencing table ", ef); + ut_print_name(ef, trx, foreign->foreign_table_name); + fputs("\nor its .ibd file or the required index does" + " not currently exist!\n", ef); + err = DB_ROW_IS_REFERENCED; } + mutex_exit(&dict_foreign_err_mutex); goto exit_func; } @@ -1923,6 +1944,7 @@ row_ins_check_foreign_constraints( /*==============================*/ dict_table_t* table, /*!< in: table */ dict_index_t* index, /*!< in: index */ + bool pk, /*!< in: index->is_primary() */ dtuple_t* entry, /*!< in: index entry for index */ que_thr_t* thr) /*!< in: query thread */ { @@ -1931,6 +1953,8 @@ row_ins_check_foreign_constraints( trx_t* trx; ibool got_s_lock = FALSE; + DBUG_ASSERT(index->is_primary() == pk); + trx = thr_get_trx(thr); DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd, @@ -1942,7 +1966,8 @@ row_ins_check_foreign_constraints( foreign = *it; - if (foreign->foreign_index == index) { + if (foreign->foreign_index == index + || (pk && !foreign->foreign_index)) { dict_table_t* ref_table = NULL; dict_table_t* referenced_table = foreign->referenced_table; @@ -3119,7 +3144,7 @@ row_ins_clust_index_entry( if (!index->table->foreign_set.empty()) { err = row_ins_check_foreign_constraints( - index->table, index, entry, thr); + index->table, index, true, entry, thr); if (err != DB_SUCCESS) { DBUG_RETURN(err); @@ -3193,7 +3218,7 @@ row_ins_sec_index_entry( if (!index->table->foreign_set.empty()) { err = row_ins_check_foreign_constraints(index->table, index, - entry, thr); + false, entry, thr); if (err != DB_SUCCESS) { return(err); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index f3d48edfb80..4b82fb9c2c4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2799,7 +2799,7 @@ row_discard_tablespace_begin( dict_table_t* table; table = dict_table_open_on_name( - name, TRUE, FALSE, DICT_ERR_IGNORE_NONE); + name, TRUE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); if (table) { dict_stats_wait_bg_to_stop_using_table(table, trx); @@ -3199,7 +3199,7 @@ row_drop_table_from_cache( dict_table_remove_from_cache(table); - if (dict_load_table(tablename, true, DICT_ERR_IGNORE_NONE)) { + if (dict_load_table(tablename, true, DICT_ERR_IGNORE_FK_NOKEY)) { ib::error() << "Not able to remove table " << ut_get_name(trx, tablename) << " from the dictionary cache!"; @@ -4164,7 +4164,7 @@ row_rename_table_for_mysql( dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH; table = dict_table_open_on_name(old_name, dict_locked, FALSE, - DICT_ERR_IGNORE_NONE); + DICT_ERR_IGNORE_FK_NOKEY); /* We look for pattern #P# to see if the table is partitioned MySQL table. */ @@ -4212,7 +4212,7 @@ row_rename_table_for_mysql( par_case_name, old_name, FALSE); #endif table = dict_table_open_on_name(par_case_name, dict_locked, FALSE, - DICT_ERR_IGNORE_NONE); + DICT_ERR_IGNORE_FK_NOKEY); } if (!table) { From e8de75db88acdf228237fbebad7f4c8f05e5cc1f Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 21 Aug 2019 11:37:40 +0300 Subject: [PATCH 34/35] MDEV-19740 Debug build of 10.3.15 FTBFS Fix debug build failing with error: extended initializer lists only available with -std=c++11 or -std=gnu++11 --- sql/sql_explain.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 8ded81788a2..70b177a556d 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -444,7 +444,8 @@ uint Explain_union::make_union_table_name(char *buf) break; default: DBUG_ASSERT(0); - type= {NULL, 0}; + type.str= NULL; + type.length= 0; } memcpy(buf, type.str, (len= (uint)type.length)); From b96e4424fb4d35dd5de52f44ed6b726a3f0dd010 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 21 Aug 2019 16:06:29 +0300 Subject: [PATCH 35/35] MDEV-17613 MIN/MAX Optimization (Select tables optimized away) does not work Current easy fix is not possible, because SELECT clones ha_partition and then closes the clone which leads to unclosed transaction in partitions we forcely prune out. We cound solve this by closing these partitions (and release from transaction) in change_partitions_to_open() at versioning conditions stage, but this is problematic because table lock is acquired for each partition at open stage and therefore must be released when we close partition handler in change_partitions_to_open(). More details in MDEV-20376. This should change after MDEV-20250 where mechanism of opening partitions will be improved. This reverts commit cdbac54df0bd857a053decd66b6067abf15a6801. --- .../suite/versioning/r/partition.result | 11 ------ .../versioning/r/partition_rotation.result | 2 +- mysql-test/suite/versioning/t/partition.test | 21 ---------- sql/sql_select.cc | 38 +++---------------- 4 files changed, 6 insertions(+), 66 deletions(-) diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index b029efa7479..7c2854d59b1 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -547,17 +547,6 @@ t1 CREATE TABLE `t1` ( create or replace table t1 (f int) with system versioning partition by hash(f); insert delayed into t1 values (1); # -# MDEV-17613 MIN/MAX Optimization (Select tables optimized away) does not work -# -create or replace table t1 (pk int primary key) with system versioning -partition by system_time ( -partition p1 history, -partition pn current); -insert into t1 values (1), (2); -explain select max(pk) from t1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -# # MDEV-20068 History partition rotation is not done under LOCK TABLES # create or replace table t1 (x int) with system versioning partition by system_time limit 1 diff --git a/mysql-test/suite/versioning/r/partition_rotation.result b/mysql-test/suite/versioning/r/partition_rotation.result index 69b30a56bd6..7e25f122238 100644 --- a/mysql-test/suite/versioning/r/partition_rotation.result +++ b/mysql-test/suite/versioning/r/partition_rotation.result @@ -44,7 +44,7 @@ i 6 explain partitions select * from t1; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 Using where explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p1_p1sp0,p1_p1sp1,p0_p0sp0,p0_p0sp1,p2_p2sp0,p2_p2sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index a3feadee1b5..17ad11a13e1 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -497,27 +497,6 @@ create or replace table t1 (f int) with system versioning partition by hash(f); --error 0,ER_DELAYED_NOT_SUPPORTED insert delayed into t1 values (1); ---echo # ---echo # MDEV-17613 MIN/MAX Optimization (Select tables optimized away) does not work ---echo # ---disable_query_log -set @saved_storage_engine= @@default_storage_engine; -if ($MTR_COMBINATION_HEAP) -{ - # This case does not work with HEAP - set default_storage_engine= myisam; -} ---enable_query_log -create or replace table t1 (pk int primary key) with system versioning -partition by system_time ( - partition p1 history, - partition pn current); -insert into t1 values (1), (2); -explain select max(pk) from t1; ---disable_query_log -set default_storage_engine= @saved_storage_engine; ---enable_query_log - --echo # --echo # MDEV-20068 History partition rotation is not done under LOCK TABLES --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7dcbafd4a88..9d74505cb74 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -721,19 +721,6 @@ void vers_select_conds_t::print(String *str, enum_query_type query_type) const } } -/** - Setup System Versioning conditions - - Add WHERE condition according to FOR SYSTEM_TIME clause. - - If the table is partitioned by SYSTEM_TIME and there is no FOR SYSTEM_TIME - clause, then select now-partition instead of modifying WHERE condition. - - @retval - -1 on error - @retval - 0 on success -*/ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("SELECT_LEX::vers_setup_cond"); @@ -801,13 +788,12 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) vers_select_conds_t &vers_conditions= table->vers_conditions; #ifdef WITH_PARTITION_STORAGE_ENGINE - Vers_part_info *vers_info; - if (table->table->part_info && (vers_info= table->table->part_info->vers_info)) - { - if (table->partition_names) + /* + if the history is stored in partitions, then partitions + themselves are not versioned + */ + if (table->partition_names && table->table->part_info->vers_info) { - /* If the history is stored in partitions, then partitions - themselves are not versioned. */ if (vers_conditions.is_set()) { my_error(ER_VERS_QUERY_IN_PARTITION, MYF(0), table->alias.str); @@ -816,19 +802,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) else vers_conditions.init(SYSTEM_TIME_ALL); } - else if (!vers_conditions.is_set() && - /* We cannot optimize REPLACE .. SELECT because it may need - to call vers_set_hist_part() to update history. */ - thd->lex->sql_command != SQLCOM_REPLACE_SELECT) - { - table->partition_names= newx List; - String *s= newx String(vers_info->now_part->partition_name, - system_charset_info); - table->partition_names->push_back(s); - table->table->file->change_partitions_to_open(table->partition_names); - vers_conditions.init(SYSTEM_TIME_ALL); - } - } #endif if (outer_table && !vers_conditions.is_set()) @@ -978,7 +951,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) DBUG_RETURN(0); #undef newx } -#undef newx /***************************************************************************** Check fields, find best join, do the select and output fields.