Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions mysql-test/main/range.result
Original file line number Diff line number Diff line change
Expand Up @@ -3755,6 +3755,53 @@ id key1
3 2
drop table t1;
#
# MDEV-39323: CROSS JOIN query returns wrong result with NOT BETWEEN
#
CREATE TABLE t1 (
c0 float DEFAULT NULL,
c1 mediumint DEFAULT NULL,
c2 int DEFAULT NULL,
UNIQUE KEY c0 (c0),
UNIQUE KEY c2 (c2),
KEY i0 (c2, c1, c0),
KEY i1 (c2),
KEY i2 (c1)
);
INSERT INTO t1 VALUES
(567621000, -8388608, NULL),
(0.363988, 0, -1643936528),
(-422810000, 0, NULL),
(0, 0, 0),
(NULL, 0, NULL),
(NULL, 8388607, NULL),
(NULL, -8388608, NULL);
CREATE TABLE t2 (c0 decimal(10,0) unsigned DEFAULT NULL);
INSERT INTO t2 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT t1.c0, t1.c1, t1.c2 FROM t2 CROSS JOIN t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
c0 c1 c2
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
SELECT t1.c0, t1.c1, t1.c2 FROM t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
c0 c1 c2
0 0 0
SELECT c0, c2 FROM t1 WHERE NOT (1 BETWEEN c0 AND c2);
c0 c2
0 0
0.363988 -1643936528
567621000 NULL
SELECT c0, c2 FROM t1 WHERE 1 NOT BETWEEN c0 AND c2;
c0 c2
0 0
0.363988 -1643936528
567621000 NULL
DROP TABLE t1, t2;
#
# End of 10.11 tests
#
set global innodb_stats_persistent= @innodb_stats_persistent_save;
Expand Down
35 changes: 35 additions & 0 deletions mysql-test/main/range.test
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,41 @@ evalp $query;

drop table t1;

--echo #
--echo # MDEV-39323: CROSS JOIN query returns wrong result with NOT BETWEEN
--echo #
CREATE TABLE t1 (
c0 float DEFAULT NULL,
c1 mediumint DEFAULT NULL,
c2 int DEFAULT NULL,
UNIQUE KEY c0 (c0),
UNIQUE KEY c2 (c2),
KEY i0 (c2, c1, c0),
KEY i1 (c2),
KEY i2 (c1)
);
INSERT INTO t1 VALUES
(567621000, -8388608, NULL),
(0.363988, 0, -1643936528),
(-422810000, 0, NULL),
(0, 0, 0),
(NULL, 0, NULL),
(NULL, 8388607, NULL),
(NULL, -8388608, NULL);
CREATE TABLE t2 (c0 decimal(10,0) unsigned DEFAULT NULL);
INSERT INTO t2 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);

SELECT t1.c0, t1.c1, t1.c2 FROM t2 CROSS JOIN t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
SELECT t1.c0, t1.c1, t1.c2 FROM t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
--sorted_result
SELECT c0, c2 FROM t1 WHERE NOT (1 BETWEEN c0 AND c2);
--sorted_result
SELECT c0, c2 FROM t1 WHERE 1 NOT BETWEEN c0 AND c2;

DROP TABLE t1, t2;

--echo #
--echo # End of 10.11 tests
--echo #
Expand Down
47 changes: 47 additions & 0 deletions mysql-test/main/range_mrr_icp.result
Original file line number Diff line number Diff line change
Expand Up @@ -3744,6 +3744,53 @@ id key1
3 2
drop table t1;
#
# MDEV-39323: CROSS JOIN query returns wrong result with NOT BETWEEN
#
CREATE TABLE t1 (
c0 float DEFAULT NULL,
c1 mediumint DEFAULT NULL,
c2 int DEFAULT NULL,
UNIQUE KEY c0 (c0),
UNIQUE KEY c2 (c2),
KEY i0 (c2, c1, c0),
KEY i1 (c2),
KEY i2 (c1)
);
INSERT INTO t1 VALUES
(567621000, -8388608, NULL),
(0.363988, 0, -1643936528),
(-422810000, 0, NULL),
(0, 0, 0),
(NULL, 0, NULL),
(NULL, 8388607, NULL),
(NULL, -8388608, NULL);
CREATE TABLE t2 (c0 decimal(10,0) unsigned DEFAULT NULL);
INSERT INTO t2 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT t1.c0, t1.c1, t1.c2 FROM t2 CROSS JOIN t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
c0 c1 c2
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
SELECT t1.c0, t1.c1, t1.c2 FROM t1
WHERE NOT (1 BETWEEN t1.c0 AND t1.c2) AND t1.c1 = t1.c2;
c0 c1 c2
0 0 0
SELECT c0, c2 FROM t1 WHERE NOT (1 BETWEEN c0 AND c2);
c0 c2
0 0
0.363988 -1643936528
567621000 NULL
SELECT c0, c2 FROM t1 WHERE 1 NOT BETWEEN c0 AND c2;
c0 c2
0 0
0.363988 -1643936528
567621000 NULL
DROP TABLE t1, t2;
#
# End of 10.11 tests
#
set global innodb_stats_persistent= @innodb_stats_persistent_save;
Expand Down
22 changes: 22 additions & 0 deletions sql/opt_range.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8621,6 +8621,9 @@ SEL_TREE *Item::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
}


/*
Disallow range creation when BETWEEN arguments' types don't match.
*/
bool
Item_func_between::can_optimize_range_const(Item_field *field_item) const
{
Expand Down Expand Up @@ -8660,7 +8663,26 @@ Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{
Item_field *field_item= (Item_field*) (arguments()[i]->real_item());
if (!can_optimize_range_const(field_item))
{
/*
For NOT BETWEEN the resulting tree is the OR of one tree per
NOT BETWEEN argument. Skipping a disjunct here is wrong
because the remaining tree wouldn't scan all rows that satisfy
the NOT BETWEEN. So bail here to avoid building a bad range.
*/
if (negated)
{
tree= nullptr;
break;
}

/*
For BETWEEN, dropping a conjunct is fine because the
remaining tree is a superset of matching rows and the WHERE
clause will filter any extra rows out.
*/
continue;
}
SEL_TREE *tmp= get_full_func_mm_tree(param, field_item,
(Item*)(intptr) i);
if (negated)
Expand Down