Skip to content
Permalink
Browse files
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
  • Loading branch information
montywi committed Nov 17, 2017
1 parent 31bd86c commit 87933d5
Show file tree
Hide file tree
Showing 21 changed files with 391 additions and 207 deletions.
@@ -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)
{
/*
@@ -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);
}


@@ -2584,7 +2584,7 @@ class Item_func_match :public Item_real_func
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);
@@ -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,15 +1881,16 @@ 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);
subq_pred->is_jtbm_merged= TRUE;

*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,

0 comments on commit 87933d5

Please sign in to comment.