summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/opt_range.cc29
1 files changed, 29 insertions, 0 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9604ed1e3b3..b8f583a66ed 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -5345,6 +5345,34 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
{
new_interval->min_value= last_val->max_value;
new_interval->min_flag= NEAR_MIN;
+
+ /*
+ If the interval is over a partial keypart, the
+ interval must be "c_{i-1} <= X < c_i" instead of
+ "c_{i-1} < X < c_i". Reason:
+
+ Consider a table with a column "my_col VARCHAR(3)",
+ and an index with definition
+ "INDEX my_idx my_col(1)". If the table contains rows
+ with my_col values "f" and "foo", the index will not
+ distinguish the two rows.
+
+ Note that tree_or() below will effectively merge
+ this range with the range created for c_{i-1} and
+ we'll eventually end up with only one range:
+ "NULL < X".
+
+ Partitioning indexes are never partial.
+ */
+ if (param->using_real_indexes)
+ {
+ const KEY key=
+ param->table->key_info[param->real_keynr[idx]];
+ const KEY_PART_INFO *kpi= key.key_part + new_interval->part;
+
+ if (kpi->key_part_flag & HA_PART_KEY_SEG)
+ new_interval->min_flag= 0;
+ }
}
}
/*
@@ -5827,6 +5855,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
if (key_part->image_type == Field::itMBR)
{
+ // @todo: use is_spatial_operator() instead?
switch (type) {
case Item_func::SP_EQUALS_FUNC:
case Item_func::SP_DISJOINT_FUNC: