Handle failures from malloc

Most "new" failures fixed in the following files:
- sql_select.cc
- item.cc
- item_func.cc
- opt_subselect.cc

Other things:
- Allocate udf_handler strings in mem_root
  - Required changes in sql_string.h
- Add mem_root as argument to some new [] calls
- Mark udf_handler strings as thread specific
- Removed some comment blocks with code
This commit is contained in:
Michael Widenius 2017-11-14 07:47:58 +02:00
parent 31bd86c8df
commit 87933d5261
21 changed files with 394 additions and 210 deletions

View File

@ -1261,7 +1261,7 @@ Item *Item::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
if (!needs_charset_converter(tocs))
return this;
Item_func_conv_charset *conv= new (thd->mem_root) Item_func_conv_charset(thd, this, tocs, 1);
return conv->safe ? conv : NULL;
return conv && conv->safe ? conv : NULL;
}
@ -3237,6 +3237,11 @@ table_map Item_field::all_used_tables() const
return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map);
}
/*
@Note thd->fatal_error can be set in case of OOM
*/
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@ -3296,6 +3301,8 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref,
}
Name_resolution_context *ctx= new Name_resolution_context();
if (!ctx)
return; // Fatal error set
if (context->select_lex == new_parent)
{
/*

View File

@ -3253,17 +3253,15 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
func->used_tables_and_const_cache_join(item);
f_args.arg_type[i]=item->result_type();
}
//TODO: why all following memory is not allocated with 1 thd->alloc() call?
if (!(buffers=new String[arg_count]) ||
!(f_args.args= (char**) thd->alloc(arg_count * sizeof(char *))) ||
!(f_args.lengths= (ulong*) thd->alloc(arg_count * sizeof(long))) ||
!(f_args.maybe_null= (char*) thd->alloc(arg_count * sizeof(char))) ||
!(num_buffer= (char*) thd->alloc(arg_count *
ALIGN_SIZE(sizeof(double)))) ||
!(f_args.attributes= (const char**) thd->alloc(arg_count *
sizeof(char *))) ||
!(f_args.attribute_lengths= (ulong*) thd->alloc(arg_count *
sizeof(long))))
if (!(buffers=new (thd->mem_root) String[arg_count]) ||
!multi_alloc_root(thd->mem_root,
&f_args.args, arg_count * sizeof(char *),
&f_args.lengths, arg_count * sizeof(long),
&f_args.maybe_null, arg_count * sizeof(char),
&num_buffer, arg_count * sizeof(double),
&f_args.attributes, arg_count * sizeof(char *),
&f_args.attribute_lengths, arg_count * sizeof(long),
NullS))
{
free_udf(u_d);
DBUG_RETURN(TRUE);
@ -3275,6 +3273,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
initid.const_item=func->const_item_cache;
initid.decimals=func->decimals;
initid.ptr=0;
for (uint i1= 0 ; i1 < arg_count ; i1++)
buffers[i1].set_thread_specific();
if (u_d->func_init)
{
@ -5299,8 +5299,8 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command,
Item_func_set_user_var(thd, name,
new (thd->mem_root) Item_null(thd))),
thd->mem_root);
/* Create the variable */
if (sql_set_variables(thd, &tmp_var_list, false))
/* Create the variable if the above allocations succeeded */
if (thd->is_fatal_error || sql_set_variables(thd, &tmp_var_list, false))
{
thd->lex= sav_lex;
goto err;
@ -5837,20 +5837,25 @@ void Item_func_get_system_var::cleanup()
cached_strval.free();
}
/**
@retval
0 ok
1 OOM error
*/
void Item_func_match::init_search(THD *thd, bool no_order)
bool Item_func_match::init_search(THD *thd, bool no_order)
{
DBUG_ENTER("Item_func_match::init_search");
if (!table->file->get_table()) // the handler isn't opened yet
DBUG_VOID_RETURN;
DBUG_RETURN(0);
/* Check if init_search() has been called before */
if (ft_handler)
{
if (join_key)
table->file->ft_handler= ft_handler;
DBUG_VOID_RETURN;
DBUG_RETURN(0);
}
if (key == NO_SUCH_KEY)
@ -5862,6 +5867,8 @@ void Item_func_match::init_search(THD *thd, bool no_order)
for (uint i= 1; i < arg_count; i++)
fields.push_back(args[i]);
concat_ws= new (thd->mem_root) Item_func_concat_ws(thd, fields);
if (thd->is_fatal_error)
DBUG_RETURN(1); // OOM
/*
Above function used only to get value and do not need fix_fields for it:
Item_string - basic constant
@ -5874,10 +5881,11 @@ void Item_func_match::init_search(THD *thd, bool no_order)
if (master)
{
join_key= master->join_key= join_key | master->join_key;
master->init_search(thd, no_order);
if (master->init_search(thd, no_order))
DBUG_RETURN(1);
ft_handler= master->ft_handler;
join_key= master->join_key;
DBUG_VOID_RETURN;
DBUG_RETURN(0);
}
String *ft_tmp= 0;
@ -5892,8 +5900,9 @@ void Item_func_match::init_search(THD *thd, bool no_order)
if (ft_tmp->charset() != cmp_collation.collation)
{
uint dummy_errors;
search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
cmp_collation.collation, &dummy_errors);
if (search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
cmp_collation.collation, &dummy_errors))
DBUG_RETURN(1);
ft_tmp= &search_value;
}
@ -5908,7 +5917,7 @@ void Item_func_match::init_search(THD *thd, bool no_order)
if (join_key)
table->file->ft_handler=ft_handler;
DBUG_VOID_RETURN;
DBUG_RETURN(0);
}

View File

@ -2584,7 +2584,7 @@ public:
virtual void print(String *str, enum_query_type query_type);
bool fix_index();
void init_search(THD *thd, bool no_order);
bool init_search(THD *thd, bool no_order);
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function("match ... against()", arg, VCOL_IMPOSSIBLE);

View File

@ -461,7 +461,7 @@ void best_access_path(JOIN *join, JOIN_TAB *s,
static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
Item_in_subselect *subq_pred);
static void remove_sj_conds(THD *thd, Item **tree);
static bool remove_sj_conds(THD *thd, Item **tree);
static bool is_cond_sj_in_equality(Item *item);
static bool sj_table_is_included(JOIN *join, JOIN_TAB *join_tab);
static Item *remove_additional_cond(Item* conds);
@ -1750,9 +1750,9 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/
Item_row *row= new (thd->mem_root) Item_row(thd, subq_lex->pre_fix);
/* fix fields on subquery was call so they should be the same */
DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols());
if (!row)
DBUG_RETURN(TRUE);
DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols());
nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr);
Item_func_eq *item_eq=
new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, row);
@ -1839,7 +1839,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
}
parent_lex->have_merged_subqueries= TRUE;
DBUG_RETURN(FALSE);
/* Fatal error may have been set to by fix_after_pullout() */
DBUG_RETURN(thd->is_fatal_error);
}
@ -1880,6 +1881,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
bool optimization_delayed= TRUE;
TABLE_LIST *jtbm;
char *tbl_alias;
THD *thd= parent_join->thd;
DBUG_ENTER("convert_subq_to_jtbm");
subq_pred->set_strategy(SUBS_MATERIALIZATION);
@ -1887,8 +1889,8 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
*remove_item= TRUE;
if (!(tbl_alias= (char*)parent_join->thd->calloc(SUBQERY_TEMPTABLE_NAME_MAX_LEN)) ||
!(jtbm= alloc_join_nest(parent_join->thd))) //todo: this is not a join nest!
if (!(tbl_alias= (char*)thd->calloc(SUBQERY_TEMPTABLE_NAME_MAX_LEN)) ||
!(jtbm= alloc_join_nest(thd))) //todo: this is not a join nest!
{
DBUG_RETURN(TRUE);
}
@ -1900,13 +1902,13 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
/* Nests do not participate in those 'chains', so: */
/* jtbm->next_leaf= jtbm->next_local= jtbm->next_global == NULL*/
emb_join_list->push_back(jtbm, parent_join->thd->mem_root);
emb_join_list->push_back(jtbm, thd->mem_root);
/*
Inject the jtbm table into TABLE_LIST::next_leaf list, so that
make_join_statistics() and co. can find it.
*/
parent_lex->leaf_tables.push_back(jtbm, parent_join->thd->mem_root);
parent_lex->leaf_tables.push_back(jtbm, thd->mem_root);
if (subq_pred->unit->first_select()->options & OPTION_SCHEMA_TABLE)
parent_lex->options |= OPTION_SCHEMA_TABLE;
@ -1931,7 +1933,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
subq_pred->unit->first_select()->select_number);
jtbm->alias= tbl_alias;
parent_join->table_count++;
DBUG_RETURN(FALSE);
DBUG_RETURN(thd->is_fatal_error);
}
subselect_hash_sj_engine *hash_sj_engine=
((subselect_hash_sj_engine*)subq_pred->engine);
@ -1954,27 +1956,10 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
jtbm->alias= tbl_alias;
parent_lex->have_merged_subqueries= TRUE;
#if 0
/* Inject sj_on_expr into the parent's WHERE or ON */
if (emb_tbl_nest)
{
DBUG_ASSERT(0);
/*emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr,
sj_nest->sj_on_expr);
emb_tbl_nest->on_expr->fix_fields(parent_join->thd, &emb_tbl_nest->on_expr);
*/
}
else
{
/* Inject into the WHERE */
parent_join->conds= and_items(parent_join->conds, conds);
parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds);
parent_join->select_lex->where= parent_join->conds;
}
#endif
/* Don't unlink the child subselect, as the subquery will be used. */
DBUG_RETURN(FALSE);
DBUG_RETURN(thd->is_fatal_error);
}
@ -1989,6 +1974,9 @@ static TABLE_LIST *alloc_join_nest(THD *thd)
return tbl;
}
/*
@Note thd->is_fatal_error can be set in case of OOM
*/
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist)
{
@ -3718,6 +3706,11 @@ bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab)
DBUG_RETURN(FALSE);
}
/**
@retval
FALSE ok
TRUE error
*/
bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
{
@ -3730,8 +3723,6 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
SJ_MATERIALIZATION_INFO *sjm= emb_sj_nest->sj_mat_info;
THD *thd= tab->join->thd;
uint i;
//List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list;
//List_iterator<Item> it(item_list);
if (!sjm->is_sj_scan)
{
@ -3781,6 +3772,8 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
null_count ? cur_ref_buff : 0,
cur_key_part->length, tab_ref->items[i],
FALSE);
if (!*ref_key)
DBUG_RETURN(TRUE);
cur_ref_buff+= cur_key_part->store_length;
}
*ref_key= NULL; /* End marker. */
@ -3806,9 +3799,9 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
*/
for (i= 0; i < sjm->tables; i++)
{
remove_sj_conds(thd, &tab[i].select_cond);
if (tab[i].select)
remove_sj_conds(thd, &tab[i].select->cond);
if (remove_sj_conds(thd, &tab[i].select_cond) ||
(tab[i].select && remove_sj_conds(thd, &tab[i].select->cond)))
DBUG_RETURN(TRUE);
}
if (!(sjm->in_equality= create_subq_in_equalities(thd, sjm,
emb_sj_nest->sj_subq_pred)))
@ -3845,7 +3838,9 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
temptable record, we copy its columns to their corresponding columns
in the record buffers for the source tables.
*/
sjm->copy_field= new Copy_field[sjm->sjm_table_cols.elements];
if (!(sjm->copy_field= new Copy_field[sjm->sjm_table_cols.elements]))
DBUG_RETURN(TRUE);
//it.rewind();
Ref_ptr_array p_items= emb_sj_nest->sj_subq_pred->unit->first_select()->ref_pointer_array;
for (uint i=0; i < sjm->sjm_table_cols.elements; i++)
@ -3972,16 +3967,20 @@ static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
}
/**
@retval
0 ok
1 error
*/
static void remove_sj_conds(THD *thd, Item **tree)
static bool remove_sj_conds(THD *thd, Item **tree)
{
if (*tree)
{
if (is_cond_sj_in_equality(*tree))
{
*tree= NULL;
return;
return 0;
}
else if ((*tree)->type() == Item::COND_ITEM)
{
@ -3990,12 +3989,19 @@ static void remove_sj_conds(THD *thd, Item **tree)
while ((item= li++))
{
if (is_cond_sj_in_equality(item))
li.replace(new (thd->mem_root) Item_int(thd, 1));
{
Item_int *tmp= new (thd->mem_root) Item_int(thd, 1);
if (!tmp)
return 1;
li.replace(tmp);
}
}
}
}
return 0;
}
/* Check if given Item was injected by semi-join equality */
static bool is_cond_sj_in_equality(Item *item)
{
@ -4183,7 +4189,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
share->db_plugin= ha_lock_engine(0, heap_hton);
table->file= get_new_handler(share, &table->mem_root,
share->db_type());
DBUG_ASSERT(uniq_tuple_length_arg <= table->file->max_key_length());
DBUG_ASSERT(!table->file || uniq_tuple_length_arg <= table->file->max_key_length());
}
if (!table->file)
goto err;
@ -5302,6 +5308,9 @@ TABLE *create_dummy_tmp_table(THD *thd)
sjm_table_param.field_count= 1;
List<Item> sjm_table_cols;
Item *column_item= new (thd->mem_root) Item_int(thd, 1);
if (!column_item)
DBUG_RETURN(NULL);
sjm_table_cols.push_back(column_item, thd->mem_root);
if (!(table= create_tmp_table(thd, &sjm_table_param,
sjm_table_cols, (ORDER*) 0,

View File

@ -8481,7 +8481,8 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
DBUG_PRINT("info",("Performing FULLTEXT search"));
while ((ifm=li++))
ifm->init_search(thd, no_order);
if (ifm->init_search(thd, no_order))
return 1;
}
return 0;
}

View File

@ -61,6 +61,8 @@ Explain_delete* Delete_plan::save_explain_delete_data(MEM_ROOT *mem_root, THD *t
Explain_query *query= thd->lex->explain;
Explain_delete *explain=
new (mem_root) Explain_delete(mem_root, thd->lex->analyze_stmt);
if (!explain)
return 0;
if (deleting_all_rows)
{
@ -71,8 +73,9 @@ Explain_delete* Delete_plan::save_explain_delete_data(MEM_ROOT *mem_root, THD *t
else
{
explain->deleting_all_rows= false;
Update_plan::save_explain_data_intern(mem_root, explain,
thd->lex->analyze_stmt);
if (Update_plan::save_explain_data_intern(mem_root, explain,
thd->lex->analyze_stmt))
return 0;
}
query->add_upd_del_plan(explain);
@ -86,13 +89,16 @@ Update_plan::save_explain_update_data(MEM_ROOT *mem_root, THD *thd)
Explain_query *query= thd->lex->explain;
Explain_update* explain=
new (mem_root) Explain_update(mem_root, thd->lex->analyze_stmt);
save_explain_data_intern(mem_root, explain, thd->lex->analyze_stmt);
if (!explain)
return 0;
if (save_explain_data_intern(mem_root, explain, thd->lex->analyze_stmt))
return 0;
query->add_upd_del_plan(explain);
return explain;
}
void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
Explain_update *explain,
bool is_analyze)
{
@ -105,13 +111,13 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
if (impossible_where)
{
explain->impossible_where= true;
return;
return 0;
}
if (no_partitions)
{
explain->no_partitions= true;
return;
return 0;
}
if (is_analyze)
@ -162,7 +168,8 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
explain->where_cond= select? select->cond: NULL;
if (using_filesort)
explain->filesort_tracker= new (mem_root) Filesort_tracker(is_analyze);
if (!(explain->filesort_tracker= new (mem_root) Filesort_tracker(is_analyze)))
return 1;
explain->using_io_buffer= using_io_buffer;
append_possible_keys(mem_root, explain->possible_keys, table,
@ -211,6 +218,7 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
if (!(unit->item && unit->item->eliminated))
explain->add_child(unit->first_select()->select_number);
}
return 0;
}
@ -385,7 +393,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_type= THD::STMT_QUERY_TYPE;
error= -1;
deleted= maybe_deleted;
query_plan.save_explain_delete_data(thd->mem_root, thd);
if (!query_plan.save_explain_delete_data(thd->mem_root, thd))
error= 1;
goto cleanup;
}
if (error != HA_ERR_WRONG_COMMAND)
@ -503,7 +512,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (thd->lex->describe)
goto produce_explain_and_leave;
explain= query_plan.save_explain_delete_data(thd->mem_root, thd);
if (!(explain= query_plan.save_explain_delete_data(thd->mem_root, thd)))
goto got_error;
ANALYZE_START_TRACKING(&explain->command_tracker);
DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start",
@ -555,7 +565,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (error)
goto got_error;
init_ftfuncs(thd, select_lex, 1);
if (init_ftfuncs(thd, select_lex, 1))
goto got_error;
if (table->prepare_triggers_for_delete_stmt_or_event())
{
@ -766,7 +777,8 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE,
no-partitions-used, impossible-range, etc.
*/
query_plan.save_explain_delete_data(thd->mem_root, thd);
if (!(query_plan.save_explain_delete_data(thd->mem_root, thd)))
goto got_error;
send_nothing_and_leave:
/*
@ -1066,7 +1078,7 @@ multi_delete::initialize_tables(JOIN *join)
MEM_STRIP_BUF_SIZE);
}
init_ftfuncs(thd, thd->lex->current_select, 1);
DBUG_RETURN(thd->is_fatal_error != 0);
DBUG_RETURN(thd->is_fatal_error);
}

View File

@ -1143,33 +1143,37 @@ void Explain_table_access::fill_key_len_str(String *key_len_str) const
}
void Explain_index_use::set(MEM_ROOT *mem_root, KEY *key, uint key_len_arg)
bool Explain_index_use::set(MEM_ROOT *mem_root, KEY *key, uint key_len_arg)
{
set_pseudo_key(mem_root, key->name.str);
if (set_pseudo_key(mem_root, key->name.str))
return 1;
key_len= key_len_arg;
uint len= 0;
for (uint i= 0; i < key->usable_key_parts; i++)
{
key_parts_list.append_str(mem_root,
key->key_part[i].field->field_name.str);
if (!key_parts_list.append_str(mem_root,
key->key_part[i].field->field_name.str))
return 1;
len += key->key_part[i].store_length;
if (len >= key_len_arg)
break;
}
return 0;
}
void Explain_index_use::set_pseudo_key(MEM_ROOT *root, const char* key_name_arg)
bool Explain_index_use::set_pseudo_key(MEM_ROOT *root, const char* key_name_arg)
{
if (key_name_arg)
{
size_t name_len= strlen(key_name_arg);
if ((key_name= (char*)alloc_root(root, name_len+1)))
memcpy(key_name, key_name_arg, name_len+1);
if (!(key_name= strdup_root(root, key_name_arg)))
return 1;
}
else
key_name= NULL;
key_len= ~(uint) 0;
return 0;
}
@ -2450,8 +2454,11 @@ int Explain_range_checked_fer::append_possible_keys_stat(MEM_ROOT *alloc,
for (j= 0; j < table->s->keys; j++)
{
if (possible_keys.is_set(j))
keys_stat_names[j]= key_set.append_str(alloc,
table->key_info[j].name.str);
{
if (!(keys_stat_names[j]= key_set.append_str(alloc,
table->key_info[j].name.str)))
return 1;
}
else
keys_stat_names[j]= NULL;
}

View File

@ -589,8 +589,8 @@ public:
key_name= NULL;
key_len= (uint)-1;
}
void set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
void set_pseudo_key(MEM_ROOT *root, const char *key_name);
bool set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
bool set_pseudo_key(MEM_ROOT *root, const char *key_name);
inline const char *get_key_name() const { return key_name; }
inline uint get_key_len() const { return key_len; }

View File

@ -2571,10 +2571,11 @@ finish:
BNLH, BKA or BKAH) to the data structure
RETURN VALUE
none
0 ok
1 error
*/
void JOIN_CACHE::save_explain_data(EXPLAIN_BKA_TYPE *explain)
bool JOIN_CACHE::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
explain->incremental= MY_TEST(prev_cache);
@ -2596,6 +2597,7 @@ void JOIN_CACHE::save_explain_data(EXPLAIN_BKA_TYPE *explain)
default:
DBUG_ASSERT(0);
}
return 0;
}
/**
@ -2608,7 +2610,7 @@ THD *JOIN_CACHE::thd()
}
static void add_mrr_explain_info(String *str, uint mrr_mode, handler *file)
static bool add_mrr_explain_info(String *str, uint mrr_mode, handler *file)
{
char mrr_str_buf[128]={0};
int len;
@ -2617,22 +2619,30 @@ static void add_mrr_explain_info(String *str, uint mrr_mode, handler *file)
if (len > 0)
{
if (str->length())
str->append(STRING_WITH_LEN("; "));
str->append(mrr_str_buf, len);
{
if (str->append(STRING_WITH_LEN("; ")))
return 1;
}
if (str->append(mrr_str_buf, len))
return 1;
}
}
void JOIN_CACHE_BKA::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
JOIN_CACHE::save_explain_data(explain);
add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
return 0;
}
void JOIN_CACHE_BKAH::save_explain_data(EXPLAIN_BKA_TYPE *explain)
bool JOIN_CACHE_BKA::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
JOIN_CACHE::save_explain_data(explain);
add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
if (JOIN_CACHE::save_explain_data(explain))
return 1;
return add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
}
bool JOIN_CACHE_BKAH::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
if (JOIN_CACHE::save_explain_data(explain))
return 1;
return add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
}

View File

@ -662,7 +662,7 @@ public:
enum_nested_loop_state join_records(bool skip_last);
/* Add a comment on the join algorithm employed by the join cache */
virtual void save_explain_data(EXPLAIN_BKA_TYPE *explain);
virtual bool save_explain_data(EXPLAIN_BKA_TYPE *explain);
THD *thd();
@ -1340,7 +1340,7 @@ public:
/* Check index condition of the joined table for a record from BKA cache */
bool skip_index_tuple(range_id_t range_info);
void save_explain_data(EXPLAIN_BKA_TYPE *explain);
bool save_explain_data(EXPLAIN_BKA_TYPE *explain);
};
@ -1431,5 +1431,5 @@ public:
/* Check index condition of the joined table for a record from BKAH cache */
bool skip_index_tuple(range_id_t range_info);
void save_explain_data(EXPLAIN_BKA_TYPE *explain);
bool save_explain_data(EXPLAIN_BKA_TYPE *explain);
};

