diff options
author | Vicenศiu Ciorbaru <vicentiu@mariadb.org> | 2018-03-21 10:36:49 +0200 |
---|---|---|
committer | Vicenศiu Ciorbaru <vicentiu@mariadb.org> | 2018-03-21 10:36:49 +0200 |
commit | 82aeb6b59640b9733c4026bda71887720153b70a (patch) | |
tree | 06ea8909b396e3a16042437b9574a85ee0156487 | |
parent | 34b03da2114892d96af651a953f6c2527437ad15 (diff) | |
parent | eee73ddfbb29816320c9fc78c8ff1012cac6567a (diff) | |
download | mariadb-git-82aeb6b59640b9733c4026bda71887720153b70a.tar.gz |
Merge branch '10.1' into 10.2
47 files changed, 1566 insertions, 295 deletions
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index b5dc8b9f157..9fa127380a4 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -26,7 +26,7 @@ ENDIF() OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default}) # Set the patch version -SET(WSREP_PATCH_VERSION "21") +SET(WSREP_PATCH_VERSION "23") # Obtain wsrep API version FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION diff --git a/include/my_global.h b/include/my_global.h index 5c325b76a7b..cdd4b503e70 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -591,6 +591,11 @@ typedef SOCKET_SIZE_TYPE size_socket; #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif +#ifdef __GLIBC__ +#define STR_O_CLOEXEC "e" +#else +#define STR_O_CLOEXEC "" +#endif #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC 0 #endif diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result index b60d711568c..cbf5f145d22 100644 --- a/mysql-test/r/ctype_latin1.result +++ b/mysql-test/r/ctype_latin1.result @@ -8241,6 +8241,19 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d` from `test`.`t1` where coalesce(`test`.`t1`.`c`,0) = '3 ' and coalesce(`test`.`t1`.`d`,0) = '3 ' DROP TABLE t1; # +# MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple +# +SET NAMES latin1; +SELECT CONVERT(1, CHAR) IN ('100', 10, '101'); +CONVERT(1, CHAR) IN ('100', 10, '101') +0 +SELECT CONVERT(1, CHAR) IN ('100', 10, '1'); +CONVERT(1, CHAR) IN ('100', 10, '1') +1 +SELECT CONVERT(1, CHAR) IN ('100', '10', '1'); +CONVERT(1, CHAR) IN ('100', '10', '1') +1 +# # End of 10.1 tests # # diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index f8146f9fda2..46b7386d993 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -10543,6 +10543,19 @@ CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1) Warnings: Warning 1977 Cannot convert 'utf8' character 0xC499 to 'latin1' # +# MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple +# +SET NAMES utf8; +SELECT CONVERT(1, CHAR) IN ('100', 10, '101'); +CONVERT(1, CHAR) IN ('100', 10, '101') +0 +SELECT CONVERT(1, CHAR) IN ('100', 10, '1'); +CONVERT(1, CHAR) IN ('100', 10, '1') +1 +SELECT CONVERT(1, CHAR) IN ('100', '10', '1'); +CONVERT(1, CHAR) IN ('100', '10', '1') +1 +# # End of 10.1 tests # # diff --git a/mysql-test/r/fast_prefix_index_fetch_innodb.result b/mysql-test/r/fast_prefix_index_fetch_innodb.result index 92af85f7fdb..c6d96389b08 100644 --- a/mysql-test/r/fast_prefix_index_fetch_innodb.result +++ b/mysql-test/r/fast_prefix_index_fetch_innodb.result @@ -30,73 +30,372 @@ id fake_id bigfield 33 1033 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 128 1128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz # Baseline sanity check: 0, 0. +select "no-op query"; no-op query no-op query -cluster_lookups_matched -1 -cluster_lookups_avoided_matched -1 +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 # Eligible for optimization. +select id, bigfield from prefixinno where bigfield = repeat('d', 31); id bigfield 31 ddddddddddddddddddddddddddddddd -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided 1 # Eligible for optimization, access via fake_id only. +select id, bigfield from prefixinno where fake_id = 1031; id bigfield 31 ddddddddddddddddddddddddddddddd -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided 1 # Not eligible for optimization, access via fake_id of big row. +select id, bigfield from prefixinno where fake_id = 1033; id bigfield 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups 1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 # Not eligible for optimization. +select id, bigfield from prefixinno where bigfield = repeat('x', 32); id bigfield 32 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups 1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 # Not eligible for optimization. +select id, bigfield from prefixinno where bigfield = repeat('y', 33); id bigfield 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups 1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 # Eligible, should not increment lookup counter. +select id, bigfield from prefixinno where bigfield = repeat('b', 8); id bigfield 8 bbbbbbbb -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided 1 # Eligible, should not increment lookup counter. +select id, bigfield from prefixinno where bigfield = repeat('c', 24); id bigfield 24 cccccccccccccccccccccccc -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided 1 # Should increment lookup counter. +select id, bigfield from prefixinno where bigfield = repeat('z', 128); id bigfield 128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz -cluster_lookups_matched -1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups 1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 # Disable optimization, confirm we still increment counter. +set global innodb_prefix_index_cluster_optimization = OFF; +select id, bigfield from prefixinno where fake_id = 1033; id bigfield 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy -cluster_lookups_matched +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +drop table prefixinno; +# Multi-byte handling case +set global innodb_prefix_index_cluster_optimization = ON; +SET NAMES utf8mb4; +CREATE TABLE t1( +f1 varchar(10) CHARACTER SET UTF8MB4 COLLATE UTF8MB4_BIN, +INDEX (f1(3)))ENGINE=INNODB; +INSERT INTO t1 VALUES('a'), ('cccc'), ('aลพ'), ('cฤc'), ('ggแตทg'), ('ยขยข'); +INSERT INTO t1 VALUES('เฎคเฎฎเฎฟเฎดเฏ'), ('๐ฑ๐'), ('๐'), ('๐'); +INSERT INTO t1 VALUES('๐me'), ('euโฌ'), ('lsยข'); +# Eligible - record length is shorter than prefix +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a'; +f1 +a +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%'; +f1 +cccc +cฤc +select @cluster_lookups; +@cluster_lookups +3 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'aลพ'; +f1 +aลพ +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'เฎคเฎฎเฎฟเฎดเฏ'; +f1 +เฎคเฎฎเฎฟเฎดเฏ +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggแตท%'; +f1 +ggแตทg +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐me +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'lsยข'; +f1 +lsยข +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ยขยข%'; +f1 +ยขยข +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐ฑ๐%'; +f1 +๐ฑ๐ +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐ +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +2 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐ +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +2 +DROP TABLE t1; +# Multi-byte with minimum character length > 1 bytes +CREATE TABLE t1( +f1 varchar(10) CHARACTER SET UTF16 COLLATE UTF16_BIN, +INDEX (f1(3)))ENGINE=INNODB; +INSERT INTO t1 VALUES('a'), ('cccc'), ('aลพ'), ('cฤc'), ('ggแตทg'), ('ยขยข'); +INSERT INTO t1 VALUES('เฎคเฎฎเฎฟเฎดเฏ'), ('๐ฑ๐'), ('๐'), ('๐'); +INSERT INTO t1 VALUES('๐me'), ('euโฌ'), ('lsยข'); +# Eligible - record length is shorter than prefix +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a'; +f1 +a +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%'; +f1 +cccc +cฤc +select @cluster_lookups; +@cluster_lookups +3 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'aลพ'; +f1 +aลพ +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'เฎคเฎฎเฎฟเฎดเฏ'; +f1 +เฎคเฎฎเฎฟเฎดเฏ +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggแตท%'; +f1 +ggแตทg +select @cluster_lookups; +@cluster_lookups +2 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐me +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Not eligible - record length longer than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'lsยข'; +f1 +lsยข +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX(`f1`) WHERE f1 like 'ยขยข%'; +f1 +ยขยข +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +# Eligible - record length shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐ฑ๐%'; +f1 +๐ฑ๐ +select @cluster_lookups; +@cluster_lookups +2 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +# Eligible - record length is shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐ +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +2 +# Eligible - record length is shorter than prefix length +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; +f1 +๐ +select @cluster_lookups; +@cluster_lookups +1 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +1 +DROP TABLE t1; +CREATE TABLE t1( +col1 INT, +col2 BLOB DEFAULT NULL, +INDEX `idx1`(col2(4), col1))ENGINE=INNODB; +INSERT INTO t1 VALUES (2, 'test'), (3, repeat('test1', 2000)); +INSERT INTO t1(col1) VALUES(1); +# Eligible - record length is shorter than prefix length +SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 is NULL; +col1 1 -cluster_lookups_avoided_matched +select @cluster_lookups; +@cluster_lookups +0 +select @cluster_lookups_avoided; +@cluster_lookups_avoided 1 -# make test suite happy by cleaning up our mess +# Not eligible - record length longer than prefix index +SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 like 'test1%'; +col1 +3 +select @cluster_lookups; +@cluster_lookups +2 +select @cluster_lookups_avoided; +@cluster_lookups_avoided +0 +DROP TABLE t1; +set global innodb_prefix_index_cluster_optimization = OFF; diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index 0e627bdb915..06da656c7cb 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -1215,6 +1215,37 @@ MAX(a) MAX(COALESCE(a)) 10:20:30 10:20:30 DROP TABLE t1; # +# MDEV-15321: different results when using value of optimizer_use_condition_selectivity=4 and =1 +# +SET @save_old_mode=@@old_mode; +SET @@old_mode=zero_date_time_cast; +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('0000-00-00 10:20:30'),('0000-00-00 10:20:31'); +INSERT INTO t1 VALUES ('0000-00-01 10:20:30'),('0000-00-01 10:20:31'); +INSERT INTO t1 VALUES ('31 10:20:30'),('32 10:20:30'),('33 10:20:30'),('34 10:20:30'); +SET @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +SET @@optimizer_use_condition_selectivity=1; +SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +a +34:20:30 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 8 +SET @@optimizer_use_condition_selectivity=4; +SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +a +34:20:30 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 8 +drop table t1; +SET @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set @@old_mode= @save_old_mode; +# # End of 10.1 tests # # diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index e29e33f074e..f6bf945ed1f 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -10,7 +10,6 @@ # ############################################################################## galera_gra_log : MDEV-13549 Galera test failures -galera_flush_local : MDEV-13549 Galera test failures galera_flush : MDEV-13549 Galera test failures galera_account_management : MariaDB 10.0 does not support ALTER USER galera_binlog_row_image : MariaDB 10.0 does not support binlog_row_image @@ -30,7 +29,6 @@ galera_gcache_recover_manytrx : MDEV-13549 Galera test failures galera_ist_mysqldump : MDEV-13549 Galera test failures mysql-wsrep#31 : MDEV-13549 Galera test failures galera_migrate : MariaDB 10.0 does not support START SLAVE USER -galera_concurrent_ctas : MDEV-13549 Galera test failures galera_wsrep_desync_wsrep_on : MDEV-13549 Galera test failures galera_ssl_upgrade : MDEV-13549 Galera test failures mysql-wsrep#33 : MDEV-13549 Galera test failures diff --git a/mysql-test/suite/galera/include/have_wsrep_replicate_myisam.inc b/mysql-test/suite/galera/include/have_wsrep_replicate_myisam.inc new file mode 100644 index 00000000000..726fc6e2b18 --- /dev/null +++ b/mysql-test/suite/galera/include/have_wsrep_replicate_myisam.inc @@ -0,0 +1,4 @@ +--require suite/galera/r/have_wsrep_replicate_myisam.require +disable_query_log; +SHOW VARIABLES LIKE 'wsrep_replicate_myisam'; +enable_query_log; diff --git a/mysql-test/suite/galera/r/MW-329.result b/mysql-test/suite/galera/r/MW-329.result index af57bc4b056..a3cb7277a9c 100644 --- a/mysql-test/suite/galera/r/MW-329.result +++ b/mysql-test/suite/galera/r/MW-329.result @@ -27,3 +27,4 @@ connection node_1; DROP PROCEDURE proc_insert; DROP TABLE t1; CALL mtr.add_suppression("conflict state 3 after post commit"); +set global innodb_status_output=Default; diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index d3004735a0a..5c5fdabf432 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -1,6 +1,6 @@ SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; COUNT(*) = 43 -1 +0 SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%' @@ -40,6 +40,7 @@ WSREP_NOTIFY_CMD WSREP_ON ON WSREP_OSU_METHOD TOI WSREP_RECOVER OFF +WSREP_REJECT_QUERIES NONE WSREP_REPLICATE_MYISAM OFF WSREP_RESTART_SLAVE OFF WSREP_RETRY_AUTOCOMMIT 1 diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result index 3fdd541b513..a8e798a693d 100644 --- a/mysql-test/suite/galera/r/galera_flush_local.result +++ b/mysql-test/suite/galera/r/galera_flush_local.result @@ -1,4 +1,5 @@ DROP TABLE IF EXISTS t1, t2, x1, x2; +connection node_1; CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; @@ -7,6 +8,8 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +connection node_2; +connection node_1; FLUSH LOCAL DES_KEY_FILE; FLUSH LOCAL HOSTS; FLUSH LOCAL QUERY CACHE; @@ -54,6 +57,7 @@ REPAIR LOCAL TABLE x1, x2; Table Op Msg_type Msg_text test.x1 repair status OK test.x2 repair status OK +connection node_2; wsrep_last_committed_diff 1 SELECT COUNT(*) = 10 FROM t1; @@ -68,6 +72,7 @@ COUNT(*) = 10000 SELECT COUNT(*) = 10 FROM x2; COUNT(*) = 10 1 +connection node_1; DROP TABLE t1, t2, x1, x2; CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); @@ -77,6 +82,8 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +connection node_2; +connection node_1; set wsrep_on=0; FLUSH DES_KEY_FILE; FLUSH HOSTS; @@ -125,6 +132,7 @@ REPAIR TABLE x1, x2; Table Op Msg_type Msg_text test.x1 repair status OK test.x2 repair status OK +connection node_2; wsrep_last_committed_diff 1 wsrep_last_committed_diff2 @@ -141,5 +149,6 @@ COUNT(*) = 10000 SELECT COUNT(*) = 10 FROM x2; COUNT(*) = 10 1 +connection node_1; set wsrep_on=1; DROP TABLE t1, t2, x1, x2; diff --git a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result new file mode 100644 index 00000000000..edf20da92c6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result @@ -0,0 +1,13 @@ +USE information_schema; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF +SET GLOBAL wsrep_reject_queries=ALL; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF +SET GLOBAL wsrep_reject_queries=NONE; +SET SESSION wsrep_dirty_reads=TRUE; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS ON diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result index 81265f44397..378d8ca84f5 100644 --- a/mysql-test/suite/galera/r/galera_var_cluster_address.result +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -4,7 +4,8 @@ connection node_2; SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; -ERROR 08S01: WSREP has not yet prepared node for application use +COUNT(*) > 0 +1 SHOW STATUS LIKE 'wsrep_ready'; Variable_name Value wsrep_ready OFF diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index beb47be1747..df54969675d 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -33,14 +33,15 @@ SET @@session.wsrep_dirty_reads=OFF; SELECT i, variable_name, variable_value FROM t1, information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads" AND i = 1; ERROR 08S01: WSREP has not yet prepared node for application use SELECT 1; -1 -1 +ERROR 08S01: WSREP has not yet prepared node for application use USE information_schema; ERROR 08S01: WSREP has not yet prepared node for application use SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; -ERROR 08S01: WSREP has not yet prepared node for application use +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history; -ERROR 08S01: WSREP has not yet prepared node for application use +COUNT(*) >= 10 +1 connection node_1; USE test; SELECT * FROM t1; diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result new file mode 100644 index 00000000000..98380238fcb --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 (f1 INTEGER); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1; +SET SESSION wsrep_reject_queries = ALL; +ERROR HY000: Variable 'wsrep_reject_queries' is a GLOBAL variable and should be set with SET GLOBAL +SET GLOBAL wsrep_reject_queries = ALL; +SELECT * FROM t1; +ERROR 08S01: WSREP has not yet prepared node for application use +SET GLOBAL wsrep_reject_queries = ALL_KILL; +ERROR HY000: Lost connection to MySQL server during query +connection node_1a; +SELECT * FROM t1; +Got one of the listed errors +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SELECT * FROM t1; +ERROR 08S01: WSREP has not yet prepared node for application use +connection node_2; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +INSERT INTO t1 VALUES (1); +connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL wsrep_reject_queries = NONE; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/have_wsrep_replicate_myisam.require b/mysql-test/suite/galera/r/have_wsrep_replicate_myisam.require new file mode 100644 index 00000000000..c55610fd049 --- /dev/null +++ b/mysql-test/suite/galera/r/have_wsrep_replicate_myisam.require @@ -0,0 +1,2 @@ +Variable_name Value +wsrep_replicate_myisam ON diff --git a/mysql-test/suite/galera/t/MW-329.test b/mysql-test/suite/galera/t/MW-329.test index b3b4e8e921f..5baa4d14966 100644 --- a/mysql-test/suite/galera/t/MW-329.test +++ b/mysql-test/suite/galera/t/MW-329.test @@ -85,3 +85,5 @@ DROP TABLE t1; # Due to MW-330, Multiple "conflict state 3 after post commit" warnings if table is dropped while SP is running CALL mtr.add_suppression("conflict state 3 after post commit"); + +set global innodb_status_output=Default;
\ No newline at end of file diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test index 46a93458271..26fec05dfe5 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test +++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test @@ -51,7 +51,7 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5); --let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1) --connection node_3 --disable_query_log ---eval SELECT "$value" IN ("Error 'Unknown command' on query. Default database: 'test'. Query: 'BEGIN'", "Node has dropped from cluster") AS expected_error +--eval SELECT "$value" IN ("Error 'WSREP has not yet prepared node for application use' on query. Default database: 'test'. Query: 'BEGIN'", "Node has dropped from cluster") AS expected_error --enable_query_log # Step #4. Bring back the async slave and restart replication @@ -85,8 +85,9 @@ DROP TABLE t1; STOP SLAVE; RESET SLAVE ALL; -CALL mtr.add_suppression("Slave SQL: Error 'Unknown command' on query"); -CALL mtr.add_suppression("Slave: Unknown command Error_code: 1047"); +CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query"); +CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047"); +CALL mtr.add_suppression("TORDERED} returned -107 \\(Transport endpoint is not connected\\)"); CALL mtr.add_suppression("Transport endpoint is not connected"); CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed, 'Deadlock found when trying to get lock; try restarting transaction', Error_code: 1213"); CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047"); diff --git a/mysql-test/suite/galera/t/galera_concurrent_ctas.test b/mysql-test/suite/galera/t/galera_concurrent_ctas.test index f0dcf8e4900..6c4e8be68a7 100644 --- a/mysql-test/suite/galera/t/galera_concurrent_ctas.test +++ b/mysql-test/suite/galera/t/galera_concurrent_ctas.test @@ -43,9 +43,9 @@ let $run=10; while($run) { --error 0,1 - exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test - < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & - $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test + exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test \ + < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & \ + $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test \ < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql; dec $run; } diff --git a/mysql-test/suite/galera/t/galera_flush_local.opt b/mysql-test/suite/galera/t/galera_flush_local.opt index 5a1fb6748d9..a084db15c5d 100644 --- a/mysql-test/suite/galera/t/galera_flush_local.opt +++ b/mysql-test/suite/galera/t/galera_flush_local.opt @@ -1 +1,3 @@ ---query_cache_type=1 --query_cache_size=1000000 +--query_cache_type=1 +--query_cache_size=1000000 +--wsrep_replicate_myisam=ON diff --git a/mysql-test/suite/galera/t/galera_flush_local.test b/mysql-test/suite/galera/t/galera_flush_local.test index 768f4ea4f1b..24acd9ec4ff 100644 --- a/mysql-test/suite/galera/t/galera_flush_local.test +++ b/mysql-test/suite/galera/t/galera_flush_local.test @@ -5,6 +5,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_query_cache.inc +--source include/have_wsrep_replicate_myisam.inc --disable_warnings DROP TABLE IF EXISTS t1, t2, x1, x2; diff --git a/mysql-test/suite/galera/t/galera_schema_dirty_reads.test b/mysql-test/suite/galera/t/galera_schema_dirty_reads.test new file mode 100644 index 00000000000..93e24244611 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_schema_dirty_reads.test @@ -0,0 +1,13 @@ +# +# Dirty reads from INFORMATION_SCHEMA tables. +# +--source include/galera_cluster.inc +--source include/have_innodb.inc +--disable_info +USE information_schema; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +SET GLOBAL wsrep_reject_queries=ALL; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +SET GLOBAL wsrep_reject_queries=NONE; +SET SESSION wsrep_dirty_reads=TRUE; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test index 03706bbbb12..6d99d35cdac 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_address.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -24,7 +24,6 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; ---error ER_UNKNOWN_COM_ERROR SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; # Must return 'OFF' diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index cba8488b879..85d759e4a27 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -47,15 +47,14 @@ SET @@session.wsrep_dirty_reads=OFF; --error ER_UNKNOWN_COM_ERROR SELECT i, variable_name, variable_value FROM t1, information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads" AND i = 1; +--error ER_UNKNOWN_COM_ERROR SELECT 1; --error ER_UNKNOWN_COM_ERROR USE information_schema; ---error ER_UNKNOWN_COM_ERROR SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; ---error ER_UNKNOWN_COM_ERROR SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history; --disable_query_log diff --git a/mysql-test/suite/galera/t/galera_var_reject_queries.test b/mysql-test/suite/galera/t/galera_var_reject_queries.test new file mode 100644 index 00000000000..b1af9d8aa2b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_reject_queries.test @@ -0,0 +1,44 @@ +# +# Test wsrep_reject_queries +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +--connection node_1 +--error ER_GLOBAL_VARIABLE +SET SESSION wsrep_reject_queries = ALL; + +SET GLOBAL wsrep_reject_queries = ALL; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM t1; + +# Lost connection +--error 2013 +SET GLOBAL wsrep_reject_queries = ALL_KILL; + +--connection node_1a +--error ER_CONNECTION_KILLED,2013 +SELECT * FROM t1; + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM t1; + +# Confirm that replication continues + +--connection node_2 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +INSERT INTO t1 VALUES (1); + +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET GLOBAL wsrep_reject_queries = NONE; + +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index 0c206975c29..db932ae8223 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -421,6 +421,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME WSREP_REJECT_QUERIES +SESSION_VALUE NULL +GLOBAL_VALUE NONE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NONE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Variable to set to reject queries +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NONE,ALL,ALL_KILL +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME WSREP_REPLICATE_MYISAM SESSION_VALUE NULL GLOBAL_VALUE OFF diff --git a/mysql-test/t/ctype_latin1.test b/mysql-test/t/ctype_latin1.test index 31d4ff7f802..38f147708b8 100644 --- a/mysql-test/t/ctype_latin1.test +++ b/mysql-test/t/ctype_latin1.test @@ -392,6 +392,15 @@ SELECT * FROM t1 WHERE COALESCE(c,0)='3 ' AND COALESCE(d,0)=COALESCE(c,0); DROP TABLE t1; --echo # +--echo # MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple +--echo # + +SET NAMES latin1; +SELECT CONVERT(1, CHAR) IN ('100', 10, '101'); +SELECT CONVERT(1, CHAR) IN ('100', 10, '1'); +SELECT CONVERT(1, CHAR) IN ('100', '10', '1'); + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index b6d2dc7d874..e293cae930a 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -2034,6 +2034,16 @@ SELECT CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1); --echo # +--echo # MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple +--echo # + +SET NAMES utf8; +SELECT CONVERT(1, CHAR) IN ('100', 10, '101'); +SELECT CONVERT(1, CHAR) IN ('100', 10, '1'); +SELECT CONVERT(1, CHAR) IN ('100', '10', '1'); + + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/fast_prefix_index_fetch_innodb.test b/mysql-test/t/fast_prefix_index_fetch_innodb.test index e563e65ec2a..c3b3440d82d 100644 --- a/mysql-test/t/fast_prefix_index_fetch_innodb.test +++ b/mysql-test/t/fast_prefix_index_fetch_innodb.test @@ -31,120 +31,638 @@ select * from prefixinno; let $show_count_statement = show status like 'innodb_secondary_index_triggered_cluster_reads'; let $show_opt_statement = show status like 'innodb_secondary_index_triggered_cluster_reads_avoided'; ---disable_query_log - --echo # Baseline sanity check: 0, 0. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select "no-op query"; ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Eligible for optimization. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('d', 31); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Eligible for optimization, access via fake_id only. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where fake_id = 1031; ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Not eligible for optimization, access via fake_id of big row. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where fake_id = 1033; ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Not eligible for optimization. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('x', 32); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Not eligible for optimization. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('y', 33); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Eligible, should not increment lookup counter. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('b', 8); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Eligible, should not increment lookup counter. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('c', 24); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Should increment lookup counter. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + select id, bigfield from prefixinno where bigfield = repeat('z', 128); ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; --echo # Disable optimization, confirm we still increment counter. ---let $base_count = query_get_value($show_count_statement, Value, 1) ---let $base_opt = query_get_value($show_opt_statement, Value, 1) +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + set global innodb_prefix_index_cluster_optimization = OFF; select id, bigfield from prefixinno where fake_id = 1033; ---let $count = query_get_value($show_count_statement, Value, 1) + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log eval select $count - $base_count into @cluster_lookups; -select @cluster_lookups = 1 as cluster_lookups_matched; ---let $opt = query_get_value($show_opt_statement, Value, 1) -eval select $opt - $base_opt into @cluster_lookups; -select @cluster_lookups = 0 as cluster_lookups_avoided_matched; +eval select $opt - $base_opt into @cluster_lookups_avoided; +--enable_query_log +select @cluster_lookups; +select @cluster_lookups_avoided; ---echo # make test suite happy by cleaning up our mess drop table prefixinno; + +--echo # Multi-byte handling case + +set global innodb_prefix_index_cluster_optimization = ON; +SET NAMES utf8mb4; +CREATE TABLE t1( + f1 varchar(10) CHARACTER SET UTF8MB4 COLLATE UTF8MB4_BIN, + INDEX (f1(3)))ENGINE=INNODB; + +INSERT INTO t1 VALUES('a'), ('cccc'), ('aลพ'), ('cฤc'), ('ggแตทg'), ('ยขยข'); +INSERT INTO t1 VALUES('เฎคเฎฎเฎฟเฎดเฏ'), ('๐ฑ๐'), ('๐'), ('๐'); +INSERT INTO t1 VALUES('๐me'), ('euโฌ'), ('lsยข'); + +--echo # Eligible - record length is shorter than prefix +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'aลพ'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'เฎคเฎฎเฎฟเฎดเฏ'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggแตท%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'lsยข'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ยขยข%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐ฑ๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +DROP TABLE t1; + +--echo # Multi-byte with minimum character length > 1 bytes + +CREATE TABLE t1( + f1 varchar(10) CHARACTER SET UTF16 COLLATE UTF16_BIN, + INDEX (f1(3)))ENGINE=INNODB; + +INSERT INTO t1 VALUES('a'), ('cccc'), ('aลพ'), ('cฤc'), ('ggแตทg'), ('ยขยข'); +INSERT INTO t1 VALUES('เฎคเฎฎเฎฟเฎดเฏ'), ('๐ฑ๐'), ('๐'), ('๐'); +INSERT INTO t1 VALUES('๐me'), ('euโฌ'), ('lsยข'); + +--echo # Eligible - record length is shorter than prefix +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'aลพ'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'เฎคเฎฎเฎฟเฎดเฏ'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggแตท%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'lsยข'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX(`f1`) WHERE f1 like 'ยขยข%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐ฑ๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length is shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Eligible - record length is shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '๐%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +DROP TABLE t1; + +CREATE TABLE t1( + col1 INT, + col2 BLOB DEFAULT NULL, + INDEX `idx1`(col2(4), col1))ENGINE=INNODB; +INSERT INTO t1 VALUES (2, 'test'), (3, repeat('test1', 2000)); +INSERT INTO t1(col1) VALUES(1); + +--echo # Eligible - record length is shorter than prefix length + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 is NULL; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +--echo # Not eligible - record length longer than prefix index + +let $base_count = query_get_value($show_count_statement, Value, 1); +let $base_opt = query_get_value($show_opt_statement, Value, 1); + +SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 like 'test1%'; + +let $count = query_get_value($show_count_statement, Value, 1); +let $opt = query_get_value($show_opt_statement, Value, 1); + +--disable_query_log +eval set @cluster_lookups = $count - $base_count; +eval set @cluster_lookups_avoided = $opt - $base_opt; +--enable_query_log + +select @cluster_lookups; +select @cluster_lookups_avoided; + +DROP TABLE t1; set global innodb_prefix_index_cluster_optimization = OFF; diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index ab496408c32..cce5900a993 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -724,6 +724,29 @@ SELECT MAX(a), MAX(COALESCE(a)) FROM t1; DROP TABLE t1; --echo # +--echo # MDEV-15321: different results when using value of optimizer_use_condition_selectivity=4 and =1 +--echo # + +SET @save_old_mode=@@old_mode; +SET @@old_mode=zero_date_time_cast; +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('0000-00-00 10:20:30'),('0000-00-00 10:20:31'); +INSERT INTO t1 VALUES ('0000-00-01 10:20:30'),('0000-00-01 10:20:31'); +INSERT INTO t1 VALUES ('31 10:20:30'),('32 10:20:30'),('33 10:20:30'),('34 10:20:30'); + +SET @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +SET @@optimizer_use_condition_selectivity=1; +SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; + +SET @@optimizer_use_condition_selectivity=4; +SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8; +drop table t1; +SET @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set @@old_mode= @save_old_mode; + +--echo # --echo # End of 10.1 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 8dce7f7c64a..dead75f548c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -179,19 +179,21 @@ bool Item::get_time_with_conversion(THD *thd, MYSQL_TIME *ltime, - truncate the YYYYMMDD part - add (MM*33+DD)*24 to hours - add (MM*31+DD)*24 to hours - Let's return NULL here, to disallow equal field propagation. + Let's return TRUE here, to disallow equal field propagation. Note, If we start to use this method in more pieces of the code other - than eqial field propagation, we should probably return - NULL only if some flag in fuzzydate is set. + than equal field propagation, we should probably return + TRUE only if some flag in fuzzydate is set. */ - return (null_value= true); + return true; } if (datetime_to_time_with_warn(thd, ltime, <ime2, TIME_SECOND_PART_DIGITS)) { /* - Time difference between CURRENT_DATE and ltime - did not fit into the supported TIME range + If the time difference between CURRENT_DATE and ltime + did not fit into the supported TIME range, then we set the + difference to the maximum possible value in the supported TIME range */ + DBUG_ASSERT(0); return (null_value= true); } *ltime= ltime2; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index ced3f343707..5f3bd1e4ca7 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1383,6 +1383,13 @@ public: { value_res= item->val_str(&value); m_null_value= item->null_value; + // Make sure to cache the result String inside "value" + if (value_res && value_res != &value) + { + if (value.copy(*value_res)) + value.set("", 0, item->collation.collation); + value_res= &value; + } } int cmp(Item *arg) { diff --git a/sql/sql_class.h b/sql/sql_class.h index d4546a0c550..89cdb5af251 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5726,11 +5726,15 @@ public: sent by the user (ie: stored procedure). */ #define CF_SKIP_QUESTIONS (1U << 1) - +#ifdef WITH_WSREP /** Do not check that wsrep snapshot is ready before allowing this command */ #define CF_SKIP_WSREP_CHECK (1U << 2) +#else +#define CF_SKIP_WSREP_CHECK 0 +#endif /* WITH_WSREP */ + /** Do not allow it for COM_MULTI batch */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b4196dafee1..96f6196bc08 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2017, MariaDB + Copyright (c) 2008, 2018, 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 @@ -506,6 +506,7 @@ void init_update_queries(void) server_command_flags[COM_SHUTDOWN]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_SLEEP]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_TIME]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_INIT_DB]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_END]= CF_SKIP_WSREP_CHECK; for (uint i= COM_MDB_GAP_BEG; i <= COM_MDB_GAP_END; i++) { @@ -519,6 +520,8 @@ void init_update_queries(void) server_command_flags[COM_QUERY]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_SET_OPTION]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_PREPARE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; + server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_STMT_FETCH]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_CLOSE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; @@ -1146,21 +1149,28 @@ static enum enum_server_command fetch_command(THD *thd, char *packet) } -#ifndef EMBEDDED_LIBRARY - #ifdef WITH_WSREP -static bool wsrep_node_is_ready(THD *thd) +static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) { - if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready) + bool has_tables = false; + for (const TABLE_LIST *table= tables; table; table= table->next_global) { - my_message(ER_UNKNOWN_COM_ERROR, - "WSREP has not yet prepared node for application use", - MYF(0)); - return false; + TABLE_CATEGORY c; + LEX_STRING db, tn; + lex_string_set(&db, table->db); + lex_string_set(&tn, table->table_name); + c= get_table_category(&db, &tn); + if (c != TABLE_CATEGORY_INFORMATION && + c != TABLE_CATEGORY_PERFORMANCE) + { + return false; + } + has_tables = true; } - return true; + return has_tables; } -#endif +#endif /* WITH_WSREP */ +#ifndef EMBEDDED_LIBRARY /** Read one command from connection and execute it (query or simple command). @@ -1336,8 +1346,9 @@ bool do_command(THD *thd) /* Bail out if DB snapshot has not been installed. */ - if (!(server_command_flags[command] & CF_SKIP_WSREP_CHECK) && - !wsrep_node_is_ready(thd)) + if (thd->variables.wsrep_on && !thd->wsrep_applier && + (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) && + (server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0) { thd->protocol->end_statement(); @@ -3143,20 +3154,23 @@ mysql_execute_command(THD *thd) } /* - Bail out if DB snapshot has not been installed. SET and SHOW commands, - however, are always allowed. - Select query is also allowed if it does not access any table. - We additionally allow all other commands that do not change data in - case wsrep_dirty_reads is enabled. - */ - if (lex->sql_command != SQLCOM_SET_OPTION && - !wsrep_is_show_query(lex->sql_command) && - !(thd->variables.wsrep_dirty_reads && - !is_update_query(lex->sql_command)) && - !(lex->sql_command == SQLCOM_SELECT && - !all_tables) && - !wsrep_node_is_ready(thd)) + * Bail out if DB snapshot has not been installed. We however, + * allow SET and SHOW queries and reads from information schema + * and dirty reads (if configured) + */ + if (thd->variables.wsrep_on && + !thd->wsrep_applier && + !(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) && + !(thd->variables.wsrep_dirty_reads && + (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) && + !wsrep_tables_accessible_when_detached(all_tables) && + lex->sql_command != SQLCOM_SET_OPTION && + !wsrep_is_show_query(lex->sql_command)) + { + my_message(ER_UNKNOWN_COM_ERROR, + "WSREP has not yet prepared node for application use", MYF(0)); goto error; + } } #endif /* WITH_WSREP */ status_var_increment(thd->status_var.com_stat[lex->sql_command]); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index ea95899b004..a640bc40f85 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1,7 +1,7 @@ /* Copyright (c) 2002, 2015, Oracle and/or its affiliates. - Copyright (c) 2012, 2017, MariaDB Corporation. + Copyright (c) 2012, 2018, MariaDB Corporation. - This program is free software; you can redistribute it and/or modify + 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 the Free Software Foundation; version 2 of the License. @@ -5077,6 +5077,14 @@ static Sys_var_mybool Sys_wsrep_desync ( ON_CHECK(wsrep_desync_check), ON_UPDATE(wsrep_desync_update)); +static const char *wsrep_reject_queries_names[]= { "NONE", "ALL", "ALL_KILL", NullS }; +static Sys_var_enum Sys_wsrep_reject_queries( + "wsrep_reject_queries", "Variable to set to reject queries", + GLOBAL_VAR(wsrep_reject_queries), CMD_LINE(OPT_ARG), + wsrep_reject_queries_names, DEFAULT(WSREP_REJECT_NONE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_reject_queries_update)); + static const char *wsrep_binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", "NONE", NullS}; static Sys_var_enum Sys_wsrep_forced_binlog_format( diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index f154b51516b..eb37b63eff6 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -80,6 +80,7 @@ extern const char* wsrep_notify_cmd; extern long wsrep_max_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; +extern ulong wsrep_reject_queries; extern my_bool wsrep_replicate_myisam; extern ulong wsrep_mysql_replication_bundle; extern my_bool wsrep_restart_slave; @@ -91,6 +92,12 @@ extern bool wsrep_new_cluster; extern bool wsrep_gtid_mode; extern uint32 wsrep_gtid_domain_id; +enum enum_wsrep_reject_types { + WSREP_REJECT_NONE, /* nothing rejected */ + WSREP_REJECT_ALL, /* reject all queries, with UNKNOWN_COMMAND error */ + WSREP_REJECT_ALL_KILL /* kill existing connections and reject all queries*/ +}; + enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU, diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index b9eb546bf76..38d727fb470 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -26,6 +26,7 @@ #include <cstdio> #include <cstdlib> +ulong wsrep_reject_queries; static long wsrep_prev_slave_threads = wsrep_slave_threads; @@ -413,6 +414,27 @@ void wsrep_provider_options_init(const char* value) wsrep_provider_options = (value) ? my_strdup(value, MYF(0)) : NULL; } +bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type) +{ + switch (wsrep_reject_queries) { + case WSREP_REJECT_NONE: + WSREP_INFO("Allowing client queries due to manual setting"); + break; + case WSREP_REJECT_ALL: + WSREP_INFO("Rejecting client queries due to manual setting"); + break; + case WSREP_REJECT_ALL_KILL: + wsrep_close_client_connections(FALSE); + WSREP_INFO("Rejecting client queries and killing connections due to manual setting"); + break; + default: + WSREP_INFO("Unknown value for wsrep_reject_queries: %lu", + wsrep_reject_queries); + return true; + } + return false; +} + static int wsrep_cluster_address_verify (const char* cluster_address_str) { /* There is no predefined address format, it depends on provider. */ diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index b9051b29843..7d3ff50f1d2 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -92,6 +92,7 @@ extern bool wsrep_desync_update UPDATE_ARGS; extern bool wsrep_max_ws_size_check CHECK_ARGS; extern bool wsrep_max_ws_size_update UPDATE_ARGS; +extern bool wsrep_reject_queries_update UPDATE_ARGS; #else /* WITH_WSREP */ diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 6cd8111e902..903f1f13ace 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -275,7 +275,20 @@ buf_dump( buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s", full_filename); - f = fopen(tmp_filename, "w"); +#if defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0 + f = fopen(tmp_filename, "w" STR_O_CLOEXEC); +#else + { + int fd; + fd = open(tmp_filename, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, 0640); + if (fd >= 0) { + f = fdopen(fd, "w"); + } + else { + f = NULL; + } + } +#endif if (f == NULL) { buf_dump_status(STATUS_ERR, "Cannot open '%s' for writing: %s", diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index a824afc6e0e..14bd79a0c5d 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2255,7 +2255,7 @@ AIO::is_linux_native_aio_supported() strcpy(name + dirnamelen, "ib_logfile0"); - fd = open(name, O_RDONLY); + fd = open(name, O_RDONLY | O_CLOEXEC); if (fd == -1) { diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index c42b08d820b..9f14be17c11 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -2915,7 +2915,9 @@ row_sel_field_store_in_mysql_format_func( || !(templ->mysql_col_len % templ->mbmaxlen)); ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len || (field_no == templ->icp_rec_field_no - && field->prefix_len > 0)); + && field->prefix_len > 0) + || templ->rec_field_is_prefix); + ut_ad(templ->is_virtual || !(field->prefix_len % templ->mbmaxlen)); @@ -4061,6 +4063,118 @@ row_sel_fill_vrow( } } +/** Return the record field length in characters. +@param[in] col table column of the field +@param[in] field_no field number +@param[in] rec physical record +@param[in] offsets field offsets in the physical record +@return field length in characters. */ +static +size_t +rec_field_len_in_chars( + const dict_col_t* col, + const ulint field_no, + const rec_t* rec, + const ulint* offsets) +{ + const ulint cset = dtype_get_charset_coll(col->prtype); + const CHARSET_INFO* cs = all_charsets[cset]; + ulint rec_field_len; + const char* rec_field = reinterpret_cast<const char *>( + rec_get_nth_field( + rec, offsets, field_no, &rec_field_len)); + + if (UNIV_UNLIKELY(!cs)) { + ib::warn() << "Missing collation " << cset; + return SIZE_T_MAX; + } + + return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len)); +} + +/** Avoid the clustered index lookup if all the following conditions +are true: +1) all columns are in 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. +@return true, to avoid clustered index lookup. */ +static +bool row_search_with_covering_prefix( + row_prebuilt_t* prebuilt, + const rec_t* rec, + const ulint* offsets) +{ + const dict_index_t* index = prebuilt->index; + ut_ad(!dict_index_is_clust(index)); + + if (!srv_prefix_index_cluster_optimization) { + return false; + } + + /** Optimization only applicable if there the number of secondary index + fields are greater than or equal to number of clustered index fields. */ + if (prebuilt->n_template > index->n_fields) { + return false; + } + + 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; + + /** Condition (1) : is the field in the index. */ + if (j == ULINT_UNDEFINED) { + return false; + } + + /** Condition (2): If this is a prefix index then + row's value size shorter than prefix length. */ + + if (!templ->rec_field_is_prefix) { + 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. */ + continue; + } + + if (rec_size * templ->mbminlen >= 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) { + /* No of chars to store the record exceeds + the index prefix character length. */ + return false; + } + } + + /* If prefix index optimization condition satisfied then + for all columns above, use rec_prefix_field_no instead of + rec_field_no, and skip the clustered lookup below. */ + for (ulint i = 0; i < prebuilt->n_template; i++) { + mysql_row_templ_t* templ = prebuilt->mysql_template + i; + templ->rec_field_no = templ->rec_prefix_field_no; + ut_a(templ->rec_field_no != ULINT_UNDEFINED); + } + + srv_stats.n_sec_rec_cluster_reads_avoided.inc(); + return true; +} + /** Searches for rows in the database using cursor. Function is mainly used for tables that are shared across connections and so it employs technique that can help re-construct the rows that @@ -4120,7 +4234,6 @@ row_search_mvcc( ulint* offsets = offsets_; ibool table_lock_waited = FALSE; byte* next_buf = 0; - ibool use_clustered_index = FALSE; bool spatial_search = false; rec_offs_init(offsets_); @@ -5179,69 +5292,10 @@ locks_ok_del_marked: break; } - /* Get the clustered index record if needed, if we did not do the - search using the clustered index... */ - - use_clustered_index = - (index != clust_index && prebuilt->need_to_access_clustered); - - if (use_clustered_index && srv_prefix_index_cluster_optimization - && prebuilt->n_template <= index->n_fields) { - /* ...but, perhaps avoid the clustered index lookup if - all of the following are true: - 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. - */ - ibool row_contains_all_values = TRUE; - uint i; - for (i = 0; i < prebuilt->n_template; i++) { - /* Condition (1) from above: is the field in the - index (prefix or not)? */ - mysql_row_templ_t* templ = - prebuilt->mysql_template + i; - ulint secondary_index_field_no = - templ->rec_prefix_field_no; - if (secondary_index_field_no == ULINT_UNDEFINED) { - row_contains_all_values = FALSE; - break; - } - /* Condition (2) from above: if this is a - prefix, is this row's value size shorter - than the prefix? */ - if (templ->rec_field_is_prefix) { - ulint record_size = rec_offs_nth_size( - offsets, - secondary_index_field_no); - const dict_field_t *field = - dict_index_get_nth_field( - index, - secondary_index_field_no); - ut_a(field->prefix_len > 0); - if (record_size >= field->prefix_len) { - row_contains_all_values = FALSE; - break; - } - } + if (index != clust_index && prebuilt->need_to_access_clustered) { + if (row_search_with_covering_prefix(prebuilt, rec, offsets)) { + goto use_covering_index; } - /* If (1) and (2) were true for all columns above, use - rec_prefix_field_no instead of rec_field_no, and skip - the clustered lookup below. */ - if (row_contains_all_values) { - for (i = 0; i < prebuilt->n_template; i++) { - mysql_row_templ_t* templ = - prebuilt->mysql_template + i; - templ->rec_field_no = - templ->rec_prefix_field_no; - ut_a(templ->rec_field_no != ULINT_UNDEFINED); - } - use_clustered_index = FALSE; - srv_stats.n_sec_rec_cluster_reads_avoided.inc(); - } - } - - if (use_clustered_index) { requires_clust_rec: ut_ad(index != clust_index); /* We use a 'goto' to the preceding label if a consistent @@ -5339,6 +5393,7 @@ requires_clust_rec: } } } else { +use_covering_index: result_rec = rec; } diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index 94f354e0a0f..e6e5dc7c109 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -29,6 +29,10 @@ #endif #ifdef HAVE_ORACLE_OCI +#if (defined(WIN32) || defined(_WIN32) || defined(WINDOWS) || defined(_WINDOWS)) +#include <Shlwapi.h> +#define strcasestr StrStr +#endif #include <oci.h> #include "spd_err.h" #include "spd_param.h" @@ -3817,7 +3821,7 @@ int spider_db_oracle_util::open_item_func( { Item_func_conv_charset *item_func_conv_charset = (Item_func_conv_charset *)item_func; - CHARSET_INFO *conv_charset = item_func_conv_charset->conv_charset; + CHARSET_INFO *conv_charset = item_func_conv_charset->collation.collation; uint cset_length = strlen(conv_charset->csname); if (str->reserve(SPIDER_SQL_USING_LEN + cset_length)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index dc1786796e6..0659ada92b5 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -371,6 +371,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( if (direct_sql->access_mode == 0) { #endif + if (direct_sql->dbton_id == SPIDER_DBTON_SIZE) + { + /* Invalid target wrapper */ + *error_num = ER_SPIDER_INVALID_CONNECT_INFO_NUM; + my_printf_error(*error_num, ER_SPIDER_INVALID_CONNECT_INFO_STR, + MYF(0), direct_sql->tgt_wrapper); + goto error_alloc_conn; + } if (!(conn = (SPIDER_CONN *) spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), @@ -398,6 +406,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( conn->default_database.init_calc_mem(138); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { + if (direct_sql->dbton_id == SPIDER_DBTON_SIZE) + { + /* Invalid target wrapper */ + *error_num = ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM; + my_printf_error(*error_num, ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_STR, + MYF(0), direct_sql->tgt_wrapper); + goto error_alloc_conn; + } if (!(conn = (SPIDER_CONN *) spider_bulk_malloc(spider_current_trx, 33, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6657.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6657.result index 2e9faddbaff..3804a583dc3 100644 --- a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6657.result +++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6657.result @@ -10,7 +10,7 @@ col3 smallint(5) NOT NULL DEFAULT '1', filler varchar(255) DEFAULT NULL, KEY pk_ersatz(col1,col2,col3), KEY key1 (col1,col2) USING BTREE -) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1 COMPRESSION=TOKUDB_LZMA; +) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1; insert into t3 select 1300000000+a, 12345, 7890, 'data' from t2; insert into t3 select 1400000000+a, 12345, 7890, 'data' from t2; insert into t3 select 1410799999+a, 12345, 7890, 'data' from t2; @@ -34,7 +34,7 @@ from t3 where col1 <= 1410799999 order by col1 desc,col2 desc,col3 desc limit 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL 2001 Using where; Using index +1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL # Using where; Using index # The same query but the constant is bigger. # The query should use range(PRIMARY), not full index scan: explain @@ -43,5 +43,5 @@ from t3 where col1 <= 1412199999 order by col1 desc, col2 desc, col3 desc limit 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL 15001 Using where; Using index +1 SIMPLE t3 range pk_ersatz,key1 pk_ersatz 4 NULL # Using where; Using index drop table t1,t2,t3; diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6657.test b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6657.test index a809c3faf06..b723a5d72e8 100644 --- a/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6657.test +++ b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6657.test @@ -15,7 +15,7 @@ CREATE TABLE t3 ( filler varchar(255) DEFAULT NULL, KEY pk_ersatz(col1,col2,col3), KEY key1 (col1,col2) USING BTREE -) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1 COMPRESSION=TOKUDB_LZMA; +) ENGINE=TokuDB DEFAULT CHARSET=latin1 PACK_KEYS=1; insert into t3 select 1300000000+a, 12345, 7890, 'data' from t2; insert into t3 select 1400000000+a, 12345, 7890, 'data' from t2; @@ -35,6 +35,7 @@ insert into t3 select 1412099999+a, 12345, 7890, 'data' from t2; insert into t3 select 1412199999+a, 12345, 7890, 'data' from t2; --echo # The following must use range(PRIMARY): +--replace_column 9 # explain select col1,col2,col3 from t3 @@ -43,6 +44,7 @@ order by col1 desc,col2 desc,col3 desc limit 1; --echo # The same query but the constant is bigger. --echo # The query should use range(PRIMARY), not full index scan: +--replace_column 9 # explain select col1,col2,col3 from t3 diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index bf384390a98..1cc40fcfbad 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -216,7 +216,20 @@ buf_dump( buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s", full_filename); - f = fopen(tmp_filename, "w"); +#if defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0 + f = fopen(tmp_filename, "w" STR_O_CLOEXEC); +#else + { + int fd; + fd = open(tmp_filename, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, 0640); + if (fd >= 0) { + f = fdopen(fd, "w"); + } + else { + f = NULL; + } + } +#endif if (f == NULL) { buf_dump_status(STATUS_ERR, "Cannot open '%s' for writing: %s", diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index b81ea60a413..97007c1107c 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -3685,6 +3685,117 @@ row_search_idx_cond_check( return(result); } +/** Return the record field length in characters. +@param[in] col table column of the field +@param[in] field_no field number +@param[in] rec physical record +@param[in] offsets field offsets in the physical record +@return field length in characters. */ +static +size_t +rec_field_len_in_chars( + const dict_col_t* col, + const ulint field_no, + const rec_t* rec, + const ulint* offsets) +{ + const ulint cset = dtype_get_charset_coll(col->prtype); + const CHARSET_INFO* cs = all_charsets[cset]; + ulint rec_field_len; + const char* rec_field = reinterpret_cast<const char *>( + rec_get_nth_field( + rec, offsets, field_no, &rec_field_len)); + + if (UNIV_UNLIKELY(!cs)) { + ib_logf(IB_LOG_LEVEL_WARN, "Missing collation " ULINTPF, cset); + return SIZE_T_MAX; + } + + return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len)); +} + + +/** Avoid the clustered index lookup if all the following conditions +are true: +1) all columns are in 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. +@return true, to avoid clustered index lookup. */ +static +bool row_search_with_covering_prefix( + row_prebuilt_t* prebuilt, + const rec_t* rec, + const ulint* offsets) +{ + const dict_index_t* index = prebuilt->index; + ut_ad(!dict_index_is_clust(index)); + + if (!srv_prefix_index_cluster_optimization) { + return false; + } + + /** Optimization only applicable if the number of secondary index + fields are greater than or equal to number of clustered index fields. */ + if (prebuilt->n_template > index->n_fields) { + return false; + } + + 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; + + /** Condition (1) : is the field in the index. */ + if (j == ULINT_UNDEFINED) { + return false; + } + + /** Condition (2): If this is a prefix index then + row's value size shorter than prefix length. */ + + if (!templ->rec_field_is_prefix) { + 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. */ + continue; + } + + if (rec_size * templ->mbminlen >= 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) { + /* No of chars to store the record exceeds + the index prefix character length. */ + return false; + } + } + + for (ulint i = 0; i < prebuilt->n_template; i++) { + mysql_row_templ_t* templ = prebuilt->mysql_template + i; + templ->rec_field_no = templ->rec_prefix_field_no; + ut_a(templ->rec_field_no != ULINT_UNDEFINED); + } + + srv_stats.n_sec_rec_cluster_reads_avoided.inc(); + return true; +} + /********************************************************************//** Searches for rows in the database. This is used in the interface to MySQL. This function opens a cursor, and also implements fetch next @@ -3748,7 +3859,6 @@ row_search_for_mysql( ulint* offsets = offsets_; ibool table_lock_waited = FALSE; byte* next_buf = 0; - bool use_clustered_index = false; rec_offs_init(offsets_); @@ -4810,71 +4920,10 @@ locks_ok: break; } - /* Get the clustered index record if needed, if we did not do the - search using the clustered index... */ - - use_clustered_index = - (index != clust_index && prebuilt->need_to_access_clustered); - - if (use_clustered_index && srv_prefix_index_cluster_optimization - && prebuilt->n_template <= index->n_fields) { - /* ...but, perhaps avoid the clustered index lookup if - all of the following are true: - 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. - */ - bool row_contains_all_values = true; - unsigned int i; - for (i = 0; i < prebuilt->n_template; i++) { - /* Condition (1) from above: is the field in the - index (prefix or not)? */ - const mysql_row_templ_t* templ = - prebuilt->mysql_template + i; - ulint secondary_index_field_no = - templ->rec_prefix_field_no; - if (secondary_index_field_no == ULINT_UNDEFINED) { - row_contains_all_values = false; - break; - } - /* Condition (2) from above: if this is a - prefix, is this row's value size shorter - than the prefix? */ - if (templ->rec_field_is_prefix) { - ulint record_size = rec_offs_nth_size( - offsets, - secondary_index_field_no); - const dict_field_t *field = - dict_index_get_nth_field( - index, - secondary_index_field_no); - ut_a(field->prefix_len > 0); - if (record_size >= field->prefix_len - / templ->mbmaxlen) { - row_contains_all_values = false; - break; - } - } - } - /* If (1) and (2) were true for all columns above, use - rec_prefix_field_no instead of rec_field_no, and skip - the clustered lookup below. */ - if (row_contains_all_values) { - for (i = 0; i < prebuilt->n_template; i++) { - mysql_row_templ_t* templ = - prebuilt->mysql_template + i; - templ->rec_field_no = - templ->rec_prefix_field_no; - ut_a(templ->rec_field_no != ULINT_UNDEFINED); - } - use_clustered_index = false; - srv_stats.n_sec_rec_cluster_reads_avoided.inc(); + if (index != clust_index && prebuilt->need_to_access_clustered) { + if (row_search_with_covering_prefix(prebuilt, rec, offsets)) { + goto use_covering_index; } - } - - if (use_clustered_index) { - requires_clust_rec: ut_ad(index != clust_index); /* We use a 'goto' to the preceding label if a consistent @@ -4960,6 +5009,7 @@ requires_clust_rec: } } } else { +use_covering_index: result_rec = rec; } |