diff options
author | Alexander Barkov <bar@mariadb.org> | 2015-08-12 14:43:17 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2015-08-12 14:43:17 +0400 |
commit | 6e091dc7ff06f9ff0bbe834f6be338f5b695ed81 (patch) | |
tree | 1886bd46170e3311552342f98c98bd730af8c14e /sql | |
parent | 9a64262db2b5b7195fbfb048f814ca25a0b7a526 (diff) | |
download | mariadb-git-6e091dc7ff06f9ff0bbe834f6be338f5b695ed81.tar.gz |
Splitting a static function get_func_mm_tree() into virtual
methods in Item_bool_func descendants, which gives some advantages:
- Removing the "bool inv" parameter, as its now available through "this"
for Item_func_between and Item_func_in, and is not needed for the other
Item_func_xxx.
- Removing casts
- Making a step to data types plugings
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_cmpfunc.h | 60 | ||||
-rw-r--r-- | sql/opt_range.cc | 464 |
2 files changed, 264 insertions, 260 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 630a1e4e5c8..f0ef596ff8c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -122,6 +122,31 @@ public: class Item_bool_func :public Item_int_func { +protected: + /* + Build a SEL_TREE for a simple predicate + @param param PARAM from SQL_SELECT::test_quick_select + @param field field in the predicate + @param value constant in the predicate + @param cmp_type compare type for the field + @return Pointer to the tree built tree + */ + virtual SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, + Item_result cmp_type) + { + DBUG_ENTER("Item_bool_func2::get_func_mm_tree"); + DBUG_ASSERT(0); + DBUG_RETURN(0); + } + SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, + Item_field *field_item, Item *value); + SEL_TREE *get_mm_parts(RANGE_OPT_PARAM *param, Field *field, + Item_func::Functype type, + Item *value, Item_result cmp_type); + SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *lt_value, Item *gt_value, + Item_result cmp_type); public: Item_bool_func() :Item_int_func() {} Item_bool_func(Item *a) :Item_int_func(a) {} @@ -291,6 +316,21 @@ protected: void add_key_fields_optimize_op(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables, bool equal_func); + SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, Item_result cmp_type) + { + DBUG_ENTER("Item_bool_func2::get_func_mm_tree"); + /* + Here the function for the following predicates are processed: + <, <=, =, <=>, >=, >, LIKE, spatial relations + If the predicate is of the form (value op field) it is handled + as the equivalent predicate (field rev_op value), e.g. + 2 <= a is handled as a >= 2. + */ + Item_func::Functype func_type= + (value != arguments()[0]) ? functype() : rev_functype(); + DBUG_RETURN(get_mm_parts(param, field, func_type, value, cmp_type)); + } public: Item_bool_func2(Item *a,Item *b) :Item_bool_func(a,b) { } @@ -587,6 +627,13 @@ public: class Item_func_ne :public Item_bool_rowready_func2 { +protected: + SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, Item_result cmp_type) + { + DBUG_ENTER("Item_func_ne::get_func_mm_tree"); + DBUG_RETURN(get_ne_mm_tree(param, field, value, value, cmp_type)); + } public: Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} longlong val_int(); @@ -635,6 +682,9 @@ public: class Item_func_between :public Item_func_opt_neg { DTCollation cmp_collation; +protected: + SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, Item_result cmp_type); public: Item_result cmp_type; String value0,value1,value2; @@ -1292,6 +1342,9 @@ public: */ class Item_func_in :public Item_func_opt_neg { +protected: + SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, Item_result cmp_type); public: /* an array of values when the right hand arguments of IN @@ -1377,6 +1430,13 @@ public: /* Functions used by where clause */ class Item_func_null_predicate :public Item_bool_func { +protected: + SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, Item_result cmp_type) + { + DBUG_ENTER("Item_func_null_predicate::get_func_mm_tree"); + DBUG_RETURN(get_mm_parts(param, field, functype(), value, cmp_type)); + } public: Item_func_null_predicate(Item *a) :Item_bool_func(a) { } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f11506b2344..afb9dc6458c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -945,9 +945,6 @@ class TABLE_READ_PLAN; struct st_index_scan_info; struct st_ror_scan_info; -static SEL_TREE * get_mm_parts(RANGE_OPT_PARAM *param,COND *cond_func,Field *field, - Item_func::Functype type,Item *value, - Item_result cmp_type); static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field, KEY_PART *key_part, Item_func::Functype type,Item *value); @@ -7543,289 +7540,239 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param, 0 on error */ -static SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, - Field *field, - Item *lt_value, Item *gt_value, - Item_result cmp_type) +SEL_TREE *Item_bool_func::get_ne_mm_tree(RANGE_OPT_PARAM *param, + Field *field, + Item *lt_value, Item *gt_value, + Item_result cmp_type) { SEL_TREE *tree; - tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, - lt_value, cmp_type); + tree= get_mm_parts(param, field, Item_func::LT_FUNC, lt_value, cmp_type); if (tree) - { - tree= tree_or(param, tree, get_mm_parts(param, cond_func, field, - Item_func::GT_FUNC, + tree= tree_or(param, tree, get_mm_parts(param, field, Item_func::GT_FUNC, gt_value, cmp_type)); - } return tree; } - - -/* - Build a SEL_TREE for a simple predicate - - SYNOPSIS - get_func_mm_tree() - param PARAM from SQL_SELECT::test_quick_select - cond_func item for the predicate - field field in the predicate - value constant in the predicate - cmp_type compare type for the field - inv TRUE <> NOT cond_func is considered - (makes sense only when cond_func is BETWEEN or IN) - RETURN - Pointer to the tree built tree -*/ -static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, - Field *field, Item *value, - Item_result cmp_type, bool inv) +SEL_TREE *Item_func_between::get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, + Item_result cmp_type) { - SEL_TREE *tree= 0; - DBUG_ENTER("get_func_mm_tree"); - - switch (cond_func->functype()) { - - case Item_func::NE_FUNC: - tree= get_ne_mm_tree(param, cond_func, field, value, value, cmp_type); - break; - - case Item_func::BETWEEN: + SEL_TREE *tree; + DBUG_ENTER("Item_func_between::get_func_mm_tree"); + if (!value) { - if (!value) + if (negated) { - if (inv) - { - tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1], - cond_func->arguments()[2], cmp_type); - } - else + tree= get_ne_mm_tree(param, field, args[1], args[2], cmp_type); + } + else + { + tree= get_mm_parts(param, field, Item_func::GE_FUNC, args[1], cmp_type); + if (tree) { - tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC, - cond_func->arguments()[1],cmp_type); - if (tree) - { - tree= tree_and(param, tree, get_mm_parts(param, cond_func, field, - Item_func::LE_FUNC, - cond_func->arguments()[2], - cmp_type)); - } + tree= tree_and(param, tree, get_mm_parts(param, field, + Item_func::LE_FUNC, + args[2], cmp_type)); } } - else - tree= get_mm_parts(param, cond_func, field, - (inv ? - (value == (Item*)1 ? Item_func::GT_FUNC : - Item_func::LT_FUNC): - (value == (Item*)1 ? Item_func::LE_FUNC : - Item_func::GE_FUNC)), - cond_func->arguments()[0], cmp_type); - break; } - case Item_func::IN_FUNC: + else { - Item_func_in *func=(Item_func_in*) cond_func; + tree= get_mm_parts(param, field, + (negated ? + (value == (Item*)1 ? Item_func::GT_FUNC : + Item_func::LT_FUNC): + (value == (Item*)1 ? Item_func::LE_FUNC : + Item_func::GE_FUNC)), + args[0], cmp_type); + } + DBUG_RETURN(tree); +} - /* - Array for IN() is constructed when all values have the same result - type. Tree won't be built for values with different result types, - so we check it here to avoid unnecessary work. - */ - if (!func->arg_types_compatible) - break; - if (inv) +SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param, + Field *field, Item *value, + Item_result cmp_type) +{ + SEL_TREE *tree= 0; + DBUG_ENTER("Iten_func_in::get_func_mm_tree"); + /* + Array for IN() is constructed when all values have the same result + type. Tree won't be built for values with different result types, + so we check it here to avoid unnecessary work. + */ + if (!arg_types_compatible) + DBUG_RETURN(0); + + if (negated) + { + if (array && array->result_type() != ROW_RESULT) { - if (func->array && func->array->result_type() != ROW_RESULT) - { - /* - We get here for conditions in form "t.key NOT IN (c1, c2, ...)", - where c{i} are constants. Our goal is to produce a SEL_TREE that - represents intervals: - - ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*) - - where $MIN is either "-inf" or NULL. - - The most straightforward way to produce it is to convert NOT IN - into "(t.key != c1) AND (t.key != c2) AND ... " and let the range - analyzer to build SEL_TREE from that. The problem is that the - range analyzer will use O(N^2) memory (which is probably a bug), - and people do use big NOT IN lists (e.g. see BUG#15872, BUG#21282), - will run out of memory. - - Another problem with big lists like (*) is that a big list is - unlikely to produce a good "range" access, while considering that - range access will require expensive CPU calculations (and for - MyISAM even index accesses). In short, big NOT IN lists are rarely - worth analyzing. - - Considering the above, we'll handle NOT IN as follows: - * if the number of entries in the NOT IN list is less than - NOT_IN_IGNORE_THRESHOLD, construct the SEL_TREE (*) manually. - * Otherwise, don't produce a SEL_TREE. - */ + /* + We get here for conditions in form "t.key NOT IN (c1, c2, ...)", + where c{i} are constants. Our goal is to produce a SEL_TREE that + represents intervals: + + ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*) + + where $MIN is either "-inf" or NULL. + + The most straightforward way to produce it is to convert NOT IN + into "(t.key != c1) AND (t.key != c2) AND ... " and let the range + analyzer to build SEL_TREE from that. The problem is that the + range analyzer will use O(N^2) memory (which is probably a bug), + and people do use big NOT IN lists (e.g. see BUG#15872, BUG#21282), + will run out of memory. + + Another problem with big lists like (*) is that a big list is + unlikely to produce a good "range" access, while considering that + range access will require expensive CPU calculations (and for + MyISAM even index accesses). In short, big NOT IN lists are rarely + worth analyzing. + + Considering the above, we'll handle NOT IN as follows: + * if the number of entries in the NOT IN list is less than + NOT_IN_IGNORE_THRESHOLD, construct the SEL_TREE (*) manually. + * Otherwise, don't produce a SEL_TREE. + */ #define NOT_IN_IGNORE_THRESHOLD 1000 - MEM_ROOT *tmp_root= param->mem_root; - param->thd->mem_root= param->old_root; - /* - Create one Item_type constant object. We'll need it as - get_mm_parts only accepts constant values wrapped in Item_Type - objects. - We create the Item on param->mem_root which points to - per-statement mem_root (while thd->mem_root is currently pointing - to mem_root local to range optimizer). - */ - Item *value_item= func->array->create_item(); - param->thd->mem_root= tmp_root; + MEM_ROOT *tmp_root= param->mem_root; + param->thd->mem_root= param->old_root; + /* + Create one Item_type constant object. We'll need it as + get_mm_parts only accepts constant values wrapped in Item_Type + objects. + We create the Item on param->mem_root which points to + per-statement mem_root (while thd->mem_root is currently pointing + to mem_root local to range optimizer). + */ + Item *value_item= array->create_item(); + param->thd->mem_root= tmp_root; + + if (array->count > NOT_IN_IGNORE_THRESHOLD || !value_item) + DBUG_RETURN(0); - if (func->array->count > NOT_IN_IGNORE_THRESHOLD || !value_item) + /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ + uint i=0; + do + { + array->value_to_item(i, value_item); + tree= get_mm_parts(param, field, Item_func::LT_FUNC, + value_item, cmp_type); + if (!tree) break; + i++; + } while (i < array->count && tree->type == SEL_TREE::IMPOSSIBLE); - /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ - uint i=0; - do + if (!tree || tree->type == SEL_TREE::IMPOSSIBLE) + { + /* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */ + DBUG_RETURN(NULL); + } + SEL_TREE *tree2; + for (; i < array->count; i++) + { + if (array->compare_elems(i, i-1)) { - func->array->value_to_item(i, value_item); - tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, - value_item, cmp_type); - if (!tree) + /* Get a SEL_TREE for "-inf < X < c_i" interval */ + array->value_to_item(i, value_item); + tree2= get_mm_parts(param, field, Item_func::LT_FUNC, + value_item, cmp_type); + if (!tree2) + { + tree= NULL; break; - i++; - } while (i < func->array->count && tree->type == SEL_TREE::IMPOSSIBLE); + } - if (!tree || tree->type == SEL_TREE::IMPOSSIBLE) - { - /* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */ - tree= NULL; - break; - } - SEL_TREE *tree2; - for (; i < func->array->count; i++) - { - if (func->array->compare_elems(i, i-1)) + /* Change all intervals to be "c_{i-1} < X < c_i" */ + for (uint idx= 0; idx < param->keys; idx++) { - /* Get a SEL_TREE for "-inf < X < c_i" interval */ - func->array->value_to_item(i, value_item); - tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, - value_item, cmp_type); - if (!tree2) - { - tree= NULL; - break; - } - - /* Change all intervals to be "c_{i-1} < X < c_i" */ - for (uint idx= 0; idx < param->keys; idx++) + SEL_ARG *new_interval, *last_val; + if (((new_interval= tree2->keys[idx])) && + (tree->keys[idx]) && + ((last_val= tree->keys[idx]->last()))) { - SEL_ARG *new_interval, *last_val; - if (((new_interval= tree2->keys[idx])) && - (tree->keys[idx]) && - ((last_val= tree->keys[idx]->last()))) + 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) { - 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; - } + 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; } } - /* - The following doesn't try to allocate memory so no need to - check for NULL. - */ - tree= tree_or(param, tree, tree2); } - } - - if (tree && tree->type != SEL_TREE::IMPOSSIBLE) - { /* - Get the SEL_TREE for the last "c_last < X < +inf" interval - (value_item cotains c_last already) + The following doesn't try to allocate memory so no need to + check for NULL. */ - tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, - value_item, cmp_type); tree= tree_or(param, tree, tree2); } } - else + + if (tree && tree->type != SEL_TREE::IMPOSSIBLE) { - tree= get_ne_mm_tree(param, cond_func, field, - func->arguments()[1], func->arguments()[1], - cmp_type); - if (tree) - { - Item **arg, **end; - for (arg= func->arguments()+2, end= arg+func->argument_count()-2; - arg < end ; arg++) - { - tree= tree_and(param, tree, get_ne_mm_tree(param, cond_func, field, - *arg, *arg, cmp_type)); - } - } + /* + Get the SEL_TREE for the last "c_last < X < +inf" interval + (value_item cotains c_last already) + */ + tree2= get_mm_parts(param, field, Item_func::GT_FUNC, + value_item, cmp_type); + tree= tree_or(param, tree, tree2); } } else - { - tree= get_mm_parts(param, cond_func, field, Item_func::EQ_FUNC, - func->arguments()[1], cmp_type); + { + tree= get_ne_mm_tree(param, field, args[1], args[1], cmp_type); if (tree) { Item **arg, **end; - for (arg= func->arguments()+2, end= arg+func->argument_count()-2; - arg < end ; arg++) + for (arg= args + 2, end= arg + arg_count - 2; arg < end ; arg++) { - tree= tree_or(param, tree, get_mm_parts(param, cond_func, field, - Item_func::EQ_FUNC, - *arg, cmp_type)); + tree= tree_and(param, tree, get_ne_mm_tree(param, field, + *arg, *arg, cmp_type)); } } } - break; } - default: + else { - /* - Here the function for the following predicates are processed: - <, <=, =, >=, >, LIKE, IS NULL, IS NOT NULL. - If the predicate is of the form (value op field) it is handled - as the equivalent predicate (field rev_op value), e.g. - 2 <= a is handled as a >= 2. - */ - Item_func::Functype func_type= - (value != cond_func->arguments()[0]) ? cond_func->functype() : - ((Item_bool_func2*) cond_func)->rev_functype(); - tree= get_mm_parts(param, cond_func, field, func_type, value, cmp_type); - } + tree= get_mm_parts(param, field, Item_func::EQ_FUNC, args[1], cmp_type); + if (tree) + { + Item **arg, **end; + for (arg= args + 2, end= arg + arg_count - 2; + arg < end ; arg++) + { + tree= tree_or(param, tree, get_mm_parts(param, field, + Item_func::EQ_FUNC, + *arg, cmp_type)); + } + } } - DBUG_RETURN(tree); } @@ -7836,7 +7783,6 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, SYNOPSIS get_full_func_mm_tree() param PARAM from SQL_SELECT::test_quick_select - cond_func item for the predicate field_item field in the predicate value constant in the predicate (or a field already read from a table in the case of dynamic range access) @@ -7901,18 +7847,16 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, Pointer to the tree representing the built conjunction of SEL_TREEs */ -static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, - Item_func *cond_func, - Item_field *field_item, Item *value, - bool inv) +SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, + Item_field *field_item, + Item *value) { + DBUG_ENTER("Item_bool_func::get_full_func_mm_tree"); SEL_TREE *tree= 0; SEL_TREE *ftree= 0; table_map ref_tables= 0; table_map param_comp= ~(param->prev_tables | param->read_tables | param->current_table); - DBUG_ENTER("get_full_func_mm_tree"); - #ifdef HAVE_SPATIAL if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) { @@ -7921,16 +7865,16 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, } #endif /*HAVE_SPATIAL*/ - for (uint i= 0; i < cond_func->arg_count; i++) + for (uint i= 0; i < arg_count; i++) { - Item *arg= cond_func->arguments()[i]->real_item(); + Item *arg= arguments()[i]->real_item(); if (arg != field_item) ref_tables|= arg->used_tables(); } Field *field= field_item->field; Item_result cmp_type= field->cmp_type(); if (!((ref_tables | field->table->map) & param_comp)) - ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv); + ftree= get_func_mm_tree(param, field, value, cmp_type); Item_equal *item_equal= field_item->item_equal; if (item_equal) { @@ -7942,7 +7886,7 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, continue; if (!((ref_tables | f->table->map) & param_comp)) { - tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv); + tree= get_func_mm_tree(param, f, value, cmp_type); ftree= !ftree ? tree : tree_and(param, ftree, tree); } } @@ -7950,6 +7894,7 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, DBUG_RETURN(ftree); } + /* make a select tree of all keys in condition @@ -8114,7 +8059,7 @@ Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) if (arguments()[0]->real_item()->type() == Item::FIELD_ITEM) { Item_field *field_item= (Item_field*) (arguments()[0]->real_item()); - ftree= get_full_func_mm_tree(param, this, field_item, NULL, negated); + ftree= get_full_func_mm_tree(param, field_item, NULL); } /* @@ -8126,8 +8071,8 @@ Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) if (arguments()[i]->real_item()->type() == Item::FIELD_ITEM) { Item_field *field_item= (Item_field*) (arguments()[i]->real_item()); - SEL_TREE *tmp= get_full_func_mm_tree(param, this, field_item, - (Item*)(intptr) i, negated); + SEL_TREE *tmp= get_full_func_mm_tree(param, field_item, + (Item*)(intptr) i); if (negated) { tree= !tree ? tmp : tree_or(param, tree, tmp); @@ -8158,7 +8103,7 @@ SEL_TREE *Item_func_in::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) if (key_item()->real_item()->type() != Item::FIELD_ITEM) DBUG_RETURN(0); Item_field *field= (Item_field*) (key_item()->real_item()); - SEL_TREE *tree= get_full_func_mm_tree(param, this, field, NULL, negated); + SEL_TREE *tree= get_full_func_mm_tree(param, field, NULL); DBUG_RETURN(tree); } @@ -8185,7 +8130,7 @@ SEL_TREE *Item_equal::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) Field *field= it.get_curr_field(); if (!((ref_tables | field->table->map) & param_comp)) { - tree= get_mm_parts(param, this, field, Item_func::EQ_FUNC, + tree= get_mm_parts(param, field, Item_func::EQ_FUNC, value, field->cmp_type()); ftree= !ftree ? tree : tree_and(param, ftree, tree); } @@ -8212,7 +8157,7 @@ SEL_TREE *Item_func_null_predicate::get_mm_tree(RANGE_OPT_PARAM *param, { Item_field *field_item= (Item_field*) args[0]->real_item(); if (!field_item->const_item()) - DBUG_RETURN(get_full_func_mm_tree(param, this, field_item, NULL, false)); + DBUG_RETURN(get_full_func_mm_tree(param, field_item, NULL)); } DBUG_RETURN(NULL); } @@ -8233,7 +8178,7 @@ SEL_TREE *Item_bool_func2::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) if (value && value->is_expensive()) DBUG_RETURN(0); if (!arguments()[0]->real_item()->const_item()) - ftree= get_full_func_mm_tree(param, this, field_item, value, false); + ftree= get_full_func_mm_tree(param, field_item, value); } /* Even if get_full_func_mm_tree() was executed above and did not @@ -8259,17 +8204,17 @@ SEL_TREE *Item_bool_func2::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) if (value && value->is_expensive()) DBUG_RETURN(0); if (!arguments()[1]->real_item()->const_item()) - ftree= get_full_func_mm_tree(param, this, field_item, value, false); + ftree= get_full_func_mm_tree(param, field_item, value); } DBUG_RETURN(ftree); } -static SEL_TREE * -get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field, - Item_func::Functype type, - Item *value, Item_result cmp_type) +SEL_TREE * +Item_bool_func::get_mm_parts(RANGE_OPT_PARAM *param, Field *field, + Item_func::Functype type, + Item *value, Item_result cmp_type) { DBUG_ENTER("get_mm_parts"); if (field->table != param->table) @@ -8290,8 +8235,7 @@ get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field, DBUG_RETURN(0); // OOM if (!value || !(value->used_tables() & ~param->read_tables)) { - sel_arg=get_mm_leaf(param,cond_func, - key_part->field,key_part,type,value); + sel_arg= get_mm_leaf(param,this,key_part->field,key_part,type,value); if (!sel_arg) continue; if (sel_arg->type == SEL_ARG::IMPOSSIBLE) |