mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug#16540042: WRONG QUERY RESULT WHEN USING RANGE OVER
PARTIAL INDEX Consider the following table definition: CREATE TABLE t ( my_col CHAR(10), ... INDEX my_idx (my_col(1)) ) The my_idx index is not able to distinguish between rows with equal first-character my_col-values (e.g. "f", "foo", "fee"). Prior to this CS, the range optimizer would translate "WHERE my_col NOT IN ('f', 'h')" into (optimizer trace syntax) "ranges": [ "NULL < my_col < f", "f < my_col" ] But this was not correct because the rows with values "foo" and "fee" would not belong to any of those ranges. However, the predicate "my_col != 'f' AND my_col != 'h'" would translate to "ranges": [ "NULL < my_col" ] because get_mm_leaf() changes from "<" to "<=" for partial keyparts. This CS changes the range optimizer implementation for NOT IN to behave like a conjunction of NOT EQUAL: it replaces "<" with "<=" for all but the first range when the keypart is partial.
This commit is contained in:
@ -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:
|
||||
|
Reference in New Issue
Block a user