Merge branch '10.1' into 10.2

This commit is contained in:
Vicențiu Ciorbaru 2018-03-21 10:36:49 +02:00
commit 82aeb6b596
47 changed files with 1566 additions and 295 deletions

View File

@ -26,7 +26,7 @@ ENDIF()
OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default}) OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default})
# Set the patch version # Set the patch version
SET(WSREP_PATCH_VERSION "21") SET(WSREP_PATCH_VERSION "23")
# Obtain wsrep API version # Obtain wsrep API version
FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION

View File

@ -591,6 +591,11 @@ typedef SOCKET_SIZE_TYPE size_socket;
#ifndef O_CLOEXEC #ifndef O_CLOEXEC
#define O_CLOEXEC 0 #define O_CLOEXEC 0
#endif #endif
#ifdef __GLIBC__
#define STR_O_CLOEXEC "e"
#else
#define STR_O_CLOEXEC ""
#endif
#ifndef SOCK_CLOEXEC #ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0 #define SOCK_CLOEXEC 0
#endif #endif

View File

@ -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 ' 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; 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 # End of 10.1 tests
# #
# #

View File

@ -10543,6 +10543,19 @@ CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1)
Warnings: Warnings:
Warning 1977 Cannot convert 'utf8' character 0xC499 to 'latin1' 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 # End of 10.1 tests
# #
# #

View File

@ -30,73 +30,372 @@ id fake_id bigfield
33 1033 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 33 1033 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
128 1128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 128 1128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
# Baseline sanity check: 0, 0. # Baseline sanity check: 0, 0.
select "no-op query";
no-op query no-op query
no-op query no-op query
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched 0
1 select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible for optimization. # Eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('d', 31);
id bigfield id bigfield
31 ddddddddddddddddddddddddddddddd 31 ddddddddddddddddddddddddddddddd
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched 0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1 1
# Eligible for optimization, access via fake_id only. # Eligible for optimization, access via fake_id only.
select id, bigfield from prefixinno where fake_id = 1031;
id bigfield id bigfield
31 ddddddddddddddddddddddddddddddd 31 ddddddddddddddddddddddddddddddd
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched 0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1 1
# Not eligible for optimization, access via fake_id of big row. # Not eligible for optimization, access via fake_id of big row.
select id, bigfield from prefixinno where fake_id = 1033;
id bigfield id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched
1 1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible for optimization. # Not eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('x', 32);
id bigfield id bigfield
32 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 32 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched
1 1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible for optimization. # Not eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('y', 33);
id bigfield id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched
1 1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible, should not increment lookup counter. # Eligible, should not increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('b', 8);
id bigfield id bigfield
8 bbbbbbbb 8 bbbbbbbb
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched 0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1 1
# Eligible, should not increment lookup counter. # Eligible, should not increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('c', 24);
id bigfield id bigfield
24 cccccccccccccccccccccccc 24 cccccccccccccccccccccccc
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched 0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1 1
# Should increment lookup counter. # Should increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('z', 128);
id bigfield id bigfield
128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
cluster_lookups_matched select @cluster_lookups;
1 @cluster_lookups
cluster_lookups_avoided_matched
1 1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Disable optimization, confirm we still increment counter. # 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 id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched select @cluster_lookups;
@cluster_lookups
1 1
cluster_lookups_avoided_matched 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 1
# make test suite happy by cleaning up our mess # 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
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
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
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# 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;

View File

@ -1215,6 +1215,37 @@ MAX(a) MAX(COALESCE(a))
10:20:30 10:20:30 10:20:30 10:20:30
DROP TABLE t1; 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 # End of 10.1 tests
# #
# #

View File

