Fixed bug#30059.

Server handles truncation for assignment of too-long values
into CHAR/VARCHAR/TEXT columns in a different ways when the
truncated characters are spaces:
1. CHAR(N) columns silently ignore end-space truncation;
2. TEXT columns post a truncation warning/error in the
   non-strict/strict mode.
3. VARCHAR columns always post a truncation note in
   any mode.

Space truncation processing has been synchronised over
CHAR/VARCHAR/TEXT columns: current behavior of VARCHAR
columns has been propagated as standard.

Binary-encoded string/BLOB columns are not affected.


mysql-test/r/heap.result:
  Updated test case for bug#30059.
mysql-test/r/innodb.result:
  Updated test case for bug#30059.
mysql-test/r/myisam.result:
  Updated test case for bug#30059.
mysql-test/r/strict.result:
  Updated test case for bug#30059.
mysql-test/r/type_binary.result:
  Updated test case for bug#30059.
mysql-test/r/warnings.result:
  Added test case for bug#30059.
mysql-test/t/warnings.test:
  Added test case for bug#30059.
sql/field.cc:
  Fixed bug#30059.
  The report_data_too_long function was replaced with the
  Field_longstr::report_if_important_data method.
  
  The Field_string::store and the Field_blob::store
  methods was synchronized with the Field_varstring::store
  method.
  Changes:
  1. to CHAR(N): posting of space truncation note has been added
     in both (strict and non-strict) modes;
  2. to BLOBs: a check for space truncation has been added,
     a warning in the non-strict mode and an error message in
     the strict mode have been replaced with a truncation note.
  
  Similar parts of Field_string::store, Field_blob::store and
  Field_varstring::store have been moved to the
  Field_longstr::report_if_important_data method.
sql/field.h:
  Fixed bug#30059.
  The Field_longstr::report_if_important_data method has been declared.
This commit is contained in:
unknown 2008-02-07 02:33:21 +04:00
commit 3891d43617
9 changed files with 110 additions and 43 deletions

View file

@ -5861,26 +5861,41 @@ check_string_copy_error(Field_str *field,
}
/*
Send a truncation warning or a truncation error
after storing a too long character string info a field.
Check if we lost any important data and send a truncation error/warning
SYNOPSIS
report_data_too_long()
field - Field
Field_longstr::report_if_important_data()
ptr - Truncated rest of string
end - End of truncated string
RETURN
N/A
RETURN VALUES
0 - None was truncated (or we don't count cut fields)
2 - Some bytes was truncated
NOTE
Check if we lost any important data (anything in a binary string,
or any non-space in others). If only trailing spaces was lost,
send a truncation note, otherwise send a truncation error.
*/
inline void
report_data_too_long(Field_str *field)
int
Field_longstr::report_if_important_data(const char *ptr, const char *end)
{
if (field->table->in_use->abort_on_warning)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
else
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
if ((ptr < end) && table->in_use->count_cuted_fields)
{
if (test_if_important_data(field_charset, ptr, end))
{
if (table->in_use->abort_on_warning)
set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
else /* If we lost only spaces then produce a NOTE, not a WARNING */
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
return 2;
}
return 0;
}
@ -5914,19 +5929,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
cannot_convert_error_pos, from + length))
return 2;
/*
Check if we lost any important data (anything in a binary string,
or any non-space in others).
*/
if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
if (test_if_important_data(field_charset, from_end_pos, from + length))
{
report_data_too_long(this);
return 2;
}
}
return 0;
return report_if_important_data(from_end_pos, from + length);
}
@ -6385,16 +6388,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
cannot_convert_error_pos, from + length))
return 2;
// Check if we lost something other than just trailing spaces
if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
if (test_if_important_data(field_charset, from_end_pos, from + length))
report_data_too_long(this);
else /* If we lost only spaces then produce a NOTE, not a WARNING */
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
return 2;
}
return 0;
return report_if_important_data(from_end_pos, from + length);
}
@ -7030,13 +7024,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
cannot_convert_error_pos, from + length))
return 2;
if (from_end_pos < from + length)
{
report_data_too_long(this);
return 2;
}
return 0;
return report_if_important_data(from_end_pos, from + length);
oom_error:
/* Fatal OOM error */