diff options
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/sql/field.cc b/sql/field.cc index 36a5daaa165..c684e6a8046 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1503,10 +1503,12 @@ Value_source::Converter_string_to_number::check_edom_and_truncation(THD *thd, */ -int Field_num::check_edom_and_truncation(const char *type, bool edom, - CHARSET_INFO *cs, - const char *str, uint length, - const char *end) +int Field_num::check_edom_and_important_data_truncation(const char *type, + bool edom, + CHARSET_INFO *cs, + const char *str, + uint length, + const char *end) { /* Test if we get an empty string or garbage */ if (edom) @@ -1521,12 +1523,23 @@ int Field_num::check_edom_and_truncation(const char *type, bool edom, set_warning(WARN_DATA_TRUNCATED, 1); return 2; } - if (end < str + length) - set_note(WARN_DATA_TRUNCATED, 1); return 0; } +int Field_num::check_edom_and_truncation(const char *type, bool edom, + CHARSET_INFO *cs, + const char *str, uint length, + const char *end) +{ + int rc= check_edom_and_important_data_truncation(type, edom, + cs, str, length, end); + if (!rc && end < str + length) + set_note(WARN_DATA_TRUNCATED, 1); + return rc; +} + + /* Conver a string to an integer then check bounds. @@ -2050,6 +2063,7 @@ Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, if (charset_arg->state & MY_CS_BINSORT) flags|=BINARY_FLAG; field_derivation= DERIVATION_IMPLICIT; + field_repertoire= my_charset_repertoire(charset_arg); } @@ -3048,7 +3062,8 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, If it does, stores the decimal in the buffer using binary format. Otherwise sets maximal number that can be stored in the field. - @param decimal_value my_decimal + @param decimal_value my_decimal + @param [OUT] native_error the error returned by my_decimal2binary(). @retval 0 ok @@ -3056,7 +3071,8 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, 1 error */ -bool Field_new_decimal::store_value(const my_decimal *decimal_value) +bool Field_new_decimal::store_value(const my_decimal *decimal_value, + int *native_error) { ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; int error= 0; @@ -3085,11 +3101,14 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) } #endif - if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, - decimal_value, ptr, precision, dec))) + *native_error= my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, + decimal_value, ptr, precision, dec); + + if (*native_error == E_DEC_OVERFLOW) { my_decimal buff; DBUG_PRINT("info", ("overflow")); + set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_value_on_overflow(&buff, decimal_value->sign()); my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec); error= 1; @@ -3100,6 +3119,16 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) } +bool Field_new_decimal::store_value(const my_decimal *decimal_value) +{ + int native_error; + bool rc= store_value(decimal_value, &native_error); + if (!rc && native_error == E_DEC_TRUNCATED) + set_note(WARN_DATA_TRUNCATED, 1); + return rc; +} + + int Field_new_decimal::store(const char *from, uint length, CHARSET_INFO *charset_arg) { @@ -3127,9 +3156,10 @@ int Field_new_decimal::store(const char *from, uint length, if (thd->count_cuted_fields) { - if (check_edom_and_truncation("decimal", - err && err != E_DEC_TRUNCATED, - charset_arg, from, length, end)) + if (check_edom_and_important_data_truncation("decimal", + err && err != E_DEC_TRUNCATED, + charset_arg, + from, length, end)) { if (!thd->abort_on_warning) { @@ -3152,12 +3182,6 @@ int Field_new_decimal::store(const char *from, uint length, } DBUG_RETURN(1); } - /* - E_DEC_TRUNCATED means minor truncation '1e-1000000000000' -> 0.0 - A note should be enough. - */ - if (err == E_DEC_TRUNCATED) - set_note(WARN_DATA_TRUNCATED, 1); } #ifndef DBUG_OFF @@ -3165,7 +3189,21 @@ int Field_new_decimal::store(const char *from, uint length, DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, &decimal_value))); #endif - store_value(&decimal_value); + int err2; + if (store_value(&decimal_value, &err2)) + DBUG_RETURN(1); + + /* + E_DEC_TRUNCATED means minor truncation, a note should be enough: + - in err: str2my_decimal() truncated '1e-1000000000000' to 0.0 + - in err2: store_value() truncated 1.123 to 1.12, e.g. for DECIMAL(10,2) + Also, we send a note if a string had some trailing spaces: '1.12 ' + */ + if (thd->count_cuted_fields && + (err == E_DEC_TRUNCATED || + err2 == E_DEC_TRUNCATED || + end < from + length)) + set_note(WARN_DATA_TRUNCATED, 1); DBUG_RETURN(0); } |