@ -10,7 +10,6 @@
# #
############################################################################## ##############################################################################
galera_gra_log : MDEV-13549 Galera test failures galera_gra_log : MDEV-13549 Galera test failures
galera_flush_local : MDEV-13549 Galera test failures
galera_flush : MDEV-13549 Galera test failures galera_flush : MDEV-13549 Galera test failures
galera_account_management : MariaDB 10.0 does not support ALTER USER galera_account_management : MariaDB 10.0 does not support ALTER USER
galera_binlog_row_image : MariaDB 10.0 does not support binlog_row_image 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 galera_ist_mysqldump : MDEV-13549 Galera test failures
mysql-wsrep#31 : 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_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_wsrep_desync_wsrep_on : MDEV-13549 Galera test failures
galera_ssl_upgrade : MDEV-13549 Galera test failures galera_ssl_upgrade : MDEV-13549 Galera test failures
mysql-wsrep#33 : MDEV-13549 Galera test failures mysql-wsrep#33 : MDEV-13549 Galera test failures

View File

@ -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;

View File

@ -27,3 +27,4 @@ connection node_1;
DROP PROCEDURE proc_insert; DROP PROCEDURE proc_insert;
DROP TABLE t1; DROP TABLE t1;
CALL mtr.add_suppression("conflict state 3 after post commit"); CALL mtr.add_suppression("conflict state 3 after post commit");
set global innodb_status_output=Default;

View File

@ -1,6 +1,6 @@
SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
COUNT(*) = 43 COUNT(*) = 43
1 0
SELECT VARIABLE_NAME, VARIABLE_VALUE SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME LIKE 'wsrep_%' WHERE VARIABLE_NAME LIKE 'wsrep_%'
@ -40,6 +40,7 @@ WSREP_NOTIFY_CMD
WSREP_ON ON WSREP_ON ON
WSREP_OSU_METHOD TOI WSREP_OSU_METHOD TOI
WSREP_RECOVER OFF WSREP_RECOVER OFF
WSREP_REJECT_QUERIES NONE
WSREP_REPLICATE_MYISAM OFF WSREP_REPLICATE_MYISAM OFF
WSREP_RESTART_SLAVE OFF WSREP_RESTART_SLAVE OFF
WSREP_RETRY_AUTOCOMMIT 1 WSREP_RETRY_AUTOCOMMIT 1

View File

@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1, t2, x1, x2; DROP TABLE IF EXISTS t1, t2, x1, x2;
connection node_1;
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER);
CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER);
CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; 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 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 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); 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 DES_KEY_FILE;
FLUSH LOCAL HOSTS; FLUSH LOCAL HOSTS;
FLUSH LOCAL QUERY CACHE; FLUSH LOCAL QUERY CACHE;
@ -54,6 +57,7 @@ REPAIR LOCAL TABLE x1, x2;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.x1 repair status OK test.x1 repair status OK
test.x2 repair status OK test.x2 repair status OK
connection node_2;
wsrep_last_committed_diff wsrep_last_committed_diff
1 1
SELECT COUNT(*) = 10 FROM t1; SELECT COUNT(*) = 10 FROM t1;
@ -68,6 +72,7 @@ COUNT(*) = 10000
SELECT COUNT(*) = 10 FROM x2; SELECT COUNT(*) = 10 FROM x2;
COUNT(*) = 10 COUNT(*) = 10
1 1
connection node_1;
DROP TABLE t1, t2, x1, x2; DROP TABLE t1, t2, x1, x2;
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER);
CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 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 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 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); 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; set wsrep_on=0;
FLUSH DES_KEY_FILE; FLUSH DES_KEY_FILE;
FLUSH HOSTS; FLUSH HOSTS;
@ -125,6 +132,7 @@ REPAIR TABLE x1, x2;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.x1 repair status OK test.x1 repair status OK
test.x2 repair status OK test.x2 repair status OK
connection node_2;
wsrep_last_committed_diff wsrep_last_committed_diff
1 1
wsrep_last_committed_diff2 wsrep_last_committed_diff2
@ -141,5 +149,6 @@ COUNT(*) = 10000
SELECT COUNT(*) = 10 FROM x2; SELECT COUNT(*) = 10 FROM x2;
COUNT(*) = 10 COUNT(*) = 10
1 1
connection node_1;
set wsrep_on=1; set wsrep_on=1;
DROP TABLE t1, t2, x1, x2; DROP TABLE t1, t2, x1, x2;

View File

@ -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

View File

