summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc181
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)