diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 181 |
1 files changed, 100 insertions, 81 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd99a6e25f6..f2f2efc9e77 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -78,7 +78,6 @@ static store_key *get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part, char *key_buff, uint maybe_null); -static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void make_join_readinfo(JOIN *join, ulonglong options); @@ -100,7 +99,7 @@ static COND* substitute_for_best_equal_field(COND *cond, void *table_join_idx); static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top); -static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next); +static bool check_interleaving_with_nj(JOIN_TAB *next); static void restore_prev_nj_state(JOIN_TAB *last); static void reset_nj_counters(List<TABLE_LIST> *join_list); static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, @@ -1619,8 +1618,13 @@ JOIN::exec() We have to test for 'conds' here as the WHERE may not be constant even if we don't have any tables for prepared statements or if conds uses something like 'rand()'. + If the HAVING clause is either impossible or always true, then + JOIN::having is set to NULL by optimize_cond. + In this case JOIN::exec must check for JOIN::having_value, in the + same way it checks for JOIN::cond_value. */ if (cond_value != Item::COND_FALSE && + having_value != Item::COND_FALSE && (!conds || conds->val_int()) && (!having || having->val_int())) { @@ -1815,7 +1819,7 @@ JOIN::exec() /* Free first data from old join */ curr_join->join_free(); - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -1935,7 +1939,7 @@ JOIN::exec() curr_join->select_distinct=0; } curr_tmp_table->reginfo.lock_type= TL_UNLOCK; - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, curr_join->group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -2381,11 +2385,12 @@ typedef struct st_sargable_param */ static bool -make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, +make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, DYNAMIC_ARRAY *keyuse_array) { int error; TABLE *table; + TABLE_LIST *tables= tables_arg; uint i,table_count,const_count,key; table_map found_const_table_map, all_table_map, found_ref, refs; key_map const_ref, eq_part; @@ -2423,10 +2428,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, table_vector[i]=s->table=table=tables->table; table->pos_in_table_list= tables; error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); - if(error) + if (error) { - table->file->print_error(error, MYF(0)); - DBUG_RETURN(1); + table->file->print_error(error, MYF(0)); + goto error; } table->quick_keys.clear_all(); table->reginfo.join_tab=s; @@ -2511,7 +2516,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { join->tables=0; // Don't use join->table my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0)); - DBUG_RETURN(1); + goto error; } s->key_dependent= s->dependent; } @@ -2521,7 +2526,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables, conds, join->cond_equal, ~outer_join, join->select_lex, &sargables)) - DBUG_RETURN(1); + goto error; /* Read tables with 0 or 1 rows (system tables) */ join->const_table_map= 0; @@ -2537,7 +2542,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp=join_read_const_table(s, p_pos))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= s->table->map; @@ -2609,7 +2614,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp= join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2658,12 +2663,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, set_position(join,const_count++,s,start_keyuse); if (create_ref_for_key(join, s, start_keyuse, found_const_table_map)) - DBUG_RETURN(1); + goto error; if ((tmp=join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2740,7 +2745,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, *s->on_expr_ref ? *s->on_expr_ref : conds, 1, &error); if (!select) - DBUG_RETURN(1); + goto error; records= get_quick_record_count(join->thd, select, s->table, &s->const_keys, join->row_limit); s->quick=select->quick; @@ -2786,7 +2791,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { optimize_keyuse(join, keyuse_array); if (choose_plan(join, all_table_map & ~join->const_table_map)) - DBUG_RETURN(TRUE); + goto error; } else { @@ -2796,6 +2801,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, } /* Generate an execution plan from the found optimal join order. */ DBUG_RETURN(join->thd->killed || get_best_combination(join)); + +error: + /* + Need to clean up join_tab from TABLEs in case of error. + They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab + may not be assigned yet by this function (which is building join_tab). + Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke. + */ + for (tables= tables_arg; tables; tables= tables->next_leaf) + tables->table->reginfo.join_tab= NULL; + DBUG_RETURN (1); } @@ -4730,6 +4746,18 @@ greedy_search(JOIN *join, */ join->positions[idx]= best_pos; + /* + Update the interleaving state after extending the current partial plan + with a new table. + We are doing this here because best_extension_by_limited_search reverts + the interleaving state to the one of the non-extended partial plan + on exit. + */ + IF_DBUG(bool is_interleave_error= ) + check_interleaving_with_nj (best_table); + /* This has been already checked by best_extension_by_limited_search */ + DBUG_ASSERT(!is_interleave_error); + /* find the position of 'best_table' in 'join->best_ref' */ best_idx= idx; JOIN_TAB *pos= join->best_ref[best_idx]; @@ -4747,7 +4775,7 @@ greedy_search(JOIN *join, --size_remain; ++idx; - DBUG_EXECUTE("opt", print_plan(join, join->tables, + DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time, "extended");); } while (TRUE); @@ -4898,7 +4926,7 @@ best_extension_by_limited_search(JOIN *join, table_map real_table_bit= s->table->map; if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent) && - (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx || !check_interleaving_with_nj(s))) { double current_record_count, current_read_time; @@ -5043,7 +5071,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, { table_map real_table_bit=s->table->map; if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) && - (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx|| !check_interleaving_with_nj(s))) { double records, best; best_access_path(join, s, thd, rest_tables, idx, record_count, @@ -5426,48 +5454,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag) } -static bool -make_simple_join(JOIN *join,TABLE *tmp_table) +/** + @details Initialize a JOIN as a query execution plan + that accesses a single table via a table scan. + + @param parent contains JOIN_TAB and TABLE object buffers for this join + @param tmp_table temporary table + + @retval FALSE success + @retval TRUE error occurred +*/ +bool +JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) { - TABLE **tableptr; - JOIN_TAB *join_tab; - DBUG_ENTER("make_simple_join"); + DBUG_ENTER("JOIN::make_simple_join"); /* Reuse TABLE * and JOIN_TAB if already allocated by a previous call to this function through JOIN::exec (may happen for sub-queries). */ - if (!join->table_reexec) - { - if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->table_reexec= join->table_reexec; - } - if (!join->join_tab_reexec) - { - if (!(join->join_tab_reexec= - (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->join_tab_reexec= join->join_tab_reexec; - } - tableptr= join->table_reexec; - join_tab= join->join_tab_reexec; - - join->join_tab=join_tab; - join->table=tableptr; tableptr[0]=tmp_table; - join->tables=1; - join->const_tables=0; - join->const_table_map=0; - join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count= - join->tmp_table_param.func_count=0; - join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0; - join->first_record=join->sort_and_group=0; - join->send_records=(ha_rows) 0; - join->group=0; - join->row_limit=join->unit->select_limit_cnt; - join->do_send_rows = (join->row_limit) ? 1 : 0; + if (!parent->join_tab_reexec && + !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) + DBUG_RETURN(TRUE); /* purecov: inspected */ + + join_tab= parent->join_tab_reexec; + table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table; + tables= 1; + const_tables= 0; + const_table_map= 0; + tmp_table_param.field_count= tmp_table_param.sum_func_count= + tmp_table_param.func_count= 0; + tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; + first_record= sort_and_group=0; + send_records= (ha_rows) 0; + group= 0; + row_limit= unit->select_limit_cnt; + do_send_rows= row_limit ? 1 : 0; join_tab->cache.buff=0; /* No caching */ join_tab->table=tmp_table; @@ -5484,7 +5506,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join_tab->ref.key = -1; join_tab->not_used_in_distinct=0; join_tab->read_first_record= join_init_read_record; - join_tab->join=join; + join_tab->join= this; join_tab->ref.key_parts= 0; bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); tmp_table->status=0; @@ -7607,7 +7629,7 @@ static int compare_fields_by_table_order(Item_field *field1, if (outer_ref) return cmp; JOIN_TAB **idx= (JOIN_TAB **) table_join_idx; - cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr]; + cmp= (uint) (idx[field2->field->table->tablenr] - idx[field1->field->table->tablenr]); return cmp < 0 ? -1 : (cmp ? 1 : 0); } @@ -8415,9 +8437,6 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) SYNOPSIS check_interleaving_with_nj() - join Join being processed - last_tab Last table in current partial join order (this function is - not called for empty partial join orders) next_tab Table we're going to extend the current partial join with DESCRIPTION @@ -8502,10 +8521,10 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) TRUE Requested join order extension not allowed. */ -static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab) +static bool check_interleaving_with_nj(JOIN_TAB *next_tab) { TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding; - JOIN *join= last_tab->join; + JOIN *join= next_tab->join; if (join->cur_embedding_map & ~next_tab->embedding_map) { @@ -9637,7 +9656,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->s->default_values= table->record[1]+alloc_length; } copy_func[0]=0; // End marker - param->func_count= copy_func - param->items_to_copy; + param->func_count= (uint) (copy_func - param->items_to_copy); recinfo=param->start_recinfo; null_flags=(uchar*) table->record[0]; @@ -15210,10 +15229,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_int((int32) join->select_lex->select_number)); item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), cs)); + (uint) strlen(join->select_lex->type), cs)); for (uint i=0 ; i < 7; i++) item_list.push_back(item_null); - item_list.push_back(new Item_string(message,strlen(message),cs)); + item_list.push_back(new Item_string(message,(uint) strlen(message),cs)); if (result->send_data(item_list)) join->error= 1; } @@ -15232,7 +15251,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_null); /* select_type */ item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), + (uint) strlen(join->select_lex->type), cs)); /* table */ { @@ -15259,7 +15278,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, } /* type */ item_list.push_back(new Item_string(join_type_str[JT_ALL], - strlen(join_type_str[JT_ALL]), + (uint) strlen(join_type_str[JT_ALL]), cs)); /* possible_keys */ item_list.push_back(item_null); @@ -15308,7 +15327,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, join->select_lex->select_number)); /* select_type */ item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), + (uint) strlen(join->select_lex->type), cs)); if (tab->type == JT_ALL && tab->select && tab->select->quick) { @@ -15333,12 +15352,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { TABLE_LIST *real_table= table->pos_in_table_list; item_list.push_back(new Item_string(real_table->alias, - strlen(real_table->alias), + (uint) strlen(real_table->alias), cs)); } /* type */ item_list.push_back(new Item_string(join_type_str[tab->type], - strlen(join_type_str[tab->type]), + (uint) strlen(join_type_str[tab->type]), cs)); /* Build "possible_keys" value and add it to item_list */ if (!tab->keys.is_clear_all()) @@ -15351,7 +15370,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tmp1.length()) tmp1.append(','); tmp1.append(table->key_info[j].name, - strlen(table->key_info[j].name), + (uint) strlen(table->key_info[j].name), system_charset_info); } } @@ -15367,17 +15386,17 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, KEY *key_info=table->key_info+ tab->ref.key; register uint length; item_list.push_back(new Item_string(key_info->name, - strlen(key_info->name), + (uint) strlen(key_info->name), system_charset_info)); - length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - - keylen_str_buf; + length= (uint) (longlong2str(tab->ref.key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); for (store_key **ref=tab->ref.key_copy ; *ref ; ref++) { if (tmp2.length()) tmp2.append(','); - tmp2.append((*ref)->name(), strlen((*ref)->name()), + tmp2.append((*ref)->name(), (uint) strlen((*ref)->name()), system_charset_info); } item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs)); @@ -15387,9 +15406,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, KEY *key_info=table->key_info+ tab->index; register uint length; item_list.push_back(new Item_string(key_info->name, - strlen(key_info->name),cs)); - length= longlong2str(key_info->key_length, keylen_str_buf, 10) - - keylen_str_buf; + (uint) strlen(key_info->name),cs)); + length= (uint) (longlong2str(key_info->key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); @@ -15422,7 +15441,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, key_read=1; if (tab->info) - item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs)); + item_list.push_back(new Item_string(tab->info,(uint) strlen(tab->info),cs)); else if (tab->packed_info & TAB_INFO_HAVE_VALUE) { if (tab->packed_info & TAB_INFO_USING_INDEX) @@ -15746,7 +15765,7 @@ void TABLE_LIST::print(THD *thd, String *str) if (schema_table) { append_identifier(thd, str, schema_table_name, - strlen(schema_table_name)); + (uint) strlen(schema_table_name)); cmp_name= schema_table_name; } else @@ -15771,7 +15790,7 @@ void TABLE_LIST::print(THD *thd, String *str) } } - append_identifier(thd, str, t_alias, strlen(t_alias)); + append_identifier(thd, str, t_alias, (uint) strlen(t_alias)); } if (use_index) |