@ -4,7 +4,8 @@ connection node_2;
SET GLOBAL wsrep_cluster_address = 'foo://'; SET GLOBAL wsrep_cluster_address = 'foo://';
SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_sync_wait=0;
SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; 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'; SHOW STATUS LIKE 'wsrep_ready';
Variable_name Value Variable_name Value
wsrep_ready OFF wsrep_ready OFF

View File

@ -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; 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 ERROR 08S01: WSREP has not yet prepared node for application use
SELECT 1; SELECT 1;
1 ERROR 08S01: WSREP has not yet prepared node for application use
1
USE information_schema; USE information_schema;
ERROR 08S01: WSREP has not yet prepared node for application use ERROR 08S01: WSREP has not yet prepared node for application use
SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; 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; 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; connection node_1;
USE test; USE test;
SELECT * FROM t1; SELECT * FROM t1;

View File

@ -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;

View File

@ -0,0 +1,2 @@
Variable_name Value
wsrep_replicate_myisam ON

View File

@ -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 # 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"); CALL mtr.add_suppression("conflict state 3 after post commit");
set global innodb_status_output=Default;

View File

@ -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) --let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1)
--connection node_3 --connection node_3
--disable_query_log --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 --enable_query_log
# Step #4. Bring back the async slave and restart replication # Step #4. Bring back the async slave and restart replication
@ -85,8 +85,9 @@ DROP TABLE t1;
STOP SLAVE; STOP SLAVE;
RESET SLAVE ALL; RESET SLAVE ALL;
CALL mtr.add_suppression("Slave SQL: Error 'Unknown command' on query"); CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query");
CALL mtr.add_suppression("Slave: Unknown command Error_code: 1047"); 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("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: 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"); CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");

View File

@ -43,9 +43,9 @@ let $run=10;
while($run) while($run)
{ {
--error 0,1 --error 0,1
exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test \
< $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & \
$MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test \
< $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql; < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql;
dec $run; dec $run;
} }

View File

@ -1 +1,3 @@
--query_cache_type=1 --query_cache_size=1000000 --query_cache_type=1
--query_cache_size=1000000
--wsrep_replicate_myisam=ON

View File

@ -5,6 +5,7 @@
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_query_cache.inc --source include/have_query_cache.inc
--source include/have_wsrep_replicate_myisam.inc
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t1, t2, x1, x2; DROP TABLE IF EXISTS t1, t2, x1, x2;

View File

@ -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";

View File

@ -24,7 +24,6 @@ SET GLOBAL wsrep_cluster_address = 'foo://';
SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_sync_wait=0;
--error ER_UNKNOWN_COM_ERROR
SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
# Must return 'OFF' # Must return 'OFF'

View File

@ -47,15 +47,14 @@ SET @@session.wsrep_dirty_reads=OFF;
--error ER_UNKNOWN_COM_ERROR --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; 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; SELECT 1;
--error ER_UNKNOWN_COM_ERROR --error ER_UNKNOWN_COM_ERROR
USE information_schema; USE information_schema;
--error ER_UNKNOWN_COM_ERROR
SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; 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; SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history;
--disable_query_log --disable_query_log

View File

@ -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;

View File

@ -421,6 +421,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON ENUM_VALUE_LIST OFF,ON
READ_ONLY YES READ_ONLY YES
COMMAND_LINE_ARGUMENT OPTIONAL 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 VARIABLE_NAME WSREP_REPLICATE_MYISAM
SESSION_VALUE NULL SESSION_VALUE NULL
GLOBAL_VALUE OFF GLOBAL_VALUE OFF

View File

