diff --git a/mysql-test/main/type_blob.result b/mysql-test/main/type_blob.result index 1318807542d..67186e10659 100644 --- a/mysql-test/main/type_blob.result +++ b/mysql-test/main/type_blob.result @@ -1140,5 +1140,18 @@ c d DROP TABLE t1, t2; SET @@sql_mode=@save_sql_mode; # +# MDEV-31800 Problem with open ranges on prefix blobs keys +# +create table t1 (d text not null, key a (d(6))) ; +insert into t1 values ('prefix 2' ), ('prefix 0' ); +select d from t1 where d >= 'prefix 1' and d < 'prefix 3'; +d +prefix 2 +alter table t1 drop index a; +select d from t1 where d >= 'prefix 1' and d < 'prefix 3'; +d +prefix 2 +drop table t1; +# # End of 10.4 test # diff --git a/mysql-test/main/type_blob.test b/mysql-test/main/type_blob.test index a9b044b5318..54102c7f004 100644 --- a/mysql-test/main/type_blob.test +++ b/mysql-test/main/type_blob.test @@ -756,6 +756,16 @@ select * from t2; DROP TABLE t1, t2; SET @@sql_mode=@save_sql_mode; +--echo # +--echo # MDEV-31800 Problem with open ranges on prefix blobs keys +--echo # +create table t1 (d text not null, key a (d(6))) ; +insert into t1 values ('prefix 2' ), ('prefix 0' ); +select d from t1 where d >= 'prefix 1' and d < 'prefix 3'; +alter table t1 drop index a; +select d from t1 where d >= 'prefix 1' and d < 'prefix 3'; +drop table t1; + --echo # --echo # End of 10.4 test --echo # diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 6ada4675ae6..0049be0daf4 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1947,18 +1947,25 @@ public: Use this constructor if value->save_in_field() went precisely, without any data rounding or truncation. */ - SEL_ARG_LT(const uchar *key, Field *field) + SEL_ARG_LT(const uchar *key, const KEY_PART *key_part, Field *field) :SEL_ARG_LE(key, field) - { max_flag= NEAR_MAX; } + { + // Don't use open ranges for partial key_segments + if (!(key_part->flag & HA_PART_KEY_SEG)) + max_flag= NEAR_MAX; + } /* Use this constructor if value->save_in_field() returned success, but we don't know if rounding or truncation happened (as some Field::store() do not report minor data changes). */ - SEL_ARG_LT(THD *thd, const uchar *key, Field *field, Item *value) + SEL_ARG_LT(THD *thd, const uchar *key, + const KEY_PART *key_part, Field *field, Item *value) :SEL_ARG_LE(key, field) { - if (stored_field_cmp_to_item(thd, field, value) == 0) + // Don't use open ranges for partial key_segments + if (!(key_part->flag & HA_PART_KEY_SEG) && + stored_field_cmp_to_item(thd, field, value) == 0) max_flag= NEAR_MAX; } }; @@ -9032,7 +9039,7 @@ SEL_ARG *Field::stored_field_make_mm_leaf(RANGE_OPT_PARAM *param, case SCALAR_CMP_LE: DBUG_RETURN(new (mem_root) SEL_ARG_LE(str, this)); case SCALAR_CMP_LT: - DBUG_RETURN(new (mem_root) SEL_ARG_LT(thd, str, this, value)); + DBUG_RETURN(new (mem_root) SEL_ARG_LT(thd, str, key_part, this, value)); case SCALAR_CMP_GT: DBUG_RETURN(new (mem_root) SEL_ARG_GT(thd, str, key_part, this, value)); case SCALAR_CMP_GE: @@ -9061,7 +9068,7 @@ SEL_ARG *Field::stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param, case SCALAR_CMP_LE: DBUG_RETURN(new (param->mem_root) SEL_ARG_LE(str, this)); case SCALAR_CMP_LT: - DBUG_RETURN(new (param->mem_root) SEL_ARG_LT(str, this)); + DBUG_RETURN(new (param->mem_root) SEL_ARG_LT(str, key_part, this)); case SCALAR_CMP_GT: DBUG_RETURN(new (param->mem_root) SEL_ARG_GT(str, key_part, this)); case SCALAR_CMP_GE: