Skip to content

Commit 5b459dd

Browse files
committed
Bug#32975221: 5.7.29+ REGRESSION, SPATIAL INDEX NOT USED
ANYMORE FOR MBRCONTAINS Description: ============ This is a regression from the fix for Bug#29770705. The fix introduced cloning of range tree for a special case when we have a predicate having an AND condition ("pred1 AND pred2") and one part of this AND condition is not a simple predicate(an OR condition - "pred2"). For such a case, we needed to clone the range tree created for "pred1". However, when we clone the range tree, we do not copy the "geometry flag" associated with the range tree. This results in ignoring the spatial index available to do the range scan. Fix === Copy the `rkey_func_flag` from original tree if GEOM_FLAG is set. On 8.0, this issue is not reproducible because the use_count handling is different and clone() is not invoked. However it is clear that for some case it might fail. So we need the changes, hence added the unit test for the same. Change-Id: I36312bc2c11db4e4e77d67e9443a98b37ade38e8
1 parent 7e64ad4 commit 5b459dd

File tree

4 files changed

+68
-7
lines changed

4 files changed

+68
-7
lines changed

mysql-test/r/gis.result

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,3 +3077,20 @@ ST_GeometryType(ST_GeomFromText('POINT(1 1)')) HOUR_SECOND;
30773077
'2010-10-10 10:10:10' + INTERVAL
30783078
ST_GeometryType(ST_GeomFromText('POINT(1 1)')) HOUR_SECOND
30793079
2010-10-10 10:10:10
3080+
#
3081+
# Bug #32975221 5.7.29+ REGRESSION, SPATIAL INDEX NOT USED ANYMORE FOR MBRCONTAINS
3082+
#
3083+
CREATE TABLE t (
3084+
c1 VARCHAR(8) NOT NULL,
3085+
c2 VARCHAR(16) NOT NULL,
3086+
geom POINT NOT NULL,
3087+
PRIMARY KEY (c2,c1),
3088+
SPATIAL KEY coord (geom)
3089+
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
3090+
INSERT INTO t VALUES (1, 2, POINT(1, 2));
3091+
EXPLAIN SELECT COUNT(*) FROM t WHERE MBRCONTAINS(ST_GEOMFROMTEXT('POLYGON((1 2, 2 2, 2 3, 1 2))'), geom) AND c1 <> '10';
3092+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
3093+
1 SIMPLE t NULL range coord coord 34 NULL ## ## Using where
3094+
Warnings:
3095+
Note 1003 /* select#1 */ select count(0) AS `COUNT(*)` from `test`.`t` where (mbrcontains(<cache>(st_geometryfromtext('POLYGON((1 2, 2 2, 2 3, 1 2))')),`test`.`t`.`geom`) and (`test`.`t`.`c1` <> '10'))
3096+
DROP TABLE t;

mysql-test/t/gis.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,3 +2868,21 @@ DROP TABLE d, dp, r;
28682868
SET collation_connection='utf32_bin';
28692869
SELECT '2010-10-10 10:10:10' + INTERVAL
28702870
ST_GeometryType(ST_GeomFromText('POINT(1 1)')) HOUR_SECOND;
2871+
2872+
--echo #
2873+
--echo # Bug #32975221 5.7.29+ REGRESSION, SPATIAL INDEX NOT USED ANYMORE FOR MBRCONTAINS
2874+
--echo #
2875+
2876+
CREATE TABLE t (
2877+
c1 VARCHAR(8) NOT NULL,
2878+
c2 VARCHAR(16) NOT NULL,
2879+
geom POINT NOT NULL,
2880+
PRIMARY KEY (c2,c1),
2881+
SPATIAL KEY coord (geom)
2882+
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
2883+
2884+
INSERT INTO t VALUES (1, 2, POINT(1, 2));
2885+
2886+
--replace_column 10 ## 11 ##
2887+
EXPLAIN SELECT COUNT(*) FROM t WHERE MBRCONTAINS(ST_GEOMFROMTEXT('POLYGON((1 2, 2 2, 2 3, 1 2))'), geom) AND c1 <> '10';
2888+
DROP TABLE t;

sql/opt_range.cc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ class SEL_ARG :public Sql_alloc
497497
SEL_ARG(SEL_ARG &);
498498
SEL_ARG(Field *,const uchar *, const uchar *);
499499
SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value,
500-
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
500+
uint8 min_flag, uint8 max_flag, uint8 maybe_flag,
501+
enum ha_rkey_function gis_func_flag);
501502
/*
502503
Used to construct MAYBE_KEY and IMPOSSIBLE SEL_ARGs. left and
503504
right is NULL, so this ctor must not be used to create other
@@ -582,18 +583,21 @@ class SEL_ARG :public Sql_alloc
582583
new_max=arg->max_value; flag_max=arg->max_flag;
583584
}
584585
return new (mem_root) SEL_ARG(field, part, new_min, new_max, flag_min, flag_max,
585-
MY_TEST(maybe_flag && arg->maybe_flag));
586+
MY_TEST(maybe_flag && arg->maybe_flag),
587+
flag_min & GEOM_FLAG ? rkey_func_flag : HA_READ_INVALID);
586588
}
587589
SEL_ARG *clone_first(SEL_ARG *arg, MEM_ROOT *mem_root)
588590
{ // min <= X < arg->min
589591
return new (mem_root) SEL_ARG(field,part, min_value, arg->min_value,
590592
min_flag, arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX,
591-
maybe_flag | arg->maybe_flag);
593+
maybe_flag | arg->maybe_flag,
594+
min_flag & GEOM_FLAG ? rkey_func_flag : HA_READ_INVALID);
592595
}
593596
SEL_ARG *clone_last(SEL_ARG *arg, MEM_ROOT *mem_root)
594597
{ // min <= X <= key_max
595598
return new (mem_root) SEL_ARG(field, part, min_value, arg->max_value,
596-
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
599+
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag,
600+
min_flag & GEOM_FLAG ? rkey_func_flag : HA_READ_INVALID);
597601
}
598602
SEL_ARG *clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next);
599603

@@ -2134,10 +2138,11 @@ SEL_ARG::SEL_ARG(Field *f,const uchar *min_value_arg,
21342138

21352139
SEL_ARG::SEL_ARG(Field *field_,uint8 part_,
21362140
uchar *min_value_, uchar *max_value_,
2137-
uint8 min_flag_,uint8 max_flag_,uint8 maybe_flag_)
2141+
uint8 min_flag_,uint8 max_flag_,uint8 maybe_flag_,
2142+
enum ha_rkey_function gis_func_flag)
21382143
:min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_), part(part_),
21392144
maybe_null(field_->real_maybe_null()),
2140-
rkey_func_flag(HA_READ_INVALID), elements(1),use_count(1),
2145+
rkey_func_flag(gis_func_flag), elements(1),use_count(1),
21412146
field(field_), min_value(min_value_), max_value(max_value_),
21422147
left(&null_element), right(&null_element),
21432148
next(NULL), prev(NULL), next_key_part(0), color(BLACK), type(KEY_RANGE)
@@ -2163,7 +2168,9 @@ SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent,
21632168
else
21642169
{
21652170
if (!(tmp= new (param->mem_root) SEL_ARG(field,part, min_value,max_value,
2166-
min_flag, max_flag, maybe_flag)))
2171+
min_flag, max_flag, maybe_flag,
2172+
min_flag & GEOM_FLAG ?
2173+
rkey_func_flag : HA_READ_INVALID)))
21672174
return 0; // OOM
21682175
tmp->parent=new_parent;
21692176
tmp->next_key_part=next_key_part;

unittest/gunit/opt_range-t.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,25 @@ TEST_F(OptRangeTest, AppendRange)
20662066
EXPECT_STREQ("42 < my_field < 42", out.c_ptr());
20672067
}
20682068

2069+
TEST_F(OptRangeTest, CloneSpatialKey) {
2070+
Fake_RANGE_OPT_PARAM param(thd(), &m_alloc, 2, false);
2071+
Mock_SEL_ARG key1(SEL_ARG::KEY_RANGE, 2, 0);
2072+
Mock_SEL_ARG key2(SEL_ARG::MAYBE_KEY, 1, 0);
2073+
// dummy field
2074+
Mock_field_long field1("geom1");
2075+
key1.field = &field1;
2076+
key1.left = &null_element;
2077+
key1.next_key_part = NULL;
2078+
key1.min_flag |= GEOM_FLAG;
2079+
key1.rkey_func_flag = HA_READ_MBR_CONTAIN;
2080+
// check if tree is cloned along with gis flag.
2081+
SEL_ARG *cloned_key1 = key_and(&param, &key1, &key2, CLONE_KEY2_MAYBE);
2082+
EXPECT_NE(cloned_key1, &key1);
2083+
EXPECT_EQ(cloned_key1->rkey_func_flag, key1.rkey_func_flag);
2084+
key1.use_count = 0;
2085+
key2.use_count = 0;
2086+
}
2087+
20692088
}
20702089

20712090
#undef create_tree

0 commit comments

Comments
 (0)