Skip to content

Commit

Permalink
Reducing duplicate code and simplifying well formed string copying
Browse files Browse the repository at this point in the history
by adding a new class String_copier.

This is a pre-requisite patch for MDEV-6566 and MDEV-6572,
to avoid adding more similar code.
  • Loading branch information
Alexander Barkov committed Feb 27, 2015
1 parent 2d01907 commit 72d7b12
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 152 deletions.
86 changes: 23 additions & 63 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6262,10 +6262,9 @@ bool Field_datetimef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
SYNOPSIS
check_string_copy_error()
field - Field
well_formed_error_pos - where not well formed data was first met
cannot_convert_error_pos - where a not-convertable character was first met
end - end of the string
copier - the conversion status
end - the very end of the source string
that was just copied
cs - character set of the string
NOTES
Expand All @@ -6282,30 +6281,25 @@ 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 String_copier *copier,
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))
if (!(pos= copier->most_important_error_pos()))
return FALSE;

convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);

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),
"string", tmp, field->field_name,
"string", tmp, field_name,
thd->get_stmt_da()->current_row_for_warning());
return TRUE;
}
Expand Down Expand Up @@ -6362,32 +6356,23 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
const char *from_end_pos;
String_copier copier;

/* See the comment for Field_long::store(long long) */
DBUG_ASSERT(!table || table->in_use == current_thd);

copy_length= well_formed_copy_nchars(field_charset,
copy_length= copier.well_formed_copy(field_charset,
(char*) ptr, field_length,
cs, from, length,
field_length / field_charset->mbmaxlen,
&well_formed_error_pos,
&cannot_convert_error_pos,
&from_end_pos);
field_length / field_charset->mbmaxlen);

/* Append spaces if the string was shorter than the field. */
if (copy_length < field_length)
field_charset->cset->fill(field_charset,(char*) ptr+copy_length,
field_length-copy_length,
field_charset->pad_char);

if (check_string_copy_error(this, well_formed_error_pos,
cannot_convert_error_pos, from + length, cs))
return 2;

return report_if_important_data(from_end_pos, from + length, FALSE);
return check_conversion_status(&copier, from + length, cs, false);
}


Expand Down Expand Up @@ -6874,29 +6859,19 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
const char *from_end_pos;
String_copier copier;

copy_length= well_formed_copy_nchars(field_charset,
copy_length= copier.well_formed_copy(field_charset,
(char*) ptr + length_bytes,
field_length,
cs, from, length,
field_length / field_charset->mbmaxlen,
&well_formed_error_pos,
&cannot_convert_error_pos,
&from_end_pos);

field_length / field_charset->mbmaxlen);
if (length_bytes == 1)
*ptr= (uchar) copy_length;
else
int2store(ptr, copy_length);

if (check_string_copy_error(this, well_formed_error_pos,
cannot_convert_error_pos, from + length, cs))
return 2;

return report_if_important_data(from_end_pos, from + length, TRUE);
return check_conversion_status(&copier, from + length, cs, true);
}


Expand Down Expand Up @@ -7351,9 +7326,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length, new_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
const char *from_end_pos, *tmp;
String_copier copier;
const char *tmp;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);

Expand Down Expand Up @@ -7401,28 +7375,14 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
return 0;
}
/*
"length" is OK as "nchars" argument to well_formed_copy_nchars as this
is never used to limit the length of the data. The cut of long data
is done with the new_length value.
*/
copy_length= well_formed_copy_nchars(field_charset,
copy_length= copier.well_formed_copy(field_charset,
(char*) value.ptr(), new_length,
cs, from, length,
length,
&well_formed_error_pos,
&cannot_convert_error_pos,
&from_end_pos);

cs, from, length);
Field_blob::store_length(copy_length);
tmp= value.ptr();
bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));

if (check_string_copy_error(this, well_formed_error_pos,
cannot_convert_error_pos, from + length, cs))
return 2;

return report_if_important_data(from_end_pos, from + length, TRUE);
return check_conversion_status(&copier, from + length, cs, true);

oom_error:
/* Fatal OOM error */
Expand Down
11 changes: 11 additions & 0 deletions sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,17 @@ 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 String_copier *copier,
const char *end, CHARSET_INFO *cs);
int check_conversion_status(const String_copier *copier,
const char *end, CHARSET_INFO *cs,
bool count_spaces)
{
if (check_string_copy_error(copier, end, cs))
return 2;
return report_if_important_data(copier->source_end_pos(),
end, count_spaces);
}
public:
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
Expand Down
19 changes: 6 additions & 13 deletions sql/sql_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2986,9 +2986,7 @@ int select_export::send_data(List<Item> &items)
if (res && !my_charset_same(write_cs, res->charset()) &&
!my_charset_same(write_cs, &my_charset_bin))
{
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
const char *from_end_pos;
String_copier copier;
const char *error_pos;
uint32 bytes;
uint64 estimated_bytes=
Expand All @@ -3001,16 +2999,11 @@ int select_export::send_data(List<Item> &items)
goto err;
}

bytes= well_formed_copy_nchars(write_cs, (char *) cvt_str.ptr(),
bytes= copier.well_formed_copy(write_cs, (char *) cvt_str.ptr(),
cvt_str.alloced_length(),
res->charset(), res->ptr(), res->length(),
UINT_MAX32, // copy all input chars,
// i.e. ignore nchars parameter
&well_formed_error_pos,
&cannot_convert_error_pos,
&from_end_pos);
error_pos= well_formed_error_pos ? well_formed_error_pos
: cannot_convert_error_pos;
res->charset(),
res->ptr(), res->length());
error_pos= copier.most_important_error_pos();
if (error_pos)
{
char printable_buff[32];
Expand All @@ -3023,7 +3016,7 @@ int select_export::send_data(List<Item> &items)
"string", printable_buff,
item->name, static_cast<long>(row_count));
}
else if (from_end_pos < res->ptr() + res->length())
else if (copier.source_end_pos() < res->ptr() + res->length())
{
/*
result is longer than UINT_MAX32 and doesn't fit into String
Expand Down
13 changes: 3 additions & 10 deletions sql/sql_signal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,16 +195,9 @@ static bool assign_fixed_string(MEM_ROOT *mem_root,
dst_str= (char*) alloc_root(mem_root, dst_len + 1);
if (dst_str)
{
const char* well_formed_error_pos;
const char* cannot_convert_error_pos;
const char* from_end_pos;

dst_copied= well_formed_copy_nchars(dst_cs, dst_str, dst_len,
src_cs, src_str, src_len,
numchars,
& well_formed_error_pos,
& cannot_convert_error_pos,
& from_end_pos);
dst_copied= String_copier().well_formed_copy(dst_cs, dst_str, dst_len,
src_cs, src_str, src_len,
numchars);
DBUG_ASSERT(dst_copied <= dst_len);
dst_len= dst_copied; /* In case the copy truncated the data */
dst_str[dst_copied]= '\0';
Expand Down
Loading

0 comments on commit 72d7b12

Please sign in to comment.