1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

MDEV-36235 Incorrect result for BETWEEN over unique blob prefix

Disallow range optimization for BETWEEN when casting one of the arguments
from STRING to a numeric type would be required to construct a range for
the query.

Adds a new method on Item_func_between called can_optimize_range_const
which allows range optimization when the types of the arguments to BETWEEN
would permit it.
This commit is contained in:
Dave Gosselin
2025-04-09 13:57:09 -04:00
committed by Dave Gosselin
parent 07b442aa68
commit 15fd232da4
10 changed files with 450 additions and 25 deletions

View File

@@ -397,3 +397,61 @@ indexed_col not_indexed_col
DROP TABLE t2;
DROP TABLE t1;
SET note_verbosity=DEFAULT;
#
# MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
#
CREATE TABLE t1 (c1 BINARY(16), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2);
SELECT HEX(c1) FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
HEX(c1)
31000000000000000000000000000000
32000000000000000000000000000000
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '-2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
SELECT HEX(c1) FROM t1 IGNORE KEY(c1) WHERE 'a' BETWEEN 0 AND (c1);
HEX(c1)
31000000000000000000000000000000
32000000000000000000000000000000
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '-2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: '2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
SELECT HEX(c1) FROM t1 WHERE '#' BETWEEN c1 AND 0;
HEX(c1)
2D310000000000000000000000000000
2D320000000000000000000000000000
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '-2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
SELECT HEX(c1) FROM t1 IGNORE KEY(c1) WHERE '#' BETWEEN c1 AND 0;
HEX(c1)
2D320000000000000000000000000000
2D310000000000000000000000000000
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '-2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
DROP TABLE t1;

View File

@@ -178,3 +178,14 @@ DELIMITER ;$$
--source unusable_keys_joins.inc
DROP TABLE t1;
SET note_verbosity=DEFAULT;
--echo #
--echo # MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
--echo #
CREATE TABLE t1 (c1 BINARY(16), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2);
SELECT HEX(c1) FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT HEX(c1) FROM t1 IGNORE KEY(c1) WHERE 'a' BETWEEN 0 AND (c1);
SELECT HEX(c1) FROM t1 WHERE '#' BETWEEN c1 AND 0;
SELECT HEX(c1) FROM t1 IGNORE KEY(c1) WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;

View File

@@ -1419,3 +1419,193 @@ Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten c
DROP TABLE t2;
DROP TABLE t1;
SET note_verbosity=DEFAULT;
#
# MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
#
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=myisam;
INSERT INTO t1 (c1) VALUES (1);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2)));
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE 3 BETWEEN 10*POW(-1,c1) AND (c1);
c1
3
5
SELECT c1 FROM t1 WHERE 'a' BETWEEN 10*POW(-1,c1) AND (c1);
c1
1
3
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=myisam;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB NOT NULL);
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=innodb;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
ALTER TABLE t1 engine=myisam;
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1)) engine=innodb;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
3
4
5
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
DROP TABLE t1;

View File

@@ -808,3 +808,48 @@ DELIMITER ;$$
--source unusable_keys_joins.inc
DROP TABLE t1;
SET note_verbosity=DEFAULT;
--echo #
--echo # MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
--echo #
# myisam has a special optimization for tables with one row
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=myisam;
INSERT INTO t1 (c1) VALUES (1);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
DROP TABLE t1;
# This case shows that we don't transform the entire WHERE clause
# into a range condition.
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2)));
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE 3 BETWEEN 10*POW(-1,c1) AND (c1);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 10*POW(-1,c1) AND (c1);
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=myisam;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB NOT NULL);
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1(2))) engine=innodb;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
ALTER TABLE t1 engine=myisam;
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;
CREATE TABLE t1 (c1 TINYBLOB, UNIQUE (c1)) engine=innodb;
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2),(3),(4),(5);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;

View File