@ -391,6 +391,15 @@ EXPLAIN EXTENDED
SELECT * FROM t1 WHERE COALESCE(c,0)='3 ' AND COALESCE(d,0)=COALESCE(c,0); SELECT * FROM t1 WHERE COALESCE(c,0)='3 ' AND COALESCE(d,0)=COALESCE(c,0);
DROP TABLE t1; 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 #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@ -2033,6 +2033,16 @@ SELECT CONVERT(_utf8 0xC499 USING latin1);
SELECT CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1); 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 #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@ -31,120 +31,638 @@ select * from prefixinno;
let $show_count_statement = show status like 'innodb_secondary_index_triggered_cluster_reads'; 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'; let $show_opt_statement = show status like 'innodb_secondary_index_triggered_cluster_reads_avoided';
--disable_query_log
--echo # Baseline sanity check: 0, 0. --echo # Baseline sanity check: 0, 0.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select "no-op query"; 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Eligible for optimization. --echo # Eligible for optimization.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('d', 31); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Eligible for optimization, access via fake_id only. --echo # Eligible for optimization, access via fake_id only.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where fake_id = 1031; 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Not eligible for optimization, access via fake_id of big row. --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_count = query_get_value($show_count_statement, Value, 1);
--let $base_opt = query_get_value($show_opt_statement, Value, 1) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where fake_id = 1033; 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Not eligible for optimization. --echo # Not eligible for optimization.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('x', 32); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Not eligible for optimization. --echo # Not eligible for optimization.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('y', 33); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Eligible, should not increment lookup counter. --echo # Eligible, should not increment lookup counter.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('b', 8); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Eligible, should not increment lookup counter. --echo # Eligible, should not increment lookup counter.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('c', 24); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Should increment lookup counter. --echo # Should increment lookup counter.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
select id, bigfield from prefixinno where bigfield = repeat('z', 128); 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched; select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # Disable optimization, confirm we still increment counter. --echo # Disable optimization, confirm we still increment counter.
--let $base_count = query_get_value($show_count_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) let $base_opt = query_get_value($show_opt_statement, Value, 1);
set global innodb_prefix_index_cluster_optimization = OFF; set global innodb_prefix_index_cluster_optimization = OFF;
select id, bigfield from prefixinno where fake_id = 1033; 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; eval select $count - $base_count into @cluster_lookups;
select @cluster_lookups = 1 as cluster_lookups_matched; eval select $opt - $base_opt into @cluster_lookups_avoided;
--let $opt = query_get_value($show_opt_statement, Value, 1) --enable_query_log
eval select $opt - $base_opt into @cluster_lookups;
select @cluster_lookups = 0 as cluster_lookups_avoided_matched;
select @cluster_lookups;
select @cluster_lookups_avoided;
--echo # make test suite happy by cleaning up our mess
drop table prefixinno; 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; set global innodb_prefix_index_cluster_optimization = OFF;

View File

