summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/field.cc')
-rw-r--r--sql/field.cc78
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);
}