diff options
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 175 |
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, ©_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, ©_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, ©_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()) { |