diff options
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 581 |
1 files changed, 520 insertions, 61 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ba674743724..7d361263548 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -29,6 +29,7 @@ #pragma implementation // gcc: Class implementation #endif +#include <my_global.h> #include "sql_priv.h" /* It is necessary to include set_var.h instead of item.h because there @@ -43,6 +44,9 @@ double get_post_group_estimate(JOIN* join, double join_op_rows); +const char *exists_outer_expr_name= "<exists outer expr>"; + +int check_and_do_in_subquery_rewrites(JOIN *join); Item_subselect::Item_subselect(): Item_result_field(), value_assigned(0), own_engine(0), thd(0), old_engine(0), @@ -83,15 +87,24 @@ void Item_subselect::init(st_select_lex *select_lex, if (unit->item) { - /* - Item can be changed in JOIN::prepare while engine in JOIN::optimize - => we do not copy old_engine here - */ engine= unit->item->engine; - own_engine= FALSE; parsing_place= unit->item->parsing_place; - thd->change_item_tree((Item**)&unit->item, this); - engine->change_result(this, result, TRUE); + if (unit->item->substype() == EXISTS_SUBS && + ((Item_exists_subselect *)unit->item)->exists_transformed) + { + /* it is permanent transformation of EXISTS to IN */ + unit->item= this; + engine->change_result(this, result, FALSE); + } + else + { + /* + Item can be changed in JOIN::prepare while engine in JOIN::optimize + => we do not copy old_engine here + */ + thd->change_item_tree((Item**)&unit->item, this); + engine->change_result(this, result, TRUE); + } } else { @@ -462,7 +475,7 @@ public: void Item_subselect::recalc_used_tables(st_select_lex *new_parent, bool after_pullout) { - List_iterator<Ref_to_outside> it(upper_refs); + List_iterator_fast<Ref_to_outside> it(upper_refs); Ref_to_outside *upper; DBUG_ENTER("recalc_used_tables"); @@ -675,9 +688,12 @@ bool Item_subselect::exec() void Item_subselect::get_cache_parameters(List<Item> ¶meters) { - Collect_deps_prm prm= {¶meters, - unit->first_select()->nest_level_base, - unit->first_select()->nest_level}; + Collect_deps_prm prm= {¶meters, // parameters + unit->first_select()->nest_level_base, // nest_level_base + 0, // count + unit->first_select()->nest_level, // nest_level + TRUE // collect + }; walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm); } @@ -1077,7 +1093,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) { char warn_buff[MYSQL_ERRMSG_SIZE]; sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } substitution= select_lex->item_list.head(); @@ -1317,10 +1333,10 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): - Item_subselect() + Item_subselect(), upper_not(NULL), abort_on_null(0), + emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0) { DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); - bool val_bool(); init(select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; null_value= FALSE; //can't be NULL @@ -1354,21 +1370,19 @@ bool Item_in_subselect::test_limit(st_select_lex_unit *unit_arg) Item_in_subselect::Item_in_subselect(Item * left_exp, st_select_lex *select_lex): - Item_exists_subselect(), - left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), - optimizer(0), pushed_cond_guards(NULL), emb_on_expr_nest(NULL), - is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), - is_flattenable_semijoin(FALSE), - is_registered_semijoin(FALSE), + Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE), + in_strategy(SUBS_NOT_TRANSFORMED), + pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), + is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), upper_item(0) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); + DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); left_expr_orig= left_expr= left_exp; func= &eq_creator; init(select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; maybe_null= 1; - abort_on_null= 0; reset(); //if test_limit will fail then error will be reported to client test_limit(select_lex->master_unit()); @@ -1755,7 +1769,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) { char warn_buff[MYSQL_ERRMSG_SIZE]; sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } DBUG_RETURN(false); @@ -1773,8 +1787,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) SELECT_LEX *current= thd->lex->current_select; thd->lex->current_select= current->return_after_parsing(); - //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, 0)) + if (!optimizer || optimizer->fix_left(thd)) { thd->lex->current_select= current; DBUG_RETURN(true); @@ -1951,7 +1964,7 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join) WHERE condition. */ return (abort_on_null || (upper_item && upper_item->is_top_level_item())) && - !join->select_lex->master_unit()->uncacheable && !func->eqne_op(); + !(join->select_lex->master_unit()->uncacheable & ~UNCACHEABLE_EXPLAIN) && !func->eqne_op(); } @@ -2153,8 +2166,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) SELECT_LEX *current= thd->lex->current_select; thd->lex->current_select= current->return_after_parsing(); - //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, 0)) + if (!optimizer || optimizer->fix_left(thd)) { thd->lex->current_select= current; DBUG_RETURN(true); @@ -2334,7 +2346,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ref_pointer_array+i, (char *)"<no matter>", (char *)"<list ref>")); - if (!abort_on_null) + if (!abort_on_null && select_lex->ref_pointer_array[i]->maybe_null) { Item *having_col_item= new Item_is_not_null_test(this, @@ -2353,10 +2365,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"<no matter>", (char *)"<list ref>")); item= new Item_cond_or(item, item_isnull); - /* - TODO: why we create the above for cases where the right part - cant be NULL? - */ if (left_expr->element_index(i)->maybe_null) { if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) @@ -2367,6 +2375,11 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, } *having_item= and_items(*having_item, having_col_item); } + if (!abort_on_null && left_expr->element_index(i)->maybe_null) + { + if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) + DBUG_RETURN(true); + } *where_item= and_items(*where_item, item); } } @@ -2397,6 +2410,12 @@ Item_in_subselect::select_transformer(JOIN *join) return select_in_like_transformer(join); } +bool +Item_exists_subselect::select_transformer(JOIN *join) +{ + return select_prepare_to_be_in(); +} + /** Create the predicates needed to transform an IN/ALL/ANY subselect into a @@ -2532,6 +2551,433 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) } +/* + If this select can potentially be converted by EXISTS->IN conversion, wrap it + in an Item_in_optimizer object. Final decision whether to do the conversion + is done at a later phase. +*/ + +bool Item_exists_subselect::select_prepare_to_be_in() +{ + bool trans_res= FALSE; + DBUG_ENTER("Item_exists_subselect::select_prepare_to_be_in"); + if (!optimizer && + thd->lex->sql_command == SQLCOM_SELECT && + !unit->first_select()->is_part_of_union() && + optimizer_flag(thd, OPTIMIZER_SWITCH_EXISTS_TO_IN) && + (is_top_level_item() || + (upper_not && upper_not->is_top_level_item()))) + { + Query_arena *arena, backup; + bool result; + arena= thd->activate_stmt_arena_if_needed(&backup); + result= (!(optimizer= new Item_in_optimizer(new Item_int(1), this))); + if (arena) + thd->restore_active_arena(arena, &backup); + if (result) + trans_res= TRUE; + else + substitution= optimizer; + } + DBUG_RETURN(trans_res); +} + +/** + Check if 'func' is an equality in form "inner_table.column = outer_expr" + + @param func Expression to check + @param local_field OUT Return "inner_table.column" here + @param outer_expr OUT Return outer_expr here + + @return true - 'func' is an Equality. +*/ + +static bool check_equality_for_exist2in(Item_func *func, + Item_ident **local_field, + Item **outer_exp) +{ + Item **args; + if (func->functype() != Item_func::EQ_FUNC) + return FALSE; + DBUG_ASSERT(func->arg_count == 2); + args= func->arguments(); + if (args[0]->real_type() == Item::FIELD_ITEM && + args[0]->all_used_tables() != OUTER_REF_TABLE_BIT && + args[1]->all_used_tables() == OUTER_REF_TABLE_BIT) + { + /* It is Item_field or Item_direct_view_ref) */ + DBUG_ASSERT(args[0]->type() == Item::FIELD_ITEM || + args[0]->type() == Item::REF_ITEM); + *local_field= (Item_ident *)args[0]; + *outer_exp= args[1]; + return TRUE; + } + else if (args[1]->real_type() == Item::FIELD_ITEM && + args[1]->all_used_tables() != OUTER_REF_TABLE_BIT && + args[0]->all_used_tables() == OUTER_REF_TABLE_BIT) + { + /* It is Item_field or Item_direct_view_ref) */ + DBUG_ASSERT(args[0]->type() == Item::FIELD_ITEM || + args[0]->type() == Item::REF_ITEM); + *local_field= (Item_ident *)args[1]; + *outer_exp= args[0]; + return TRUE; + } + + return FALSE; +} + +typedef struct st_eq_field_outer +{ + Item **eq_ref; + Item_ident *local_field; + Item *outer_exp; +} EQ_FIELD_OUTER; + + +/** + Check if 'conds' is a set of AND-ed outer_expr=inner_table.col equalities + + @detail + Check if 'conds' has form + + outer1=inner_tbl1.col1 AND ... AND outer2=inner_tbl1.col2 AND remainder_cond + + @param conds Condition to be checked + @parm result Array to collect EQ_FIELD_OUTER elements describing + inner-vs-outer equalities the function has found. + @return + false - some inner-vs-outer equalities were found + true - otherwise. +*/ + +static bool find_inner_outer_equalities(Item **conds, + Dynamic_array<EQ_FIELD_OUTER> &result) +{ + bool found= FALSE; + EQ_FIELD_OUTER element; + if (is_cond_and(*conds)) + { + List_iterator<Item> li(*((Item_cond*)*conds)->argument_list()); + Item *item; + while ((item= li++)) + { + if (item->type() == Item::FUNC_ITEM && + check_equality_for_exist2in((Item_func *)item, + &element.local_field, + &element.outer_exp)) + { + found= TRUE; + element.eq_ref= li.ref(); + if (result.append(element)) + goto alloc_err; + } + } + } + else if ((*conds)->type() == Item::FUNC_ITEM && + check_equality_for_exist2in((Item_func *)*conds, + &element.local_field, + &element.outer_exp)) + { + found= TRUE; + element.eq_ref= conds; + if (result.append(element)) + goto alloc_err; + } + + return !found; +alloc_err: + return TRUE; +} + +/** + Converts EXISTS subquery to IN subquery if it is possible and has sense + + @param opt_arg Pointer on THD + + @return TRUE in case of error and FALSE otherwise. +*/ + +bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) +{ + THD *thd= (THD *)opt_arg; + SELECT_LEX *first_select=unit->first_select(), *save_select; + JOIN *join= first_select->join; + Item **eq_ref= NULL; + Item_ident *local_field= NULL; + Item *outer_exp= NULL; + Item *left_exp= NULL; Item_in_subselect *in_subs; + Query_arena *arena= NULL, backup; + int res= FALSE; + List<Item> outer; + Dynamic_array<EQ_FIELD_OUTER> eqs(5, 5); + bool will_be_correlated; + DBUG_ENTER("Item_exists_subselect::exists2in_processor"); + + if (!optimizer || + !optimizer_flag(thd, OPTIMIZER_SWITCH_EXISTS_TO_IN) || + (!is_top_level_item() && (!upper_not || + !upper_not->is_top_level_item())) || + first_select->is_part_of_union() || + first_select->group_list.elements || + first_select->order_list.elements || + join->having || + first_select->with_sum_func || + !first_select->leaf_tables.elements|| + !join->conds) + DBUG_RETURN(FALSE); + + DBUG_ASSERT(first_select->order_list.elements == 0 && + first_select->group_list.elements == 0 && + first_select->having == NULL); + + if (find_inner_outer_equalities(&join->conds, eqs)) + DBUG_RETURN(FALSE); + + DBUG_ASSERT(eqs.elements() != 0); + + save_select= thd->lex->current_select; + thd->lex->current_select= first_select; + + /* check that the subquery has only dependencies we are going pull out */ + { + List<Item> unused; + Collect_deps_prm prm= {&unused, // parameters + unit->first_select()->nest_level_base, // nest_level_base + 0, // count + unit->first_select()->nest_level, // nest_level + FALSE // collect + }; + walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm); + DBUG_ASSERT(prm.count > 0); + DBUG_ASSERT(prm.count >= (uint)eqs.elements()); + will_be_correlated= prm.count > (uint)eqs.elements(); + if (upper_not && will_be_correlated) + goto out; + } + + if ((uint)eqs.elements() > (first_select->item_list.elements + + first_select->select_n_reserved)) + goto out; + /* It is simple query */ + DBUG_ASSERT(first_select->join->all_fields.elements == + first_select->item_list.elements); + + arena= thd->activate_stmt_arena_if_needed(&backup); + + while (first_select->item_list.elements > (uint)eqs.elements()) + { + first_select->item_list.pop(); + first_select->join->all_fields.elements--; + } + { + List_iterator<Item> it(first_select->item_list); + + for (uint i= 0; i < (uint)eqs.elements(); i++) + { + Item *item= it++; + eq_ref= eqs.at(i).eq_ref; + local_field= eqs.at(i).local_field; + outer_exp= eqs.at(i).outer_exp; + /* Add the field to the SELECT_LIST */ + if (item) + it.replace(local_field); + else + { + first_select->item_list.push_back(local_field); + first_select->join->all_fields.elements++; + } + first_select->ref_pointer_array[i]= (Item *)local_field; + + /* remove the parts from condition */ + if (!upper_not || !local_field->maybe_null) + *eq_ref= new Item_int(1); + else + { + *eq_ref= new Item_func_isnotnull( + new Item_field(thd, + ((Item_field*)(local_field->real_item()))->context, + ((Item_field*)(local_field->real_item()))->field)); + if((*eq_ref)->fix_fields(thd, (Item **)eq_ref)) + { + res= TRUE; + goto out; + } + } + outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp); + outer_exp->update_used_tables(); + outer.push_back(outer_exp); + } + } + + join->conds->update_used_tables(); + + /* make IN SUBQUERY and put outer_exp as left part */ + if (eqs.elements() == 1) + left_exp= outer_exp; + else + { + if (!(left_exp= new Item_row(outer))) + { + res= TRUE; + goto out; + } + } + + /* make EXISTS->IN permanet (see Item_subselect::init()) */ + set_exists_transformed(); + + first_select->select_limit= NULL; + if (!(in_subs= new Item_in_subselect(left_exp, first_select))) + { + res= TRUE; + goto out; + } + in_subs->set_exists_transformed(); + optimizer->arguments()[0]= left_exp; + optimizer->arguments()[1]= in_subs; + in_subs->optimizer= optimizer; + DBUG_ASSERT(is_top_level_item() || + (upper_not && upper_not->is_top_level_item())); + in_subs->top_level_item(); + { + SELECT_LEX *current= thd->lex->current_select; + optimizer->reset_cache(); // renew cache, and we will not keep it + thd->lex->current_select= unit->outer_select(); + DBUG_ASSERT(optimizer); + if (optimizer->fix_left(thd)) + { + res= TRUE; + /* + We should not restore thd->lex->current_select because it will be + reset on exit from this procedure + */ + goto out; + } + /* + As far as Item_ref_in_optimizer do not substitute itself on fix_fields + we can use same item for all selects. + */ + in_subs->expr= new Item_direct_ref(&first_select->context, + (Item**)optimizer->get_cache(), + (char *)"<no matter>", + (char *)in_left_expr_name); + if (in_subs->fix_fields(thd, optimizer->arguments() + 1)) + { + res= TRUE; + /* + We should not restore thd->lex->current_select because it will be + reset on exit from this procedure + */ + goto out; + } + { + /* Move dependence list */ + List_iterator_fast<Ref_to_outside> it(upper_refs); + Ref_to_outside *upper; + while ((upper= it++)) + { + uint i; + for (i= 0; i < (uint)eqs.elements(); i++) + if (eqs.at(i).outer_exp-> + walk(&Item::find_item_processor, TRUE, (uchar*)upper->item)) + break; + if (i == (uint)eqs.elements() && + (in_subs->upper_refs.push_back(upper, thd->stmt_arena->mem_root))) + goto out; + } + } + in_subs->update_used_tables(); + /* + The engine of the subquery is fixed so above fix_fields() is not + complete and should be fixed + */ + in_subs->upper_refs= upper_refs; + upper_refs.empty(); + thd->lex->current_select= current; + } + + DBUG_ASSERT(unit->item == in_subs); + DBUG_ASSERT(join == first_select->join); + /* + Fix dependency info + */ + in_subs->is_correlated= will_be_correlated; + if (!will_be_correlated) + { + first_select->uncacheable&= ~UNCACHEABLE_DEPENDENT_GENERATED; + unit->uncacheable&= ~UNCACHEABLE_DEPENDENT_GENERATED; + } + /* + set possible optimization strategies + */ + in_subs->emb_on_expr_nest= emb_on_expr_nest; + res= check_and_do_in_subquery_rewrites(join); + first_select->join->prepare_stage2(); + + first_select->fix_prepare_information(thd, &join->conds, &join->having); + + if (upper_not) + { + Item *exp; + if (eqs.elements() == 1) + { + exp= (optimizer->arguments()[0]->maybe_null ? + (Item*) + new Item_cond_and( + new Item_func_isnotnull( + new Item_direct_ref(&unit->outer_select()->context, + optimizer->arguments(), + (char *)"<no matter>", + (char *)exists_outer_expr_name)), + optimizer) : + (Item *)optimizer); + } + else + { + List<Item> *and_list= new List<Item>; + if (!and_list) + { + res= TRUE; + goto out; + } + for (size_t i= 0; i < eqs.elements(); i++) + { + if (optimizer->arguments()[0]->maybe_null) + { + and_list-> + push_front( + new Item_func_isnotnull( + new Item_direct_ref(&unit->outer_select()->context, + optimizer->arguments()[0]->addr(i), + (char *)"<no matter>", + (char *)exists_outer_expr_name))); + } + } + if (and_list->elements > 0) + { + and_list->push_front(optimizer); + exp= new Item_cond_and(*and_list); + } + else + exp= optimizer; + } + upper_not->arguments()[0]= exp; + if (!exp->fixed && exp->fix_fields(thd, upper_not->arguments())) + { + res= TRUE; + goto out; + } + } + +out: + thd->lex->current_select= save_select; + if (arena) + thd->restore_active_arena(arena, &backup); + DBUG_RETURN(res); +} + + /** Prepare IN/ALL/ANY/SOME subquery transformation and call the appropriate transformation function. @@ -2592,7 +3038,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) } thd->lex->current_select= current->return_after_parsing(); - result= optimizer->fix_left(thd, optimizer->arguments()); + result= optimizer->fix_left(thd); thd->lex->current_select= current; if (changed) @@ -2646,15 +3092,24 @@ void Item_in_subselect::print(String *str, enum_query_type query_type) Item_subselect::print(str, query_type); } +bool Item_exists_subselect::fix_fields(THD *thd_arg, Item **ref) +{ + DBUG_ENTER("Item_exists_subselect::fix_fields"); + if (exists_transformed) + DBUG_RETURN( !( (*ref)= new Item_int(1))); + DBUG_RETURN(Item_subselect::fix_fields(thd_arg, ref)); +} + bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) { uint outer_cols_num; List<Item> *inner_cols; char const *save_where= thd->where; + DBUG_ENTER("Item_in_subselect::fix_fields"); if (test_strategy(SUBS_SEMI_JOIN)) - return !( (*ref)= new Item_int(1)); + DBUG_RETURN( !( (*ref)= new Item_int(1)) ); thd->where= "IN/ALL/ANY subquery"; /* @@ -2706,15 +3161,15 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) left_expr->fix_fields(thd_arg, &left_expr)) goto err; else - if (Item_subselect::fix_fields(thd_arg, ref)) - goto err; + if (Item_subselect::fix_fields(thd_arg, ref)) + goto err; fixed= TRUE; thd->where= save_where; - return FALSE; + DBUG_RETURN(FALSE); err: thd->where= save_where; - return TRUE; + DBUG_RETURN(TRUE); } @@ -2947,7 +3402,7 @@ bool subselect_union_engine::is_executed() const bool subselect_union_engine::no_rows() { /* Check if we got any rows when reading UNION result from temp. table: */ - return test(!unit->fake_select_lex->join->send_records); + return MY_TEST(!unit->fake_select_lex->join->send_records); } @@ -3784,7 +4239,7 @@ void subselect_uniquesubquery_engine::print(String *str) { KEY *key_info= tab->table->key_info + tab->ref.key; str->append(STRING_WITH_LEN("<primary_index_lookup>(")); - for (uint i= 0; i < key_info->key_parts; i++) + for (uint i= 0; i < key_info->user_defined_key_parts; i++) tab->ref.items[i]->print(str); str->append(STRING_WITH_LEN(" in ")); str->append(tab->table->s->table_name.str, tab->table->s->table_name.length); @@ -3842,6 +4297,7 @@ subselect_single_select_engine::change_result(Item_subselect *si, select_result_interceptor *res, bool temp) { + DBUG_ENTER("subselect_single_select_engine::change_result"); item= si; if (temp) { @@ -3862,7 +4318,7 @@ subselect_single_select_engine::change_result(Item_subselect *si, that would not require a lot of extra code that would be harder to manage than the current code. */ - return select_lex->join->change_result(res); + DBUG_RETURN(select_lex->join->change_result(res)); } @@ -4230,13 +4686,13 @@ ulonglong subselect_hash_sj_engine::rowid_merge_buff_size( */ static my_bool -bitmap_init_memroot(MY_BITMAP *map, uint n_bits, MEM_ROOT *mem_root) +my_bitmap_init_memroot(MY_BITMAP *map, uint n_bits, MEM_ROOT *mem_root) { my_bitmap_map *bitmap_buf; if (!(bitmap_buf= (my_bitmap_map*) alloc_root(mem_root, bitmap_buffer_size(n_bits))) || - bitmap_init(map, bitmap_buf, n_bits, FALSE)) + my_bitmap_init(map, bitmap_buf, n_bits, FALSE)) return TRUE; bitmap_clear_all(map); return FALSE; @@ -4274,9 +4730,9 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id) DBUG_ENTER("subselect_hash_sj_engine::init"); - if (bitmap_init_memroot(&non_null_key_parts, tmp_columns->elements, + if (my_bitmap_init_memroot(&non_null_key_parts, tmp_columns->elements, thd->mem_root) || - bitmap_init_memroot(&partial_match_key_parts, tmp_columns->elements, + my_bitmap_init_memroot(&partial_match_key_parts, tmp_columns->elements, thd->mem_root)) DBUG_RETURN(TRUE); @@ -4341,7 +4797,8 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id) DBUG_ASSERT( tmp_table->s->uniques || tmp_table->key_info->key_length >= tmp_table->file->max_key_length() || - tmp_table->key_info->key_parts > tmp_table->file->max_key_parts()); + tmp_table->key_info->user_defined_key_parts > + tmp_table->file->max_key_parts()); free_tmp_table(thd, tmp_table); tmp_table= NULL; delete result; @@ -4355,7 +4812,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id) */ DBUG_ASSERT(tmp_table->s->keys == 1 && ((Item_in_subselect *) item)->left_expr->cols() == - tmp_table->key_info->key_parts); + tmp_table->key_info->user_defined_key_parts); if (make_semi_join_conds() || /* A unique_engine is used both for complete and partial matching. */ @@ -4598,7 +5055,7 @@ double get_fanout_with_deps(JOIN *join, table_map tset) !tab->emb_sj_nest && tab->records_read != 0) { - fanout *= rows2double(tab->records_read); + fanout *= tab->records_read; } } return fanout; @@ -4785,8 +5242,8 @@ int subselect_hash_sj_engine::exec() /* The subquery should be optimized, and materialized only once. */ DBUG_ASSERT(materialize_join->optimized && !is_materialized); materialize_join->exec(); - if ((res= test(materialize_join->error || thd->is_fatal_error || - thd->is_error()))) + if ((res= MY_TEST(materialize_join->error || thd->is_fatal_error || + thd->is_error()))) goto err; /* @@ -4869,7 +5326,7 @@ int subselect_hash_sj_engine::exec() count_pm_keys= count_partial_match_columns - count_null_only_columns + (nn_key_parts ? 1 : 0); - choose_partial_match_strategy(test(nn_key_parts), + choose_partial_match_strategy(MY_TEST(nn_key_parts), has_covering_null_row, &partial_match_key_parts); DBUG_ASSERT(strategy == PARTIAL_MATCH_MERGE || @@ -4997,7 +5454,7 @@ Ordered_key::Ordered_key(uint keyid_arg, TABLE *tbl_arg, Item *search_key_arg, Ordered_key::~Ordered_key() { my_free(key_buff); - bitmap_free(&null_key); + my_bitmap_free(&null_key); } @@ -5098,7 +5555,7 @@ bool Ordered_key::alloc_keys_buffers() DBUG_ASSERT(key_buff_elements > 0); if (!(key_buff= (rownum_t*) my_malloc((size_t)(key_buff_elements * - sizeof(rownum_t)), MYF(MY_WME)))) + sizeof(rownum_t)), MYF(MY_WME | MY_THREAD_SPECIFIC)))) return TRUE; /* @@ -5107,7 +5564,7 @@ bool Ordered_key::alloc_keys_buffers() lookup offset. */ /* Notice that max_null_row is max array index, we need count, so +1. */ - if (bitmap_init(&null_key, NULL, (uint)(max_null_row + 1), FALSE)) + if (my_bitmap_init(&null_key, NULL, (uint)(max_null_row + 1), FALSE)) return TRUE; cur_key_idx= HA_POS_ERROR; @@ -5129,7 +5586,8 @@ int Ordered_key::cmp_keys_by_row_data(ha_rows a, ha_rows b) { uchar *rowid_a, *rowid_b; - int error, cmp_res; + int __attribute__((unused)) error; + int cmp_res; /* The length in bytes of the rowids (positions) of tmp_table. */ uint rowid_length= tbl->file->ref_length; @@ -5225,7 +5683,8 @@ int Ordered_key::cmp_key_with_search_key(rownum_t row_num) /* The length in bytes of the rowids (positions) of tmp_table. */ uint rowid_length= tbl->file->ref_length; uchar *cur_rowid= row_num_to_rowid + row_num * rowid_length; - int error, cmp_res; + int __attribute__((unused)) error; + int cmp_res; if ((error= tbl->file->ha_rnd_pos(tbl->record[0], cur_rowid))) { @@ -5523,7 +5982,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, !(null_bitmaps= (MY_BITMAP**) thd->alloc(merge_keys_count * sizeof(MY_BITMAP*))) || !(row_num_to_rowid= (uchar*) my_malloc((size_t)(row_count * rowid_length), - MYF(MY_WME)))) + MYF(MY_WME | MY_THREAD_SPECIFIC)))) return TRUE; /* Create the only non-NULL key if there is any. */ @@ -5544,8 +6003,8 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, */ if (!has_covering_null_columns) { - if (bitmap_init_memroot(&matching_keys, merge_keys_count, thd->mem_root) || - bitmap_init_memroot(&matching_outer_cols, merge_keys_count, thd->mem_root)) + if (my_bitmap_init_memroot(&matching_keys, merge_keys_count, thd->mem_root) || + my_bitmap_init_memroot(&matching_outer_cols, merge_keys_count, thd->mem_root)) return TRUE; /* @@ -5842,7 +6301,7 @@ bool subselect_rowid_merge_engine::partial_match() Do not add the non_null_key, since it was already processed above. */ bitmap_clear_all(&matching_outer_cols); - for (uint i= test(non_null_key); i < merge_keys_count; i++) + for (uint i= MY_TEST(non_null_key); i < merge_keys_count; i++) { DBUG_ASSERT(merge_keys[i]->get_column_count() == 1); if (merge_keys[i]->get_search_key(0)->null_value) @@ -5859,7 +6318,7 @@ bool subselect_rowid_merge_engine::partial_match() nullable columns (above we guarantee there is a match for the non-null coumns), the result is UNKNOWN. */ - if (count_nulls_in_search_key == merge_keys_count - test(non_null_key)) + if (count_nulls_in_search_key == merge_keys_count - MY_TEST(non_null_key)) { res= TRUE; goto end; |