@@ -0,0 +1,42 @@
#
# MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
#
CREATE TABLE t1 (c1 VARBINARY(10), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 IGNORE KEY(c1) WHERE 'a' BETWEEN 0 AND (c1);
c1
1
2
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
c1
-1
-2
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
SELECT c1 FROM t1 IGNORE KEY(c1) WHERE '#' BETWEEN c1 AND 0;
c1
-2
-1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
Warning 1292 Truncated incorrect DECIMAL value: '#'
DROP TABLE t1;

View File

@@ -0,0 +1,10 @@
--echo #
--echo # MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
--echo #
CREATE TABLE t1 (c1 VARBINARY(10), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (-2),(-1),(1),(2);
SELECT c1 FROM t1 WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 IGNORE KEY(c1) WHERE 'a' BETWEEN 0 AND (c1);
SELECT c1 FROM t1 WHERE '#' BETWEEN c1 AND 0;
SELECT c1 FROM t1 IGNORE KEY(c1) WHERE '#' BETWEEN c1 AND 0;
DROP TABLE t1;

View File

@@ -2407,3 +2407,26 @@ f::f
DROP TABLE t1;
SET max_sort_length=DEFAULT;
# End of 10.8 tests
#
# MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
#
CREATE OR REPLACE TABLE t1 (c1 BINARY(16), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (0x00000000000000000000000000000001);
INSERT INTO t1 (c1) VALUES (0x00000000000000000000000000000002);
SELECT CAST(c1 AS INET6) FROM t1 WHERE '::1' BETWEEN CAST('::1' AS INET6) AND c1;
CAST(c1 AS INET6)
::1
::2
SELECT CAST(c1 AS INET6) FROM t1 IGNORE KEY(c1) WHERE '::1' BETWEEN CAST('::1' AS INET6) AND c1;
CAST(c1 AS INET6)
::1
::2
SELECT CAST(c1 AS INET6) FROM t1 WHERE '::2' BETWEEN c1 AND CAST('::2' AS INET6);
CAST(c1 AS INET6)
::1
::2
SELECT CAST(c1 AS INET6) FROM t1 IGNORE KEY(c1) WHERE '::2' BETWEEN c1 AND CAST('::2' AS INET6);
CAST(c1 AS INET6)
::1
::2
DROP TABLE t1;

View File

@@ -1741,3 +1741,15 @@ DROP TABLE t1;
SET max_sort_length=DEFAULT;
--echo # End of 10.8 tests
--echo #
--echo # MDEV-36235 Incorrect result for BETWEEN over unique blob prefix
--echo #
CREATE OR REPLACE TABLE t1 (c1 BINARY(16), UNIQUE (c1));
INSERT INTO t1 (c1) VALUES (0x00000000000000000000000000000001);
INSERT INTO t1 (c1) VALUES (0x00000000000000000000000000000002);
SELECT CAST(c1 AS INET6) FROM t1 WHERE '::1' BETWEEN CAST('::1' AS INET6) AND c1;
SELECT CAST(c1 AS INET6) FROM t1 IGNORE KEY(c1) WHERE '::1' BETWEEN CAST('::1' AS INET6) AND c1;
SELECT CAST(c1 AS INET6) FROM t1 WHERE '::2' BETWEEN c1 AND CAST('::2' AS INET6);
SELECT CAST(c1 AS INET6) FROM t1 IGNORE KEY(c1) WHERE '::2' BETWEEN c1 AND CAST('::2' AS INET6);
DROP TABLE t1;

View File

@@ -1003,6 +1003,23 @@ public:
class Item_func_between :public Item_func_opt_neg
{
/*
If the types of the arguments to BETWEEN permit, then:
WHERE const1 BETWEEN expr2 AND field1
can be optimized as if it was just:
WHERE const1 <= field1
as expr2 could be an arbitrary expression. More generally,
this optimization is permitted if aggregation for comparison
for three expressions (const1,const2,field1) and for two
expressions (const1,field1) return the same type handler.
@param [IN] field_item - This is a field from the right side
of the BETWEEN operator.
*/
bool can_optimize_range_const(Item_field *field_item) const;
protected:
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *value) override;

View File

@@ -8364,9 +8364,9 @@ SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param,
(makes sense only when cond_func is BETWEEN or IN)
DESCRIPTION
For a simple SARGable predicate of the form (f op c), where f is a field and
c is a constant, the function builds a conjunction of all SEL_TREES that can
be obtained by the substitution of f for all different fields equal to f.
For a simple SARGable predicate of the form (f op c), where f is a field
and c is a constant, the function builds a conjunction of all SEL_TREES that
can be obtained by the substitution of f for all different fields equal to f.
NOTES
If the WHERE condition contains a predicate (fi op c),
@@ -8379,24 +8379,26 @@ SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param,
and
a SEL_TREE for t1.a > 10 will be built for quick select from t1.
A BETWEEN predicate of the form (fi [NOT] BETWEEN c1 AND c2) is treated
in a similar way: we build a conjuction of trees for the results
of all substitutions of fi for equal fj.
A BETWEEN predicate of the form (fi [NOT] BETWEEN c1 AND c2), where fi
is some field, is treated in a similar way: we build a conjuction of
trees for the results of all substitutions of fi equal fj.
Yet a predicate of the form (c BETWEEN f1i AND f2i) is processed
differently. It is considered as a conjuction of two SARGable
predicates (f1i <= c) and (f2i <=c) and the function get_full_func_mm_tree
predicates (f1i <= c) and (c <= f2i) and the function get_full_func_mm_tree
is called for each of them separately producing trees for
AND j (f1j <=c ) and AND j (f2j <= c)
AND j (f1j <= c) and AND j (c <= f2j)
After this these two trees are united in one conjunctive tree.
It's easy to see that the same tree is obtained for
AND j,k (f1j <=c AND f2k<=c)
AND j,k (f1j <= c AND c <= f2k)
which is equivalent to
AND j,k (c BETWEEN f1j AND f2k).
The validity of the processing of the predicate (c NOT BETWEEN f1i AND f2i)
which equivalent to (f1i > c OR f2i < c) is not so obvious. Here the
function get_full_func_mm_tree is called for (f1i > c) and (f2i < c)
producing trees for AND j (f1j > c) and AND j (f2j < c). Then this two
trees are united in one OR-tree. The expression
function get_full_func_mm_tree is called for (f1i > c) and called for
(f2i < c) producing trees for AND j (f1j > c) and AND j (f2j < c). Then
this two trees are united in one OR-tree. The expression
(AND j (f1j > c) OR AND j (f2j < c)
is equivalent to the expression
AND j,k (f1j > c OR f2k < c)
@@ -8623,6 +8625,19 @@ SEL_TREE *Item::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
}
bool
Item_func_between::can_optimize_range_const(Item_field *field_item) const
{
const Type_handler *fi_handler= field_item->type_handler_for_comparison();
Type_handler_hybrid_field_type cmp(fi_handler);
if (cmp.aggregate_for_comparison(args[0]->type_handler_for_comparison()) ||
cmp.type_handler() != m_comparator.type_handler())
return false; // Cannot optimize range because of type mismatch.
return true;
}
SEL_TREE *
Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{
@@ -8648,6 +8663,8 @@ Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
if (arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
{
Item_field *field_item= (Item_field*) (arguments()[i]->real_item());
if (!can_optimize_range_const(field_item))
continue;
SEL_TREE *tmp= get_full_func_mm_tree(param, field_item,
(Item*)(intptr) i);
if (negated)