diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2009-12-22 19:23:13 +0300 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2009-12-22 19:23:13 +0300 |
commit | 12f364ece7663663cabdc29f106ca69af63fe4e7 (patch) | |
tree | 40437c602d2a9ddaa03a54742cec4884f0974253 /client/sql_string.cc | |
parent | d4f23f0cf6db38731a161c5c7b0b056fc67e5c02 (diff) | |
download | mariadb-git-12f364ece7663663cabdc29f106ca69af63fe4e7.tar.gz |
Backport of WL #2934: Make/find library for doing float/double
to string conversions and vice versa"
Initial import of the dtoa.c code and custom wrappers around it
to allow its usage from the server code.
Conversion of FLOAT/DOUBLE values to DECIMAL ones or strings
and vice versa has been significantly reworked. As the new
algoritms are more precise than the older ones, results of such
conversions may not always match those obtained from older
server versions. This in turn may break compatibility for some
applications.
This patch also fixes the following bugs:
- bug #12860 "Difference in zero padding of exponent between
Unix and Windows"
- bug #21497 "DOUBLE truncated to unusable value"
- bug #26788 "mysqld (debug) aborts when inserting specific
numbers into char fields"
- bug #24541 "Data truncated..." on decimal type columns
without any good reason"
Diffstat (limited to 'client/sql_string.cc')
-rw-r--r-- | client/sql_string.cc | 80 |
1 files changed, 7 insertions, 73 deletions
diff --git a/client/sql_string.cc b/client/sql_string.cc index 3292bc7e6f2..ccbc8977e7f 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -24,10 +24,6 @@ #include <m_string.h> #include <m_ctype.h> #include <mysql_com.h> -#ifdef HAVE_FCONVERT -#include <floatingpoint.h> -#endif - /* The following extern declarations are ok as these are interface functions required by the string function @@ -117,82 +113,19 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) bool String::set(double num,uint decimals, CHARSET_INFO *cs) { - char buff[331]; + char buff[FLOATING_POINT_BUFFER]; uint dummy_errors; + size_t len; str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME + len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL); return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } -#ifdef HAVE_FCONVERT - int decpt,sign; - char *pos,*to; - - (void) fconvert(num,(int) decimals,&decpt,&sign,buff+1); - if (!my_isdigit(&my_charset_latin1, buff[1])) - { // Nan or Inf - pos=buff+1; - if (sign) - { - buff[0]='-'; - pos=buff; - } - uint dummy_errors; - return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors); - } - if (alloc((uint32) ((uint32) decpt+3+decimals))) - return TRUE; - to=Ptr; - if (sign) - *to++='-'; - - pos=buff+1; - if (decpt < 0) - { /* value is < 0 */ - *to++='0'; - if (!decimals) - goto end; - *to++='.'; - if ((uint32) -decpt > decimals) - decpt= - (int) decimals; - decimals=(uint32) ((int) decimals+decpt); - while (decpt++ < 0) - *to++='0'; - } - else if (decpt == 0) - { - *to++= '0'; - if (!decimals) - goto end; - *to++='.'; - } - else - { - while (decpt-- > 0) - *to++= *pos++; - if (!decimals) - goto end; - *to++='.'; - } - while (decimals--) - *to++= *pos++; - -end: - *to=0; - str_length=(uint32) (to-Ptr); - return FALSE; -#else -#ifdef HAVE_SNPRINTF - buff[sizeof(buff)-1]=0; // Safety - snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num); -#else - sprintf(buff,"%.*f",(int) decimals,num); -#endif - return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs, + len= my_fcvt(num, decimals, buff, NULL); + return copy(buff, (uint32) len, &my_charset_latin1, cs, &dummy_errors); -#endif } @@ -675,7 +608,8 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.15g", d)); + str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff, + NULL); } void String::qs_append(double *d) |