@ -723,6 +723,29 @@ INSERT INTO t1 VALUES ('10:10:10'),('10:20:30');
SELECT MAX(a), MAX(COALESCE(a)) FROM t1; SELECT MAX(a), MAX(COALESCE(a)) FROM t1;
DROP TABLE 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 #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@ -179,19 +179,21 @@ bool Item::get_time_with_conversion(THD *thd, MYSQL_TIME *ltime,
- truncate the YYYYMMDD part - truncate the YYYYMMDD part
- add (MM*33+DD)*24 to hours - add (MM*33+DD)*24 to hours
- add (MM*31+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 Note, If we start to use this method in more pieces of the code other
than eqial field propagation, we should probably return than equal field propagation, we should probably return
NULL only if some flag in fuzzydate is set. TRUE only if some flag in fuzzydate is set.
*/ */
return (null_value= true); return true;
} }
if (datetime_to_time_with_warn(thd, ltime, &ltime2, TIME_SECOND_PART_DIGITS)) if (datetime_to_time_with_warn(thd, ltime, &ltime2, TIME_SECOND_PART_DIGITS))
{ {
/* /*
Time difference between CURRENT_DATE and ltime If the time difference between CURRENT_DATE and ltime
did not fit into the supported TIME range 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); return (null_value= true);
} }
*ltime= ltime2; *ltime= ltime2;

View File

@ -1383,6 +1383,13 @@ public:
{ {
value_res= item->val_str(&value); value_res= item->val_str(&value);
m_null_value= item->null_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) int cmp(Item *arg)
{ {

View File

@ -5726,11 +5726,15 @@ public:
sent by the user (ie: stored procedure). sent by the user (ie: stored procedure).
*/ */
#define CF_SKIP_QUESTIONS (1U << 1) #define CF_SKIP_QUESTIONS (1U << 1)
#ifdef WITH_WSREP
/** /**
Do not check that wsrep snapshot is ready before allowing this command Do not check that wsrep snapshot is ready before allowing this command
*/ */
#define CF_SKIP_WSREP_CHECK (1U << 2) #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 Do not allow it for COM_MULTI batch
*/ */

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. /* 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 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 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_SHUTDOWN]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_SLEEP]= 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_TIME]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_INIT_DB]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_END]= 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++) 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_QUERY]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_SET_OPTION]= 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_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_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_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_EXECUTE]= 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 #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)
{
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)
{ {
my_message(ER_UNKNOWN_COM_ERROR,
"WSREP has not yet prepared node for application use",
MYF(0));
return false; return false;
} }
return true; has_tables = true;
} }
#endif return has_tables;
}
#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
/** /**
Read one command from connection and execute it (query or simple command). 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. Bail out if DB snapshot has not been installed.
*/ */
if (!(server_command_flags[command] & CF_SKIP_WSREP_CHECK) && if (thd->variables.wsrep_on && !thd->wsrep_applier &&
!wsrep_node_is_ready(thd)) (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) &&
(server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0)
{ {
thd->protocol->end_statement(); thd->protocol->end_statement();
@ -3143,21 +3154,24 @@ mysql_execute_command(THD *thd)
} }
/* /*
Bail out if DB snapshot has not been installed. SET and SHOW commands, * Bail out if DB snapshot has not been installed. We however,
however, are always allowed. * allow SET and SHOW queries and reads from information schema
Select query is also allowed if it does not access any table. * and dirty reads (if configured)
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 && if (thd->variables.wsrep_on &&
!wsrep_is_show_query(lex->sql_command) && !thd->wsrep_applier &&
!(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) &&
!(thd->variables.wsrep_dirty_reads && !(thd->variables.wsrep_dirty_reads &&
!is_update_query(lex->sql_command)) && (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) &&
!(lex->sql_command == SQLCOM_SELECT && !wsrep_tables_accessible_when_detached(all_tables) &&
!all_tables) && lex->sql_command != SQLCOM_SET_OPTION &&
!wsrep_node_is_ready(thd)) !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; goto error;
} }
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
status_var_increment(thd->status_var.com_stat[lex->sql_command]); status_var_increment(thd->status_var.com_stat[lex->sql_command]);
thd->progress.report_to_client= MY_TEST(sql_command_flags[lex->sql_command] & thd->progress.report_to_client= MY_TEST(sql_command_flags[lex->sql_command] &

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates. /* 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 it under the terms of the GNU General Public License as published by
@ -5077,6 +5077,14 @@ static Sys_var_mybool Sys_wsrep_desync (
ON_CHECK(wsrep_desync_check), ON_CHECK(wsrep_desync_check),
ON_UPDATE(wsrep_desync_update)); 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[]= static const char *wsrep_binlog_format_names[]=
{"MIXED", "STATEMENT", "ROW", "NONE", NullS}; {"MIXED", "STATEMENT", "ROW", "NONE", NullS};
static Sys_var_enum Sys_wsrep_forced_binlog_format( static Sys_var_enum Sys_wsrep_forced_binlog_format(

View File

@ -80,6 +80,7 @@ extern const char* wsrep_notify_cmd;
extern long wsrep_max_protocol_version; extern long wsrep_max_protocol_version;
extern ulong wsrep_forced_binlog_format; extern ulong wsrep_forced_binlog_format;
extern my_bool wsrep_desync; extern my_bool wsrep_desync;
extern ulong wsrep_reject_queries;
extern my_bool wsrep_replicate_myisam; extern my_bool wsrep_replicate_myisam;
extern ulong wsrep_mysql_replication_bundle; extern ulong wsrep_mysql_replication_bundle;
extern my_bool wsrep_restart_slave; extern my_bool wsrep_restart_slave;
@ -91,6 +92,12 @@ extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode; extern bool wsrep_gtid_mode;
extern uint32 wsrep_gtid_domain_id; 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 { enum enum_wsrep_OSU_method {
WSREP_OSU_TOI, WSREP_OSU_TOI,
WSREP_OSU_RSU, WSREP_OSU_RSU,

View File

@ -26,6 +26,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
ulong wsrep_reject_queries;
static long wsrep_prev_slave_threads = wsrep_slave_threads; 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; 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) static int wsrep_cluster_address_verify (const char* cluster_address_str)
{ {
/* There is no predefined address format, it depends on provider. */ /* There is no predefined address format, it depends on provider. */

View File

@ -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_check CHECK_ARGS;
extern bool wsrep_max_ws_size_update UPDATE_ARGS; extern bool wsrep_max_ws_size_update UPDATE_ARGS;
extern bool wsrep_reject_queries_update UPDATE_ARGS;
#else /* WITH_WSREP */ #else /* WITH_WSREP */

View File

@ -275,7 +275,20 @@ buf_dump(
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s", buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s",
full_filename); 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) { if (f == NULL) {
buf_dump_status(STATUS_ERR, buf_dump_status(STATUS_ERR,
"Cannot open '%s' for writing: %s", "Cannot open '%s' for writing: %s",

View File

@ -2255,7 +2255,7 @@ AIO::is_linux_native_aio_supported()
strcpy(name + dirnamelen, "ib_logfile0"); strcpy(name + dirnamelen, "ib_logfile0");
fd = open(name, O_RDONLY); fd = open(name, O_RDONLY | O_CLOEXEC);
if (fd == -1) { if (fd == -1) {

View File

@ -2915,7 +2915,9 @@ row_sel_field_store_in_mysql_format_func(
|| !(templ->mysql_col_len % templ->mbmaxlen)); || !(templ->mysql_col_len % templ->mbmaxlen));
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|| (field_no == templ->icp_rec_field_no || (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 ut_ad(templ->is_virtual
|| !(field->prefix_len % templ->mbmaxlen)); || !(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. /** Searches for rows in the database using cursor.
Function is mainly used for tables that are shared across connections and Function is mainly used for tables that are shared across connections and
so it employs technique that can help re-construct the rows that so it employs technique that can help re-construct the rows that
@ -4120,7 +4234,6 @@ row_search_mvcc(
ulint* offsets = offsets_; ulint* offsets = offsets_;
ibool table_lock_waited = FALSE; ibool table_lock_waited = FALSE;
byte* next_buf = 0; byte* next_buf = 0;
ibool use_clustered_index = FALSE;
bool spatial_search = false; bool spatial_search = false;
rec_offs_init(offsets_); rec_offs_init(offsets_);
@ -5179,69 +5292,10 @@ locks_ok_del_marked:
break; break;
} }
/* Get the clustered index record if needed, if we did not do the if (index != clust_index && prebuilt->need_to_access_clustered) {
search using the clustered index... */ if (row_search_with_covering_prefix(prebuilt, rec, offsets)) {
goto use_covering_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 (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: requires_clust_rec:
ut_ad(index != clust_index); ut_ad(index != clust_index);
/* We use a 'goto' to the preceding label if a consistent /* We use a 'goto' to the preceding label if a consistent
@ -5339,6 +5393,7 @@ requires_clust_rec:
} }
} }
} else { } else {
use_covering_index:
result_rec = rec; result_rec = rec;
} }

View File

@ -29,6 +29,10 @@
#endif #endif
#ifdef HAVE_ORACLE_OCI #ifdef HAVE_ORACLE_OCI
#if (defined(WIN32) || defined(_WIN32) || defined(WINDOWS) || defined(_WINDOWS))
#include <Shlwapi.h>
#define strcasestr StrStr
#endif
#include <oci.h> #include <oci.h>
#include "spd_err.h" #include "spd_err.h"
#include "spd_param.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_conv_charset =
(Item_func_conv_charset *)item_func; (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); uint cset_length = strlen(conv_charset->csname);
if (str->reserve(SPIDER_SQL_USING_LEN + cset_length)) if (str->reserve(SPIDER_SQL_USING_LEN + cset_length))
DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(HA_ERR_OUT_OF_MEM);

View File

@ -371,6 +371,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn(
if (direct_sql->access_mode == 0) if (direct_sql->access_mode == 0)
{ {
#endif #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 *) if (!(conn = (SPIDER_CONN *)
spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL), spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL),
&conn, sizeof(*conn), &conn, sizeof(*conn),
@ -398,6 +406,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn(
conn->default_database.init_calc_mem(138); conn->default_database.init_calc_mem(138);
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
} else { } 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 *) if (!(conn = (SPIDER_CONN *)
spider_bulk_malloc(spider_current_trx, 33, MYF(MY_WME | MY_ZEROFILL), spider_bulk_malloc(spider_current_trx, 33, MYF(MY_WME | MY_ZEROFILL),
&conn, sizeof(*conn), &conn, sizeof(*conn),

View File

@ -10,7 +10,7 @@ col3 smallint(5) NOT NULL DEFAULT '1',
filler varchar(255) DEFAULT NULL, filler varchar(255) DEFAULT NULL,
KEY pk_ersatz(col1,col2,col3), KEY pk_ersatz(col1,col2,col3),
KEY key1 (col1,col2) USING BTREE 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 1300000000+a, 12345, 7890, 'data' from t2;
insert into t3 select 1400000000+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; insert into t3 select 1410799999+a, 12345, 7890, 'data' from t2;
@ -34,7 +34,7 @@ from t3
where col1 <= 1410799999 where col1 <= 1410799999
order by col1 desc,col2 desc,col3 desc limit 1; order by col1 desc,col2 desc,col3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra 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 same query but the constant is bigger.
# The query should use range(PRIMARY), not full index scan: # The query should use range(PRIMARY), not full index scan:
explain explain
@ -43,5 +43,5 @@ from t3
where col1 <= 1412199999 where col1 <= 1412199999
order by col1 desc, col2 desc, col3 desc limit 1; order by col1 desc, col2 desc, col3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra 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; drop table t1,t2,t3;

View File

@ -15,7 +15,7 @@ CREATE TABLE t3 (
filler varchar(255) DEFAULT NULL, filler varchar(255) DEFAULT NULL,
KEY pk_ersatz(col1,col2,col3), KEY pk_ersatz(col1,col2,col3),
KEY key1 (col1,col2) USING BTREE 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 1300000000+a, 12345, 7890, 'data' from t2;
insert into t3 select 1400000000+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; insert into t3 select 1412199999+a, 12345, 7890, 'data' from t2;
--echo # The following must use range(PRIMARY): --echo # The following must use range(PRIMARY):
--replace_column 9 #
explain explain
select col1,col2,col3 select col1,col2,col3
from t3 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 same query but the constant is bigger.
--echo # The query should use range(PRIMARY), not full index scan: --echo # The query should use range(PRIMARY), not full index scan:
--replace_column 9 #
explain explain
select col1,col2,col3 select col1,col2,col3
from t3 from t3

View File

@ -216,7 +216,20 @@ buf_dump(
buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s", buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s",
full_filename); 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) { if (f == NULL) {
buf_dump_status(STATUS_ERR, buf_dump_status(STATUS_ERR,
"Cannot open '%s' for writing: %s", "Cannot open '%s' for writing: %s",

View File

@ -3685,6 +3685,117 @@ row_search_idx_cond_check(
return(result); 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 Searches for rows in the database. This is used in the interface to
MySQL. This function opens a cursor, and also implements fetch next MySQL. This function opens a cursor, and also implements fetch next
@ -3748,7 +3859,6 @@ row_search_for_mysql(
ulint* offsets = offsets_; ulint* offsets = offsets_;
ibool table_lock_waited = FALSE; ibool table_lock_waited = FALSE;
byte* next_buf = 0; byte* next_buf = 0;
bool use_clustered_index = false;
rec_offs_init(offsets_); rec_offs_init(offsets_);
@ -4810,71 +4920,10 @@ locks_ok:
break; break;
} }
/* Get the clustered index record if needed, if we did not do the if (index != clust_index && prebuilt->need_to_access_clustered) {
search using the clustered index... */ if (row_search_with_covering_prefix(prebuilt, rec, offsets)) {
goto use_covering_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 (use_clustered_index) {
requires_clust_rec: requires_clust_rec:
ut_ad(index != clust_index); ut_ad(index != clust_index);
/* We use a 'goto' to the preceding label if a consistent /* We use a 'goto' to the preceding label if a consistent
@ -4960,6 +5009,7 @@ requires_clust_rec:
} }
} }
} else { } else {
use_covering_index:
result_rec = rec; result_rec = rec;
} }