diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-04 18:44:44 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-04 18:44:44 +0300 |
commit | 5ff7e68c7eaf2a2daacb0c1ea07b21c8a7bd2639 (patch) | |
tree | f0dac9f004764d37c81ef781707163bf105c0bc1 | |
parent | 938db04898ee9029421f5251751239255dd81c15 (diff) | |
parent | 7f8cd326c68ce15961a84abbc844dfe72aa05a93 (diff) | |
download | mariadb-git-5ff7e68c7eaf2a2daacb0c1ea07b21c8a7bd2639.tar.gz |
Merge 10.4 into 10.5
94 files changed, 2113 insertions, 1259 deletions
diff --git a/.travis.yml b/.travis.yml index bc3b948af77..46588177faf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -153,7 +153,7 @@ jobs: script: *deb-script # Just one OS X build is enough - os: osx - osx_image: xcode11.3 + osx_image: xcode12u compiler: clang env: CC_VERSION=8 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=main # Some chosen ones with s390x and gcc diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index a93d925db58..f3b6632cf5d 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -975,8 +975,12 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, my_b_printf(body_cache, "'%s\n", print_event_info->delimiter); // flush cache - if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) || - copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file))) + if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, + result_file) || + copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, + result_file) || + copy_event_cache_to_file_and_reinit(&print_event_info->tail_cache, + result_file))) return 1; } } diff --git a/include/my_atomic_wrapper.h b/include/my_atomic_wrapper.h index 61db886d53f..64835e30ca7 100644 --- a/include/my_atomic_wrapper.h +++ b/include/my_atomic_wrapper.h @@ -48,6 +48,8 @@ public: { return m.fetch_add(i, o); } Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed) { return m.fetch_sub(i, o); } + Type fetch_xor(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_xor(i, o); } bool compare_exchange_strong(Type& i1, const Type i2, std::memory_order o1= std::memory_order_relaxed, std::memory_order o2= std::memory_order_relaxed) diff --git a/include/my_cpu.h b/include/my_cpu.h index fba04ccea66..e536ff285f9 100644 --- a/include/my_cpu.h +++ b/include/my_cpu.h @@ -53,6 +53,7 @@ #ifdef _WIN32 #elif defined HAVE_PAUSE_INSTRUCTION #elif defined(_ARCH_PWR8) +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) #else # include "my_global.h" # include "my_atomic.h" @@ -81,6 +82,9 @@ static inline void MY_RELAX_CPU(void) #endif #elif defined(_ARCH_PWR8) __ppc_get_timebase(); +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) + /* Mainly, prevent the compiler from optimizing away delay loops */ + __asm__ __volatile__ ("":::"memory"); #else int32 var, oldval = 0; my_atomic_cas32_strong_explicit(&var, &oldval, 1, MY_MEMORY_ORDER_RELAXED, diff --git a/mysql-test/suite/galera/include/have_mariabackup.inc b/mysql-test/include/have_mariabackup.inc index 6c4ad240172..6c4ad240172 100644 --- a/mysql-test/suite/galera/include/have_mariabackup.inc +++ b/mysql-test/include/have_mariabackup.inc diff --git a/mysql-test/include/innodb_prefix_index_cluster_optimization.combinations b/mysql-test/include/innodb_prefix_index_cluster_optimization.combinations new file mode 100644 index 00000000000..ad82f82aa9d --- /dev/null +++ b/mysql-test/include/innodb_prefix_index_cluster_optimization.combinations @@ -0,0 +1,5 @@ +[covering] +innodb_prefix_index_cluster_optimization=on + +[unoptimized] +innodb_prefix_index_cluster_optimization=off diff --git a/mysql-test/include/innodb_prefix_index_cluster_optimization.inc b/mysql-test/include/innodb_prefix_index_cluster_optimization.inc new file mode 100644 index 00000000000..c841fece702 --- /dev/null +++ b/mysql-test/include/innodb_prefix_index_cluster_optimization.inc @@ -0,0 +1 @@ +--source include/have_innodb.inc diff --git a/mysql-test/main/fast_prefix_index_fetch_innodb.result b/mysql-test/main/fast_prefix_index_fetch_innodb.result index c6d96389b08..ef297e5c6b5 100644 --- a/mysql-test/main/fast_prefix_index_fetch_innodb.result +++ b/mysql-test/main/fast_prefix_index_fetch_innodb.result @@ -1,4 +1,4 @@ -drop table if exists prefixinno; +SET @save_opt= @@GLOBAL.innodb_prefix_index_cluster_optimization; set global innodb_prefix_index_cluster_optimization = ON; show variables like 'innodb_prefix_index_cluster_optimization'; Variable_name Value @@ -346,10 +346,10 @@ f1 🐱🌑 select @cluster_lookups; @cluster_lookups -2 +1 select @cluster_lookups_avoided; @cluster_lookups_avoided -0 +1 # Eligible - record length is shorter than prefix length SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🌑%'; f1 @@ -366,10 +366,10 @@ f1 🌒 select @cluster_lookups; @cluster_lookups -1 +0 select @cluster_lookups_avoided; @cluster_lookups_avoided -1 +2 DROP TABLE t1; CREATE TABLE t1( col1 INT, @@ -398,4 +398,60 @@ select @cluster_lookups_avoided; @cluster_lookups_avoided 0 DROP TABLE t1; -set global innodb_prefix_index_cluster_optimization = OFF; +# +# MDEV-20464 Division by 0 in row_search_with_covering_prefix() +# +CREATE TABLE t1 (f1 INT, f2 INT AS (f1), f3 INT AS (f1), f4 INT AS (f1), +KEY (f1,f2,f3)) ENGINE=InnoDB; +INSERT INTO t1 (f1) VALUES (NULL),(0); +SELECT f1, MAX(f3), COUNT(f4) FROM t1 GROUP BY f1; +f1 MAX(f3) COUNT(f4) +NULL NULL 0 +0 0 1 +DROP TABLE t1; +# +# MDEV-23600 Division by 0 in row_search_with_covering_prefix() +# +CREATE TABLE t(c POINT UNIQUE) ENGINE=InnoDB; +INSERT t SET c=POINT(1,1); +SELECT * FROM t WHERE c > (SELECT MAX(c) FROM t); +c +DROP TABLE t; +# +# MDEV-12486 Wrong results with innodb_prefix_index_cluster_optimization +# +CREATE TABLE wp_blogs ( +blog_id bigint(20) NOT NULL auto_increment, +site_id bigint(20) NOT NULL default '0', +domain varchar(200) NOT NULL default '', +path varchar(100) NOT NULL default '', +registered datetime NOT NULL default '0000-00-00 00:00:00', +last_updated datetime NOT NULL default '0000-00-00 00:00:00', +public tinyint(2) NOT NULL default '1', +archived tinyint(2) NOT NULL default '0', +mature tinyint(2) NOT NULL default '0', +spam tinyint(2) NOT NULL default '0', +deleted tinyint(2) NOT NULL default '0', +lang_id int(11) NOT NULL default '0', +PRIMARY KEY (blog_id), +KEY domain (domain(50),path(5)), +KEY lang_id (lang_id) +) ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +INSERT INTO wp_blogs (domain, path) VALUES +('domain.no', '/fondsinvesteringer/'), ('domain.no', '/'), +('foo', 'bar'), ('bar', 'foo'), ('foo', 'foo'), ('bar', 'bar'), +('foo', 'foobar'), ('bar', 'foobar'), ('foobar', 'foobar'); +SET GLOBAL innodb_prefix_index_cluster_optimization=off; +SELECT blog_id FROM wp_blogs WHERE domain IN ('domain.no') +AND path IN ( '/fondsinvesteringer/', '/' ); +blog_id +2 +1 +SET GLOBAL innodb_prefix_index_cluster_optimization=on; +SELECT blog_id FROM wp_blogs WHERE domain IN ('domain.no') +AND path IN ( '/fondsinvesteringer/', '/' ); +blog_id +2 +1 +DROP TABLE wp_blogs; +SET GLOBAL innodb_prefix_index_cluster_optimization = @save_opt; diff --git a/mysql-test/main/fast_prefix_index_fetch_innodb.test b/mysql-test/main/fast_prefix_index_fetch_innodb.test index c3b3440d82d..1987416ff87 100644 --- a/mysql-test/main/fast_prefix_index_fetch_innodb.test +++ b/mysql-test/main/fast_prefix_index_fetch_innodb.test @@ -1,9 +1,6 @@ -- source include/have_innodb.inc ---disable_warnings -drop table if exists prefixinno; ---enable_warnings - +SET @save_opt= @@GLOBAL.innodb_prefix_index_cluster_optimization; set global innodb_prefix_index_cluster_optimization = ON; show variables like 'innodb_prefix_index_cluster_optimization'; @@ -665,4 +662,58 @@ select @cluster_lookups; select @cluster_lookups_avoided; DROP TABLE t1; -set global innodb_prefix_index_cluster_optimization = OFF; + +--echo # +--echo # MDEV-20464 Division by 0 in row_search_with_covering_prefix() +--echo # +CREATE TABLE t1 (f1 INT, f2 INT AS (f1), f3 INT AS (f1), f4 INT AS (f1), + KEY (f1,f2,f3)) ENGINE=InnoDB; +INSERT INTO t1 (f1) VALUES (NULL),(0); +SELECT f1, MAX(f3), COUNT(f4) FROM t1 GROUP BY f1; +DROP TABLE t1; + +--echo # +--echo # MDEV-23600 Division by 0 in row_search_with_covering_prefix() +--echo # +CREATE TABLE t(c POINT UNIQUE) ENGINE=InnoDB; +INSERT t SET c=POINT(1,1); +SELECT * FROM t WHERE c > (SELECT MAX(c) FROM t); +DROP TABLE t; + +--echo # +--echo # MDEV-12486 Wrong results with innodb_prefix_index_cluster_optimization +--echo # +CREATE TABLE wp_blogs ( + blog_id bigint(20) NOT NULL auto_increment, + site_id bigint(20) NOT NULL default '0', + domain varchar(200) NOT NULL default '', + path varchar(100) NOT NULL default '', + registered datetime NOT NULL default '0000-00-00 00:00:00', + last_updated datetime NOT NULL default '0000-00-00 00:00:00', + public tinyint(2) NOT NULL default '1', + archived tinyint(2) NOT NULL default '0', + mature tinyint(2) NOT NULL default '0', + spam tinyint(2) NOT NULL default '0', + deleted tinyint(2) NOT NULL default '0', + lang_id int(11) NOT NULL default '0', + PRIMARY KEY (blog_id), + KEY domain (domain(50),path(5)), + KEY lang_id (lang_id) +) ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + +INSERT INTO wp_blogs (domain, path) VALUES +('domain.no', '/fondsinvesteringer/'), ('domain.no', '/'), +('foo', 'bar'), ('bar', 'foo'), ('foo', 'foo'), ('bar', 'bar'), +('foo', 'foobar'), ('bar', 'foobar'), ('foobar', 'foobar'); + +SET GLOBAL innodb_prefix_index_cluster_optimization=off; +SELECT blog_id FROM wp_blogs WHERE domain IN ('domain.no') +AND path IN ( '/fondsinvesteringer/', '/' ); + +SET GLOBAL innodb_prefix_index_cluster_optimization=on; +SELECT blog_id FROM wp_blogs WHERE domain IN ('domain.no') +AND path IN ( '/fondsinvesteringer/', '/' ); + +DROP TABLE wp_blogs; + +SET GLOBAL innodb_prefix_index_cluster_optimization = @save_opt; diff --git a/mysql-test/main/innodb_ext_key,off.rdiff b/mysql-test/main/innodb_ext_key,off.rdiff new file mode 100644 index 00000000000..195456958d8 --- /dev/null +++ b/mysql-test/main/innodb_ext_key,off.rdiff @@ -0,0 +1,295 @@ +@@ -9,7 +9,7 @@ + explain + select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 8 const,const 1 Using index ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where + flush status; + select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; + count(*) +@@ -19,7 +19,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 1 ++Handler_read_next 5 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -50,7 +50,7 @@ + select count(*) from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem range PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 8 NULL 1 Using where; Using index ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index + flush status; + select count(*) from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; +@@ -61,7 +61,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 1 ++Handler_read_next 6 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -71,7 +71,7 @@ + select l_orderkey, l_linenumber from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem range PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 8 NULL 3 Using where; Using index ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index + flush status; + select l_orderkey, l_linenumber from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; +@@ -84,7 +84,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 3 ++Handler_read_next 6 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -93,7 +93,7 @@ + explain + select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away ++1 SIMPLE lineitem ref i_l_shipdate i_l_shipdate 4 const 6 Using index + flush status; + select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; + min(l_orderkey) +@@ -103,7 +103,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 0 ++Handler_read_next 6 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -113,7 +113,7 @@ + select min(l_orderkey) from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index + flush status; + select min(l_orderkey) from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; +@@ -124,7 +124,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 0 ++Handler_read_next 6 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -134,7 +134,7 @@ + select max(l_linenumber) from lineitem + where l_shipdate='1992-07-01' and l_orderkey=130; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where + flush status; + select max(l_linenumber) from lineitem + where l_shipdate='1992-07-01' and l_orderkey=130; +@@ -145,7 +145,7 @@ + Handler_read_first 0 + Handler_read_key 1 + Handler_read_last 0 +-Handler_read_next 0 ++Handler_read_next 5 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -157,7 +157,7 @@ + where l_shipdate='1992-07-01' and l_orderkey=130 + or l_receiptdate='1992-07-01' and l_orderkey=5603; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 8,8 NULL 2 Using union(i_l_shipdate,i_l_receiptdate); Using where ++1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 4,4 NULL 9 Using union(i_l_shipdate,i_l_receiptdate); Using where + flush status; + select l_orderkey, l_linenumber + from lineitem use index (i_l_shipdate, i_l_receiptdate) +@@ -171,10 +171,10 @@ + Handler_read_first 0 + Handler_read_key 2 + Handler_read_last 0 +-Handler_read_next 2 ++Handler_read_next 9 + Handler_read_prev 0 + Handler_read_retry 0 +-Handler_read_rnd 2 ++Handler_read_rnd 9 + Handler_read_rnd_deleted 0 + Handler_read_rnd_next 0 + explain +@@ -183,7 +183,7 @@ + where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 + or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 8,8 NULL 3 Using sort_union(i_l_shipdate,i_l_receiptdate); Using where ++1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 4,4 NULL 9 Using union(i_l_shipdate,i_l_receiptdate); Using where + flush status; + select l_orderkey, l_linenumber + from lineitem use index (i_l_shipdate, i_l_receiptdate) +@@ -198,10 +198,10 @@ + Handler_read_first 0 + Handler_read_key 2 + Handler_read_last 0 +-Handler_read_next 3 ++Handler_read_next 9 + Handler_read_prev 0 + Handler_read_retry 0 +-Handler_read_rnd 3 ++Handler_read_rnd 9 + Handler_read_rnd_deleted 0 + Handler_read_rnd_next 0 + explain +@@ -209,7 +209,7 @@ + where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 + or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem index_merge PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate,i_l_receiptdate 8,8 NULL 3 Using sort_union(i_l_shipdate,i_l_receiptdate); Using where ++1 SIMPLE lineitem index_merge PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate,PRIMARY,i_l_receiptdate,PRIMARY 4,4,4,4 NULL 2 Using union(intersect(i_l_shipdate,PRIMARY),intersect(i_l_receiptdate,PRIMARY)); Using where + flush status; + select l_orderkey, l_linenumber from lineitem + where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 +@@ -223,7 +223,7 @@ + Handler_read_first 0 + Handler_read_key 2 + Handler_read_last 0 +-Handler_read_next 3 ++Handler_read_next 9 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 3 +@@ -233,7 +233,7 @@ + select max(l_orderkey) from lineitem + where l_partkey between 1 and 10 group by l_partkey; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem range i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 NULL # Using where; Using index for group-by ++1 SIMPLE lineitem range i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 NULL # Using where; Using index + flush status; + select max(l_orderkey) from lineitem + where l_partkey between 1 and 10 group by l_partkey; +@@ -251,9 +251,9 @@ + show status like 'handler_read%'; + Variable_name Value + Handler_read_first 0 +-Handler_read_key 21 +-Handler_read_last 1 +-Handler_read_next 0 ++Handler_read_key 1 ++Handler_read_last 0 ++Handler_read_next 294 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -263,7 +263,7 @@ + select max(l_orderkey) from lineitem + where l_suppkey in (1,4) group by l_suppkey; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE lineitem range i_l_suppkey i_l_suppkey 5 NULL # Using where; Using index for group-by ++1 SIMPLE lineitem range i_l_suppkey i_l_suppkey 5 NULL # Using where; Using index + flush status; + select max(l_orderkey) from lineitem + where l_suppkey in (1,4) group by l_suppkey; +@@ -273,9 +273,9 @@ + show status like 'handler_read%'; + Variable_name Value + Handler_read_first 0 +-Handler_read_key 6 +-Handler_read_last 1 +-Handler_read_next 0 ++Handler_read_key 2 ++Handler_read_last 0 ++Handler_read_next 1230 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -291,7 +291,7 @@ + id select_type table type possible_keys key key_len ref rows Extra + 1 SIMPLE part range i_p_retailprice i_p_retailprice 9 NULL # Using where; Using index + 1 SIMPLE orders ref PRIMARY,i_o_orderdate i_o_orderdate 4 const # Using index +-1 SIMPLE lineitem ref i_l_partkey i_l_partkey 9 dbt3_s001.part.p_partkey,dbt3_s001.orders.o_orderkey # Using index ++1 SIMPLE lineitem ref i_l_partkey i_l_partkey 5 dbt3_s001.part.p_partkey # Using where; Using index + flush status; + select o_orderkey, p_partkey + from part use index (i_p_retailprice), +@@ -305,7 +305,7 @@ + Handler_read_first 0 + Handler_read_key 3 + Handler_read_last 0 +-Handler_read_next 3 ++Handler_read_next 26 + Handler_read_prev 0 + Handler_read_retry 0 + Handler_read_rnd 0 +@@ -322,8 +322,8 @@ + select * from t0, part ignore index (primary) + where p_partkey=t0.a and p_size=1; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE t0 ALL NULL NULL NULL NULL 5 Using where +-1 SIMPLE part eq_ref i_p_size i_p_size 9 const,dbt3_s001.t0.a 1 ++1 SIMPLE t0 ALL NULL NULL NULL NULL 5 ++1 SIMPLE part ref i_p_size i_p_size 5 const 5 Using index condition + select * from t0, part ignore index (primary) + where p_partkey=t0.a and p_size=1; + a p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment +@@ -502,7 +502,7 @@ + select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a and t3.pk1=t1.a; + id select_type table type possible_keys key key_len ref rows Extra + 1 SIMPLE t1 ALL NULL NULL NULL NULL # Using where +-1 SIMPLE t3 ref PRIMARY,col1 col1 12 test.t1.a,test.t1.a,test.t1.a # Using index ++1 SIMPLE t3 ref PRIMARY,col1 col1 8 test.t1.a,test.t1.a # Using where; Using index + drop table t1,t2,t3; + # + # Bug mdev-4340: performance regression with extended_keys=on +@@ -722,13 +722,13 @@ + select * from t1 force index(index_date_updated) + where index_date_updated= 10 and index_id < 800; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE t1 range index_date_updated index_date_updated 13 NULL # Using index condition ++1 SIMPLE t1 ref index_date_updated index_date_updated 5 const # Using index condition + # This used to work from the start: + explain + select * from t2 force index(index_date_updated) + where index_date_updated= 10 and index_id < 800; + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE t2 range index_date_updated index_date_updated 13 NULL # Using index condition ++1 SIMPLE t2 ref index_date_updated index_date_updated 5 const # Using index condition + drop table t0,t1,t2; + # + # MDEV-11196: Error:Run-Time Check Failure #2 - Stack around the variable 'key_buff' +@@ -763,11 +763,12 @@ + "select_id": 1, + "table": { + "table_name": "t1", +- "access_type": "range", ++ "access_type": "ref", + "possible_keys": ["f2"], + "key": "f2", +- "key_length": "3070", +- "used_key_parts": ["f2", "pk1"], ++ "key_length": "3066", ++ "used_key_parts": ["f2"], ++ "ref": ["const"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.pk1 <= 5 and t1.pk2 <= 5 and t1.f2 = 'abc'", +@@ -796,8 +797,8 @@ + "access_type": "range", + "possible_keys": ["k1"], + "key": "k1", +- "key_length": "3011", +- "used_key_parts": ["pk1", "f2", "pk2"], ++ "key_length": "3007", ++ "used_key_parts": ["pk1", "f2"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.f2 <= 5 and t1.pk2 <= 5 and t1.pk1 = 'abc'", diff --git a/mysql-test/main/innodb_ext_key.combinations b/mysql-test/main/innodb_ext_key.combinations new file mode 100644 index 00000000000..6ad97eaf75b --- /dev/null +++ b/mysql-test/main/innodb_ext_key.combinations @@ -0,0 +1,5 @@ +[on] +optimizer_switch=extended_keys=on + +[off] +optimizer_switch=extended_keys=off diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result index b0792605e54..e00192e1d64 100644 --- a/mysql-test/main/innodb_ext_key.result +++ b/mysql-test/main/innodb_ext_key.result @@ -1,5 +1,3 @@ -DROP TABLE IF EXISTS t1,t2,t3,t4; -DROP DATABASE IF EXISTS dbt3_s001; SET SESSION DEFAULT_STORAGE_ENGINE='InnoDB'; set @innodb_stats_persistent_save= @@innodb_stats_persistent; set @innodb_stats_persistent_sample_pages_save= @@ -8,28 +6,6 @@ set global innodb_stats_persistent= 1; set global innodb_stats_persistent_sample_pages=100; CREATE DATABASE dbt3_s001; use dbt3_s001; -set @save_ext_key_optimizer_switch=@@optimizer_switch; -set optimizer_switch='extended_keys=off'; -explain -select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where -flush status; -select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; -count(*) -1 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 5 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; id select_type table type possible_keys key key_len ref rows Extra @@ -49,29 +25,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select count(*) from lineitem -where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem const PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 8 const,const 1 -flush status; -select count(*) from lineitem -where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; -count(*) -1 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 0 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select count(*) from lineitem where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; @@ -93,29 +46,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select count(*) from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index -flush status; -select count(*) from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; -count(*) -1 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 6 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select count(*) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; @@ -137,31 +67,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index -flush status; -select l_orderkey, l_linenumber from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -l_orderkey l_linenumber -1088 3 -1217 1 -1221 3 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 6 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; @@ -185,27 +90,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref i_l_shipdate i_l_shipdate 4 const 6 Using index -flush status; -select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; -min(l_orderkey) -130 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 6 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; id select_type table type possible_keys key key_len ref rows Extra @@ -225,29 +109,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select min(l_orderkey) from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index -flush status; -select min(l_orderkey) from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -min(l_orderkey) -1088 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 6 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select min(l_orderkey) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; @@ -269,29 +130,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select max(l_linenumber) from lineitem -where l_shipdate='1992-07-01' and l_orderkey=130; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where -flush status; -select max(l_linenumber) from lineitem -where l_shipdate='1992-07-01' and l_orderkey=130; -max(l_linenumber) -2 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 5 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select max(l_linenumber) from lineitem where l_shipdate='1992-07-01' and l_orderkey=130; @@ -313,34 +151,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber -from lineitem use index (i_l_shipdate, i_l_receiptdate) -where l_shipdate='1992-07-01' and l_orderkey=130 -or l_receiptdate='1992-07-01' and l_orderkey=5603; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 4,4 NULL 9 Using union(i_l_shipdate,i_l_receiptdate); Using where -flush status; -select l_orderkey, l_linenumber -from lineitem use index (i_l_shipdate, i_l_receiptdate) -where l_shipdate='1992-07-01' and l_orderkey=130 -or l_receiptdate='1992-07-01' and l_orderkey=5603; -l_orderkey l_linenumber -130 2 -5603 2 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 2 -Handler_read_last 0 -Handler_read_next 9 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 9 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem use index (i_l_shipdate, i_l_receiptdate) @@ -367,35 +177,6 @@ Handler_read_retry 0 Handler_read_rnd 2 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber -from lineitem use index (i_l_shipdate, i_l_receiptdate) -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 -or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem index_merge i_l_shipdate,i_l_receiptdate i_l_shipdate,i_l_receiptdate 4,4 NULL 9 Using union(i_l_shipdate,i_l_receiptdate); Using where -flush status; -select l_orderkey, l_linenumber -from lineitem use index (i_l_shipdate, i_l_receiptdate) -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 -or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -l_orderkey l_linenumber -130 2 -5603 2 -5959 3 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 2 -Handler_read_last 0 -Handler_read_next 9 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 9 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem use index (i_l_shipdate, i_l_receiptdate) @@ -423,33 +204,6 @@ Handler_read_retry 0 Handler_read_rnd 3 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 -or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem index_merge PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate,PRIMARY,i_l_receiptdate,PRIMARY 4,4,4,4 NULL 2 Using union(intersect(i_l_shipdate,PRIMARY),intersect(i_l_receiptdate,PRIMARY)); Using where -flush status; -select l_orderkey, l_linenumber from lineitem -where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 -or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -l_orderkey l_linenumber -130 2 -5603 2 -5959 3 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 2 -Handler_read_last 0 -Handler_read_next 9 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 3 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 @@ -475,38 +229,6 @@ Handler_read_retry 0 Handler_read_rnd 3 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select max(l_orderkey) from lineitem -where l_partkey between 1 and 10 group by l_partkey; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem range i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 NULL # Using where; Using index -flush status; -select max(l_orderkey) from lineitem -where l_partkey between 1 and 10 group by l_partkey; -max(l_orderkey) -5984 -5957 -5892 -5856 -5959 -5957 -5794 -5894 -5859 -5632 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 1 -Handler_read_last 0 -Handler_read_next 294 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select max(l_orderkey) from lineitem where l_partkey between 1 and 10 group by l_partkey; @@ -537,30 +259,6 @@ Handler_read_retry 0 Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=off'; -explain -select max(l_orderkey) from lineitem -where l_suppkey in (1,4) group by l_suppkey; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem range i_l_suppkey i_l_suppkey 5 NULL # Using where; Using index -flush status; -select max(l_orderkey) from lineitem -where l_suppkey in (1,4) group by l_suppkey; -max(l_orderkey) -5988 -5984 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 2 -Handler_read_last 0 -Handler_read_next 1230 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select max(l_orderkey) from lineitem where l_suppkey in (1,4) group by l_suppkey; @@ -584,37 +282,6 @@ Handler_read_rnd 0 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 create index i_p_retailprice on part(p_retailprice); -set optimizer_switch='extended_keys=off'; -explain -select o_orderkey, p_partkey -from part use index (i_p_retailprice), -lineitem use index (i_l_partkey), orders -where p_retailprice > 1100 and o_orderdate='1997-01-01' -and o_orderkey=l_orderkey and p_partkey=l_partkey; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE part range i_p_retailprice i_p_retailprice 9 NULL # Using where; Using index -1 SIMPLE orders ref PRIMARY,i_o_orderdate i_o_orderdate 4 const # Using index -1 SIMPLE lineitem ref i_l_partkey i_l_partkey 5 dbt3_s001.part.p_partkey # Using where; Using index -flush status; -select o_orderkey, p_partkey -from part use index (i_p_retailprice), -lineitem use index (i_l_partkey), orders -where p_retailprice > 1100 and o_orderdate='1997-01-01' -and o_orderkey=l_orderkey and p_partkey=l_partkey; -o_orderkey p_partkey -5895 200 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 3 -Handler_read_last 0 -Handler_read_next 26 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 0 -set optimizer_switch='extended_keys=on'; explain select o_orderkey, p_partkey from part use index (i_p_retailprice), @@ -651,7 +318,6 @@ Handler_read_rnd_next 0 create table t0 (a int); insert into t0 values (1), (2), (3), (4), (5); create index i_p_size on part(p_size); -set optimizer_switch='extended_keys=on'; explain select * from t0, part ignore index (primary) where p_partkey=t0.a and p_size=1; @@ -672,7 +338,6 @@ use test; # set @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch='materialization=on,semijoin=on'; -SET optimizer_switch='extended_keys=on'; CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); SELECT * FROM t1 WHERE 2 IN (SELECT MAX(s1.a) FROM t1 AS s1, t1 AS s2); @@ -693,9 +358,7 @@ set optimizer_switch=@save_optimizer_switch; # + extended_keys = on # (valgrinf complains fixed by the patch for bug #914560) # -set @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch = 'derived_with_keys=on'; -SET optimizer_switch = 'extended_keys=on'; CREATE TABLE t1 (a varchar(1)) ENGINE=MyISAM; INSERT INTO t1 VALUES ('j'), ('v'); CREATE TABLE t2 (b varchar(1)) ENGINE=MyISAM; @@ -725,21 +388,6 @@ c int NOT NULL PRIMARY KEY INSERT INTO t2 VALUES (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (24); -set @save_optimizer_switch=@@optimizer_switch; -SET optimizer_switch = 'extended_keys=off'; -EXPLAIN -SELECT a FROM t1 AS t, t2 -WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t index a,b b 7 NULL 10 Using index -1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary -1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join) -1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index -SELECT a FROM t1 AS t, t2 -WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); -a -24 -SET optimizer_switch = 'extended_keys=on'; EXPLAIN SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); @@ -752,7 +400,6 @@ SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); a 24 -set optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t2; # # LP Bug #923236: hash join + extended_keys = on @@ -761,12 +408,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; CREATE TABLE t2 (b int) ENGINE=MyISAM; INSERT INTO t1 (a) VALUES (4), (6); INSERT INTO t2 (b) VALUES (0), (8); -set @save_optimizer_switch=@@optimizer_switch; set @save_join_cache_level=@@join_cache_level; SET join_cache_level=3; SET optimizer_switch='join_cache_hashed=on'; SET optimizer_switch='join_cache_bka=on'; -SET optimizer_switch='extended_keys=on'; EXPLAIN SELECT * FROM t1, t2 WHERE b=a; id select_type table type possible_keys key key_len ref rows Extra @@ -791,26 +436,16 @@ UNIQUE KEY uq (c2,c3), KEY c3 (c3), KEY c4 (c4) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -set @save_optimizer_switch=@@optimizer_switch; -set session optimizer_switch='extended_keys=off'; -INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') -ON DUPLICATE KEY UPDATE c4 = VALUES(c4); INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') ON DUPLICATE KEY UPDATE c4 = VALUES(c4); -DELETE FROM t1; -set session optimizer_switch='extended_keys=on'; INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') ON DUPLICATE KEY UPDATE c4 = VALUES(c4); -INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') -ON DUPLICATE KEY UPDATE c4 = VALUES(c4); -set optimizer_switch=@save_optimizer_switch; DROP TABLE t1; # # Bug mdev-4220: using ref instead of eq_ref # with extended_keys=on # (performance regression introduced in the patch for mdev-3851) # -set @save_optimizer_switch=@@optimizer_switch; create table t1 (a int not null) engine=innodb; insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t2 ( @@ -820,29 +455,6 @@ insert into t2 select A.a + 10 * B.a, A.a + 10 * B.a, A.a + 10 * B.a from t1 A, t1 B; -set optimizer_switch='extended_keys=off'; -explain -select * from t1, t2 where t2.a=t1.a and t2.b < 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL # -1 SIMPLE t2 eq_ref a a 4 test.t1.a # Using where -flush status; -select * from t1, t2 where t2.a=t1.a and t2.b < 2; -a pk a b -0 0 0 0 -1 1 1 1 -show status like 'handler_read%'; -Variable_name Value -Handler_read_first 0 -Handler_read_key 10 -Handler_read_last 0 -Handler_read_next 0 -Handler_read_prev 0 -Handler_read_retry 0 -Handler_read_rnd 0 -Handler_read_rnd_deleted 0 -Handler_read_rnd_next 11 -set optimizer_switch='extended_keys=on'; explain select * from t1, t2 where t2.a=t1.a and t2.b < 2; id select_type table type possible_keys key key_len ref rows Extra @@ -881,18 +493,6 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK -set optimizer_switch='extended_keys=off'; -explain -select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL # Using where -1 SIMPLE t3 ref col1 col1 8 test.t1.a,test.t1.a # Using index -explain -select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a and t3.pk1=t1.a; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL # Using where -1 SIMPLE t3 ref PRIMARY,col1 col1 8 test.t1.a,test.t1.a # Using where; Using index -set optimizer_switch='extended_keys=on'; explain select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a; id select_type table type possible_keys key key_len ref rows Extra @@ -907,7 +507,6 @@ drop table t1,t2,t3; # # Bug mdev-4340: performance regression with extended_keys=on # -set @save_optimizer_switch=@@optimizer_switch; CREATE TABLE t1 ( page_id int(8) unsigned NOT NULL AUTO_INCREMENT, page_namespace int(11) NOT NULL DEFAULT '0', @@ -1011,16 +610,6 @@ INSERT INTO t3 VALUES (89,'text-8008',''),(90,'text-9008',''),(91,'text-9',''),(92,'text-1009',''), (93,'text-2009',''),(94,'text-3009',''),(95,'text-4009',''),(96,'text-5009',''), (97,'text-6009',''),(98,'text-7009',''),(99,'text-8009',''),(100,'text-9009',''); -set optimizer_switch='extended_keys=off'; -EXPLAIN -SELECT * FROM t1, t2 IGNORE INDEX (PRIMARY), t3 -WHERE page_id=rev_page AND rev_text_id=old_id AND page_namespace=4 AND page_title='Sandbox' -ORDER BY rev_timestamp ASC LIMIT 10; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 const PRIMARY,name_title name_title 261 const,const 1 -1 SIMPLE t2 ref page_timestamp page_timestamp 4 const 10 Using where -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.rev_text_id 1 -set optimizer_switch='extended_keys=on'; EXPLAIN SELECT * FROM t1, t2 IGNORE INDEX (PRIMARY), t3 WHERE page_id=rev_page AND rev_text_id=old_id AND page_namespace=4 AND page_title='Sandbox' @@ -1044,7 +633,6 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK -set optimizer_switch='extended_keys=on'; explain select a from t1 where b is null order by a desc limit 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index b PRIMARY 8 NULL 2 Using where @@ -1059,14 +647,6 @@ select a from t2 where b is null order by a desc limit 2; a 3 2 -set optimizer_switch='extended_keys=off'; -explain select a from t2 where b is null order by a desc limit 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range b b 9 NULL 3 Using where; Using filesort -select a from t2 where b is null order by a desc limit 2; -a -3 -2 explain select a from t2 where b is null order by a desc; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index b PRIMARY 8 NULL 3 Using where @@ -1084,7 +664,6 @@ a 2 1 drop table t1, t2; -set optimizer_switch=@save_optimizer_switch; # # MDEV-10325: Queries examines all rows of a tables when it should not # diff --git a/mysql-test/main/innodb_ext_key.test b/mysql-test/main/innodb_ext_key.test index 926a3472a6a..2f6097c7850 100644 --- a/mysql-test/main/innodb_ext_key.test +++ b/mysql-test/main/innodb_ext_key.test @@ -1,9 +1,4 @@ ---source include/have_innodb.inc - ---disable_warnings -DROP TABLE IF EXISTS t1,t2,t3,t4; -DROP DATABASE IF EXISTS dbt3_s001; ---enable_warnings +--source include/innodb_prefix_index_cluster_optimization.inc SET SESSION DEFAULT_STORAGE_ENGINE='InnoDB'; @@ -26,32 +21,12 @@ use dbt3_s001; --enable_result_log --enable_query_log -set @save_ext_key_optimizer_switch=@@optimizer_switch; - -set optimizer_switch='extended_keys=off'; explain select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; flush status; select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; show status like 'handler_read%'; -set optimizer_switch='extended_keys=on'; -explain -select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; -flush status; -select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=off'; -explain -select count(*) from lineitem - where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; -flush status; -select count(*) from lineitem - where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; explain select count(*) from lineitem where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; @@ -60,16 +35,6 @@ select count(*) from lineitem where l_orderkey=130 and l_linenumber=2 and l_shipdate='1992-07-01'; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; -explain -select count(*) from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; -flush status; -select count(*) from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; explain select count(*) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; @@ -78,16 +43,6 @@ select count(*) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -flush status; -select l_orderkey, l_linenumber from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; @@ -96,21 +51,12 @@ select l_orderkey, l_linenumber from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; explain select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; flush status; select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; show status like 'handler_read%'; -set optimizer_switch='extended_keys=on'; -explain -select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; -flush status; -select min(l_orderkey) from lineitem where l_shipdate='1992-07-01'; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=off'; explain select min(l_orderkey) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; @@ -119,25 +65,6 @@ select min(l_orderkey) from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; show status like 'handler_read%'; -set optimizer_switch='extended_keys=on'; -explain -select min(l_orderkey) from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -flush status; -select min(l_orderkey) from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1001 and 2000; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=off'; -explain -select max(l_linenumber) from lineitem - where l_shipdate='1992-07-01' and l_orderkey=130; -flush status; -select max(l_linenumber) from lineitem - where l_shipdate='1992-07-01' and l_orderkey=130; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; explain select max(l_linenumber) from lineitem where l_shipdate='1992-07-01' and l_orderkey=130; @@ -146,7 +73,6 @@ select max(l_linenumber) from lineitem where l_shipdate='1992-07-01' and l_orderkey=130; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; explain select l_orderkey, l_linenumber from lineitem use index (i_l_shipdate, i_l_receiptdate) @@ -159,20 +85,6 @@ select l_orderkey, l_linenumber or l_receiptdate='1992-07-01' and l_orderkey=5603; show status like 'handler_read%'; -set optimizer_switch='extended_keys=on'; -explain -select l_orderkey, l_linenumber - from lineitem use index (i_l_shipdate, i_l_receiptdate) - where l_shipdate='1992-07-01' and l_orderkey=130 - or l_receiptdate='1992-07-01' and l_orderkey=5603; -flush status; -select l_orderkey, l_linenumber - from lineitem use index (i_l_shipdate, i_l_receiptdate) - where l_shipdate='1992-07-01' and l_orderkey=130 - or l_receiptdate='1992-07-01' and l_orderkey=5603; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=off'; explain select l_orderkey, l_linenumber from lineitem use index (i_l_shipdate, i_l_receiptdate) @@ -185,31 +97,6 @@ select l_orderkey, l_linenumber or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; show status like 'handler_read%'; -set optimizer_switch='extended_keys=on'; -explain -select l_orderkey, l_linenumber - from lineitem use index (i_l_shipdate, i_l_receiptdate) - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 - or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -flush status; -select l_orderkey, l_linenumber - from lineitem use index (i_l_shipdate, i_l_receiptdate) - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 - or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=off'; -explain -select l_orderkey, l_linenumber from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 - or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -flush status; -select l_orderkey, l_linenumber from lineitem - where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 - or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; explain select l_orderkey, l_linenumber from lineitem where l_shipdate='1992-07-01' and l_orderkey between 1 and 1000 @@ -220,17 +107,6 @@ select l_orderkey, l_linenumber from lineitem or l_receiptdate='1992-07-01' and l_orderkey between 5001 and 6000; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; ---replace_column 9 # -explain -select max(l_orderkey) from lineitem - where l_partkey between 1 and 10 group by l_partkey; -flush status; -select max(l_orderkey) from lineitem - where l_partkey between 1 and 10 group by l_partkey; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; --replace_column 9 # explain select max(l_orderkey) from lineitem @@ -240,17 +116,6 @@ select max(l_orderkey) from lineitem where l_partkey between 1 and 10 group by l_partkey; show status like 'handler_read%'; -set optimizer_switch='extended_keys=off'; ---replace_column 9 # -explain -select max(l_orderkey) from lineitem - where l_suppkey in (1,4) group by l_suppkey; -flush status; -select max(l_orderkey) from lineitem - where l_suppkey in (1,4) group by l_suppkey; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; --replace_column 9 # explain select max(l_orderkey) from lineitem @@ -262,23 +127,6 @@ show status like 'handler_read%'; create index i_p_retailprice on part(p_retailprice); -set optimizer_switch='extended_keys=off'; ---replace_column 9 # -explain -select o_orderkey, p_partkey - from part use index (i_p_retailprice), - lineitem use index (i_l_partkey), orders - where p_retailprice > 1100 and o_orderdate='1997-01-01' - and o_orderkey=l_orderkey and p_partkey=l_partkey; -flush status; -select o_orderkey, p_partkey - from part use index (i_p_retailprice), - lineitem use index (i_l_partkey), orders - where p_retailprice > 1100 and o_orderdate='1997-01-01' - and o_orderkey=l_orderkey and p_partkey=l_partkey; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; --replace_column 9 # explain select o_orderkey, p_partkey @@ -303,8 +151,6 @@ create table t0 (a int); insert into t0 values (1), (2), (3), (4), (5); create index i_p_size on part(p_size); -set optimizer_switch='extended_keys=on'; - explain select * from t0, part ignore index (primary) where p_partkey=t0.a and p_size=1; @@ -327,7 +173,6 @@ use test; set @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch='materialization=on,semijoin=on'; -SET optimizer_switch='extended_keys=on'; CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); @@ -346,10 +191,7 @@ set optimizer_switch=@save_optimizer_switch; --echo # (valgrinf complains fixed by the patch for bug #914560) --echo # -set @save_optimizer_switch=@@optimizer_switch; - SET optimizer_switch = 'derived_with_keys=on'; -SET optimizer_switch = 'extended_keys=on'; CREATE TABLE t1 (a varchar(1)) ENGINE=MyISAM; INSERT INTO t1 VALUES ('j'), ('v'); @@ -389,24 +231,12 @@ INSERT INTO t2 VALUES (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (24); -set @save_optimizer_switch=@@optimizer_switch; - -SET optimizer_switch = 'extended_keys=off'; EXPLAIN SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); -SET optimizer_switch = 'extended_keys=on'; -EXPLAIN -SELECT a FROM t1 AS t, t2 - WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); -SELECT a FROM t1 AS t, t2 - WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); - -set optimizer_switch=@save_optimizer_switch; - DROP TABLE t1,t2; --echo # @@ -420,13 +250,11 @@ CREATE TABLE t2 (b int) ENGINE=MyISAM; INSERT INTO t1 (a) VALUES (4), (6); INSERT INTO t2 (b) VALUES (0), (8); -set @save_optimizer_switch=@@optimizer_switch; set @save_join_cache_level=@@join_cache_level; SET join_cache_level=3; SET optimizer_switch='join_cache_hashed=on'; SET optimizer_switch='join_cache_bka=on'; -SET optimizer_switch='extended_keys=on'; EXPLAIN SELECT * FROM t1, t2 WHERE b=a; @@ -455,24 +283,11 @@ KEY c4 (c4) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -set @save_optimizer_switch=@@optimizer_switch; - -set session optimizer_switch='extended_keys=off'; -INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') - ON DUPLICATE KEY UPDATE c4 = VALUES(c4); -INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') - ON DUPLICATE KEY UPDATE c4 = VALUES(c4); - -DELETE FROM t1; - -set session optimizer_switch='extended_keys=on'; INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') ON DUPLICATE KEY UPDATE c4 = VALUES(c4); INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar') ON DUPLICATE KEY UPDATE c4 = VALUES(c4); -set optimizer_switch=@save_optimizer_switch; - DROP TABLE t1; --echo # @@ -481,8 +296,6 @@ DROP TABLE t1; --echo # (performance regression introduced in the patch for mdev-3851) --echo # -set @save_optimizer_switch=@@optimizer_switch; - create table t1 (a int not null) engine=innodb; insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); @@ -496,15 +309,6 @@ select A.a + 10 * B.a, A.a + 10 * B.a, A.a + 10 * B.a from t1 A, t1 B; -set optimizer_switch='extended_keys=off'; ---replace_column 9 # -explain -select * from t1, t2 where t2.a=t1.a and t2.b < 2; -flush status; -select * from t1, t2 where t2.a=t1.a and t2.b < 2; -show status like 'handler_read%'; - -set optimizer_switch='extended_keys=on'; --replace_column 9 # explain select * from t1, t2 where t2.a=t1.a and t2.b < 2; @@ -531,15 +335,6 @@ alter table t3 add primary key (pk1, pk2); alter table t3 add key (col1, col2); analyze table t1,t3; -set optimizer_switch='extended_keys=off'; ---replace_column 9 # -explain -select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a; ---replace_column 9 # -explain -select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a and t3.pk1=t1.a; - -set optimizer_switch='extended_keys=on'; --replace_column 9 # explain select * from t1, t3 where t3.col1=t1.a and t3.col2=t1.a; @@ -553,8 +348,6 @@ drop table t1,t2,t3; --echo # Bug mdev-4340: performance regression with extended_keys=on --echo # -set @save_optimizer_switch=@@optimizer_switch; - CREATE TABLE t1 ( page_id int(8) unsigned NOT NULL AUTO_INCREMENT, page_namespace int(11) NOT NULL DEFAULT '0', @@ -662,13 +455,6 @@ INSERT INTO t3 VALUES (97,'text-6009',''),(98,'text-7009',''),(99,'text-8009',''),(100,'text-9009',''); -set optimizer_switch='extended_keys=off'; -EXPLAIN -SELECT * FROM t1, t2 IGNORE INDEX (PRIMARY), t3 - WHERE page_id=rev_page AND rev_text_id=old_id AND page_namespace=4 AND page_title='Sandbox' -ORDER BY rev_timestamp ASC LIMIT 10; - -set optimizer_switch='extended_keys=on'; EXPLAIN SELECT * FROM t1, t2 IGNORE INDEX (PRIMARY), t3 WHERE page_id=rev_page AND rev_text_id=old_id AND page_namespace=4 AND page_title='Sandbox' @@ -689,14 +475,10 @@ insert into t2 (b) values (null), (null), (null); analyze table t1,t2; -set optimizer_switch='extended_keys=on'; explain select a from t1 where b is null order by a desc limit 2; select a from t1 where b is null order by a desc limit 2; explain select a from t2 where b is null order by a desc limit 2; select a from t2 where b is null order by a desc limit 2; -set optimizer_switch='extended_keys=off'; -explain select a from t2 where b is null order by a desc limit 2; -select a from t2 where b is null order by a desc limit 2; explain select a from t2 where b is null order by a desc; select a from t2 where b is null order by a desc; @@ -706,8 +488,6 @@ select a from t2 where b is null order by a desc,a,a; drop table t1, t2; -set optimizer_switch=@save_optimizer_switch; - --echo # --echo # MDEV-10325: Queries examines all rows of a tables when it should not --echo # diff --git a/mysql-test/main/mysqlbinlog_row_minimal.result b/mysql-test/main/mysqlbinlog_row_minimal.result index f385b4ca69a..659228a57e2 100644 --- a/mysql-test/main/mysqlbinlog_row_minimal.result +++ b/mysql-test/main/mysqlbinlog_row_minimal.result @@ -327,6 +327,24 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; DROP TABLE t1,t2; +# +# MDEV-16372 ER_BASE64_DECODE_ERROR upon replaying binary log with system table +# +FLUSH BINARY LOGS; +CREATE TABLE t1 (pk INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1), (2) ON DUPLICATE KEY UPDATE pk= pk + 10; +FLUSH BINARY LOGS; +Proof: two subsequent patterns must be found +FOUND 1 /### UPDATE `test`.`t1`/ in mysqlbinlog.sql +FOUND 2 /### INSERT INTO `test`.`t1`/ in mysqlbinlog.sql +DROP TABLE t1; +SELECT * FROM t1; +pk +2 +11 +# Cleanup +DROP TABLE t1; CREATE TABLE `t1` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `is_deleted` BIT(1) DEFAULT b'0', @@ -351,23 +369,23 @@ FLUSH BINARY LOGS; /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; -# at 387 -#<date> server id 1 end_log_pos 429 CRC32 XXX GTID 0-1-16 +# at POS +#<date> server id 1 end_log_pos END_LOG_POS CRC32 XXX GTID D-S-N /*!100101 SET @@session.skip_parallel_replication=0*//*!*/; /*!100001 SET @@session.gtid_domain_id=0*//*!*/; /*!100001 SET @@session.server_id=1*//*!*/; -/*!100001 SET @@session.gtid_seq_no=16*//*!*/; +/*!100001 SET @@session.gtid_seq_no=21*//*!*/; START TRANSACTION /*!*/; -# at 429 -# at 543 -#<date> server id 1 end_log_pos 543 CRC32 XXX Annotate_rows: +# at POS +# at POS +#<date> server id 1 end_log_pos END_LOG_POS CRC32 XXX Annotate_rows: #Q> UPDATE t1 t1 INNER JOIN t2 t2 ON t1.ref_id = t2.id #Q> SET t1.is_deleted = TRUE #Q> WHERE t1.id = -#<date> server id 1 end_log_pos 594 CRC32 XXX Table_map: `test`.`t1` mapped to number 35 -# at 594 -#<date> server id 1 end_log_pos 643 CRC32 XXX Update_rows: table id 35 flags: STMT_END_F +#<date> server id 1 end_log_pos END_LOG_POS CRC32 XXX Table_map: `test`.`t1` mapped to number TID +# at POS +#<date> server id 1 end_log_pos END_LOG_POS CRC32 XXX Update_rows: table id TID flags: STMT_END_F ### UPDATE `test`.`t1` ### WHERE ### @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */ @@ -375,10 +393,10 @@ START TRANSACTION ### @2=b'1' /* BIT(1) meta=1 nullable=1 is_null=0 */ ### @3=X /* TIMESTAMP(0) meta=0 nullable=0 is_null=0 */ # Number of rows: 1 -# at 643 -#<date> server id 1 end_log_pos 725 CRC32 XXX Query thread_id=5 exec_time=x error_code=0 +# at POS +#<date> server id 1 end_log_pos END_LOG_POS CRC32 XXX Query thread_id=TID exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; -SET @@session.pseudo_thread_id=5/*!*/; +SET @@session.pseudo_thread_id=TID/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0/*!*/; SET @@session.sql_mode=#/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; @@ -388,8 +406,6 @@ SET @@session.lc_time_names=0/*!*/; SET @@session.collation_database=DEFAULT/*!*/; COMMIT /*!*/; -# at 725 -#<date> server id 1 end_log_pos 773 CRC32 XXX Rotate to master-bin.000004 pos: 4 DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/main/mysqlbinlog_row_minimal.test b/mysql-test/main/mysqlbinlog_row_minimal.test index b69aa6da14b..b399cc4ac45 100644 --- a/mysql-test/main/mysqlbinlog_row_minimal.test +++ b/mysql-test/main/mysqlbinlog_row_minimal.test @@ -33,6 +33,33 @@ FLUSH BINARY LOGS; DROP TABLE t1,t2; +--echo # +--echo # MDEV-16372 ER_BASE64_DECODE_ERROR upon replaying binary log with system table +--echo # +FLUSH BINARY LOGS; +CREATE TABLE t1 (pk INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1), (2) ON DUPLICATE KEY UPDATE pk= pk + 10; + +--let $binlog = query_get_value(SHOW MASTER STATUS, File, 1) + +FLUSH BINARY LOGS; +--exec $MYSQL_BINLOG --verbose $datadir/$binlog > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--echo Proof: two subsequent patterns must be found +--let SEARCH_PATTERN= ### UPDATE `test`.`t1` +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= ### INSERT INTO `test`.`t1` +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--source include/search_pattern_in_file.inc + +DROP TABLE t1; +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +SELECT * FROM t1; + +--echo # Cleanup +DROP TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql # # MDEV-14605 ON UPDATE CURRENT_TIMESTAMP fields by multi-table UPDATE are not logged with binlog_row_image=MINIMAL # @@ -64,11 +91,12 @@ UPDATE t1 t1 INNER JOIN t2 t2 ON t1.ref_id = t2.id WHERE t1.id = 1; --let $binlog = query_get_value(SHOW MASTER STATUS, File, 1) +--let $binlog_end= query_get_value(SHOW MASTER STATUS, Position, 1) FLUSH BINARY LOGS; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---replace_regex /\d{6} *\d*:\d\d:\d\d/<date>/ /SET TIMESTAMP=\d*/SET TIMESTAMP=X/ /exec_time=\d*/exec_time=x/ /@3=\d*/@3=X/ /CRC32 0x[0-9a-f]+/CRC32 XXX/ /@@session.sql_mode=\d+/@@session.sql_mode=#/ /collation_server=\d+/collation_server=#/ ---exec $MYSQL_BINLOG --verbose --verbose --base64-output=DECODE-ROWS $datadir/$binlog --start-position=$binlog_pos +--replace_regex /table id \d*/table id TID/ /mapped to number \d*/mapped to number TID/ /at \d*/at POS/ /end_log_pos \d*/end_log_pos END_LOG_POS/ /GTID \d*-\d*-\d*/GTID D-S-N/ /\d{6} *\d*:\d\d:\d\d/<date>/ /SET TIMESTAMP=\d*/SET TIMESTAMP=X/ /exec_time=\d*/exec_time=x/ /@3=\d*/@3=X/ /CRC32 0x[0-9a-f]+/CRC32 XXX/ /@@session.sql_mode=\d+/@@session.sql_mode=#/ /collation_server=\d+/collation_server=#/ /thread_id=\d*/thread_id=TID/ +--exec $MYSQL_BINLOG --verbose --verbose --base64-output=DECODE-ROWS $datadir/$binlog --start-position=$binlog_pos --stop-position=$binlog_end DROP TABLE t1,t2; diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index de0d3dc4003..a3811ca61e2 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3433,6 +3433,22 @@ SET sort_buffer_size= @save_sort_buffer_size; SET max_length_for_sort_data= @save_max_length_for_sort_data; DROP TABLE t1; # +# MDEV-23596: Assertion `tab->ref.use_count' failed in join_read_key_unlock_row +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY(b)); +INSERT INTO t1 VALUES (0, 1),(1, 2); +CREATE TABLE t2 SELECT * FROM t1; +EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +2 DEPENDENT SUBQUERY t1 index PRIMARY b 5 NULL 1 Using where +SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; +c +1 +NULL +DROP TABLE t1,t2; +# end of 10.1 tests +# # MDEV-13994: Bad join results with orderby_uses_equalities=on # CREATE TABLE books ( diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test index 038bf82b0fb..8e0b479e02d 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -2203,6 +2203,21 @@ SET max_length_for_sort_data= @save_max_length_for_sort_data; DROP TABLE t1; --echo # +--echo # MDEV-23596: Assertion `tab->ref.use_count' failed in join_read_key_unlock_row +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY(b)); +INSERT INTO t1 VALUES (0, 1),(1, 2); +CREATE TABLE t2 SELECT * FROM t1; + +EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; +SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; + +DROP TABLE t1,t2; + +--echo # end of 10.1 tests + +--echo # --echo # MDEV-13994: Bad join results with orderby_uses_equalities=on --echo # diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index d37b76e5f74..1d3acaf062b 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -1945,6 +1945,95 @@ KILL ( SELECT 1 ) + LASTVAL(s); ERROR 42000: KILL does not support subqueries or stored functions KILL LASTVAL(s); ERROR 42000: KILL does not support subqueries or stored functions +# +# MDEV-23094: Multiple calls to a Stored Procedure from another +# Stored Procedure crashes server +# +create table t1 (id1 int primary key, data1 int); +create table t2 (id2 int primary key, data2 int); +create procedure p1(IN id int, IN dt int) +begin +if (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +then +select 1; +end if; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(IN id int, IN dt int) +begin +case (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +when 1 then +select 1; +else +select 0; +end case; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(IN id int, IN dt int) +begin +declare wcont int default 1; +while (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) and wcont +do +select 1; +set wcont=0; +end while; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(IN id int, IN dt int) +begin +declare count int default 1; +repeat +select 1; +set count=count+1; +until (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) and +count < 3 +end repeat; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(IN id int, IN dt int) +begin +for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +do +select 1; +end for; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +drop table t1,t2; # End of 10.4 tests # # Start of 10.5 tests diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test index 3689f38dc7f..755cbb95c45 100644 --- a/mysql-test/main/parser.test +++ b/mysql-test/main/parser.test @@ -1698,6 +1698,103 @@ KILL ( SELECT 1 ) + LASTVAL(s); --error ER_SUBQUERIES_NOT_SUPPORTED KILL LASTVAL(s); +--echo # +--echo # MDEV-23094: Multiple calls to a Stored Procedure from another +--echo # Stored Procedure crashes server +--echo # + +create table t1 (id1 int primary key, data1 int); +create table t2 (id2 int primary key, data2 int); + +delimiter //; +create procedure p1(IN id int, IN dt int) +begin + if (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) + then + select 1; + end if; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(IN id int, IN dt int) +begin +case (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) +when 1 then + select 1; +else + select 0; +end case; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(IN id int, IN dt int) +begin +declare wcont int default 1; +while (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) and wcont +do + select 1; + set wcont=0; +end while; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(IN id int, IN dt int) +begin +declare count int default 1; +repeat + select 1; + set count=count+1; +until (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) and + count < 3 +end repeat; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(IN id int, IN dt int) +begin +for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) +do + select 1; +end for; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +drop table t1,t2; + --echo # End of 10.4 tests diff --git a/mysql-test/main/rowid_filter.result b/mysql-test/main/rowid_filter.result index 6fda4b03b0f..83cf932bdae 100644 --- a/mysql-test/main/rowid_filter.result +++ b/mysql-test/main/rowid_filter.result @@ -2165,6 +2165,12 @@ A.a+1000*B.a + 10000, 'filler-data-filler-data' from t11 A, t10 B; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'el_index' +test.t1 analyze Warning Engine-independent statistics are not collected for column 'filler' +test.t1 analyze status Table is already up to date # This must not use rowid_filter with key=el_index|el_index_60: explain select * from t1 diff --git a/mysql-test/main/rowid_filter.test b/mysql-test/main/rowid_filter.test index c47710e65b8..ed1227d3770 100644 --- a/mysql-test/main/rowid_filter.test +++ b/mysql-test/main/rowid_filter.test @@ -377,6 +377,7 @@ select 'filler-data-filler-data' from t11 A, t10 B; +analyze table t1 persistent for all; --echo # This must not use rowid_filter with key=el_index|el_index_60: explain diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result index 15e77f5689e..b2d598ca229 100644 --- a/mysql-test/main/rowid_filter_innodb.result +++ b/mysql-test/main/rowid_filter_innodb.result @@ -2114,6 +2114,12 @@ A.a+1000*B.a + 10000, 'filler-data-filler-data' from t11 A, t10 B; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'el_index' +test.t1 analyze Warning Engine-independent statistics are not collected for column 'filler' +test.t1 analyze status OK # This must not use rowid_filter with key=el_index|el_index_60: explain select * from t1 diff --git a/mysql-test/main/temp_table_symlink.result b/mysql-test/main/temp_table_symlink.result new file mode 100644 index 00000000000..1c5c68170ff --- /dev/null +++ b/mysql-test/main/temp_table_symlink.result @@ -0,0 +1,13 @@ +create table d1 (a int); +create temporary table t1 (a int); +create temporary table t2 (a int); +Got one of the listed errors +create temporary table t3 (a int) engine=Aria; +Got one of the listed errors +select * from information_schema.columns where table_schema='test'; +Got one of the listed errors +flush tables; +select * from d1; +a +drop temporary table t1; +drop table d1; diff --git a/mysql-test/main/temp_table_symlink.test b/mysql-test/main/temp_table_symlink.test new file mode 100644 index 00000000000..35f956e8890 --- /dev/null +++ b/mysql-test/main/temp_table_symlink.test @@ -0,0 +1,33 @@ +source include/not_windows.inc; + +# +# MDEV-23569 temporary tables can overwrite existing files +# + +let datadir=`select @@datadir`; +create table d1 (a int); +create temporary table t1 (a int); +perl; +chdir "$ENV{MYSQL_TMP_DIR}/mysqld.1/"; +for (<#sql*.MYI>) { + /^(#sql-temptable-[0-9a-f]+)(-[0-9a-f]+-)([0-9a-f]+)\.MYI$/ or die $_; + symlink "$ENV{datadir}/test/d1.MYI", sprintf "$1$2%x.MYI", hex($3)+1; + symlink "$ENV{datadir}/test/d1.MYI", sprintf "$1$2%x.MAI", hex($3)+1; + symlink "$ENV{datadir}/test/d1.MYI", sprintf "$1$2%x.MAI", hex($3)+2; + symlink "$ENV{datadir}/test/d1.MYI", sprintf "$1$2%x.MAI", hex($3)+3; + symlink "$ENV{datadir}/test/d1.MYI", "$1-0.MAI"; +} +EOF + +error 1,1030; +create temporary table t2 (a int); +error 1,1030; +create temporary table t3 (a int) engine=Aria; +error 1,1030; +select * from information_schema.columns where table_schema='test'; + +flush tables; +select * from d1; +drop temporary table t1; +remove_files_wildcard $MYSQL_TMP_DIR/mysqld.1 *sql*; +drop table d1; diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result index 1229ef885b4..3e400d4f272 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result @@ -5356,7 +5356,5 @@ START TRANSACTION #010909 4:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1dec102` mapped to number # # at # #010909 4:46:40 server id 1 end_log_pos # CRC32 XXX Write_rows: table id # flags: STMT_END_F -### INSERT INTO `test`.`t1dec102` -### SET -### @1= + Error: Found Old DECIMAL (mysql-4.1 or earlier). Not enough metadata to display the value. diff --git a/mysql-test/suite/binlog/r/binlog_row_annotate.result b/mysql-test/suite/binlog/r/binlog_row_annotate.result index 5d70f7871ab..e41258ccafd 100644 --- a/mysql-test/suite/binlog/r/binlog_row_annotate.result +++ b/mysql-test/suite/binlog/r/binlog_row_annotate.result @@ -449,7 +449,6 @@ START TRANSACTION ### DELETE FROM `test1`.`t1` ### WHERE ### @1=3 /* INT meta=0 nullable=1 is_null=0 */ -'/*!*/; # at # #010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; @@ -1073,7 +1072,6 @@ START TRANSACTION ### DELETE FROM `test1`.`t1` ### WHERE ### @1=3 /* INT meta=0 nullable=1 is_null=0 */ -'/*!*/; # at # #010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test index 9f0d0f2588b..3e18ef1e351 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test @@ -11,8 +11,7 @@ SELECT a into @a from t; FLUSH LOGS; DELETE FROM t; -# Todo: MDEV-10362 to test multi-row Rows_log_event:s in verbose mode ---exec $MYSQL_BINLOG -vv --debug-binlog-row-event-max-encoded-size=256 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--exec $MYSQL_BINLOG --verbose --debug-binlog-row-event-max-encoded-size=256 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql --let SEARCH_PATTERN= BINLOG @binlog_fragment_0, @binlog_fragment_1 --let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql diff --git a/mysql-test/suite/binlog_encryption/binlog_row_annotate.result b/mysql-test/suite/binlog_encryption/binlog_row_annotate.result index b5e6721ace1..142714f2377 100644 --- a/mysql-test/suite/binlog_encryption/binlog_row_annotate.result +++ b/mysql-test/suite/binlog_encryption/binlog_row_annotate.result @@ -456,7 +456,6 @@ START TRANSACTION ### DELETE FROM `test1`.`t1` ### WHERE ### @1=3 /* INT meta=0 nullable=1 is_null=0 */ -'/*!*/; # at # #010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result index c5810c7c1d5..3f02382b6e4 100644 --- a/mysql-test/suite/compat/oracle/r/parser.result +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -644,6 +644,121 @@ END; # End of 10.3 tests # # +# MDEV-21998: Server crashes in st_select_lex::add_table_to_list +# upon mix of KILL and sequences +# +KILL ( SELECT 1 ) + LASTVAL(s); +ERROR 42000: KILL does not support subqueries or stored functions +KILL LASTVAL(s); +ERROR 42000: KILL does not support subqueries or stored functions +# +# MDEV-23094: Multiple calls to a Stored Procedure from another +# Stored Procedure crashes server +# +create table t1 (id1 int primary key, data1 int); +create table t2 (id2 int primary key, data2 int); +create procedure p1(id int,dt int) as +begin +if (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +then +select 1; +end if; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(id int, dt int) as +begin +case (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +when 1 then +select 1; +else +select 0; +end case; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(id int, dt int) as +begin +declare wcont int default 1; +begin +while (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) and wcont +loop +select 1; +set wcont=0; +end loop; +end; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(id int, dt int) as +begin +declare count int default 1; +begin +repeat +select 1; +set count=count+1; +until (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) and +count < 3 +end repeat; +end; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +create procedure p1(id int, dt int) as +begin +for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)) +loop +select 1; +end loop; +end // +call p1(1,2); +1 +1 +call p1(1,2); +1 +1 +drop procedure p1; +set sql_mode=ORACLE; +create or replace procedure p1(id int, dt int) as +begin +while (1) +loop +exit when (exists(select * from t1 where id1 = id and data1 = dt) or +not exists (select * from t2 where id2 = id and data2 = dt)); +end loop; +end; +// +call p1(1,2); +call p1(1,2); +drop procedure p1; +drop table t1,t2; +# End of 10.4 tests +# # Start of 10.5 tests # # diff --git a/mysql-test/suite/compat/oracle/t/parser.test b/mysql-test/suite/compat/oracle/t/parser.test index 99355c57dc3..d5d3b39f0b9 100644 --- a/mysql-test/suite/compat/oracle/t/parser.test +++ b/mysql-test/suite/compat/oracle/t/parser.test @@ -462,6 +462,137 @@ DELIMITER ;// --echo # +--echo # MDEV-21998: Server crashes in st_select_lex::add_table_to_list +--echo # upon mix of KILL and sequences +--echo # + +--error ER_SUBQUERIES_NOT_SUPPORTED +KILL ( SELECT 1 ) + LASTVAL(s); +--error ER_SUBQUERIES_NOT_SUPPORTED +KILL LASTVAL(s); + +--echo # +--echo # MDEV-23094: Multiple calls to a Stored Procedure from another +--echo # Stored Procedure crashes server +--echo # + +create table t1 (id1 int primary key, data1 int); +create table t2 (id2 int primary key, data2 int); + +delimiter //; +create procedure p1(id int,dt int) as +begin + if (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) + then + select 1; + end if; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(id int, dt int) as +begin +case (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) +when 1 then + select 1; +else + select 0; +end case; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(id int, dt int) as +begin +declare wcont int default 1; +begin + while (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) and wcont + loop + select 1; + set wcont=0; + end loop; +end; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(id int, dt int) as +begin +declare count int default 1; +begin + repeat + select 1; + set count=count+1; + until (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) and + count < 3 + end repeat; +end; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +create procedure p1(id int, dt int) as +begin +for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)) +loop + select 1; +end loop; +end // +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +delimiter //; +set sql_mode=ORACLE; +create or replace procedure p1(id int, dt int) as +begin + while (1) + loop + exit when (exists(select * from t1 where id1 = id and data1 = dt) or + not exists (select * from t2 where id2 = id and data2 = dt)); + end loop; +end; +// +delimiter ;// + +call p1(1,2); +call p1(1,2); + +drop procedure p1; + +drop table t1,t2; + +--echo # End of 10.4 tests + +--echo # --echo # Start of 10.5 tests --echo # diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 1e993bca1e9..baff20752be 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -16,6 +16,7 @@ MDEV-16509 : MDEV-21523 galera.MDEV-16509 MDEV-20225 : MDEV-20886 galera.MDEV-20225 MW-286 : MDEV-18464 Killing thread can cause mutex deadlock if done concurrently with Galera/replication victim kill MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 +MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-329 : MDEV-19962 Galera test failure on MW-329 galera.galera_defaults : MDEV-21494 Galera test sporadic failure on galera.galera_defaults galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result index 291d641db88..16db26c3c6b 100644 --- a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result +++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result @@ -1,5 +1,10 @@ connection node_2; connection node_1; +# +# test phase with cascading foreign key through 3 tables +# +connection node_1; +set wsrep_sync_wait=0; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY ) ENGINE=InnoDB; @@ -21,14 +26,15 @@ INSERT INTO grandparent VALUES (1),(2); INSERT INTO parent VALUES (1,1), (2,2); INSERT INTO child VALUES (1,1), (2,2); connection node_2; +set wsrep_sync_wait=0; DELETE FROM grandparent WHERE id = 1; connection node_1; -SELECT COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; -COUNT(*) = 0 -1 -SELECT COUNT(*) = 0 FROM child WHERE parent_id = 1; -COUNT(*) = 0 -1 +SELECT COUNT(*), COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child WHERE parent_id = 1; +COUNT(*) COUNT(*) = 0 +0 1 DROP TABLE child; DROP TABLE parent; DROP TABLE grandparent; diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result new file mode 100644 index 00000000000..33ae66b1989 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result @@ -0,0 +1,69 @@ +connection node_2; +connection node_1; +# +# test phase with foreign key of varchar type +# +connection node_1; +CREATE TABLE parent ( +`id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE TABLE child ( +`id` int NOT NULL, +`parent_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `parent_id` (`parent_id`), +CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +INSERT INTO parent VALUES ('row one'), ('row two'); +INSERT INTO child VALUES (1,'row one'), (2,'row two'); +connection node_2; +DELETE FROM parent; +connection node_1; +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child; +COUNT(*) COUNT(*) = 0 +0 1 +DROP TABLE child; +DROP TABLE parent; +# +# test phase with MM conflict in FK cascade +# +connection node_1; +set wsrep_retry_autocommit=0; +CREATE TABLE parent ( +id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; +CREATE TABLE child ( +id INT NOT NULL PRIMARY KEY, +j int default 0, +parent_id INT, +FOREIGN KEY (parent_id) +REFERENCES parent(id) +ON DELETE CASCADE +) ENGINE=InnoDB; +INSERT INTO parent VALUES (1); +INSERT INTO child VALUES (1,0,1); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; +connection node_2; +DELETE FROM parent; +connection node_1a; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_1; +update child set j=2;; +connection node_1a; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; +connection node_1; +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child; +COUNT(*) COUNT(*) = 0 +0 1 +DROP TABLE child; +DROP TABLE parent; diff --git a/mysql-test/suite/galera/r/galera_trigger.result b/mysql-test/suite/galera/r/galera_trigger.result new file mode 100644 index 00000000000..48147492979 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_trigger.result @@ -0,0 +1,34 @@ +connection node_2; +connection node_1; +CREATE TABLE IF NOT EXISTS t1 (id int(10) not null primary key) engine=innodb; +CREATE OR REPLACE TRIGGER tr1 +BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +SET NEW.id = 100; +END| +INSERT INTO t1 VALUES (1); +SELECT * from t1; +id +100 +CREATE OR REPLACE TRIGGER tr1 +BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +SET NEW.id = 200; +END| +connection node_2; +SET SESSION wsrep_sync_wait=15; +SELECT * FROM t1; +id +100 +INSERT INTO t1 values (2); +SELECT * FROM t1; +id +100 +200 +connection node_1; +SELECT * FROM t1; +id +100 +200 +DROP TRIGGER tr1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_fk_cascade_delete.test b/mysql-test/suite/galera/t/galera_fk_cascade_delete.test index 9b79b4c30b6..6f0de0a1f4a 100644 --- a/mysql-test/suite/galera/t/galera_fk_cascade_delete.test +++ b/mysql-test/suite/galera/t/galera_fk_cascade_delete.test @@ -3,7 +3,13 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc + +--echo # +--echo # test phase with cascading foreign key through 3 tables +--echo # + +--connection node_1 +set wsrep_sync_wait=0; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY @@ -30,11 +36,17 @@ INSERT INTO parent VALUES (1,1), (2,2); INSERT INTO child VALUES (1,1), (2,2); --connection node_2 +set wsrep_sync_wait=0; + +--let $wait_condition = SELECT COUNT(*) = 2 FROM child; +--source include/wait_condition.inc DELETE FROM grandparent WHERE id = 1; --connection node_1 -SELECT COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; -SELECT COUNT(*) = 0 FROM child WHERE parent_id = 1; +--let $wait_condition = SELECT COUNT(*) = 1 FROM child; +--source include/wait_condition.inc +SELECT COUNT(*), COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; +SELECT COUNT(*), COUNT(*) = 0 FROM child WHERE parent_id = 1; DROP TABLE child; DROP TABLE parent; diff --git a/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test b/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test new file mode 100644 index 00000000000..f38c028b7d6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test @@ -0,0 +1,98 @@ +--source include/galera_cluster.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--echo # +--echo # test phase with foreign key of varchar type +--echo # +--connection node_1 + CREATE TABLE parent ( + `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + + CREATE TABLE child ( + `id` int NOT NULL, + `parent_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `parent_id` (`parent_id`), + CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +INSERT INTO parent VALUES ('row one'), ('row two'); +INSERT INTO child VALUES (1,'row one'), (2,'row two'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM child; +--source include/wait_condition.inc +DELETE FROM parent; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM child; +--source include/wait_condition.inc + +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +SELECT COUNT(*), COUNT(*) = 0 FROM child; + +DROP TABLE child; +DROP TABLE parent; + +--echo # +--echo # test phase with MM conflict in FK cascade +--echo # + +--connection node_1 +set wsrep_retry_autocommit=0; +CREATE TABLE parent ( + id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; + +CREATE TABLE child ( + id INT NOT NULL PRIMARY KEY, + j int default 0, + parent_id INT, + FOREIGN KEY (parent_id) + REFERENCES parent(id) + ON DELETE CASCADE +) ENGINE=InnoDB; + +INSERT INTO parent VALUES (1); +INSERT INTO child VALUES (1,0,1); + +# block applier before applying +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM child; +--source include/wait_condition.inc +DELETE FROM parent; + +--connection node_1a +# wait until applier has reached the sync point +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + + +--connection node_1 +# issue conflicting write to child table, it should fail in certification +--error ER_LOCK_DEADLOCK +--send update child set j=2; + +--connection node_1a +# release the applier +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; + +--connection node_1 +--reap + +--let $wait_condition = SELECT COUNT(*) = 0 FROM child; +--source include/wait_condition.inc +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +SELECT COUNT(*), COUNT(*) = 0 FROM child; + +DROP TABLE child; +DROP TABLE parent; diff --git a/mysql-test/suite/galera/t/galera_trigger.test b/mysql-test/suite/galera/t/galera_trigger.test new file mode 100644 index 00000000000..54508583f4b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_trigger.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +# +# MDEV-21578 CREATE OR REPLACE TRIGGER in Galera cluster not replicating +# +CREATE TABLE IF NOT EXISTS t1 (id int(10) not null primary key) engine=innodb; +--delimiter | +CREATE OR REPLACE TRIGGER tr1 +BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +SET NEW.id = 100; +END| +--delimiter ; + +INSERT INTO t1 VALUES (1); +SELECT * from t1; + +--delimiter | +CREATE OR REPLACE TRIGGER tr1 +BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +SET NEW.id = 200; +END| +--delimiter ; + +--connection node_2 +SET SESSION wsrep_sync_wait=15; +SELECT * FROM t1; +INSERT INTO t1 values (2); +SELECT * FROM t1; + +--connection node_1 +SELECT * FROM t1; + +DROP TRIGGER tr1; +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 415da407cf7..c6d3ece75d1 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -10,12 +10,6 @@ # ############################################################################## -galera_ipv6_mariabackup : MDEV-23573 Could not open '../galera/include/have_mariabackup.inc' -galera_ipv6_mariabackup_section : MDEV-23574 Could not open '../galera/include/have_mariabackup.inc' -galera_ipv6_mysqldump : MDEV-23576 WSREP_SST: [ERROR] rsync daemon port '16008' has been taken -galera_ipv6_rsyn : MDEV-23581 WSREP_SST: [ERROR] rsync daemon port '16008' has been taken -galera_ipv6_rsync_section : MDEV-23580 WSREP_SST: [ERROR] rsync daemon port '16008' has been taken -galera_ipv6_xtrabackup-v2 : MDEV-23575 WSREP_SST: [ERROR] innobackupex not in path galera_ist_gcache_rollover : MDEV-23578 WSREP: exception caused by message: {v=0,t=1,ut=255,o=4,s=0,sr=0,as=1,f=6,src=50524cfe,srcvid=view_id(REG,50524cfe,4),insvid=view_id(UNKNOWN,00000000,0),ru=00000000,r=[-1,-1],fs=75,nl=(} galera_slave_options_do :MDEV-8798 galera_slave_options_ignore : MDEV-8798 diff --git a/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result b/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result deleted file mode 100644 index e3935c32fda..00000000000 --- a/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result +++ /dev/null @@ -1,20 +0,0 @@ -connection node_2; -connection node_1; -connection node_1; -connection node_2; -connection node_3; -connection node_1; -CREATE TABLE t1 (f1 INTEGER); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); -connection node_2; -SELECT COUNT(*) = 10 FROM t1; -COUNT(*) = 10 -1 -Killing server ... -connection node_1; -INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); -# restart -SELECT COUNT(*) = 20 FROM t1; -COUNT(*) = 20 -1 -DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm index da02d4a9020..f93cd0e0909 100644 --- a/mysql-test/suite/galera_3nodes/suite.pm +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -17,7 +17,6 @@ push @::global_suppressions, qr(WSREP:.*down context.*), qr(WSREP: Failed to send state UUID:), qr(WSREP: last inactive check more than .* skipping check), - qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), qr|WSREP: access file\(.*gvwstate.dat\) failed\(No such file or directory\)|, qr(WSREP: Quorum: No node with complete state), @@ -31,14 +30,34 @@ push @::global_suppressions, qr(WSREP: user message in state LEAVING), qr(WSREP: .* sending install message failed: Transport endpoint is not connected), qr(WSREP: .* sending install message failed: Resource temporarily unavailable), - qr(WSREP: Sending JOIN failed: -107 \(Transport endpoint is not connected\). Will retry in new primary component.), + qr(WSREP: Maximum writeset size exceeded by .*), + qr(WSREP: transaction size exceeded.*), + qr(WSREP: RBR event .*), + qr(WSREP: Ignoring error for TO isolated action: .*), + qr(WSREP: transaction size limit .*), + qr(WSREP: rbr write fail, .*), + qr(WSREP: .*Backend not supported: foo.*), + qr(WSREP: .*Failed to initialize backend using .*), + qr(WSREP: .*Failed to open channel 'my_wsrep_cluster' at .*), + qr(WSREP: gcs connect failed: Socket type not supported), + qr(WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 .*), + qr(WSREP: .*Failed to open backend connection: -110 .*), + qr(WSREP: .*Failed to open channel 'my_wsrep_cluster' at .*), + qr(WSREP: gcs connect failed: Connection timed out), + qr|WSREP: wsrep::connect\(.*\) failed: 7|, + qr(WSREP: SYNC message from member .* in non-primary configuration. Ignored.), qr(WSREP: Could not find peer:), + qr(WSREP: TO isolation failed for: .*), qr|WSREP: gcs_caused\(\) returned .*|, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(JOINED\). Message ignored.|, + qr|WSREP: Unsupported protocol downgrade: incremental data collection disabled. Expect abort.|, qr(WSREP: Action message in non-primary configuration from member [0-9]*), + qr(WSREP: Last Applied Action message in non-primary configuration from member [0-9]*), + qr(WSREP: discarding established .*), + qr|WSREP: .*core_handle_uuid_msg.*|, qr(WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0. WSREP_SYNC_WAIT_BEFORE_READ is on), - qr(WSREP: JOIN message from member .* in non-primary configuration. Ignored.), + qr|WSREP: JOIN message from member .* in non-primary configuration. Ignored.|, qr|Query apply failed:*|, qr(WSREP: Ignoring error*), qr(WSREP: Failed to remove page file .*), diff --git a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.cnf b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.cnf deleted file mode 100644 index 35ecb8b5937..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.cnf +++ /dev/null @@ -1,4 +0,0 @@ -!include ../galera_3nodes.cnf - -[mysqld] -wsrep-causal-reads=OFF diff --git a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test deleted file mode 100644 index cd5c020ae38..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test +++ /dev/null @@ -1,80 +0,0 @@ -# -# This test uses innobackupex to take a backup on node #2 and then restores that node from backup -# - ---source include/galera_cluster.inc ---source include/have_innodb.inc ---source suite/galera/include/have_mariabackup.inc - ---let $galera_connection_name = node_3 ---let $galera_server_number = 3 ---source include/galera_connect.inc - -# Save original auto_increment_offset values. ---let $node_1=node_1 ---let $node_2=node_2 ---let $node_3=node_3 ---source ../galera/include/auto_increment_offset_save.inc - ---connection node_1 -CREATE TABLE t1 (f1 INTEGER); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); - ---connection node_2 -SELECT COUNT(*) = 10 FROM t1; - ---exec rm -rf $MYSQL_TMP_DIR/innobackupex_backup ---exec mariabackup --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp $MYSQL_TMP_DIR/innobackupex_backup &> $MYSQL_TMP_DIR/innobackupex-backup.log ---exec mariabackup --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 --apply-log --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp $MYSQL_TMP_DIR/innobackupex_backup &> $MYSQL_TMP_DIR/innobackupex-apply.log - ---source ../galera/include/kill_galera.inc ---sleep 1 - ---connection node_1 -INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); - ---exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/* ---exec mariabackup --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 --copy-back --port=$NODE_MYPORT_2 --host=127.0.0.1 $MYSQL_TMP_DIR/innobackupex_backup &> $MYSQL_TMP_DIR/innobackupex-restore.log - -# -# Convert the xtrabackup_galera_info into a grastate.dat file -# - ---perl - use strict; - my $xtrabackup_galera_info_file = $ENV{'MYSQL_TMP_DIR'}.'/innobackupex_backup/xtrabackup_galera_info'; - open(XTRABACKUP_GALERA_INFO, $xtrabackup_galera_info_file) or die "Can not open $xtrabackup_galera_info_file: $!"; - my $xtrabackup_galera_info = <XTRABACKUP_GALERA_INFO>; - my ($uuid, $seqno) = split(':', $xtrabackup_galera_info); - - my $grastate_dat_file = $ENV{'MYSQLTEST_VARDIR'}.'/mysqld.2/data/grastate.dat'; - die "grastate.dat already exists" if -e $grastate_dat_file; - - open(GRASTATE_DAT, ">$grastate_dat_file") or die "Can not write to $grastate_dat_file: $!"; - print GRASTATE_DAT "version: 2.1\n"; - print GRASTATE_DAT "uuid: $uuid\n"; - print GRASTATE_DAT "seqno: $seqno\n"; - print GRASTATE_DAT "cert_index:\n"; - exit(0); -EOF - ---source include/start_mysqld.inc ---sleep 5 - ---source include/wait_until_connected_again.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc - -SELECT COUNT(*) = 20 FROM t1; - -DROP TABLE t1; - ---sleep 10 - ---let $galera_connection_name = node_2a ---let $galera_server_number = 2 ---source include/galera_connect.inc ---let $node_2=node_2a - -# Restore original auto_increment_offset values. ---source ../galera/include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test index d6b97f939f2..d492a735bbf 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test @@ -1,7 +1,8 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc --source include/have_innodb.inc ---source ../galera/include/have_mariabackup.inc +--source include/have_mariabackup.inc +--source include/force_restart.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test index e9425bcffdf..688e6950d54 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test @@ -1,7 +1,8 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc --source include/have_innodb.inc ---source ../galera/include/have_mariabackup.inc +--source include/have_mariabackup.inc +--source include/force_restart.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test index c9c32f23230..ff93ed07763 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test @@ -1,5 +1,6 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc +--source include/force_restart.inc call mtr.add_suppression("WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to'"); call mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos"); diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test index 1937eb43e13..fff776d98b6 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test @@ -1,5 +1,6 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc +--source include/force_restart.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test index 1937eb43e13..fff776d98b6 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test @@ -1,5 +1,6 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc +--source include/force_restart.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test index 9f9d6da17b9..8c1d6246d44 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test +++ b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test @@ -34,6 +34,9 @@ SET SESSION wsrep_sync_wait = 0; SET SESSION wsrep_dirty_reads = 1; +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + # Those statements should succeed --error 0 @@ -111,6 +114,7 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST; # Restore cluster SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +--source include/galera_wait_ready.inc --connection node_1 --let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; diff --git a/mysql-test/suite/gcol/inc/gcol_keys.inc b/mysql-test/suite/gcol/inc/gcol_keys.inc index 97c9e41b5e8..475ab96e56f 100644 --- a/mysql-test/suite/gcol/inc/gcol_keys.inc +++ b/mysql-test/suite/gcol/inc/gcol_keys.inc @@ -747,4 +747,66 @@ ANALYZE TABLE t1, t2; --eval $query DROP TABLE t1, t2; +if($support_virtual_index) +{ +--echo # +--echo # MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed +--echo # in row_upd_sec_index_entry +--echo # +CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT, + PRIMARY KEY (PK), UNIQUE KEY (VA)); + +INSERT IGNORE INTO t1 VALUES ( '\r1','a',1); +--error ER_DATA_TOO_LONG +REPLACE INTO t1 (PK) VALUES (1); + +DROP TABLE t1; + +--echo # +--echo # MDEV-17890 Record in index was not found on update, server crash in +--echo # row_upd_build_difference_binary or +--echo # Assertion `0' failed in row_upd_sec_index_entry +--echo # +CREATE TABLE t1 ( + pk BIGINT AUTO_INCREMENT, + b BIT(15), + v BIT(10) AS (b) VIRTUAL, + PRIMARY KEY(pk), + UNIQUE(v) +); + +INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101'); +SELECT pk, b INTO OUTFILE 'load.data' FROM t1; +--error ER_DATA_TOO_LONG +LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b); + +--let $datadir= `SELECT @@datadir` +--remove_file $datadir/test/load.data +DROP TABLE t1; + +--echo # +--echo # MDEV-17834 Server crashes in row_upd_build_difference_binary +--echo # on LOAD DATA into table with indexed virtual column --echo # +CREATE TABLE t1 ( + pk INT, + i TINYINT, + ts TIMESTAMP NULL, + vi TINYINT AS (i+1) PERSISTENT, + vts TIMESTAMP(5) AS (ts) VIRTUAL, + PRIMARY KEY(pk), + UNIQUE(vts) +); + +INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); + +--write_file $MYSQLTEST_VARDIR/tmp/load.data +1 4 2019-01-01 00:00:00 +EOF +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--error ER_WARN_DATA_OUT_OF_RANGE +eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts); + +--remove_file $MYSQLTEST_VARDIR/tmp/load.data +DROP TABLE t1; +} diff --git a/mysql-test/suite/gcol/r/gcol_keys_innodb.result b/mysql-test/suite/gcol/r/gcol_keys_innodb.result index 2028a95a081..4f7d654ac4e 100644 --- a/mysql-test/suite/gcol/r/gcol_keys_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_keys_innodb.result @@ -833,6 +833,56 @@ a1 a2 b 0 NULL 1 DROP TABLE t1, t2; # +# MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed +# in row_upd_sec_index_entry +# +CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT, +PRIMARY KEY (PK), UNIQUE KEY (VA)); +INSERT IGNORE INTO t1 VALUES ( '\r1','a',1); +Warnings: +Warning 1906 The value specified for generated column 'VA' in table 't1' has been ignored +Warning 1264 Out of range value for column 'VA' at row 1 +REPLACE INTO t1 (PK) VALUES (1); +ERROR 22001: Data too long for column 'VA' at row 1 +DROP TABLE t1; +# +# MDEV-17890 Record in index was not found on update, server crash in +# row_upd_build_difference_binary or +# Assertion `0' failed in row_upd_sec_index_entry +# +CREATE TABLE t1 ( +pk BIGINT AUTO_INCREMENT, +b BIT(15), +v BIT(10) AS (b) VIRTUAL, +PRIMARY KEY(pk), +UNIQUE(v) +); +INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101'); +Warnings: +Warning 1264 Out of range value for column 'v' at row 1 +SELECT pk, b INTO OUTFILE 'load.data' FROM t1; +LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b); +ERROR 22001: Data too long for column 'v' at row 1 +DROP TABLE t1; +# +# MDEV-17834 Server crashes in row_upd_build_difference_binary +# on LOAD DATA into table with indexed virtual column +# +CREATE TABLE t1 ( +pk INT, +i TINYINT, +ts TIMESTAMP NULL, +vi TINYINT AS (i+1) PERSISTENT, +vts TIMESTAMP(5) AS (ts) VIRTUAL, +PRIMARY KEY(pk), +UNIQUE(vts) +); +INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); +Warnings: +Warning 1264 Out of range value for column 'vi' at row 1 +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts); +ERROR 22003: Out of range value for column 'vi' at row 1 +DROP TABLE t1; # # BUG#21365158 WL8149:ASSERTION `!TABLE || (!TABLE->WRITE_SET # diff --git a/mysql-test/suite/gcol/r/gcol_keys_myisam.result b/mysql-test/suite/gcol/r/gcol_keys_myisam.result index 91bd8fcdb78..3f00d344901 100644 --- a/mysql-test/suite/gcol/r/gcol_keys_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_keys_myisam.result @@ -833,6 +833,56 @@ a1 a2 b 0 NULL 1 DROP TABLE t1, t2; # +# MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed +# in row_upd_sec_index_entry +# +CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT, +PRIMARY KEY (PK), UNIQUE KEY (VA)); +INSERT IGNORE INTO t1 VALUES ( '\r1','a',1); +Warnings: +Warning 1906 The value specified for generated column 'VA' in table 't1' has been ignored +Warning 1264 Out of range value for column 'VA' at row 1 +REPLACE INTO t1 (PK) VALUES (1); +ERROR 22001: Data too long for column 'VA' at row 1 +DROP TABLE t1; +# +# MDEV-17890 Record in index was not found on update, server crash in +# row_upd_build_difference_binary or +# Assertion `0' failed in row_upd_sec_index_entry +# +CREATE TABLE t1 ( +pk BIGINT AUTO_INCREMENT, +b BIT(15), +v BIT(10) AS (b) VIRTUAL, +PRIMARY KEY(pk), +UNIQUE(v) +); +INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101'); +Warnings: +Warning 1264 Out of range value for column 'v' at row 1 +SELECT pk, b INTO OUTFILE 'load.data' FROM t1; +LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b); +ERROR 22001: Data too long for column 'v' at row 1 +DROP TABLE t1; +# +# MDEV-17834 Server crashes in row_upd_build_difference_binary +# on LOAD DATA into table with indexed virtual column +# +CREATE TABLE t1 ( +pk INT, +i TINYINT, +ts TIMESTAMP NULL, +vi TINYINT AS (i+1) PERSISTENT, +vts TIMESTAMP(5) AS (ts) VIRTUAL, +PRIMARY KEY(pk), +UNIQUE(vts) +); +INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); +Warnings: +Warning 1264 Out of range value for column 'vi' at row 1 +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts); +ERROR 22003: Out of range value for column 'vi' at row 1 +DROP TABLE t1; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_index.result b/mysql-test/suite/gcol/r/innodb_virtual_index.result index 3918cf95ae1..70c9d10a68b 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_index.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_index.result @@ -255,6 +255,9 @@ ERROR 22007: Incorrect date value: '20190132' for column `test`.`t1`.`vb` at row SELECT * FROM t1; a b vb ROLLBACK; +SELECT * FROM t1; +a b vb +1 20190132 0000-00-00 CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.test b/mysql-test/suite/gcol/t/innodb_virtual_index.test index c2f9cd78fe2..353841840dc 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_index.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_index.test @@ -278,7 +278,6 @@ DELETE FROM t1; INSERT INTO t1 (a,b) VALUES(1,20190123); SELECT * FROM t1; ROLLBACK; -# MDEV-18366 FIXME: fix the crash and enable this -# SELECT * FROM t1; +SELECT * FROM t1; CHECK TABLE t1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/foreign-keys.result b/mysql-test/suite/innodb/r/foreign-keys.result index 62b4d37a979..45177a4bddf 100644 --- a/mysql-test/suite/innodb/r/foreign-keys.result +++ b/mysql-test/suite/innodb/r/foreign-keys.result @@ -220,3 +220,19 @@ drop table t1,t2; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails drop table t1,t2; ERROR 42S02: Unknown table 'test.t2' +# +# MDEV-23470 InnoDB: Failing assertion: cmp < 0 in +# row_ins_check_foreign_constraint +# +CREATE TABLE t1(f1 INT NOT NULL PRIMARY KEY, f2 INT NOT NULL)ENGINE=InnoDB; +CREATE TABLE t2(f1 VARCHAR(100), f2 INT NOT NULL, +INDEX(f2))ENGINE=InnoDB; +INSERT INTO t1 VALUES(99, 2); +ALTER TABLE t2 ADD FOREIGN KEY(f2) REFERENCES t1(f1); +SET FOREIGN_KEY_CHECKS=0; +DROP INDEX f2 ON t2; +SET FOREIGN_KEY_CHECKS=1; +INSERT INTO t2 VALUES('G', 3); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)) +DROP TABLE t2, t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; diff --git a/mysql-test/suite/innodb/t/foreign-keys.test b/mysql-test/suite/innodb/t/foreign-keys.test index aec6bb54e72..b93f82c93ef 100644 --- a/mysql-test/suite/innodb/t/foreign-keys.test +++ b/mysql-test/suite/innodb/t/foreign-keys.test @@ -249,3 +249,22 @@ show create table t2; drop table t1,t2; --error ER_BAD_TABLE_ERROR drop table t1,t2; + +--echo # +--echo # MDEV-23470 InnoDB: Failing assertion: cmp < 0 in +--echo # row_ins_check_foreign_constraint +--echo # +CREATE TABLE t1(f1 INT NOT NULL PRIMARY KEY, f2 INT NOT NULL)ENGINE=InnoDB; +CREATE TABLE t2(f1 VARCHAR(100), f2 INT NOT NULL, + INDEX(f2))ENGINE=InnoDB; + +INSERT INTO t1 VALUES(99, 2); +ALTER TABLE t2 ADD FOREIGN KEY(f2) REFERENCES t1(f1); + +SET FOREIGN_KEY_CHECKS=0; +DROP INDEX f2 ON t2; +SET FOREIGN_KEY_CHECKS=1; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t2 VALUES('G', 3); +DROP TABLE t2, t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; diff --git a/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result index b6c82e3754c..9ef2f4a89db 100644 --- a/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result +++ b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result @@ -7,6 +7,8 @@ SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first connection slave; include/stop_slave.inc +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test index d4a4faf8d67..529613b37b1 100644 --- a/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test +++ b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test @@ -51,6 +51,8 @@ SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; connection slave; source include/stop_slave.inc; +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; source include/start_slave.inc; diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 1df31a4dfab..b7bd63f662e 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -476,8 +476,7 @@ select pk, col_bit+0, vcol_bit+0 from t1; pk col_bit+0 vcol_bit+0 99 10000 1023 REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99); -Warnings: -Warning 1264 Out of range value for column 'vcol_bit' at row 1 +ERROR 22001: Data too long for column 'vcol_bit' at row 1 drop table t1; # # MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status() @@ -496,8 +495,7 @@ INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); Warnings: Warning 1264 Out of range value for column 'vi' at row 1 REPLACE INTO t1 (pk,i) VALUES (1,2); -Warnings: -Warning 1264 Out of range value for column 'vi' at row 1 +ERROR 22003: Out of range value for column 'vi' at row 1 DROP TABLE t1; SET @sql_mode=@old_sql_mode; # diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 1bbd18d6eab..6f770190bb1 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -448,6 +448,7 @@ replace INTO `t1` (`pk`,col_bit) VALUES (99,1000); select pk, col_bit+0, vcol_bit+0 from t1; replace INTO `t1` (`pk`,col_bit) VALUES (99,10000); select pk, col_bit+0, vcol_bit+0 from t1; +--error ER_DATA_TOO_LONG REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99); drop table t1; @@ -468,6 +469,7 @@ CREATE TABLE t1 ( INSERT INTO t1 (pk,i) VALUES (1,1); TRUNCATE TABLE t1; INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); +--error ER_WARN_DATA_OUT_OF_RANGE REPLACE INTO t1 (pk,i) VALUES (1,2); DROP TABLE t1; SET @sql_mode=@old_sql_mode; diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 2e34cef5d19..75ff99b40a5 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -769,7 +769,8 @@ int _my_b_cache_read(IO_CACHE *info, uchar *Buffer, size_t Count) info->read_pos=info->buffer+Count; info->read_end=info->buffer+length; info->pos_in_file=pos_in_file; - memcpy(Buffer, info->buffer, Count); + if (Count) + memcpy(Buffer, info->buffer, Count); DBUG_RETURN(0); } @@ -1270,7 +1271,8 @@ static int _my_b_cache_read_r(IO_CACHE *cache, uchar *Buffer, size_t Count) DBUG_RETURN(1); } cnt= (len > Count) ? Count : len; - memcpy(Buffer, cache->read_pos, cnt); + if (cnt) + memcpy(Buffer, cache->read_pos, cnt); Count -= cnt; Buffer+= cnt; left_length+= cnt; diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index b4a63e93be3..d7e62726b22 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -465,7 +466,8 @@ char *strmake_root(MEM_ROOT *root, const char *str, size_t len) char *pos; if ((pos=alloc_root(root,len+1))) { - memcpy(pos,str,len); + if (len) + memcpy(pos,str,len); pos[len]=0; } return pos; diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 63ff5646535..15e5ebeacf0 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -1,6 +1,6 @@ #!/bin/bash -ue # Copyright (C) 2013 Percona Inc -# Copyright (C) 2017-2019 MariaDB +# Copyright (C) 2017-2020 MariaDB # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -359,7 +359,7 @@ read_cnf() iopts=$(parse_cnf sst inno-backup-opts "") iapts=$(parse_cnf sst inno-apply-opts "") impts=$(parse_cnf sst inno-move-opts "") - stimeout=$(parse_cnf sst sst-initial-timeout 100) + stimeout=$(parse_cnf sst sst-initial-timeout 300) ssyslog=$(parse_cnf sst sst-syslog 0) ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") ssystag+="-" @@ -620,7 +620,8 @@ recv_joiner() popd 1>/dev/null if [[ ${RC[0]} -eq 124 ]];then - wsrep_log_error "Possible timeout in receving first data from donor in gtid stage" + wsrep_log_error "Possible timeout in receiving first data from " + "donor in gtid stage: exit codes: ${RC[@]}" exit 32 fi diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index d2656f36967..dde3ce5a35b 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -348,7 +348,8 @@ static char *debug_sync_bmove_len(char *to, char *to_end, DBUG_ASSERT(to_end); DBUG_ASSERT(!length || from); set_if_smaller(length, (size_t) (to_end - to)); - memcpy(to, from, length); + if (length) + memcpy(to, from, length); return (to + length); } diff --git a/sql/log_event.h b/sql/log_event.h index 5e110dbd3fd..222e611ecae 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -896,6 +896,7 @@ typedef struct st_print_event_info */ IO_CACHE head_cache; IO_CACHE body_cache; + IO_CACHE tail_cache; #ifdef WHEN_FLASHBACK_REVIEW_READY /* Storing the SQL for reviewing */ IO_CACHE review_sql_cache; @@ -906,6 +907,7 @@ typedef struct st_print_event_info ~st_print_event_info() { close_cached_file(&head_cache); close_cached_file(&body_cache); + close_cached_file(&tail_cache); #ifdef WHEN_FLASHBACK_REVIEW_READY close_cached_file(&review_sql_cache); #endif diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index bdc42885312..4c26acd2cc1 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -1729,7 +1729,7 @@ bool Log_event::print_base64(IO_CACHE* file, ev->need_flashback_review= need_flashback_review; if (print_event_info->verbose) { - if (ev->print_verbose(file, print_event_info)) + if (ev->print_verbose(&print_event_info->tail_cache, print_event_info)) goto err; } else @@ -1753,22 +1753,9 @@ bool Log_event::print_base64(IO_CACHE* file, } #else if (print_event_info->verbose) - { - /* - Verbose event printout can't start before encoded data - got enquoted. This is done at this point though multi-row - statement remain vulnerable. - TODO: fix MDEV-10362 to remove this workaround. - */ - if (print_event_info->base64_output_mode != - BASE64_OUTPUT_DECODE_ROWS) - my_b_printf(file, "'%s\n", print_event_info->delimiter); - error= ev->print_verbose(file, print_event_info); - } + error= ev->print_verbose(&print_event_info->tail_cache, print_event_info); else - { ev->count_row_events(print_event_info); - } #endif delete ev; if (unlikely(error)) @@ -2763,7 +2750,7 @@ bool copy_cache_to_file_wrapped(IO_CACHE *body, FILE *file, bool do_wrap, const char *delimiter, - bool is_verbose) + bool is_verbose /*TODO: remove */) { const my_off_t cache_size= my_b_tell(body); @@ -2796,8 +2783,7 @@ bool copy_cache_to_file_wrapped(IO_CACHE *body, my_fprintf(file, fmt_frag, 1); if (my_b_copy_to_file(body, file, SIZE_T_MAX)) goto err; - if (!is_verbose) - my_fprintf(file, fmt_delim, delimiter); + my_fprintf(file, fmt_delim, delimiter); my_fprintf(file, fmt_binlog2, delimiter); } @@ -2806,8 +2792,7 @@ bool copy_cache_to_file_wrapped(IO_CACHE *body, my_fprintf(file, str_binlog); if (my_b_copy_to_file(body, file, SIZE_T_MAX)) goto err; - if (!is_verbose) - my_fprintf(file, fmt_delim, delimiter); + my_fprintf(file, fmt_delim, delimiter); } reinit_io_cache(body, WRITE_CACHE, 0, FALSE, TRUE); @@ -2893,7 +2878,6 @@ bool copy_cache_to_string_wrapped(IO_CACHE *cache, goto err; str += (add_to_len= uint32(cache->end_of_file - (cache_size/2 + 1))); to->length += add_to_len; - if (!is_verbose) { str += (add_to_len= sprintf(str , fmt_delim, delimiter)); to->length += add_to_len; @@ -2909,7 +2893,6 @@ bool copy_cache_to_string_wrapped(IO_CACHE *cache, goto err; str += cache->end_of_file; to->length += (size_t)cache->end_of_file; - if (!is_verbose) to->length += sprintf(str , fmt_delim, delimiter); } @@ -2957,6 +2940,7 @@ bool Rows_log_event::print_helper(FILE *file, { IO_CACHE *const head= &print_event_info->head_cache; IO_CACHE *const body= &print_event_info->body_cache; + IO_CACHE *const tail= &print_event_info->tail_cache; #ifdef WHEN_FLASHBACK_REVIEW_READY IO_CACHE *const sql= &print_event_info->review_sql_cache; #endif @@ -2987,7 +2971,8 @@ bool Rows_log_event::print_helper(FILE *file, if (copy_event_cache_to_file_and_reinit(head, file) || copy_cache_to_file_wrapped(body, file, do_print_encoded, print_event_info->delimiter, - print_event_info->verbose)) + print_event_info->verbose) || + copy_event_cache_to_file_and_reinit(tail, file)) goto err; } else @@ -3005,6 +2990,11 @@ bool Rows_log_event::print_helper(FILE *file, return 1; output_buf.append(tmp_str.str, tmp_str.length); my_free(tmp_str.str); + if (copy_event_cache_to_string_and_reinit(tail, &tmp_str)) + return 1; + output_buf.append(tmp_str.str, tmp_str.length); + my_free(tmp_str.str); + #ifdef WHEN_FLASHBACK_REVIEW_READY if (copy_event_cache_to_string_and_reinit(sql, &tmp_str)) return 1; @@ -3787,6 +3777,7 @@ st_print_event_info::st_print_event_info() base64_output_mode=BASE64_OUTPUT_UNSPEC; open_cached_file(&head_cache, NULL, NULL, 0, flags); open_cached_file(&body_cache, NULL, NULL, 0, flags); + open_cached_file(&tail_cache, NULL, NULL, 0, flags); #ifdef WHEN_FLASHBACK_REVIEW_READY open_cached_file(&review_sql_cache, NULL, NULL, 0, flags); #endif diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index f02f74ca093..10d1df4f3e7 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1850,6 +1850,7 @@ bool Old_rows_log_event::print_helper(FILE *file, { IO_CACHE *const head= &print_event_info->head_cache; IO_CACHE *const body= &print_event_info->body_cache; + IO_CACHE *const tail= &print_event_info->tail_cache; bool do_print_encoded= print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS && print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER && @@ -1869,8 +1870,9 @@ bool Old_rows_log_event::print_helper(FILE *file, { if (copy_event_cache_to_file_and_reinit(head, file) || copy_cache_to_file_wrapped(body, file, do_print_encoded, - print_event_info->delimiter, - print_event_info->verbose)) + print_event_info->delimiter, + print_event_info->verbose) || + copy_event_cache_to_file_and_reinit(tail, file)) goto err; } return 0; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c8fb9b45a2d..7e5f7934f75 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3566,7 +3566,8 @@ static const char *rpl_make_log_name(PSI_memory_key key, const char *opt, const char *def, const char *ext) { DBUG_ENTER("rpl_make_log_name"); - DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt, def, ext)); + DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt ? opt : "(null)", + def, ext)); char buff[FN_REFLEN]; const char *base= opt ? opt : def; unsigned int options= diff --git a/sql/net_serv.cc b/sql/net_serv.cc index ebd92a0e45a..a96c43a94fe 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -612,7 +612,8 @@ net_write_buff(NET *net, const uchar *packet, size_t len) return net_real_write(net, packet, len) ? 1 : 0; /* Send out rest of the blocks as full sized blocks */ } - memcpy((char*) net->write_pos,packet,len); + if (len) + memcpy((char*) net->write_pos,packet,len); net->write_pos+= len; return 0; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e1df56c6d79..4ad4c478937 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1851,15 +1851,13 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) } if (table->vfield) { - my_bool abort_on_warning= thd->abort_on_warning; /* We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ) in handler methods for the just read row in record[1]. */ table->move_fields(table->field, table->record[1], table->record[0]); - thd->abort_on_warning= 0; - table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); - thd->abort_on_warning= abort_on_warning; + if (table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE)) + goto err; table->move_fields(table->field, table->record[0], table->record[1]); } if (info->handle_duplicates == DUP_UPDATE) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 37def6df7ed..592b53ceecf 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -400,6 +400,9 @@ bool sp_create_assignment_lex(THD *thd, const char *pos) new_lex->sphead->m_tmp_query= pos; return thd->lex->sphead->reset_lex(thd, new_lex); } + else + if (thd->lex->main_select_push(false)) + return true; return false; } @@ -491,6 +494,8 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead, /* Copy option_type to outer lex in case it has changed. */ thd->lex->option_type= inner_option_type; } + else + lex->pop_select(); return false; } @@ -2960,6 +2965,7 @@ void st_select_lex::init_query() changed_elements= 0; first_natural_join_processing= 1; first_cond_optimization= 1; + is_service_select= 0; parsing_place= NO_MATTER; save_parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; @@ -8242,7 +8248,7 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name, return new (thd->mem_root) Item_func_sqlerrm(thd); } - if (!select_stack_head() && + if (fields_are_impossible() && (current_select->parsing_place != FOR_LOOP_BOUND || spcont->find_cursor(name, &unused_off, false) == NULL)) { @@ -9579,11 +9585,13 @@ void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit) } -bool LEX::main_select_push() +bool LEX::main_select_push(bool service) { DBUG_ENTER("LEX::main_select_push"); + DBUG_PRINT("info", ("service: %u", service)); current_select_number= 1; builtin_select.select_number= 1; + builtin_select.is_service_select= service; if (push_select(&builtin_select)) DBUG_RETURN(TRUE); DBUG_RETURN(FALSE); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f516219c01a..a07121b9a58 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1293,6 +1293,8 @@ public: bool no_wrap_view_item; /* exclude this select from check of unique_table() */ bool exclude_from_table_unique_test; + /* the select is "service-select" and can not have tables*/ + bool is_service_select; /* index in the select list of the expression currently being fixed */ int cur_pos_in_select_list; @@ -3701,8 +3703,9 @@ public: if (unlikely(!select_stack_top)) { current_select= &builtin_select; - DBUG_PRINT("info", ("Top Select is empty -> sel builtin: %p", - current_select)); + DBUG_PRINT("info", ("Top Select is empty -> sel builtin: %p service: %u", + current_select, builtin_select.is_service_select)); + builtin_select.is_service_select= false; } else current_select= select_stack[select_stack_top - 1]; @@ -4528,7 +4531,7 @@ public: wild= 0; exchange= 0; } - bool main_select_push(); + bool main_select_push(bool service= false); bool insert_select_hack(SELECT_LEX *sel); SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest); @@ -4678,6 +4681,14 @@ public: void mark_first_table_as_inserting(); + bool fields_are_impossible() + { + // no select or it is last select with no tables (service select) + return !select_stack_head() || + (select_stack_top == 1 && + select_stack[0]->is_service_select); + } + bool add_table_foreign_key(const LEX_CSTRING *name, const LEX_CSTRING *constraint_name, Table_ident *table_name, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c2b6fb02325..4ef2a4c5d46 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8147,6 +8147,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, (alias ? alias->str : table->table.str), table, this, select_number)); + DBUG_ASSERT(!is_service_select || (table_options & TL_OPTION_SEQUENCE)); if (unlikely(!table)) DBUG_RETURN(0); // End of memory diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ac0500f0e04..f0d42c32dd0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1137,6 +1137,8 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, proc_param= proc_param_init; tables_list= tables_init; select_lex= select_lex_arg; + DBUG_PRINT("info", ("select %p (%u) = JOIN %p", + select_lex, select_lex->select_number, this)); select_lex->join= this; join_list= &select_lex->top_join_list; union_part= unit_arg->is_unit_op(); @@ -4471,6 +4473,9 @@ int JOIN::destroy() { DBUG_ENTER("JOIN::destroy"); + + DBUG_PRINT("info", ("select %p (%u) <> JOIN %p", + select_lex, select_lex->select_number, this)); select_lex->join= 0; cond_equal= 0; @@ -23733,6 +23738,9 @@ check_reverse_order: else if (select && select->quick) select->quick->need_sorted_output(); + tab->read_record.unlock_row= (tab->type == JT_EQ_REF) ? + join_read_key_unlock_row : rr_unlock_row; + } // QEP has been modified /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8834c4d26e9..57045c251a7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -578,7 +578,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, /** - Create path to a temporary table mysql_tmpdir/#sql1234_12_1 + Create path to a temporary table mysql_tmpdir/#sql-temptable-1234-12-1 (i.e. to its .FRM file but without an extension). @param thd The thread handle. diff --git a/sql/sql_test.cc b/sql/sql_test.cc index f19d27df71f..cc3c9badefb 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -387,10 +387,10 @@ void print_sjm(SJ_MATERIALIZATION_INFO *sjm) /* Debugging help: force List<...>::elem function not be removed as unused. */ -Item* (List<Item>:: *dbug_list_item_elem_ptr)(uint)= &List<Item>::elem; -Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(uint)= +Item* (List<Item>::*dbug_list_item_elem_ptr)(uint)= &List<Item>::elem; +Item_equal* (List<Item_equal>::*dbug_list_item_equal_elem_ptr)(uint)= &List<Item_equal>::elem; -TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(uint) = +TABLE_LIST* (List<TABLE_LIST>::*dbug_list_table_list_elem_ptr)(uint) = &List<TABLE_LIST>::elem; #endif diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f1df76508d7..99a199886ce 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -2721,6 +2721,8 @@ bool st_select_lex::cleanup() bool error= FALSE; DBUG_ENTER("st_select_lex::cleanup()"); + DBUG_PRINT("info", ("select: %p (%u) JOIN %p", + this, select_number, join)); cleanup_order(order_list.first); cleanup_order(group_list.first); cleanup_ftfuncs(this); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3fa54a3bf54..e54b335e418 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2447,8 +2447,6 @@ create: Lex->create_info.default_table_charset= NULL; Lex->create_info.schema_comment= NULL; Lex->create_info.used_fields= 0; - if (Lex->main_select_push()) - MYSQL_YYABORT; } opt_create_database_options { @@ -2457,7 +2455,6 @@ create: $1 | $3))) MYSQL_YYABORT; lex->name= $4; - Lex->pop_select(); //main select } | create_or_replace definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident @@ -3174,10 +3171,13 @@ sp_cursor_stmt: { DBUG_ASSERT(thd->free_list == NULL); Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } select { DBUG_ASSERT(Lex == $1); + Lex->pop_select(); //main select if (unlikely($1->stmt_finalize(thd)) || unlikely($1->sphead->restore_lex(thd))) MYSQL_YYABORT; @@ -3623,6 +3623,11 @@ sp_proc_stmt_statement: Lex_input_stream *lip= YYLIP; lex->sphead->reset_lex(thd); + /* + We should not push main select here, it will be done or not + done by the statement, we just provide only a new LEX for the + statement here as if it is start of parsing a new statement. + */ lex->sphead->m_tmp_query= lip->get_tok_start(); } sp_statement @@ -3736,12 +3741,15 @@ expr_lex: sp_expr_lex(thd, thd->lex)))) MYSQL_YYABORT; Lex->sphead->reset_lex(thd, $<expr_lex>$); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } expr { $$= $<expr_lex>1; $$->sp_lex_in_use= true; $$->set_item($2); + Lex->pop_select(); //min select if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } @@ -3762,6 +3770,8 @@ assignment_source_expr: { DBUG_ASSERT(thd->free_list == NULL); Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } expr { @@ -3770,6 +3780,7 @@ assignment_source_expr: $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, thd->free_list); thd->free_list= NULL; + Lex->pop_select(); //min select if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } @@ -3779,6 +3790,8 @@ for_loop_bound_expr: assignment_source_lex { Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; Lex->current_select->parsing_place= FOR_LOOP_BOUND; } expr @@ -3787,6 +3800,7 @@ for_loop_bound_expr: $$= $1; $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, NULL); + Lex->pop_select(); //main select if (unlikely($$->sphead->restore_lex(thd))) MYSQL_YYABORT; Lex->current_select->parsing_place= NO_MATTER; @@ -7160,7 +7174,7 @@ alter: Lex->create_info.default_table_charset= NULL; Lex->create_info.schema_comment= NULL; Lex->create_info.used_fields= 0; - if (Lex->main_select_push()) + if (Lex->main_select_push(true)) MYSQL_YYABORT; } create_database_options @@ -12611,7 +12625,7 @@ do: { LEX *lex=Lex; lex->sql_command = SQLCOM_DO; - if (lex->main_select_push()) + if (lex->main_select_push(true)) MYSQL_YYABORT; mysql_init_select(lex); } @@ -16070,12 +16084,13 @@ set: SET { LEX *lex=Lex; - if (lex->main_select_push()) - MYSQL_YYABORT; lex->set_stmt_init(); } set_param - stmt_end {} + { + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; set_param: @@ -16178,24 +16193,44 @@ opt_var_ident_type: Let's put them to the main ones. */ set_stmt_option: - ident_cli equal set_expr_or_default + ident_cli equal + { + if (Lex->main_select_push(false)) + MYSQL_YYABORT; + } + set_expr_or_default { Lex_ident_sys tmp(thd, &$1); if (unlikely(!tmp.str) || - unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3))) + unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4))) MYSQL_YYABORT; + Lex->pop_select(); //min select } - | ident_cli '.' ident equal set_expr_or_default + | ident_cli '.' ident equal + { + if (Lex->main_select_push(false)) + MYSQL_YYABORT; + } + set_expr_or_default { Lex_ident_sys tmp(thd, &$1); if (unlikely(!tmp.str) || - unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5))) + unlikely(Lex->set_system_variable(thd, Lex->option_type, + &tmp, &$3, $6))) + MYSQL_YYABORT; + Lex->pop_select(); //min select + } + | DEFAULT '.' ident equal + { + if (Lex->main_select_push(false)) MYSQL_YYABORT; } - | DEFAULT '.' ident equal set_expr_or_default + set_expr_or_default { - if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $5))) + if (unlikely(Lex->set_default_system_variable(Lex->option_type, + &$3, $6))) MYSQL_YYABORT; + Lex->pop_select(); //min select } ; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index d0155f27d6d..ae664e951b5 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2867,7 +2867,14 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) definer_host.length= 0; } - stmt_query.append(STRING_WITH_LEN("CREATE ")); + const LEX_CSTRING command[2]= + {{ C_STRING_WITH_LEN("CREATE ") }, + { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; + + if (thd->lex->create_info.or_replace()) + stmt_query.append(command[1]); + else + stmt_query.append(command[0]); append_definer(thd, &stmt_query, &definer_user, &definer_host); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 9fdd5f6b457..6102b59198f 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1490,12 +1490,15 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, } } - if (it == end) - return NULL; + while (it != end) + { + space= &*it; + if (space->acquire()) + return space; + while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + } - space= &*it; - space->acquire(); - return space; + return NULL; } /** Return the next tablespace. @@ -1517,12 +1520,14 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck, space= UT_LIST_GET_FIRST(fil_system.space_list); /* We can trust that space is not NULL because at least the system tablespace is always present and loaded first. */ - space->acquire(); + if (!space->acquire()) + goto next; } else { /* Move on to the next fil_space_t */ space->release(); +next: space= UT_LIST_GET_NEXT(space_list, space); /* Skip abnormal tablespaces or those that are being created by @@ -1532,8 +1537,8 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck, space->is_stopping() || space->purpose != FIL_TYPE_TABLESPACE)) space= UT_LIST_GET_NEXT(space_list, space); - if (space) - space->acquire(); + if (space && !space->acquire()) + goto next; } mutex_exit(&fil_system.mutex); @@ -2246,31 +2251,27 @@ static void fil_crypt_rotation_list_fill() space = UT_LIST_GET_NEXT(space_list, space)) { if (space->purpose != FIL_TYPE_TABLESPACE || space->is_in_rotation_list - || space->is_stopping() - || UT_LIST_GET_LEN(space->chain) == 0) { + || UT_LIST_GET_LEN(space->chain) == 0 + || !space->acquire()) { continue; } /* Ensure that crypt_data has been initialized. */ if (!space->size) { - /* Protect the tablespace while we may - release fil_system.mutex. */ - ut_d(space->acquire()); ut_d(const fil_space_t* s=) fil_system.read_page0(space->id); ut_ad(!s || s == space); - ut_d(space->release()); if (!space->size) { /* Page 0 was not loaded. Skip this tablespace. */ - continue; + goto next; } } /* Skip ENCRYPTION!=DEFAULT tablespaces. */ if (space->crypt_data && !space->crypt_data->is_default_encryption()) { - continue; + goto next; } if (srv_encrypt_tables) { @@ -2278,19 +2279,21 @@ static void fil_crypt_rotation_list_fill() innodb_encrypt_tables!=OFF */ if (space->crypt_data && space->crypt_data->min_key_version) { - continue; + goto next; } } else { /* Skip unencrypted tablespaces if innodb_encrypt_tables=OFF */ if (!space->crypt_data || !space->crypt_data->min_key_version) { - continue; + goto next; } } fil_system.rotation_list.push_back(*space); space->is_in_rotation_list = true; +next: + space->release(); } } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 3874616e230..9b9d920c9d6 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -588,8 +588,7 @@ fil_try_to_close_file_in_LRU( static void fil_flush_low(fil_space_t* space, bool metadata = false) { ut_ad(mutex_own(&fil_system.mutex)); - ut_ad(space); - ut_ad(!space->stop_new_ops); + ut_ad(!space->is_stopping()); if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { /* No need to flush. User has explicitly disabled @@ -1724,10 +1723,8 @@ fil_space_t* fil_space_acquire_low(ulint id, bool silent) ib::warn() << "Trying to access missing" " tablespace " << id; } - } else if (space->is_stopping()) { + } else if (!space->acquire()) { space = NULL; - } else { - space->acquire(); } mutex_exit(&fil_system.mutex); @@ -1955,14 +1952,14 @@ static ulint fil_check_pending_ops(const fil_space_t* space, ulint count) { ut_ad(mutex_own(&fil_system.mutex)); - if (space == NULL) { + if (!space) { return 0; } - if (ulint n_pending_ops = space->n_pending_ops) { + if (auto n_pending_ops = space->referenced()) { - /* Give a warning every 10 second, starting after 1 second */ - if ((count % 500) == 50) { + /* Give a warning every 10 second, starting after 1 second */ + if ((count % 500) == 50) { ib::warn() << "Trying to delete" " tablespace '" << space->name << "' but there are " << n_pending_ops @@ -2033,14 +2030,13 @@ fil_check_pending_operations( fil_space_t* sp = fil_space_get_by_id(id); if (sp) { - sp->stop_new_ops = true; - if (sp->crypt_data) { - sp->acquire(); + if (sp->crypt_data && sp->acquire()) { mutex_exit(&fil_system.mutex); fil_space_crypt_close_tablespace(sp); mutex_enter(&fil_system.mutex); sp->release(); } + sp->set_stopping(true); } /* Check for pending operations. */ @@ -2521,7 +2517,7 @@ fil_rename_tablespace( multiple datafiles per tablespace. */ ut_a(UT_LIST_GET_LEN(space->chain) == 1); node = UT_LIST_GET_FIRST(space->chain); - space->n_pending_ops++; + ut_a(space->acquire()); mutex_exit(&fil_system.mutex); @@ -2543,8 +2539,7 @@ fil_rename_tablespace( /* log_sys.mutex is above fil_system.mutex in the latching order */ ut_ad(log_mutex_own()); mutex_enter(&fil_system.mutex); - ut_ad(space->n_pending_ops); - space->n_pending_ops--; + space->release(); ut_ad(space->name == old_space_name); ut_ad(node->name == old_file_name); bool success; @@ -3797,7 +3792,7 @@ fil_io( if (!space || (req_type.is_read() && !sync - && space->stop_new_ops + && space->is_stopping() && !space->is_being_truncated)) { mutex_exit(&fil_system.mutex); @@ -4223,7 +4218,7 @@ fil_space_validate_for_mtr_commit( mini-transaction, we should have !space->stop_new_ops. This is guaranteed by meta-data locks or transactional locks, or dict_sys.latch (X-lock in DROP, S-lock in purge). */ - ut_ad(!space->stop_new_ops + ut_ad(!space->is_stopping() || space->is_being_truncated /* fil_truncate_prepare() */ || space->referenced()); } @@ -4430,23 +4425,3 @@ fil_space_get_block_size(const fil_space_t* space, unsigned offset) return block_size; } - -/*******************************************************************//** -Returns the table space by a given id, NULL if not found. */ -fil_space_t* -fil_space_found_by_id( -/*==================*/ - ulint id) /*!< in: space id */ -{ - fil_space_t* space = NULL; - mutex_enter(&fil_system.mutex); - space = fil_space_get_by_id(id); - - /* Not found if space is being deleted */ - if (space && space->stop_new_ops) { - space = NULL; - } - - mutex_exit(&fil_system.mutex); - return space; -} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 22e77764f91..c891743991d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -106,6 +106,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include "fil0crypt.h" #include "srv0mon.h" #include "srv0start.h" +#include "rem0rec.h" #ifdef UNIV_DEBUG #include "trx0purge.h" #endif /* UNIV_DEBUG */ @@ -5255,14 +5256,13 @@ innobase_vcol_build_templ( mysql_row_templ_t* templ, ulint col_no) { - if (col->is_virtual()) { - templ->is_virtual = true; - templ->col_no = col_no; + templ->col_no = col_no; + templ->is_virtual = col->is_virtual(); + + if (templ->is_virtual) { templ->clust_rec_field_no = ULINT_UNDEFINED; templ->rec_field_no = col->ind; } else { - templ->is_virtual = false; - templ->col_no = col_no; templ->clust_rec_field_no = dict_col_get_clust_pos( col, clust_index); ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); @@ -6874,6 +6874,8 @@ build_template_field( templ = prebuilt->mysql_template + prebuilt->n_template++; MEM_UNDEFINED(templ, sizeof *templ); + templ->rec_field_is_prefix = FALSE; + templ->rec_prefix_field_no = ULINT_UNDEFINED; templ->is_virtual = !field->stored_in_db(); if (!templ->is_virtual) { @@ -6935,8 +6937,6 @@ build_template_field( << " query " << innobase_get_stmt_unsafe(current_thd, &size); } - templ->rec_field_is_prefix = FALSE; - templ->rec_prefix_field_no = ULINT_UNDEFINED; if (dict_index_is_clust(index)) { templ->rec_field_no = templ->clust_rec_field_no; @@ -6954,7 +6954,6 @@ build_template_field( DBUG_ASSERT(!ha_innobase::omits_virtual_cols(*table->s)); col = &dict_table_get_nth_v_col(index->table, v_no)->m_col; templ->clust_rec_field_no = v_no; - templ->rec_prefix_field_no = ULINT_UNDEFINED; if (dict_index_is_clust(index)) { templ->rec_field_no = templ->clust_rec_field_no; @@ -20508,64 +20507,53 @@ innobase_get_field_from_update_vector( Allocate a heap and record for calculating virtual fields Used mainly for virtual fields in indexes -@param[in] thd MariaDB THD -@param[in] index Index in use -@param[out] heap Heap that holds temporary row -@param[in,out] table MariaDB table -@param[out] record Pointer to allocated MariaDB record -@param[out] storage Internal storage for blobs etc +@param[in] thd MariaDB THD +@param[in] index Index in use +@param[out] heap Heap that holds temporary row +@param[in,out] table MariaDB table +@param[out] record Pointer to allocated MariaDB record +@param[out] storage Internal storage for blobs etc -@retval false on success -@retval true on malloc failure or failed to open the maria table +@retval true on success +@retval false on malloc failure or failed to open the maria table for purge thread. */ -bool innobase_allocate_row_for_vcol( - THD * thd, - dict_index_t* index, - mem_heap_t** heap, - TABLE** table, - byte** record, - VCOL_STORAGE** storage) -{ - TABLE *maria_table; - String *blob_value_storage; - if (!*table) - *table= innodb_find_table_for_vc(thd, index->table); - - /* For purge thread, there is a possiblity that table could have - dropped, corrupted or unaccessible. */ - if (!*table) - return true; - maria_table= *table; - if (!*heap && !(*heap= mem_heap_create(srv_page_size))) - { - *storage= 0; - return TRUE; - } - *record= static_cast<byte*>(mem_heap_alloc(*heap, - maria_table->s->reclength)); - *storage= static_cast<VCOL_STORAGE*> - (mem_heap_alloc(*heap, sizeof(**storage))); - blob_value_storage= static_cast<String*> - (mem_heap_alloc(*heap, - maria_table->s->virtual_not_stored_blob_fields * - sizeof(String))); - if (!*record || !*storage || !blob_value_storage) - { - *storage= 0; - return TRUE; - } - (*storage)->maria_table= maria_table; - (*storage)->innobase_record= *record; - (*storage)->maria_record= maria_table->field[0]->record_ptr(); - (*storage)->blob_value_storage= blob_value_storage; +bool innobase_allocate_row_for_vcol(THD *thd, dict_index_t *index, + mem_heap_t **heap, TABLE **table, + VCOL_STORAGE *storage) +{ + TABLE *maria_table; + String *blob_value_storage; + if (!*table) + *table = innodb_find_table_for_vc(thd, index->table); + + /* For purge thread, there is a possiblity that table could have + dropped, corrupted or unaccessible. */ + if (!*table) + return false; + maria_table = *table; + if (!*heap && !(*heap = mem_heap_create(srv_page_size))) + return false; + + uchar *record = static_cast<byte *>(mem_heap_alloc(*heap, + maria_table->s->reclength)); - maria_table->move_fields(maria_table->field, *record, - (*storage)->maria_record); - maria_table->remember_blob_values(blob_value_storage); + size_t len = maria_table->s->virtual_not_stored_blob_fields * sizeof(String); + blob_value_storage = static_cast<String *>(mem_heap_alloc(*heap, len)); - return FALSE; + if (!record || !blob_value_storage) + return false; + + storage->maria_table = maria_table; + storage->innobase_record = record; + storage->maria_record = maria_table->field[0]->record_ptr(); + storage->blob_value_storage = blob_value_storage; + + maria_table->move_fields(maria_table->field, record, storage->maria_record); + maria_table->remember_blob_values(blob_value_storage); + + return true; } @@ -20580,6 +20568,13 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage) } +void innobase_report_computed_value_failed(dtuple_t *row) +{ + ib::error() << "Compute virtual column values failed for " + << rec_printer(row).str(); +} + + /** Get the computed value by supplying the base column values. @param[in,out] row the data row @param[in] col virtual column @@ -20715,13 +20710,6 @@ innobase_get_computed_value( dbug_tmp_restore_column_map(mysql_table->write_set, old_write_set); if (ret != 0) { - // FIXME: Why this error message is macro-hidden? -#ifdef INNODB_VIRTUAL_DEBUG - ib::warn() << "Compute virtual column values failed "; - fputs("InnoDB: Cannot compute value for following record ", - stderr); - dtuple_print(stderr, row); -#endif /* INNODB_VIRTUAL_DEBUG */ DBUG_RETURN(NULL); } diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 125456c1ad4..4cff424179c 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -7048,8 +7048,7 @@ i_s_tablespaces_encryption_fill_table( for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); space; space = UT_LIST_GET_NEXT(space_list, space)) { if (space->purpose == FIL_TYPE_TABLESPACE - && !space->is_stopping()) { - space->acquire(); + && space->acquire()) { mutex_exit(&fil_system.mutex); if (int err = i_s_dict_fill_tablespaces_encryption( thd, space, tables->table)) { diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 3a2f78fa25f..6fe754759cd 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -330,14 +330,6 @@ struct fil_space_t Protected by log_sys.mutex. If and only if this is nonzero, the tablespace will be in named_spaces. */ - /** set when an .ibd file is about to be deleted, - or an undo tablespace is about to be truncated. - When this is set, the following new ops are not allowed: - * read IO request - * file flush - Note that we can still possibly have new write operations - because we don't check this flag when doing flush batches. */ - bool stop_new_ops; /** whether undo tablespace truncation is in progress */ bool is_being_truncated; fil_type_t purpose;/*!< purpose */ @@ -364,14 +356,22 @@ struct fil_space_t ulint n_pending_flushes; /*!< this is positive when flushing the tablespace to disk; dropping of the tablespace is forbidden if this is positive */ - /** Number of pending buffer pool operations accessing the tablespace - without holding a table lock or dict_sys.latch S-latch - that would prevent the table (and tablespace) from being - dropped. An example is fil_crypt_thread. - The tablespace cannot be dropped while this is nonzero, - or while fil_node_t::n_pending is nonzero. - Protected by fil_system.mutex and std::atomic. */ - std::atomic<ulint> n_pending_ops; +private: + /** Number of pending buffer pool operations accessing the + tablespace without holding a table lock or dict_operation_lock + S-latch that would prevent the table (and tablespace) from being + dropped. An example is encryption key rotation. + + The tablespace cannot be dropped while this is nonzero, or while + fil_node_t::n_pending is nonzero. + + The most significant bit contains the STOP_NEW_OPS flag. */ + Atomic_relaxed<size_t> n_pending_ops; + + /** Flag in n_pending_ops that indicates that the tablespace is being + deleted, and no further operations should be performed */ + static const size_t STOP_NEW_OPS= ~(~size_t(0) >> 1); +public: /** Number of pending block read or write operations (when a write is imminent or a read has recently completed). The tablespace object cannot be freed while this is nonzero, @@ -415,9 +415,6 @@ struct fil_space_t ulint magic_n;/*!< FIL_SPACE_MAGIC_N */ - /** @return whether the tablespace is about to be dropped */ - bool is_stopping() const { return stop_new_ops; } - /** Clamp a page number for batched I/O, such as read-ahead. @param offset page number limit @return offset clamped to the tablespace size */ @@ -502,20 +499,45 @@ struct fil_space_t /** Close each file. Only invoked on fil_system.temp_space. */ void close(); - /** Acquire a tablespace reference. */ - void acquire() { n_pending_ops++; } - /** Release a tablespace reference. - @return whether this was the last reference */ - bool release() { auto n= n_pending_ops--; ut_ad(n); return n == 1; } - /** @return whether references are being held */ - bool referenced() const { return n_pending_ops; } - - /** Acquire a tablespace reference for I/O. */ - void acquire_for_io() { n_pending_ios++; } - /** Release a tablespace reference for I/O. */ - void release_for_io() { ut_ad(pending_io()); n_pending_ios--; } - /** @return whether I/O is pending */ - bool pending_io() const { return n_pending_ios; } + /** @return whether the tablespace is about to be dropped */ + bool is_stopping() const { return n_pending_ops & STOP_NEW_OPS; } + + /** @return number of references being held */ + size_t referenced() const { return n_pending_ops & ~STOP_NEW_OPS; } + + /** Note that operations on the tablespace must stop or can resume */ + void set_stopping(bool stopping) + { + ut_d(auto n=) n_pending_ops.fetch_xor(STOP_NEW_OPS); + ut_ad(!(n & STOP_NEW_OPS) == stopping); + } + + MY_ATTRIBUTE((warn_unused_result)) + /** @return whether a tablespace reference was successfully acquired */ + bool acquire() + { + size_t n= 0; + while (!n_pending_ops.compare_exchange_strong(n, n + 1, + std::memory_order_acquire, + std::memory_order_relaxed)) + if (UNIV_UNLIKELY(n & STOP_NEW_OPS)) + return false; + return true; + } + /** Release a tablespace reference. + @return whether this was the last reference */ + bool release() + { + auto n= n_pending_ops.fetch_sub(1); + ut_ad(n & ~STOP_NEW_OPS); + return (n & ~STOP_NEW_OPS) == 1; + } + /** Acquire a tablespace reference for I/O. */ + void acquire_for_io() { n_pending_ios++; } + /** Release a tablespace reference for I/O. */ + void release_for_io() { ut_d(auto n=) n_pending_ios--; ut_ad(n); } + /** @return whether I/O is pending */ + bool pending_io() const { return n_pending_ios; } /** @return whether the tablespace file can be closed and reopened */ bool belongs_in_lru() const diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 0acff406326..82941b18a33 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -1186,16 +1186,17 @@ struct rec_offsets_print @param[in,out] o output stream @param[in] r record to display @return the output stream */ +ATTRIBUTE_COLD std::ostream& operator<<(std::ostream& o, const rec_offsets_print& r); -# ifndef DBUG_OFF /** Pretty-printer of records and tuples */ class rec_printer : public std::ostringstream { public: /** Construct a pretty-printed record. @param rec record with header @param offsets rec_get_offsets(rec, ...) */ + ATTRIBUTE_COLD rec_printer(const rec_t* rec, const rec_offs* offsets) : std::ostringstream () @@ -1209,6 +1210,7 @@ public: @param rec record, possibly lacking header @param info rec_get_info_bits(rec) @param offsets rec_get_offsets(rec, ...) */ + ATTRIBUTE_COLD rec_printer(const rec_t* rec, ulint info, const rec_offs* offsets) : std::ostringstream () @@ -1218,6 +1220,7 @@ public: /** Construct a pretty-printed tuple. @param tuple data tuple */ + ATTRIBUTE_COLD rec_printer(const dtuple_t* tuple) : std::ostringstream () @@ -1228,6 +1231,7 @@ public: /** Construct a pretty-printed tuple. @param field array of data tuple fields @param n number of fields */ + ATTRIBUTE_COLD rec_printer(const dfield_t* field, ulint n) : std::ostringstream () @@ -1244,7 +1248,7 @@ private: /** Assignment operator */ rec_printer& operator=(const rec_printer& other); }; -# endif /* !DBUG_OFF */ + # ifdef UNIV_DEBUG /** Read the DB_TRX_ID of a clustered index record. diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index c4163f8d2e0..fc454826c2b 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -848,6 +848,8 @@ struct VCOL_STORAGE byte *innobase_record; byte *maria_record; String *blob_value_storage; + VCOL_STORAGE(): maria_table(NULL), innobase_record(NULL), + maria_record(NULL), blob_value_storage(NULL) {} }; /** @@ -870,12 +872,48 @@ bool innobase_allocate_row_for_vcol( dict_index_t* index, mem_heap_t** heap, TABLE** table, - byte** record, - VCOL_STORAGE** storage); + VCOL_STORAGE* storage); /** Free memory allocated by innobase_allocate_row_for_vcol() */ void innobase_free_row_for_vcol(VCOL_STORAGE *storage); +class ib_vcol_row +{ + VCOL_STORAGE storage; +public: + mem_heap_t *heap; + + ib_vcol_row(mem_heap_t *heap) : heap(heap) {} + + byte *record(THD *thd, dict_index_t *index, TABLE **table) + { + if (!storage.innobase_record) + { + bool ok = innobase_allocate_row_for_vcol(thd, index, &heap, table, + &storage); + if (!ok) + return NULL; + } + return storage.innobase_record; + }; + + ~ib_vcol_row() + { + if (heap) + { + if (storage.innobase_record) + innobase_free_row_for_vcol(&storage); + mem_heap_free(heap); + } + } +}; + +/** Report virtual value computation failure in ib::error +@param[in] row the data row +*/ +ATTRIBUTE_COLD +void innobase_report_computed_value_failed(dtuple_t *row); + /** Get the computed value by supplying the base column values. @param[in,out] row the data row @param[in] col virtual column diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index cdd12a10cf7..b1589934014 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -877,16 +877,15 @@ row_ins_invalidate_query_cache( @param[in] index clustered index of child table @param[in] node parent update node @param[in] foreign foreign key information -@param[out] err error code. */ +@return error code. */ static -void +dberr_t row_ins_foreign_fill_virtual( upd_node_t* cascade, const rec_t* rec, dict_index_t* index, upd_node_t* node, - dict_foreign_t* foreign, - dberr_t* err) + dict_foreign_t* foreign) { THD* thd = current_thd; row_ext_t* ext; @@ -895,10 +894,7 @@ row_ins_foreign_fill_virtual( const rec_offs* offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &cascade->heap); - mem_heap_t* v_heap = NULL; TABLE* mysql_table= NULL; - VCOL_STORAGE* vcol_storage= NULL; - byte* record; upd_t* update = cascade->update; ulint n_v_fld = index->table->n_v_def; ulint n_diff; @@ -918,12 +914,10 @@ row_ins_foreign_fill_virtual( innobase_init_vc_templ(index->table); } - if (innobase_allocate_row_for_vcol(thd, index, &v_heap, - &mysql_table, - &record, &vcol_storage)) { - if (v_heap) mem_heap_free(v_heap); - *err = DB_OUT_OF_MEMORY; - goto func_exit; + ib_vcol_row vc(NULL); + uchar *record = vc.record(thd, index, &mysql_table); + if (!record) { + return DB_OUT_OF_MEMORY; } for (uint16_t i = 0; i < n_v_fld; i++) { @@ -939,12 +933,11 @@ row_ins_foreign_fill_virtual( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, - &v_heap, update->heap, NULL, thd, mysql_table, + &vc.heap, update->heap, NULL, thd, mysql_table, record, NULL, NULL, NULL); if (vfield == NULL) { - *err = DB_COMPUTE_VALUE_FAILED; - goto func_exit; + return DB_COMPUTE_VALUE_FAILED; } upd_field = upd_get_nth_field(update, n_diff); @@ -969,13 +962,12 @@ row_ins_foreign_fill_virtual( dfield_t* new_vfield = innobase_get_computed_value( update->old_vrow, col, index, - &v_heap, update->heap, NULL, thd, + &vc.heap, update->heap, NULL, thd, mysql_table, record, NULL, node->update, foreign); if (new_vfield == NULL) { - *err = DB_COMPUTE_VALUE_FAILED; - goto func_exit; + return DB_COMPUTE_VALUE_FAILED; } dfield_copy(&(upd_field->new_val), new_vfield); @@ -985,14 +977,7 @@ row_ins_foreign_fill_virtual( } update->n_fields = n_diff; - *err = DB_SUCCESS; - -func_exit: - if (v_heap) { - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); - mem_heap_free(v_heap); - } + return DB_SUCCESS; } #ifdef WITH_WSREP @@ -1279,9 +1264,9 @@ row_ins_foreign_check_on_constraint( if (foreign->v_cols != NULL && foreign->v_cols->size() > 0) { - row_ins_foreign_fill_virtual( + err = row_ins_foreign_fill_virtual( cascade, clust_rec, clust_index, - node, foreign, &err); + node, foreign); if (err != DB_SUCCESS) { goto nonstandard_exit_func; @@ -1317,9 +1302,9 @@ row_ins_foreign_check_on_constraint( node, foreign, tmp_heap, trx); if (foreign->v_cols && !foreign->v_cols->empty()) { - row_ins_foreign_fill_virtual( + err = row_ins_foreign_fill_virtual( cascade, clust_rec, clust_index, - node, foreign, &err); + node, foreign); if (err != DB_SUCCESS) { goto nonstandard_exit_func; @@ -1377,21 +1362,20 @@ row_ins_foreign_check_on_constraint( btr_pcur_store_position(cascade->pcur, mtr); } +#ifdef WITH_WSREP + err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, + FALSE, WSREP_SERVICE_KEY_EXCLUSIVE); + if (err != DB_SUCCESS) { + ib::info() << "WSREP: foreign key append failed: " << err; + goto nonstandard_exit_func; + } +#endif /* WITH_WSREP */ mtr_commit(mtr); ut_a(cascade->pcur->rel_pos == BTR_PCUR_ON); cascade->state = UPD_NODE_UPDATE_CLUSTERED; -#ifdef WITH_WSREP - err = wsrep_append_foreign_key(trx, foreign, cascade->pcur->old_rec, - clust_index, - FALSE, WSREP_SERVICE_KEY_EXCLUSIVE); - if (err != DB_SUCCESS) { - fprintf(stderr, - "WSREP: foreign key append failed: %d\n", err); - } else -#endif /* WITH_WSREP */ err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); @@ -1911,6 +1895,39 @@ exit_func: DBUG_RETURN(err); } +/** Sets the values of the dtuple fields in ref_entry from the values of +foreign columns in entry. +@param[in] foreign foreign key constraint +@param[in] index clustered index +@param[in] entry tuple of clustered index +@param[in] ref_entry tuple of foreign columns +@return true if all foreign key fields present in clustered index */ +static +bool row_ins_foreign_index_entry(dict_foreign_t *foreign, + const dict_index_t *index, + const dtuple_t *entry, + dtuple_t *ref_entry) +{ + for (ulint i= 0; i < foreign->n_fields; i++) + { + for (ulint j= 0; j < index->n_fields; j++) + { + const char *col_name= dict_table_get_col_name( + index->table, dict_index_get_nth_col_no(index, j)); + if (0 == innobase_strcasecmp(col_name, foreign->foreign_col_names[i])) + { + dfield_copy(&ref_entry->fields[i], &entry->fields[j]); + goto got_match; + } + } + return false; +got_match: + continue; + } + + return true; +} + /***************************************************************//** Checks if foreign key constraints fail for an index entry. If index is not mentioned in any constraint, this function does nothing, @@ -1929,9 +1946,10 @@ row_ins_check_foreign_constraints( que_thr_t* thr) /*!< in: query thread */ { dict_foreign_t* foreign; - dberr_t err; + dberr_t err = DB_SUCCESS; trx_t* trx; ibool got_s_lock = FALSE; + mem_heap_t* heap = NULL; DBUG_ASSERT(index->is_primary() == pk); @@ -1941,13 +1959,36 @@ row_ins_check_foreign_constraints( "foreign_constraint_check_for_ins"); for (dict_foreign_set::iterator it = table->foreign_set.begin(); - it != table->foreign_set.end(); + err == DB_SUCCESS && it != table->foreign_set.end(); ++it) { foreign = *it; if (foreign->foreign_index == index || (pk && !foreign->foreign_index)) { + + dtuple_t* ref_tuple = entry; + if (UNIV_UNLIKELY(!foreign->foreign_index)) { + /* Change primary key entry to + foreign key index entry */ + if (!heap) { + heap = mem_heap_create(1000); + } else { + mem_heap_empty(heap); + } + + ref_tuple = dtuple_create( + heap, foreign->n_fields); + dtuple_set_n_fields_cmp( + ref_tuple, foreign->n_fields); + if (!row_ins_foreign_index_entry( + foreign, index, entry, ref_tuple)) { + err = DB_NO_REFERENCED_ROW; + break; + } + + } + dict_table_t* ref_table = NULL; dict_table_t* referenced_table = foreign->referenced_table; @@ -1975,7 +2016,7 @@ row_ins_check_foreign_constraints( table from being dropped while the check is running. */ err = row_ins_check_foreign_constraint( - TRUE, foreign, table, entry, thr); + TRUE, foreign, table, ref_tuple, thr); if (referenced_table) { foreign->foreign_table->dec_fk_checks(); @@ -1988,15 +2029,14 @@ row_ins_check_foreign_constraints( if (ref_table != NULL) { dict_table_close(ref_table, FALSE, FALSE); } - - if (err != DB_SUCCESS) { - - return(err); - } } } - return(DB_SUCCESS); + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + return err; } /***************************************************************//** diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 4f4329082fe..37814b70188 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -513,8 +513,7 @@ row_merge_buf_add( ulint bucket = 0; doc_id_t write_doc_id; ulint n_row_added = 0; - VCOL_STORAGE* vcol_storage= 0; - byte* record; + VCOL_STORAGE vcol_storage; DBUG_ENTER("row_merge_buf_add"); if (buf->n_tuples >= buf->max_tuples) { @@ -548,23 +547,16 @@ row_merge_buf_add( for (i = 0; i < n_fields; i++, field++, ifield++) { ulint len; - const dict_col_t* col; - ulint col_no; ulint fixed_len; const dfield_t* row_field; - - col = ifield->col; - const dict_v_col_t* v_col = NULL; - if (col->is_virtual()) { - v_col = reinterpret_cast<const dict_v_col_t*>(col); - } - - col_no = dict_col_get_no(col); + const dict_col_t* const col = ifield->col; + const dict_v_col_t* const v_col = col->is_virtual() + ? reinterpret_cast<const dict_v_col_t*>(col) + : NULL; /* Process the Doc ID column */ - if (*doc_id > 0 - && col_no == index->table->fts->doc_col - && !col->is_virtual()) { + if (!v_col && *doc_id + && col->ind == index->table->fts->doc_col) { fts_write_doc_id((byte*) &write_doc_id, *doc_id); /* Note: field->data now points to a value on the @@ -583,12 +575,15 @@ row_merge_buf_add( field->type.len = ifield->col->len; } else { /* Use callback to get the virtual column value */ - if (col->is_virtual()) { + if (v_col) { dict_index_t* clust_index = dict_table_get_first_index(new_table); - if (!vcol_storage && - innobase_allocate_row_for_vcol(trx->mysql_thd, clust_index, v_heap, &my_table, &record, &vcol_storage)) { + if (!vcol_storage.innobase_record && + !innobase_allocate_row_for_vcol( + trx->mysql_thd, clust_index, + v_heap, &my_table, + &vcol_storage)) { *err = DB_OUT_OF_MEMORY; goto error; } @@ -596,8 +591,8 @@ row_merge_buf_add( row_field = innobase_get_computed_value( row, v_col, clust_index, v_heap, NULL, ifield, trx->mysql_thd, - my_table, record, old_table, NULL, - NULL); + my_table, vcol_storage.innobase_record, + old_table, NULL, NULL); if (row_field == NULL) { *err = DB_COMPUTE_VALUE_FAILED; @@ -605,7 +600,8 @@ row_merge_buf_add( } dfield_copy(field, row_field); } else { - row_field = dtuple_get_nth_field(row, col_no); + row_field = dtuple_get_nth_field(row, + col->ind); dfield_copy(field, row_field); } @@ -712,7 +708,7 @@ row_merge_buf_add( } else if (!ext) { } else if (dict_index_is_clust(index)) { /* Flag externally stored fields. */ - const byte* buf = row_ext_lookup(ext, col_no, + const byte* buf = row_ext_lookup(ext, col->ind, &len); if (UNIV_LIKELY_NULL(buf)) { ut_a(buf != field_ref_zero); @@ -723,9 +719,9 @@ row_merge_buf_add( len = dfield_get_len(field); } } - } else if (!col->is_virtual()) { + } else if (!v_col) { /* Only non-virtual column are stored externally */ - const byte* buf = row_ext_lookup(ext, col_no, + const byte* buf = row_ext_lookup(ext, col->ind, &len); if (UNIV_LIKELY_NULL(buf)) { ut_a(buf != field_ref_zero); @@ -840,13 +836,13 @@ row_merge_buf_add( } end: - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); + if (vcol_storage.innobase_record) + innobase_free_row_for_vcol(&vcol_storage); DBUG_RETURN(n_row_added); error: - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); + if (vcol_storage.innobase_record) + innobase_free_row_for_vcol(&vcol_storage); DBUG_RETURN(0); } diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 595a72eb415..8e171f9bf20 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -156,11 +156,15 @@ fields are compared with collation! must be protected by a page s-latch @param[in] clust_index clustered index @param[in] thr query thread -@return TRUE if the secondary record is equal to the corresponding -fields in the clustered record, when compared with collation; -FALSE if not equal or if the clustered record has been marked for deletion */ +@retval DB_COMPUTE_VALUE_FAILED in case of virtual column value computation + failure. +@retval DB_SUCCESS_LOCKED_REC if the secondary record is equal to the + corresponding fields in the clustered record, when compared with + collation; +@retval DB_SUCCESS if not equal or if the clustered record has been marked + for deletion */ static -ibool +dberr_t row_sel_sec_rec_is_for_clust_rec( const rec_t* sec_rec, dict_index_t* sec_index, @@ -178,9 +182,6 @@ row_sel_sec_rec_is_for_clust_rec( rec_offs sec_offsets_[REC_OFFS_SMALL_SIZE]; rec_offs* clust_offs = clust_offsets_; rec_offs* sec_offs = sec_offsets_; - ibool is_equal = TRUE; - VCOL_STORAGE* vcol_storage= 0; - byte* record; rec_offs_init(clust_offsets_); rec_offs_init(sec_offsets_); @@ -195,10 +196,11 @@ row_sel_sec_rec_is_for_clust_rec( it is not visible in the read view. Besides, if there are any externally stored columns, some of them may have already been purged. */ - return(FALSE); + return DB_SUCCESS; } heap = mem_heap_create(256); + ib_vcol_row vc(heap); clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs, true, ULINT_UNDEFINED, &heap); @@ -227,16 +229,9 @@ row_sel_sec_rec_is_for_clust_rec( dfield_t* vfield; row_ext_t* ext; - if (!vcol_storage) - { - TABLE *mysql_table= thr->prebuilt->m_mysql_table; - innobase_allocate_row_for_vcol(thr_get_trx(thr)->mysql_thd, - clust_index, - &heap, - &mysql_table, - &record, - &vcol_storage); - } + byte *record = vc.record(thr_get_trx(thr)->mysql_thd, + clust_index, + &thr->prebuilt->m_mysql_table); v_col = reinterpret_cast<const dict_v_col_t*>(col); @@ -253,6 +248,10 @@ row_sel_sec_rec_is_for_clust_rec( thr->prebuilt->m_mysql_table, record, NULL, NULL, NULL); + if (vfield == NULL) { + innobase_report_computed_value_failed(row); + return DB_COMPUTE_VALUE_FAILED; + } clust_len = vfield->len; clust_field = static_cast<byte*>(vfield->data); } else { @@ -286,7 +285,7 @@ row_sel_sec_rec_is_for_clust_rec( sec_field, sec_len, ifield->prefix_len, clust_index->table)) { - goto inequal; + return DB_SUCCESS; } continue; @@ -321,28 +320,19 @@ row_sel_sec_rec_is_for_clust_rec( rtr_read_mbr(sec_field, &sec_mbr); if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) { - is_equal = FALSE; - goto func_exit; + return DB_SUCCESS; } } else { if (0 != cmp_data_data(col->mtype, col->prtype, clust_field, len, sec_field, sec_len)) { -inequal: - is_equal = FALSE; - goto func_exit; + return DB_SUCCESS; } } } -func_exit: - if (UNIV_LIKELY_NULL(heap)) { - if (UNIV_LIKELY_NULL(vcol_storage)) - innobase_free_row_for_vcol(vcol_storage); - mem_heap_free(heap); - } - return(is_equal); + return DB_SUCCESS_LOCKED_REC; } /*********************************************************************//** @@ -908,7 +898,7 @@ row_sel_get_clust_rec( dict_index_t* index; rec_t* clust_rec; rec_t* old_vers; - dberr_t err; + dberr_t err = DB_SUCCESS; mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; @@ -950,7 +940,7 @@ row_sel_get_clust_rec( clustered index record did not exist in the read view of trx. */ - goto func_exit; + goto err_exit; } offsets = rec_get_offsets(clust_rec, index, offsets, true, @@ -1003,7 +993,7 @@ row_sel_get_clust_rec( clust_rec = old_vers; if (clust_rec == NULL) { - goto func_exit; + goto err_exit; } } @@ -1020,13 +1010,14 @@ row_sel_get_clust_rec( visit through secondary index records that would not really exist in our snapshot. */ - if ((old_vers - || rec_get_deleted_flag(rec, dict_table_is_comp( - plan->table))) - && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, - clust_rec, index, - thr)) { - goto func_exit; + if (old_vers || rec_get_deleted_flag(rec, dict_table_is_comp( + plan->table))) { + err = row_sel_sec_rec_is_for_clust_rec(rec, + plan->index, clust_rec, + index, thr); + if (err != DB_SUCCESS_LOCKED_REC) { + goto err_exit; + } } } @@ -1039,7 +1030,6 @@ row_sel_get_clust_rec( row_sel_fetch_columns(index, clust_rec, offsets, UT_LIST_GET_FIRST(plan->columns)); *out_rec = clust_rec; -func_exit: err = DB_SUCCESS; err_exit: if (UNIV_LIKELY_NULL(heap)) { @@ -3458,10 +3448,18 @@ Row_sel_get_clust_rec_for_mysql::operator()( || trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED || dict_index_is_spatial(sec_index) || rec_get_deleted_flag(rec, dict_table_is_comp( - sec_index->table))) - && !row_sel_sec_rec_is_for_clust_rec( - rec, sec_index, clust_rec, clust_index, thr)) { - clust_rec = NULL; + sec_index->table)))) { + err = row_sel_sec_rec_is_for_clust_rec(rec, sec_index, + clust_rec, clust_index, thr); + switch (err) { + case DB_SUCCESS: + clust_rec = NULL; + break; + case DB_SUCCESS_LOCKED_REC: + break; + default: + goto err_exit; + } } err = DB_SUCCESS; @@ -4091,6 +4089,10 @@ bool row_search_with_covering_prefix( const dict_index_t* index = prebuilt->index; ut_ad(!dict_index_is_clust(index)); + if (dict_index_is_spatial(index)) { + return false; + } + if (!srv_prefix_index_cluster_optimization) { return false; } @@ -4101,9 +4103,16 @@ bool row_search_with_covering_prefix( return false; } + /* We can avoid a clustered index lookup if + all of the following hold: + (1) all columns are in the secondary index + (2) all values for columns that are prefix-only + indexes are shorter than the prefix size + This optimization can avoid many IOs for certain schemas. */ for (ulint i = 0; i < prebuilt->n_template; i++) { mysql_row_templ_t* templ = prebuilt->mysql_template + i; ulint j = templ->rec_prefix_field_no; + ut_ad(!templ->mbminlen == !templ->mbmaxlen); /** Condition (1) : is the field in the index. */ if (j == ULINT_UNDEFINED) { @@ -4113,33 +4122,29 @@ bool row_search_with_covering_prefix( /** Condition (2): If this is a prefix index then row's value size shorter than prefix length. */ - if (!templ->rec_field_is_prefix) { + if (!templ->rec_field_is_prefix + || rec_offs_nth_sql_null(offsets, j)) { continue; } - ulint rec_size = rec_offs_nth_size(offsets, j); const dict_field_t* field = dict_index_get_nth_field(index, j); - ulint max_chars = field->prefix_len / templ->mbmaxlen; - - ut_a(field->prefix_len > 0); - if (rec_size < max_chars) { - /* Record in bytes shorter than the index - prefix length in char. */ + if (!field->prefix_len) { continue; } - if (rec_size * templ->mbminlen >= field->prefix_len) { + const ulint rec_size = rec_offs_nth_size(offsets, j); + + if (rec_size >= field->prefix_len) { /* Shortest representation string by the byte length of the record is longer than the maximum possible index prefix. */ return false; } - size_t num_chars = rec_field_len_in_chars( - field->col, j, rec, offsets); - - if (num_chars >= max_chars) { + if (templ->mbminlen != templ->mbmaxlen + && rec_field_len_in_chars(field->col, j, rec, offsets) + >= field->prefix_len / templ->mbmaxlen) { /* No of chars to store the record exceeds the index prefix character length. */ return false; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 7c8d5601352..fa3fad5fe26 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -739,10 +739,6 @@ row_upd_build_difference_binary( for purge/mvcc purpose) */ if (n_v_fld > 0) { row_ext_t* ext; - mem_heap_t* v_heap = NULL; - byte* record; - VCOL_STORAGE* vcol_storage; - THD* thd; if (trx == NULL) { @@ -753,9 +749,8 @@ row_upd_build_difference_binary( ut_ad(!update->old_vrow); - innobase_allocate_row_for_vcol(thd, index, &v_heap, - &mysql_table, - &record, &vcol_storage); + ib_vcol_row vc(NULL); + uchar *record = vc.record(thd, index, &mysql_table); for (uint16_t i = 0; i < n_v_fld; i++) { const dict_v_col_t* col @@ -773,10 +768,9 @@ row_upd_build_difference_binary( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, - &v_heap, heap, NULL, thd, mysql_table, record, + &vc.heap, heap, NULL, thd, mysql_table, record, NULL, NULL, NULL); if (vfield == NULL) { - if (v_heap) mem_heap_free(v_heap); *error = DB_COMPUTE_VALUE_FAILED; return(NULL); } @@ -797,12 +791,6 @@ row_upd_build_difference_binary( upd_field_set_v_field_no(uf, i, index); } } - - if (v_heap) { - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); - mem_heap_free(v_heap); - } } update->n_fields = n_diff; @@ -1792,23 +1780,19 @@ row_upd_eval_new_vals( @param[in,out] node row update node @param[in] update an update vector if it is update @param[in] thd mysql thread handle -@param[in,out] mysql_table mysql table object */ +@param[in,out] mysql_table mysql table object +@return true if success + false if virtual column value computation fails. */ static -void +bool row_upd_store_v_row( upd_node_t* node, const upd_t* update, THD* thd, TABLE* mysql_table) { - mem_heap_t* heap = NULL; dict_index_t* index = dict_table_get_first_index(node->table); - byte* record= 0; - VCOL_STORAGE *vcol_storage= 0; - - if (!update) - innobase_allocate_row_for_vcol(thd, index, &heap, &mysql_table, - &record, &vcol_storage); + ib_vcol_row vc(NULL); for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(node->table); col_no++) { @@ -1858,33 +1842,37 @@ row_upd_store_v_row( dfield_dup(dfield, node->heap); } } else { + uchar *record = vc.record(thd, index, + &mysql_table); /* Need to compute, this happens when deleting row */ - innobase_get_computed_value( - node->row, col, index, - &heap, node->heap, NULL, - thd, mysql_table, record, NULL, - NULL, NULL); + dfield_t* vfield = + innobase_get_computed_value( + node->row, col, index, + &vc.heap, node->heap, + NULL, thd, mysql_table, + record, NULL, NULL, + NULL); + if (vfield == NULL) { + return false; + } } } } } - if (heap) { - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); - mem_heap_free(heap); - } - + return true; } /** Stores to the heap the row on which the node->pcur is positioned. @param[in] node row update node @param[in] thd mysql thread handle @param[in,out] mysql_table NULL, or mysql table object when - user thread invokes dml */ + user thread invokes dml +@return false if virtual column value computation fails + true otherwise. */ static -void +bool row_upd_store_row( upd_node_t* node, THD* thd, @@ -1928,8 +1916,12 @@ row_upd_store_row( NULL, NULL, NULL, ext, node->heap); if (node->table->n_v_cols) { - row_upd_store_v_row(node, node->is_delete ? NULL : node->update, + bool ok = row_upd_store_v_row(node, + node->is_delete ? NULL : node->update, thd, mysql_table); + if (!ok) { + return false; + } } if (node->is_delete == PLAIN_DELETE) { @@ -1944,6 +1936,7 @@ row_upd_store_row( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } + return true; } /***********************************************************//** @@ -2675,9 +2668,12 @@ row_upd_del_mark_clust_rec( /* Store row because we have to build also the secondary index entries */ - row_upd_store_row(node, trx->mysql_thd, + if (!row_upd_store_row(node, trx->mysql_thd, thr->prebuilt && thr->prebuilt->table == node->table - ? thr->prebuilt->m_mysql_table : NULL); + ? thr->prebuilt->m_mysql_table : NULL)) { + err = DB_COMPUTE_VALUE_FAILED; + return err; + } /* Mark the clustered index record deleted; we do not have to check locks, because we assume that we have an x-lock on the record */ @@ -2894,8 +2890,11 @@ row_upd_clust_step( goto exit_func; } - row_upd_store_row(node, trx->mysql_thd, - thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL); + if(!row_upd_store_row(node, trx->mysql_thd, + thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL)) { + err = DB_COMPUTE_VALUE_FAILED; + goto exit_func; + } if (row_upd_changes_ord_field_binary(index, node->update, thr, node->row, node->ext)) { diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index eb948855032..7f410487b9a 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -442,52 +442,44 @@ row_vers_impl_x_locked( @param[in] index the secondary index @param[in] heap heap used to build virtual dtuple. */ static -void +bool row_vers_build_clust_v_col( dtuple_t* row, dict_index_t* clust_index, dict_index_t* index, mem_heap_t* heap) { - mem_heap_t* local_heap = NULL; - VCOL_STORAGE *vcol_storage= NULL; THD* thd= current_thd; TABLE* maria_table= 0; - byte* record= 0; ut_ad(dict_index_has_virtual(index)); ut_ad(index->table == clust_index->table); - innobase_allocate_row_for_vcol(thd, index, - &local_heap, - &maria_table, - &record, - &vcol_storage); + ib_vcol_row vc(nullptr); + byte *record = vc.record(thd, index, &maria_table); ut_ad(maria_table); for (ulint i = 0; i < dict_index_get_n_fields(index); i++) { - const dict_field_t* ind_field = dict_index_get_nth_field( - index, i); - - if (ind_field->col->is_virtual()) { - const dict_v_col_t* col; + const dict_col_t* c = dict_index_get_nth_col(index, i); - col = reinterpret_cast<const dict_v_col_t*>( - ind_field->col); + if (c->is_virtual()) { + const dict_v_col_t* col + = reinterpret_cast<const dict_v_col_t*>(c); - innobase_get_computed_value( - row, col, clust_index, &local_heap, + dfield_t *vfield = innobase_get_computed_value( + row, col, clust_index, &vc.heap, heap, NULL, thd, maria_table, record, NULL, NULL, NULL); + if (!vfield) { + innobase_report_computed_value_failed(row); + ut_ad(0); + return false; + } } } - if (local_heap) { - if (vcol_storage) - innobase_free_row_for_vcol(vcol_storage); - mem_heap_free(local_heap); - } + return true; } /** Build latest virtual column data from undo log @@ -568,9 +560,8 @@ row_vers_build_cur_vrow_low( all_filled = true; for (i = 0; i < entry_len; i++) { - const dict_field_t* ind_field - = dict_index_get_nth_field(index, i); - const dict_col_t* col = ind_field->col; + const dict_col_t* col + = dict_index_get_nth_col(index, i); if (!col->is_virtual()) { continue; @@ -816,8 +807,10 @@ row_vers_build_cur_vrow( rec, *clust_offsets, NULL, NULL, NULL, NULL, heap); - row_vers_build_clust_v_col( - row, clust_index, index, heap); + if (!row_vers_build_clust_v_col(row, clust_index, index, + heap)) { + return nullptr; + } cur_vrow = dtuple_copy(row, v_heap); dtuple_dup_v_fld(cur_vrow, v_heap); @@ -925,8 +918,10 @@ row_vers_old_has_index_entry( if (trx_undo_roll_ptr_is_insert(t_roll_ptr) || dbug_v_purge) { - row_vers_build_clust_v_col( - row, clust_index, index, heap); + if (!row_vers_build_clust_v_col( + row, clust_index, index, heap)) { + goto unsafe_to_purge; + } entry = row_build_index_entry( row, ext, index, heap); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 3f1d4258484..393f044d23a 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -778,12 +778,12 @@ not_free: /* This is only executed by srv_purge_coordinator_thread. */ export_vars.innodb_undo_truncations++; - /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */ + /* In MDEV-8319 (10.5) we will PUNCH_HOLE the garbage + (with write-ahead logging). */ mutex_enter(&fil_system.mutex); ut_ad(&space == purge_sys.truncate.current); - ut_ad(space.stop_new_ops); ut_ad(space.is_being_truncated); - purge_sys.truncate.current->stop_new_ops = false; + purge_sys.truncate.current->set_stopping(false); purge_sys.truncate.current->is_being_truncated = false; mutex_exit(&fil_system.mutex); diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 25c44f7c90e..d64dc8308c5 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -319,7 +319,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, { options|= HA_OPTION_TMP_TABLE; tmp_table= TRUE; - create_mode|= O_NOFOLLOW; + create_mode|= O_NOFOLLOW | (internal_table ? 0 : O_EXCL); /* "CREATE TEMPORARY" tables are not crash-safe (dropped at restart) */ ci->transactional= FALSE; flags&= ~HA_CREATE_PAGE_CHECKSUM; @@ -894,9 +894,10 @@ int maria_create(const char *name, enum data_file_type datafile_type, { char *iext= strrchr(name, '.'); int have_iext= iext && !strcmp(iext, MARIA_NAME_IEXT); - fn_format(kfilename, name, "", MARIA_NAME_IEXT, - MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | + fn_format(kfilename, name, "", MARIA_NAME_IEXT, MY_UNPACK_FILENAME | + (internal_table ? 0 : MY_RETURN_REAL_PATH) | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); + klinkname_ptr= NullS; /* Replace the current file. Don't sync dir now if the data file has the same path. @@ -1173,14 +1174,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, FALSE, TRUE)) goto err; my_free(log_data); - - /* - We don't need to sync directory as we can use the log to recreate - the index and data files if needed. - */ - sync_dir= 0; } - DBUG_ASSERT(!internal_table || sync_dir == 0); if (!(flags & HA_DONT_TOUCH_DATA)) { @@ -1218,7 +1212,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, if ((dfile= mysql_file_create_with_symlink(key_file_dfile, dlinkname_ptr, dfilename, 0, create_mode, - MYF(MY_WME | create_flag))) < 0) + MYF(MY_WME | create_flag | sync_dir))) < 0) goto err; errpos=3; diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 6f2825a3319..51354e0e8b5 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -185,7 +185,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (flags & HA_CREATE_TMP_TABLE) { options|= HA_OPTION_TMP_TABLE; - create_mode|= O_NOFOLLOW; + create_mode|= O_NOFOLLOW | (internal_table ? 0 : O_EXCL); } if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { @@ -620,9 +620,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, { char *iext= strrchr(name, '.'); int have_iext= iext && !strcmp(iext, MI_NAME_IEXT); - fn_format(kfilename, name, "", MI_NAME_IEXT, - MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | + fn_format(kfilename, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | + (internal_table ? 0 : MY_RETURN_REAL_PATH) | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); + klinkname_ptr= 0; /* Replace the current file */ create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD; } diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt index 19f0d3cfa99..c2fc8de8149 100644 --- a/storage/rocksdb/CMakeLists.txt +++ b/storage/rocksdb/CMakeLists.txt @@ -54,6 +54,9 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU") SKIP_ROCKSDB_PLUGIN("${OLD_COMPILER_MSG}") ENDIF() SET(CXX11_FLAGS "-std=c++11") + IF (GCC_VERSION VERSION_LESS 5.0) + SET(CXX11_FLAGS "-std=c++11 -Wno-missing-field-initializers") + ENDIF() ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang") IF ((CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3) OR (CLANG_VERSION_STRING AND CLANG_VERSION_STRING VERSION_LESS 3.3)) |