summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/field.cc')
-rw-r--r--sql/field.cc175
1 files changed, 97 insertions, 78 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 4f04fef1a26..9b413ca8a78 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1348,7 +1348,7 @@ bool Field::sp_prepare_and_store_item(THD *thd, Item **value)
expr_item->save_in_field(this, 0);
- if (!thd->is_error())
+ if (likely(!thd->is_error()))
DBUG_RETURN(false);
error:
@@ -1388,7 +1388,7 @@ void Field_num::prepend_zeros(String *value) const
if ((diff= (int) (field_length - value->length())) > 0)
{
const bool error= value->realloc(field_length);
- if (!error)
+ if (likely(!error))
{
bmove_upp((uchar*) value->ptr()+field_length,
(uchar*) value->ptr()+value->length(),
@@ -1630,7 +1630,7 @@ double Field_real::get_double(const char *str, size_t length, CHARSET_INFO *cs,
{
char *end;
double nr= my_strntod(cs,(char*) str, length, &end, error);
- if (*error)
+ if (unlikely(*error))
{
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
*error= 1;
@@ -3190,7 +3190,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value,
*native_error= my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
decimal_value, ptr, precision, dec);
- if (*native_error == E_DEC_OVERFLOW)
+ if (unlikely(*native_error == E_DEC_OVERFLOW))
{
my_decimal buff;
DBUG_PRINT("info", ("overflow"));
@@ -3209,7 +3209,7 @@ 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)
+ if (unlikely(!rc && native_error == E_DEC_TRUNCATED))
set_note(WARN_DATA_TRUNCATED, 1);
return rc;
}
@@ -4189,7 +4189,7 @@ int Field_long::store(double nr)
else
res=(int32) (longlong) nr;
}
- if (error)
+ if (unlikely(error))
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
int4store(ptr,res);
@@ -4235,7 +4235,7 @@ int Field_long::store(longlong nr, bool unsigned_val)
else
res=(int32) nr;
}
- if (error)
+ if (unlikely(error))
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
int4store(ptr,res);
@@ -4319,7 +4319,7 @@ int Field_longlong::store(const char *from,size_t len,CHARSET_INFO *cs)
ulonglong tmp;
tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error);
- if (error == MY_ERRNO_ERANGE)
+ if (unlikely(error == MY_ERRNO_ERANGE))
{
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
@@ -4339,7 +4339,7 @@ int Field_longlong::store(double nr)
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
Converter_double_to_longlong conv(nr, unsigned_flag);
- if (conv.error())
+ if (unlikely(conv.error()))
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
int8store(ptr, conv.result());
@@ -4352,7 +4352,7 @@ int Field_longlong::store(longlong nr, bool unsigned_val)
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
- if (nr < 0) // Only possible error
+ if (unlikely(nr < 0)) // Only possible error
{
/*
if field is unsigned and value is signed (< 0) or
@@ -4501,7 +4501,7 @@ int Field_float::store(double nr)
int error= truncate_double(&nr, field_length,
not_fixed ? NOT_FIXED_DEC : dec,
unsigned_flag, FLT_MAX);
- if (error)
+ if (unlikely(error))
{
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
if (error < 0) // Wrong double value
@@ -4680,7 +4680,7 @@ int Field_double::store(double nr)
int error= truncate_double(&nr, field_length,
not_fixed ? NOT_FIXED_DEC : dec,
unsigned_flag, DBL_MAX);
- if (error)
+ if (unlikely(error))
{
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
if (error < 0) // Wrong double value
@@ -4847,7 +4847,7 @@ double Field_double::val_real(void)
longlong Field_double::val_int_from_real(bool want_unsigned_result)
{
Converter_double_to_longlong conv(val_real(), want_unsigned_result);
- if (!want_unsigned_result && conv.error())
+ if (unlikely(!want_unsigned_result && conv.error()))
conv.push_warning(get_thd(), Field_double::val_real(), false);
return conv.result();
}
@@ -5084,7 +5084,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
timestamp= TIME_to_timestamp(thd, l_time, &conversion_error);
if (timestamp == 0 && l_time->second_part == 0)
conversion_error= ER_WARN_DATA_OUT_OF_RANGE;
- if (conversion_error)
+ if (unlikely(conversion_error))
{
set_datetime_warning(conversion_error,
str, MYSQL_TIMESTAMP_DATETIME, !error);
@@ -6276,7 +6276,7 @@ int Field_year::store(const char *from, size_t len,CHARSET_INFO *cs)
if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
(error= check_int(cs, from, len, end, error)))
{
- if (error == 1) /* empty or incorrect string */
+ if (unlikely(error == 1) /* empty or incorrect string */)
{
*ptr= 0;
return 1;
@@ -6943,7 +6943,7 @@ Field_longstr::check_string_copy_error(const String_copier *copier,
const char *pos;
char tmp[32];
- if (!(pos= copier->most_important_error_pos()))
+ if (likely(!(pos= copier->most_important_error_pos())))
return FALSE;
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
@@ -7003,15 +7003,15 @@ int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
- String_copier copier;
+ int rc;
/* See the comment for Field_long::store(long long) */
DBUG_ASSERT(!table || table->in_use == current_thd);
- copy_length= copier.well_formed_copy(field_charset,
- (char*) ptr, field_length,
- cs, from, length,
- field_length / field_charset->mbmaxlen);
+ rc= well_formed_copy_with_check((char*) ptr, field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ false, &copy_length);
/* Append spaces if the string was shorter than the field. */
if (copy_length < field_length)
@@ -7019,7 +7019,7 @@ int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs)
field_length-copy_length,
field_charset->pad_char);
- return check_conversion_status(&copier, from + length, cs, false);
+ return rc;
}
@@ -7055,10 +7055,10 @@ int Field_str::store(double nr)
my_bool error= (local_char_length == 0);
// my_gcvt() requires width > 0, and we may have a CHAR(0) column.
- if (!error)
+ if (likely(!error))
length= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, local_char_length, buff, &error);
- if (error)
+ if (unlikely(error))
{
if (get_thd()->abort_on_warning)
set_warning(ER_DATA_TOO_LONG, 1);
@@ -7553,19 +7553,16 @@ int Field_varstring::store(const char *from,size_t length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
- String_copier copier;
+ int rc;
- copy_length= copier.well_formed_copy(field_charset,
- (char*) ptr + length_bytes,
- field_length,
- cs, from, length,
- field_length / field_charset->mbmaxlen);
- if (length_bytes == 1)
- *ptr= (uchar) copy_length;
- else
- int2store(ptr, copy_length);
+ rc= well_formed_copy_with_check((char*) get_data(), field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ true, &copy_length);
+
+ store_length(copy_length);
- return check_conversion_status(&copier, from + length, cs, true);
+ return rc;
}
@@ -7959,10 +7956,13 @@ void Field_varstring::hash(ulong *nr, ulong *nr2)
Compress field
@param[out] to destination buffer for compressed data
- @param[in,out] to_length in: size of to, out: compressed data length
+ @param[in] to_length size of to
@param[in] from data to compress
@param[in] length from length
+ @param[in] max_length truncate `from' to this length
+ @param[out] out_length compessed data length
@param[in] cs from character set
+ @param[in] nchars copy no more than "nchars" characters
In worst case (no compression performed) storage requirement is increased by
1 byte to store header. If it exceeds field length, normal data truncation is
@@ -7986,52 +7986,57 @@ void Field_varstring::hash(ulong *nr, ulong *nr2)
followed by compressed data.
*/
-int Field_longstr::compress(char *to, uint *to_length,
+int Field_longstr::compress(char *to, uint to_length,
const char *from, uint length,
- CHARSET_INFO *cs)
+ uint max_length,
+ uint *out_length,
+ CHARSET_INFO *cs, size_t nchars)
{
THD *thd= get_thd();
- char *buf= 0;
+ char *buf;
+ uint buf_length;
int rc= 0;
- if (length == 0)
- {
- *to_length= 0;
- return 0;
- }
-
if (String::needs_conversion_on_storage(length, cs, field_charset) ||
- *to_length <= length)
+ max_length < length)
{
- String_copier copier;
- const char *end= from + length;
-
- if (!(buf= (char*) my_malloc(*to_length - 1, MYF(MY_WME))))
+ set_if_smaller(max_length, static_cast<ulonglong>(field_charset->mbmaxlen) * length + 1);
+ if (!(buf= (char*) my_malloc(max_length, MYF(MY_WME))))
{
- *to_length= 0;
+ *out_length= 0;
return -1;
}
- length= copier.well_formed_copy(field_charset, buf, *to_length - 1,
- cs, from, length,
- (*to_length - 1) / field_charset->mbmaxlen);
- rc= check_conversion_status(&copier, end, cs, true);
- from= buf;
- DBUG_ASSERT(length > 0);
+ rc= well_formed_copy_with_check(buf, max_length, cs, from, length,
+ nchars, true, &buf_length);
+ }
+ else
+ {
+ buf= const_cast<char*>(from);
+ buf_length= length;
}
- if (length >= thd->variables.column_compression_threshold &&
- (*to_length= compression_method()->compress(thd, to, from, length)))
+ if (buf_length == 0)
+ *out_length= 0;
+ else if (buf_length >= thd->variables.column_compression_threshold &&
+ (*out_length= compression_method()->compress(thd, to, buf, buf_length)))
status_var_increment(thd->status_var.column_compressions);
else
{
/* Store uncompressed */
to[0]= 0;
- memcpy(to + 1, from, length);
- *to_length= length + 1;
+ if (buf_length < to_length)
+ memcpy(to + 1, buf, buf_length);
+ else
+ {
+ /* Storing string at blob capacity, e.g. 255 bytes string to TINYBLOB. */
+ rc= well_formed_copy_with_check(to + 1, to_length - 1, cs, from, length,
+ nchars, true, &buf_length);
+ }
+ *out_length= buf_length + 1;
}
- if (buf)
+ if (buf != from)
my_free(buf);
return rc;
}
@@ -8085,9 +8090,12 @@ int Field_varstring_compressed::store(const char *from, size_t length,
CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- uint to_length= (uint)MY_MIN(field_length, field_charset->mbmaxlen * length + 1);
- int rc= compress((char*) get_data(), &to_length, from, (uint)length, cs);
- store_length(to_length);
+ uint compressed_length;
+ int rc= compress((char*) get_data(), field_length, from, (uint) length,
+ Field_varstring_compressed::max_display_length(),
+ &compressed_length, cs,
+ Field_varstring_compressed::char_length());
+ store_length(compressed_length);
return rc;
}
@@ -8215,10 +8223,11 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
size_t copy_length, new_length;
- String_copier copier;
+ uint copy_len;
char *tmp;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
+ int rc;
if (!length)
{
@@ -8285,13 +8294,13 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
return 0;
}
- copy_length= copier.well_formed_copy(field_charset,
- (char*) value.ptr(), (uint)new_length,
- cs, from, length);
- Field_blob::store_length(copy_length);
+ rc= well_formed_copy_with_check((char*) value.ptr(), (uint) new_length,
+ cs, from, length,
+ length, true, &copy_len);
+ Field_blob::store_length(copy_len);
bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));
- return check_conversion_status(&copier, from + length, cs, true);
+ return rc;
oom_error:
/* Fatal OOM error */
@@ -8695,7 +8704,10 @@ int Field_blob_compressed::store(const char *from, size_t length,
CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- uint to_length= (uint)MY_MIN(max_data_length(), field_charset->mbmaxlen * length + 1);
+ uint compressed_length;
+ uint max_length= max_data_length();
+ uint to_length= (uint) MY_MIN(max_length,
+ field_charset->mbmaxlen * length + 1);
String tmp(from, length, cs);
int rc;
@@ -8705,8 +8717,9 @@ int Field_blob_compressed::store(const char *from, size_t length,
if (value.alloc(to_length))
goto oom;
- rc= compress((char*) value.ptr(), &to_length, tmp.ptr(), (uint) length, cs);
- set_ptr(to_length, (uchar*) value.ptr());
+ rc= compress((char*) value.ptr(), to_length, tmp.ptr(), (uint) length,
+ max_length, &compressed_length, cs, (uint) length);
+ set_ptr(compressed_length, (uchar*) value.ptr());
return rc;
oom:
@@ -10319,7 +10332,7 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
if (type == VCOL_GENERATED_VIRTUAL)
filter|= VCOL_NOT_VIRTUAL;
- if (ret || (res.errors & filter))
+ if (unlikely(ret || (res.errors & filter)))
{
my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), res.name,
vcol_type_name(type), name->str);
@@ -10805,6 +10818,12 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field,
uint32 Field_blob::char_length() const
{
+ return Field_blob::octet_length();
+}
+
+
+uint32 Field_blob::octet_length() const
+{
switch (packlength)
{
case 1:
@@ -10879,7 +10898,7 @@ bool Column_definition::set_compressed(const char *method)
length
*/
-uint32 Field_blob::max_display_length()
+uint32 Field_blob::max_display_length() const
{
switch (packlength)
{
@@ -11061,8 +11080,8 @@ bool Field::save_in_field_default_value(bool view_error_processing)
{
THD *thd= table->in_use;
- if (flags & NO_DEFAULT_VALUE_FLAG &&
- real_type() != MYSQL_TYPE_ENUM)
+ if (unlikely(flags & NO_DEFAULT_VALUE_FLAG &&
+ real_type() != MYSQL_TYPE_ENUM))
{
if (reset())
{