mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bug#20095 Changing length of VARCHAR field with UTF8 collation does not truncate values
Problem: single byte do_varstring1() function was called, which didn't check limit on "number of character", and checked only "number of bytes". Fix: adding a multi-byte aware function do_varstring1_mb(), to limit on "number of characters"
This commit is contained in:
@ -434,6 +434,26 @@ static void do_varstring1(Copy_field *copy)
|
||||
}
|
||||
|
||||
|
||||
static void do_varstring1_mb(Copy_field *copy)
|
||||
{
|
||||
int well_formed_error;
|
||||
CHARSET_INFO *cs= copy->from_field->charset();
|
||||
uint from_length= (uint) *(uchar*) copy->from_ptr;
|
||||
const char *from_ptr= copy->from_ptr + 1;
|
||||
uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
|
||||
uint length= cs->cset->well_formed_len(cs, from_ptr, from_ptr + from_length,
|
||||
to_char_length, &well_formed_error);
|
||||
if (length < from_length)
|
||||
{
|
||||
if (current_thd->count_cuted_fields)
|
||||
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
WARN_DATA_TRUNCATED, 1);
|
||||
}
|
||||
*(uchar*) copy->to_ptr= (uchar) length;
|
||||
memcpy(copy->to_ptr + 1, from_ptr, length);
|
||||
}
|
||||
|
||||
|
||||
static void do_varstring2(Copy_field *copy)
|
||||
{
|
||||
uint length=uint2korr(copy->from_ptr);
|
||||
@ -459,6 +479,12 @@ static void do_varstring2_mb(Copy_field *copy)
|
||||
const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
|
||||
uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length,
|
||||
char_length, &well_formed_error);
|
||||
if (length < from_length)
|
||||
{
|
||||
if (current_thd->count_cuted_fields)
|
||||
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
WARN_DATA_TRUNCATED, 1);
|
||||
}
|
||||
int2store(copy->to_ptr, length);
|
||||
memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
|
||||
}
|
||||
@ -634,8 +660,10 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
|
||||
return do_field_string;
|
||||
if (to_length != from_length)
|
||||
return (((Field_varstring*) to)->length_bytes == 1 ?
|
||||
do_varstring1 : (from->charset()->mbmaxlen == 1 ?
|
||||
do_varstring2 : do_varstring2_mb));
|
||||
(from->charset()->mbmaxlen == 1 ? do_varstring1 :
|
||||
do_varstring1_mb) :
|
||||
(from->charset()->mbmaxlen == 1 ? do_varstring2 :
|
||||
do_varstring2_mb));
|
||||
}
|
||||
else if (to_length < from_length)
|
||||
return (from->charset()->mbmaxlen == 1 ?
|
||||
|
Reference in New Issue
Block a user