diff options
author | Michael Widenius <monty@mariadb.org> | 2017-11-14 07:47:58 +0200 |
---|---|---|
committer | Michael Widenius <monty@mariadb.org> | 2017-11-17 07:30:05 +0200 |
commit | 87933d52619c3f0df84922e23d5a8b03fa050133 (patch) | |
tree | 6e495d5f9bf731b055a4d7a582fa092d19c5929f /sql | |
parent | 31bd86c8df63a4d9e98d67541e136456bd6d9cc2 (diff) | |
download | mariadb-git-87933d52619c3f0df84922e23d5a8b03fa050133.tar.gz |
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
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 9 | ||||
-rw-r--r-- | sql/item_func.cc | 51 | ||||
-rw-r--r-- | sql/item_func.h | 2 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 85 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_delete.cc | 36 | ||||
-rw-r--r-- | sql/sql_explain.cc | 27 | ||||
-rw-r--r-- | sql/sql_explain.h | 4 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 32 | ||||
-rw-r--r-- | sql/sql_join_cache.h | 6 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 290 | ||||
-rw-r--r-- | sql/sql_select.h | 6 | ||||
-rw-r--r-- | sql/sql_string.h | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_tvc.cc | 8 | ||||
-rw-r--r-- | sql/sql_tvc.h | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 8 | ||||
-rw-r--r-- | sql/sql_update.cc | 11 | ||||
-rw-r--r-- | sql/sql_window.cc | 4 |
20 files changed, 389 insertions, 205 deletions
diff --git a/sql/item.cc b/sql/item.cc index 2285ae28041..fb620aa84d9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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) { /* diff --git a/sql/item_func.cc b/sql/item_func.cc index 0d32fdf1824..659ec29e452 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -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); } diff --git a/sql/item_func.h b/sql/item_func.h index 3ba2ebf9d86..c3a717614fb 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index b6378685268..72da68816ad 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -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, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7fd6599df51..0a84dc2b351 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -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; } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d0fc422c2f9..0d4bed836b8 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -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); } diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 05df9a21572..660d68427d1 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -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; } diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 154769fe289..895c059f1b0 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -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; } diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 2f1a81cc2ec..6df92f13585 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -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; } + return 0; } -void JOIN_CACHE_BKA::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); } -void JOIN_CACHE_BKAH::save_explain_data(EXPLAIN_BKA_TYPE *explain) +bool JOIN_CACHE_BKAH::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); } diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h index 4ae843ebfc2..f6894c6727d 100644 --- a/sql/sql_join_cache.h +++ b/sql/sql_join_cache.h @@ -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); }; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3cec59193ff..d4e438ab98c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -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() {} diff --git a/sql/sql_select.cc b/sql/sql_select.cc index abbf2616537..28600088153 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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(), ©_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); } diff --git a/sql/sql_select.h b/sql/sql_select.h index cc52cae02da..c1e5a9f95ce 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -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, diff --git a/sql/sql_string.h b/sql/sql_string.h index c88c58b1b40..41d31dc33c2 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -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 */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 58a6666b219..b021844427c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -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 */ diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 8c8e132746e..79e894f5a7f 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -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; } diff --git a/sql/sql_tvc.h b/sql/sql_tvc.h index b4fca78262b..7861f6fd16b 100644 --- a/sql/sql_tvc.h +++ b/sql/sql_tvc.h @@ -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); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8cce7f33057..40f4f984e0a 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -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 { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 47ec8b89d48..bd577426483 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -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> ¬_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); } diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 4bcdca3ca11..bf393ab1c4d 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -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; |