From aa0f7e9bd7818adf7d93c26b1fe29ae6aa2d6e41 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Wed, 31 May 2017 17:53:32 +0530 Subject: [PATCH 01/47] Fix galera_defaults test and check_galera_version.inc script Signed-off-by: Sachin Setiya --- .../suite/galera/r/galera_defaults.result | 7 ++++--- .../suite/galera/t/galera_defaults.test | 4 ++-- .../wsrep/include/check_galera_version.inc | 19 ++++++++----------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index b5b94ad317b..878fe80ff98 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -1,5 +1,5 @@ -SELECT COUNT(*) = 39 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; -COUNT(*) = 39 +SELECT COUNT(*) = 40 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +COUNT(*) = 40 1 SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -25,6 +25,7 @@ WSREP_CONVERT_LOCK_TO_TRX OFF WSREP_DBUG_OPTION WSREP_DEBUG OFF WSREP_DESYNC OFF +WSREP_DIRTY_READS OFF WSREP_DRUPAL_282555_WORKAROUND OFF WSREP_FORCED_BINLOG_FORMAT NONE WSREP_LOAD_DATA_SPLITTING ON @@ -47,7 +48,7 @@ WSREP_SST_DONOR WSREP_SST_DONOR_REJECTS_QUERIES OFF WSREP_SST_METHOD rsync WSREP_SYNC_WAIT 7 -; ; ; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; ; gcache.keep_pages_size = 0; gcache.mem_size = 0; ; gcache.page_size = 128M; gcache.recover = no; gcache.size = 128M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; ;gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; ; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; ; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; socket.recv_buf_size = 212992; +; ; ; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; ; gcache.keep_pages_size = 0; gcache.mem_size = 0; ; gcache.page_size = 128M; gcache.recover = no; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; ; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; ; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; ; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; socket.recv_buf_size = 212992; SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_%' AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test index 87eddedafe9..cd718ae2bdb 100644 --- a/mysql-test/suite/galera/t/galera_defaults.test +++ b/mysql-test/suite/galera/t/galera_defaults.test @@ -13,13 +13,13 @@ # Make sure that the test is operating on the right version of galera library. --disable_query_log ---let $galera_version=25.3.17 +--let $galera_version=3.20 source ../wsrep/include/check_galera_version.inc; --enable_query_log # Global Variables -SELECT COUNT(*) = 39 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +SELECT COUNT(*) = 40 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES diff --git a/mysql-test/suite/wsrep/include/check_galera_version.inc b/mysql-test/suite/wsrep/include/check_galera_version.inc index cb35269249b..e495da8f1ee 100644 --- a/mysql-test/suite/wsrep/include/check_galera_version.inc +++ b/mysql-test/suite/wsrep/include/check_galera_version.inc @@ -2,7 +2,7 @@ # Enable tests to check the galera library version. # # ==== Usage ==== -# --let $galera_version=25.3.6 +# --let $galera_version=3.6 # source include/check_galera_lib_version.inc; # # Parameters: @@ -15,25 +15,22 @@ # Required Version eval SET @GALERA_VERSION='$galera_version'; -SELECT CAST(REGEXP_REPLACE(@GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\1') AS UNSIGNED) INTO @GALERA_MAJOR_VERSION; -SELECT CAST(REGEXP_REPLACE(@GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\2') AS UNSIGNED) INTO @GALERA_MID_VERSION; -SELECT CAST(REGEXP_REPLACE(@GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\3') AS UNSIGNED) INTO @GALERA_MINOR_VERSION; +SELECT CAST(REGEXP_REPLACE(@GALERA_VERSION,'^(\\d+)\\.(\\d+).*','\\1') AS UNSIGNED) INTO @GALERA_MAJOR_VERSION; +SELECT CAST(REGEXP_REPLACE(@GALERA_VERSION,'^(\\d+)\\.(\\d+).*','\\2') AS UNSIGNED) INTO @GALERA_MINOR_VERSION; # Actual SELECT VARIABLE_VALUE INTO @ACTUAL_GALERA_VERSION FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_provider_version'; -SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\1') AS UNSIGNED) INTO @ACTUAL_GALERA_MAJOR_VERSION; -SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\2') AS UNSIGNED) INTO @ACTUAL_GALERA_MID_VERSION; -SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^(\\d+)\\.(\\d+)\\.(\\d+).*','\\3') AS UNSIGNED) INTO @ACTUAL_GALERA_MINOR_VERSION; +SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^(\\d+)\\.(\\d+).*','\\1') AS UNSIGNED) INTO @ACTUAL_GALERA_MAJOR_VERSION; +SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^(\\d+)\\.(\\d+).*','\\2') AS UNSIGNED) INTO @ACTUAL_GALERA_MINOR_VERSION; # For testing -#SELECT @GALERA_MAJOR_VERSION, @GALERA_MID_VERSION, @GALERA_MINOR_VERSION; +#SELECT @GALERA_MAJOR_VERSION, @GALERA_MINOR_VERSION; #SELECT @ACTUAL_GALERA_VERSION; -#SELECT @ACTUAL_GALERA_MAJOR_VERSION, @ACTUAL_GALERA_MID_VERSION, @ACTUAL_GALERA_MINOR_VERSION; +#SELECT @ACTUAL_GALERA_MAJOR_VERSION, @ACTUAL_GALERA_MINOR_VERSION; if (!`SELECT (@ACTUAL_GALERA_MAJOR_VERSION > @GALERA_MAJOR_VERSION) OR - (@ACTUAL_GALERA_MAJOR_VERSION = @GALERA_MAJOR_VERSION AND @ACTUAL_GALERA_MID_VERSION > @GALERA_MID_VERSION) OR - (@ACTUAL_GALERA_MAJOR_VERSION = @GALERA_MAJOR_VERSION AND @ACTUAL_GALERA_MID_VERSION = @GALERA_MID_VERSION AND @ACTUAL_GALERA_MINOR_VERSION >= @GALERA_MINOR_VERSION) + (@ACTUAL_GALERA_MAJOR_VERSION = @GALERA_MAJOR_VERSION AND @ACTUAL_GALERA_MINOR_VERSION >= @GALERA_MINOR_VERSION) `) { skip Test requires Galera library version $galera_version; From 3806a323ce414fb3b425d762b9fbe08403432f2a Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Thu, 1 Jun 2017 16:40:57 +0530 Subject: [PATCH 02/47] Fix galera_var_node_address.test --- mysql-test/suite/galera/r/galera_var_node_address.result | 1 + mysql-test/suite/galera/t/galera_var_node_address.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_var_node_address.result b/mysql-test/suite/galera/r/galera_var_node_address.result index fa88f4b3128..b562883176a 100644 --- a/mysql-test/suite/galera/r/galera_var_node_address.result +++ b/mysql-test/suite/galera/r/galera_var_node_address.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("WSREP: Stray state UUID msg: .* current group state WAIT_STATE_UUID .*"); SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 diff --git a/mysql-test/suite/galera/t/galera_var_node_address.test b/mysql-test/suite/galera/t/galera_var_node_address.test index cf118cf9934..c2105823326 100644 --- a/mysql-test/suite/galera/t/galera_var_node_address.test +++ b/mysql-test/suite/galera/t/galera_var_node_address.test @@ -6,6 +6,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +call mtr.add_suppression("WSREP: Stray state UUID msg: .* current group state WAIT_STATE_UUID .*"); SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --connection node_1 From 4f40f87c48a9ee252f797b5d760a6b6f07cc3815 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Fri, 2 Jun 2017 11:33:35 -0400 Subject: [PATCH 03/47] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 22d7ed0a903..ab62b5a1c7c 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=31 +MYSQL_VERSION_PATCH=32 From c258ca2463947fcc3d69bb50a8b5cf6906778508 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 7 Jun 2017 12:45:09 -0700 Subject: [PATCH 04/47] Fixed the bug mdev-12838. If the optimizer chose an execution plan where a semi-join nest were materialized and the result of materialization was scanned to access other tables by ref access it could build a key over columns of the tables from the nest that were actually inaccessible. The patch performs a proper check whether a key that uses columns of the tables from a materialized semi-join nest can be employed to access outer tables. --- mysql-test/r/subselect_mat.result | 88 ++++++++++++ mysql-test/r/subselect_sj_mat.result | 88 ++++++++++++ mysql-test/t/subselect_sj_mat.test | 207 +++++++++++++++++++++++++++ sql/opt_subselect.cc | 4 + sql/sql_select.cc | 71 ++++++++- sql/sql_select.h | 8 ++ 6 files changed, 461 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index ffa37b025eb..d4dc519227b 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2272,6 +2272,94 @@ pk f1 sq 5 3 5 set optimizer_switch= @save_optimizer_switch; DROP TABLE t1,t2; +# +# mdev-12838: scan of materialized of semi-join subquery in join +# +set @save_optimizer_switch=@@optimizer_switch; +CREATE TABLE t1 ( +dispatch_group varchar(32), +assignment_group varchar(32), +sys_id char(32), +PRIMARY KEY (sys_id), +KEY idx1 (dispatch_group), +KEY idx2 (assignment_group) +) ENGINE=MyISAM; +CREATE TABLE t2 ( +ugroup varchar(32), +user varchar(32), +sys_id char(32), +PRIMARY KEY (sys_id), +KEY idx3 (ugroup), +KEY idx4 (user) +) ENGINE=MyISAM; +CREATE TABLE t3 ( +type mediumtext, +sys_id char(32), +PRIMARY KEY (sys_id) +) ENGINE=MyISAM; +set optimizer_switch='materialization=off'; +explain SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ref idx3,idx4 idx4 35 const 2 Using index condition; Using where; Start temporary +1 PRIMARY t3_i eq_ref PRIMARY PRIMARY 32 test.t2.ugroup 1 Using index condition; Using where +1 PRIMARY t1 ref idx1,idx2 idx1 35 test.t3_i.sys_id 2 Using index condition; Using where; End temporary +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 32 test.t1.assignment_group 1 Using where; Using index +SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +assignment_group +df50316637232000158bbfc8bcbe5d23 +e08fad2637232000158bbfc8bcbe5d39 +ec70316637232000158bbfc8bcbe5d60 +7b10fd2637232000158bbfc8bcbe5d30 +ebb4620037332000158bbfc8bcbe5d89 +set optimizer_switch='materialization=on'; +explain SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 2 +1 PRIMARY t1 ref idx1,idx2 idx1 35 test.t2.ugroup 2 Using where +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 32 test.t1.assignment_group 1 Using where; Using index +2 MATERIALIZED t2 ref idx3,idx4 idx4 35 const 2 Using index condition; Using where +2 MATERIALIZED t3_i eq_ref PRIMARY PRIMARY 32 test.t2.ugroup 1 Using index condition; Using where +SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +assignment_group +df50316637232000158bbfc8bcbe5d23 +e08fad2637232000158bbfc8bcbe5d39 +ec70316637232000158bbfc8bcbe5d60 +7b10fd2637232000158bbfc8bcbe5d30 +ebb4620037332000158bbfc8bcbe5d89 +DROP TABLE t1,t2,t3; +set optimizer_switch=@save_optimizer_switch; # End of 5.5 tests set @subselect_mat_test_optimizer_switch_value=null; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off'; diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index 47f578fb589..cb5012a91c9 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2312,4 +2312,92 @@ pk f1 sq 5 3 5 set optimizer_switch= @save_optimizer_switch; DROP TABLE t1,t2; +# +# mdev-12838: scan of materialized of semi-join subquery in join +# +set @save_optimizer_switch=@@optimizer_switch; +CREATE TABLE t1 ( +dispatch_group varchar(32), +assignment_group varchar(32), +sys_id char(32), +PRIMARY KEY (sys_id), +KEY idx1 (dispatch_group), +KEY idx2 (assignment_group) +) ENGINE=MyISAM; +CREATE TABLE t2 ( +ugroup varchar(32), +user varchar(32), +sys_id char(32), +PRIMARY KEY (sys_id), +KEY idx3 (ugroup), +KEY idx4 (user) +) ENGINE=MyISAM; +CREATE TABLE t3 ( +type mediumtext, +sys_id char(32), +PRIMARY KEY (sys_id) +) ENGINE=MyISAM; +set optimizer_switch='materialization=off'; +explain SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ref idx3,idx4 idx4 35 const 2 Using index condition; Using where; Start temporary +1 PRIMARY t3_i eq_ref PRIMARY PRIMARY 32 test.t2.ugroup 1 Using index condition; Using where +1 PRIMARY t1 ref idx1,idx2 idx1 35 test.t3_i.sys_id 2 Using index condition; Using where; End temporary +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 32 test.t1.assignment_group 1 Using where; Using index +SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +assignment_group +df50316637232000158bbfc8bcbe5d23 +e08fad2637232000158bbfc8bcbe5d39 +ec70316637232000158bbfc8bcbe5d60 +7b10fd2637232000158bbfc8bcbe5d30 +ebb4620037332000158bbfc8bcbe5d89 +set optimizer_switch='materialization=on'; +explain SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 2 +1 PRIMARY t1 ref idx1,idx2 idx1 35 test.t2.ugroup 2 Using where +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 32 test.t1.assignment_group 1 Using where; Using index +2 MATERIALIZED t2 ref idx3,idx4 idx4 35 const 2 Using index condition; Using where +2 MATERIALIZED t3_i eq_ref PRIMARY PRIMARY 32 test.t2.ugroup 1 Using index condition; Using where +SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND +t1.dispatch_group IN +(SELECT t2.ugroup +FROM t2, t3 t3_i +WHERE t2.ugroup = t3_i.sys_id AND +t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND +t2.user = '86826bf03710200044e0bfc8bcbe5d79'); +assignment_group +df50316637232000158bbfc8bcbe5d23 +e08fad2637232000158bbfc8bcbe5d39 +ec70316637232000158bbfc8bcbe5d60 +7b10fd2637232000158bbfc8bcbe5d30 +ebb4620037332000158bbfc8bcbe5d89 +DROP TABLE t1,t2,t3; +set optimizer_switch=@save_optimizer_switch; # End of 5.5 tests diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index cd71ae5c901..90f63bea561 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1944,4 +1944,211 @@ set optimizer_switch= @save_optimizer_switch; DROP TABLE t1,t2; +--echo # +--echo # mdev-12838: scan of materialized of semi-join subquery in join +--echo # + +set @save_optimizer_switch=@@optimizer_switch; + +CREATE TABLE t1 ( + dispatch_group varchar(32), + assignment_group varchar(32), + sys_id char(32), + PRIMARY KEY (sys_id), + KEY idx1 (dispatch_group), + KEY idx2 (assignment_group) +) ENGINE=MyISAM; + +CREATE TABLE t2 ( + ugroup varchar(32), + user varchar(32), + sys_id char(32), + PRIMARY KEY (sys_id), + KEY idx3 (ugroup), + KEY idx4 (user) +) ENGINE=MyISAM; + +CREATE TABLE t3 ( + type mediumtext, + sys_id char(32), + PRIMARY KEY (sys_id) +) ENGINE=MyISAM; + +--disable_query_log + +INSERT INTO t1 VALUES +('e5d9f63237232000158bbfc8bcbe5dbf','f304ae0037332000158bbfc8bcbe5d4f', +'5398c0e037003000158bbfc8bcbe5dbb'), +('69d9f63237232000158bbfc8bcbe5dcb','7172ea0037332000158bbfc8bcbe5db6', +'5c188ca037003000158bbfc8bcbe5dbc'), +('577ed708d773020058c92cf65e61037a','699708d4d773020058c92cf65e61037c', +'623a8cd4d773020058c92cf65e6103ea'), +('96fb652637232000158bbfc8bcbe5db4','df50316637232000158bbfc8bcbe5d23', +'6835bd6637232000158bbfc8bcbe5d21'), +('e1d9f63237232000158bbfc8bcbe5db8','96346e0037332000158bbfc8bcbe5daa', +'697880e037003000158bbfc8bcbe5dcd'), +('25d9f63237232000158bbfc8bcbe5dbe','f304ae0037332000158bbfc8bcbe5d4f', +'6a9804e037003000158bbfc8bcbe5d09'), +('96fb652637232000158bbfc8bcbe5db4','e08fad2637232000158bbfc8bcbe5d39', +'6d25f96637232000158bbfc8bcbe5d79'), +('e9d9f63237232000158bbfc8bcbe5dc6','7172ea0037332000158bbfc8bcbe5db6', +'702880e037003000158bbfc8bcbe5d94'), +('a5d9f63237232000158bbfc8bcbe5dca','f304ae0037332000158bbfc8bcbe5d4f', +'7188c0e037003000158bbfc8bcbe5d75'), +('65d9f63237232000158bbfc8bcbe5dc4','f304ae0037332000158bbfc8bcbe5d4f', +'778880e037003000158bbfc8bcbe5d9e'), +('a1d9f63237232000158bbfc8bcbe5dc3','7172ea0037332000158bbfc8bcbe5db6', +'7d0840e037003000158bbfc8bcbe5dde'), +('21d9f63237232000158bbfc8bcbe5db7','96346e0037332000158bbfc8bcbe5daa', +'7f6880e037003000158bbfc8bcbe5da7'), +('96fb652637232000158bbfc8bcbe5db4','ec70316637232000158bbfc8bcbe5d60', +'8025f96637232000158bbfc8bcbe5dd0'), +('3dd9f63237232000158bbfc8bcbe5dcc','7172ea0037332000158bbfc8bcbe5db6', +'823880e037003000158bbfc8bcbe5ded'), +('96fb652637232000158bbfc8bcbe5db4','7b10fd2637232000158bbfc8bcbe5d30', +'9a353d6637232000158bbfc8bcbe5dee'), +('75d9f63237232000158bbfc8bcbe5dd0','ebb4620037332000158bbfc8bcbe5d89', +'a558c0e037003000158bbfc8bcbe5d36'), +('6dd9f63237232000158bbfc8bcbe5db5','96346e0037332000158bbfc8bcbe5daa', +'bc78cca037003000158bbfc8bcbe5d74'), +('add9f63237232000158bbfc8bcbe5dc7','7172ea0037332000158bbfc8bcbe5db6', +'c53804a037003000158bbfc8bcbe5db8'), +('fdd9f63237232000158bbfc8bcbe5dcd','7864ae0037332000158bbfc8bcbe5db8', +'cfe740e037003000158bbfc8bcbe5de8'), +('96fb652637232000158bbfc8bcbe5db4','3120fd2637232000158bbfc8bcbe5d42', +'e2257d6637232000158bbfc8bcbe5ded'), +('3c3725e237232000158bbfc8bcbe5da1','96346e0037332000158bbfc8bcbe5daa', +'ee78c0e037003000158bbfc8bcbe5db5'), +('a9d9f63237232000158bbfc8bcbe5dc0','7172ea0037332000158bbfc8bcbe5db6', +'f00888a037003000158bbfc8bcbe5dd3'), +('29d9f63237232000158bbfc8bcbe5db9','7172ea0037332000158bbfc8bcbe5db6', +'fa0880e037003000158bbfc8bcbe5d70'), +('b1d9f63237232000158bbfc8bcbe5dcf','ebb4620037332000158bbfc8bcbe5d89', +'fa48c0e037003000158bbfc8bcbe5d28'); + +INSERT INTO t2 VALUES +('17801ac21b13200050fdfbcd2c0713e8','8e826bf03710200044e0bfc8bcbe5d86', +'14c19a061b13200050fdfbcd2c07134b'), +('577ed708d773020058c92cf65e61037a','931644d4d773020058c92cf65e61034c', +'339888d4d773020058c92cf65e6103aa'), +('df50316637232000158bbfc8bcbe5d23','92826bf03710200044e0bfc8bcbe5da9', +'3682f56637232000158bbfc8bcbe5d44'), +('b4f342b237232000158bbfc8bcbe5def','86826bf03710200044e0bfc8bcbe5d70', +'38e4c2b237232000158bbfc8bcbe5dea'), +('7b10fd2637232000158bbfc8bcbe5d30','8a826bf03710200044e0bfc8bcbe5d72', +'4442b56637232000158bbfc8bcbe5d43'), +('3120fd2637232000158bbfc8bcbe5d42','82826bf03710200044e0bfc8bcbe5d89', +'49d2396637232000158bbfc8bcbe5d12'), +('96fb652637232000158bbfc8bcbe5db4','86826bf03710200044e0bfc8bcbe5d79', +'4e3ca52637232000158bbfc8bcbe5d3e'), +('17801ac21b13200050fdfbcd2c0713e8','824fd523bf4320007a6d257b3f073963', +'58c19a061b13200050fdfbcd2c07134e'), +('699708d4d773020058c92cf65e61037c','901784d4d773020058c92cf65e6103da', +'5bc708d4d773020058c92cf65e6103d5'), +('75d9f63237232000158bbfc8bcbe5dd0','86826bf03710200044e0bfc8bcbe5d79', +'6b52cb7237232000158bbfc8bcbe5ded'), +('f253da061b13200050fdfbcd2c0713ab','8e826bf03710200044e0bfc8bcbe5d86', +'81045e061b13200050fdfbcd2c071373'), +('7b10fd2637232000158bbfc8bcbe5d30','8e826bf03710200044e0bfc8bcbe5d74', +'8c42b56637232000158bbfc8bcbe5d3f'), +('e5d9f63237232000158bbfc8bcbe5dbf','7a826bf03710200044e0bfc8bcbe5df5', +'a7acfe3237232000158bbfc8bcbe5d78'), +('8a5055c9c61122780043563ef53438e3','9ee1b13dc6112271007f9d0efdb69cd0', +'a9aff553c6112276015a8006174bee21'), +('8a4dde73c6112278017a6a4baf547aa7','9ee1b13dc6112271007f9d0efdb69cd0', +'a9b2f526c61122760003ae07349d294f'), +('aaccc971c0a8001500fe1ff4302de101','9ee1b13dc6112271007f9d0efdb69cd0', +'aacceed3c0a80015009069bba51c4e21'), +('65d9f63237232000158bbfc8bcbe5dc4','8d56406a0a0a0a6b004070b354aada28', +'ac1bfa3237232000158bbfc8bcbe5dc3'), +('b85d44954a3623120004689b2d5dd60a','97000fcc0a0a0a6e0104ca999f619e5b', +'b77bc032cbb00200d71cb9c0c24c9c45'), +('220f8e71c61122840197e57c33464f70','8d56406a0a0a0a6b004070b354aada28', +'b9b74f080a0a0b343ba75b95bdb27056'), +('e08fad2637232000158bbfc8bcbe5d39','82826bf03710200044e0bfc8bcbe5d80', +'be02756637232000158bbfc8bcbe5d8b'), +('ebb4620037332000158bbfc8bcbe5d89','7682abf03710200044e0bfc8bcbe5d25', +'c0122f4437732000158bbfc8bcbe5d7d'), +('96fb652637232000158bbfc8bcbe5db4','7a82abf03710200044e0bfc8bcbe5d27', +'c23ca52637232000158bbfc8bcbe5d3b'), +('22122b37c611228400f9ff91c857581d','9ee1b13dc6112271007f9d0efdb69cd0', +'d23bbf5dac14641866947512bde59dc5'), +('db53a9290a0a0a650091abebccf833c6','9ee1b13dc6112271007f9d0efdb69cd0', +'db54a0f60a0a0a65002c54dcb72b4f41'), +('e08fad2637232000158bbfc8bcbe5d39','8e826bf03710200044e0bfc8bcbe5d86', +'f602756637232000158bbfc8bcbe5d88'), +('699708d4d773020058c92cf65e61037c','8d59d601d7b3020058c92cf65e6103c2', +'f718a241d7b3020058c92cf65e610332'), +('df50316637232000158bbfc8bcbe5d23','9e826bf03710200044e0bfc8bcbe5da6', +'fe82f56637232000158bbfc8bcbe5d4e'), +('f972d6061b13200050fdfbcd2c0713e5','780395f0df031100a9e78b6c3df2631f', +'ff4395f0df031100a9e78b6c3df2637e'); + +INSERT INTO t3 VALUES +('87245e061b13200050fdfbcd2c0713cc','7172ea0037332000158bbfc8bcbe5db6'), +('74af88c6c611227d0066386e74dc853d','74ad1ff3c611227d01d25feac2af603f'), +('59e22fb137032000158bbfc8bcbe5d52','75d9f63237232000158bbfc8bcbe5dd0'), +('98906fb137032000158bbfc8bcbe5d65','781da52637232000158bbfc8bcbe5db8'), +('87245e061b13200050fdfbcd2c0713cc','7864ae0037332000158bbfc8bcbe5db8'), +('87245e061b13200050fdfbcd2c0713cc','7b10fd2637232000158bbfc8bcbe5d30'), +('59e22fb137032000158bbfc8bcbe5d52','81a880e037003000158bbfc8bcbe5df8'), +('74af88c6c611227d0066386e74dc853d','8a4cb6d4c61122780043b1642efcd52b'), +('1cb8ab9bff500200158bffffffffff62','8a4dde73c6112278017a6a4baf547aa7'), +('1cb8ab9bff500200158bffffffffff62','8a5055c9c61122780043563ef53438e3'), +('87245e061b13200050fdfbcd2c0713cc','96346e0037332000158bbfc8bcbe5daa'), +('59e22fb137032000158bbfc8bcbe5d52','96fb652637232000158bbfc8bcbe5db4'), +('59e22fb137032000158bbfc8bcbe5d52','a1d9f63237232000158bbfc8bcbe5dc3'), +('59e22fb137032000158bbfc8bcbe5d52','a5d9f63237232000158bbfc8bcbe5dca'), +('1cb8ab9bff500200158bffffffffff62','a715cd759f2002002920bde8132e7018'), +('59e22fb137032000158bbfc8bcbe5d52','a9d9f63237232000158bbfc8bcbe5dc0'), +('74af88c6c611227d0066386e74dc853d','aacb62e2c0a80015007f67f752c2b12c'), +('74af88c6c611227d0066386e74dc853d','aaccc971c0a8001500fe1ff4302de101'), +('59e22fb137032000158bbfc8bcbe5d52','add9f63237232000158bbfc8bcbe5dbb'), +('59e22fb137032000158bbfc8bcbe5d52','add9f63237232000158bbfc8bcbe5dc7'), +('59e22fb137032000158bbfc8bcbe5d52','b1d9f63237232000158bbfc8bcbe5dcf'), +('1cb8ab9bff500200158bffffffffff62','b85d44954a3623120004689b2d5dd60a'), +('1cb8ab9bff500200158bffffffffff62','b97e89b94a36231201676b73322a0311'), +('1cb8ab9bff500200158bffffffffff62','cfcbad03d711110050f5edcb9e61038f'), +('1cb8ab9bff500200158bffffffffff62','d625dccec0a8016700a222a0f7900d06'), +('1cb8ab9bff500200158bffffffffff62','db53580b0a0a0a6501aa37c294a2ba6b'), +('1cb8ab9bff500200158bffffffffff62','db53a9290a0a0a650091abebccf833c6'), +('1cb8ab9bff500200158bffffffffff62','dc0db135c332010016194ffe5bba8f23'), +('87245e061b13200050fdfbcd2c0713cc','df50316637232000158bbfc8bcbe5d23'), +('87245e061b13200050fdfbcd2c0713cc','e08fad2637232000158bbfc8bcbe5d39'), +('59e22fb137032000158bbfc8bcbe5d52','e1d9f63237232000158bbfc8bcbe5db8'), +('59e22fb137032000158bbfc8bcbe5d52','e5d9f63237232000158bbfc8bcbe5db4'), +('59e22fb137032000158bbfc8bcbe5d52','e5d9f63237232000158bbfc8bcbe5dbf'), +('59e22fb137032000158bbfc8bcbe5d52','e9d9f63237232000158bbfc8bcbe5dba'), +('59e22fb137032000158bbfc8bcbe5d52','e9d9f63237232000158bbfc8bcbe5dc6'), +('87245e061b13200050fdfbcd2c0713cc','ebb4620037332000158bbfc8bcbe5d89'), +('87245e061b13200050fdfbcd2c0713cc','ec70316637232000158bbfc8bcbe5d60'), +('87245e061b13200050fdfbcd2c0713cc','f253da061b13200050fdfbcd2c0713ab'), +('87245e061b13200050fdfbcd2c0713cc','f304ae0037332000158bbfc8bcbe5d4f'), +('98906fb137032000158bbfc8bcbe5d65','f972d6061b13200050fdfbcd2c0713e5'), +('59e22fb137032000158bbfc8bcbe5d52','fdd9f63237232000158bbfc8bcbe5dcd'); + +--enable_query_log + +let $q= +SELECT t1.assignment_group +FROM t1, t3 +WHERE t1.assignment_group = t3.sys_id AND + t1.dispatch_group IN + (SELECT t2.ugroup + FROM t2, t3 t3_i + WHERE t2.ugroup = t3_i.sys_id AND + t3_i.type LIKE '59e22fb137032000158bbfc8bcbe5d52' AND + t2.user = '86826bf03710200044e0bfc8bcbe5d79'); + +set optimizer_switch='materialization=off'; +eval explain $q; +eval $q; + +set optimizer_switch='materialization=on'; +eval explain $q; +eval $q; + +DROP TABLE t1,t2,t3; +set optimizer_switch=@save_optimizer_switch; + --echo # End of 5.5 tests diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index d8b4de29f47..af1abb2001e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3429,6 +3429,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) table_map remaining_tables= 0; table_map handled_tabs= 0; join->sjm_lookup_tables= 0; + join->sjm_scan_tables= 0; for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--) { POSITION *pos= join->best_positions + tablenr; @@ -3487,6 +3488,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) for (i= tablenr; i != (first + sjm->tables - 1); i--) rem_tables |= join->best_positions[i].table->table->map; + for (i= first; i < first+ sjm->tables; i++) + join->sjm_scan_tables |= join->best_positions[i].table->table->map; + POSITION dummy; join->cur_sj_inner_tables= 0; for (i= first + sjm->tables; i <= tablenr; i++) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bad57aeac87..86ba0346366 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7361,6 +7361,63 @@ bool JOIN_TAB::hash_join_is_possible() } +/** + @brief + Check whether a KEYUSE can be really used for access this join table + + @param join Join structure with the best join order + for which the check is performed + @param keyuse Evaluated KEYUSE structure + + @details + This function is supposed to be used after the best execution plan have been + already chosen and the JOIN_TAB array for the best join order been already set. + For a given KEYUSE to access this JOIN_TAB in the best execution plan the + function checks whether it really can be used. The function first performs + the check with access_from_tables_is_allowed(). If it succeeds it checks + whether the keyuse->val does not use some fields of a materialized semijoin + nest that cannot be used to build keys to access outer tables. + Such KEYUSEs exists for the query like this: + select * from ot + where ot.c in (select it1.c from it1, it2 where it1.c=f(it2.c)) + Here we have two KEYUSEs to access table ot: with val=it1.c and val=f(it2.c). + However if the subquery was materialized the second KEYUSE cannot be employed + to access ot. + + @retval true the given keyuse can be used for ref access of this JOIN_TAB + @retval false otherwise +*/ + +bool JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, + KEYUSE *keyuse) +{ + if (!access_from_tables_is_allowed(keyuse->used_tables, + join->sjm_lookup_tables)) + return false; + if (join->sjm_scan_tables & table->map) + return true; + table_map keyuse_sjm_scan_tables= keyuse->used_tables & + join->sjm_scan_tables; + if (!keyuse_sjm_scan_tables) + return true; + uint sjm_tab_nr= 0; + while (!(keyuse_sjm_scan_tables & table_map(1) << sjm_tab_nr)) + sjm_tab_nr++; + JOIN_TAB *sjm_tab= join->map2table[sjm_tab_nr]; + TABLE_LIST *emb_sj_nest= sjm_tab->emb_sj_nest; + if (!(emb_sj_nest->sj_mat_info && emb_sj_nest->sj_mat_info->is_used && + emb_sj_nest->sj_mat_info->is_sj_scan)) + return true; + st_select_lex *sjm_sel= emb_sj_nest->sj_subq_pred->unit->first_select(); + for (uint i= 0; i < sjm_sel->item_list.elements; i++) + { + if (sjm_sel->ref_pointer_array[i] == keyuse->val) + return true; + } + return false; +} + + static uint cache_record_length(JOIN *join,uint idx) { @@ -7904,6 +7961,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, do { if (!(~used_tables & keyuse->used_tables) && + join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) && are_tables_local(join_tab, keyuse->used_tables)) { if (first_keyuse) @@ -7918,6 +7976,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, { if (curr->keypart == keyuse->keypart && !(~used_tables & curr->used_tables) && + join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, + keyuse) && are_tables_local(join_tab, curr->used_tables)) break; } @@ -7951,6 +8011,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, do { if (!(~used_tables & keyuse->used_tables) && + join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) && are_tables_local(join_tab, keyuse->used_tables)) { bool add_key_part= TRUE; @@ -7960,7 +8021,9 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, { if (curr->keypart == keyuse->keypart && !(~used_tables & curr->used_tables) && - are_tables_local(join_tab, curr->used_tables)) + join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, + curr) && + are_tables_local(join_tab, curr->used_tables)) { keyuse->keypart= NO_KEYPART; add_key_part= FALSE; @@ -8062,8 +8125,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, do { if (!(~used_tables & keyuse->used_tables) && - j->access_from_tables_is_allowed(keyuse->used_tables, - join->sjm_lookup_tables)) + j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse)) { if (are_tables_local(j, keyuse->val->used_tables())) { @@ -8132,8 +8194,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, for (i=0 ; i < keyparts ; keyuse++,i++) { while (((~used_tables) & keyuse->used_tables) || - !j->access_from_tables_is_allowed(keyuse->used_tables, - join->sjm_lookup_tables) || + !j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) || keyuse->keypart == NO_KEYPART || (keyuse->keypart != (is_hash_join_key_no(key) ? diff --git a/sql/sql_select.h b/sql/sql_select.h index 0623672840e..1bc1e4c2b7a 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -540,6 +540,8 @@ typedef struct st_join_table { !(used_sjm_lookup_tables & ~emb_sj_nest->sj_inner_tables)); } + bool keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, KEYUSE *keyuse); + } JOIN_TAB; @@ -1003,6 +1005,11 @@ public: to materialize and access by lookups */ table_map sjm_lookup_tables; + /** + Bitmap of semijoin tables that the chosen plan decided + to materialize to scan the results of materialization + */ + table_map sjm_scan_tables; /* Constant tables for which we have found a row (as opposed to those for which we didn't). @@ -1331,6 +1338,7 @@ public: pre_sort_join_tab= NULL; emb_sjm_nest= NULL; sjm_lookup_tables= 0; + sjm_scan_tables= 0; /* The following is needed because JOIN::cleanup(true) may be called for joins for which JOIN::optimize was aborted with an error before a proper From 151f4e9b4adea020fbe19b640016845dfa65d820 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 7 Jun 2017 16:29:55 -0700 Subject: [PATCH 05/47] Fixed the bug mdev-12963. This patch corrects the fix for bug mdev-7599. When the min/max optimization of the function opt_sum_query() optimizes away all tables of a subquery it should not ever be rolled back. --- mysql-test/r/subselect_mat_cost_bugs.result | 17 +++++++++++++++++ mysql-test/t/subselect_mat_cost_bugs.test | 16 ++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 34 insertions(+) diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result index dba4d049da3..57b0526c6a3 100644 --- a/mysql-test/r/subselect_mat_cost_bugs.result +++ b/mysql-test/r/subselect_mat_cost_bugs.result @@ -485,3 +485,20 @@ FROM t2 AS t2a INNER JOIN t2 t2b INNER JOIN t3 ON (f3 = t2b.f2) ); f1 DROP TABLE t1,t2,t3; +# +# MDEV-12963: min/max optimization optimizing away all tables employed +# for uncorrelated IN subquery used in a disjunct of WHERE +# +create table t1 (a int, index idx(a)) engine=myisam; +insert into t1 values (4),(7),(1),(3),(9); +select * from t1 where a in (select max(a) from t1 where a < 4) or a > 5; +a +3 +7 +9 +explain +select * from t1 where a in (select max(a) from t1 where a < 4) or a > 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index idx idx 5 NULL 5 Using where; Using index +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1; diff --git a/mysql-test/t/subselect_mat_cost_bugs.test b/mysql-test/t/subselect_mat_cost_bugs.test index 9e3ac603ec6..35f2b9588fe 100644 --- a/mysql-test/t/subselect_mat_cost_bugs.test +++ b/mysql-test/t/subselect_mat_cost_bugs.test @@ -507,3 +507,19 @@ SELECT * FROM t1 ON (f3 = t2b.f2) ); DROP TABLE t1,t2,t3; + +--echo # +--echo # MDEV-12963: min/max optimization optimizing away all tables employed +--echo # for uncorrelated IN subquery used in a disjunct of WHERE +--echo # + +create table t1 (a int, index idx(a)) engine=myisam; +insert into t1 values (4),(7),(1),(3),(9); + +select * from t1 where a in (select max(a) from t1 where a < 4) or a > 5; +explain +select * from t1 where a in (select max(a) from t1 where a < 4) or a > 5; + +drop table t1; + + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 86ba0346366..f2be17f71d6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1195,6 +1195,7 @@ JOIN::optimize() DBUG_PRINT("info",("Select tables optimized away")); zero_result_cause= "Select tables optimized away"; tables_list= 0; // All tables resolved + select_lex->min_max_opt_list.empty(); const_tables= top_join_tab_count= table_count; /* Extract all table-independent conditions and replace the WHERE From b850fc66ca72ed9b63cb8b899b64f8c555a525c7 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 7 Jun 2017 22:54:57 -0700 Subject: [PATCH 06/47] Fixed the bug mdev-12855. This is actually a legacy bug: SQL_SELECT::test_quick_select() was called with SQL_SELECT::head not set. It looks like that this problem can be reproduced only on queries with ORDER BY that use IN predicates converted to semi-joins. --- mysql-test/r/subselect_sj2_mat.result | 22 ++++++++++++++++++++++ mysql-test/t/subselect_sj2_mat.test | 20 ++++++++++++++++++++ sql/sql_select.cc | 5 ++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 202e6cc4b9e..835742a3ff4 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1579,3 +1579,25 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join (`test`.`t2`) where ((rand() < 0)) drop table t1,t2; set optimizer_switch=@save_optimizer_switch; +# +# mdev-12855: materialization of a semi-join subquery + ORDER BY +# +CREATE TABLE t1 (f1 varchar(8), KEY(f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('qux'),('foo'); +CREATE TABLE t2 (f2 varchar(8)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('bar'),('foo'),('qux'); +SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; +f1 +qux +explain SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index f1 f1 11 NULL 2 Using index +1 PRIMARY eq_ref distinct_key distinct_key 11 func 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test index 0f2892ae2dc..cfb6c8c2819 100644 --- a/mysql-test/t/subselect_sj2_mat.test +++ b/mysql-test/t/subselect_sj2_mat.test @@ -283,3 +283,23 @@ select * from t1 where (rand() < 0) and i in (select i from t2); drop table t1,t2; set optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # mdev-12855: materialization of a semi-join subquery + ORDER BY +--echo # + +CREATE TABLE t1 (f1 varchar(8), KEY(f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('qux'),('foo'); +CREATE TABLE t2 (f2 varchar(8)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('bar'),('foo'),('qux'); + +let $q= +SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; + +eval $q; +eval explain $q; + +DROP TABLE t1,t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f2be17f71d6..720c0a22681 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2759,8 +2759,11 @@ JOIN::exec() if (sort_table_cond) { if (!curr_table->select) + { if (!(curr_table->select= new SQL_SELECT)) DBUG_VOID_RETURN; + curr_table->select->head= curr_table->table; + } if (!curr_table->select->cond) curr_table->select->cond= sort_table_cond; else @@ -2846,7 +2849,7 @@ JOIN::exec() curr_join->select_limit, (select_options & OPTION_FOUND_ROWS ? HA_POS_ERROR : unit->select_limit_cnt), - curr_join->group_list ? TRUE : FALSE)) + curr_join->group_list ? FALSE : TRUE)) DBUG_VOID_RETURN; sortorder= curr_join->sortorder; if (curr_join->const_tables != curr_join->table_count && From 70b94c35d79eb9cef6963d535a5e8eb74a76198f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 11:27:36 +0200 Subject: [PATCH 07/47] cleanup: move common test into a function --- sql/sql_plugin.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2ec67a89746..0ceb3088c6a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -316,6 +316,12 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin); static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); +bool plugin_is_forced(struct st_plugin_int *p) +{ + return p->load_option == PLUGIN_FORCE || + p->load_option == PLUGIN_FORCE_PLUS_PERMANENT; +} + static void report_error(int where_to, uint error, ...) { va_list args; @@ -1657,8 +1663,7 @@ int plugin_init(int *argc, char **argv, int flags) while ((plugin_ptr= *(--reap))) { mysql_mutex_unlock(&LOCK_plugin); - if (plugin_ptr->load_option == PLUGIN_FORCE || - plugin_ptr->load_option == PLUGIN_FORCE_PLUS_PERMANENT) + if (plugin_is_forced(plugin_ptr)) reaped_mandatory_plugin= TRUE; plugin_deinitialize(plugin_ptr, true); mysql_mutex_lock(&LOCK_plugin); @@ -3505,8 +3510,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, plugin_dash.length + 1); strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, plugin_name_ptr, NullS); - if (tmp->load_option != PLUGIN_FORCE && - tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT) + if (!plugin_is_forced(tmp)) { /* support --skip-plugin-foo syntax */ options[0].name= plugin_name_ptr; @@ -3823,8 +3827,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, We adjust the default value to account for the hardcoded exceptions we have set for the federated and ndbcluster storage engines. */ - if (tmp->load_option != PLUGIN_FORCE && - tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT) + if (!plugin_is_forced(tmp)) opts[0].def_value= opts[1].def_value= plugin_load_option; error= handle_options(argc, &argv, opts, NULL); @@ -3840,8 +3843,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, Set plugin loading policy from option value. First element in the option list is always the option value. */ - if (tmp->load_option != PLUGIN_FORCE && - tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT) + if (!plugin_is_forced(tmp)) plugin_load_option= (enum_plugin_load_option) *(ulong*) opts[0].value; } From 918e47030b49867d449bd9aaa54257616d5ebe42 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 11:30:32 +0200 Subject: [PATCH 08/47] MDEV-13063 Server crashes in intern_plugin_lock or assertion `plugin_ptr->ref_count == 1' fails in plugin_init if a forced plugin is disabled (for any reason, e.g. invalid command-line option) - it's an error --- mysql-test/t/bootstrap.test | 6 ++++++ sql/sql_plugin.cc | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/bootstrap.test b/mysql-test/t/bootstrap.test index 405c24a6d74..2930d936830 100644 --- a/mysql-test/t/bootstrap.test +++ b/mysql-test/t/bootstrap.test @@ -60,4 +60,10 @@ SHOW VARIABLES LIKE 'have_innodb'; SELECT 'bug' as '' FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb' and SUPPORT='YES'; +# +# MDEV-13063 Server crashes in intern_plugin_lock or assertion `plugin_ptr->ref_count == 1' fails in plugin_init +# +--error 1 +--exec $MYSQLD_BOOTSTRAP_CMD --myisam_recover_options=NONE + --echo End of 5.5 tests diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0ceb3088c6a..75aca02990d 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1359,7 +1359,7 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin, if (options_only || state == PLUGIN_IS_DISABLED) { - ret= 0; + ret= !options_only && plugin_is_forced(plugin); goto err; } From 5cbbfe9f54f15a5281439dc21f22b599a69b5f87 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 00:33:11 +0200 Subject: [PATCH 09/47] cleanup: remove duplicate code --- sql/sql_partition.cc | 37 ++++++++++++++----------------------- sql/sql_priv.h | 2 +- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index b0fb38bf748..43f9797eb62 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1913,6 +1913,19 @@ static int add_subpartition_by(File fptr) return err + add_partition_by(fptr); } +static int add_name_string(File fptr, const char *name) +{ + int err; + String name_string("", 0, system_charset_info); + THD *thd= current_thd; + ulonglong save_options= thd->variables.option_bits; + thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; + append_identifier(thd, &name_string, name, strlen(name)); + thd->variables.option_bits= save_options; + err= add_string_object(fptr, &name_string); + return err; +} + static int add_part_field_list(File fptr, List field_list) { uint i, num_fields; @@ -1924,15 +1937,7 @@ static int add_part_field_list(File fptr, List field_list) err+= add_begin_parenthesis(fptr); while (i < num_fields) { - const char *field_str= part_it++; - String field_string("", 0, system_charset_info); - THD *thd= current_thd; - ulonglong save_options= thd->variables.option_bits; - thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; - append_identifier(thd, &field_string, field_str, - strlen(field_str)); - thd->variables.option_bits= save_options; - err+= add_string_object(fptr, &field_string); + err+= add_name_string(fptr, part_it++); if (i != (num_fields-1)) err+= add_comma(fptr); i++; @@ -1941,20 +1946,6 @@ static int add_part_field_list(File fptr, List field_list) return err; } -static int add_name_string(File fptr, const char *name) -{ - int err; - String name_string("", 0, system_charset_info); - THD *thd= current_thd; - ulonglong save_options= thd->variables.option_bits; - thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; - append_identifier(thd, &name_string, name, - strlen(name)); - thd->variables.option_bits= save_options; - err= add_string_object(fptr, &name_string); - return err; -} - static int add_int(File fptr, longlong number) { char buff[32]; diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 749ee245aa7..b5589cb4b22 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -121,7 +121,7 @@ #define OPTION_AUTOCOMMIT (1ULL << 8) // THD, user #define OPTION_BIG_SELECTS (1ULL << 9) // THD, user #define OPTION_LOG_OFF (1ULL << 10) // THD, user -#define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user, unused +#define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user #define TMP_TABLE_ALL_COLUMNS (1ULL << 12) // SELECT, intern #define OPTION_WARNINGS (1ULL << 13) // THD, user #define OPTION_AUTO_IS_NULL (1ULL << 14) // THD, user, binlog From c661b4d0fb38c103fc0b659a95e8552ea72574cf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 00:48:34 +0200 Subject: [PATCH 10/47] MDEV-13017 LOCK TABLE fails with irrelevant error while working with tables affected by ANSI_QUOTES --- mysql-test/suite/parts/r/quoting.result | 6 ++++++ mysql-test/suite/parts/t/quoting.test | 10 ++++++++++ sql/sql_partition.cc | 3 +++ 3 files changed, 19 insertions(+) create mode 100644 mysql-test/suite/parts/r/quoting.result create mode 100644 mysql-test/suite/parts/t/quoting.test diff --git a/mysql-test/suite/parts/r/quoting.result b/mysql-test/suite/parts/r/quoting.result new file mode 100644 index 00000000000..ba6a155e6ac --- /dev/null +++ b/mysql-test/suite/parts/r/quoting.result @@ -0,0 +1,6 @@ +set sql_mode=ansi_quotes; +create table t1 (i int) partition by range (i) (partition flush values less than maxvalue); +set sql_mode=default; +lock tables t1 read local; +unlock tables; +drop table t1; diff --git a/mysql-test/suite/parts/t/quoting.test b/mysql-test/suite/parts/t/quoting.test new file mode 100644 index 00000000000..297896fd9cf --- /dev/null +++ b/mysql-test/suite/parts/t/quoting.test @@ -0,0 +1,10 @@ +# +# MDEV-13017 LOCK TABLE fails with irrelevant error while working with tables affected by ANSI_QUOTES +# +--source include/have_partition.inc +set sql_mode=ansi_quotes; +create table t1 (i int) partition by range (i) (partition flush values less than maxvalue); +set sql_mode=default; +lock tables t1 read local; +unlock tables; +drop table t1; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 43f9797eb62..e6513fc7476 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1918,9 +1918,12 @@ static int add_name_string(File fptr, const char *name) int err; String name_string("", 0, system_charset_info); THD *thd= current_thd; + ulonglong save_sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_ANSI_QUOTES; ulonglong save_options= thd->variables.option_bits; thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; append_identifier(thd, &name_string, name, strlen(name)); + thd->variables.sql_mode= save_sql_mode; thd->variables.option_bits= save_options; err= add_string_object(fptr, &name_string); return err; From 2579b252dd0e38c75a854052873c9bf41043e43f Mon Sep 17 00:00:00 2001 From: =Ian Gilfillan Date: Thu, 15 Jun 2017 12:35:53 +0200 Subject: [PATCH 11/47] Update MariaDB Foundation sponsors --- CREDITS | 24 +++++++++++++----------- mysql-test/r/contributors.result | 2 ++ sql/contributors.h | 2 ++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CREDITS b/CREDITS index d352232ad2e..6288c2cdea4 100644 --- a/CREDITS +++ b/CREDITS @@ -4,17 +4,19 @@ organization registered in the USA. The current main sponsors of the MariaDB Foundation are: Alibaba Cloud https://intl.aliyun.com (2017) -Booking.com https://www.booking.com (2013 - 2017) -Development Bank of Singapore https://dbs.com (2016 - 2017) -MariaDB Corporation https://www.mariadb.com (2013 - 2017) -Visma https://visma.com (2015 - 2017) -Acronis http://acronis.com (2016 - 2017) -Nexedi https://www.nexedi.com (2016 - 2017) -Automattic https://automattic.com (2014 - 2017) -Tencent Game DBA http://tencentdba.com/about (2016 - 2017) -Tencent TDSQL http://tdsql.org/ (2016 - 2017) -Verkkokauppa.com https://www.verkkokauppa.com (2015 - 2017) -Virtuozzo https://virtuozzo.com (2016 - 2017) +Booking.com https://www.booking.com (2013) +Tencent Cloud https://cloud.tencent.com (2017) +Development Bank of Singapore https://dbs.com (2016) +IBM https://www.ibm.com (2017) +MariaDB Corporation https://www.mariadb.com (2013) +Visma https://visma.com (2015) +Acronis http://acronis.com (2016) +Nexedi https://www.nexedi.com (2016) +Automattic https://automattic.com (2014) +Tencent Game DBA http://tencentdba.com/about (2016) +Tencent TDSQL http://tdsql.org (2016) +Verkkokauppa.com https://www.verkkokauppa.com (2015) +Virtuozzo https://virtuozzo.com (2016) For a full list of sponsors, see https://mariadb.org/about/supporters/ diff --git a/mysql-test/r/contributors.result b/mysql-test/r/contributors.result index 4a26d0f19dd..5d92184f191 100644 --- a/mysql-test/r/contributors.result +++ b/mysql-test/r/contributors.result @@ -2,9 +2,11 @@ SHOW CONTRIBUTORS; Name Location Comment Booking.com https://www.booking.com Founding member, Platinum Sponsor of the MariaDB Foundation Alibaba Cloud https://intl.aliyun.com Platinum Sponsor of the MariaDB Foundation +Tencent Cloud https://cloud.tencent.com Platinum Sponsor of the MariaDB Foundation MariaDB Corporation https://mariadb.com Founding member, Gold Sponsor of the MariaDB Foundation Visma https://visma.com Gold Sponsor of the MariaDB Foundation DBS https://dbs.com Gold Sponsor of the MariaDB Foundation +IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation Nexedi https://www.nexedi.com Silver Sponsor of the MariaDB Foundation Acronis http://www.acronis.com Silver Sponsor of the MariaDB Foundation Auttomattic https://automattic.com Bronze Sponsor of the MariaDB Foundation diff --git a/sql/contributors.h b/sql/contributors.h index 3a771e2b493..88a4a088acf 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -39,9 +39,11 @@ struct show_table_contributors_st show_table_contributors[]= { /* MariaDB foundation sponsors, in contribution, size , time order */ {"Booking.com", "https://www.booking.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"}, {"Alibaba Cloud", "https://intl.aliyun.com", "Platinum Sponsor of the MariaDB Foundation"}, + {"Tencent Cloud", "https://cloud.tencent.com", "Platinum Sponsor of the MariaDB Foundation"}, {"MariaDB Corporation", "https://mariadb.com", "Founding member, Gold Sponsor of the MariaDB Foundation"}, {"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"}, {"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"}, + {"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"}, {"Nexedi", "https://www.nexedi.com", "Silver Sponsor of the MariaDB Foundation"}, {"Acronis", "http://www.acronis.com", "Silver Sponsor of the MariaDB Foundation"}, {"Auttomattic", "https://automattic.com", "Bronze Sponsor of the MariaDB Foundation"}, From 34da3be8a832306410ddb42006f8a067d38127be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 22 May 2017 13:38:26 +0300 Subject: [PATCH 12/47] MDEV-10463: Granted as a whole to roles, databases are not show in SHOW DATABASES The problem lies in not checking role privileges as well during SHOW DATABASES command. This problem is also apparent for SHOW CREATE DATABASE command. Other SHOW COMMANDS make use of check_access, which in turn makes use of acl_get for both priv_user and priv_role parts, which allows them to function correctly. --- .../roles/show_create_database-10463.result | 65 +++++++++++++++++++ .../roles/show_create_database-10463.test | 55 ++++++++++++++++ sql/sql_show.cc | 15 +++-- 3 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/roles/show_create_database-10463.result create mode 100644 mysql-test/suite/roles/show_create_database-10463.test diff --git a/mysql-test/suite/roles/show_create_database-10463.result b/mysql-test/suite/roles/show_create_database-10463.result new file mode 100644 index 00000000000..1bf14933966 --- /dev/null +++ b/mysql-test/suite/roles/show_create_database-10463.result @@ -0,0 +1,65 @@ +drop database if exists db; +Warnings: +Note 1008 Can't drop database 'db'; database doesn't exist +create role r1; +create user beep@'%'; +create database db; +create table db.t1 (i int); +create table db.t2 (b int); +grant select on db.* to r1; +grant r1 to beep@'%'; +show databases; +Database +information_schema +test +show create database db; +ERROR 42000: Access denied for user 'beep'@'localhost' to database 'db' +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; +table_schema table_name +set role r1; +show databases; +Database +db +information_schema +test +show create database db; +Database Create Database +db CREATE DATABASE `db` /*!40100 DEFAULT CHARACTER SET latin1 */ +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; +table_schema table_name +db t1 +db t2 +create role r2; +create user beep2@'%'; +grant update on db.* to r2; +grant r2 to beep2; +show databases; +Database +information_schema +test +show create database db; +ERROR 42000: Access denied for user 'beep2'@'localhost' to database 'db' +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; +table_schema table_name +set role r2; +show databases; +Database +db +information_schema +test +show create database db; +Database Create Database +db CREATE DATABASE `db` /*!40100 DEFAULT CHARACTER SET latin1 */ +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; +table_schema table_name +db t1 +db t2 +drop database db; +drop role r1; +drop user beep; +drop role r2; +drop user beep2; diff --git a/mysql-test/suite/roles/show_create_database-10463.test b/mysql-test/suite/roles/show_create_database-10463.test new file mode 100644 index 00000000000..2d921629c10 --- /dev/null +++ b/mysql-test/suite/roles/show_create_database-10463.test @@ -0,0 +1,55 @@ +source include/not_embedded.inc; + +drop database if exists db; + +create role r1; +create user beep@'%'; + +create database db; +create table db.t1 (i int); +create table db.t2 (b int); +grant select on db.* to r1; +grant r1 to beep@'%'; + +--connect (con1,localhost,beep,,) +show databases; +--error ER_DBACCESS_DENIED_ERROR +show create database db; +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; + +set role r1; +show databases; +show create database db; +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; + + +connection default; +create role r2; +create user beep2@'%'; + +grant update on db.* to r2; +grant r2 to beep2; +--connect (con2,localhost,beep2,,) +show databases; +--error ER_DBACCESS_DENIED_ERROR +show create database db; +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; + +set role r2; +show databases; + +show create database db; +select table_schema, table_name from information_schema.tables +where table_schema = 'db'; + + +connection default; + +drop database db; +drop role r1; +drop user beep; +drop role r2; +drop user beep2; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3f161fb8aec..9a743388149 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1167,8 +1167,13 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, if (test_all_bits(sctx->master_access, DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname->str, 0) | - sctx->master_access); + { + db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname->str, 0) | + sctx->master_access; + if (sctx->priv_role[0]) + db_access|= acl_get("", "", sctx->priv_role, dbname->str, 0); + } + if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname->str)) { status_var_increment(thd->status_var.access_denied_errors); @@ -5118,8 +5123,10 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) } #ifndef NO_EMBEDDED_ACCESS_CHECKS if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0) || - !check_grant_db(thd, db_name->str)) + acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, false) || + (sctx->priv_role[0] ? + acl_get("", "", sctx->priv_role, db_name->str, false) : 0) || + !check_grant_db(thd, db_name->str)) #endif { load_db_opt_by_name(thd, db_name->str, &create); From f0ad93403f4f39873618759585ca765169ecf000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 22 May 2017 17:06:01 +0300 Subject: [PATCH 13/47] MDEV-12666: CURRENT_ROLE() and DATABASE() does not work in a view The problem lies in how CURRENT_ROLE is defined. The Item_func_current_role inherits from Item_func_sysconst, which defines a safe_charset_converter to be a const_charset_converter. During view creation, if there is no role previously set, the current_role() function returns NULL. This is captured on item instantiation and the const_charset_converter call subsequently returns an Item_null. In turn, the function is replaced with Item_null and the view is then created with an Item_null instead of Item_func_current_role. Without this patch, the first SHOW CREATE VIEW from the testcase would have a where clause of WHERE role_name = NULL, while the second SHOW CREATE VIEW would show a correctly created view. The same applies for the DATABASE function, as it can change as well. There is an additional problem with CURRENT_ROLE() when used in a prepared statement. During prepared statement creation we used to set the string_value of the function to the current role as well as the null_value flag. During execution, if CURRENT_ROLE was not null, the null_value flag was never set to not-null during fix_fields. Item_func_current_user however can never be NULL so it did not show this problem in a view before. At the same time, the CURRENT_USER() can not be changed between prepared statement execution and creation so the implementation where the value is stored during fix_fields is sufficient. Note also that DATABASE() function behaves differently during prepared statements. See bug 25843 for details or commit 7e0ad09edff587dadc3e9855fc81e1b7de8f2199 --- mysql-test/r/view.result | 62 +++++++++++ .../roles/current_role_view-12666.result | 103 ++++++++++++++++++ .../suite/roles/current_role_view-12666.test | 102 +++++++++++++++++ mysql-test/t/view.test | 49 +++++++++ sql/item.cc | 1 + sql/item.h | 2 +- sql/item_strfunc.cc | 27 ++++- sql/item_strfunc.h | 8 +- 8 files changed, 345 insertions(+), 9 deletions(-) create mode 100644 mysql-test/suite/roles/current_role_view-12666.result create mode 100644 mysql-test/suite/roles/current_role_view-12666.test diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d6da2a03b46..30c3aaba36e 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5944,6 +5944,68 @@ use_case_id InitialDeadline 10 2015-12-18 drop view v1; drop table t1; +# +# MDEV-12666: CURRENT_ROLE() and DATABASE() does not work in a view +# +# DATABASE() fails only when the initial view creation features a NULL +# default database. +# +# CREATE, USE and DROP database so that we have no "default" database. +# +CREATE DATABASE temporary; +USE temporary; +DROP DATABASE temporary; +SELECT DATABASE(); +DATABASE() +NULL +CREATE VIEW test.v_no_db AS SELECT DATABASE() = 'temporary_two'; +SHOW CREATE VIEW test.v_no_db; +View Create View character_set_client collation_connection +v_no_db CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v_no_db` AS select (database() = 'temporary_two') AS `DATABASE() = 'temporary_two'` latin1 latin1_swedish_ci +PREPARE prepared_no_database FROM "SELECT DATABASE() = 'temporary_two'"; +# +# All statements should return NULL +# +EXECUTE prepared_no_database; +DATABASE() = 'temporary_two' +NULL +SELECT DATABASE() = 'temporary_two'; +DATABASE() = 'temporary_two' +NULL +SELECT * FROM test.v_no_db; +DATABASE() = 'temporary_two' +NULL +CREATE DATABASE temporary_two; +USE temporary_two; +CREATE VIEW test.v_with_db AS SELECT DATABASE() = 'temporary_two'; +PREPARE prepared_with_database FROM "SELECT DATABASE() = 'temporary_two'"; +# +# All statements should return 1; +# +SELECT DATABASE() = 'temporary_two'; +DATABASE() = 'temporary_two' +1 +SELECT * FROM test.v_no_db; +DATABASE() = 'temporary_two' +1 +SELECT * FROM test.v_with_db; +DATABASE() = 'temporary_two' +1 +EXECUTE prepared_with_database; +DATABASE() = 'temporary_two' +1 +# +# Prepared statements maintain default database to be the same +# during on creation so this should return NULL still. +# See MySQL bug #25843 +# +EXECUTE prepared_no_database; +DATABASE() = 'temporary_two' +NULL +DROP DATABASE temporary_two; +DROP VIEW test.v_no_db; +DROP VIEW test.v_with_db; +USE test; # ----------------------------------------------------------------- # -- End of 10.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/suite/roles/current_role_view-12666.result b/mysql-test/suite/roles/current_role_view-12666.result new file mode 100644 index 00000000000..1d14593be4b --- /dev/null +++ b/mysql-test/suite/roles/current_role_view-12666.result @@ -0,0 +1,103 @@ +CREATE USER has_role@'localhost'; +GRANT ALL PRIVILEGES ON *.* TO has_role@'localhost'; +CREATE ROLE test_role; +GRANT test_role TO has_role@'localhost'; +CREATE USER no_role@'localhost'; +GRANT ALL PRIVILEGES ON *.* TO no_role@'localhost'; +CREATE TABLE view_role_test ( +id int primary key, +role_name varchar(50) +); +INSERT INTO view_role_test VALUES (1, 'test_role'); +# +# Use the same logic for stored procedures. +# +PREPARE prepared_no_current_role FROM "SELECT * from view_role_test WHERE role_name = CURRENT_ROLE()"; +# +# Creating a view with no CURRENT_ROLE() set and one with CURRENT_ROLE() +# set. Both should produce the same SHOW CREATE VIEW output. +# +CREATE +DEFINER = no_role@localhost +SQL SECURITY INVOKER +VIEW v_view_role_test_no_current_role +AS +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +SHOW CREATE VIEW v_view_role_test_no_current_role; +View Create View character_set_client collation_connection +v_view_role_test_no_current_role CREATE ALGORITHM=UNDEFINED DEFINER=`no_role`@`localhost` SQL SECURITY INVOKER VIEW `v_view_role_test_no_current_role` AS select `view_role_test`.`id` AS `id`,`view_role_test`.`role_name` AS `role_name` from `view_role_test` where (`view_role_test`.`role_name` = current_role()) latin1 latin1_swedish_ci +# +# No values should be returned +# +EXECUTE prepared_no_current_role; +id role_name +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +id role_name +SELECT * FROM v_view_role_test_no_current_role; +id role_name +# +# Now let's set the role. Create identical views as before. See if +# their behaviour is different. It should not be. +# +SET ROLE test_role; +SELECT CURRENT_USER(); +CURRENT_USER() +root@localhost +SELECT CURRENT_ROLE(); +CURRENT_ROLE() +test_role +# +# Create the VIEW and prepared Statement with a CURRENT_ROLE() set. +# +CREATE +DEFINER = no_role@localhost +SQL SECURITY INVOKER +VIEW v_view_role_test_with_current_role +AS +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +PREPARE prepared_with_current_role FROM "SELECT * from view_role_test WHERE role_name = CURRENT_ROLE()"; +SHOW CREATE VIEW v_view_role_test_with_current_role; +View Create View character_set_client collation_connection +v_view_role_test_with_current_role CREATE ALGORITHM=UNDEFINED DEFINER=`no_role`@`localhost` SQL SECURITY INVOKER VIEW `v_view_role_test_with_current_role` AS select `view_role_test`.`id` AS `id`,`view_role_test`.`role_name` AS `role_name` from `view_role_test` where (`view_role_test`.`role_name` = current_role()) latin1 latin1_swedish_ci +# +# Values should be returned for all select statements as we do have +# a CURRENT_ROLE() active; +# +EXECUTE prepared_no_current_role; +id role_name +1 test_role +EXECUTE prepared_with_current_role; +id role_name +1 test_role +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +id role_name +1 test_role +SELECT * FROM v_view_role_test_no_current_role; +id role_name +1 test_role +SELECT * FROM v_view_role_test_with_current_role; +id role_name +1 test_role +SET ROLE NONE; +# +# No values should be returned for all select statements as we do not have +# a CURRENT_ROLE() active; +# +EXECUTE prepared_no_current_role; +id role_name +EXECUTE prepared_with_current_role; +id role_name +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +id role_name +SELECT * FROM v_view_role_test_no_current_role; +id role_name +SELECT * FROM v_view_role_test_with_current_role; +id role_name +DROP USER has_role@'localhost'; +DROP USER no_role@'localhost'; +DROP ROLE test_role; +DROP table view_role_test; +DROP VIEW v_view_role_test_no_current_role; +DROP VIEW v_view_role_test_with_current_role; +DROP PREPARE prepared_no_current_role; +DROP PREPARE prepared_with_current_role; diff --git a/mysql-test/suite/roles/current_role_view-12666.test b/mysql-test/suite/roles/current_role_view-12666.test new file mode 100644 index 00000000000..32039ffef07 --- /dev/null +++ b/mysql-test/suite/roles/current_role_view-12666.test @@ -0,0 +1,102 @@ +# +# MDEV-12666 CURRENT_ROLE() does not work in a view +# +--source include/not_embedded.inc + +CREATE USER has_role@'localhost'; +GRANT ALL PRIVILEGES ON *.* TO has_role@'localhost'; + +CREATE ROLE test_role; +GRANT test_role TO has_role@'localhost'; + +CREATE USER no_role@'localhost'; +GRANT ALL PRIVILEGES ON *.* TO no_role@'localhost'; + +CREATE TABLE view_role_test ( + id int primary key, + role_name varchar(50) + ); + +INSERT INTO view_role_test VALUES (1, 'test_role'); + +--echo # +--echo # Use the same logic for stored procedures. +--echo # +PREPARE prepared_no_current_role FROM "SELECT * from view_role_test WHERE role_name = CURRENT_ROLE()"; + +--echo # +--echo # Creating a view with no CURRENT_ROLE() set and one with CURRENT_ROLE() +--echo # set. Both should produce the same SHOW CREATE VIEW output. +--echo # +CREATE +DEFINER = no_role@localhost +SQL SECURITY INVOKER +VIEW v_view_role_test_no_current_role +AS +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); + +SHOW CREATE VIEW v_view_role_test_no_current_role; + + +--echo # +--echo # No values should be returned +--echo # +EXECUTE prepared_no_current_role; +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +SELECT * FROM v_view_role_test_no_current_role; + +--echo # +--echo # Now let's set the role. Create identical views as before. See if +--echo # their behaviour is different. It should not be. +--echo # +SET ROLE test_role; + +SELECT CURRENT_USER(); +SELECT CURRENT_ROLE(); + +--echo # +--echo # Create the VIEW and prepared Statement with a CURRENT_ROLE() set. +--echo # +CREATE +DEFINER = no_role@localhost +SQL SECURITY INVOKER +VIEW v_view_role_test_with_current_role +AS +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); + +PREPARE prepared_with_current_role FROM "SELECT * from view_role_test WHERE role_name = CURRENT_ROLE()"; + +SHOW CREATE VIEW v_view_role_test_with_current_role; + + +--echo # +--echo # Values should be returned for all select statements as we do have +--echo # a CURRENT_ROLE() active; +--echo # +EXECUTE prepared_no_current_role; +EXECUTE prepared_with_current_role; +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +SELECT * FROM v_view_role_test_no_current_role; +SELECT * FROM v_view_role_test_with_current_role; + +SET ROLE NONE; +--echo # +--echo # No values should be returned for all select statements as we do not have +--echo # a CURRENT_ROLE() active; +--echo # +EXECUTE prepared_no_current_role; +EXECUTE prepared_with_current_role; +SELECT * FROM view_role_test WHERE role_name = CURRENT_ROLE(); +SELECT * FROM v_view_role_test_no_current_role; +SELECT * FROM v_view_role_test_with_current_role; + + +DROP USER has_role@'localhost'; +DROP USER no_role@'localhost'; +DROP ROLE test_role; + +DROP table view_role_test; +DROP VIEW v_view_role_test_no_current_role; +DROP VIEW v_view_role_test_with_current_role; +DROP PREPARE prepared_no_current_role; +DROP PREPARE prepared_with_current_role; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 89a8e0c9ffc..db48e1a7661 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5814,6 +5814,55 @@ SELECT * FROM v1 where use_case_id = 10; drop view v1; drop table t1; +--echo # +--echo # MDEV-12666: CURRENT_ROLE() and DATABASE() does not work in a view +--echo # +--echo # DATABASE() fails only when the initial view creation features a NULL +--echo # default database. +--echo # +--echo # CREATE, USE and DROP database so that we have no "default" database. +--echo # +CREATE DATABASE temporary; +USE temporary; +DROP DATABASE temporary; +SELECT DATABASE(); + +CREATE VIEW test.v_no_db AS SELECT DATABASE() = 'temporary_two'; +SHOW CREATE VIEW test.v_no_db; +PREPARE prepared_no_database FROM "SELECT DATABASE() = 'temporary_two'"; + +--echo # +--echo # All statements should return NULL +--echo # +EXECUTE prepared_no_database; +SELECT DATABASE() = 'temporary_two'; +SELECT * FROM test.v_no_db; + +CREATE DATABASE temporary_two; +USE temporary_two; +CREATE VIEW test.v_with_db AS SELECT DATABASE() = 'temporary_two'; +PREPARE prepared_with_database FROM "SELECT DATABASE() = 'temporary_two'"; + +--echo # +--echo # All statements should return 1; +--echo # +SELECT DATABASE() = 'temporary_two'; +SELECT * FROM test.v_no_db; +SELECT * FROM test.v_with_db; +EXECUTE prepared_with_database; + +--echo # +--echo # Prepared statements maintain default database to be the same +--echo # during on creation so this should return NULL still. +--echo # See MySQL bug #25843 +--echo # +EXECUTE prepared_no_database; + +DROP DATABASE temporary_two; +DROP VIEW test.v_no_db; +DROP VIEW test.v_with_db; +USE test; + --echo # ----------------------------------------------------------------- --echo # -- End of 10.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.cc b/sql/item.cc index 4ce8396f71e..77b6ff5b82d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1263,6 +1263,7 @@ Item *Item::const_charset_converter(CHARSET_INFO *tocs, DBUG_ASSERT(fixed); StringBuffer<64>tmp; String *s= val_str(&tmp); + if (!s) return new Item_null((char *) func_name, tocs); diff --git a/sql/item.h b/sql/item.h index 4d33a0eb6c1..28a6649b9b1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1476,7 +1476,7 @@ public: virtual Item *expr_cache_insert_transformer(uchar *thd_arg) { return this; } virtual bool expr_cache_is_needed(THD *) { return FALSE; } virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) + bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const { /* This will return "true" if conversion happens: diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7cd712cc5e1..08b9ded80f5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2344,6 +2344,7 @@ String *Item_func_database::val_str(String *str) } else str->copy(thd->db, thd->db_length, system_charset_info); + null_value= 0; return str; } @@ -2378,6 +2379,28 @@ bool Item_func_user::init(const char *user, const char *host) } +Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs) +{ + /* + During view or prepared statement creation, the item should not + make use of const_charset_converter as it would imply substitution + with constant items which is not correct. Functions can have different + values during view creation and view execution based on context. + + Return the identical item during view creation and prepare. + */ + if (!Item_func_sysconst::const_item()) + return this; + return const_charset_converter(tocs, true, fully_qualified_func_name()); +} + +bool Item_func_sysconst::const_item() const +{ + if (current_thd->lex->is_ps_or_view_context_analysis()) + return false; + return true; +} + bool Item_func_user::fix_fields(THD *thd, Item **ref) { return (Item_func_sysconst::fix_fields(thd, ref) || @@ -2403,21 +2426,19 @@ bool Item_func_current_role::fix_fields(THD *thd, Item **ref) Security_context *ctx= context->security_ctx ? context->security_ctx : thd->security_ctx; - if (ctx->priv_role[0]) { if (str_value.copy(ctx->priv_role, strlen(ctx->priv_role), system_charset_info)) return 1; - str_value.mark_as_const(); + null_value= maybe_null= 0; return 0; } null_value= maybe_null= 1; return 0; } - void Item_func_soundex::fix_length_and_dec() { uint32 char_length= args[0]->max_char_length(); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2886cb68f9b..78989e9f517 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -542,10 +542,7 @@ class Item_func_sysconst :public Item_str_func public: Item_func_sysconst() { collation.set(system_charset_info,DERIVATION_SYSCONST); } - Item *safe_charset_converter(CHARSET_INFO *tocs) - { - return const_charset_converter(tocs, true, fully_qualified_func_name()); - } + Item *safe_charset_converter(CHARSET_INFO *tocs); /* Used to create correct Item name in new converted item in safe_charset_converter, return string representation of this function @@ -557,6 +554,7 @@ public: return trace_unsupported_by_check_vcol_func_processor( fully_qualified_func_name()); } + bool const_item() const; }; @@ -635,7 +633,7 @@ public: String *val_str(String *) { DBUG_ASSERT(fixed == 1); - return (null_value ? 0 : &str_value); + return null_value ? NULL : &str_value; } }; From c7141fa75df91ae4c2a1214283111eeb1c2eda11 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 15 Jun 2017 14:41:59 +0200 Subject: [PATCH 14/47] MDEV-13002 mysqltest regex replace results in incorrect result regex didn't replace lines that were split by 16K chunk reads. --- client/mysqltest.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index b22959677d0..4de40953f7d 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1698,12 +1698,22 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename) { int fd; size_t len; - char buff[16384]; + char *buff; if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0) return 1; - while((len= my_read(fd, (uchar*)&buff, - sizeof(buff)-1, MYF(0))) > 0) + + len= (size_t) my_seek(fd, 0, SEEK_END, MYF(0)); + my_seek(fd, 0, SEEK_SET, MYF(0)); + if (len == (size_t)MY_FILEPOS_ERROR || + !(buff= (char*)my_malloc(len + 1, MYF(0)))) + { + my_close(fd, MYF(0)); + return 1; + } + len= my_read(fd, (uchar*)buff, len, MYF(0)); + my_close(fd, MYF(0)); + { char *p= buff, *start= buff,*end=buff+len; while (p < end) @@ -1726,7 +1736,7 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename) *p= 0; replace_dynstr_append_mem(ds, start, p-start); } - my_close(fd, MYF(0)); + my_free(buff); return 0; } From e548e2184bed04478ba1fe5107da817bc768d023 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 26 Mar 2017 16:00:35 +1100 Subject: [PATCH 15/47] Use CPACK_RPM_FILE_NAME="RPM-DEFAULT" This has been implemented in for cmake-3.6 to match distro version of what the filename should look like. Thanks to Domen Vranka for the suggestion. --- cmake/cpack_rpm.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 5789eb7694a..c3ec731144b 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -28,7 +28,11 @@ SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts Common Client SharedLibraries) SET(CPACK_RPM_PACKAGE_NAME "MariaDB") -SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") +IF(CMAKE_VERSION VERSION_LESS "3.6.0") + SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") +ELSE() + SET(CPACK_RPM_FILE_NAME "RPM-DEFAULT") +ENDIF() SET(CPACK_RPM_PACKAGE_RELEASE "1%{?dist}") SET(CPACK_RPM_PACKAGE_LICENSE "GPLv2") From 48429359d6bb6382245f1949c458f8219996aa4a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 16 Jun 2017 11:34:59 +0200 Subject: [PATCH 16/47] MDEV-4646 No mysqld-debug or debuginfo in MariaDB-Server RPM --- cmake/cpack_rpm.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index c3ec731144b..4e9410306a8 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -32,6 +32,7 @@ IF(CMAKE_VERSION VERSION_LESS "3.6.0") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") ELSE() SET(CPACK_RPM_FILE_NAME "RPM-DEFAULT") + SET(CPACK_RPM_DEBUGINFO_PACKAGE ON) ENDIF() SET(CPACK_RPM_PACKAGE_RELEASE "1%{?dist}") From 3a37afec293e36e51b83a9bd338ad5f74e7f63c0 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 19 Jun 2017 12:45:32 +0400 Subject: [PATCH 17/47] MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery The bug happens because of a combination of unfortunate circumstances: 1. Arguments args[0] and args[2] of Item_func_concat point recursively (through Item_direct_view_ref's) to the same Item_func_conv_charset. Both args[0]->args[0]->ref[0] and args[2]->args[0]->ref[0] refer to this Item_func_conv_charset. 2. When Item_func_concat::args[0]->val_str() is called, Item_func_conv_charset::val_str() writes its result to Item_func_conc_charset::tmp_value. 3. Then, for optimization purposes (to avoid copying), Item_func_substr::val_str() initializes Item_func_substr::tmp_value to point to the buffer fragment owned by Item_func_conv_charset::tmp_value Item_func_substr::tmp_value is returned as a result of Item_func_concat::args[0]->val_str(). 4. Due to optimization to avoid memory reallocs, Item_func_concat::val_str() remembers the result of args[0]->val_str() in "res" and further uses "res" to collect the return value. 5. When Item_func_concat::args[2]->val_str() is called, Item_func_conv_charset::tmp_value gets overwritten (see #1), which effectively overwrites args[0]'s Item_func_substr::tmp_value (see #3), which effectively overwrites "res" (see #4). This patch does the following: a. Changes Item_func_conv_charset::val_str(String *str) to use tmp_value and str the other way around. After this change tmp_value is used to store a temporary result, while str is used to return the value. The fixes the second problem (without SUBSTR): SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; As Item_func_concat::val_str() supplies two different buffers when calling args[0]->val_str() and args[2]->val_str(), in the new reduction the result created during args[0]->val_str() does not get overwritten by args[2]->val_str(). b. Fixing the same problem in val_str() for similar classes Item_func_to_base64 Item_func_from_base64 Item_func_weight_string Item_func_hex Item_func_unhex Item_func_quote Item_func_compress Item_func_uncompress Item_func_des_encrypt Item_func_des_decrypt Item_func_conv_charset Item_func_reverse Item_func_soundex Item_func_aes_encrypt Item_func_aes_decrypt Item_func_buffer c. Fixing Item_func::val_str_from_val_str_ascii() the same way. Now Item_str_ascii_func::ascii_buff is used for temporary value, while the parameter passed to val_str() is used to return the result. This fixes the same problem when conversion (from ASCII to e.g. UCS2) takes place. See the ctype_ucs.test for example queries that returned wrong results before the fix. d. Some Item_func descendand classes had temporary String buffers (tmp_value and tmp_str), but did not really use them. Removing these temporary buffers from: Item_func_decode_histogram Item_func_format Item_func_binlog_gtid_pos Item_func_spatial_collection: e. Removing Item_func_buffer::tmp_value, because it's not used any more. f. Renaming Item_func_[un]compress::buffer to "tmp_value", for consistency with other classes. Note, this patch does not fix the following classes (although they have a similar problem): Item_str_conv Item_func_make_set Item_char_typecast They have a complex implementations and simple swapping between "tmp_value" and "str" won't work. These classes will be fixed separately. --- mysql-test/r/ctype_ucs.result | 17 +++ mysql-test/r/func_concat.result | 113 +++++++++++++++++ mysql-test/r/func_crypt.result | 18 +++ mysql-test/r/gis.result | 18 +++ mysql-test/t/ctype_ucs.test | 16 +++ mysql-test/t/func_concat.test | 91 ++++++++++++++ mysql-test/t/func_crypt.test | 24 ++++ mysql-test/t/gis.test | 15 +++ sql/item.h | 33 +++-- sql/item_geofunc.cc | 2 +- sql/item_geofunc.h | 2 - sql/item_strfunc.cc | 211 +++++++++++++++++--------------- sql/item_strfunc.h | 8 +- 13 files changed, 438 insertions(+), 130 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 843b49c1f75..8c69745b12c 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -5552,5 +5552,22 @@ SELECT 'a','aa'; a aa a aa # +# MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +# +SET NAMES utf8, character_set_connection=ucs2; +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_utf8'derived_merge=on'; +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SET NAMES utf8, character_set_connection=ucs2; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT HEX(t) t2 FROM t1) sub; +c2 +616263646566676869-616263646566676869 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TO_BASE64(t) t2 FROM t1) sub; +c2 +YWJjZGVmZ2hp-YWJjZGVmZ2hp +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; +# # End of 10.0 tests # diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result index 925158ab129..b87ee7bfc52 100644 --- a/mysql-test/r/func_concat.result +++ b/mysql-test/r/func_concat.result @@ -149,3 +149,116 @@ CALL p1(); ########################################40100.000 DROP PROCEDURE p1; # End of 5.1 tests +# +# Start of 10.0 tests +# +# +# MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('1234567'); +SELECT CONCAT(SUBSTR(t2, 1, 3), SUBSTR(t2, 5)) c1, +CONCAT(SUBSTR(t2,1,3),'---',SUBSTR(t2,5)) c2 +FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +c1 c2 +123567 123---567 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +c2 +1234567-1234567 +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('1234567'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +c2 +1234567-1234567 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT REVERSE(t) t2 FROM t1) sub; +c2 +7654321-7654321 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT SOUNDEX(t) t2 FROM t1) sub; +c2 +- +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TO_BASE64(t) t2 FROM t1) sub; +c2 +MTIzNDU2Nw==-MTIzNDU2Nw== +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT WEIGHT_STRING(t) t2 FROM t1) sub; +c2 +1234567-1234567 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT HEX(t) t2 FROM t1) sub; +c2 +31323334353637-31323334353637 +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT QUOTE(t) t2 FROM t1) sub; +c2 +'1234567'-'1234567' +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES(TO_BASE64('abcdefghi')); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT FROM_BASE64(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES(HEX('abcdefghi')); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UNHEX(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(30) CHARSET latin1); +INSERT INTO t1 VALUES('test'); +SELECT LENGTH(CONCAT(t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +c2 +16 +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +c2 +33 +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +c2 +34 +SELECT LENGTH(CONCAT(t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +c2 +4 +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +c2 +9 +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +c2 +10 +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(64) CHARSET latin1); +INSERT INTO t1 VALUES('123456789'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT MD5(t) t2 FROM t1) sub; +c2 +25f9e794323b453885f5181f1b624d0b-25f9e794323b453885f5181f1b624d0b +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT FORMAT(t,2) t2 FROM t1) sub; +c2 +123,456,789.00-123,456,789.00 +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT INSERT(t,3,4,'xxx') t2 FROM t1) sub; +c2 +abxxxghi-abxxxghi +DROP TABLE t1; +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LEFT(t,10) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT RIGHT(t,10) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT SUBSTR(t,1,10) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LTRIM(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT RTRIM(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TRIM(t) t2 FROM t1) sub; +c2 +abcdefghi-abcdefghi +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result index 1eda56ac114..707e767ddf5 100644 --- a/mysql-test/r/func_crypt.result +++ b/mysql-test/r/func_crypt.result @@ -106,3 +106,21 @@ OLD_PASSWORD(c1) PASSWORD(c1) 77023ffe214c04ff *82E58A2C08AAFE72C8EB523069CD8ADB33F78F58 DROP TABLE t1; End of 5.0 tests +# +# Start of 10.0 tests +# +# +# MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT ENCRYPT(t,'aa') t2 FROM t1) sub; +c2 +aaHHlPHAM4sjs-aaHHlPHAM4sjs +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; +# +# End of 10.0 tests +# diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 2bd492008bc..f029542e717 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1641,5 +1641,23 @@ AsText(g) NULL POINT(1 1) # +# MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 (x INT, y INT); +INSERT INTO t1 VALUES(0,0); +SELECT LENGTH(t2) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +c2 +25 +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +c2 +51 +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +c2 +52 +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; +# # End 10.0 tests # diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 165d945944e..04156622ab2 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -923,6 +923,22 @@ SET NAMES utf8, character_set_connection=ucs2; SELECT 'a','aa'; +--echo # +--echo # MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +--echo # + +SET NAMES utf8, character_set_connection=ucs2; +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch=_utf8'derived_merge=on'; +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SET NAMES utf8, character_set_connection=ucs2; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT HEX(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TO_BASE64(t) t2 FROM t1) sub; +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; + + --echo # --echo # End of 10.0 tests --echo # diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test index e56d1121808..be573f494a2 100644 --- a/mysql-test/t/func_concat.test +++ b/mysql-test/t/func_concat.test @@ -145,3 +145,94 @@ CALL p1(); DROP PROCEDURE p1; --echo # End of 5.1 tests + + +--echo # +--echo # Start of 10.0 tests +--echo # + +--echo # +--echo # MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +--echo # + +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; + +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('1234567'); +SELECT CONCAT(SUBSTR(t2, 1, 3), SUBSTR(t2, 5)) c1, + CONCAT(SUBSTR(t2,1,3),'---',SUBSTR(t2,5)) c2 + FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +DROP TABLE t1; + +# Other functions affected by MDEV-10306 + +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('1234567'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT CONVERT(t USING latin1) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT REVERSE(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT SOUNDEX(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TO_BASE64(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT WEIGHT_STRING(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT HEX(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT QUOTE(t) t2 FROM t1) sub; +DROP TABLE t1; + +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES(TO_BASE64('abcdefghi')); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT FROM_BASE64(t) t2 FROM t1) sub; +DROP TABLE t1; + +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES(HEX('abcdefghi')); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT UNHEX(t) t2 FROM t1) sub; +DROP TABLE t1; + +CREATE TABLE t1 (t VARCHAR(30) CHARSET latin1); +INSERT INTO t1 VALUES('test'); +SELECT LENGTH(CONCAT(t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT AES_ENCRYPT(t,'x') t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT AES_DECRYPT(AES_ENCRYPT(t,'x'),'x') t2 FROM t1) sub; +DROP TABLE t1; + + +# Functions not affected by MDEV-10306 +# They only had an unused tmp_value, which was removed. + +CREATE TABLE t1 (t VARCHAR(64) CHARSET latin1); +INSERT INTO t1 VALUES('123456789'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT MD5(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT FORMAT(t,2) t2 FROM t1) sub; +DROP TABLE t1; + +# Functions not affected by MDEV-10306 +# They already use tmp_value only for internal purposes and +# return the result in the String passed to val_str() + +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT INSERT(t,3,4,'xxx') t2 FROM t1) sub; +DROP TABLE t1; + + +# Functions not affected by MDEV-10306 +# They use this code style: +# String *res= args[0]->val_str(str); +# tmp_value.set(*res, start, end); +# return &tmp_value; + +CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LEFT(t,10) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT RIGHT(t,10) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT SUBSTR(t,1,10) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT LTRIM(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT RTRIM(t) t2 FROM t1) sub; +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TRIM(t) t2 FROM t1) sub; +DROP TABLE t1; + +SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test index ca6e712f45c..785cc63d3f1 100644 --- a/mysql-test/t/func_crypt.test +++ b/mysql-test/t/func_crypt.test @@ -70,3 +70,27 @@ SELECT OLD_PASSWORD(c1), PASSWORD(c1) FROM t1; DROP TABLE t1; --echo End of 5.0 tests + + +--echo # +--echo # Start of 10.0 tests +--echo # + +--echo # +--echo # MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +--echo # + +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; +# ENCRYPT() is not affected by MDEV-10306 +# It already uses tmp_value only for internal purposes and +# returns the result in the String passed to val_str() +CREATE TABLE t1 (t VARCHAR(32) CHARSET latin1); +INSERT INTO t1 VALUES('abcdefghi'); +SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT ENCRYPT(t,'aa') t2 FROM t1) sub; +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # End of 10.0 tests +--echo # diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index f689902533a..fe7b8ff7383 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -1502,6 +1502,21 @@ DROP VIEW v1; --echo # SELECT AsText(g) FROM (SELECT NULL AS g UNION SELECT Point(1,1)) AS t1; +--echo # +--echo # MDEV-10306 Wrong results with combination of CONCAT, SUBSTR and CONVERT in subquery +--echo # + +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 (x INT, y INT); +INSERT INTO t1 VALUES(0,0); +SELECT LENGTH(t2) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'-',t2)) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +SELECT LENGTH(CONCAT(t2,'--',t2)) c2 FROM (SELECT ST_BUFFER(POINT(x,y), 0) t2 FROM t1) sub; +DROP TABLE t1; +SET optimizer_switch=@save_optimizer_switch; + + --echo # --echo # End 10.0 tests --echo # diff --git a/sql/item.h b/sql/item.h index 28a6649b9b1..f363950b9bc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -830,25 +830,20 @@ public: store return value of this method. NOTE - Buffer passed via argument should only be used if the item itself - doesn't have an own String buffer. In case when the item maintains - it's own string buffer, it's preferable to return it instead to - minimize number of mallocs/memcpys. - The caller of this method can modify returned string, but only in case - when it was allocated on heap, (is_alloced() is true). This allows - the caller to efficiently use a buffer allocated by a child without - having to allocate a buffer of it's own. The buffer, given to - val_str() as argument, belongs to the caller and is later used by the - caller at it's own choosing. - A few implications from the above: - - unless you return a string object which only points to your buffer - but doesn't manages it you should be ready that it will be - modified. - - even for not allocated strings (is_alloced() == false) the caller - can change charset (see Item_func_{typecast/binary}. XXX: is this - a bug? - - still you should try to minimize data copying and return internal - object whenever possible. + The caller can modify the returned String, if it's not marked + "const" (with the String::mark_as_const() method). That means that + if the item returns its own internal buffer (e.g. tmp_value), it + *must* be marked "const" [1]. So normally it's preferrable to + return the result value in the String, that was passed as an + argument. But, for example, SUBSTR() returns a String that simply + points into the buffer of SUBSTR()'s args[0]->val_str(). Such a + String is always "const", so it's ok to use tmp_value for that and + avoid reallocating/copying of the argument String. + + [1] consider SELECT CONCAT(f, ":", f) FROM (SELECT func() AS f); + here the return value of f() is used twice in the top-level + select, and if they share the same tmp_value buffer, modifying the + first one will implicitly modify the second too. RETURN In case of NULL value return 0 (NULL pointer) and set null_value flag diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 568a28e6465..a9e39ab717a 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1268,7 +1268,7 @@ String *Item_func_buffer::val_str(String *str_value) { DBUG_ENTER("Item_func_buffer::val_str"); DBUG_ASSERT(fixed == 1); - String *obj= args[0]->val_str(&tmp_value); + String *obj= args[0]->val_str(str_value); double dist= args[1]->val_real(); Geometry_buffer buffer; Geometry *g; diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 62d2198e221..d32edff599c 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -171,7 +171,6 @@ public: class Item_func_spatial_collection: public Item_geometry_func { - String tmp_value; enum Geometry::wkbType coll_type; enum Geometry::wkbType item_type; public: @@ -325,7 +324,6 @@ protected: Gcalc_result_receiver res_receiver; Gcalc_operation_reducer operation; - String tmp_value; public: Item_func_buffer(Item *obj, Item *distance): diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 08b9ded80f5..f559677051b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -73,8 +73,14 @@ size_t username_char_length= 80; Conversion happens only in case of "tricky" Item character set (e.g. UCS2). Normally conversion does not happen, and val_str_ascii() is immediately returned instead. + + No matter if conversion is needed or not needed, + the result is always returned in "str" (see MDEV-10306 why). + + @param [OUT] str - Store the result here + @param [IN] ascii_buffer - Use this temporary buffer to call val_str_ascii() */ -String *Item_func::val_str_from_val_str_ascii(String *str, String *str2) +String *Item_func::val_str_from_val_str_ascii(String *str, String *ascii_buffer) { DBUG_ASSERT(fixed == 1); @@ -86,19 +92,19 @@ String *Item_func::val_str_from_val_str_ascii(String *str, String *str2) return res; } - DBUG_ASSERT(str != str2); + DBUG_ASSERT(str != ascii_buffer); uint errors; - String *res= val_str_ascii(str); + String *res= val_str_ascii(ascii_buffer); if (!res) return 0; - if ((null_value= str2->copy(res->ptr(), res->length(), - &my_charset_latin1, collation.collation, - &errors))) + if ((null_value= str->copy(res->ptr(), res->length(), + &my_charset_latin1, collation.collation, + &errors))) return 0; - return str2; + return str; } @@ -368,12 +374,12 @@ void Item_func_sha2::fix_length_and_dec() /* Implementation of AES encryption routines */ -String *Item_func_aes_encrypt::val_str(String *str) +String *Item_func_aes_encrypt::val_str(String *str2) { DBUG_ASSERT(fixed == 1); char key_buff[80]; String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info); - String *sptr= args[0]->val_str(str); // String to encrypt + String *sptr= args[0]->val_str(&str_value); // String to encrypt String *key= args[1]->val_str(&tmp_key_value); // key int aes_length; if (sptr && key) // we need both arguments to be not NULL @@ -381,15 +387,15 @@ String *Item_func_aes_encrypt::val_str(String *str) null_value=0; aes_length=my_aes_get_size(sptr->length()); // Calculate result length - if (!str_value.alloc(aes_length)) // Ensure that memory is free + if (!str2->alloc(aes_length)) // Ensure that memory is free { // finally encrypt directly to allocated buffer. - if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str_value.ptr(), + if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str2->ptr(), key->ptr(), key->length()) == aes_length) { // We got the expected result length - str_value.length((uint) aes_length); - return &str_value; + str2->length((uint) aes_length); + return str2; } } } @@ -412,22 +418,22 @@ String *Item_func_aes_decrypt::val_str(String *str) String *sptr, *key; DBUG_ENTER("Item_func_aes_decrypt::val_str"); - sptr= args[0]->val_str(str); // String to decrypt + sptr= args[0]->val_str(&str_value); // String to decrypt key= args[1]->val_str(&tmp_key_value); // Key if (sptr && key) // Need to have both arguments not NULL { null_value=0; - if (!str_value.alloc(sptr->length())) // Ensure that memory is free + if (!str->alloc(sptr->length())) // Ensure that memory is free { // finally decrypt directly to allocated buffer. int length; length=my_aes_decrypt(sptr->ptr(), sptr->length(), - (char*) str_value.ptr(), + (char*) str->ptr(), key->ptr(), key->length()); if (length >= 0) // if we got correct data data { - str_value.length((uint) length); - DBUG_RETURN(&str_value); + str->length((uint) length); + DBUG_RETURN(str); } } } @@ -464,7 +470,7 @@ void Item_func_to_base64::fix_length_and_dec() String *Item_func_to_base64::val_str_ascii(String *str) { - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); bool too_long= false; int length; if (!res || @@ -472,7 +478,7 @@ String *Item_func_to_base64::val_str_ascii(String *str) (too_long= ((uint) (length= base64_needed_encoded_length((int) res->length())) > current_thd->variables.max_allowed_packet)) || - tmp_value.alloc((uint) length)) + str->alloc((uint) length)) { null_value= 1; // NULL input, too long input, or OOM. if (too_long) @@ -484,11 +490,11 @@ String *Item_func_to_base64::val_str_ascii(String *str) } return 0; } - base64_encode(res->ptr(), (int) res->length(), (char*) tmp_value.ptr()); + base64_encode(res->ptr(), (int) res->length(), (char*) str->ptr()); DBUG_ASSERT(length > 0); - tmp_value.length((uint) length - 1); // Without trailing '\0' + str->length((uint) length - 1); // Without trailing '\0' null_value= 0; - return &tmp_value; + return str; } @@ -509,7 +515,7 @@ void Item_func_from_base64::fix_length_and_dec() String *Item_func_from_base64::val_str(String *str) { - String *res= args[0]->val_str_ascii(str); + String *res= args[0]->val_str_ascii(&tmp_value); int length; const char *end_ptr; @@ -527,11 +533,11 @@ String *Item_func_from_base64::val_str(String *str) goto err; } - if (tmp_value.alloc((uint) length)) + if (str->alloc((uint) length)) goto err; if ((length= base64_decode(res->ptr(), (int) res->length(), - (char *) tmp_value.ptr(), &end_ptr, 0)) < 0 || + (char *) str->ptr(), &end_ptr, 0)) < 0 || end_ptr < res->ptr() + res->length()) { push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, @@ -540,9 +546,9 @@ String *Item_func_from_base64::val_str(String *str) goto err; } - tmp_value.length((uint) length); + str->length((uint) length); null_value= 0; - return &tmp_value; + return str; err: null_value= 1; // NULL input, too long input, OOM, or badly formed input return 0; @@ -797,7 +803,7 @@ String *Item_func_des_encrypt::val_str(String *str) struct st_des_keyschedule keyschedule; const char *append_str="********"; uint key_number, res_length, tail; - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); if ((null_value= args[0]->null_value)) return 0; // ENCRYPT(NULL) == NULL @@ -821,7 +827,7 @@ String *Item_func_des_encrypt::val_str(String *str) } else { - String *keystr=args[1]->val_str(&tmp_value); + String *keystr= args[1]->val_str(str); if (!keystr) goto error; key_number=127; // User key string @@ -853,23 +859,23 @@ String *Item_func_des_encrypt::val_str(String *str) tmp_arg.length(0); tmp_arg.append(res->ptr(), res->length()); code= ER_OUT_OF_RESOURCES; - if (tmp_arg.append(append_str, tail) || tmp_value.alloc(res_length+1)) + if (tmp_arg.append(append_str, tail) || str->alloc(res_length+1)) goto error; tmp_arg[res_length-1]=tail; // save extra length - tmp_value.realloc(res_length+1); - tmp_value.length(res_length+1); - tmp_value.set_charset(&my_charset_bin); - tmp_value[0]=(char) (128 | key_number); + str->realloc(res_length+1); + str->length(res_length+1); + str->set_charset(&my_charset_bin); + (*str)[0]=(char) (128 | key_number); // Real encryption bzero((char*) &ivec,sizeof(ivec)); DES_ede3_cbc_encrypt((const uchar*) (tmp_arg.ptr()), - (uchar*) (tmp_value.ptr()+1), + (uchar*) (str->ptr()+1), res_length, &keyschedule.ks1, &keyschedule.ks2, &keyschedule.ks3, &ivec, TRUE); - return &tmp_value; + return str; error: push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN, @@ -893,7 +899,7 @@ String *Item_func_des_decrypt::val_str(String *str) DES_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); uint length,tail; if ((null_value= args[0]->null_value)) @@ -917,7 +923,7 @@ String *Item_func_des_decrypt::val_str(String *str) else { // We make good 24-byte (168 bit) key from given plaintext key with MD5 - String *keystr=args[1]->val_str(&tmp_value); + String *keystr= args[1]->val_str(str); if (!keystr) goto error; @@ -932,23 +938,23 @@ String *Item_func_des_decrypt::val_str(String *str) DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3); } code= ER_OUT_OF_RESOURCES; - if (tmp_value.alloc(length-1)) + if (str->alloc(length-1)) goto error; bzero((char*) &ivec,sizeof(ivec)); DES_ede3_cbc_encrypt((const uchar*) res->ptr()+1, - (uchar*) (tmp_value.ptr()), + (uchar*) (str->ptr()), length-1, &keyschedule.ks1, &keyschedule.ks2, &keyschedule.ks3, &ivec, FALSE); /* Restore old length of key */ - if ((tail=(uint) (uchar) tmp_value[length-2]) > 8) + if ((tail=(uint) (uchar) (*str)[length-2]) > 8) goto wrong_key; // Wrong key - tmp_value.length(length-1-tail); - tmp_value.set_charset(&my_charset_bin); - return &tmp_value; + str->length(length-1-tail); + str->set_charset(&my_charset_bin); + return str; error: push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN, @@ -1136,25 +1142,26 @@ void Item_func_concat_ws::fix_length_and_dec() String *Item_func_reverse::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); - char *ptr, *end, *tmp; + String *res= args[0]->val_str(&tmp_value); + const char *ptr, *end; + char *tmp; if ((null_value=args[0]->null_value)) return 0; /* An empty string is a special case as the string pointer may be null */ if (!res->length()) return make_empty_result(); - if (tmp_value.alloced_length() < res->length() && - tmp_value.realloc(res->length())) + if (str->alloced_length() < res->length() && + str->realloc(res->length())) { null_value= 1; return 0; } - tmp_value.length(res->length()); - tmp_value.set_charset(res->charset()); - ptr= (char *) res->ptr(); - end= ptr + res->length(); - tmp= (char *) tmp_value.ptr() + tmp_value.length(); + str->length(res->length()); + str->set_charset(res->charset()); + ptr= res->ptr(); + end= res->end(); + tmp= (char *) str->end(); #ifdef USE_MB if (use_mb(res->charset())) { @@ -1178,7 +1185,7 @@ String *Item_func_reverse::val_str(String *str) while (ptr < end) *--tmp= *ptr++; } - return &tmp_value; + return str; } @@ -2446,7 +2453,6 @@ void Item_func_soundex::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); set_if_bigger(char_length, 4); fix_char_length(char_length); - tmp_value.set_charset(collation.collation); } @@ -2491,7 +2497,7 @@ static bool my_uni_isalpha(int wc) String *Item_func_soundex::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); char last_ch,ch; CHARSET_INFO *cs= collation.collation; my_wc_t wc; @@ -2501,10 +2507,11 @@ String *Item_func_soundex::val_str(String *str) if ((null_value= args[0]->null_value)) return 0; /* purecov: inspected */ - if (tmp_value.alloc(MY_MAX(res->length(), 4 * cs->mbminlen))) - return str; /* purecov: inspected */ - char *to= (char *) tmp_value.ptr(); - char *to_end= to + tmp_value.alloced_length(); + if (str->alloc(MY_MAX(res->length(), 4 * cs->mbminlen))) + return &tmp_value; /* purecov: inspected */ + str->set_charset(collation.collation); + char *to= (char *) str->ptr(); + char *to_end= to + str->alloced_length(); char *from= (char *) res->ptr(), *end= from + res->length(); for ( ; ; ) /* Skip pre-space */ @@ -2589,8 +2596,8 @@ String *Item_func_soundex::val_str(String *str) to+= nbytes; } - tmp_value.length((uint) (to-tmp_value.ptr())); - return &tmp_value; + str->length((uint) (to - str->ptr())); + return str; } @@ -3399,16 +3406,16 @@ String *Item_func_conv_charset::val_str(String *str) DBUG_ASSERT(fixed == 1); if (use_cached_value) return null_value ? 0 : &str_value; - String *arg= args[0]->val_str(str); + String *arg= args[0]->val_str(&tmp_value); uint dummy_errors; if (args[0]->null_value) { null_value=1; return 0; } - null_value= tmp_value.copy(arg->ptr(), arg->length(), arg->charset(), - conv_charset, &dummy_errors); - return null_value ? 0 : check_well_formed_result(&tmp_value); + null_value= str->copy(arg->ptr(), arg->length(), arg->charset(), + conv_charset, &dummy_errors); + return null_value ? 0 : check_well_formed_result(str); } void Item_func_conv_charset::fix_length_and_dec() @@ -3551,7 +3558,7 @@ String *Item_func_weight_string::val_str(String *str) DBUG_ASSERT(fixed == 1); if (args[0]->result_type() != STRING_RESULT || - !(res= args[0]->val_str(str))) + !(res= args[0]->val_str(&tmp_value))) goto nl; /* @@ -3598,19 +3605,19 @@ String *Item_func_weight_string::val_str(String *str) goto nl; } - if (tmp_value.alloc(tmp_length)) + if (str->alloc(tmp_length)) goto nl; frm_length= cs->coll->strnxfrm(cs, - (uchar *) tmp_value.ptr(), tmp_length, + (uchar *) str->ptr(), tmp_length, nweights ? nweights : tmp_length, (const uchar *) res->ptr(), res->length(), flags); DBUG_ASSERT(frm_length <= tmp_length); - tmp_value.length(frm_length); + str->length(frm_length); null_value= 0; - return &tmp_value; + return str; nl: null_value= 1; @@ -3651,18 +3658,18 @@ String *Item_func_hex::val_str_ascii(String *str) } /* Convert given string to a hex string, character by character */ - res= args[0]->val_str(str); - if (!res || tmp_value.alloc(res->length()*2+1)) + res= args[0]->val_str(&tmp_value); + if (!res || str->alloc(res->length()*2+1)) { null_value=1; return 0; } null_value=0; - tmp_value.length(res->length()*2); - tmp_value.set_charset(&my_charset_latin1); + str->length(res->length()*2); + str->set_charset(&my_charset_latin1); - octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length()); - return &tmp_value; + octet2hex((char*) str->ptr(), res->ptr(), res->length()); + return str; } /** Convert given hex string to a binary string. */ @@ -3675,8 +3682,8 @@ String *Item_func_unhex::val_str(String *str) uint length; DBUG_ASSERT(fixed == 1); - res= args[0]->val_str(str); - if (!res || tmp_value.alloc(length= (1+res->length())/2)) + res= args[0]->val_str(&tmp_value); + if (!res || str->alloc(length= (1+res->length())/2)) { null_value=1; return 0; @@ -3684,8 +3691,8 @@ String *Item_func_unhex::val_str(String *str) from= res->ptr(); null_value= 0; - tmp_value.length(length); - to= (char*) tmp_value.ptr(); + str->length(length); + to= (char*) str->ptr(); if (res->length() % 2) { int hex_char; @@ -3703,7 +3710,7 @@ String *Item_func_unhex::val_str(String *str) if ((null_value= (hex_char == -1))) return 0; } - return &tmp_value; + return str; } @@ -3949,7 +3956,7 @@ String *Item_func_quote::val_str(String *str) ulong max_allowed_packet= current_thd->variables.max_allowed_packet; char *from, *to, *end, *start; - String *arg= args[0]->val_str(str); + String *arg= args[0]->val_str(&tmp_value); uint arg_length, new_length; if (!arg) // Null argument { @@ -3976,7 +3983,7 @@ String *Item_func_quote::val_str(String *str) set_if_smaller(new_length, max_allowed_packet); } - if (tmp_value.alloc(new_length)) + if (str->alloc(new_length)) goto null; if (collation.collation->mbmaxlen > 1) @@ -3984,7 +3991,7 @@ String *Item_func_quote::val_str(String *str) CHARSET_INFO *cs= collation.collation; int mblen; uchar *to_end; - to= (char*) tmp_value.ptr(); + to= (char*) str->ptr(); to_end= (uchar*) to + new_length; /* Put leading quote */ @@ -4021,14 +4028,14 @@ String *Item_func_quote::val_str(String *str) if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) goto toolong; to+= mblen; - new_length= to - tmp_value.ptr(); + new_length= to - str->ptr(); goto ret; } /* We replace characters from the end to the beginning */ - to= (char*) tmp_value.ptr() + new_length - 1; + to= (char*) str->ptr() + new_length - 1; *to--= '\''; for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--) { @@ -4058,10 +4065,10 @@ String *Item_func_quote::val_str(String *str) *to= '\''; ret: - tmp_value.length(new_length); - tmp_value.set_charset(collation.collation); + str->length(new_length); + str->set_charset(collation.collation); null_value= 0; - return &tmp_value; + return str; toolong: push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, @@ -4134,7 +4141,7 @@ String *Item_func_compress::val_str(String *str) char *tmp, *last_char; DBUG_ASSERT(fixed == 1); - if (!(res= args[0]->val_str(str))) + if (!(res= args[0]->val_str(&tmp_value))) { null_value= 1; return 0; @@ -4155,13 +4162,13 @@ String *Item_func_compress::val_str(String *str) // Check new_size overflow: new_size <= res->length() if (((uint32) (new_size+5) <= res->length()) || - buffer.realloc((uint32) new_size + 4 + 1)) + str->realloc((uint32) new_size + 4 + 1)) { null_value= 1; return 0; } - body= ((Byte*)buffer.ptr()) + 4; + body= ((Byte*)str->ptr()) + 4; // As far as we have checked res->is_empty() we can use ptr() if ((err= my_compress_buffer(body, &new_size, (const uchar *)res->ptr(), @@ -4173,7 +4180,7 @@ String *Item_func_compress::val_str(String *str) return 0; } - tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects + tmp= (char*) str->ptr(); // int4store is a macro; avoid side effects int4store(tmp, res->length() & 0x3FFFFFFF); /* This is to ensure that things works for CHAR fields, which trim ' ': */ @@ -4184,15 +4191,15 @@ String *Item_func_compress::val_str(String *str) new_size++; } - buffer.length((uint32)new_size + 4); - return &buffer; + str->length((uint32)new_size + 4); + return str; } String *Item_func_uncompress::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); ulong new_size; int err; uint code; @@ -4223,14 +4230,14 @@ String *Item_func_uncompress::val_str(String *str) max_allowed_packet)); goto err; } - if (buffer.realloc((uint32)new_size)) + if (str->realloc((uint32)new_size)) goto err; - if ((err= uncompress((Byte*)buffer.ptr(), &new_size, + if ((err= uncompress((Byte*)str->ptr(), &new_size, ((const Bytef*)res->ptr())+4,res->length()-4)) == Z_OK) { - buffer.length((uint32) new_size); - return &buffer; + str->length((uint32) new_size); + return str; } code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR : diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 78989e9f517..769bde67cb1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -87,7 +87,6 @@ public: class Item_func_md5 :public Item_str_ascii_func { - String tmp_value; public: Item_func_md5(Item *a) :Item_str_ascii_func(a) {} String *val_str_ascii(String *); @@ -167,7 +166,6 @@ public: class Item_func_decode_histogram :public Item_str_func { - String tmp_value; public: Item_func_decode_histogram(Item *a, Item *b) :Item_str_func(a, b) {} @@ -675,7 +673,6 @@ public: class Item_func_format :public Item_str_ascii_func { - String tmp_str; MY_LOCALE *locale; public: Item_func_format(Item *org, Item *dec): Item_str_ascii_func(org, dec) {} @@ -729,7 +726,6 @@ public: class Item_func_binlog_gtid_pos :public Item_str_func { - String tmp_value; public: Item_func_binlog_gtid_pos(Item *arg1,Item *arg2) :Item_str_func(arg1,arg2) {} String *val_str(String *); @@ -1106,7 +1102,7 @@ public: class Item_func_compress: public Item_str_func { - String buffer; + String tmp_value; public: Item_func_compress(Item *a):Item_str_func(a){} void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} @@ -1116,7 +1112,7 @@ public: class Item_func_uncompress: public Item_str_func { - String buffer; + String tmp_value; public: Item_func_uncompress(Item *a): Item_str_func(a){} void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; } From 5e4f4ec8211b61e71ec29069161d0f41f4c05376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 19 Jun 2017 15:59:19 +0300 Subject: [PATCH 18/47] MDEV-12975 InnoDB redo log minimum size check uses detected file size instead of requested innodb_log_file_size log_calc_max_ages(): Use the requested size in the check, instead of the detected redo log size. The redo log will be resized at startup if it differs from what has been requested. --- mysql-test/suite/innodb/t/log_file_size.test | 8 +- storage/innobase/log/log0log.cc | 95 +++++++------------- storage/xtradb/log/log0log.cc | 95 +++++++------------- 3 files changed, 71 insertions(+), 127 deletions(-) diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index 4bae93957e8..6c1003881cf 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -1,6 +1,6 @@ # Test resizing the InnoDB redo log. ---source include/have_innodb.inc +--source include/innodb_page_size.inc # Embedded server does not support crashing --source include/not_embedded.inc @@ -37,6 +37,12 @@ call mtr.add_suppression("Attempting backtrace"); FLUSH TABLES; --enable_query_log +--let $restart_parameters= --innodb-thread-concurrency=1 --innodb-log-file-size=1m --innodb-log-files-in-group=2 +--source include/restart_mysqld.inc + +--let $restart_parameters= --innodb-thread-concurrency=100 --innodb-log-file-size=10M --innodb-log-files-in-group=2 +--source include/restart_mysqld.inc + CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; BEGIN; INSERT INTO t1 VALUES (42); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 65981829f16..2b4bcb628f1 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -734,43 +734,16 @@ ibool log_calc_max_ages(void) /*===================*/ { - log_group_t* group; lsn_t margin; ulint free; - ibool success = TRUE; - lsn_t smallest_capacity; - lsn_t archive_margin; - lsn_t smallest_archive_margin; - mutex_enter(&(log_sys->mutex)); - - group = UT_LIST_GET_FIRST(log_sys->log_groups); - - ut_ad(group); - - smallest_capacity = LSN_MAX; - smallest_archive_margin = LSN_MAX; - - while (group) { - if (log_group_get_capacity(group) < smallest_capacity) { - - smallest_capacity = log_group_get_capacity(group); - } - - archive_margin = log_group_get_capacity(group) - - (group->file_size - LOG_FILE_HDR_SIZE) - - LOG_ARCHIVE_EXTRA_MARGIN; - - if (archive_margin < smallest_archive_margin) { - - smallest_archive_margin = archive_margin; - } - - group = UT_LIST_GET_NEXT(log_groups, group); - } + lsn_t smallest_capacity = ((srv_log_file_size_requested + << srv_page_size_shift) + - LOG_FILE_HDR_SIZE) + * srv_n_log_files; /* Add extra safety */ - smallest_capacity = smallest_capacity - smallest_capacity / 10; + smallest_capacity -= smallest_capacity / 10; /* For each OS thread we must reserve so much free space in the smallest log group that it can accommodate the log entries produced @@ -780,36 +753,6 @@ log_calc_max_ages(void) free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency) + LOG_CHECKPOINT_EXTRA_FREE; if (free >= smallest_capacity / 2) { - success = FALSE; - - goto failure; - } else { - margin = smallest_capacity - free; - } - - margin = margin - margin / 10; /* Add still some extra safety */ - - log_sys->log_group_capacity = smallest_capacity; - - log_sys->max_modified_age_async = margin - - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC; - log_sys->max_modified_age_sync = margin - - margin / LOG_POOL_PREFLUSH_RATIO_SYNC; - - log_sys->max_checkpoint_age_async = margin - margin - / LOG_POOL_CHECKPOINT_RATIO_ASYNC; - log_sys->max_checkpoint_age = margin; - -#ifdef UNIV_LOG_ARCHIVE - log_sys->max_archived_lsn_age = smallest_archive_margin; - - log_sys->max_archived_lsn_age_async = smallest_archive_margin - - smallest_archive_margin / LOG_ARCHIVE_RATIO_ASYNC; -#endif /* UNIV_LOG_ARCHIVE */ -failure: - mutex_exit(&(log_sys->mutex)); - - if (!success) { fprintf(stderr, "InnoDB: Error: ib_logfiles are too small" " for innodb_thread_concurrency %lu.\n" @@ -829,8 +772,34 @@ failure: exit(1); } + margin = smallest_capacity - free; + margin = margin - margin / 10; /* Add still some extra safety */ - return(success); + mutex_enter(&log_sys->mutex); + + log_sys->log_group_capacity = smallest_capacity; + + log_sys->max_modified_age_async = margin + - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC; + log_sys->max_modified_age_sync = margin + - margin / LOG_POOL_PREFLUSH_RATIO_SYNC; + + log_sys->max_checkpoint_age_async = margin - margin + / LOG_POOL_CHECKPOINT_RATIO_ASYNC; + log_sys->max_checkpoint_age = margin; + +#ifdef UNIV_LOG_ARCHIVE + lsn_t archive_margin = smallest_capacity + - (srv_log_file_size_requested - LOG_FILE_HDR_SIZE) + - LOG_ARCHIVE_EXTRA_MARGIN; + log_sys->max_archived_lsn_age = archive_margin; + + log_sys->max_archived_lsn_age_async = archive_margin + - archive_margin / LOG_ARCHIVE_RATIO_ASYNC; +#endif /* UNIV_LOG_ARCHIVE */ + mutex_exit(&log_sys->mutex); + + return(true); } /******************************************************//** diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index 47261aa633a..211cde3cc7a 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -839,43 +839,16 @@ ibool log_calc_max_ages(void) /*===================*/ { - log_group_t* group; lsn_t margin; ulint free; - ibool success = TRUE; - lsn_t smallest_capacity; - lsn_t archive_margin; - lsn_t smallest_archive_margin; - mutex_enter(&(log_sys->mutex)); - - group = UT_LIST_GET_FIRST(log_sys->log_groups); - - ut_ad(group); - - smallest_capacity = LSN_MAX; - smallest_archive_margin = LSN_MAX; - - while (group) { - if (log_group_get_capacity(group) < smallest_capacity) { - - smallest_capacity = log_group_get_capacity(group); - } - - archive_margin = log_group_get_capacity(group) - - (group->file_size - LOG_FILE_HDR_SIZE) - - LOG_ARCHIVE_EXTRA_MARGIN; - - if (archive_margin < smallest_archive_margin) { - - smallest_archive_margin = archive_margin; - } - - group = UT_LIST_GET_NEXT(log_groups, group); - } + lsn_t smallest_capacity = ((srv_log_file_size_requested + << srv_page_size_shift) + - LOG_FILE_HDR_SIZE) + * srv_n_log_files; /* Add extra safety */ - smallest_capacity = smallest_capacity - smallest_capacity / 10; + smallest_capacity -= smallest_capacity / 10; /* For each OS thread we must reserve so much free space in the smallest log group that it can accommodate the log entries produced @@ -885,36 +858,6 @@ log_calc_max_ages(void) free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency) + LOG_CHECKPOINT_EXTRA_FREE; if (free >= smallest_capacity / 2) { - success = FALSE; - - goto failure; - } else { - margin = smallest_capacity - free; - } - - margin = margin - margin / 10; /* Add still some extra safety */ - - log_sys->log_group_capacity = smallest_capacity; - - log_sys->max_modified_age_async = margin - - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC; - log_sys->max_modified_age_sync = margin - - margin / LOG_POOL_PREFLUSH_RATIO_SYNC; - - log_sys->max_checkpoint_age_async = margin - margin - / LOG_POOL_CHECKPOINT_RATIO_ASYNC; - log_sys->max_checkpoint_age = margin; - -#ifdef UNIV_LOG_ARCHIVE - log_sys->max_archived_lsn_age = smallest_archive_margin; - - log_sys->max_archived_lsn_age_async = smallest_archive_margin - - smallest_archive_margin / LOG_ARCHIVE_RATIO_ASYNC; -#endif /* UNIV_LOG_ARCHIVE */ -failure: - mutex_exit(&(log_sys->mutex)); - - if (!success) { fprintf(stderr, "InnoDB: Error: ib_logfiles are too small" " for innodb_thread_concurrency %lu.\n" @@ -934,8 +877,34 @@ failure: exit(1); } + margin = smallest_capacity - free; + margin = margin - margin / 10; /* Add still some extra safety */ - return(success); + mutex_enter(&log_sys->mutex); + + log_sys->log_group_capacity = smallest_capacity; + + log_sys->max_modified_age_async = margin + - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC; + log_sys->max_modified_age_sync = margin + - margin / LOG_POOL_PREFLUSH_RATIO_SYNC; + + log_sys->max_checkpoint_age_async = margin - margin + / LOG_POOL_CHECKPOINT_RATIO_ASYNC; + log_sys->max_checkpoint_age = margin; + +#ifdef UNIV_LOG_ARCHIVE + lsn_t archive_margin = smallest_capacity + - (srv_log_file_size_requested - LOG_FILE_HDR_SIZE) + - LOG_ARCHIVE_EXTRA_MARGIN; + log_sys->max_archived_lsn_age = archive_margin; + + log_sys->max_archived_lsn_age_async = archive_margin + - archive_margin / LOG_ARCHIVE_RATIO_ASYNC; +#endif /* UNIV_LOG_ARCHIVE */ + mutex_exit(&log_sys->mutex); + + return(true); } /******************************************************//** From ded614d7dbc930e373d1a69a0d2a7e4bf0a2c6d3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 13:44:31 +0200 Subject: [PATCH 19/47] MDEV-12778 mariadb-10.1 FTBFS on GNU/Hurd due to use of PATH_MAX --- mysys/my_symlink.c | 2 +- mysys/mysys_priv.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index ed35fff41e9..12959f1f24a 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -197,7 +197,7 @@ int my_realpath(char *to, const char *filename, myf MyFlags) const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd) { - char buf[PATH_MAX+1]; + char buf[FN_REFLEN + 1]; char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf)); int fd, dfd= -1; diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 661c4c184f1..1004bf8889f 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -107,12 +107,21 @@ const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd); res= AT; \ if (dfd >= 0) close(dfd); \ return res; -#elif defined(HAVE_REALPATH) +#elif defined(HAVE_REALPATH) && defined(PATH_MAX) #define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ char buf[PATH_MAX+1]; \ if (realpath(pathname, buf) == NULL) return -1; \ if (strcmp(pathname, buf)) { errno= ENOTDIR; return -1; } \ return NOAT; +#elif defined(HAVE_REALPATH) +#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ + char *buf= realpath(pathname, NULL); \ + int res; \ + if (buf == NULL) return -1; \ + if (strcmp(pathname, buf)) { errno= ENOTDIR; res= -1; } \ + else res= NOAT; \ + free(buf); \ + return res; #else #define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ return NOAT; From b9a326b6e1c1a4b14b27e7fb634fb5f16981f731 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 19 Jun 2017 17:00:09 +0000 Subject: [PATCH 20/47] MDEV-12709 : mariabackup - during backup phase read some innodb parameter using "show variables", rather than take the value from my.cnf. "show variables" is more accurate than my.cnf,it also works for parameters set on the mysqld command line, which is especially important for MTR. --- extra/mariabackup/backup_mysql.cc | 37 +++++++++++++------------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 2353c7692cb..00fed457304 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -344,7 +344,8 @@ get_mysql_vars(MYSQL *connection) char *innodb_data_home_dir_var = NULL; char *innodb_undo_directory_var = NULL; char *innodb_page_size_var = NULL; - + char *innodb_undo_tablespaces_var = NULL; + char *endptr; unsigned long server_version = mysql_get_server_version(connection); bool ret = true; @@ -372,6 +373,7 @@ get_mysql_vars(MYSQL *connection) {"innodb_data_home_dir", &innodb_data_home_dir_var}, {"innodb_undo_directory", &innodb_undo_directory_var}, {"innodb_page_size", &innodb_page_size_var}, + {"innodb_undo_tablespaces", &innodb_undo_tablespaces_var}, {NULL, NULL} }; @@ -460,62 +462,55 @@ get_mysql_vars(MYSQL *connection) } /* get some default values is they are missing from my.cnf */ - if (!check_if_param_set("datadir") && datadir_var && *datadir_var) { + if (datadir_var && *datadir_var) { strmake(mysql_real_data_home, datadir_var, FN_REFLEN - 1); mysql_data_home= mysql_real_data_home; } - if (!check_if_param_set("innodb_data_file_path") - && innodb_data_file_path_var && *innodb_data_file_path_var) { + if (innodb_data_file_path_var && *innodb_data_file_path_var) { innobase_data_file_path = my_strdup( innodb_data_file_path_var, MYF(MY_FAE)); } - if (!check_if_param_set("innodb_data_home_dir") - && innodb_data_home_dir_var && *innodb_data_home_dir_var) { + if (innodb_data_home_dir_var && *innodb_data_home_dir_var) { innobase_data_home_dir = my_strdup( innodb_data_home_dir_var, MYF(MY_FAE)); } - if (!check_if_param_set("innodb_log_group_home_dir") - && innodb_log_group_home_dir_var + if (innodb_log_group_home_dir_var && *innodb_log_group_home_dir_var) { srv_log_group_home_dir = my_strdup( innodb_log_group_home_dir_var, MYF(MY_FAE)); } - if (!check_if_param_set("innodb_undo_directory") - && innodb_undo_directory_var && *innodb_undo_directory_var) { + if (innodb_undo_directory_var && *innodb_undo_directory_var) { srv_undo_dir = my_strdup( innodb_undo_directory_var, MYF(MY_FAE)); } - if (!check_if_param_set("innodb_log_files_in_group") - && innodb_log_files_in_group_var) { - char *endptr; - + if (innodb_log_files_in_group_var) { innobase_log_files_in_group = strtol( innodb_log_files_in_group_var, &endptr, 10); ut_ad(*endptr == 0); } - if (!check_if_param_set("innodb_log_file_size") - && innodb_log_file_size_var) { - char *endptr; - + if (innodb_log_file_size_var) { innobase_log_file_size = strtoll( innodb_log_file_size_var, &endptr, 10); ut_ad(*endptr == 0); } - if (!check_if_param_set("innodb_page_size") && innodb_page_size_var) { - char *endptr; - + if (innodb_page_size_var) { innobase_page_size = strtoll( innodb_page_size_var, &endptr, 10); ut_ad(*endptr == 0); } + if (innodb_undo_tablespaces_var) { + srv_undo_tablespaces = strtoul(innodb_undo_tablespaces_var, &endptr, 10); + ut_ad(*endptr == 0); + } + out: free_mysql_variables(mysql_vars); From 472c2d9b2fbb262665bdd08338ea902e8398010d Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 19 Jun 2017 18:23:55 +0000 Subject: [PATCH 21/47] MDEV-13106 : Fix check for empty directory in MSI installer --- win/packaging/ca/CustomAction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index 9a174b8529e..9281ce27d34 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -180,7 +180,7 @@ extern "C" UINT __stdcall CheckDirectoryEmpty(MSIHANDLE hInstall, empty= true; for(;;) { - if (wcscmp(data.cFileName, L".") || wcscmp(data.cFileName, L"..")) + if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { empty= false; break; From e333d8296480afc63962892f6c8e101dfcaa2686 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Thu, 22 Jun 2017 11:38:50 +0530 Subject: [PATCH 22/47] MDEV-12398 All cluster nodes stop due to a foreign key constraint failure Comment from Codership:- To fix the problem, we changed the certification logic in galera to treat insert on child table row as exclusive to prevent any operation on referenced parent table row. At the same time, update and delete on child table row were demoted to "shared", which makes it possible to update/delete referenced parent table row, but only in a later transaction. This change allows somewhat more concurrency for foreign key constrained transactions, but is still safe for correct certification end result. --- mysql-test/suite/galera/r/MW-369.result | 155 +++++++++++++++ mysql-test/suite/galera/t/MW-369.inc | 75 +++++++ mysql-test/suite/galera/t/MW-369.test | 247 ++++++++++++++++++++++++ storage/innobase/row/row0ins.cc | 21 +- storage/xtradb/row/row0ins.cc | 19 +- 5 files changed, 502 insertions(+), 15 deletions(-) create mode 100644 mysql-test/suite/galera/r/MW-369.result create mode 100644 mysql-test/suite/galera/t/MW-369.inc create mode 100644 mysql-test/suite/galera/t/MW-369.test diff --git a/mysql-test/suite/galera/r/MW-369.result b/mysql-test/suite/galera/r/MW-369.result new file mode 100644 index 00000000000..516904d1b2a --- /dev/null +++ b/mysql-test/suite/galera/r/MW-369.result @@ -0,0 +1,155 @@ +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +SET AUTOCOMMIT=ON; +START TRANSACTION; +DELETE FROM p WHERE f1 = 1; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +INSERT INTO c VALUES (1, 1); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM p; +f1 f2 +1 0 +2 0 +SELECT * FROM c; +f1 p_id +1 1 +DROP TABLE c; +DROP TABLE p; +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, +f2 INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1, 0); +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p SET f2 = 1 WHERE f1 = 1; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +UPDATE c SET f2 = 1 WHERE f1 = 1; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +SELECT * FROM p; +f1 f2 +1 1 +2 0 +SELECT * FROM c; +f1 p_id f2 +1 1 1 +DROP TABLE c; +DROP TABLE p; +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1); +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p SET f2 = 1 WHERE f1 = 1; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +DELETE FROM c WHERE f1 = 1; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +SELECT * FROM p; +f1 f2 +1 1 +2 0 +SELECT * FROM c; +f1 p_id +DROP TABLE c; +DROP TABLE p; +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER UNIQUE KEY) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f2)) ; +INSERT INTO p VALUES (1, 0); +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p SET f2 = 1 WHERE f1 = 1; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +INSERT INTO c VALUES (1, 0);; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM p; +f1 f2 +1 0 +SELECT * FROM c; +f1 p_id +1 0 +DROP TABLE c; +DROP TABLE p; +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) +ON DELETE CASCADE) ; +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1, 0); +SET AUTOCOMMIT=ON; +START TRANSACTION; +DELETE FROM p WHERE f1 = 1; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +UPDATE c SET f2 = 1 WHERE f1 = 1; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM p; +f1 f2 +1 0 +2 0 +SELECT * FROM c; +f1 p_id f2 +1 1 1 +DROP TABLE c; +DROP TABLE p; diff --git a/mysql-test/suite/galera/t/MW-369.inc b/mysql-test/suite/galera/t/MW-369.inc new file mode 100644 index 00000000000..5fd9ef150ae --- /dev/null +++ b/mysql-test/suite/galera/t/MW-369.inc @@ -0,0 +1,75 @@ +# +# This file should be included from tests for MW-369 to run concurrent +# transaction from node_1 with autocommit query from node_2. +# +# The parameters: +# * $mw_369_parent_query - the parent query to be run inside transaction +# * $mw_369_child_query - the child query +# +# The operations are the following: +# +# node_1: +# START TRANSACTION; +# $mw_369_parent_query +# node_2 +# $mw_369_child_query - will be blocked on node_1 in apply monitor +# node_1: +# COMMIT; - will be blocked on node_1 in local monitor +# +# The $mw_369_child_query is always expected to succeed. The caller is +# responsible for checking if the final COMMIT on connection node_1 +# succeeds. +# + +--connection node_1 +SET AUTOCOMMIT=ON; +START TRANSACTION; + +--eval $mw_369_parent_query + +# +# Block the $mw_369_child_query from node_2 +# +# --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +# +# insert client row, which will make it impossible to replay the +# delete on parent +# +--connection node_2 +--eval $mw_369_child_query + +# +# Wait until $mw_369_child_query from node_2 reaches the sync point and +# block the 'COMMIT' from node_1 before it certifies. +# +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +--let $galera_sync_point = local_monitor_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_1 +--send COMMIT + +# +# Wait until both sync points have been reached +# +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_enter_sync +--source include/galera_wait_sync_point.inc + +# +# both threads are now parked in sync points, signal them to continue +# +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc + +--let $galera_sync_point = local_monitor_enter_sync +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc diff --git a/mysql-test/suite/galera/t/MW-369.test b/mysql-test/suite/galera/t/MW-369.test new file mode 100644 index 00000000000..bfb9460b411 --- /dev/null +++ b/mysql-test/suite/galera/t/MW-369.test @@ -0,0 +1,247 @@ +# +# Test A Outline: +# =============== +# +# This test tests the scenario for MW-369 where a new child table +# row referring to parent table row is inserted concurrently from +# another node while the transaction which tries to delete a +# referred row from the parent table is committing. +# +# The p table will originally have rows (1, 0), (2, 0). +# The c table will be empty. +# +# A new row (1, 1) pointing to parent row (1, 0) is inserted from +# connection node_2, the transaction which tries to remove the +# parent row (1, 0) is run from connection node_1. +# +# Expected outcome: +# ================ +# +# The transaction on node_1 will fail. The parent table will contain +# rows (1, 0), (2, 0) and the child table will contain row (1, 1). +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source suite/galera/include/galera_have_debug_sync.inc + +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; + +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); + +--let $mw_369_parent_query = DELETE FROM p WHERE f1 = 1 +--let $mw_369_child_query = INSERT INTO c VALUES (1, 1) + +# +# we must open connection node_1a here, MW-369.inc will use it later +# +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--source MW-369.inc + +# Commit fails +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + +--connection node_2 +SELECT * FROM p; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p; + +# +# Test B Outline: +# =============== +# +# This test tests the scenario for MW-369 where a existing +# child table row is updated concurrently from another node +# with a transaction which updates the parent table. +# +# The p table will originally have rows (1, 0), (2, 0). +# The c table will originally have rows (1, 1, 0) which points +# to parent table row (1, 0). +# +# Expected outcome: +# ================ +# +# Both updates should succeed since they are done to separate tables and +# rows. The parent table will contain rows (1, 1), (2, 0). The child +# table will contain row (1, 1, 1). +# + +--connection node_1 +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, + f2 INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; + +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1, 0); + +--let mw_369_parent_query = UPDATE p SET f2 = 1 WHERE f1 = 1 +--let $mw_369_child_query = UPDATE c SET f2 = 1 WHERE f1 = 1 +--source MW-369.inc + +# Commit succeeds +--connection node_1 +--reap + +--connection node_2 +SELECT * FROM p; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p; + +# +# Test C Outline: +# =============== +# +# This test tests the scenario for MW-369 where a child table row is +# deleted concurrently from the other node while a transaction updates +# the parent table referred by the child table row. +# +# The p table will originally have rows (1, 0), (2, 0) +# The c table will originally have row (1, 1) which points to parent +# table row (1, 0). +# +# A row (1, 1) pointing to parent row (1, 0) is deleted from +# connection node_2, the transaction which tries to update the +# parent row (1, 0) is run from connection node_1. +# +# Expected Outcome: +# ================ +# Both operations on node_1 and node_2 should succeed without conflicts. +# The parent table should contain values (1, 1), (2, 0) and the child +# table should be empty. + +--connection node_1 +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; + +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1); + +--let $mw_369_parent_query = UPDATE p SET f2 = 1 WHERE f1 = 1 +--let $mw_369_child_query = DELETE FROM c WHERE f1 = 1 +--source MW-369.inc + +# Commit succeeds +--connection node_1 +--reap + +--connection node_2 +SELECT * FROM p; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p; + + +# +# Test D Outline: +# =============== +# +# This test is similar to test A, where parent row is deleted while a child row +# is inserted simultaneously on node 2. However, in this test case the FK +# constraint's target column is a unique key, and parent row is not delete, +# but this key value is changed so that insert on node 2 will cause FK +# violation +# +# The p table will originally have rows (1, 0) +# The c table will originally be empty +# +# in node_1, parent row is updated to value (1,1) +# A row (1, 0) pointing to the old version of parent row (1, 0) is inserted +# in connection node_2 +# +# Expected Outcome: +# ================ +# This is a true conflict and one transaciton must abort. In this case it is node_1 +# transaction, which was scheduled later. +# Parent table should have row (1,0) +# child table should have row (1,0) +# + +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER UNIQUE KEY) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f2)) ; + +INSERT INTO p VALUES (1, 0); + +--let $mw_369_parent_query = UPDATE p SET f2 = 1 WHERE f1 = 1 +--let $mw_369_child_query = INSERT INTO c VALUES (1, 0); +--source MW-369.inc + +# Commit fails +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + +--connection node_2 +SELECT * FROM p; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p; + +# +# Test E Outline: +# =============== +# +# This test is similar to test B, where parent row is deleted while a child row +# is updated simultaneously on node 2. However, in this test case the FK +# constraint has ON DELETE CASCADE option, and the delete on parent row will +# cascade a delete on child row as well. This will cause true conflict with +# connection node_2, which tries to update unrelated column on child table. +# +# The p table will originally have rows (1, 0), (2,0) +# The c table will originally have row (1,1,0) +# +# in node_1, parent row (1,0) is deleted and cascaded delete will happen on +# child table row (1,1,0). +# in connection node_2 child table row is update to value (1,1,1) +# +# Expected Outcome: +# ================ +# This is a true conflict and one transaciton must abort. In this case it is node_1 +# transaction, which was scheduled later. +# Parent table should have rows (1,0), (2,0) +# child table should have row (1,1,1) +# + + +CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) + ON DELETE CASCADE) ; + +INSERT INTO p VALUES (1, 0); +INSERT INTO p VALUES (2, 0); +INSERT INTO c VALUES (1, 1, 0); + +--let $mw_369_parent_query = DELETE FROM p WHERE f1 = 1 +--let $mw_369_child_query = UPDATE c SET f2 = 1 WHERE f1 = 1 +--source MW-369.inc + +# Commit fails +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + +--connection node_2 +SELECT * FROM p; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p; + +--sleep 3 diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 5ded12c2c34..c9d616cfb2a 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1290,11 +1290,12 @@ row_ins_foreign_check_on_constraint( #ifdef WITH_WSREP err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - clust_rec, - clust_index, - FALSE, FALSE); + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, + (node) ? TRUE : FALSE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); @@ -1455,6 +1456,9 @@ row_ins_check_foreign_constraint( ulint* offsets = offsets_; rec_offs_init(offsets_); +#ifdef WITH_WSREP + upd_node= NULL; +#endif /* WITH_WSREP */ run_again: #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED)); @@ -1638,9 +1642,10 @@ run_again: err = wsrep_append_foreign_key( thr_get_trx(thr), foreign, - rec, - check_index, - check_ref, TRUE); + rec, + check_index, + check_ref, + (upd_node) ? TRUE : FALSE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index 6072b303d3a..00b8ce17b26 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1296,11 +1296,12 @@ row_ins_foreign_check_on_constraint( #ifdef WITH_WSREP err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - clust_rec, - clust_index, - FALSE, FALSE); + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, + (node) ? TRUE : FALSE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); @@ -1461,6 +1462,9 @@ row_ins_check_foreign_constraint( ulint* offsets = offsets_; rec_offs_init(offsets_); +#ifdef WITH_WSREP + upd_node= NULL; +#endif /* WITH_WSREP */ run_again: #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED)); @@ -1651,8 +1655,9 @@ run_again: thr_get_trx(thr), foreign, rec, - check_index, - check_ref, TRUE); + check_index, + check_ref, + (upd_node) ? TRUE : FALSE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { From d4007f2e73e3ad2676c3f766b233e96f21874c7d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 4 May 2017 17:18:45 +0200 Subject: [PATCH 23/47] disable getopt prefix matching in mtr bootstrap it was disabled in mtr tests in 4280b25ed8 --- mysql-test/mysql-test-run.pl | 1 + mysql-test/r/mysqld--help.result | 2 +- .../suite/perfschema/r/bad_option_2.result | 2 +- .../suite/perfschema/t/bad_option_2.test | 25 +++---------------- 4 files changed, 7 insertions(+), 23 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 64483fa50f1..ff929f8a2e8 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3105,6 +3105,7 @@ sub mysql_install_db { my $args; mtr_init_args(\$args); mtr_add_arg($args, "--no-defaults"); + mtr_add_arg($args, "--disable-getopt-prefix-matching"); mtr_add_arg($args, "--bootstrap"); mtr_add_arg($args, "--basedir=%s", $install_basedir); mtr_add_arg($args, "--datadir=%s", $install_datadir); diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 4b9370f2cd4..3b49f334557 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1200,7 +1200,7 @@ ft-query-expansion-limit 20 ft-stopword-file (No default value) gdb FALSE general-log FALSE -getopt-prefix-matching TRUE +getopt-prefix-matching FALSE group-concat-max-len 1024 gtid-domain-id 0 gtid-ignore-duplicates FALSE diff --git a/mysql-test/suite/perfschema/r/bad_option_2.result b/mysql-test/suite/perfschema/r/bad_option_2.result index d8fda2af3b6..b8fd2ff9a3c 100644 --- a/mysql-test/suite/perfschema/r/bad_option_2.result +++ b/mysql-test/suite/perfschema/r/bad_option_2.result @@ -1 +1 @@ -Found: ambiguous option '--performance-schema-max_=12' +FOUND /ambiguous option '--performance-schema-max_=12'/ in bad_option_2.txt diff --git a/mysql-test/suite/perfschema/t/bad_option_2.test b/mysql-test/suite/perfschema/t/bad_option_2.test index 175767bb9f2..ce3e5c3243b 100644 --- a/mysql-test/suite/perfschema/t/bad_option_2.test +++ b/mysql-test/suite/perfschema/t/bad_option_2.test @@ -8,26 +8,9 @@ let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_2.txt; --error 0,1 --remove_file $outfile --error 3 ---exec $MYSQLD_BOOTSTRAP_CMD --loose-console --performance-schema-max_=12 > $outfile 2>&1 - -perl; - use strict; - use warnings; - my $fname= "$ENV{'MYSQLTEST_VARDIR'}/tmp/bad_option_2.txt"; - open(FILE, "<", $fname) or die; - my @lines= ; - # those must be in the file for the test to pass - my @patterns= - ("ambiguous option '--performance-schema-max_=12'"); - foreach my $one_line (@lines) - { - foreach my $one_pattern (@patterns) - { - # print pattern, not line, to get a stable output - print "Found: $one_pattern\n" if ($one_line =~ /$one_pattern/); - } - } - close FILE; -EOF +--exec $MYSQLD_BOOTSTRAP_CMD --loose-console --enable-getopt-prefix-matching --performance-schema-max_=12 > $outfile 2>&1 +--let SEARCH_PATTERN=ambiguous option '--performance-schema-max_=12' +--let SEARCH_FILE=$outfile +--source include/search_pattern_in_file.inc --remove_file $outfile From d937916c064d46076f5cec2280d91870ed7576d4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Jun 2017 20:21:24 +0200 Subject: [PATCH 24/47] MDEV-12193 Discontinue support of unsecure and unsupported OpenSSL versions (< 1.0.1) --- cmake/ssl.cmake | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index b699a3b493f..74d61b582ea 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -167,6 +167,20 @@ MACRO (MYSQL_CHECK_SSL) SET(CMAKE_REQUIRED_INCLUDES) IF(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES AND CRYPTO_LIBRARY AND HAVE_SHA512_DIGEST_LENGTH) + # Verify version number. Version information looks like: + # #define OPENSSL_VERSION_NUMBER 0x1000103fL + # Encoded as MNNFFPPS: major minor fix patch status + FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" + OPENSSL_VERSION_NUMBER + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*" + ) + STRING(REGEX REPLACE + "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1" + OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}" + ) + MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}") + ENDIF() + IF(OPENSSL_MAJOR_VERSION GREATER 0) SET(SSL_SOURCES "") SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY}) IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") @@ -176,22 +190,9 @@ MACRO (MYSQL_CHECK_SSL) SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBDL}) ENDIF() - # Verify version number. Version information looks like: - # #define OPENSSL_VERSION_NUMBER 0x1000103fL - # Encoded as MNNFFPPS: major minor fix patch status - FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" - OPENSSL_VERSION_NUMBER - REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*" - ) - STRING(REGEX REPLACE - "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1" - OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}" - ) - MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}") MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}") MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}") - MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}") MESSAGE(STATUS "SSL_LIBRARIES = ${SSL_LIBRARIES}") SET(SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) SET(SSL_INTERNAL_INCLUDE_DIRS "") From b6ce68f450ce06db989febf4dc3e2428d6400dd7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 15 Jun 2017 20:16:18 +0200 Subject: [PATCH 25/47] MDEV-13012 Assertion `share->error' failed in discover_handlerton upon executing statement with max_session_mem_used = 8192 and MDEV-13011 Server crashes in THD::handle_condition or Assertion `! is_set() || m_can_overwrite_status' fails upon attempt to connect with max_session_mem_used = 8192 errors when a connection is killed in the * TABLE_SHARE::init_from_sql_statement_string() * THD::init() also, safety-wise, don't check max_mem_used on free() and when some error was already issued. --- mysql-test/r/errors.result | 4 ++++ mysql-test/t/errors.test | 9 +++++++++ sql/handler.cc | 7 ++++++- sql/mysqld.cc | 8 +++++--- sql/sql_class.cc | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result index 23c77d3978c..bf75bf73862 100644 --- a/mysql-test/r/errors.result +++ b/mysql-test/r/errors.result @@ -168,3 +168,7 @@ UPDATE t1 SET a = 'new' WHERE COLUMN_CREATE( 1, 'v', 1, 'w' ) IS NULL; ERROR 22007: Illegal value used as argument of dynamic column function drop table t1; +set max_session_mem_used = 8192; +select * from seq_1_to_1000; +ERROR HY000: Engine SEQUENCE failed to discover table `test`.`seq_1_to_1000` with 'create table seq (seq bigint unsigned primary key)' +set global max_session_mem_used = default; diff --git a/mysql-test/t/errors.test b/mysql-test/t/errors.test index 6ce6e439919..9d5cbef89b1 100644 --- a/mysql-test/t/errors.test +++ b/mysql-test/t/errors.test @@ -1,6 +1,7 @@ # # Test some error conditions # +--source include/have_sequence.inc --disable_warnings drop table if exists t1; @@ -198,3 +199,11 @@ CREATE TABLE t1 (a CHAR(3), b BLOB); UPDATE t1 SET a = 'new' WHERE COLUMN_CREATE( 1, 'v', 1, 'w' ) IS NULL; drop table t1; + +# +# errors caused by max_session_mem_used +# +set max_session_mem_used = 8192; +--error ER_SQL_DISCOVER_ERROR +select * from seq_1_to_1000; +set global max_session_mem_used = default; diff --git a/sql/handler.cc b/sql/handler.cc index aa87da5dd44..dae47668410 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4857,7 +4857,12 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, { if (error) { - DBUG_ASSERT(share->error); // tdc_lock_share needs that + if (!share->error) + { + share->error= OPEN_FRM_ERROR_ALREADY_ISSUED; + plugin_unlock(0, share->db_plugin); + } + /* report an error, unless it is "generic" and a more specific one was already reported diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1e6ee4decbe..17172207613 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3939,8 +3939,9 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) (longlong) thd->status_var.local_memory_used, size)); thd->status_var.local_memory_used+= size; - if (thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used && - !thd->killed) + if (size > 0 && + thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used && + !thd->killed && !thd->get_stmt_da()->is_set()) { char buf[1024]; thd->killed= KILL_QUERY; @@ -6646,11 +6647,12 @@ void handle_connections_sockets() */ DBUG_PRINT("info", ("Creating THD for new connection")); - if (!(thd= new THD)) + if (!(thd= new THD) || thd->is_error()) { (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) mysql_socket_close(new_sock); statistic_increment(connection_errors_internal, &LOCK_status); + delete thd; continue; } /* Set to get io buffers to be part of THD */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 304036a67ff..6fb74d6e14c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -879,6 +879,7 @@ THD::THD(bool is_wsrep_applier) debug_sync_control(0), #endif /* defined(ENABLED_DEBUG_SYNC) */ wait_for_commit_ptr(0), + m_internal_handler(0), main_da(0, false, false), m_stmt_da(&main_da), tdc_hash_pins(0), @@ -1073,7 +1074,6 @@ THD::THD(bool is_wsrep_applier) MYF(MY_WME|MY_THREAD_SPECIFIC)); } - m_internal_handler= NULL; m_binlog_invoker= INVOKER_NONE; memset(&invoker_user, 0, sizeof(invoker_user)); memset(&invoker_host, 0, sizeof(invoker_host)); From 3f240bff80b51458c85cd8a8b5616872f21fa033 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 16 Jun 2017 00:35:57 +0200 Subject: [PATCH 26/47] MDEV-13097 Online alter of a partitioned MyISAM table with auto_increment MyISAM only allows online alter if autoincrement didn't change. MyISAM detects that by comparing new autoinc value from create_info, with the old one, stored in MYI. But in partitioned tables, create_info->auto_increment_value is for the whole table, max of autoinc values of individual MYI partitions. So *some* MYI partitions will inevitably think that alter table changes auto_increment value and will deny online alter. Fix: only compare autoinc values, if the user has used AUTO_INCREMENT in the ALTER TABLE statement. --- mysql-test/r/partition_alter.result | 20 ++++++++++++++++++++ mysql-test/t/partition_alter.test | 9 +++++++++ storage/myisam/ha_myisam.cc | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/partition_alter.result b/mysql-test/r/partition_alter.result index 4aea0045617..4275ef72f24 100644 --- a/mysql-test/r/partition_alter.result +++ b/mysql-test/r/partition_alter.result @@ -92,3 +92,23 @@ t1 CREATE TABLE `t1` ( PARTITION p2 VALUES LESS THAN ('2020-10-19') ENGINE = MyISAM) */ insert t1 values (2, '2020-01-03', 20); drop table t1; +create table t1 (id_1 int auto_increment, id_2 int, id_3 int, d1 date, dt1 datetime default current_timestamp, dt2 datetime default current_timestamp on update current_timestamp, primary key (id_2, id_3), key(id_1)) partition by hash(id_2) partitions 3 (partition p01, partition p02, partition p03); +insert into t1 values(0, 1, 1, NULL, now(), now()); +alter online table t1 delay_key_write=1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id_1` int(11) NOT NULL AUTO_INCREMENT, + `id_2` int(11) NOT NULL, + `id_3` int(11) NOT NULL, + `d1` date DEFAULT NULL, + `dt1` datetime DEFAULT CURRENT_TIMESTAMP, + `dt2` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id_2`,`id_3`), + KEY `id_1` (`id_1`) +) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 +/*!50100 PARTITION BY HASH (id_2) +(PARTITION p01 ENGINE = MyISAM, + PARTITION p02 ENGINE = MyISAM, + PARTITION p03 ENGINE = MyISAM) */ +drop table t1; diff --git a/mysql-test/t/partition_alter.test b/mysql-test/t/partition_alter.test index 2f3c2a319fb..feb792624ab 100644 --- a/mysql-test/t/partition_alter.test +++ b/mysql-test/t/partition_alter.test @@ -103,3 +103,12 @@ show create table t1; insert t1 values (2, '2020-01-03', 20); drop table t1; --list_files $datadir/test + +# +# MDEV-13097 Online alter of a partitioned MyISAM table with auto_increment +# +create table t1 (id_1 int auto_increment, id_2 int, id_3 int, d1 date, dt1 datetime default current_timestamp, dt2 datetime default current_timestamp on update current_timestamp, primary key (id_2, id_3), key(id_1)) partition by hash(id_2) partitions 3 (partition p01, partition p02, partition p03); +insert into t1 values(0, 1, 1, NULL, now(), now()); +alter online table t1 delay_key_write=1; +show create table t1; +drop table t1; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index b335d360379..82bcbdb12a9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2266,7 +2266,8 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *create_info, { uint options= table->s->db_options_in_use; - if (create_info->auto_increment_value != stats.auto_increment_value || + if ((create_info->used_fields & HA_CREATE_USED_AUTO && + create_info->auto_increment_value != stats.auto_increment_value) || create_info->data_file_name != data_file_name || create_info->index_file_name != index_file_name || table_changes == IS_EQUAL_NO || From f1a6d24af3f78ffd4441522b7352ab36f37b6b24 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 21 Jun 2017 23:29:19 +0200 Subject: [PATCH 27/47] MDEV-11003 ndb test suite still exists and does not work fix a merge mistake --- .../suite/ndb/r/ndb_restore_discover.result | 33 --------- .../suite/ndb/t/ndb_restore_discover.test | 70 ------------------- 2 files changed, 103 deletions(-) delete mode 100644 mysql-test/suite/ndb/r/ndb_restore_discover.result delete mode 100644 mysql-test/suite/ndb/t/ndb_restore_discover.test diff --git a/mysql-test/suite/ndb/r/ndb_restore_discover.result b/mysql-test/suite/ndb/r/ndb_restore_discover.result deleted file mode 100644 index de10af87047..00000000000 --- a/mysql-test/suite/ndb/r/ndb_restore_discover.result +++ /dev/null @@ -1,33 +0,0 @@ -# -# 18075170 - sql node restart required to avoid deadlock after -# restore -# -CREATE TABLE t1 (id INT) ENGINE=NDBCluster; -CREATE TABLE t2 (id INT) ENGINE=NDBCluster; -INSERT INTO t1 VALUES (1); -INSERT INTO t2 VALUES (1); -DROP TABLE t1; -DROP TABLE t2; -SET autocommit = 0; -SELECT * FROM t1; -id -1 -SELECT * FROM t2; -id -1 -ROLLBACK; -SET autocommit = 1; -drop table t1; -drop table t2; -SET autocommit = 0; -SELECT * FROM t1; -id -1 -SELECT * FROM t2; -id -1 -ALTER TABLE t1 ADD val INT; -ROLLBACK; -SET autocommit = 1; -drop table t1; -drop table t2; diff --git a/mysql-test/suite/ndb/t/ndb_restore_discover.test b/mysql-test/suite/ndb/t/ndb_restore_discover.test deleted file mode 100644 index 6631c74d5c8..00000000000 --- a/mysql-test/suite/ndb/t/ndb_restore_discover.test +++ /dev/null @@ -1,70 +0,0 @@ --- source include/have_ndb.inc --- source include/count_sessions.inc - ---echo # ---echo # 18075170 - sql node restart required to avoid deadlock after ---echo # restore ---echo # -# Test Auto Discover option within a transaction -# and make sure the transaction is not broken. -CREATE TABLE t1 (id INT) ENGINE=NDBCluster; -CREATE TABLE t2 (id INT) ENGINE=NDBCluster; - -INSERT INTO t1 VALUES (1); -INSERT INTO t2 VALUES (1); - --- source include/ndb_backup.inc - -DROP TABLE t1; -DROP TABLE t2; - --- source include/ndb_restore_master.inc - -SET autocommit = 0; -SELECT * FROM t1; - -# Without fix below select was resulting in DEADLOCK error. With fix select -# should succeed. -SELECT * FROM t2; -ROLLBACK; -SET autocommit = 1; - -drop table t1; -drop table t2; - -# -# Checking lock preservation in transaction -# -# Using existing backup to create the scenario. Tables are deleted as part of -# above test cleanup. Thus restoring the backup will bring the system to -# required state. --- source include/ndb_restore_master.inc - -SET autocommit = 0; -SELECT * FROM t1; -SELECT * FROM t2; - -connect(con2, localhost, root); ---SEND ALTER TABLE t1 ADD val INT - -connection default; -# Alter from con2 will be in waiting state as there is a lock on t1 from -# default connection due to active transaction. We check for this condition -# then releasing the lock by rollbacking active transaction. -let $wait_condition= - SELECT count(*) = 1 FROM information_schema.processlist WHERE state - LIKE "Waiting%" AND info = "ALTER TABLE t1 ADD val INT"; ---source include/wait_condition.inc -ROLLBACK; -SET autocommit = 1; - -connection con2; ---REAP - -disconnect con2; -connection default; -drop table t1; -drop table t2; - -# Wait till all disconnects are completed --- source include/wait_until_count_sessions.inc From ba9daddcd831e04be59bf1d60cb666624642f07c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 20 Jun 2017 20:02:20 +0000 Subject: [PATCH 28/47] Cherrypick Perconas fix for leaking descriptors with new xbstream. https://github.com/percona/percona-xtrabackup/pull/368/commits/72c55f4fc2ba9ede7b960eceb01261ccc339c041 --- extra/mariabackup/xbstream.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extra/mariabackup/xbstream.c b/extra/mariabackup/xbstream.c index edfe20a9e3c..f3880f9ec03 100644 --- a/extra/mariabackup/xbstream.c +++ b/extra/mariabackup/xbstream.c @@ -444,7 +444,11 @@ extract_worker_thread_func(void *arg) } if (chunk.type == XB_CHUNK_TYPE_EOF) { + pthread_mutex_lock(ctxt->mutex); pthread_mutex_unlock(&entry->mutex); + my_hash_delete(ctxt->filehash, (uchar *) entry); + pthread_mutex_unlock(ctxt->mutex); + continue; } From 9b7afd4188dfe5db64fbf8a58360b09f90f77fed Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 16 Jun 2017 16:24:36 +0200 Subject: [PATCH 29/47] MDEV-12819 order by ordering expression changed to empty string when creatin view with union prepare of "fake_select" for union made in JOIN::prepare only if we do not execute it then before reset, i.e it was for PS prepare and now required for CREATE VIEW to make global ORDER BY which belongs to "fake_select" prepared. --- mysql-test/r/view.result | 18 ++++++++++++++++++ mysql-test/t/view.test | 21 +++++++++++++++++++++ sql/sql_union.cc | 4 +++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d7cf89577eb..0ded1dd4cb3 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -6065,5 +6065,23 @@ three COUNT(*) drop view v1; drop table t1; # +# MDEV-12819: order by ordering expression changed to empty string +# when creatin view with union +# +create table t1 (t1col1 int, t1col2 int,t1col3 int ); +create table t2 (t2col1 int, t2col2 int, t2col3 int); +create view v1 as +select t1col1,t1col2,t1col3 from t1 +union all +select t2col1,t2col2,t2col3 from t2 +order by 2,3; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`t1col1` AS `t1col1`,`t1`.`t1col2` AS `t1col2`,`t1`.`t1col3` AS `t1col3` from `t1` union all select `t2`.`t2col1` AS `t2col1`,`t2`.`t2col2` AS `t2col2`,`t2`.`t2col3` AS `t2col3` from `t2` order by 2,3 latin1 latin1_swedish_ci +select * from v1; +t1col1 t1col2 t1col3 +drop view v1; +drop table t1,t2; +# # End of 10.1 tests # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 7a935838216..3ad7b9483ac 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5900,6 +5900,27 @@ SELECT * FROM v1; drop view v1; drop table t1; +--echo # +--echo # MDEV-12819: order by ordering expression changed to empty string +--echo # when creatin view with union +--echo # + +create table t1 (t1col1 int, t1col2 int,t1col3 int ); +create table t2 (t2col1 int, t2col2 int, t2col3 int); + +create view v1 as +select t1col1,t1col2,t1col3 from t1 +union all +select t2col1,t2col2,t2col3 from t2 +order by 2,3; + +show create view v1; + +select * from v1; + +drop view v1; +drop table t1,t2; + --echo # --echo # End of 10.1 tests --echo # diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 2086d1d6c03..7ca0a9bb867 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -618,7 +618,9 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, if (saved_error) goto err; - if (fake_select_lex != NULL && thd->stmt_arena->is_stmt_prepare()) + if (fake_select_lex != NULL && + (thd->stmt_arena->is_stmt_prepare() || + (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW))) { /* Validate the global parameters of this union */ From f65d6a03f0870fbac0ce99bc948b28963e594ff3 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 22 Jun 2017 19:28:07 +0000 Subject: [PATCH 30/47] workaround for a test failure on windows (by serg) --- mysql-test/r/mysqld--help.result | 1 + mysql-test/t/mysqld--help.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 3b49f334557..af96555645b 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1,3 +1,4 @@ +Windows bug: happens when a new line is exactly at the right offset The following options may be given as the first argument: --print-defaults Print the program argument list and exit. --no-defaults Don't read default options from any option file. diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index c8fb5e5b953..00d0b58bd05 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -42,6 +42,7 @@ perl; $re2=join('|', @plugins); $skip=0; open(F, '<', "$ENV{MYSQL_TMP_DIR}/mysqld--help.txt") or die; + print "Windows bug: happens when a new line is exactly at the right offset\n"; while () { next if 1../The following groups are read/; # formatting, skip line consisting entirely of dashes and blanks From b76b69cd5fe634d8ddb9406aa2c82ef2a375b4d8 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 20 Jun 2017 14:55:30 +0200 Subject: [PATCH 31/47] MDEV-10880: Assertions `keypart_map' or `prebuilt->search_tuple->n_fields > 0' fail on DISTINCT and GROUP BY constant add_group_and_distinct_keys() should take into account JOIN::simple_group. --- mysql-test/r/bench_count_distinct.result | 2 +- mysql-test/r/distinct.result | 2 +- mysql-test/r/explain_json.result | 18 ++++---- mysql-test/r/group_min_max.result | 46 +++++++++---------- mysql-test/r/order_by.result | 16 +++++++ .../suite/vcol/r/vcol_select_innodb.result | 2 +- .../suite/vcol/r/vcol_select_myisam.result | 2 +- mysql-test/t/order_by.test | 12 +++++ sql/sql_select.cc | 2 +- 9 files changed, 65 insertions(+), 37 deletions(-) diff --git a/mysql-test/r/bench_count_distinct.result b/mysql-test/r/bench_count_distinct.result index 8b67e4be38a..79e12afd237 100644 --- a/mysql-test/r/bench_count_distinct.result +++ b/mysql-test/r/bench_count_distinct.result @@ -5,7 +5,7 @@ count(distinct n) 100 explain extended select count(distinct n) from t1; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range NULL n 4 NULL 10 100.00 Using index for group-by +1 SIMPLE t1 index NULL n 4 NULL 200 100.00 Using index Warnings: Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1` drop table t1; diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index d6e5a69e217..b5e8cefca69 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -212,7 +212,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 1 Using index explain SELECT distinct a from t3 order by a desc limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index NULL a 5 NULL 40 Using index +1 SIMPLE t3 index NULL a 5 NULL 2 Using index explain SELECT distinct a,b from t3 order by a+1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort diff --git a/mysql-test/r/explain_json.result b/mysql-test/r/explain_json.result index 568373f1e16..a46a3bcefa5 100644 --- a/mysql-test/r/explain_json.result +++ b/mysql-test/r/explain_json.result @@ -1030,10 +1030,10 @@ Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 Using where; Using index for group-by (scanning) +1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index explain format=json select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); EXPLAIN { @@ -1041,14 +1041,14 @@ EXPLAIN "select_id": 1, "table": { "table_name": "t1", - "access_type": "range", - "key": "idx_t1_1", + "access_type": "index", + "key": "idx_t1_2", "key_length": "147", "used_key_parts": ["a1", "a2", "b"], - "rows": 17, + "rows": 128, "filtered": 100, "attached_condition": "((t1.b = 'a') and (t1.a2 >= 'b'))", - "using_index_for_group_by": true + "using_index": true } } } @@ -1059,14 +1059,14 @@ EXPLAIN "select_id": 1, "table": { "table_name": "t1", - "access_type": "range", + "access_type": "index", "key": "idx_t1_1", "key_length": "163", "used_key_parts": ["a1", "a2", "b", "c"], - "rows": 65, + "rows": 128, "filtered": 100, "attached_condition": "((t1.b = 'a') and (t1.c = 'i121') and (t1.a2 >= 'b'))", - "using_index_for_group_by": "scanning" + "using_index": true } } } diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 8fbcdae38cd..cd7f1014ec0 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -1707,13 +1707,13 @@ select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1 a1 a2 b explain select distinct a1,a2,b from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index explain extended select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 50.78 Using where; Using index +1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 100.00 Using where; Using index Warnings: Note 1003 select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`b` = 'a') and (`test`.`t1`.`c` = 'i121') and (`test`.`t1`.`a2` >= 'b')) explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); @@ -1724,13 +1724,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index explain select distinct a1,a2,b from t2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by +1 SIMPLE t2 index NULL idx_t2_2 146 NULL # Using index explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by +1 SIMPLE t2 index NULL idx_t2_2 146 NULL # Using where; Using index explain extended select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 50.61 Using where; Using index +1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 100.00 Using where; Using index Warnings: Note 1003 select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`b` = 'a') and (`test`.`t2`.`c` = 'i121') and (`test`.`t2`.`a2` >= 'b')) explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); @@ -1855,7 +1855,7 @@ c e d e explain select distinct a1,a2,b from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by @@ -1870,7 +1870,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by; Using temporary; Using filesort explain select distinct a1,a2,b from t2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by +1 SIMPLE t2 index NULL idx_t2_2 146 NULL # Using index explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by @@ -1953,10 +1953,10 @@ b a explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 Using where; Using index for group-by (scanning) +1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 100.00 Using where; Using index for group-by @@ -2173,7 +2173,7 @@ c d explain select distinct a1 from t1 where a2 = 'b'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by +1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index select distinct a1 from t1 where a2 = 'b'; a1 a @@ -2283,7 +2283,7 @@ INSERT INTO t1 (a) VALUES ('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN'); EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 66 NULL 6 Using index for group-by +1 SIMPLE t1 index NULL a 66 NULL 11 Using index SELECT DISTINCT a,a FROM t1 ORDER BY a; a a @@ -2499,7 +2499,7 @@ INSERT INTO t1 VALUES (4), (2), (1), (2), (2), (4), (1), (4); EXPLAIN SELECT DISTINCT(a) FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx 5 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL idx 5 NULL 16 Using index SELECT DISTINCT(a) FROM t1; a 1 @@ -2507,7 +2507,7 @@ a 4 EXPLAIN SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx 5 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL idx 5 NULL 16 Using index SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1; a 1 @@ -2646,7 +2646,7 @@ INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT a,b,c+1,d FROM t1; EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL foo 10 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 index NULL foo 20 NULL 32 Using where; Using index SELECT DISTINCT c FROM t1 WHERE d=4; c 1 @@ -3339,19 +3339,19 @@ INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2; INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2; EXPLAIN SELECT COUNT(DISTINCT a) FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL a 10 NULL 16 Using index SELECT COUNT(DISTINCT a) FROM t1; COUNT(DISTINCT a) 2 EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL a 10 NULL 16 Using index SELECT COUNT(DISTINCT a,b) FROM t1; COUNT(DISTINCT a,b) 16 EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL a 10 NULL 16 Using index SELECT COUNT(DISTINCT b,a) FROM t1; COUNT(DISTINCT b,a) 16 @@ -3414,7 +3414,7 @@ COUNT(DISTINCT a) 2 EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL a 10 NULL 16 Using index SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10; 1 1 @@ -3435,19 +3435,19 @@ COUNT(DISTINCT t1_1.a) 1 EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by +1 SIMPLE t1 index NULL a 10 NULL 16 Using index SELECT COUNT(DISTINCT a), 12 FROM t1; COUNT(DISTINCT a) 12 2 12 EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by +1 SIMPLE t2 index NULL a 15 NULL 16 Using index SELECT COUNT(DISTINCT a, b, c) FROM t2; COUNT(DISTINCT a, b, c) 16 EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by +1 SIMPLE t2 index NULL a 15 NULL 16 Using index SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2; COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT a) 2 3 1.5000 @@ -3459,7 +3459,7 @@ COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT f) 2 3 1.0000 EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by +1 SIMPLE t2 index NULL a 15 NULL 16 Using index SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2; COUNT(DISTINCT a, b) COUNT(DISTINCT b, a) 16 16 diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index e24d9a94891..71aa32f0cee 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -3145,3 +3145,19 @@ id select_type table type possible_keys key key_len ref rows Extra drop table t0,t1,t2,t3; set @@optimizer_switch=@tmp_8989; set optimizer_switch='orderby_uses_equalities=on'; +# +# MDEV-10880: Assertions `keypart_map' or +# `prebuilt->search_tuple->n_fields > 0' fail on DISTINCT and +# GROUP BY constant +# +CREATE TABLE t1 (pk INT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT DISTINCT pk FROM t1 GROUP BY 'foo'; +pk +1 +SELECT DISTINCT pk FROM t1; +pk +1 +2 +3 +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/r/vcol_select_innodb.result b/mysql-test/suite/vcol/r/vcol_select_innodb.result index 97bfbbe4eaf..5c29f5f8283 100644 --- a/mysql-test/suite/vcol/r/vcol_select_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_select_innodb.result @@ -133,7 +133,7 @@ count(distinct c) 3 explain select count(distinct c) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL c 5 NULL 6 Using index for group-by (scanning) +1 SIMPLE t1 index NULL c 5 NULL 5 Using index ### ### filesort & range-based utils ### diff --git a/mysql-test/suite/vcol/r/vcol_select_myisam.result b/mysql-test/suite/vcol/r/vcol_select_myisam.result index 6dee132b3e5..7c371a1008a 100644 --- a/mysql-test/suite/vcol/r/vcol_select_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_select_myisam.result @@ -133,7 +133,7 @@ count(distinct c) 3 explain select count(distinct c) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL c 5 NULL 6 Using index for group-by (scanning) +1 SIMPLE t1 index NULL c 5 NULL 5 Using index ### ### filesort & range-based utils ### diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 2d0c134a2d9..f61a6a8be34 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -2091,3 +2091,15 @@ set @@optimizer_switch=@tmp_8989; set optimizer_switch='orderby_uses_equalities=on'; + +--echo # +--echo # MDEV-10880: Assertions `keypart_map' or +--echo # `prebuilt->search_tuple->n_fields > 0' fail on DISTINCT and +--echo # GROUP BY constant +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT DISTINCT pk FROM t1 GROUP BY 'foo'; +SELECT DISTINCT pk FROM t1; +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 50f121ce47f..9f339146646 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5708,7 +5708,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) Item_field *cur_item; key_map possible_keys(0); - if (join->group_list) + if (join->group_list || join->simple_group) { /* Collect all query fields referenced in the GROUP clause. */ for (cur_group= join->group_list; cur_group; cur_group= cur_group->next) (*cur_group->item)->walk(&Item::collect_item_field_processor, 0, From 32659db8644504940f8d34835fde8f7b6535f1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 26 Jun 2017 12:22:27 +0300 Subject: [PATCH 32/47] Fix merge error from 10.0 Item_func_sysconst behaves as a non-constant function during prepared statements and view creation and constant otherwise. Current condition implied the opposite. --- sql/item_strfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6de9b3ca785..8e8a77e5042 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2339,7 +2339,7 @@ Item *Item_func_sysconst::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) Return the identical item during view creation and prepare. */ - if (!thd->lex->is_ps_or_view_context_analysis()) + if (thd->lex->is_ps_or_view_context_analysis()) return this; return const_charset_converter(thd, tocs, true, fully_qualified_func_name()); } From 3125ba891292ff16186c105b6780fbadc74421e9 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Tue, 27 Jun 2017 03:48:04 +0300 Subject: [PATCH 33/47] Updated list of unstable tests for 10.1.25 release --- mysql-test/unstable-tests | 144 ++++++++++++++------------------------ 1 file changed, 51 insertions(+), 93 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index d21035a868e..9e7d4f7f76f 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -29,63 +29,57 @@ main.analyze_format_json : MDEV-11866 - Wrong result main.analyze_stmt_orderby : MDEV-11866 - Wrong result main.analyze_stmt_slow_query_log : MDEV-12237 - Wrong result main.create_delayed : MDEV-10605 - failed with timeout -main.ctype_upgrade : Modified in 10.1.23 main.ctype_utf16le : MDEV-10675: timeout or extra warnings main.derived_view : Modified in 10.1.24 main.drop-no_root : MDEV-12633 - Valgrind warnings -main.events_2 : Modified in 10.1.23 +main.errors : MDEV-13179 - Wrong error 1290; modified in 10.1.25 main.events_bugs : MDEV-12892 - Crash in fill_schema_processlist main.events_restart : MDEV-12236 - Server shutdown problem -main.func_regexp_pcre : Modified in 10.1.24 -main.gis : Modified in 10.1.23 +main.func_regexp_pcre : Modified in 10.1.25 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout main.index_merge_innodb : MDEV-7142 - Wrong execution plan, timeout with valgrind main.innodb_mysql_lock : MDEV-7861 - sporadic lock detection failure +main.join_outer : Modified in 10.1.25 main.kill_processlist-6619 : MDEV-10793 - wrong result in processlist -main.loaddata : Modified in 10.1.23 main.loadxml : Modified in 10.1.24 -main.log_tables-big : Modified in 10.1.23 main.mdev-504 : MDEV-10607 - sporadic "can't connect" main.mdev375 : MDEV-10607 - sporadic "can't connect" +main.mdl_sync : Modified in 10.1.25 main.merge : MDEV-10607 - sporadic "can't connect" main.myisam_debug : Modified in 10.1.24 main.mysqlcheck : MDEV-12633 - Valgrind warnings -main.mysqlhotcopy_myisam : Uses mysqlhotcopy.inc modified in 10.1.23 main.mysqlslap : MDEV-11801 - timeout main.mysqltest : MDEV-9269 - fails on Alpha; modified in 10.1.24 main.mysql_client_test : MDEV-12633 - Valgrind warnings main.mysql_client_test_comp : MDEV-12633 - Valgrind warnings main.mysql_client_test_nonblock : MDEV-12633 - Valgrind warnings -main.mysqldump : Modified in 10.1.23 -main.mysqltest : Modified in 10.1.23 +main.mysqld--help : Modified in 10.1.25 +main.order_by : MOdified in 10.1.25 main.order_by_optimizer_innodb : MDEV-10683 - wrong execution plan -main.partition_alter : Modified in 10.1.24 +main.partition_alter : Modified in 10.1.25 +main.partition_innodb_plugin : MDEV-12901 - Valgrind warnings main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count main.query_cache : MDEV-12895 - Wrong result main.range_vs_index_merge_innodb : MDEV-12637 - Timeout main.repair_symlink-5543 : MDEV-12215 - Wrong error codes +main.set_statement : MDEV-13183 - Wrong result main.show_check : MDEV-12633 - Valgrind warnings main.show_explain : MDEV-10674 - sporadic failure main.sp-security : MDEV-10607 - sporadic "can't connect" main.status : MDEV-8510 - sporadic wrong result -main.subselect4 : Modified in 10.1.23 -main.subselect_exists2in : Modified in 10.1.23 -main.subselect_innodb : MDEV-10614 - sporadic wrong results; also modified in 10.1.23 +main.subselect_innodb : MDEV-10614 - sporadic wrong results main.subselect_mat_cost_bugs : Modified in 10.1.24 main.subselect_sj : Modified in 10.1.24 -main.subselect_sj_mat : Modified in 10.1.23 main.subselect_sj2_mat : Modified in 10.1.24 -main.symlink : Modified in 10.1.23 main.symlink-aria-11902 : MDEV-12215 - Unexpected errors -main.symlink-myisam-11902 : MDEV-12215 - Unexpected errors; modified in 10.1.23 +main.symlink-myisam-11902 : MDEV-12215 - Unexpected errors main.type_datetime_hires : MDEV-10687 - timeout -main.view : Modified in 10.1.23 +main.view : Modified in 10.1.25 #---------------------------------------------------------------- archive.discover : MDEV-10510 - table is marked as crashed -archive.mysqlhotcopy_archive : Uses mysqlhotcopy.inc modified in 10.1.23 #---------------------------------------------------------------- @@ -104,7 +98,6 @@ binlog_encryption.rpl_semi_sync : MDEV-11220 - Wrong result, MDEV-11673 - Val #---------------------------------------------------------------- connect.jdbc_new : Modified in 10.1.24 -connect.secure_file_priv : Modified in 10.1.23 connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results #---------------------------------------------------------------- @@ -114,29 +107,21 @@ csv.read_only : Added in 10.1.24 #---------------------------------------------------------------- encryption.create_or_replace : MDEV-9359 - Assertion failure -encryption.debug_key_management : Modified in 10.1.23 -encryption.encrypt_and_grep : Modified in 10.1.23 -encryption.innodb-bad-key-change : MDEV-12926 - Valgrind; modified in 10.1.23 -encryption.innodb-bad-key-change2 : MDEV-12632 - Valgrind warnings, modified in 10.1.23 -encryption.innodb-bad-key-change4 : Modified in 10.1.23 -encryption.innodb-compressed-blob : Added in 10.1.23 +encryption.innodb-bad-key-change2 : MDEV-12632 - Valgrind warnings +encryption.innodb-checksum-algorithm : MDEV-13167 - Assertion failure; added in 10.1.25 +encryption.innodb-compressed-blob : Modified in 10.1.25 encryption.innodb-discard-import-change : MDEV-12632 - Valgrind warnings -encryption.innodb-encryption-disable : Modified in 10.1.23 encryption.innodb_encryption_discard_import : MDEV-12903 - Wrong result encryption.innodb_encryption_filekeys : MDEV-9962 - timeouts -encryption.innodb_encryption-page-compression : MDEV-12630 - crash or assertion failure, modified in 10.1.23 +encryption.innodb_encryption-page-compression : MDEV-12630 - crash or assertion failure encryption.innodb_encryption_tables : MDEV-9359 - Assertion failure encryption.innodb_first_page : MDEV-10689 - crashes -encryption.innodb-force-corrupt : Added in 10.1.23 +encryption.innodb-first-page-read : MDEV-13181 - Signal 8; added in 10.1.25 encryption.innodb-key-rotation-disable : Modified in 10.1.24 encryption.innodb_lotoftables : MDEV-11531 - InnoDB error -encryption.innodb-missing-key : MDEV-9359 - assertion failure; also modified in 10.1.23 -encryption.innodb_onlinealter_encryption : MDEV-12926 - Valgrind; modified in 10.1.23 +encryption.innodb-missing-key : MDEV-9359 - assertion failure encryption.innodb-page_encryption : MDEV-10641 - mutex problem -encryption.innodb-page_encryption_compression : Modified in 10.1.23 -encryption.innodb-page_encryption_log_encryption : Modified in 10.1.23 -encryption.innodb-redo-badkey : MDEV-12898 - Server hang on startup, also added in 10.1.23 -encryption.innodb-redo-nokeys : Added in 10.1.23 +encryption.innodb-redo-badkey : MDEV-12898 - Server hang on startup encryption.innodb_scrub : MDEV-8139 - scrubbing tests need fixing encryption.innodb_scrub_background : MDEV-8139 - scrubbing tests need fixing encryption.innodb_scrub_compressed : MDEV-8139 - scrubbing tests need fixing @@ -164,68 +149,28 @@ funcs_2.myisam_charset : MDEV-11535 - Timeout #---------------------------------------------------------------- -galera.ev51914 : Added in 10.1.23 -galera.GAL-401 : Added in 10.1.23 -galera.GAL-419 : Added in 10.1.23 -galera.GAL-480 : Added in 10.1.23 -galera.galera_account_management : Modified in 10.1.23 -galera.galera_admin : Added in 10.1.23 galera.galera_autoinc_sst_xtrabackup : Config modified in 10.1.24 -galera.galera_bf_abort : Modified in 10.1.23 galera.galera_defaults : Include file modified in 10.1.24 -galera.galera_desync_overlapped : Added in 10.1.23 -galera.galera_gcache_recover : Added in 10.1.23 -galera.galera_gcache_recover_full_gcache : Added in 10.1.23 -galera.galera_gcache_recover_manytrx : Added in 10.1.23 galera.galera_gcs_fc_limit : Modified in 10.1.24 -galera.galera_many_tables_pk : Modified in 10.1.23 -galera.galera_restart_on_unknown_option : Added in 10.1.23 -galera.galera_roles : Modified in 10.1.23 -galera.galera_toi_ddl_fk_update : Added in 10.1.23 -galera.galera_toi_drop_database : Added in 10.1.23 -galera.galera_toi_truncate : Added in 10.1.23 -galera.galera_var_cluster_address : Modified in 10.1.23 -galera.galera_var_retry_autocommit : Added in 10.1.23 -galera.galera_var_slave_threads : Modified in 10.1.23 -galera.galera_wsrep_log_conficts : Added in 10.1.23 -galera.galera_wsrep_provider_options_syntax : Added in 10.1.23 -galera.galera#414 : Modified in 10.1.23 -galera.lp1376747 : Added in 10.1.23 -galera.lp1376747-2 : Added in 10.1.23 -galera.lp1376747-3 : Added in 10.1.23 -galera.lp1376747-4 : Added in 10.1.23 -galera.MW-258 : Modified in 10.1.23 -galera.MW-309 : Added in 10.1.24 -galera.MW-313 : Added in 10.1.23 -galera.MW-328A : Added in 10.1.23 -galera.MW-328B : Added in 10.1.23 -galera.MW-328C : Added in 10.1.23 -galera.MW-328D : Added in 10.1.23 -galera.MW-328E : Added in 10.1.23 -galera.MW-329 : Added in 10.1.23 -galera.pxc-421 : Added in 10.1.23 +galera.MW-369 : Added in 10.1.25 -galera_3nodes.* : MDEV-11490 - Warnings not suppressed; config files modified in 10.1.24 - -galera_3nodes.galera_safe_to_bootstrap : Added in 10.1.23 +galera_3nodes.* : config files modified in 10.1.24 #---------------------------------------------------------------- -innodb.autoinc_debug : Added in 10.1.23 +innodb.101_compatibility : Modified in 10.1.25 innodb.binlog_consistent : MDEV-10618 - Server fails to start -innodb.doublewrite : MDEV-12905 - Lost connection to MySQL server +innodb.doublewrite : MDEV-12905 - Lost connection to MySQL server; modified in 10.1.25 innodb.drop_table_background : Added in 10.1.24 -innodb.innodb-alter-debug : Added in 10.1.23 -innodb.innodb-alter-nullable : Added in 10.1.23 -innodb.innodb-alter-table : MDEV-10619 - Testcase timeout +innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS; modified in 10.1.25 +innodb.innodb-alter-discard : Modified in 10.1.25 +innodb.innodb-alter-nullable : Modified in 10.1.25 +innodb.innodb-alter-table : MDEV-10619 - Testcase timeout; modified in 10.1.25 +innodb.innodb-alter-tempfile : Modified in 10.1.25 innodb.innodb-blob : MDEV-12053 - Client crash innodb.innodb_bug14147491 : MDEV-11808 - wrong error codes, also modified in 10.1.24 -innodb.innodb_bug14676111 : Modified in 10.1.23 innodb.innodb_bug30423 : MDEV-7311 - Wrong number of rows in the plan innodb.innodb_bug53290 : MDEV-12634 - Valgrind warnings -innodb.innodb_defragment : Modified in 10.1.23 -innodb.innodb_defragment_small : Added in 10.1.23 -innodb.innodb-index-online-norebuild : Added in 10.1.23 innodb.innodb-page_compression_bzip2 : Modified in 10.1.24 innodb.innodb-page_compression_default : Modified in 10.1.24 innodb.innodb-page_compression_lz4 : Modified in 10.1.24 @@ -236,15 +181,29 @@ innodb.innodb-page_compression_zip : MDEV-10641 - mutex problem; modified innodb.innodb_prefix_index_restart_server : MDEV-12899 - Server crash on shutdown innodb.innodb_stats : MDEV-10682 - wrong result innodb.innodb_sys_semaphore_waits : MDEV-10331 - wrong result -innodb.log_data_file_size : MDEV-12893 - Database page corruption -innodb.log_file_size : Modified in 10.1.24 +innodb.log_data_file_size : MDEV-12893 - Database page corruption; modified in 10.1.25 +innodb.log_file_size : Modified in 10.1.25 +innodb.row_format_redundant : Added in 10.1.25 +innodb.table_flags : Added in 10.1.25 innodb_fts.fulltext_misc : MDEV-12636 - Valgrind warnings +innodb_zip.innodb_bug36169 : Modified in 10.1.25 +innodb_zip.innodb_bug36172 : Modified in 10.1.25 +innodb_zip.innodb_bug52745 : Modified in 10.1.25 +innodb_zip.innodb_bug53591 : Modified in 10.1.25 +innodb_zip.innodb_bug56680 : Modified in 10.1.25 +innodb_zip.innodb-create-options : Modified in 10.1.25 +innodb_zip.innodb-zip : Modified in 10.1.25 + #---------------------------------------------------------------- mariabackup.* : suite.pm modified in 10.1.24 +mariabackup.full_backup : Modified in 10.1.25 +mariabackup.incremental_encrypted : Modified in 10.1.25 +mariabackup.xb_file_key_management : Modified in 10.1.25 + #---------------------------------------------------------------- mroonga/storage.column_datetime_32bit_2038 : Wrong result on Alpha @@ -260,6 +219,7 @@ mroonga/storage.repair_table_no_index_file : MDEV-9364 - multi_source.gtid : MDEV-10417 - Fails on Mips multi_source.info_logs : MDEV-10042 - Wrong result, MDEV-12629 - Valgrind warnings +multi_source.mdev-9544 : Added in 10.1.25 multi_source.multisource : MDEV-10417 - Fails on Mips multi_source.reset_slave : MDEV-10690 - wrong result multi_source.simple : MDEV-4633 - Wrong slave status output @@ -271,13 +231,10 @@ parts.partition_innodb_status_file : MDEV-12901 - Valgrind #---------------------------------------------------------------- +perfschema.bad_option_2 : Modified in 10.1.25 perfschema.func_file_io : MDEV-5708 - fails for s390x perfschema.func_mutex : MDEV-5708 - fails for s390x -perfschema.pfs_upgrade_event : Modified in 10.1.23 -perfschema.pfs_upgrade_func : Modified in 10.1.23 -perfschema.pfs_upgrade_proc : Modified in 10.1.23 -perfschema.pfs_upgrade_table : Modified in 10.1.23 -perfschema.pfs_upgrade_view : Modified in 10.1.23 +perfschema.privilege_table_io : MDEV-13184 - Extra lines perfschema.setup_actors : MDEV-10679 - rare crash perfschema.socket_summary_by_event_name_func : MDEV-10622 - Socket summary tables do not match perfschema.stage_mdl_global : MDEV-11803 - wrong result on slow builders @@ -311,10 +268,10 @@ rpl.rpl_insert : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_insert_delayed : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips rpl.rpl_mariadb_slave_capability : MDEV-11018 - sporadic wrong events in binlog -rpl.rpl_mdev-11092 : Added in 10.1.24 +rpl.rpl_mdev-11092 : MDEV-13065 - Wrong value in include; added in 10.1.24 rpl.rpl_mdev6020 : MDEV-10630, MDEV-10417 - Timeouts, fails on Mips -rpl.rpl_mysql_upgrade : Modified in 10.1.23 rpl.rpl_parallel : MDEV-10653 - Timeouts +rpl.rpl_parallel_mdev6589 : MDEV-12979 - Assertion failure rpl.rpl_parallel_optimistic : MDEV-10511 - timeout rpl.rpl_parallel_retry : MDEV-11119 - Server crash rpl.rpl_parallel_temptable : MDEV-10356 - Crash in close_thread_tables @@ -322,6 +279,7 @@ rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips rpl.rpl_password_boundaries : MDEV-11534 - Slave IO warnings rpl.rpl_row_log_innodb : MDEV-10688 - Wrong result rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x +rpl.rpl_row_utf32 : One-time server startup timeout on ppc64le in 10.1.25 rpl.rpl_semi_sync : MDEV-11220 - Wrong result rpl.rpl_semi_sync_event_after_sync : MDEV-11806 - warnings rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Wrong plugin status, MDEV-10892 - Assertion failure @@ -370,6 +328,7 @@ sys_vars.delay_key_write_func : Modified in 10.1.24 sys_vars.keep_files_on_create_basic : MDEV-10676 - timeout sys_vars.innodb_buffer_pool_dump_pct_basic : MDEV-10651 - sporadic failure on file_exists sys_vars.innodb_fatal_semaphore_wait_threshold : MDEV-10513 - crashes +sys_vars.innodb_sched_priority_cleaner_basic : Modified in 10.1.25 sys_vars.log_slow_admin_statements_func : MDEV-12235 - Server crash sys_vars.rpl_init_slave_func : MDEV-10149 - wrong results sys_vars.sysvars_innodb : MDEV-6958 - error-prone rdiffs @@ -424,6 +383,5 @@ vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout wsrep.binlog_format : MDEV-11532 - WSREP has not yet prepared node wsrep.pool_of_threads : MDEV-12234 - Library problem on Power wsrep.variables : Include file modified in 10.1.24 -wsrep.wsrep_rpl : Modified in 10.1.23 wsrep_info.plugin : MDEV-12909 - Wrong result From 39385ff7b253302723a94c896d199a83adb8622f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 27 Jun 2017 13:25:50 +0200 Subject: [PATCH 34/47] MDEV-13187 incorrect backslash parsing in clients don't do backslash escapes inside backticks --- client/mysql.cc | 4 ++-- client/mysqltest.cc | 4 ++-- mysql-test/r/mysql.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/mysql.test | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 57cb0a918a7..6a800e407a3 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2287,8 +2287,8 @@ static bool add_line(String &buffer, char *line, ulong line_length, continue; } #endif - if (!*ml_comment && inchar == '\\' && - !(*in_string && + if (!*ml_comment && inchar == '\\' && *in_string != '`' && + !(*in_string && (mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES))) { // Found possbile one character command like \c diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 4de40953f7d..ee636c9401d 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6594,7 +6594,7 @@ int read_line(char *buf, int size) state= R_Q; } } - have_slash= (c == '\\'); + have_slash= (c == '\\' && last_quote != '`'); break; case R_COMMENT: @@ -6664,7 +6664,7 @@ int read_line(char *buf, int size) case R_Q: if (c == last_quote) state= R_NORMAL; - else if (c == '\\') + else if (c == '\\' && last_quote != '`') state= R_SLASH_IN_Q; break; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index dd0129df0d9..dad8b3a701c 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -529,3 +529,31 @@ a +-------------------+ End of tests +create table `a1\``b1` (a int); +show tables; +Tables_in_test +a1\`b1 +insert `a1\``b1` values (1),(2); +show create table `a1\``b1`; +Table Create Table +a1\`b1 CREATE TABLE `a1\``b1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `a1\``b1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; +INSERT INTO `a1\``b1` VALUES (1),(2); +insert `a1\``b1` values (4),(5); +show create table `a1\``b1`; +Table Create Table +a1\`b1 CREATE TABLE `a1\``b1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from `a1\``b1`; +a +1 +2 +drop table `a1\``b1`; diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index d59083d66b0..20205924e15 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -618,3 +618,18 @@ EOF --echo --echo End of tests + +# +# MDEV-13187 incorrect backslash parsing in clients +# +create table `a1\``b1` (a int); +show tables; +insert `a1\``b1` values (1),(2); +show create table `a1\``b1`; +--exec $MYSQL_DUMP --compact test +--exec $MYSQL_DUMP test > $MYSQLTEST_VARDIR/tmp/bug.sql +insert `a1\``b1` values (4),(5); +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug.sql +show create table `a1\``b1`; +select * from `a1\``b1`; +drop table `a1\``b1`; From d5cd33450413816f8696125cd66c8393921e6267 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 27 Jun 2017 14:00:10 +0200 Subject: [PATCH 35/47] MDEV-13187 incorrect backslash parsing in clients cover ANSI_QUOTES and NO_BACKSLASH_ESCAPES in mysqltest --- client/mysql.cc | 2 ++ client/mysqltest.cc | 14 ++++++++++++-- include/mysql_com.h | 2 ++ mysql-test/r/mysql.result | 30 ++++++++++++++++++++++++++++++ mysql-test/r/mysqltest.result | 5 +++++ mysql-test/t/mysql.test | 15 +++++++++++++++ mysql-test/t/mysqltest.test | 8 +++++++- sql/sql_class.cc | 2 ++ sql/sys_vars.cc | 4 ++++ 9 files changed, 79 insertions(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 6a800e407a3..a965ced89c6 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2288,6 +2288,8 @@ static bool add_line(String &buffer, char *line, ulong line_length, } #endif if (!*ml_comment && inchar == '\\' && *in_string != '`' && + !(*in_string == '"' && + (mysql.server_status & SERVER_STATUS_ANSI_QUOTES)) && !(*in_string && (mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES))) { diff --git a/client/mysqltest.cc b/client/mysqltest.cc index ee636c9401d..f5ee94f1839 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6486,6 +6486,16 @@ my_bool end_of_query(int c) } +static inline bool is_escape_char(char c, char in_string) +{ + if (c != '\\' || in_string == '`') return false; + if (!cur_con) return true; + uint server_status= cur_con->mysql->server_status; + if (server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) return false; + return !(server_status & SERVER_STATUS_ANSI_QUOTES && in_string == '"'); +} + + /* Read one "line" from the file @@ -6594,7 +6604,7 @@ int read_line(char *buf, int size) state= R_Q; } } - have_slash= (c == '\\' && last_quote != '`'); + have_slash= is_escape_char(c, last_quote); break; case R_COMMENT: @@ -6664,7 +6674,7 @@ int read_line(char *buf, int size) case R_Q: if (c == last_quote) state= R_NORMAL; - else if (c == '\\' && last_quote != '`') + else if (is_escape_char(c, last_quote)) state= R_SLASH_IN_Q; break; diff --git a/include/mysql_com.h b/include/mysql_com.h index 0d57b178937..df9681e02a4 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -296,6 +296,8 @@ enum enum_server_command */ #define SERVER_PS_OUT_PARAMS 4096 +#define SERVER_STATUS_ANSI_QUOTES 32768 + /** Server status flags that must be cleared when starting execution of a new SQL statement. diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index dad8b3a701c..8a24128daa2 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -557,3 +557,33 @@ a 1 2 drop table `a1\``b1`; +set sql_mode=ansi_quotes; +create table "a1\""b1" (a int); +show tables; +Tables_in_test +a1\"b1 +insert "a1\""b1" values (1),(2); +show create table "a1\""b1"; +Table Create Table +a1\"b1 CREATE TABLE "a1\""b1" ( + "a" int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE "a1\""b1" ( + "a" int(11) DEFAULT NULL +); +/*!40101 SET character_set_client = @saved_cs_client */; +INSERT INTO "a1\""b1" VALUES (1),(2); +insert "a1\""b1" values (4),(5); +show create table "a1\""b1"; +Table Create Table +a1\"b1 CREATE TABLE "a1\""b1" ( + "a" int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from "a1\""b1"; +a +1 +2 +drop table "a1\""b1"; +set sql_mode=default; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 0ebef585974..9800aed6368 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -957,4 +957,9 @@ con1 con2 con2 -closed_connection- +set sql_mode=no_backslash_escapes; +select "foo\""bar"; +foo\"bar +foo\"bar +set sql_mode=default; End of tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 20205924e15..dd964c46420 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -633,3 +633,18 @@ insert `a1\``b1` values (4),(5); show create table `a1\``b1`; select * from `a1\``b1`; drop table `a1\``b1`; + +# same with ansi_quotes +set sql_mode=ansi_quotes; +create table "a1\""b1" (a int); +show tables; +insert "a1\""b1" values (1),(2); +show create table "a1\""b1"; +--exec $MYSQL_DUMP --compact --compatible=postgres test +--exec $MYSQL_DUMP --compatible=postgres test > $MYSQLTEST_VARDIR/tmp/bug.sql +insert "a1\""b1" values (4),(5); +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug.sql +show create table "a1\""b1"; +select * from "a1\""b1"; +drop table "a1\""b1"; +set sql_mode=default; diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 6470ede4f14..afe37926591 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -2942,11 +2942,17 @@ disconnect $x; # Disconnect the selected connection disconnect $y; --echo $CURRENT_CONNECTION +connection default; +# +# MDEV-13187 incorrect backslash parsing in clients +# +set sql_mode=no_backslash_escapes; +select "foo\""bar"; +set sql_mode=default; --echo End of tests -connection default; # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 46eabb41a74..3c07c1606a2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1250,6 +1250,8 @@ void THD::init(void) server_status= SERVER_STATUS_AUTOCOMMIT; if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; + if (variables.sql_mode & MODE_ANSI_QUOTES) + server_status|= SERVER_STATUS_ANSI_QUOTES; transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 35997525456..ffe861ddfbc 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2173,6 +2173,10 @@ static bool fix_sql_mode(sys_var *self, THD *thd, enum_var_type type) thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; else thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES; + if (thd->variables.sql_mode & MODE_ANSI_QUOTES) + thd->server_status|= SERVER_STATUS_ANSI_QUOTES; + else + thd->server_status&= ~SERVER_STATUS_ANSI_QUOTES; } return false; } From 5c89f23b4591db0c60eed34caaa28e1ba67bea63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 29 Jun 2017 21:27:05 +0300 Subject: [PATCH 36/47] Fix debug assert post MDEV-10306 tmp variable now points to str->ptr() buffer, not tmp_value buffer. Comparing pointers otherwise can lead to false assertion errors as we don't know where buffers are allocated in respect to each other. --- sql/item_strfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f559677051b..22e13bf6c38 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1171,7 +1171,7 @@ String *Item_func_reverse::val_str(String *str) if ((l= my_ismbchar(res->charset(),ptr,end))) { tmp-= l; - DBUG_ASSERT(tmp >= tmp_value.ptr()); + DBUG_ASSERT(tmp >= str->ptr()); memcpy(tmp,ptr,l); ptr+= l; } From 4db6e1e4a502df5a4b30aed60552314533b35d79 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 29 Jun 2017 20:47:08 +0200 Subject: [PATCH 37/47] uninitialized variable --- client/mysqltest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f5ee94f1839..98e35136b2a 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6522,7 +6522,7 @@ static inline bool is_escape_char(char c, char in_string) int read_line(char *buf, int size) { - char c, UNINIT_VAR(last_quote), last_char= 0; + char c, last_quote=0, last_char= 0; char *p= buf, *buf_end= buf + size - 1; int skip_char= 0; my_bool have_slash= FALSE; From 273e0f663e5a7254aa4e956572f6faa97e5579c9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 30 Jun 2017 10:28:01 +0200 Subject: [PATCH 38/47] MDEV-13179 main.errors fails in buildbot and outside with wrong errno 1290 --- mysql-test/r/errors.result | 2 +- mysql-test/t/errors.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result index bf75bf73862..be1a9f06810 100644 --- a/mysql-test/r/errors.result +++ b/mysql-test/r/errors.result @@ -170,5 +170,5 @@ ERROR 22007: Illegal value used as argument of dynamic column function drop table t1; set max_session_mem_used = 8192; select * from seq_1_to_1000; -ERROR HY000: Engine SEQUENCE failed to discover table `test`.`seq_1_to_1000` with 'create table seq (seq bigint unsigned primary key)' +Got one of the listed errors set global max_session_mem_used = default; diff --git a/mysql-test/t/errors.test b/mysql-test/t/errors.test index 9d5cbef89b1..d1d83248df4 100644 --- a/mysql-test/t/errors.test +++ b/mysql-test/t/errors.test @@ -204,6 +204,6 @@ drop table t1; # errors caused by max_session_mem_used # set max_session_mem_used = 8192; ---error ER_SQL_DISCOVER_ERROR +--error ER_SQL_DISCOVER_ERROR,ER_OPTION_PREVENTS_STATEMENT select * from seq_1_to_1000; set global max_session_mem_used = default; From 4fe89773d811f1414165d1efb1b910a7f47a69f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 22 Jun 2017 12:21:54 +0300 Subject: [PATCH 39/47] Mariabackup: Clean up xtrabackup options Fix the binding of databases_file. It was incorrectly mapped to OPT_XTRA_TABLES_FILE. Remove some unused options and variables. --- extra/mariabackup/xtrabackup.cc | 21 +-------------------- extra/mariabackup/xtrabackup.h | 4 ---- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index a268c3f7a78..6e15a9973ce 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -239,7 +239,6 @@ long innobase_open_files = 300L; longlong innobase_page_size = (1LL << 14); /* 16KB */ static ulong innobase_log_block_size = 512; -my_bool innobase_fast_checksum = FALSE; char* innobase_doublewrite_file = NULL; char* innobase_buffer_pool_filename = NULL; @@ -361,9 +360,6 @@ const char *opt_history = NULL; #if defined(HAVE_OPENSSL) my_bool opt_ssl_verify_server_cert = FALSE; -#if !defined(HAVE_YASSL) -char *opt_server_public_key = NULL; -#endif #endif /* Whether xtrabackup_binlog_info should be created on recovery */ @@ -511,8 +507,6 @@ enum options_xtrabackup OPT_INNODB_USE_NATIVE_AIO, OPT_INNODB_PAGE_SIZE, OPT_INNODB_LOG_BLOCK_SIZE, - OPT_INNODB_FAST_CHECKSUM, - OPT_INNODB_EXTRA_UNDOSLOTS, OPT_INNODB_DOUBLEWRITE_FILE, OPT_INNODB_BUFFER_POOL_FILENAME, OPT_INNODB_FORCE_RECOVERY, @@ -564,10 +558,6 @@ enum options_xtrabackup OPT_BINLOG_INFO, OPT_XB_SECURE_AUTH, - OPT_SSL_SSL, - OPT_SSL_VERIFY_SERVER_CERT, - OPT_SERVER_PUBLIC_KEY, - OPT_XTRA_TABLES_EXCLUDE, OPT_XTRA_DATABASES_EXCLUDE, }; @@ -629,7 +619,7 @@ struct my_option xb_client_options[] = {"databases", OPT_XTRA_DATABASES, "filtering by list of databases.", (G_PTR*) &xtrabackup_databases, (G_PTR*) &xtrabackup_databases, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"databases_file", OPT_XTRA_TABLES_FILE, + {"databases_file", OPT_XTRA_DATABASES_FILE, "filtering by list of databases in the file.", (G_PTR*) &xtrabackup_databases_file, (G_PTR*) &xtrabackup_databases_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -1060,10 +1050,6 @@ Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, "Changing for created log file is not supported. Use on your own risk!", (G_PTR*) &innobase_log_block_size, (G_PTR*) &innobase_log_block_size, 0, GET_ULONG, REQUIRED_ARG, 512, 512, 1 << UNIV_PAGE_SIZE_SHIFT_MAX, 0, 1L, 0}, - {"innodb_fast_checksum", OPT_INNODB_FAST_CHECKSUM, - "Change the algorithm of checksum for the whole of datapage to 4-bytes word based.", - (G_PTR*) &innobase_fast_checksum, - (G_PTR*) &innobase_fast_checksum, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_doublewrite_file", OPT_INNODB_DOUBLEWRITE_FILE, "Path to special datafile for doublewrite buffer. (default is "": not used)", (G_PTR*) &innobase_doublewrite_file, (G_PTR*) &innobase_doublewrite_file, @@ -1290,11 +1276,6 @@ xb_get_one_option(int optid, ADD_PRINT_PARAM_OPT(innobase_page_size); break; - case OPT_INNODB_FAST_CHECKSUM: - - ADD_PRINT_PARAM_OPT(!!innobase_fast_checksum); - break; - case OPT_INNODB_LOG_BLOCK_SIZE: ADD_PRINT_PARAM_OPT(innobase_log_block_size); diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index a26f00f6b06..455b85c4abc 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -213,11 +213,7 @@ bool check_if_param_set(const char *param); #if defined(HAVE_OPENSSL) -extern my_bool opt_use_ssl; extern my_bool opt_ssl_verify_server_cert; -#if !defined(HAVE_YASSL) -extern char *opt_server_public_key; -#endif #endif From a1e51e7f479cab7f46c12d0c488a6b310ae64807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 30 Jun 2017 11:28:52 +0300 Subject: [PATCH 40/47] Mariabackup: Test file cleanup --- .../suite/mariabackup/include/restart_and_restore.inc | 10 ++-------- .../suite/mariabackup/xb_compressed_encrypted.test | 6 +++--- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/mariabackup/include/restart_and_restore.inc b/mysql-test/suite/mariabackup/include/restart_and_restore.inc index 7ee4a660b78..9056867b07f 100644 --- a/mysql-test/suite/mariabackup/include/restart_and_restore.inc +++ b/mysql-test/suite/mariabackup/include/restart_and_restore.inc @@ -1,15 +1,9 @@ -let $_server_id= `SELECT @@server_id`; let $_datadir= `SELECT @@datadir`; -let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect; -exec echo "wait" > $_expect_file_name; echo # shutdown server; -shutdown_server; +--source include/shutdown_mysqld.inc echo # remove datadir; rmdir $_datadir; echo # xtrabackup move back; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir --parallel=2 --throttle=1; echo # restart server; -exec echo "restart" > $_expect_file_name; -enable_reconnect; -source include/wait_until_connected_again.inc; -disable_reconnect; +--source include/start_mysqld.inc diff --git a/mysql-test/suite/mariabackup/xb_compressed_encrypted.test b/mysql-test/suite/mariabackup/xb_compressed_encrypted.test index 11f63eb0330..9a5be4b19d6 100644 --- a/mysql-test/suite/mariabackup/xb_compressed_encrypted.test +++ b/mysql-test/suite/mariabackup/xb_compressed_encrypted.test @@ -1,7 +1,7 @@ source include/have_file_key_management.inc; CREATE TABLE t1(c1 INT, b VARCHAR(2400), index(b(100),c1)) ENGINE=INNODB ROW_FORMAT=compressed ENCRYPTED=YES; - + DELIMITER //; CREATE PROCEDURE innodb_insert_proc (REPEAT_COUNT INT) BEGIN @@ -14,12 +14,12 @@ BEGIN END// DELIMITER ;// COMMIT; - + SET AUTOCOMMIT=0; CALL innodb_insert_proc(50000); COMMIT; - + echo # xtrabackup backup; --disable_result_log let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; From b503b1c0edaa976e90b9bf3339677a710752e58a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 23 Jun 2017 15:14:22 +0200 Subject: [PATCH 41/47] MDEV-11646 main.myisam, maria.maria, main.mix2_myisam, main.myisampack, main.mrr_icp_extra fail in buildbot with valgrind (Syscall param pwrite64(buf) points to uninitialised byte(s)) If the table has a varchar column and a forced fixed for format (as in varchar.inc), Field_varstring::store() will only store the actual number of bytes, not padded, in the record[0]. That is, on inserts a part of record[0] can be uninitialized. Fix: initialize record[0] when a TABLE is created, it doesn't matter what kind of garbage can be in this unused/invisible part of the record, as long as it's not some random memory contents (that can contain sensitive data). --- sql/sql_insert.cc | 7 +------ sql/table.cc | 11 +---------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 88eb76ef1ed..e750e97194a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -970,12 +970,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, be overwritten by fill_record() anyway (and fill_record() does not use default values in this case). */ -#ifdef HAVE_valgrind - if (table->file->ha_table_flags() && HA_RECORD_MUST_BE_CLEAN_ON_WRITE) - restore_record(table,s->default_values); // Get empty record - else -#endif - table->record[0][0]= share->default_values[0]; + table->record[0][0]= share->default_values[0]; /* Fix undefined null_bits. */ if (share->null_bytes > 1 && share->last_null_bit_pos) diff --git a/sql/table.cc b/sql/table.cc index a1e9ebfc0cc..3ab89897e07 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4150,16 +4150,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) DBUG_ASSERT(key_read == 0); - /* mark the record[0] uninitialized */ - TRASH(record[0], s->reclength); - - /* - Initialize the null marker bits, to ensure that if we are doing a read - of only selected columns (like in keyread), all null markers are - initialized. - */ - memset(record[0], 255, s->null_bytes); - memset(record[1], 255, s->null_bytes); + restore_record(this, s->default_values); /* Tables may be reused in a sub statement. */ DBUG_ASSERT(!file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN)); From 806d4e3127b8ceac4e1517139d40be0a9f85822f Mon Sep 17 00:00:00 2001 From: Jacob Mathew Date: Fri, 30 Jun 2017 16:17:29 -0700 Subject: [PATCH 42/47] Run spider mtr suites in 10.1 only on demand. --- storage/spider/mysql-test/spider/bg/suite.pm | 1 + storage/spider/mysql-test/spider/suite.pm | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/spider/mysql-test/spider/bg/suite.pm b/storage/spider/mysql-test/spider/bg/suite.pm index 5569c57bec9..1bb6d7592c8 100644 --- a/storage/spider/mysql-test/spider/bg/suite.pm +++ b/storage/spider/mysql-test/spider/bg/suite.pm @@ -4,6 +4,7 @@ package My::Suite::Spider; return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "Not run for embedded server" if $::opt_embedded_server; +return "Test needs --big-test" unless $::opt_big_test; bless { }; diff --git a/storage/spider/mysql-test/spider/suite.pm b/storage/spider/mysql-test/spider/suite.pm index 171fa6c4f01..1bb6d7592c8 100644 --- a/storage/spider/mysql-test/spider/suite.pm +++ b/storage/spider/mysql-test/spider/suite.pm @@ -4,8 +4,7 @@ package My::Suite::Spider; return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "Not run for embedded server" if $::opt_embedded_server; - -sub is_default { 1 } +return "Test needs --big-test" unless $::opt_big_test; bless { }; From da7604a2943f633df3b193e26ee20110bae9fa7a Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sat, 1 Jul 2017 21:12:26 +0300 Subject: [PATCH 43/47] Latest additions to the list of unstable tests in 10.1.25 --- mysql-test/unstable-tests | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 9e7d4f7f76f..0aa1425ce4c 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -28,14 +28,19 @@ main.alter_table_trans : MDEV-12084 - timeout main.analyze_format_json : MDEV-11866 - Wrong result main.analyze_stmt_orderby : MDEV-11866 - Wrong result main.analyze_stmt_slow_query_log : MDEV-12237 - Wrong result +main.bootstrap : Modified in 10.1.25 main.create_delayed : MDEV-10605 - failed with timeout +main.ctype_ucs : Modified in 10.1.25 main.ctype_utf16le : MDEV-10675: timeout or extra warnings main.derived_view : Modified in 10.1.24 main.drop-no_root : MDEV-12633 - Valgrind warnings main.errors : MDEV-13179 - Wrong error 1290; modified in 10.1.25 main.events_bugs : MDEV-12892 - Crash in fill_schema_processlist main.events_restart : MDEV-12236 - Server shutdown problem +main.func_concat : Modified in 10.1.25 +main.func_crypt : Modified in 10.1.25 main.func_regexp_pcre : Modified in 10.1.25 +main.gis : Modified in 10.1.25 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout main.index_merge_innodb : MDEV-7142 - Wrong execution plan, timeout with valgrind @@ -48,9 +53,10 @@ main.mdev375 : MDEV-10607 - sporadic "can't connect" main.mdl_sync : Modified in 10.1.25 main.merge : MDEV-10607 - sporadic "can't connect" main.myisam_debug : Modified in 10.1.24 +main.mysql : Modified in 10.1.25 main.mysqlcheck : MDEV-12633 - Valgrind warnings main.mysqlslap : MDEV-11801 - timeout -main.mysqltest : MDEV-9269 - fails on Alpha; modified in 10.1.24 +main.mysqltest : MDEV-9269 - fails on Alpha; modified in 10.1.25 main.mysql_client_test : MDEV-12633 - Valgrind warnings main.mysql_client_test_comp : MDEV-12633 - Valgrind warnings main.mysql_client_test_nonblock : MDEV-12633 - Valgrind warnings @@ -69,9 +75,10 @@ main.show_explain : MDEV-10674 - sporadic failure main.sp-security : MDEV-10607 - sporadic "can't connect" main.status : MDEV-8510 - sporadic wrong result main.subselect_innodb : MDEV-10614 - sporadic wrong results -main.subselect_mat_cost_bugs : Modified in 10.1.24 +main.subselect_mat_cost_bugs : Modified in 10.1.25 main.subselect_sj : Modified in 10.1.24 -main.subselect_sj2_mat : Modified in 10.1.24 +main.subselect_sj_mat : Modified in 10.1.25 +main.subselect_sj2_mat : Modified in 10.1.25 main.symlink-aria-11902 : MDEV-12215 - Unexpected errors main.symlink-myisam-11902 : MDEV-12215 - Unexpected errors main.type_datetime_hires : MDEV-10687 - timeout @@ -143,6 +150,7 @@ federated.federatedx : MDEV-10617 - Wrong checksum, timeouts #---------------------------------------------------------------- funcs_1.processlist_val_no_prot : MDEV-11223 - Wrong result +funcs_1.processlist_val_ps : MDEV-12175 - Wrong plan funcs_2.memory_charset : MDEV-10290 - Timeout funcs_2.myisam_charset : MDEV-11535 - Timeout @@ -150,7 +158,7 @@ funcs_2.myisam_charset : MDEV-11535 - Timeout #---------------------------------------------------------------- galera.galera_autoinc_sst_xtrabackup : Config modified in 10.1.24 -galera.galera_defaults : Include file modified in 10.1.24 +galera.galera_defaults : Modified in 10.1.25 galera.galera_gcs_fc_limit : Modified in 10.1.24 galera.MW-369 : Added in 10.1.25 @@ -201,8 +209,14 @@ innodb_zip.innodb-zip : Modified in 10.1.25 mariabackup.* : suite.pm modified in 10.1.24 mariabackup.full_backup : Modified in 10.1.25 +mariabackup.incremental_backup : Uses include file modified in 10.1.25 mariabackup.incremental_encrypted : Modified in 10.1.25 +mariabackup.xb_aws_key_management : Uses include file modified in 10.1.25 +mariabackup.xb_compressed_encrypted : Modified in 10.1.25 mariabackup.xb_file_key_management : Modified in 10.1.25 +mariabackup.xb_fulltext_encrypted : Uses include file modified in 10.1.25 +mariabackup.xb_partition : Uses include file modified in 10.1.25 +mariabackup.xbstream : Uses include file modified in 10.1.25 #---------------------------------------------------------------- @@ -227,7 +241,8 @@ multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_h #---------------------------------------------------------------- -parts.partition_innodb_status_file : MDEV-12901 - Valgrind +parts.partition_innodb_status_file : MDEV-12901 - Valgrind +parts.quoting : Modified in 10.1.25 #---------------------------------------------------------------- @@ -250,6 +265,11 @@ plugins.thread_pool_server_audit : MDEV-9562 - crashes on sol10-sparc #---------------------------------------------------------------- +roles.current_role_view-12666 : Added in 10.1.25 +roles.show_create_database-10463 : Added in 10.1.25 + +#---------------------------------------------------------------- + rpl.last_insert_id : MDEV-10625 - warnings in error log rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips @@ -382,6 +402,6 @@ vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout wsrep.binlog_format : MDEV-11532 - WSREP has not yet prepared node wsrep.pool_of_threads : MDEV-12234 - Library problem on Power -wsrep.variables : Include file modified in 10.1.24 +wsrep.variables : Include file modified in 10.1.25 wsrep_info.plugin : MDEV-12909 - Wrong result From 228479a28ce7e4c91f96962159fccc8dc71b5a36 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 29 May 2017 11:35:36 +0300 Subject: [PATCH 44/47] MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail CREATE/DROP TEMPORARY TABLE are not safe to optimistically replicate in parallel with other transactions, so they need to be marked as "ddl" in the binlog. This was already done for stand-alone CREATE/DROP TEMPORARY. But temporary tables can also be created and dropped inside a BEGIN...END transaction, and such transactions were not marked as ddl. Nor was the DROP TEMPORARY TABLE statement emitted implicitly when a client connection is closed. So this patch adds such ddl mark for the missing cases. The difference to Kristian's original patch is mainly a fix in mysql_trans_commit_alter_copy_data() to remember the unsafe_rollback_flags over the temporary commit. --- .../binlog_parallel_replication_marks.test | 85 ++++++++++++++++ ...nlog_parallel_replication_marks_row.result | 97 +++++++++++++++++++ ..._parallel_replication_marks_stm_mix.result | 96 ++++++++++++++++++ ...binlog_parallel_replication_marks_row.test | 3 + ...og_parallel_replication_marks_stm_mix.test | 3 + .../rpl/r/rpl_parallel_optimistic.result | 47 +++++++++ .../suite/rpl/t/rpl_parallel_optimistic.test | 24 +++++ sql/handler.h | 14 +++ sql/log_event.cc | 6 +- sql/sql_base.cc | 1 + sql/sql_class.h | 10 ++ sql/sql_insert.cc | 9 ++ sql/sql_parse.cc | 4 +- sql/sql_table.cc | 27 ++++-- sql/transaction.cc | 29 +++--- 15 files changed, 429 insertions(+), 26 deletions(-) create mode 100644 mysql-test/include/binlog_parallel_replication_marks.test create mode 100644 mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result create mode 100644 mysql-test/suite/binlog/r/binlog_parallel_replication_marks_stm_mix.result create mode 100644 mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test create mode 100644 mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test diff --git a/mysql-test/include/binlog_parallel_replication_marks.test b/mysql-test/include/binlog_parallel_replication_marks.test new file mode 100644 index 00000000000..1b6fbe26142 --- /dev/null +++ b/mysql-test/include/binlog_parallel_replication_marks.test @@ -0,0 +1,85 @@ +# Test the markings on GTID events (ddl, waited, trans, +# @@skip_parallel_replication) that are used to control parallel +# replication on the slave. + +--source include/have_innodb.inc + +RESET MASTER; +--source include/wait_for_binlog_checkpoint.inc + +set time_zone="+02:00"; +--let $stable_stamp= `SELECT UNIX_TIMESTAMP("2020-01-21 15:32:22")` +eval set timestamp=$stable_stamp; + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +--let $binlog_pos1=query_get_value(SHOW MASTER STATUS, Position, 1) +/* GTID */ INSERT INTO t1 VALUES (1,0); +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (2,0); +/* GTID */ ALTER TABLE t1 ADD c INT; +/* GTID */ INSERT INTO t1 VALUES (3,0,0); +/* GTID */ COMMIT; +/* GTID */ BEGIN; +/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2; +/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20); +/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2; +/* GTID */ DROP TEMPORARY TABLE t2; +/* GTID */ INSERT INTO t1 VALUES (6, 3, 0); +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ DELETE FROM t1 WHERE a=5; +/* GTID */ INSERT INTO t3 VALUES (7); +/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3; +/* GTID */ UPDATE t1 SET c=1 WHERE a=7; +/* GTID */ DROP TEMPORARY TABLE t3; +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (8, 5, 0); +/* GTID */ ALTER TABLE t4 ADD b INT; +/* GTID */ INSERT INTO t1 VALUES (9, 5, 1); +/* GTID */ COMMIT; +connect (tmp_con,localhost,root,,); +eval set timestamp=$stable_stamp; +/* GTID */ INSERT INTO t1 VALUES (10, 6, 0); +/* GTID */ BEGIN; +/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ INSERT INTO t1 VALUES (11, 7, 0); +/* GTID */ COMMIT; +--let $before_drop_pos=query_get_value(SHOW MASTER STATUS, Position, 1) +disconnect tmp_con; +connection default; + +# We need to wait for the implicit DROP TEMPORARY TABLE to be logged after +# tmp_con disconnect, otherwise we get sporadic test failures. +--let $wait_condition= SELECT variable_value > $before_drop_pos FROM information_schema.global_status WHERE variable_name = 'binlog_snapshot_position' +--source include/wait_condition.inc + +--let $binlog_pos2=query_get_value(SHOW MASTER STATUS, Position, 1) + +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +FLUSH LOGS; + +--let $MYSQLD_DATADIR= `select @@datadir` +--let $file= $MYSQLTEST_VARDIR/tmp/binlog_parallel_replication_marks.out +--let OUTPUT_FILE=$file +exec $MYSQL_BINLOG --start_position=$binlog_pos1 --stop_position=$binlog_pos2 $MYSQLD_DATADIR/$binlog_file > $file; + +perl; +my $file= $ENV{'OUTPUT_FILE'}; +open F, "<", $file + or die "Unable to open file '$file': $!\n"; +while () { + s/^#\d+ \d+:\d+:\d+ /# /; + s/GTID \d+-\d+-\d+/GTID #-#-#/; + s/end_log_pos \d+/end_log_pos #/; + s/table id \d+/table id #/; + s/mapped to number \d+/mapped to number #/; + print if /GTID|BEGIN|COMMIT|Table_map|Write_rows|Update_rows|Delete_rows|generated by server|40005 TEMPORARY/; +} +close F; +EOF + +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result new file mode 100644 index 00000000000..b0bba30bd00 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result @@ -0,0 +1,97 @@ +RESET MASTER; +set time_zone="+02:00"; +set timestamp=1579613542; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +/* GTID */ INSERT INTO t1 VALUES (1,0); +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (2,0); +/* GTID */ ALTER TABLE t1 ADD c INT; +/* GTID */ INSERT INTO t1 VALUES (3,0,0); +/* GTID */ COMMIT; +/* GTID */ BEGIN; +/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2; +/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20); +/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2; +/* GTID */ DROP TEMPORARY TABLE t2; +/* GTID */ INSERT INTO t1 VALUES (6, 3, 0); +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ DELETE FROM t1 WHERE a=5; +/* GTID */ INSERT INTO t3 VALUES (7); +/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3; +/* GTID */ UPDATE t1 SET c=1 WHERE a=7; +/* GTID */ DROP TEMPORARY TABLE t3; +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (8, 5, 0); +/* GTID */ ALTER TABLE t4 ADD b INT; +/* GTID */ INSERT INTO t1 VALUES (9, 5, 1); +/* GTID */ COMMIT; +set timestamp=1579613542; +/* GTID */ INSERT INTO t1 VALUES (10, 6, 0); +/* GTID */ BEGIN; +/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ INSERT INTO t1 VALUES (11, 7, 0); +/* GTID */ COMMIT; +FLUSH LOGS; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +/* GTID */ ALTER TABLE t1 ADD c INT +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Update_rows: table id # flags: STMT_END_F +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Delete_rows: table id # flags: STMT_END_F +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Update_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t5` +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_stm_mix.result b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_stm_mix.result new file mode 100644 index 00000000000..c5dffff7446 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_stm_mix.result @@ -0,0 +1,96 @@ +RESET MASTER; +set time_zone="+02:00"; +set timestamp=1579613542; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +/* GTID */ INSERT INTO t1 VALUES (1,0); +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (2,0); +/* GTID */ ALTER TABLE t1 ADD c INT; +/* GTID */ INSERT INTO t1 VALUES (3,0,0); +/* GTID */ COMMIT; +/* GTID */ BEGIN; +/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2; +/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20); +/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2; +/* GTID */ DROP TEMPORARY TABLE t2; +/* GTID */ INSERT INTO t1 VALUES (6, 3, 0); +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ DELETE FROM t1 WHERE a=5; +/* GTID */ INSERT INTO t3 VALUES (7); +/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3; +/* GTID */ UPDATE t1 SET c=1 WHERE a=7; +/* GTID */ DROP TEMPORARY TABLE t3; +/* GTID */ COMMIT; +/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ BEGIN; +/* GTID */ INSERT INTO t1 VALUES (8, 5, 0); +/* GTID */ ALTER TABLE t4 ADD b INT; +/* GTID */ INSERT INTO t1 VALUES (9, 5, 1); +/* GTID */ COMMIT; +set timestamp=1579613542; +/* GTID */ INSERT INTO t1 VALUES (10, 6, 0); +/* GTID */ BEGIN; +/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB; +/* GTID */ INSERT INTO t1 VALUES (11, 7, 0); +/* GTID */ COMMIT; +FLUSH LOGS; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (1,0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (2,0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +/* GTID */ ALTER TABLE t1 ADD c INT +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (3,0,0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +BEGIN +/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2 +/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB +/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20) +/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2 +DROP TEMPORARY TABLE `t2` /* generated by server */ +/* GTID */ INSERT INTO t1 VALUES (6, 3, 0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB +# server id 1 end_log_pos # GTID #-#-# ddl +BEGIN +/* GTID */ DELETE FROM t1 WHERE a=5 +/* GTID */ INSERT INTO t3 VALUES (7) +/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3 +/* GTID */ UPDATE t1 SET c=1 WHERE a=7 +DROP TEMPORARY TABLE `t3` /* generated by server */ +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (8, 5, 0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +/* GTID */ ALTER TABLE t4 ADD b INT +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (9, 5, 1) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# trans +BEGIN +/* GTID */ INSERT INTO t1 VALUES (10, 6, 0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +BEGIN +/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB +/* GTID */ INSERT INTO t1 VALUES (11, 7, 0) +COMMIT/*!*/; +# server id 1 end_log_pos # GTID #-#-# ddl +DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t5` +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test new file mode 100644 index 00000000000..82898486089 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test @@ -0,0 +1,3 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc +--source include/binlog_parallel_replication_marks.test diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test new file mode 100644 index 00000000000..15042b3a07f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test @@ -0,0 +1,3 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed_or_statement.inc +--source include/binlog_parallel_replication_marks.test diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result index fc8a5edc997..0177e65b10f 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result @@ -496,6 +496,53 @@ a b 57 7 58 8 59 9 +*** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail *** +include/stop_slave.inc +INSERT INTO t1 VALUES (40, 10); +CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (41); +BEGIN; +INSERT INTO t2 SELECT a, 20 FROM t1; +DROP TEMPORARY TABLE t1; +COMMIT; +INSERT INTO t1 VALUES (42, 10); +include/save_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +a b +40 10 +42 10 +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; +a b +41 20 +50 0 +51 1 +52 2 +53 3 +54 4 +55 5 +56 6 +57 7 +58 8 +59 9 +include/start_slave.inc +include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +a b +40 10 +42 10 +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; +a b +41 20 +50 0 +51 1 +52 2 +53 3 +54 4 +55 5 +56 6 +57 7 +58 8 +59 9 include/stop_slave.inc SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test index 93dfe4d5e7c..41fb6ebb72e 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -456,6 +456,30 @@ SELECT * FROM t2 WHERE a >= 50 ORDER BY a; SELECT * FROM t2 WHERE a >= 50 ORDER BY a; +--echo *** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (40, 10); +CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (41); +BEGIN; +INSERT INTO t2 SELECT a, 20 FROM t1; +DROP TEMPORARY TABLE t1; +COMMIT; +INSERT INTO t1 VALUES (42, 10); +--source include/save_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; + # Clean up. --connection server_2 diff --git a/sql/handler.h b/sql/handler.h index dad2b81b39c..1d4dded3971 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1470,16 +1470,30 @@ struct THD_TRANS static unsigned int const CREATED_TEMP_TABLE= 0x02; static unsigned int const DROPPED_TEMP_TABLE= 0x04; static unsigned int const DID_WAIT= 0x08; + static unsigned int const DID_DDL= 0x10; void mark_created_temp_table() { DBUG_PRINT("debug", ("mark_created_temp_table")); m_unsafe_rollback_flags|= CREATED_TEMP_TABLE; } + void mark_dropped_temp_table() + { + DBUG_PRINT("debug", ("mark_dropped_temp_table")); + m_unsafe_rollback_flags|= DROPPED_TEMP_TABLE; + } + bool has_created_dropped_temp_table() const { + return + (m_unsafe_rollback_flags & (CREATED_TEMP_TABLE|DROPPED_TEMP_TABLE)) != 0; + } void mark_trans_did_wait() { m_unsafe_rollback_flags|= DID_WAIT; } bool trans_did_wait() const { return (m_unsafe_rollback_flags & DID_WAIT) != 0; } + void mark_trans_did_ddl() { m_unsafe_rollback_flags|= DID_DDL; } + bool trans_did_ddl() const { + return (m_unsafe_rollback_flags & DID_DDL) != 0; + } }; diff --git a/sql/log_event.cc b/sql/log_event.cc index f098664b1ba..4265a23df2b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6635,8 +6635,10 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg, if (thd_arg->transaction.stmt.trans_did_wait() || thd_arg->transaction.all.trans_did_wait()) flags2|= FL_WAITED; - if (sql_command_flags[thd->lex->sql_command] & - (CF_DISALLOW_IN_RO_TRANS | CF_AUTO_COMMIT_TRANS)) + if (thd_arg->transaction.stmt.trans_did_ddl() || + thd_arg->transaction.stmt.has_created_dropped_temp_table() || + thd_arg->transaction.all.trans_did_ddl() || + thd_arg->transaction.all.has_created_dropped_temp_table()) flags2|= FL_DDL; else if (is_transactional) flags2|= FL_TRANSACTIONAL; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9c56b7d8f22..ae10c0b771d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1245,6 +1245,7 @@ bool close_temporary_tables(THD *thd) thd->variables.character_set_client= cs_save; thd->get_stmt_da()->set_overwrite_status(true); + thd->transaction.stmt.mark_dropped_temp_table(); if ((error= (mysql_bin_log.write(&qinfo) || error))) { /* diff --git a/sql/sql_class.h b/sql/sql_class.h index db1214ab26b..342902363c6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4048,6 +4048,16 @@ public: { main_lex.restore_set_statement_var(); } + /* Copy relevant `stmt` transaction flags to `all` transaction. */ + void merge_unsafe_rollback_flags() + { + if (transaction.stmt.modified_non_trans_table) + transaction.all.modified_non_trans_table= TRUE; + transaction.all.m_unsafe_rollback_flags|= + (transaction.stmt.m_unsafe_rollback_flags & + (THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE | + THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL)); + } }; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e750e97194a..092b2154c61 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4360,6 +4360,15 @@ void select_create::store_values(List &values) bool select_create::send_eof() { DBUG_ENTER("select_create::send_eof"); + + /* + The routine that writes the statement in the binary log + is in select_insert::prepare_eof(). For that reason, we + mark the flag at this point. + */ + if (table->s->tmp_table) + thd->transaction.stmt.mark_created_temp_table(); + if (prepare_eof()) { abort_result_set(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 62d73f5306a..c4b32933b8a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2847,6 +2847,7 @@ mysql_execute_command(THD *thd) goto error; } } + thd->transaction.stmt.mark_trans_did_ddl(); } #ifndef DBUG_OFF @@ -6936,8 +6937,7 @@ void THD::reset_for_next_command() if (!thd->in_multi_stmt_transaction_mode()) { thd->variables.option_bits&= ~OPTION_KEEP_LOG; - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); } DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx); thd->thread_specific_used= FALSE; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index db0d6d4f377..ace8ff1a7a9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2560,6 +2560,9 @@ err: if (non_trans_tmp_table_deleted || trans_tmp_table_deleted || non_tmp_table_deleted) { + if (non_trans_tmp_table_deleted || trans_tmp_table_deleted) + thd->transaction.stmt.mark_dropped_temp_table(); + query_cache_invalidate3(thd, tables, 0); if (!dont_log_query && mysql_bin_log.is_open()) { @@ -5073,6 +5076,9 @@ err: if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) DBUG_RETURN(result); + if (create_info->tmp_table()) + thd->transaction.stmt.mark_created_temp_table(); + /* Write log if no error or if we already deleted a table */ if (!result || thd->log_current_statement) { @@ -5567,13 +5573,17 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, DBUG_PRINT("info", ("res: %d tmp_table: %d create_info->table: %p", res, create_info->tmp_table(), local_create_info.table)); - if (!res && create_info->tmp_table() && local_create_info.table) + if (create_info->tmp_table()) { - /* - Remember that tmp table creation was logged so that we know if - we should log a delete of it. - */ - local_create_info.table->s->table_creation_was_logged= 1; + thd->transaction.stmt.mark_created_temp_table(); + if (!res && local_create_info.table) + { + /* + Remember that tmp table creation was logged so that we know if + we should log a delete of it. + */ + local_create_info.table->s->table_creation_was_logged= 1; + } } do_logging= TRUE; } @@ -9366,8 +9376,12 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd) bool mysql_trans_commit_alter_copy_data(THD *thd) { bool error= FALSE; + uint save_unsafe_rollback_flags; DBUG_ENTER("mysql_trans_commit_alter_copy_data"); + /* Save flags as transcommit_implicit_are_deleting_them */ + save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags; + if (ha_enable_transaction(thd, TRUE)) DBUG_RETURN(TRUE); @@ -9382,6 +9396,7 @@ bool mysql_trans_commit_alter_copy_data(THD *thd) if (trans_commit_implicit(thd)) error= TRUE; + thd->transaction.stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags; DBUG_RETURN(error); } diff --git a/sql/transaction.cc b/sql/transaction.cc index 8b188709ce6..f03cced7bc8 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -151,11 +151,10 @@ bool trans_begin(THD *thd, uint flags) thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); /* - The following set should not be needed as the flag should always be 0 - when we come here. We should at some point change this to an assert. + The following set should not be needed as transaction state should + already be reset. We should at some point change this to an assert. */ - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); thd->has_waiter= false; thd->waiting_on_group_commit= false; @@ -251,8 +250,7 @@ bool trans_commit(THD *thd) else (void) RUN_HOOK(transaction, after_commit, (thd, FALSE)); thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); thd->lex->start_transaction_opt= 0; DBUG_RETURN(MY_TEST(res)); @@ -299,8 +297,7 @@ bool trans_commit_implicit(THD *thd) } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); /* Upon implicit commit, reset the current transaction @@ -345,8 +342,7 @@ bool trans_rollback(THD *thd) thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); /* Reset the binlog transaction marker */ thd->variables.option_bits&= ~OPTION_GTID_BEGIN; - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); thd->lex->start_transaction_opt= 0; DBUG_RETURN(MY_TEST(res)); @@ -390,8 +386,7 @@ bool trans_rollback_implicit(THD *thd) preserve backward compatibility. */ thd->variables.option_bits&= ~(OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= false; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); /* Rollback should clear transaction_rollback_request flag. */ DBUG_ASSERT(! thd->transaction_rollback_request); @@ -427,6 +422,8 @@ bool trans_commit_stmt(THD *thd) */ DBUG_ASSERT(! thd->in_sub_stmt); + thd->merge_unsafe_rollback_flags(); + if (thd->transaction.stmt.ha_list) { if (WSREP_ON) @@ -481,6 +478,8 @@ bool trans_rollback_stmt(THD *thd) */ DBUG_ASSERT(! thd->in_sub_stmt); + thd->merge_unsafe_rollback_flags(); + if (thd->transaction.stmt.ha_list) { if (WSREP_ON) @@ -904,8 +903,7 @@ bool trans_xa_commit(THD *thd) } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -960,8 +958,7 @@ bool trans_xa_rollback(THD *thd) res= xa_trans_force_rollback(thd); thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= FALSE; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction.all.reset(); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); From f8dadbdf241a5400a9180f03cab4dbf25206bf7c Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 4 Jun 2017 11:47:30 +0300 Subject: [PATCH 45/47] Ensure that we have LOG_log locked when relay_log.close is called If open of the relay log failed, we got an assert in MYSQL_BIN_LOG::close This only affected DEBUG systems --- sql/rpl_rli.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 1b969fb4257..363f114ce9a 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -122,11 +122,14 @@ int init_relay_log_info(Relay_log_info* rli, int info_fd; const char* msg = 0; int error = 0; + mysql_mutex_t *log_lock; DBUG_ENTER("init_relay_log_info"); DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage if (rli->inited) // Set if this function called DBUG_RETURN(0); + + log_lock= rli->relay_log.get_log_lock(); fn_format(fname, info_fname, mysql_data_home, "", 4+32); mysql_mutex_lock(&rli->data_lock); info_fd = rli->info_fd; @@ -208,7 +211,6 @@ a file name for --relay-log-index option", opt_relaylog_index_name); Master_info* mi= rli->mi; char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN]; char *buf_relaylog_index_name= opt_relaylog_index_name; - mysql_mutex_t *log_lock; create_logfile_name_with_suffix(buf_relay_logname, sizeof(buf_relay_logname), @@ -228,7 +230,6 @@ a file name for --relay-log-index option", opt_relaylog_index_name); note, that if open() fails, we'll still have index file open but a destructor will take care of that */ - log_lock= rli->relay_log.get_log_lock(); mysql_mutex_lock(log_lock); if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) || rli->relay_log.open(ln, LOG_BIN, 0, 0, SEQ_READ_APPEND, @@ -306,7 +307,9 @@ Failed to open the existing relay log info file '%s' (errno %d)", if (info_fd >= 0) mysql_file_close(info_fd, MYF(0)); rli->info_fd= -1; + mysql_mutex_lock(log_lock); rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + mysql_mutex_unlock(log_lock); mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(1); } @@ -437,8 +440,12 @@ err: if (info_fd >= 0) mysql_file_close(info_fd, MYF(0)); rli->info_fd= -1; + + mysql_mutex_lock(log_lock); rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + mysql_mutex_unlock(log_lock); mysql_mutex_unlock(&rli->data_lock); + DBUG_RETURN(1); } From 8ae9c86f2a79f1301f5428542fc7f53feed7d4f4 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Tue, 4 Jul 2017 10:26:14 -0400 Subject: [PATCH 46/47] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index aa7108a440a..14662450ff9 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=1 -MYSQL_VERSION_PATCH=25 +MYSQL_VERSION_PATCH=26 From e555540ab6b9c3e0d4fdd00af093b115a9401d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 5 Jul 2017 14:35:55 +0300 Subject: [PATCH 47/47] MDEV-13105 InnoDB fails to load a table with PAGE_COMPRESSION_LEVEL after upgrade from 10.1.20 When using innodb_page_size=16k, InnoDB tables that were created in MariaDB 10.1.0 to 10.1.20 with PAGE_COMPRESSED=1 and PAGE_COMPRESSION_LEVEL=2 or PAGE_COMPRESSION_LEVEL=3 would fail to load. fsp_flags_is_valid(): When using innodb_page_size=16k, use a more strict check for .ibd files, with the assumption that nobody would try to use different-page-size files. --- mysql-test/suite/innodb/include/ibd_convert.pl | 2 +- .../suite/innodb/r/101_compatibility.result | 2 +- mysql-test/suite/innodb/t/101_compatibility.test | 2 +- storage/innobase/buf/buf0dblwr.cc | 2 +- storage/innobase/fil/fil0fil.cc | 14 +++++++------- storage/innobase/fsp/fsp0fsp.cc | 2 +- storage/innobase/include/dict0dict.ic | 2 +- storage/innobase/include/fsp0fsp.h | 16 +++++++++++----- storage/innobase/row/row0import.cc | 2 +- storage/xtradb/buf/buf0dblwr.cc | 2 +- storage/xtradb/fil/fil0fil.cc | 14 +++++++------- storage/xtradb/fsp/fsp0fsp.cc | 2 +- storage/xtradb/include/dict0dict.ic | 2 +- storage/xtradb/include/fsp0fsp.h | 16 +++++++++++----- storage/xtradb/row/row0import.cc | 2 +- 15 files changed, 47 insertions(+), 35 deletions(-) diff --git a/mysql-test/suite/innodb/include/ibd_convert.pl b/mysql-test/suite/innodb/include/ibd_convert.pl index 9c7e829f455..bb9dfbe74b8 100644 --- a/mysql-test/suite/innodb/include/ibd_convert.pl +++ b/mysql-test/suite/innodb/include/ibd_convert.pl @@ -11,7 +11,7 @@ sub convert_to_mariadb_101 # FIL_PAGE_DATA + FSP_SPACE_FLAGS = 38 + 16 = 54 bytes from the start my($flags) = unpack "x[54]N", $_; my $badflags = ($flags & 0x3f); - my $compression_level=6; + my $compression_level=3; $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); $badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE diff --git a/mysql-test/suite/innodb/r/101_compatibility.result b/mysql-test/suite/innodb/r/101_compatibility.result index bf613c1b3b1..7ec8bb19c10 100644 --- a/mysql-test/suite/innodb/r/101_compatibility.result +++ b/mysql-test/suite/innodb/r/101_compatibility.result @@ -7,7 +7,7 @@ CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT; CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='MYSQL_TMP_DIR'; -CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1; +CREATE TABLE tp(a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC PAGE_COMPRESSED=1; CREATE TABLE ti(a INT) ENGINE=InnoDB; FLUSH TABLES ti FOR EXPORT; backup: ti diff --git a/mysql-test/suite/innodb/t/101_compatibility.test b/mysql-test/suite/innodb/t/101_compatibility.test index 25567b939c7..df3261cebd1 100644 --- a/mysql-test/suite/innodb/t/101_compatibility.test +++ b/mysql-test/suite/innodb/t/101_compatibility.test @@ -28,7 +28,7 @@ CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; --replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR EVAL CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='$MYSQL_TMP_DIR'; -CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1; +CREATE TABLE tp(a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC PAGE_COMPRESSED=1; CREATE TABLE ti(a INT) ENGINE=InnoDB; FLUSH TABLES ti FOR EXPORT; perl; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 8ff5428d3a5..f35a34e5e98 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -616,7 +616,7 @@ buf_dblwr_process() if (page_no == 0) { /* Check the FSP_SPACE_FLAGS. */ ulint flags = fsp_header_get_flags(page); - if (!fsp_flags_is_valid(flags) + if (!fsp_flags_is_valid(flags, space_id) && fsp_flags_convert_from_101(flags) == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index d78a8b20f33..6abc7f0e1c2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -662,7 +662,7 @@ fil_node_open_file( ut_free(buf2); os_file_close(node->handle); - if (!fsp_flags_is_valid(flags)) { + if (!fsp_flags_is_valid(flags, space->id)) { ulint cflags = fsp_flags_convert_from_101(flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2366,7 +2366,7 @@ fil_read_first_page( FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); } - if (!fsp_flags_is_valid(*flags)) { + if (!fsp_flags_is_valid(*flags, *space_id)) { ulint cflags = fsp_flags_convert_from_101(*flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2497,7 +2497,7 @@ fil_op_write_log( ulint len; log_ptr = mlog_open(mtr, 11 + 2 + 1); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, space_id)); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: @@ -3718,7 +3718,7 @@ fil_create_new_single_table_tablespace( ut_ad(!srv_read_only_mode); ut_a(space_id < SRV_LOG_SPACE_FIRST_ID); ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); - ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); + ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, space_id)); if (is_temp) { /* Temporary table filepath */ @@ -3979,7 +3979,7 @@ void fsp_flags_try_adjust(ulint space_id, ulint flags) { ut_ad(!srv_read_only_mode); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, space_id)); mtr_t mtr; mtr_start(&mtr); @@ -4061,7 +4061,7 @@ fil_open_single_table_tablespace( return(DB_CORRUPTION); } - ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); + ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, id)); atomic_writes = fsp_flags_get_atomic_writes(flags); memset(&def, 0, sizeof(def)); @@ -4601,7 +4601,7 @@ fil_user_tablespace_restore_page( flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (!fsp_flags_is_valid(flags)) { + if (!fsp_flags_is_valid(flags, fsp->id)) { ulint cflags = fsp_flags_convert_from_101(flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 9d5e2e984fc..ab96befb700 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -661,7 +661,7 @@ fsp_header_init_fields( ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */ { flags &= ~FSP_FLAGS_MEM_MASK; - ut_a(fsp_flags_is_valid(flags)); + ut_a(fsp_flags_is_valid(flags, space_id)); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page, space_id); diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 6044f992d82..147968a343a 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -934,7 +934,7 @@ dict_tf_to_fsp_flags( fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; } - ut_a(fsp_flags_is_valid(fsp_flags)); + ut_a(fsp_flags_is_valid(fsp_flags, false)); if (DICT_TF_HAS_DATA_DIR(table_flags)) { fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index d8d044ba2ec..275a5785ce2 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -788,11 +788,12 @@ fseg_print( /** Validate the tablespace flags, which are stored in the tablespace header at offset FSP_SPACE_FLAGS. @param[in] flags the contents of FSP_SPACE_FLAGS +@param[in] is_ibd whether this is an .ibd file (not system tablespace) @return whether the flags are correct (not in the buggy 10.1) format */ MY_ATTRIBUTE((warn_unused_result, const)) UNIV_INLINE bool -fsp_flags_is_valid(ulint flags) +fsp_flags_is_valid(ulint flags, bool is_ibd) { DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); @@ -816,7 +817,7 @@ fsp_flags_is_valid(ulint flags) bits 10..14 would be nonzero 0bsssaa where sss is nonzero PAGE_SSIZE (3, 4, 6, or 7) and aa is ATOMIC_WRITES (not 0b11). */ - if (FSP_FLAGS_GET_RESERVED(flags) & ~1) { + if (FSP_FLAGS_GET_RESERVED(flags) & ~1U) { return(false); } @@ -839,7 +840,12 @@ fsp_flags_is_valid(ulint flags) return(false); } - return(true); + /* The flags do look valid. But, avoid misinterpreting + buggy MariaDB 10.1 format flags for + PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL={0,2,3} + as valid-looking PAGE_SSIZE if this is known to be + an .ibd file and we are using the default innodb_page_size=16k. */ + return(ssize == 0 || !is_ibd || srv_page_size != UNIV_PAGE_SIZE_ORIG); } /** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format. @@ -948,7 +954,7 @@ fsp_flags_convert_from_101(ulint flags) flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE | FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) << FSP_FLAGS_POS_PAGE_COMPRESSION); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, false)); return(flags); } @@ -962,7 +968,7 @@ bool fsp_flags_match(ulint expected, ulint actual) { expected &= ~FSP_FLAGS_MEM_MASK; - ut_ad(fsp_flags_is_valid(expected)); + ut_ad(fsp_flags_is_valid(expected, false)); if (actual == expected) { return(true); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 43830725978..4375d491ba7 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -548,7 +548,7 @@ AbstractCallback::init( const page_t* page = block->frame; m_space_flags = fsp_header_get_flags(page); - if (!fsp_flags_is_valid(m_space_flags)) { + if (!fsp_flags_is_valid(m_space_flags, true)) { ulint cflags = fsp_flags_convert_from_101(m_space_flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR, diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 49371f9a6f1..d6e738f15fa 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -616,7 +616,7 @@ buf_dblwr_process() if (page_no == 0) { /* Check the FSP_SPACE_FLAGS. */ ulint flags = fsp_header_get_flags(page); - if (!fsp_flags_is_valid(flags) + if (!fsp_flags_is_valid(flags, space_id) && fsp_flags_convert_from_101(flags) == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index fdd09a6034e..dbf6501b183 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -670,7 +670,7 @@ fil_node_open_file( ut_free(buf2); os_file_close(node->handle); - if (!fsp_flags_is_valid(flags)) { + if (!fsp_flags_is_valid(flags, space->id)) { ulint cflags = fsp_flags_convert_from_101(flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2426,7 +2426,7 @@ fil_read_first_page( FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); } - if (!fsp_flags_is_valid(*flags)) { + if (!fsp_flags_is_valid(*flags, *space_id)) { ulint cflags = fsp_flags_convert_from_101(*flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2541,7 +2541,7 @@ fil_op_write_log( ulint len; log_ptr = mlog_open(mtr, 11 + 2 + 1); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, space_id)); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: @@ -3778,7 +3778,7 @@ fil_create_new_single_table_tablespace( ut_ad(!srv_read_only_mode); ut_a(space_id < SRV_LOG_SPACE_FIRST_ID); ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); - ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); + ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, space_id)); if (is_temp) { /* Temporary table filepath */ @@ -4172,7 +4172,7 @@ void fsp_flags_try_adjust(ulint space_id, ulint flags) { ut_ad(!srv_read_only_mode); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, space_id)); mtr_t mtr; mtr_start(&mtr); @@ -4254,7 +4254,7 @@ fil_open_single_table_tablespace( return(DB_CORRUPTION); } - ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); + ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, id)); atomic_writes = fsp_flags_get_atomic_writes(flags); memset(&def, 0, sizeof(def)); @@ -4795,7 +4795,7 @@ fil_user_tablespace_restore_page( flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (!fsp_flags_is_valid(flags)) { + if (!fsp_flags_is_valid(flags, fsp->id)) { ulint cflags = fsp_flags_convert_from_101(flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc index df8c6ffe222..b5491ac6550 100644 --- a/storage/xtradb/fsp/fsp0fsp.cc +++ b/storage/xtradb/fsp/fsp0fsp.cc @@ -664,7 +664,7 @@ fsp_header_init_fields( ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */ { flags &= ~FSP_FLAGS_MEM_MASK; - ut_a(fsp_flags_is_valid(flags)); + ut_a(fsp_flags_is_valid(flags, space_id)); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page, space_id); diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index f68d4e176da..4db6a73bbc2 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -934,7 +934,7 @@ dict_tf_to_fsp_flags( fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; } - ut_a(fsp_flags_is_valid(fsp_flags)); + ut_a(fsp_flags_is_valid(fsp_flags, false)); if (DICT_TF_HAS_DATA_DIR(table_flags)) { fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h index 715572199ab..7395a248bed 100644 --- a/storage/xtradb/include/fsp0fsp.h +++ b/storage/xtradb/include/fsp0fsp.h @@ -787,11 +787,12 @@ fseg_print( /** Validate the tablespace flags, which are stored in the tablespace header at offset FSP_SPACE_FLAGS. @param[in] flags the contents of FSP_SPACE_FLAGS +@param[in] is_ibd whether this is an .ibd file (not system tablespace) @return whether the flags are correct (not in the buggy 10.1) format */ MY_ATTRIBUTE((warn_unused_result, const)) UNIV_INLINE bool -fsp_flags_is_valid(ulint flags) +fsp_flags_is_valid(ulint flags, bool is_ibd) { DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); @@ -815,7 +816,7 @@ fsp_flags_is_valid(ulint flags) bits 10..14 would be nonzero 0bsssaa where sss is nonzero PAGE_SSIZE (3, 4, 6, or 7) and aa is ATOMIC_WRITES (not 0b11). */ - if (FSP_FLAGS_GET_RESERVED(flags) & ~1) { + if (FSP_FLAGS_GET_RESERVED(flags) & ~1U) { return(false); } @@ -838,7 +839,12 @@ fsp_flags_is_valid(ulint flags) return(false); } - return(true); + /* The flags do look valid. But, avoid misinterpreting + buggy MariaDB 10.1 format flags for + PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL={0,2,3} + as valid-looking PAGE_SSIZE if this is known to be + an .ibd file and we are using the default innodb_page_size=16k. */ + return(ssize == 0 || !is_ibd || srv_page_size != UNIV_PAGE_SIZE_ORIG); } /** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format. @@ -947,7 +953,7 @@ fsp_flags_convert_from_101(ulint flags) flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE | FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) << FSP_FLAGS_POS_PAGE_COMPRESSION); - ut_ad(fsp_flags_is_valid(flags)); + ut_ad(fsp_flags_is_valid(flags, false)); return(flags); } @@ -961,7 +967,7 @@ bool fsp_flags_match(ulint expected, ulint actual) { expected &= ~FSP_FLAGS_MEM_MASK; - ut_ad(fsp_flags_is_valid(expected)); + ut_ad(fsp_flags_is_valid(expected, false)); if (actual == expected) { return(true); diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index 86b2d782b7b..a99c72c01b5 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -549,7 +549,7 @@ AbstractCallback::init( const page_t* page = block->frame; m_space_flags = fsp_header_get_flags(page); - if (!fsp_flags_is_valid(m_space_flags)) { + if (!fsp_flags_is_valid(m_space_flags, true)) { ulint cflags = fsp_flags_convert_from_101(m_space_flags); if (cflags == ULINT_UNDEFINED) { ib_logf(IB_LOG_LEVEL_ERROR,