Skip to content

Commit 15ef38d

Browse files
committed
MDEV-10228: Delete missing rows with OR conditions
Fix get_quick_keys(): When building range tree from a condition in form keypart1=const AND (keypart2 < 0 OR keypart2>=0) the SEL_ARG for keypart2 represents an interval (-inf, +inf). However, the logic that sets UNIQUE_RANGE flag fails to recognize this, and sets UNIQUE_RANGE flag if (keypart1, keypart2) covered a unique key. As a result, range access executor assumes the interval can have at most one row and only reads the first row from it.
1 parent 1b5da2c commit 15ef38d

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

mysql-test/r/range.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,3 +2113,34 @@ a b
21132113
0 0
21142114
1 1
21152115
drop table t2;
2116+
#
2117+
# MDEV-10228: Delete missing rows with OR conditions
2118+
# (The example uses UPDATE, because UPDATE allows to use index hints
2119+
# and so it's possible to make an example that works with any storage
2120+
# engine)
2121+
#
2122+
CREATE TABLE t1 (
2123+
key1varchar varchar(14) NOT NULL,
2124+
key2int int(11) NOT NULL DEFAULT '0',
2125+
col1 int,
2126+
PRIMARY KEY (key1varchar,key2int),
2127+
KEY key1varchar (key1varchar),
2128+
KEY key2int (key2int)
2129+
) DEFAULT CHARSET=utf8;
2130+
insert into t1 values
2131+
('value1',0, 0),
2132+
('value1',1, 0),
2133+
('value1',1000685, 0),
2134+
('value1',1003560, 0),
2135+
('value1',1004807, 0);
2136+
update t1 force index (PRIMARY) set col1=12345
2137+
where (key1varchar='value1' AND (key2int <=1 OR key2int > 1));
2138+
# The following must show col1=12345 for all rows:
2139+
select * from t1;
2140+
key1varchar key2int col1
2141+
value1 0 12345
2142+
value1 1 12345
2143+
value1 1000685 12345
2144+
value1 1003560 12345
2145+
value1 1004807 12345
2146+
drop table t1;

mysql-test/t/range.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,3 +1689,32 @@ insert into t2 values (0, 0, 0, 0), (1, 1, 1, 1);
16891689
analyze table t2;
16901690
select a, b from t2 where (a, b) in ((0, 0), (1, 1));
16911691
drop table t2;
1692+
1693+
--echo #
1694+
--echo # MDEV-10228: Delete missing rows with OR conditions
1695+
--echo # (The example uses UPDATE, because UPDATE allows to use index hints
1696+
--echo # and so it's possible to make an example that works with any storage
1697+
--echo # engine)
1698+
--echo #
1699+
1700+
CREATE TABLE t1 (
1701+
key1varchar varchar(14) NOT NULL,
1702+
key2int int(11) NOT NULL DEFAULT '0',
1703+
col1 int,
1704+
PRIMARY KEY (key1varchar,key2int),
1705+
KEY key1varchar (key1varchar),
1706+
KEY key2int (key2int)
1707+
) DEFAULT CHARSET=utf8;
1708+
1709+
insert into t1 values
1710+
('value1',0, 0),
1711+
('value1',1, 0),
1712+
('value1',1000685, 0),
1713+
('value1',1003560, 0),
1714+
('value1',1004807, 0);
1715+
1716+
update t1 force index (PRIMARY) set col1=12345
1717+
where (key1varchar='value1' AND (key2int <=1 OR key2int > 1));
1718+
--echo # The following must show col1=12345 for all rows:
1719+
select * from t1;
1720+
drop table t1;

sql/opt_range.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10409,8 +10409,10 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
1040910409
KEY *table_key=quick->head->key_info+quick->index;
1041010410
flag=EQ_RANGE;
1041110411
if ((table_key->flags & HA_NOSAME) &&
10412+
min_part == key_tree->part &&
1041210413
key_tree->part == table_key->key_parts-1)
1041310414
{
10415+
DBUG_ASSERT(min_part == max_part);
1041410416
if ((table_key->flags & HA_NULL_PART_KEY) &&
1041510417
null_part_in_key(key,
1041610418
param->min_key,

0 commit comments

Comments
 (0)