diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 19 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 11 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 8 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 14 | ||||
-rw-r--r-- | sql/item_xmlfunc.cc | 4 | ||||
-rw-r--r-- | sql/key.cc | 4 | ||||
-rw-r--r-- | sql/sp.cc | 8 | ||||
-rw-r--r-- | sql/sp_head.cc | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 3 | ||||
-rw-r--r-- | sql/sql_show.cc | 13 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 7 |
12 files changed, 64 insertions, 40 deletions
diff --git a/sql/item.cc b/sql/item.cc index 5645a1bee1c..b1e453121bd 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7503,9 +7503,19 @@ void Item_cache_datetime::store(Item *item, longlong val_arg) } +void Item_cache_datetime::store(Item *item) +{ + Item_cache::store(item); + str_value_cached= FALSE; +} + String *Item_cache_datetime::val_str(String *str) { DBUG_ASSERT(fixed == 1); + + if ((value_cached || str_value_cached) && null_value) + return NULL; + if (!str_value_cached) { /* @@ -7519,6 +7529,8 @@ String *Item_cache_datetime::val_str(String *str) if (value_cached) { MYSQL_TIME ltime; + /* Return NULL in case of OOM/conversion error. */ + null_value= TRUE; if (str_value.alloc(MAX_DATE_STRING_REP_LENGTH)) return NULL; if (cached_field_type == MYSQL_TYPE_TIME) @@ -7541,13 +7553,14 @@ String *Item_cache_datetime::val_str(String *str) { int was_cut; longlong res; - res= number_to_datetime(val_int(), <ime, TIME_FUZZY_DATE, &was_cut); + res= number_to_datetime(int_value, <ime, TIME_FUZZY_DATE, &was_cut); if (res == -1) return NULL; } str_value.length(my_TIME_to_str(<ime, const_cast<char*>(str_value.ptr()))); str_value_cached= TRUE; + null_value= FALSE; } else if (!cache_value()) return NULL; @@ -7568,7 +7581,7 @@ my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val) double Item_cache_datetime::val_real() { DBUG_ASSERT(fixed == 1); - if (!value_cached && !cache_value_int()) + if ((!value_cached && !cache_value_int()) || null_value) return 0.0; return (double) int_value; } @@ -7576,7 +7589,7 @@ double Item_cache_datetime::val_real() longlong Item_cache_datetime::val_int() { DBUG_ASSERT(fixed == 1); - if (!value_cached && !cache_value_int()) + if ((!value_cached && !cache_value_int()) || null_value) return 0; return int_value; } diff --git a/sql/item.h b/sql/item.h index e65bacf4cb7..2249cc9dd4a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3451,8 +3451,8 @@ public: cmp_context= STRING_RESULT; } - virtual void store(Item *item) { Item_cache::store(item); } void store(Item *item, longlong val_arg); + void store(Item *item); double val_real(); longlong val_int(); String* val_str(String *str); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 18a92c6b8c2..737fa02bcd2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4720,6 +4720,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) String *escape_str= escape_item->val_str(&cmp.value1); if (escape_str) { + const char *escape_str_ptr= escape_str->ptr(); if (escape_used_in_parsing && ( (((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) && escape_str->numchars() != 1) || @@ -4734,9 +4735,9 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) CHARSET_INFO *cs= escape_str->charset(); my_wc_t wc; int rc= cs->cset->mb_wc(cs, &wc, - (const uchar*) escape_str->ptr(), - (const uchar*) escape_str->ptr() + - escape_str->length()); + (const uchar*) escape_str_ptr, + (const uchar*) escape_str_ptr + + escape_str->length()); escape= (int) (rc > 0 ? wc : '\\'); } else @@ -4753,13 +4754,13 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) { char ch; uint errors; - uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(), + uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str_ptr, escape_str->length(), escape_str->charset(), &errors); escape= cnvlen ? ch : '\\'; } else - escape= *(escape_str->ptr()); + escape= escape_str_ptr ? *escape_str_ptr : '\\'; } } else diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3c92c829144..2a93bcd0153 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1080,9 +1080,15 @@ String *Item_func_replace::val_str(String *str) search=res2->ptr(); search_end=search+from_length; redo: + DBUG_ASSERT(res->ptr() || !offset); ptr=res->ptr()+offset; strend=res->ptr()+res->length(); - end=strend-from_length+1; + /* + In some cases val_str() can return empty string + with ptr() == NULL and length() == 0. + Let's check strend to avoid overflow. + */ + end= strend ? strend - from_length + 1 : NULL; while (ptr < end) { if (*ptr == *search) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3771706fb63..73b8b6047e0 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2526,14 +2526,14 @@ String *Item_char_typecast::val_str(String *str) { // Convert character set if differ uint dummy_errors; - if (!(res= args[0]->val_str(&tmp_value)) || - str->copy(res->ptr(), res->length(), from_cs, - cast_cs, &dummy_errors)) + if (!(res= args[0]->val_str(str)) || + tmp_value.copy(res->ptr(), res->length(), from_cs, + cast_cs, &dummy_errors)) { null_value= 1; return 0; } - res= str; + res= &tmp_value; } res->set_charset(cast_cs); @@ -2568,9 +2568,9 @@ String *Item_char_typecast::val_str(String *str) { if (res->alloced_length() < (uint) cast_length) { - str->alloc(cast_length); - str->copy(*res); - res= str; + str_value.alloc(cast_length); + str_value.copy(*res); + res= &str_value; } bzero((char*) res->ptr() + res->length(), (uint) cast_length - res->length()); diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index f124c37f0eb..49d18b1bb0f 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -2798,12 +2798,12 @@ String *Item_func_xml_extractvalue::val_str(String *str) null_value= 0; if (!nodeset_func || !(res= args[0]->val_str(str)) || - !parse_xml(res, &pxml)) + !parse_xml(res, &pxml) || + !(res= nodeset_func->val_str(&tmp_value))) { null_value= 1; return 0; } - res= nodeset_func->val_str(&tmp_value); return res; } diff --git a/sql/key.cc b/sql/key.cc index e28e0803986..288afd034a9 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -364,9 +364,7 @@ void key_unpack(String *to,TABLE *table,uint idx) while (tmp_end > tmp.ptr() && !*--tmp_end) ; tmp.length(tmp_end - tmp.ptr() + 1); } - if (cs->mbmaxlen > 1 && - table->field[key_part->fieldnr - 1]->field_length != - key_part->length) + if (cs->mbmaxlen > 1 && (key_part->key_part_flag & HA_PART_KEY_SEG)) { /* Prefix key, multi-byte charset. diff --git a/sql/sp.cc b/sql/sp.cc index 5d424564317..ae11c2ad14c 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -779,9 +779,6 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, int ret= 0; - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&ret)) - return TRUE; - thd->lex= &newlex; newlex.current_select= NULL; @@ -1375,6 +1372,8 @@ public: MYSQL_ERROR ** cond_hdl) { if (sql_errno == ER_NO_SUCH_TABLE || + sql_errno == ER_CANNOT_LOAD_FROM_TABLE || + sql_errno == ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE || sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED) return true; return false; @@ -1611,9 +1610,6 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, (int) name->m_name.length, name->m_name.str, type, cache_only)); - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&depth)) - return NULL; - if ((sp= sp_cache_lookup(cp, name))) { ulong level; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6017541266b..6959d21abd6 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1240,8 +1240,11 @@ sp_head::execute(THD *thd, bool merge_da_on_success) The same with db_load_routine() required circa 7k bytes and 14k bytes accordingly. Hence, here we book the stack with some reasonable margin. + + Reverting back to 8 * STACK_MIN_SIZE until further fix. + 8 * STACK_MIN_SIZE is required on some exotic platforms. */ - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&old_packet)) + if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (uchar*)&old_packet)) DBUG_RETURN(TRUE); /* init per-instruction memroot */ @@ -2915,9 +2918,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, It's merged with the saved parent's value at the exit of this func. */ bool parent_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&parent_modified_non_trans_table)) - DBUG_RETURN(TRUE); - thd->transaction.stmt.modified_non_trans_table= FALSE; DBUG_ASSERT(!thd->derived_tables); DBUG_ASSERT(thd->change_list.is_empty()); @@ -3073,9 +3073,6 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_ENTER("sp_instr_stmt::execute"); DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command())); - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res)) - DBUG_RETURN(TRUE); - const CSET_STRING query_backup= thd->query_string; #if defined(ENABLED_PROFILING) /* This s-p instr is profilable and will be captured. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c4782f37417..e5aac6a5a81 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7209,9 +7209,6 @@ bool parse_sql(THD *thd, Object_creation_ctx *backup_ctx= NULL; - if (check_stack_overrun(thd, 2 * STACK_MIN_SIZE, (uchar*)&backup_ctx)) - return TRUE; - if (creation_ctx) backup_ctx= creation_ctx->set_n_backup(thd); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 58b15ed1ec7..0421cc35c5d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -29,6 +29,8 @@ #include "repl_failsafe.h" #include "sql_parse.h" // check_access, check_table_access #include "sql_partition.h" // partition_element +#include "sql_derived.h" // mysql_derived_prepare, + // mysql_handle_derived, #include "sql_db.h" // check_db_dir_existence, load_db_opt_by_name #include "sql_time.h" // interval_type_to_name #include "tztime.h" // struct Time_zone @@ -677,11 +679,18 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW; { + /* + Use open_tables() directly rather than open_normal_and_derived_tables(). + This ensures that close_thread_tables() is not called if open tables fails + and the error is ignored. This allows us to handle broken views nicely. + */ + uint counter; Show_create_error_handler view_error_suppressor(thd, table_list); thd->push_internal_handler(&view_error_suppressor); bool open_error= - open_normal_and_derived_tables(thd, table_list, - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL); + open_tables(thd, &table_list, &counter, + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) || + mysql_handle_derived(thd->lex, &mysql_derived_prepare); thd->pop_internal_handler(); if (open_error && (thd->killed || thd->is_error())) goto exit; diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 0cff2875ac8..909c6a08b67 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -472,6 +472,13 @@ bool Truncate_statement::truncate_table(THD *thd, TABLE_LIST *table_ref) binlog_stmt= !error || error != HA_ERR_WRONG_COMMAND; } + /* + If we tried to open a MERGE table and failed due to problems with the + children tables, the table will have been closed and table_ref->table + will be invalid. Reset the pointer here in any case as + query_cache_invalidate does not need a valid TABLE object. + */ + table_ref->table= NULL; query_cache_invalidate3(thd, table_ref, FALSE); } |