diff options
author | Nirbhay Choubey <nirbhay@mariadb.com> | 2015-06-21 23:54:55 -0400 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@mariadb.com> | 2015-06-21 23:54:55 -0400 |
commit | 46024098be1d7887134a3a3d8d289dd7711c56dc (patch) | |
tree | c175b6b9f5913b2c2424ca4fa799b1c545e3d9a5 /sql | |
parent | 41d40029875bfd7f4cd6a5255e05a3c93103220f (diff) | |
parent | a6087e7dc1ef3561d8189c8db15e9591d0f9b520 (diff) | |
download | mariadb-git-46024098be1d7887134a3a3d8d289dd7711c56dc.tar.gz |
Merge tag 'mariadb-10.0.20' into 10.0-galera
Diffstat (limited to 'sql')
37 files changed, 553 insertions, 342 deletions
diff --git a/sql/field.cc b/sql/field.cc index 31d8b46e587..c5319ae0b72 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1307,18 +1307,13 @@ int Field_num::check_int(CHARSET_INFO *cs, const char *str, int length, if (str == int_end || error == MY_ERRNO_EDOM) { ErrConvString err(str, length, cs); - push_warning_printf(get_thd(), Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, - ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "integer", err.ptr(), field_name, - (ulong) table->in_use->get_stmt_da()-> - current_row_for_warning()); + set_warning_truncated_wrong_value("integer", err.ptr()); return 1; } /* Test if we have garbage at the end of the given string. */ if (test_if_important_data(cs, int_end, str + length)) { - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); return 2; } return 0; @@ -1387,7 +1382,7 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len, return 0; out_of_range: - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } @@ -1408,12 +1403,12 @@ int Field::warn_if_overflow(int op_result) { if (op_result == E_DEC_OVERFLOW) { - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } if (op_result == E_DEC_TRUNCATED) { - set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); + set_note(WARN_DATA_TRUNCATED, 1); /* We return 0 here as this is not a critical issue */ } return 0; @@ -1739,7 +1734,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val, { if (val->sign()) { - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); i= 0; *err= 1; } @@ -2047,7 +2042,7 @@ void Field_decimal::overflow(bool negative) uint len=field_length; uchar *to=ptr, filler= '9'; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); if (negative) { if (!unsigned_flag) @@ -2155,7 +2150,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) from++; if (from == end) { - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); is_cuted_fields_incr=1; } else if (*from == '+' || *from == '-') // Found some sign ? @@ -2231,7 +2226,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) for (;from != end && my_isspace(&my_charset_bin, *from); from++) ; if (from != end) // If still something left, warn { - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); is_cuted_fields_incr=1; } } @@ -2409,8 +2404,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) if (tmp_char != '0') // Losing a non zero digit ? { if (!is_cuted_fields_incr) - set_warning(Sql_condition::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); return 0; } continue; @@ -2432,7 +2426,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) This is a note, not a warning, as we don't want to abort when we cut decimals in strict mode */ - set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); + set_note(WARN_DATA_TRUNCATED, 1); } return 0; } @@ -2633,7 +2627,7 @@ void Field_decimal::sql_type(String &res) const if (dec) tmp--; res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "decimal(%d,%d)",tmp,dec)); + "decimal(%d,%d)/*old*/",tmp,dec)); add_zerofill_and_unsigned(res); } @@ -2782,7 +2776,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) if (unsigned_flag && decimal_value->sign()) { DBUG_PRINT("info", ("unsigned overflow")); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; decimal_value= &decimal_zero; } @@ -2826,32 +2820,22 @@ int Field_new_decimal::store(const char *from, uint length, thd->abort_on_warning) { ErrConvString errmsg(from, length, charset_arg); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, - ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", errmsg.ptr(), field_name, - static_cast<ulong>(thd->get_stmt_da()-> - current_row_for_warning())); + set_warning_truncated_wrong_value("decimal", errmsg.ptr()); DBUG_RETURN(err); } switch (err) { case E_DEC_TRUNCATED: - set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); + set_note(WARN_DATA_TRUNCATED, 1); break; case E_DEC_OVERFLOW: - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_value_on_overflow(&decimal_value, decimal_value.sign()); break; case E_DEC_BAD_NUM: { ErrConvString errmsg(from, length, charset_arg); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, - ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", errmsg.ptr(), field_name, - static_cast<ulong>(thd->get_stmt_da()-> - current_row_for_warning())); + set_warning_truncated_wrong_value("decimal", errmsg.ptr()); my_decimal_set_zero(&decimal_value); break; } @@ -3158,13 +3142,13 @@ int Field_tiny::store(double nr) if (nr < 0.0) { *ptr=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > 255.0) { *ptr= (uchar) 255; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3175,13 +3159,13 @@ int Field_tiny::store(double nr) if (nr < -128.0) { *ptr= (uchar) -128; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > 127.0) { *ptr=127; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3201,13 +3185,13 @@ int Field_tiny::store(longlong nr, bool unsigned_val) if (nr < 0 && !unsigned_val) { *ptr= 0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if ((ulonglong) nr > (ulonglong) 255) { *ptr= (char) 255; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3220,13 +3204,13 @@ int Field_tiny::store(longlong nr, bool unsigned_val) if (nr < -128) { *ptr= (char) -128; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > 127) { *ptr=127; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3337,13 +3321,13 @@ int Field_short::store(double nr) if (nr < 0) { res=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > (double) UINT_MAX16) { res=(int16) UINT_MAX16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3354,13 +3338,13 @@ int Field_short::store(double nr) if (nr < (double) INT_MIN16) { res=INT_MIN16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > (double) INT_MAX16) { res=INT_MAX16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3382,13 +3366,13 @@ int Field_short::store(longlong nr, bool unsigned_val) if (nr < 0L && !unsigned_val) { res=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if ((ulonglong) nr > (ulonglong) UINT_MAX16) { res=(int16) UINT_MAX16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3402,13 +3386,13 @@ int Field_short::store(longlong nr, bool unsigned_val) if (nr < INT_MIN16) { res=INT_MIN16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > (longlong) INT_MAX16) { res=INT_MAX16; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3525,14 +3509,14 @@ int Field_medium::store(double nr) if (nr < 0) { int3store(ptr,0); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr >= (double) (long) (1L << 24)) { uint32 tmp=(uint32) (1L << 24)-1L; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3544,14 +3528,14 @@ int Field_medium::store(double nr) { long tmp=(long) INT_MIN24; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > (double) INT_MAX24) { long tmp=(long) INT_MAX24; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3571,14 +3555,14 @@ int Field_medium::store(longlong nr, bool unsigned_val) if (nr < 0 && !unsigned_val) { int3store(ptr,0); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if ((ulonglong) nr >= (ulonglong) (long) (1L << 24)) { long tmp= (long) (1L << 24)-1L; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3593,14 +3577,14 @@ int Field_medium::store(longlong nr, bool unsigned_val) { long tmp= (long) INT_MIN24; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (nr > (longlong) INT_MAX24) { long tmp=(long) INT_MAX24; int3store(ptr,tmp); - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3722,7 +3706,7 @@ int Field_long::store(double nr) else if (nr > (double) UINT_MAX32) { res= UINT_MAX32; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else @@ -3744,7 +3728,7 @@ int Field_long::store(double nr) res=(int32) (longlong) nr; } if (error) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); int4store(ptr,res); return error; @@ -3790,7 +3774,7 @@ int Field_long::store(longlong nr, bool unsigned_val) res=(int32) nr; } if (error) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); int4store(ptr,res); return error; @@ -3889,7 +3873,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error); if (error == MY_ERRNO_ERANGE) { - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (get_thd()->count_cuted_fields && @@ -3911,7 +3895,7 @@ int Field_longlong::store(double nr) res= double_to_longlong(nr, unsigned_flag, &error); if (error) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); int8store(ptr,res); return error; @@ -3932,7 +3916,7 @@ int Field_longlong::store(longlong nr, bool unsigned_val) if (unsigned_flag != unsigned_val) { nr= unsigned_flag ? (ulonglong) 0 : (ulonglong) LONGLONG_MAX; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } } @@ -4046,8 +4030,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) if (error || (!len || ((uint) (end-from) != len && get_thd()->count_cuted_fields))) { - set_warning(Sql_condition::WARN_LEVEL_WARN, - (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1); + set_warning(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED, 1); error= error ? 1 : 2; } Field_float::store(nr); @@ -4063,7 +4046,7 @@ int Field_float::store(double nr) unsigned_flag, FLT_MAX); if (error) { - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); if (error < 0) // Wrong double value { error= 1; @@ -4234,8 +4217,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) if (error || (!len || ((uint) (end-from) != len && get_thd()->count_cuted_fields))) { - set_warning(Sql_condition::WARN_LEVEL_WARN, - (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1); + set_warning(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED, 1); error= error ? 1 : 2; } Field_double::store(nr); @@ -4251,7 +4233,7 @@ int Field_double::store(double nr) unsigned_flag, DBL_MAX); if (error) { - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); if (error < 0) // Wrong double value { error= 1; @@ -4612,7 +4594,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time, if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !have_smth_to_conv) { error= 1; - set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, + set_datetime_warning(WARN_DATA_TRUNCATED, str, MYSQL_TIMESTAMP_DATETIME, 1); } else if (MYSQL_TIME_WARN_HAVE_NOTES(was_cut)) @@ -4630,7 +4612,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time, conversion_error= ER_WARN_DATA_OUT_OF_RANGE; if (conversion_error) { - set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, conversion_error, + set_datetime_warning(conversion_error, str, MYSQL_TIMESTAMP_DATETIME, !error); error= 1; } @@ -5128,7 +5110,7 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED, str, mysql_type_to_time_type(type()), 1); if (was_cut & MYSQL_TIME_WARN_OUT_OF_RANGE) - set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, + set_datetime_warning(ER_WARN_DATA_OUT_OF_RANGE, str, mysql_type_to_time_type(type()), 1); } @@ -5656,7 +5638,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) error == MY_ERRNO_ERANGE) { *ptr=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } if (get_thd()->count_cuted_fields && @@ -5699,7 +5681,7 @@ int Field_year::store(longlong nr, bool unsigned_val) if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155) { *ptr= 0; - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } if (nr != 0 || field_length != 4) // 0000 -> 0; 00 -> 2000 @@ -5720,8 +5702,7 @@ int Field_year::store_time_dec(MYSQL_TIME *ltime, uint dec) if (Field_year::store(ltime->year, 0)) return 1; - set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, - &str, ltime->time_type, 1); + set_datetime_warning(WARN_DATA_TRUNCATED, &str, ltime->time_type, 1); return 0; } @@ -6281,31 +6262,21 @@ bool Field_datetimef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) TRUE - If an error happened */ -static bool -check_string_copy_error(Field_str *field, - const char *well_formed_error_pos, - const char *cannot_convert_error_pos, - const char *end, - CHARSET_INFO *cs) +bool +Field_longstr::check_string_copy_error(const char *well_formed_error_pos, + const char *cannot_convert_error_pos, + const char *end, + CHARSET_INFO *cs) { const char *pos; char tmp[32]; - THD *thd; - - thd= field->get_thd(); if (!(pos= well_formed_error_pos) && !(pos= cannot_convert_error_pos)) return FALSE; convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6); - - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, - ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "string", tmp, field->field_name, - thd->get_stmt_da()->current_row_for_warning()); + set_warning_truncated_wrong_value("string", tmp); return TRUE; } @@ -6340,14 +6311,14 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end, if (test_if_important_data(field_charset, pstr, end)) { if (thd->abort_on_warning) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1); + set_warning(ER_DATA_TOO_LONG, 1); else - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); return 2; } else if (count_spaces) { /* If we lost only spaces then produce a NOTE, not a WARNING */ - set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); + set_note(WARN_DATA_TRUNCATED, 1); return 2; } } @@ -6382,7 +6353,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_length-copy_length, field_charset->pad_char); - if (check_string_copy_error(this, well_formed_error_pos, + if (check_string_copy_error(well_formed_error_pos, cannot_convert_error_pos, from + length, cs)) return 2; @@ -6413,9 +6384,9 @@ int Field_str::store(double nr) if (error) { if (get_thd()->abort_on_warning) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1); + set_warning(ER_DATA_TOO_LONG, 1); else - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); } return store(buff, length, &my_charset_numeric); } @@ -6891,7 +6862,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) else int2store(ptr, copy_length); - if (check_string_copy_error(this, well_formed_error_pos, + if (check_string_copy_error(well_formed_error_pos, cannot_convert_error_pos, from + length, cs)) return 2; @@ -7417,7 +7388,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) tmp= value.ptr(); bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*)); - if (check_string_copy_error(this, well_formed_error_pos, + if (check_string_copy_error(well_formed_error_pos, cannot_convert_error_pos, from + length, cs)) return 2; @@ -7923,6 +7894,14 @@ err_exit: return -1; } +Field::geometry_type Field_geom::geometry_type_merge(geometry_type a, + geometry_type b) +{ + if (a == b) + return a; + return Field::GEOM_GEOMETRY; +} + #endif /*HAVE_SPATIAL*/ /**************************************************************************** @@ -7983,13 +7962,13 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) if (err || end != from+length || tmp > typelib->count) { tmp=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); } if (!get_thd()->count_cuted_fields) err= 0; } else - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); } store_type((ulonglong) tmp); return err; @@ -8008,7 +7987,7 @@ int Field_enum::store(longlong nr, bool unsigned_val) int error= 0; if ((ulonglong) nr > typelib->count || nr == 0) { - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); if (nr != 0 || get_thd()->count_cuted_fields) { nr= 0; @@ -8161,11 +8140,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1)) { tmp=0; - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); } } else if (got_warning) - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); store_type(tmp); return err; } @@ -8185,7 +8164,7 @@ int Field_set::store(longlong nr, bool unsigned_val) if ((ulonglong) nr > max_nr) { nr&= max_nr; - set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + set_warning(WARN_DATA_TRUNCATED, 1); error=1; } store_type((ulonglong) nr); @@ -8537,9 +8516,9 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) set_rec_bits((1 << bit_len) - 1, bit_ptr, bit_ofs, bit_len); memset(ptr, 0xff, bytes_in_rec); if (get_thd()->really_abort_on_warning()) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1); + set_warning(ER_DATA_TOO_LONG, 1); else - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } /* delta is >= -1 here */ @@ -8974,9 +8953,9 @@ int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs) if (bits) *ptr&= ((1 << bits) - 1); /* set first uchar */ if (get_thd()->really_abort_on_warning()) - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1); + set_warning(ER_DATA_TOO_LONG, 1); else - set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } bzero(ptr, delta); @@ -10119,6 +10098,19 @@ void Field::set_datetime_warning(Sql_condition::enum_warning_level level, } +void Field::set_warning_truncated_wrong_value(const char *type, + const char *value) +{ + THD *thd= get_thd(); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, + ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), + type, value, field_name, + static_cast<ulong>(thd->get_stmt_da()-> + current_row_for_warning())); +} + + /* @brief Return possible keys for a field diff --git a/sql/field.h b/sql/field.h index a52bd01395a..a40e2ef9913 100644 --- a/sql/field.h +++ b/sql/field.h @@ -885,14 +885,32 @@ public: virtual int set_time() { return 1; } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment) const; +protected: + bool set_warning(unsigned int code, int cuted_increment) const + { + return set_warning(Sql_condition::WARN_LEVEL_WARN, code, cuted_increment); + } + bool set_note(unsigned int code, int cuted_increment) const + { + return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment); + } void set_datetime_warning(Sql_condition::enum_warning_level, uint code, const ErrConv *str, timestamp_type ts_type, int cuted_increment); + void set_datetime_warning(uint code, + const ErrConv *str, timestamp_type ts_type, + int cuted_increment) + { + set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, code, str, ts_type, + cuted_increment); + } + void set_warning_truncated_wrong_value(const char *type, const char *value); inline bool check_overflow(int op_result) { return (op_result == E_DEC_OVERFLOW); } int warn_if_overflow(int op_result); +public: void set_table_name(String *alias) { table_name= &alias->Ptr; @@ -1139,6 +1157,10 @@ class Field_longstr :public Field_str protected: int report_if_important_data(const char *ptr, const char *end, bool count_spaces); + bool check_string_copy_error(const char *well_formed_error_pos, + const char *cannot_convert_error_pos, + const char *end, + CHARSET_INFO *cs); public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -2591,6 +2613,7 @@ public: int reset(void) { return Field_blob::reset() || !maybe_null(); } geometry_type get_geometry_type() { return geom_type; }; + static geometry_type geometry_type_merge(geometry_type, geometry_type); }; #endif /*HAVE_SPATIAL*/ diff --git a/sql/filesort.cc b/sql/filesort.cc index 027437fca67..a545bb623c0 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, Monty Program Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 73513ac9f40..64ae31ce231 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1,5 +1,4 @@ -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. - Copyright (c) 2012, 2013, Monty Proram Ab. +/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. 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 @@ -2529,7 +2528,8 @@ ndbcluster_check_if_local_tables_in_db(THD *thd, const char *dbname) char path[FN_REFLEN + 1]; build_table_filename(path, sizeof(path) - 1, dbname, "", "", 0); - if (find_files(thd, &files, dbname, path, NullS, 0) != FIND_FILES_OK) + if (find_files(thd, &files, dbname, path, NullS, 0, NULL) != + FIND_FILES_OK) { DBUG_PRINT("info", ("Failed to find files")); DBUG_RETURN(true); diff --git a/sql/handler.cc b/sql/handler.cc index fa22ab64d82..01d3eed8d08 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2363,9 +2363,11 @@ handle_condition(THD *, } -/** @brief - This should return ENOENT if the file doesn't exists. - The .frm file will be deleted only if we return 0 or ENOENT +/** delete a table in the engine + + @note + ENOENT and HA_ERR_NO_SUCH_TABLE are not considered errors. + The .frm file will be deleted only if we return 0. */ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, const char *db, const char *alias, bool generate_warning) @@ -2380,47 +2382,66 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, /* table_type is NULL in ALTER TABLE when renaming only .frm files */ if (table_type == NULL || table_type == view_pseudo_hton || ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); + DBUG_RETURN(0); bzero((char*) &dummy_table, sizeof(dummy_table)); bzero((char*) &dummy_share, sizeof(dummy_share)); dummy_table.s= &dummy_share; path= get_canonical_filename(file, path, tmp_path); - if ((error= file->ha_delete_table(path)) && generate_warning) + if ((error= file->ha_delete_table(path))) { /* - Because file->print_error() use my_error() to generate the error message - we use an internal error handler to intercept it and store the text - in a temporary buffer. Later the message will be presented to user - as a warning. + it's not an error if the table doesn't exist in the engine. + warn the user, but still report DROP being a success */ - Ha_delete_table_error_handler ha_delete_table_error_handler; - - /* Fill up strucutures that print_error may need */ - dummy_share.path.str= (char*) path; - dummy_share.path.length= strlen(path); - dummy_share.normalized_path= dummy_share.path; - dummy_share.db.str= (char*) db; - dummy_share.db.length= strlen(db); - dummy_share.table_name.str= (char*) alias; - dummy_share.table_name.length= strlen(alias); - dummy_table.alias.set(alias, dummy_share.table_name.length, - table_alias_charset); + bool intercept= error == ENOENT || error == HA_ERR_NO_SUCH_TABLE; - file->change_table_ptr(&dummy_table, &dummy_share); - - thd->push_internal_handler(&ha_delete_table_error_handler); - file->print_error(error, 0); + if (!intercept || generate_warning) + { + /* + Because file->print_error() use my_error() to generate the error message + we use an internal error handler to intercept it and store the text + in a temporary buffer. Later the message will be presented to user + as a warning. + */ + Ha_delete_table_error_handler ha_delete_table_error_handler; + + /* Fill up strucutures that print_error may need */ + dummy_share.path.str= (char*) path; + dummy_share.path.length= strlen(path); + dummy_share.normalized_path= dummy_share.path; + dummy_share.db.str= (char*) db; + dummy_share.db.length= strlen(db); + dummy_share.table_name.str= (char*) alias; + dummy_share.table_name.length= strlen(alias); + dummy_table.alias.set(alias, dummy_share.table_name.length, + table_alias_charset); + + file->change_table_ptr(&dummy_table, &dummy_share); + +#if MYSQL_VERSION_ID > 100105 + // XXX as an ugly 10.0-only hack we intercept HA_ERR_ROW_IS_REFERENCED, + // to report it under the old historical error number. +#error remove HA_ERR_ROW_IS_REFERENCED, use ME_JUST_WARNING instead of a handler +#endif + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + thd->push_internal_handler(&ha_delete_table_error_handler); - thd->pop_internal_handler(); + file->print_error(error, 0); - /* - XXX: should we convert *all* errors to warnings here? - What if the error is fatal? - */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, - ha_delete_table_error_handler.buff); + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + { + thd->pop_internal_handler(); + if (error == HA_ERR_ROW_IS_REFERENCED) + my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); + else + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, + ha_delete_table_error_handler.buff); + } + } + if (intercept) + error= 0; } delete file; diff --git a/sql/item.cc b/sql/item.cc index a465c2d4e36..bffa7e2990d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1179,6 +1179,42 @@ Item *Item::safe_charset_converter(CHARSET_INFO *tocs) /** + Some pieces of the code do not support changing of + Item_cache to other Item types. + + Example: + Item_singlerow_subselect has "Item_cache **row". + Creating of Item_func_conv_charset followed by THD::change_item_tree() + should not change row[i] from Item_cache directly to Item_func_conv_charset, because Item_singlerow_subselect + because Item_singlerow_subselect later calls Item_cache-specific methods, + e.g. row[i]->store() and row[i]->cache_value(). + + Let's wrap Item_func_conv_charset in a new Item_cache, + so the Item_cache-specific methods can still be used for + Item_singlerow_subselect::row[i] safely. + + As a bonus we cache the converted value, instead of converting every time + + TODO: we should eventually check all other use cases of change_item_tree(). + Perhaps some more potentially dangerous substitution examples exist. +*/ +Item *Item_cache::safe_charset_converter(CHARSET_INFO *tocs) +{ + if (!example) + return Item::safe_charset_converter(tocs); + Item *conv= example->safe_charset_converter(tocs); + if (conv == example) + return this; + Item_cache *cache; + if (!conv || !(cache= new Item_cache_str(conv))) + return NULL; // Safe conversion is not possible, or OEM + cache->setup(conv); + cache->fixed= false; // Make Item::fix_fields() happy + return cache; +} + + +/** @details Created mostly for mysql_prepare_table(). Important when a string ENUM/SET column is described with a numeric default value: @@ -9471,6 +9507,11 @@ bool Item_type_holder::join_types(THD *thd, Item *item) item_decimals= 0; decimals= MY_MAX(decimals, item_decimals); } + + if (fld_type == FIELD_TYPE_GEOMETRY) + geometry_type= + Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type()); + if (Field::result_merge_type(fld_type) == DECIMAL_RESULT) { decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE); diff --git a/sql/item.h b/sql/item.h index ce757749217..171bdb05310 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4477,7 +4477,6 @@ class Item_cache: public Item_basic_constant { protected: Item *example; - table_map used_table_map; /** Field that this object will get value from. This is used by index-based subquery engines to detect and remove the equality injected @@ -4495,7 +4494,7 @@ protected: bool value_cached; public: Item_cache(): - example(0), used_table_map(0), cached_field(0), + example(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING), value_cached(0) { @@ -4504,7 +4503,7 @@ public: null_value= 1; } Item_cache(enum_field_types field_type_arg): - example(0), used_table_map(0), cached_field(0), + example(0), cached_field(0), cached_field_type(field_type_arg), value_cached(0) { @@ -4513,8 +4512,6 @@ public: null_value= 1; } - void set_used_tables(table_map map) { used_table_map= map; } - virtual bool allocate(uint i) { return 0; } virtual bool setup(Item *item) { @@ -4531,7 +4528,6 @@ public: enum_field_types field_type() const { return cached_field_type; } static Item_cache* get_cache(const Item *item); static Item_cache* get_cache(const Item* item, const Item_result type); - table_map used_tables() const { return used_table_map; } virtual void keep_array() {} virtual void print(String *str, enum_query_type query_type); bool eq_def(Field *field) @@ -4582,6 +4578,7 @@ public: return TRUE; return (this->*processor)(arg); } + virtual Item *safe_charset_converter(CHARSET_INFO *tocs); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1f1982ffb80..90eef1ea55c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5160,10 +5160,65 @@ bool Regexp_processor_pcre::compile(Item *item, bool send_error) } +/** + Send a warning explaining an error code returned by pcre_exec(). +*/ +void Regexp_processor_pcre::pcre_exec_warn(int rc) const +{ + char buf[64]; + const char *errmsg= NULL; + /* + Make a descriptive message only for those pcre_exec() error codes + that can actually happen in MariaDB. + */ + switch (rc) + { + case PCRE_ERROR_NOMEMORY: + errmsg= "pcre_exec: Out of memory"; + break; + case PCRE_ERROR_BADUTF8: + errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string"; + break; + case PCRE_ERROR_RECURSELOOP: + errmsg= "pcre_exec: Recursion loop detected"; + break; + default: + /* + As other error codes should normally not happen, + we just report the error code without textual description + of the code. + */ + my_snprintf(buf, sizeof(buf), "pcre_exec: Internal error (%d)", rc); + errmsg= buf; + } + push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_REGEXP_ERROR, ER(ER_REGEXP_ERROR), errmsg); +} + + +/** + Call pcre_exec() and send a warning if pcre_exec() returned with an error. +*/ +int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code, + const pcre_extra *extra, + const char *subject, + int length, int startoffset, + int options, int *ovector, + int ovecsize) +{ + int rc= pcre_exec(code, extra, subject, length, + startoffset, options, ovector, ovecsize); + DBUG_EXECUTE_IF("pcre_exec_error_123", rc= -123;); + if (rc < PCRE_ERROR_NOMATCH) + pcre_exec_warn(rc); + return rc; +} + + bool Regexp_processor_pcre::exec(const char *str, int length, int offset) { - m_pcre_exec_rc= pcre_exec(m_pcre, NULL, str, length, - offset, 0, m_SubStrVec, m_subpatterns_needed * 3); + m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL, str, length, offset, 0, + m_SubStrVec, m_subpatterns_needed * 3); return false; } @@ -5173,8 +5228,10 @@ bool Regexp_processor_pcre::exec(String *str, int offset, { if (!(str= convert_if_needed(str, &subject_converter))) return true; - m_pcre_exec_rc= pcre_exec(m_pcre, NULL, str->c_ptr_safe(), str->length(), - offset, 0, m_SubStrVec, m_subpatterns_needed * 3); + m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL, + str->c_ptr_safe(), str->length(), + offset, 0, + m_SubStrVec, m_subpatterns_needed * 3); if (m_pcre_exec_rc > 0) { uint i; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8611182f32d..c4933e6d7ed 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1549,6 +1549,10 @@ class Regexp_processor_pcre int m_pcre_exec_rc; int m_SubStrVec[30]; uint m_subpatterns_needed; + void pcre_exec_warn(int rc) const; + int pcre_exec_with_warn(const pcre *code, const pcre_extra *extra, + const char *subject, int length, int startoffset, + int options, int *ovector, int ovecsize); public: String *convert_if_needed(String *src, String *converter); String subject_converter; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 32a19341895..972ae5afb16 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5122,6 +5122,16 @@ null: void Item_dyncol_get::print(String *str, enum_query_type query_type) { + /* + Parent cast doesn't exist yet, only print dynamic column name. This happens + when called from create_func_cast() / wrong_precision_error(). + */ + if (!str->length()) + { + args[1]->print(str, query_type); + return; + } + /* see create_func_dyncol_get */ DBUG_ASSERT(str->length() >= 5); DBUG_ASSERT(strncmp(str->ptr() + str->length() - 5, "cast(", 5) == 0); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 21f14ae8435..1c5682417a5 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2008, 2015, 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 @@ -3311,7 +3311,19 @@ void Item_func_group_concat::cleanup() } DBUG_ASSERT(tree == 0); } - + /* + As the ORDER structures pointed to by the elements of the + 'order' array may be modified in find_order_in_list() called + from Item_func_group_concat::setup() to point to runtime + created objects, we need to reset them back to the original + arguments of the function. + */ + ORDER **order_ptr= order; + for (uint i= 0; i < arg_count_order; i++) + { + (*order_ptr)->item= &args[arg_count_field + i]; + order_ptr++; + } DBUG_VOID_RETURN; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 2ba99d556e9..adcb53f8bc1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2409,6 +2409,12 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, my_snprintf(typestr, typestr_length, "STRING(%d)", length); return my_b_write_quoted_with_length(file, ptr, length); + case MYSQL_TYPE_DECIMAL: + my_b_printf(file, + "!! Old DECIMAL (mysql-4.1 or earlier). " + "Not enough metadata to display the value. "); + break; + default: { char tmp[5]; diff --git a/sql/message.rc b/sql/message.rc index 116522b7d48..0885a897e6f 100644 --- a/sql/message.rc +++ b/sql/message.rc @@ -1,2 +1,2 @@ -LANGUAGE 0x9,0x1
-1 11 MSG00001.bin
+LANGUAGE 0x9,0x1 +1 11 MSG00001.bin diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 39f7e8062a3..c297367b1af 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2565,10 +2565,11 @@ static MYSQL_SOCKET activate_tcp_port(uint port) if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET) { - sql_print_error("Failed to create a socket for %s '%s': errno: %d.", - (a->ai_family == AF_INET) ? "IPv4" : "IPv6", - (const char *) ip_addr, - (int) socket_errno); + sql_print_message_func func= real_bind_addr_str ? sql_print_error + : sql_print_warning; + func("Failed to create a socket for %s '%s': errno: %d.", + (a->ai_family == AF_INET) ? "IPv4" : "IPv6", + (const char *) ip_addr, (int) socket_errno); } else { @@ -6288,6 +6289,8 @@ int mysqld_main(int argc, char **argv) mysql_cond_signal(&COND_server_started); mysql_mutex_unlock(&LOCK_server_started); + MYSQL_SET_STAGE(0 ,__FILE__, __LINE__); + #if defined(_WIN32) || defined(HAVE_SMEM) handle_connections_methods(); #else @@ -10320,6 +10323,7 @@ PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work fr PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to commit", 0}; PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0}; PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0}; +PSI_stage_info stage_waiting_for_workers_idle= { 0, "Waiting for worker threads to be idle", 0}; PSI_stage_info stage_master_gtid_wait_primary= { 0, "Waiting in MASTER_GTID_WAIT() (primary waiter)", 0}; PSI_stage_info stage_master_gtid_wait= { 0, "Waiting in MASTER_GTID_WAIT()", 0}; PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process GTID received on multiple master connections", 0}; diff --git a/sql/mysqld.h b/sql/mysqld.h index 89cb4e9c5cb..90204bc6dc6 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -457,6 +457,7 @@ extern PSI_stage_info stage_waiting_for_work_from_sql_thread; extern PSI_stage_info stage_waiting_for_prior_transaction_to_commit; extern PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit; extern PSI_stage_info stage_waiting_for_room_in_worker_thread; +extern PSI_stage_info stage_waiting_for_workers_idle; extern PSI_stage_info stage_master_gtid_wait_primary; extern PSI_stage_info stage_master_gtid_wait; extern PSI_stage_info stage_gtid_wait_other_connection; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 3cd80ec53a4..f322ca0e8b8 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -973,7 +973,7 @@ bool Master_info_index::init_all_master_info() { /* Master_info is not in HASH; Add it */ if (master_info_index->add_master_info(mi, FALSE)) - return 1; + DBUG_RETURN(1); succ_num++; unlock_slave_threads(mi); } @@ -1006,7 +1006,7 @@ bool Master_info_index::init_all_master_info() /* Master_info was not registered; add it */ if (master_info_index->add_master_info(mi, FALSE)) - return 1; + DBUG_RETURN(1); succ_num++; unlock_slave_threads(mi); @@ -1103,7 +1103,7 @@ Master_info_index::get_master_info(LEX_STRING *connection_name, mysql_mutex_assert_owner(&LOCK_active_mi); if (!this) // master_info_index is set to NULL on server shutdown - return NULL; + DBUG_RETURN(NULL); /* Make name lower case for comparison */ res= strmake(buff, connection_name->str, connection_name->length); @@ -1258,7 +1258,7 @@ bool Master_info_index::give_error_if_slave_running() DBUG_ENTER("give_error_if_slave_running"); mysql_mutex_assert_owner(&LOCK_active_mi); if (!this) // master_info_index is set to NULL on server shutdown - return TRUE; + DBUG_RETURN(TRUE); for (uint i= 0; i< master_info_hash.records; ++i) { @@ -1289,7 +1289,7 @@ bool Master_info_index::any_slave_sql_running() { DBUG_ENTER("any_slave_sql_running"); if (!this) // master_info_index is set to NULL on server shutdown - return TRUE; + DBUG_RETURN(TRUE); for (uint i= 0; i< master_info_hash.records; ++i) { diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 99ddde95689..305e8053032 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -168,6 +168,8 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id, done and also no longer need waiting for. */ entry->last_committed_sub_id= sub_id; + if (entry->need_sub_id_signal) + mysql_cond_broadcast(&entry->COND_parallel_entry); /* Now free any GCOs in which all transactions have committed. */ group_commit_orderer *tmp_gco= rgi->gco; @@ -1894,26 +1896,29 @@ rpl_parallel::wait_for_workers_idle(THD *thd) max_i= domain_hash.records; for (i= 0; i < max_i; ++i) { - bool active; - wait_for_commit my_orderer; + PSI_stage_info old_stage; struct rpl_parallel_entry *e; + int err= 0; e= (struct rpl_parallel_entry *)my_hash_element(&domain_hash, i); mysql_mutex_lock(&e->LOCK_parallel_entry); - if ((active= (e->current_sub_id > e->last_committed_sub_id))) - { - wait_for_commit *waitee= &e->current_group_info->commit_orderer; - my_orderer.register_wait_for_prior_commit(waitee); - thd->wait_for_commit_ptr= &my_orderer; - } - mysql_mutex_unlock(&e->LOCK_parallel_entry); - if (active) + e->need_sub_id_signal= true; + thd->ENTER_COND(&e->COND_parallel_entry, &e->LOCK_parallel_entry, + &stage_waiting_for_workers_idle, &old_stage); + while (e->current_sub_id > e->last_committed_sub_id) { - int err= my_orderer.wait_for_prior_commit(thd); - thd->wait_for_commit_ptr= NULL; - if (err) - return err; + if (thd->check_killed()) + { + thd->send_kill_message(); + err= 1; + break; + } + mysql_cond_wait(&e->COND_parallel_entry, &e->LOCK_parallel_entry); } + e->need_sub_id_signal= false; + thd->EXIT_COND(&old_stage); + if (err) + return err; } return 0; } diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index 09e0f39c0cd..0c2e4270646 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -228,6 +228,12 @@ struct rpl_parallel_entry { */ bool force_abort; /* + Set in wait_for_workers_idle() to show that it is waiting, so that + finish_event_group knows to signal it when last_committed_sub_id is + increased. + */ + bool need_sub_id_signal; + /* At STOP SLAVE (force_abort=true), we do not want to process all events in the queue (which could unnecessarily delay stop, if a lot of events happen to be queued). The stop_count provides a safe point at which to stop, so diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 9067f1e4253..146bf3b0c0e 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -452,7 +452,7 @@ void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_ CHARSET_INFO *cs= str->charset(); uint32 length= cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), - "decimal(%d,?)", metadata); + "decimal(%d,?)/*old*/", metadata); str->length(length); } break; diff --git a/sql/slave.cc b/sql/slave.cc index c9dc55f2bf7..f8754e9d4cb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -647,11 +647,10 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); mysql_mutex_unlock(log_lock); - - if (opt_slave_parallel_threads > 0 && - !master_info_index->any_slave_sql_running()) - rpl_parallel_inactivate_pool(&global_rpl_thread_pool); } + if (opt_slave_parallel_threads > 0 && + !master_info_index->any_slave_sql_running()) + rpl_parallel_inactivate_pool(&global_rpl_thread_pool); if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) { DBUG_PRINT("info",("Terminating IO thread")); @@ -4849,10 +4848,8 @@ err_during_init: THD_CHECK_SENTRY(thd); rli->sql_driver_thd= 0; mysql_mutex_lock(&LOCK_thread_count); - THD_CHECK_SENTRY(thd); thd->rgi_fake= thd->rgi_slave= NULL; delete serial_rgi; - delete thd; mysql_mutex_unlock(&LOCK_thread_count); #ifdef WITH_WSREP /* if slave stopped due to node going non primary, we set global flag to @@ -4884,6 +4881,22 @@ err_during_init: DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); mysql_mutex_unlock(&rli->run_lock); // tell the world we are done + /* + Deactivate the parallel replication thread pool, if there are now no more + SQL threads running. Do this here, when we have released all locks, but + while our THD (and current_thd) is still valid. + */ + mysql_mutex_lock(&LOCK_active_mi); + if (opt_slave_parallel_threads > 0 && + !master_info_index->any_slave_sql_running()) + rpl_parallel_inactivate_pool(&global_rpl_thread_pool); + mysql_mutex_unlock(&LOCK_active_mi); + + mysql_mutex_lock(&LOCK_thread_count); + THD_CHECK_SENTRY(thd); + delete thd; + mysql_mutex_unlock(&LOCK_thread_count); + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); #ifdef HAVE_OPENSSL diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 238d1bcb7a9..38e584f65e7 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8057,9 +8057,10 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (select_lex->first_cond_optimization) { leaves.empty(); - if (!select_lex->is_prep_leaf_list_saved) + if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED) { make_leaves_list(leaves, tables, full_table_list, first_select_table); + select_lex->prep_leaf_list_state= SELECT_LEX::READY; select_lex->leaf_tables_exec.empty(); } else diff --git a/sql/sql_class.cc b/sql/sql_class.cc index bdd187279db..128961d95a4 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -6934,6 +6934,7 @@ wait_for_commit::wakeup_subsequent_commits2(int wakeup_error) a mutex), so no extra explicit barrier is needed here. */ wakeup_subsequent_commits_running= false; + DBUG_EXECUTE_IF("inject_wakeup_subsequent_commits_sleep", my_sleep(21000);); } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index fc47e562514..7b9769cab89 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1125,7 +1125,7 @@ bool setup_connection_thread_globals(THD *thd) bool login_connection(THD *thd) { NET *net= &thd->net; - int error; + int error= 0; DBUG_ENTER("login_connection"); DBUG_PRINT("info", ("login_connection called by thread %lu", thd->thread_id)); @@ -1144,7 +1144,8 @@ bool login_connection(THD *thd) my_sleep(1000); /* must wait after eof() */ #endif statistic_increment(aborted_connects,&LOCK_status); - DBUG_RETURN(1); + error=1; + goto exit; } /* Connect completed, set read/write timeouts back to default */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); @@ -1154,10 +1155,13 @@ bool login_connection(THD *thd) if (increment_connection_count(thd, TRUE)) { my_error(ER_OUTOFMEMORY, MYF(0), 2*sizeof(USER_STATS)); - DBUG_RETURN(1); + error= 1; + goto exit; } - DBUG_RETURN(0); +exit: + mysql_audit_notify_connection_connect(thd); + DBUG_RETURN(error); } @@ -1309,7 +1313,6 @@ bool thd_prepare_connection(THD *thd) bool rc; lex_start(thd); rc= login_connection(thd); - mysql_audit_notify_connection_connect(thd); if (rc) return rc; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index e9774e436ab..df66e035e78 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -556,6 +556,7 @@ void lex_start(THD *thd) lex->is_lex_started= TRUE; lex->used_tables= 0; + lex->only_view= FALSE; lex->reset_slave_info.all= false; lex->limit_rows_examined= 0; lex->limit_rows_examined_cnt= ULONGLONG_MAX; @@ -1884,7 +1885,7 @@ void st_select_lex::init_query() exclude_from_table_unique_test= no_wrap_view_item= FALSE; nest_level= 0; link_next= 0; - is_prep_leaf_list_saved= FALSE; + prep_leaf_list_state= UNINIT; have_merged_subqueries= FALSE; bzero((char*) expr_cache_may_be_used, sizeof(expr_cache_may_be_used)); m_non_agg_field_used= false; @@ -4163,12 +4164,22 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) { List_iterator_fast<TABLE_LIST> li(leaf_tables); TABLE_LIST *table; + + /* + Check that the SELECT_LEX was really prepared and so tables are setup. + + It can be subquery in SET clause of UPDATE which was not prepared yet, so + its tables are not yet setup and ready for storing. + */ + if (prep_leaf_list_state != READY) + return FALSE; + while ((table= li++)) { if (leaf_tables_prep.push_back(table)) return TRUE; } - is_prep_leaf_list_saved= TRUE; + prep_leaf_list_state= SAVED; for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit()) { for (SELECT_LEX *sl= u->first_select(); sl; sl= sl->next_select()) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b17f0f4ec63..dcd8ddfce91 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -733,7 +733,8 @@ public: List<TABLE_LIST> leaf_tables; List<TABLE_LIST> leaf_tables_exec; List<TABLE_LIST> leaf_tables_prep; - bool is_prep_leaf_list_saved; + enum leaf_list_state {UNINIT, READY, SAVED}; + enum leaf_list_state prep_leaf_list_state; uint insert_tables; st_select_lex *merged_into; /* select which this select is merged into */ /* (not 0 only for views/derived tables) */ diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index ac67291fbd1..029744b63f5 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -837,9 +837,16 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) log. The exception is a unimplemented truncate method or failure before any call to handler::truncate() is done. Also, it is logged in statement format, regardless of the binlog format. + + Since we've changed data within the table, we also have to invalidate + the query cache for it. */ - if (error != HA_ERR_WRONG_COMMAND && binlog_stmt) - error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); + if (error != HA_ERR_WRONG_COMMAND) + { + query_cache_invalidate3(thd, first_table, FALSE); + if (binlog_stmt) + error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); + } /* A locked table ticket was upgraded to a exclusive lock. After the diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 4b2144a48ef..b511548dd51 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -264,13 +264,14 @@ public: { TRASH(ptr_arg, size); } sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, - struct st_mysql_sys_var *plugin_var_arg) + struct st_mysql_sys_var *plugin_var_arg, + struct st_plugin_int *plugin_arg) :sys_var(chain, name_arg, plugin_var_arg->comment, (plugin_var_arg->flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) | (plugin_var_arg->flags & PLUGIN_VAR_READONLY ? READONLY : 0), 0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0, VARIABLE_NOT_IN_BINLOG, NULL, NULL, NULL), - plugin_var(plugin_var_arg) + plugin(plugin_arg), plugin_var(plugin_var_arg) { plugin_var->name= name_arg; } sys_var_pluginvar *cast_pluginvar() { return this; } bool check_update_type(Item_result type); @@ -1413,22 +1414,6 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin, goto err; } - /* - set the plugin attribute of plugin's sys vars so they are pointing - to the active plugin - */ - if (plugin->system_vars) - { - sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar(); - for (;;) - { - var->plugin= plugin; - if (!var->next) - break; - var= var->next->cast_pluginvar(); - } - } - ret= 0; err: @@ -3967,7 +3952,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, continue; tmp_backup[tmp->nbackups++].save(&o->name); if ((var= find_bookmark(plugin_name.str, o->name, o->flags))) - v= new (mem_root) sys_var_pluginvar(&chain, var->key + 1, o); + v= new (mem_root) sys_var_pluginvar(&chain, var->key + 1, o, tmp); else { len= plugin_name.length + strlen(o->name) + 2; @@ -3975,7 +3960,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, strxmov(varname, plugin_name.str, "-", o->name, NullS); my_casedn_str(&my_charset_latin1, varname); convert_dash_to_underscore(varname, len-1); - v= new (mem_root) sys_var_pluginvar(&chain, varname, o); + v= new (mem_root) sys_var_pluginvar(&chain, varname, o, tmp); } DBUG_ASSERT(v); /* check that an object was actually constructed */ } /* end for */ diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 2c17898f07c..6496e1895fb 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -238,7 +238,6 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, { int rc= 1; handlerton *hton; - bool new_exists, old_exists; const char *new_alias, *old_alias; DBUG_ENTER("do_rename"); @@ -254,17 +253,13 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, } DBUG_ASSERT(new_alias); - new_exists= ha_table_exists(thd, new_db, new_alias); - - if (new_exists) + if (ha_table_exists(thd, new_db, new_alias)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); DBUG_RETURN(1); // This can't be skipped } - old_exists= ha_table_exists(thd, ren_table->db, old_alias, &hton); - - if (old_exists) + if (ha_table_exists(thd, ren_table->db, old_alias, &hton) && hton) { DBUG_ASSERT(!thd->locked_tables_mode); tdc_remove_table(thd, TDC_RT_REMOVE_ALL, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2aeddf2415d..e0f560f0b3a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9736,10 +9736,24 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (!sel->quick_keys.is_subset(tab->checked_keys) || !sel->needed_reg.is_subset(tab->checked_keys)) { + /* + "Range checked for each record" is a "last resort" access method + that should only be used when the other option is a cross-product + join. + + We use the following condition (it's approximate): + 1. There are potential keys for (sel->needed_reg) + 2. There were no possible ways to construct a quick select, or + the quick select would be more expensive than the full table + scan. + */ tab->use_quick= (!sel->needed_reg.is_clear_all() && (sel->quick_keys.is_clear_all() || - (sel->quick && - (sel->quick->records >= 100L)))) ? + (sel->quick && + sel->quick->read_time > + tab->table->file->scan_time() + + tab->table->file->stats.records/TIME_FOR_COMPARE + ))) ? 2 : 1; sel->read_tables= used_tables & ~current_map; sel->quick_keys.clear_all(); diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 2b0576ffba9..8d5bb2b596d 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -326,7 +326,8 @@ get_server_from_table_to_cache(TABLE *table) table->use_all_columns(); /* get each field into the server struct ptr */ - server->server_name= get_field(&mem, table->field[0]); + ptr= get_field(&mem, table->field[0]); + server->server_name= ptr ? ptr : blank; server->server_name_length= (uint) strlen(server->server_name); ptr= get_field(&mem, table->field[1]); server->host= ptr ? ptr : blank; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a658abbc7b3..f3e948079e8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 @@ -2305,7 +2305,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) Security_context *tmp_sctx= tmp->security_ctx; struct st_my_thread_var *mysys_var; if ((tmp->vio_ok() || tmp->system_thread) && - (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) + (!user || (!tmp->system_thread && + tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) { thread_info *thd_info= new thread_info; @@ -2683,7 +2684,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) ulonglong max_counter; if ((!tmp->vio_ok() && !tmp->system_thread) || - (user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user)))) + (user && (tmp->system_thread || !tmp_sctx->user || + strcmp(tmp_sctx->user, user)))) continue; restore_record(table, s->default_values); @@ -8136,15 +8138,20 @@ bool get_schema_tables_result(JOIN *join, TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_information_schema_tables()) { +#if MYSQL_VERSION_ID > 100105 +#error I_S tables only need to be re-populated if make_cond_for_info_schema() will preserve outer fields bool is_subselect= (&lex->unit != lex->current_select->master_unit() && lex->current_select->master_unit()->item); +#else +#define is_subselect false +#endif /* A value of 0 indicates a dummy implementation */ if (table_list->schema_table->fill_table == 0) continue; /* skip I_S optimizations specific to get_all_tables */ - if (thd->lex->describe && + if (lex->describe && (table_list->schema_table->fill_table != get_all_tables)) continue; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2ca4ac0946f..6922d1802cb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1672,6 +1672,7 @@ void execute_ddl_log_recovery() (void) mysql_file_delete(key_file_global_ddl_log, file_name, MYF(0)); global_ddl_log.recovery_phase= FALSE; mysql_mutex_unlock(&LOCK_gdl); + thd->reset_query(); delete thd; /* Remember that we don't have a THD */ set_current_thd(0); @@ -2200,15 +2201,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, char path[FN_REFLEN + 1], wrong_tables_buff[160], *alias= NULL; String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1, system_charset_info); - uint path_length= 0; + uint path_length= 0, errors= 0; int error= 0; int non_temp_tables_count= 0; - bool foreign_key_error=0; bool non_tmp_error= 0; bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0; bool non_tmp_table_deleted= 0; bool is_drop_tmp_if_exists_added= 0; - bool one_table= tables->next_local == 0; bool was_view= 0; String built_query; String built_trans_tmp_query, built_non_trans_tmp_query; @@ -2494,12 +2493,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= ha_delete_table(thd, table_type, path, db, table->table_name, !dont_log_query); - if (error == HA_ERR_ROW_IS_REFERENCED) - { - /* the table is referenced by a foreign key constraint */ - foreign_key_error= 1; - } - if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) + if (!error) { int frm_delete_error, trigger_drop_error= 0; /* Delete the table definition file */ @@ -2517,11 +2511,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, if (trigger_drop_error || (frm_delete_error && frm_delete_error != ENOENT)) error= 1; - else if (!frm_delete_error || !error || if_exists) - { - error= 0; + else if (frm_delete_error && if_exists) thd->clear_error(); - } } non_tmp_error= error ? TRUE : non_tmp_error; } @@ -2532,6 +2523,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(db); wrong_tables.append('.'); wrong_tables.append(table->table_name); + errors++; } else { @@ -2555,14 +2547,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, err: if (wrong_tables.length()) { - if (one_table && was_view) + DBUG_ASSERT(errors); + if (errors == 1 && was_view) my_printf_error(ER_IT_IS_A_VIEW, ER(ER_IT_IS_A_VIEW), MYF(0), wrong_tables.c_ptr_safe()); - else if (!foreign_key_error) + else if (errors > 1 || !thd->is_error()) my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0), wrong_tables.c_ptr_safe()); - else - my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); error= 1; } @@ -2613,8 +2604,8 @@ err: /* Chop of the last comma */ built_query.chop(); built_query.append(" /* generated by server */"); - int error_code = (non_tmp_error ? - (foreign_key_error ? ER_ROW_IS_REFERENCED : ER_BAD_TABLE_ERROR) : 0); + int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno() + : 0; error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_query.ptr(), built_query.length(), @@ -5149,6 +5140,7 @@ mysql_rename_table(handlerton *base, const char *old_db, ulonglong save_bits= thd->variables.option_bits; int length; DBUG_ENTER("mysql_rename_table"); + DBUG_ASSERT(base); DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'", old_db, old_name, new_db, new_name)); @@ -5156,8 +5148,7 @@ mysql_rename_table(handlerton *base, const char *old_db, if (flags & NO_FK_CHECKS) thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; - file= (base == NULL ? 0 : - get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base)); + file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base); build_table_filename(from, sizeof(from) - 1, old_db, old_name, "", flags & FN_FROM_IS_TMP); @@ -5534,7 +5525,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, if (!table->view) { int result __attribute__((unused))= - show_create_table(thd, table, &query, create_info, WITHOUT_DB_NAME); + show_create_table(thd, table, &query, create_info, WITH_DB_NAME); DBUG_ASSERT(result == 0); // show_create_table() always return 0 do_logging= FALSE; @@ -5922,12 +5913,17 @@ drop_create_field: /* let us check the name of the first key part. */ if ((keyname= key->name.str) == NULL) { - List_iterator<Key_part_spec> part_it(key->columns); - Key_part_spec *kp; - if ((kp= part_it++)) - keyname= kp->field_name.str; - if (keyname == NULL) - continue; + if (key->type == Key::PRIMARY) + keyname= primary_key_name; + else + { + List_iterator<Key_part_spec> part_it(key->columns); + Key_part_spec *kp; + if ((kp= part_it++)) + keyname= kp->field_name.str; + if (keyname == NULL) + continue; + } } if (key->type != Key::FOREIGN_KEY) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 41647a7262f..a63d8a51a86 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -225,7 +225,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) view->definer.user= decoy.definer.user; lex->definer= &view->definer; } - if (lex->create_view_algorithm == DTYPE_ALGORITHM_UNDEFINED) + if (lex->create_view_algorithm == VIEW_ALGORITHM_INHERIT) lex->create_view_algorithm= (uint8) decoy.algorithm; if (lex->create_view_suid == VIEW_SUID_DEFAULT) lex->create_view_suid= decoy.view_suid ? diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b4b1154a283..b2e3b0e46c0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7142,7 +7142,7 @@ alter: my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"); MYSQL_YYABORT; } - lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; + lex->create_view_algorithm= VIEW_ALGORITHM_INHERIT; lex->create_view_mode= VIEW_ALTER; } view_tail @@ -7918,8 +7918,13 @@ opt_checksum_type: | EXTENDED_SYM { Lex->check_opt.flags= T_EXTEND; } ; +repair_table_or_view: + table_or_tables table_list opt_mi_repair_type + | VIEW_SYM { Lex->only_view= TRUE; } table_list opt_view_repair_type + ; + repair: - REPAIR opt_no_write_to_binlog table_or_view + REPAIR opt_no_write_to_binlog { LEX *lex=Lex; lex->sql_command = SQLCOM_REPAIR; @@ -7929,18 +7934,9 @@ repair: /* Will be overriden during execution. */ YYPS->m_lock_type= TL_UNLOCK; } - table_list opt_mi_repair_type + repair_table_or_view { LEX* lex= thd->lex; - if ((lex->only_view && - ((lex->check_opt.flags & (T_QUICK | T_EXTEND)) || - (lex->check_opt.sql_flags & TT_USEFRM))) || - (!lex->only_view && - (lex->check_opt.sql_flags & TT_FROM_MYSQL))) - { - my_parse_error(ER(ER_SYNTAX_ERROR)); - MYSQL_YYABORT; - } DBUG_ASSERT(!lex->m_sql_cmd); lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table(); if (lex->m_sql_cmd == NULL) @@ -7962,6 +7958,10 @@ mi_repair_type: QUICK { Lex->check_opt.flags|= T_QUICK; } | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; } | USE_FRM { Lex->check_opt.sql_flags|= TT_USEFRM; } + ; + +opt_view_repair_type: + /* empty */ { } | FROM MYSQL_SYM { Lex->check_opt.sql_flags|= TT_FROM_MYSQL; } ; @@ -8081,30 +8081,27 @@ binlog_base64_event: } ; -check: - CHECK_SYM table_or_view +check_view_or_table: + table_or_tables table_list opt_mi_check_type + | VIEW_SYM { Lex->only_view= TRUE; } table_list opt_view_check_type + ; + +check: CHECK_SYM { LEX *lex=Lex; - if (lex->sphead) - { - my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK"); - MYSQL_YYABORT; - } lex->sql_command = SQLCOM_CHECK; lex->check_opt.init(); lex->alter_info.reset(); /* Will be overriden during execution. */ YYPS->m_lock_type= TL_UNLOCK; } - table_list opt_mi_check_type + check_view_or_table { LEX* lex= thd->lex; - if (lex->only_view && - (lex->check_opt.flags & (T_QUICK | T_FAST | T_EXTEND | - T_CHECK_ONLY_CHANGED))) + if (lex->sphead) { - my_parse_error(ER(ER_SYNTAX_ERROR)); + my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK"); MYSQL_YYABORT; } DBUG_ASSERT(!lex->m_sql_cmd); @@ -8133,6 +8130,11 @@ mi_check_type: | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; } ; +opt_view_check_type: + /* empty */ { } + | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; } + ; + optimize: OPTIMIZE opt_no_write_to_binlog table_or_tables { @@ -8214,7 +8216,6 @@ keycache: LEX *lex=Lex; lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE; lex->ident= $6; - lex->only_view= FALSE; } ; @@ -8259,7 +8260,6 @@ preload: LEX *lex=Lex; lex->sql_command=SQLCOM_PRELOAD_KEYS; lex->alter_info.reset(); - lex->only_view= FALSE; } preload_list_or_parts {} @@ -12546,7 +12546,6 @@ show_param: lex->sql_command = SQLCOM_SHOW_CREATE; if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0)) MYSQL_YYABORT; - lex->only_view= 0; lex->create_info.storage_media= HA_SM_DEFAULT; } | CREATE VIEW_SYM table_ident @@ -14864,13 +14863,8 @@ lock: ; table_or_tables: - TABLE_SYM { Lex->only_view= FALSE; } - | TABLES { Lex->only_view= FALSE; } - ; - -table_or_view: - table_or_tables - | VIEW_SYM { Lex->only_view= TRUE; } + TABLE_SYM { } + | TABLES { } ; table_lock_list: diff --git a/sql/table.h b/sql/table.h index df7fd852a76..39faa8b9765 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1541,6 +1541,8 @@ typedef struct st_schema_table #define DT_PHASES_MATERIALIZE (DT_COMMON | DT_MATERIALIZE) #define VIEW_ALGORITHM_UNDEFINED 0 +/* Special value for ALTER VIEW: inherit original algorithm. */ +#define VIEW_ALGORITHM_INHERIT DTYPE_VIEW #define VIEW_ALGORITHM_MERGE (DTYPE_VIEW | DTYPE_MERGE) #define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW | DTYPE_MATERIALIZE) diff --git a/sql/tztime.cc b/sql/tztime.cc index 2a5a5d1681b..8e7200c9ba1 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2523,7 +2523,8 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level, uint verbose) for (i= 0; i < cur_dir->number_of_files; i++) { - if (cur_dir->dir_entry[i].name[0] != '.') + if (cur_dir->dir_entry[i].name[0] != '.' && + strcmp(cur_dir->dir_entry[i].name, "Factory")) { name_end_tmp= strmake(name_end, cur_dir->dir_entry[i].name, FN_REFLEN - (name_end - fullname)); diff --git a/sql/winservice.h b/sql/winservice.h index fca7b129de5..c3e2bfe1b20 100644 --- a/sql/winservice.h +++ b/sql/winservice.h @@ -1,40 +1,40 @@ -/*
- Copyright (c) 2011, 2012, Monty Program Ab
-
- 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
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Extract properties of a windows service binary path
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <windows.h>
-typedef struct mysqld_service_properties_st
-{
- char mysqld_exe[MAX_PATH];
- char inifile[MAX_PATH];
- char datadir[MAX_PATH];
- int version_major;
- int version_minor;
- int version_patch;
-} mysqld_service_properties;
-
-extern int get_mysql_service_properties(const wchar_t *bin_path,
- mysqld_service_properties *props);
-
-#ifdef __cplusplus
-}
-#endif
+/* + Copyright (c) 2011, 2012, Monty Program Ab + + 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Extract properties of a windows service binary path +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#include <windows.h> +typedef struct mysqld_service_properties_st +{ + char mysqld_exe[MAX_PATH]; + char inifile[MAX_PATH]; + char datadir[MAX_PATH]; + int version_major; + int version_minor; + int version_patch; +} mysqld_service_properties; + +extern int get_mysql_service_properties(const wchar_t *bin_path, + mysqld_service_properties *props); + +#ifdef __cplusplus +} +#endif |