diff --git a/sql/sql_string.cc b/sql/sql_string.cc index e68e57e6eb8..dfc450ada92 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -118,6 +118,38 @@ bool Binary_string::realloc_raw(size_t alloc_length) } +static uint32 write_float_str_to_buff(char *buff, int buff_len, + float num, uint decimals) +{ + if (decimals >= FLOATING_POINT_DECIMALS) + return (uint32)my_gcvt(num, MY_GCVT_ARG_FLOAT, buff_len - 1, buff, NULL); + else + return (uint32)my_fcvt(num, decimals, buff, NULL); +} + +bool String::append_float(float num, uint decimals) +{ + uint dummy_errors; + size_t len; + DBUG_ASSERT(!std::isnan(num)); + DBUG_ASSERT(!std::isinf(num)); + if (realloc_with_extra_if_needed(str_length + FLOATING_POINT_BUFFER)) + return true; + + if (charset()->mbminlen > 1) + { + char buff[FLOATING_POINT_BUFFER]; + len= write_float_str_to_buff(buff, sizeof(buff), num, decimals); + str_length+= copy_and_convert(Ptr + str_length, len, charset(), buff, len, + &my_charset_latin1, &dummy_errors); + } + else + str_length+= write_float_str_to_buff(Ptr + str_length, + FLOATING_POINT_BUFFER, num, decimals); + return false; +} + + bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs) { /* diff --git a/sql/sql_string.h b/sql/sql_string.h index e5d90d4f688..dfa0d8fb7ce 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -20,9 +20,13 @@ /* This file is originally from the mysql distribution. Coded by monty */ +#include +#include + #include "m_ctype.h" /* my_charset_bin */ #include /* alloc_root, my_free, my_realloc */ #include "m_string.h" /* TRASH */ +#include "sql_const.h" #include "sql_list.h" class String; @@ -1007,6 +1011,12 @@ public: { return Binary_string::append(s); } + + // Append a float value to the string keeping the string's charset. + // + // The float value must not be NaN or Inf, it will be represented as 0 in + // that case. + bool append_float(float num, uint decimals); inline bool append(char chr) { return Binary_string::append_char(chr); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 0924066e798..d4d9b520bfe 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -328,27 +328,9 @@ Type_handler_data *type_handler_data= NULL; bool Float::to_string(String *val_buffer, uint dec) const { - uint to_length= 70; - if (val_buffer->alloc(to_length)) - return true; - - char *to=(char*) val_buffer->ptr(); - size_t len; - - if (dec >= FLOATING_POINT_DECIMALS) - len= my_gcvt(m_value, MY_GCVT_ARG_FLOAT, to_length - 1, to, NULL); - else - { - /* - We are safe here because the buffer length is 70, and - fabs(float) < 10^39, dec < FLOATING_POINT_DECIMALS. So the resulting string - will be not longer than 69 chars + terminating '\0'. - */ - len= my_fcvt(m_value, (int) dec, to, NULL); - } - val_buffer->length((uint) len); val_buffer->set_charset(&my_charset_numeric); - return false; + val_buffer->length(0); + return val_buffer->append_float(m_value, dec); }