View File

@ -2588,7 +2588,7 @@ public:
Explain_update* save_explain_update_data(MEM_ROOT *mem_root, THD *thd);
protected:
void save_explain_data_intern(MEM_ROOT *mem_root, Explain_update *eu, bool is_analyze);
bool save_explain_data_intern(MEM_ROOT *mem_root, Explain_update *eu, bool is_analyze);
public:
virtual ~Update_plan() {}

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
Copyright (c) 2009, 2016 MariaDB
Copyright (c) 2009, 2016, 2017 MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -713,7 +713,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
union_part= unit_arg->is_unit_op();
if (select_lex->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
DBUG_RETURN(-1);
thd->lex->current_select->context_analysis_place= NO_MATTER;
thd->lex->current_select->is_item_list_lookup= 1;
@ -948,6 +948,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
(*ord->item)->field_type() == MYSQL_TYPE_BIT)
{
Item_field *field= new (thd->mem_root) Item_field(thd, *(Item_field**)ord->item);
if (!field)
DBUG_RETURN(-1);
int el= all_fields.elements;
ref_ptrs[el]= field;
all_fields.push_front(field, thd->mem_root);
@ -1080,14 +1082,16 @@ err:
DBUG_RETURN(res); /* purecov: inspected */
}
void JOIN::build_explain()
bool JOIN::build_explain()
{
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE;
save_explain_data(thd->lex->explain, false /* can overwrite */,
need_tmp,
!skip_sort_order && !no_order && (order || group_list),
select_distinct);
if (save_explain_data(thd->lex->explain, false /* can overwrite */,
need_tmp,
!skip_sort_order && !no_order && (order || group_list),
select_distinct))
return 1;
uint select_nr= select_lex->select_number;
JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt();
for (uint i= 0; i < aggr_tables; i++, curr_tab++)
@ -1105,8 +1109,10 @@ void JOIN::build_explain()
get_using_temporary_read_tracker();
}
}
return 0;
}
int JOIN::optimize()
{
int res= 0;
@ -1126,7 +1132,7 @@ int JOIN::optimize()
init_state == JOIN::OPTIMIZATION_PHASE_1_DONE)
{
if (!res && have_query_plan != QEP_DELETED)
build_explain();
res= build_explain();
optimization_state= JOIN::OPTIMIZATION_DONE;
}
return res;
@ -1720,6 +1726,9 @@ int JOIN::optimize_stage2()
{
ref_item= substitute_for_best_equal_field(thd, tab, ref_item,
equals, map2table);
if (thd->is_fatal_error)
DBUG_RETURN(1);
if (first_inner)
{
equals= first_inner->cond_equal;
@ -2032,7 +2041,8 @@ int JOIN::optimize_stage2()
/* Perform FULLTEXT search before all regular searches */
if (!(select_options & SELECT_DESCRIBE))
init_ftfuncs(thd, select_lex, MY_TEST(order));
if (init_ftfuncs(thd, select_lex, MY_TEST(order)))
DBUG_RETURN(1);
/*
It's necessary to check const part of HAVING cond as
@ -2419,7 +2429,8 @@ bool JOIN::make_aggr_tables_info()
if (gbh)
{
pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh);
if (!(pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh)))
DBUG_RETURN(1);
/*
We must store rows in the tmp table if we need to do an ORDER BY
or DISTINCT and the storage handler can't handle it.
@ -2436,7 +2447,8 @@ bool JOIN::make_aggr_tables_info()
curr_tab->ref.key= -1;
curr_tab->join= this;
curr_tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param);
if (!(curr_tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param)))
DBUG_RETURN(1);
TABLE* table= create_tmp_table(thd, curr_tab->tmp_table_param,
all_fields,
NULL, query.distinct,
@ -2446,7 +2458,8 @@ bool JOIN::make_aggr_tables_info()
if (!table)
DBUG_RETURN(1);
curr_tab->aggr= new (thd->mem_root) AGGR_OP(curr_tab);
if (!(curr_tab->aggr= new (thd->mem_root) AGGR_OP(curr_tab)))
DBUG_RETURN(1);
curr_tab->aggr->set_write_func(::end_send);
curr_tab->table= table;
/*
@ -2886,7 +2899,8 @@ bool JOIN::make_aggr_tables_info()
curr_tab= join_tab + exec_join_tab_cnt() + aggr_tables - 1;
if (select_lex->window_funcs.elements)
{
curr_tab->window_funcs_step= new Window_funcs_computation;
if (!(curr_tab->window_funcs_step= new Window_funcs_computation))
DBUG_RETURN(true);
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs,
curr_tab))
DBUG_RETURN(true);
@ -2928,7 +2942,8 @@ JOIN::create_postjoin_aggr_table(JOIN_TAB *tab, List<Item> *table_fields,
!select_lex->with_sum_func) ?
select_limit : HA_POS_ERROR;
tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param);
if (!(tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param)))
DBUG_RETURN(true);
tab->tmp_table_param->skip_create_table= true;
TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields,
table_group, distinct,
@ -2942,8 +2957,7 @@ JOIN::create_postjoin_aggr_table(JOIN_TAB *tab, List<Item> *table_fields,
DBUG_ASSERT(tab > tab->join->join_tab || !top_join_tab_count || !tables_list);
if (tab > join_tab)
(tab - 1)->next_select= sub_select_postjoin_aggr;
tab->aggr= new (thd->mem_root) AGGR_OP(tab);
if (!tab->aggr)
if (!(tab->aggr= new (thd->mem_root) AGGR_OP(tab)))
goto err;
tab->table= table;
table->reginfo.join_tab= tab;
@ -3093,33 +3107,42 @@ bool JOIN::setup_subquery_caches()
select_lex->expr_cache_may_be_used[IN_ON] ||
select_lex->expr_cache_may_be_used[NO_MATTER])
{
if (conds)
conds= conds->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
JOIN_TAB *tab;
if (conds &&
!(conds= conds->transform(thd, &Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
{
if (tab->select_cond)
tab->select_cond=
tab->select_cond->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (tab->select_cond &&
!(tab->select_cond=
tab->select_cond->transform(thd,
&Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
if (tab->cache_select && tab->cache_select->cond)
tab->cache_select->cond=
tab->cache_select->
cond->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (!(tab->cache_select->cond=
tab->cache_select->
cond->transform(thd, &Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
}
if (having)
having= having->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (having &&
!(having= having->transform(thd,
&Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
if (tmp_having)
{
DBUG_ASSERT(having == NULL);
tmp_having= tmp_having->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (!(tmp_having=
tmp_having->transform(thd,
&Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
}
}
if (select_lex->expr_cache_may_be_used[SELECT_LIST] ||
@ -3130,9 +3153,11 @@ bool JOIN::setup_subquery_caches()
Item *item;
while ((item= li++))
{
Item *new_item=
item->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
Item *new_item;
if (!(new_item=
item->transform(thd, &Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
if (new_item != item)
{
thd->change_item_tree(li.ref(), new_item);
@ -3140,18 +3165,22 @@ bool JOIN::setup_subquery_caches()
}
for (ORDER *tmp_group= group_list; tmp_group ; tmp_group= tmp_group->next)
{
*tmp_group->item=
(*tmp_group->item)->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (!(*tmp_group->item=
(*tmp_group->item)->transform(thd,
&Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
}
}
if (select_lex->expr_cache_may_be_used[NO_MATTER])
{
for (ORDER *ord= order; ord; ord= ord->next)
{
*ord->item=
(*ord->item)->transform(thd, &Item::expr_cache_insert_transformer,
NULL);
if (!(*ord->item=
(*ord->item)->transform(thd,
&Item::expr_cache_insert_transformer,
NULL)))
DBUG_RETURN(TRUE);
}
}
DBUG_RETURN(FALSE);
@ -3276,7 +3305,8 @@ JOIN::reinit()
}
if (!(select_options & SELECT_DESCRIBE))
init_ftfuncs(thd, select_lex, MY_TEST(order));
if (init_ftfuncs(thd, select_lex, MY_TEST(order)))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
@ -3318,7 +3348,14 @@ err:
}
void JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
/**
@retval
0 ok
1 error
*/
bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
bool need_tmp_table, bool need_order,
bool distinct)
{
@ -3337,9 +3374,8 @@ void JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
/* It's a degenerate join */
message= zero_result_cause ? zero_result_cause : "No tables used";
}
save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order,
distinct, message);
return;
return save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order,
distinct, message);
}
/*
@ -3359,11 +3395,13 @@ void JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
{
if (join_tab[i].filesort)
{
join_tab[i].filesort->tracker=
new Filesort_tracker(thd->lex->analyze_stmt);
if (!(join_tab[i].filesort->tracker=
new Filesort_tracker(thd->lex->analyze_stmt)))
return 1;
}
}
}
return 0;
}
@ -12241,7 +12279,8 @@ bool JOIN_TAB::preread_init()
/* init ftfuns for just initialized derived table */
if (table->fulltext_searched)
init_ftfuncs(join->thd, join->select_lex, MY_TEST(join->order));
if (init_ftfuncs(join->thd, join->select_lex, MY_TEST(join->order)))
return TRUE;
return FALSE;
}
@ -14422,7 +14461,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
This works OK with PS/SP re-execution as changes are made to
the arguments of AND/OR items only
*/
if (new_item != item)
if (new_item && new_item != item)
li.replace(new_item);
}
@ -14501,7 +14540,9 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
while((item_equal= it++))
{
REPLACE_EQUAL_FIELD_ARG arg= {item_equal, context_tab};
cond= cond->transform(thd, &Item::replace_equal_field, (uchar *) &arg);
if (!(cond= cond->transform(thd, &Item::replace_equal_field,
(uchar *) &arg)))
return 0;
}
cond_equal= cond_equal->upper_levels;
}
@ -14658,6 +14699,7 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
{
cond->marker=1;
COND_CMP *tmp2;
/* Will work, even if malloc would fail */
if ((tmp2= new (thd->mem_root) COND_CMP(and_father, func)))
save_list->push_back(tmp2);
}
@ -14690,6 +14732,7 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
thd->change_item_tree(args + 1, value);
cond->marker=1;
COND_CMP *tmp2;
/* Will work, even if malloc would fail */
if ((tmp2=new (thd->mem_root) COND_CMP(and_father, func)))
save_list->push_back(tmp2);
}
@ -16121,6 +16164,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
query_cache_abort(thd, &thd->query_cache_tls);
#endif
COND *new_cond, *cond= this;
/* If this fails, we will catch it later before executing query */
if ((new_cond= new (thd->mem_root) Item_func_eq(thd, args[0],
new (thd->mem_root) Item_int(thd, "last_insert_id()",
thd->read_first_successful_insert_id_in_prev_stmt(),
@ -16958,7 +17002,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
Item *arg= sum_item->get_arg(i);
if (!arg->const_item())
{
Field *new_field=
Item *tmp_item;
Field *new_field=
create_tmp_field(thd, table, arg, arg->type(), &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,not_all_columns,
@ -16983,7 +17028,10 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
string_total_length+= new_field->pack_length();
}
thd->mem_root= mem_root_save;
arg= sum_item->set_arg(i, thd, new (thd->mem_root) Item_temptable_field(thd, new_field));
if (!(tmp_item= new (thd->mem_root)
Item_temptable_field(thd, new_field)))
goto err;
arg= sum_item->set_arg(i, thd, tmp_item);
thd->mem_root= &table->mem_root;
if (param->force_not_null_cols)
{
@ -22859,6 +22907,10 @@ setup_new_fields(THD *thd, List<Item> &fields,
Try to use the fields in the order given by 'order' to allow one to
optimize away 'order by'.
@retval
0 OOM error if thd->is_fatal_error is set. Otherwise group was eliminated
# Pointer to new group
*/
ORDER *
@ -22921,6 +22973,8 @@ create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
BIT type and will be returned [el]client.
*/
Item_field *new_item= new (thd->mem_root) Item_field(thd, (Item_field*)item);
if (!new_item)
return 0;
int el= all_fields.elements;
orig_ref_pointer_array[el]= new_item;
all_fields.push_front(new_item, thd->mem_root);
@ -23602,7 +23656,10 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
item_field= item;
else if (item->type() == Item::FIELD_ITEM)
item_field= item->get_tmp_table_item(thd);
{
if (!(item_field= item->get_tmp_table_item(thd)))
DBUG_RETURN(true);
}
else if (item->type() == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC)
{
@ -23710,8 +23767,13 @@ change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
if (item->type() == Item::SUM_FUNC_ITEM && item->const_item())
new_item= item;
else
new_item= item->get_tmp_table_item(thd);
res_all_fields.push_back(new_item, thd->mem_root);
{
if (!(new_item= item->get_tmp_table_item(thd)))
return 1;
}
if (res_all_fields.push_back(new_item, thd->mem_root))
return 1;
ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
new_item;
}
@ -24077,7 +24139,9 @@ bool JOIN::rollup_init()
*/
for (i= 0 ; i < send_group_parts ; i++)
{
rollup.null_items[i]= new (thd->mem_root) Item_null_result(thd);
if (!(rollup.null_items[i]= new (thd->mem_root) Item_null_result(thd)))
return true;
List<Item> *rollup_fields= &rollup.fields[i];
rollup_fields->empty();
rollup.ref_pointer_arrays[i]= Ref_ptr_array(ref_array, all_fields.elements);
@ -24421,8 +24485,12 @@ void JOIN::clear()
}
/*
/**
Print an EXPLAIN line with all NULLs and given message in the 'Extra' column
@retval
0 ok
1 OOM error or error from send_data()
*/
int print_explain_message_line(select_result_sink *result,
@ -24481,7 +24549,7 @@ int print_explain_message_line(select_result_sink *result,
else
item_list.push_back(item_null, mem_root);
if (result->send_data(item_list))
if (thd->is_fatal_error || result->send_data(item_list))
return 1;
return 0;
}
@ -24515,13 +24583,14 @@ int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table,
for (j=0 ; j < table->s->keys ; j++)
{
if (possible_keys.is_set(j))
list.append_str(alloc, table->key_info[j].name.str);
if (!(list.append_str(alloc, table->key_info[j].name.str)))
return 1;
}
return 0;
}
void JOIN_TAB::save_explain_data(Explain_table_access *eta,
bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
table_map prefix_tables,
bool distinct_arg, JOIN_TAB *first_top_tab)
{
@ -24550,9 +24619,11 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
if (filesort)
{
eta->pre_join_sort= new Explain_aggr_filesort(thd->mem_root,
thd->lex->analyze_stmt,
filesort);
if (!(eta->pre_join_sort=
new Explain_aggr_filesort(thd->mem_root,
thd->lex->analyze_stmt,
filesort)))
return 1;
}
tracker= &eta->tracker;
@ -24649,7 +24720,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
// psergey-todo: why does this use thd MEM_ROOT??? Doesn't this
// break ANALYZE ? thd->mem_root will be freed, and after that we will
// attempt to print the query plan?
append_possible_keys(thd->mem_root, eta->possible_keys, table, keys);
if (append_possible_keys(thd->mem_root, eta->possible_keys, table, keys))
return 1;
// psergey-todo: ^ check for error return code
/* Build "key", "key_len", and "ref" */
@ -24670,7 +24742,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
*/
if (tab_select && tab_select->quick && tab_type != JT_CONST)
{
eta->quick_info= tab_select->quick->get_explain(thd->mem_root);
if (!(eta->quick_info= tab_select->quick->get_explain(thd->mem_root)))
return 1;
}
if (key_info) /* 'index' or 'ref' access */
@ -24683,10 +24756,14 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
for (uint kp= 0; kp < ref.key_parts; kp++)
{
if ((key_part_map(1) << kp) & ref.const_ref_part_map)
eta->ref_list.append_str(thd->mem_root, "const");
{
if (!(eta->ref_list.append_str(thd->mem_root, "const")))
return 1;
}
else
{
eta->ref_list.append_str(thd->mem_root, (*key_ref)->name());
if (!(eta->ref_list.append_str(thd->mem_root, (*key_ref)->name())))
return 1;
key_ref++;
}
}
@ -24943,7 +25020,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
if (cache)
{
eta->push_extra(ET_USING_JOIN_BUFFER);
cache->save_explain_data(&eta->bka_type);
if (cache->save_explain_data(&eta->bka_type))
return 1;
}
}
@ -24956,15 +25034,21 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
/* The same for non-merged semi-joins */
eta->non_merged_sjm_number = get_non_merged_semijoin_select();
return 0;
}
/*
Walk through join->aggr_tables and save aggregation/grouping query plan into
an Explain_select object
@retval
0 ok
1 error
*/
void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
bool save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
{
JOIN_TAB *join_tab=join->join_tab + join->exec_join_tab_cnt();
Explain_aggr_node *prev_node;
@ -24976,7 +25060,8 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
{
// Each aggregate means a temp.table
prev_node= node;
node= new Explain_aggr_tmp_table;
if (!(node= new Explain_aggr_tmp_table))
return 1;
node->child= prev_node;
if (join_tab->window_funcs_step)
@ -24984,19 +25069,20 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
Explain_aggr_node *new_node=
join_tab->window_funcs_step->save_explain_plan(thd->mem_root,
is_analyze);
if (new_node)
{
prev_node=node;
node= new_node;
node->child= prev_node;
}
if (!new_node)
return 1;
prev_node=node;
node= new_node;
node->child= prev_node;
}
/* The below matches execution in join_init_read_record() */
if (join_tab->distinct)
{
prev_node= node;
node= new Explain_aggr_remove_dups;
if (!(node= new Explain_aggr_remove_dups))
return 1;
node->child= prev_node;
}
@ -25004,20 +25090,27 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
{
Explain_aggr_filesort *eaf =
new Explain_aggr_filesort(thd->mem_root, is_analyze, join_tab->filesort);
if (!eaf)
return 1;
prev_node= node;
node= eaf;
node->child= prev_node;
}
}
xpl_sel->aggr_tree= node;
return 0;
}
/*
/**
Save Query Plan Footprint
@note
Currently, this function may be called multiple times
@retval
0 ok
1 error
*/
int JOIN::save_explain_data_intern(Explain_query *output,
@ -25026,7 +25119,6 @@ int JOIN::save_explain_data_intern(Explain_query *output,
const char *message)
{
JOIN *join= this; /* Legacy: this code used to be a non-member function */
int cur_error= 0;
DBUG_ENTER("JOIN::save_explain_data_intern");
DBUG_PRINT("info", ("Select %p, type %s, message %s",
join->select_lex, join->select_lex->type,
@ -25044,8 +25136,11 @@ int JOIN::save_explain_data_intern(Explain_query *output,
if (message)
{
explain= new (output->mem_root) Explain_select(output->mem_root,
thd->lex->analyze_stmt);
if (!(explain= new (output->mem_root)
Explain_select(output->mem_root,
thd->lex->analyze_stmt)))
DBUG_RETURN(1);
join->select_lex->set_explain_type(true);
explain->select_id= join->select_lex->select_number;
@ -25058,13 +25153,17 @@ int JOIN::save_explain_data_intern(Explain_query *output,
if (select_lex->master_unit()->derived)
explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
save_agg_explain_data(this, explain);
if (save_agg_explain_data(this, explain))
DBUG_RETURN(1);
output->add_node(explain);
}
else if (pushdown_query)
{
explain= new (output->mem_root) Explain_select(output->mem_root,
thd->lex->analyze_stmt);
if (!(explain= new (output->mem_root)
Explain_select(output->mem_root,
thd->lex->analyze_stmt)))
DBUG_RETURN(1);
select_lex->set_explain_type(true);
explain->select_id= select_lex->select_number;
@ -25084,6 +25183,9 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain= xpl_sel=
new (output->mem_root) Explain_select(output->mem_root,
thd->lex->analyze_stmt);
if (!explain)
DBUG_RETURN(1);
table_map used_tables=0;
join->select_lex->set_explain_type(true);
@ -25093,7 +25195,8 @@ int JOIN::save_explain_data_intern(Explain_query *output,
if (select_lex->master_unit()->derived)
xpl_sel->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
save_agg_explain_data(this, xpl_sel);
if (save_agg_explain_data(this, xpl_sel))
DBUG_RETURN(1);
xpl_sel->exec_const_cond= exec_const_cond;
xpl_sel->outer_ref_cond= outer_ref_cond;
@ -25125,6 +25228,8 @@ int JOIN::save_explain_data_intern(Explain_query *output,
Explain_table_access *eta= (new (output->mem_root)
Explain_table_access(output->mem_root));
if (!eta)
DBUG_RETURN(1);
if (tab->bush_root_tab != prev_bush_root_tab)
{
if (tab->bush_root_tab)
@ -25132,7 +25237,9 @@ int JOIN::save_explain_data_intern(Explain_query *output,
/*
We've entered an SJ-Materialization nest. Create an object for it.
*/
cur_parent= new (output->mem_root) Explain_basic_join(output->mem_root);
if (!(cur_parent=
new (output->mem_root) Explain_basic_join(output->mem_root)))
DBUG_RETURN(1);
JOIN_TAB *first_child= tab->bush_root_tab->bush_children->start;
cur_parent->select_id=
@ -25152,7 +25259,8 @@ int JOIN::save_explain_data_intern(Explain_query *output,
prev_bush_root_tab= tab->bush_root_tab;
cur_parent->add_table(eta, output);
tab->save_explain_data(eta, used_tables, distinct_arg, first_top_tab);
if (tab->save_explain_data(eta, used_tables, distinct_arg, first_top_tab))
DBUG_RETURN(1);
if (saved_join_tab)
tab= saved_join_tab;
@ -25184,10 +25292,10 @@ int JOIN::save_explain_data_intern(Explain_query *output,
}
}
if (!cur_error && select_lex->is_top_level_node())
if (select_lex->is_top_level_node())
output->query_plan_ready();
DBUG_RETURN(cur_error);
DBUG_RETURN(0);
}

View File

@ -608,7 +608,7 @@ typedef struct st_join_table {
void remove_redundant_bnl_scan_conds();
void save_explain_data(Explain_table_access *eta, table_map prefix_tables,
bool save_explain_data(Explain_table_access *eta, table_map prefix_tables,
bool distinct, struct st_join_table *first_top_tab);
bool use_order() const; ///< Use ordering provided by chosen index?
@ -1526,7 +1526,7 @@ public:
int optimize();
int optimize_inner();
int optimize_stage2();
void build_explain();
bool build_explain();
int reinit();
int init_execution();
void exec();
@ -1667,7 +1667,7 @@ public:
{
return (unit->item && unit->item->is_in_predicate());
}
void save_explain_data(Explain_query *output, bool can_overwrite,
bool save_explain_data(Explain_query *output, bool can_overwrite,
bool need_tmp_table, bool need_order, bool distinct);
int save_explain_data_intern(Explain_query *output, bool need_tmp_table,
bool need_order, bool distinct,

View File

@ -181,6 +181,8 @@ public:
}
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
{ return (void*) alloc_root(mem_root, (uint) size); }
static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
{ return alloc_root(mem_root, size); }
static void operator delete(void *ptr_arg, size_t size)
{
(void) ptr_arg;
@ -189,6 +191,10 @@ public:
}
static void operator delete(void *, MEM_ROOT *)
{ /* never called */ }
static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); }
static void operator delete[](void *ptr, MEM_ROOT *mem_root)
{ /* never called */ }
~String() { free(); }
/* Mark variable thread specific it it's not allocated already */

View File

@ -9697,7 +9697,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (mysql_trans_prepare_alter_copy_data(thd))
DBUG_RETURN(-1);
if (!(copy= new Copy_field[to->s->fields]))
if (!(copy= new (thd->mem_root) Copy_field[to->s->fields]))
DBUG_RETURN(-1); /* purecov: inspected */
/* We need external lock before we can disable/enable keys */

View File

@ -283,6 +283,9 @@ int table_value_constr::save_explain_data_intern(THD *thd,
explain= new (output->mem_root) Explain_select(output->mem_root,
thd->lex->analyze_stmt);
if (!explain)
DBUG_RETURN(1);
select_lex->set_explain_type(true);
explain->select_id= select_lex->select_number;
@ -309,7 +312,7 @@ int table_value_constr::save_explain_data_intern(THD *thd,
Optimization of TVC
*/
void table_value_constr::optimize(THD *thd)
bool table_value_constr::optimize(THD *thd)
{
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE;
@ -320,8 +323,9 @@ void table_value_constr::optimize(THD *thd)
thd->lex->explain && // for "SET" command in SPs.
(!thd->lex->explain->get_select(select_lex->select_number)))
{
save_explain_data_intern(thd, thd->lex->explain);
return save_explain_data_intern(thd, thd->lex->explain);
}
return 0;
}

View File

@ -57,7 +57,7 @@ public:
int save_explain_data_intern(THD *thd_arg,
Explain_query *output);
void optimize(THD *thd_arg);
bool optimize(THD *thd_arg);
bool exec(SELECT_LEX *sl);
void print(THD *thd_arg, String *str, enum_query_type query_type);

View File

@ -1282,7 +1282,11 @@ bool st_select_lex_unit::optimize()
sl->tvc->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
sl->tvc->optimize(thd);
if (sl->tvc->optimize(thd))
{
thd->lex->current_select= lex_select_save;
DBUG_RETURN(TRUE);
}
continue;
}
thd->lex->current_select= sl;
@ -1397,7 +1401,7 @@ bool st_select_lex_unit::exec()
sl->tvc->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
sl->tvc->optimize(thd);
saved_error= sl->tvc->optimize(thd);
}
else
{

View File

@ -451,7 +451,8 @@ int mysql_update(THD *thd,
goto err;
}
}
init_ftfuncs(thd, select_lex, 1);
if (init_ftfuncs(thd, select_lex, 1))
goto err;
table->mark_columns_needed_for_update();
@ -522,7 +523,8 @@ int mysql_update(THD *thd,
*/
if (thd->lex->describe)
goto produce_explain_and_leave;
explain= query_plan.save_explain_update_data(query_plan.mem_root, thd);
if (!(explain= query_plan.save_explain_update_data(query_plan.mem_root, thd)))
goto err;
ANALYZE_START_TRACKING(&explain->command_tracker);
@ -1046,7 +1048,8 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE,
no-partitions-used, impossible-range, etc.
*/
query_plan.save_explain_update_data(query_plan.mem_root, thd);
if (!query_plan.save_explain_update_data(query_plan.mem_root, thd))
goto err;
emit_explain_and_leave:
int err2= thd->lex->explain->send_explain(thd);
@ -1776,7 +1779,7 @@ int multi_update::prepare(List<Item> &not_used_values,
switch_to_nullable_trigger_fields(*values_for_table[i], table);
}
}
copy_field= new Copy_field[max_fields];
copy_field= new (thd->mem_root) Copy_field[max_fields];
DBUG_RETURN(thd->is_fatal_error != 0);
}

View File

@ -3093,10 +3093,14 @@ Window_funcs_computation::save_explain_plan(MEM_ROOT *mem_root,
Explain_aggr_window_funcs *xpl= new Explain_aggr_window_funcs;
List_iterator<Window_funcs_sort> it(win_func_sorts);
Window_funcs_sort *srt;
if (!xpl)
return 0;
while ((srt = it++))
{
Explain_aggr_filesort *eaf=
new Explain_aggr_filesort(mem_root, is_analyze, srt->filesort);
if (!eaf)
return 0;
xpl->sorts.push_back(eaf, mem_root);
}
return xpl;

View File

@ -4290,9 +4290,9 @@ int ha_mroonga::storage_open_columns(void)
{
if (blob_buffers)
{
delete [] blob_buffers;
::delete [] blob_buffers;
}
if (!(blob_buffers = new String[n_columns]))
if (!(blob_buffers = ::new String[n_columns]))
{
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}