[MDEV-10475] Range instead of ref access is used for BETWEEN Created: 2016-08-01  Updated: 2023-04-27

Status: Open
Project: MariaDB Server
Component/s: Optimizer
Affects Version/s: 5.5, 10.0, 10.1, 10.2
Fix Version/s: 10.4

Type: Bug Priority: Major
Reporter: Alexander Barkov Assignee: Alexander Barkov
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This script:

DROP TABLE IF EXISTS t1;
SET NAMES utf8, collation_connection=utf8_general_ci;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8, b INT NOT NULL DEFAULT 0, key(a));
INSERT INTO t1 (a) VALUES ('a'),('b'),('c'),('d'),('¢');
EXPLAIN SELECT * FROM t1 WHERE a BETWEEN _utf8'¢' and '¢';

returns

+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                 |
+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
|    1 | SIMPLE      | t1    | ref  | a             | a    | 33      | const |    1 | Using index condition |
+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+

It's using "ref" access. Looks good so far.

Now if I change the session collation to utf8_swedish_ci:

DROP TABLE IF EXISTS t1;
SET NAMES utf8, collation_connection=utf8_swedish_ci;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8, b INT NOT NULL DEFAULT 0, key(a));
INSERT INTO t1 (a) VALUES ('a'),('b'),('c'),('d'),('¢');
EXPLAIN SELECT * FROM t1 WHERE a BETWEEN _utf8'¢' and '¢';

It returns:

+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
| id   | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                 |
+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
|    1 | SIMPLE      | t1    | range | a             | a    | 33      | NULL |    1 | Using index condition |
+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+

Notice, it's now using "range" instead of "ref" access. This looks wrong. The value of @@collation_connection should not be important here, because the comparison operation should be done according to the collation of the field "a", which is utf8_general_ci.



 Comments   
Comment by Alexander Barkov [ 2016-08-01 ]

The same problem is repeatable with prepared statements.
This script:

DROP TABLE IF EXISTS t1;
SET NAMES utf8, collation_connection=utf8_general_ci;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8, b INT NOT NULL DEFAULT 0, key(a));
INSERT INTO t1 (a) VALUES ('a'),('b'),('c'),('d'),('¢');
SET @arg='¢';
PREPARE stmt FROM "EXPLAIN SELECT * FROM t1 WHERE a BETWEEN _utf8'¢' and ?";
EXECUTE stmt USING @arg;

returns:

+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                 |
+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
|    1 | SIMPLE      | t1    | ref  | a             | a    | 33      | const |    1 | Using index condition |
+------+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+

This script:

DROP TABLE IF EXISTS t1;
SET NAMES utf8, collation_connection=utf8_swedish_ci;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8, b INT NOT NULL DEFAULT 0, key(a));
INSERT INTO t1 (a) VALUES ('a'),('b'),('c'),('d'),('¢');
SET @arg='¢';
PREPARE stmt FROM "EXPLAIN SELECT * FROM t1 WHERE a BETWEEN _utf8'¢' and ?";
EXECUTE stmt USING @arg;

returns

+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
| id   | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                 |
+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
|    1 | SIMPLE      | t1    | range | a             | a    | 33      | NULL |    1 | Using index condition |
+------+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+

Generated at Thu Feb 08 07:42:30 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.