diff options
author | unknown <kaa@polly.local> | 2007-05-28 12:52:05 +0400 |
---|---|---|
committer | unknown <kaa@polly.local> | 2007-05-28 12:52:05 +0400 |
commit | 5beaf49378a7676d02cddbc0609dd71877387857 (patch) | |
tree | 4fea6fd04847e73e6e9f52860ac3c3f54de6f0c2 /sql/field.cc | |
parent | 937f7256c70e19cb9761135f597ba87482b37ffe (diff) | |
parent | f506f5cade2e403f185f545fb84a802e4570a4ab (diff) | |
download | mariadb-git-5beaf49378a7676d02cddbc0609dd71877387857.tar.gz |
Merge polly.local:/home/kaa/src/maint/bug28121/my50-bug28121
into polly.local:/home/kaa/src/maint/bug28121/my51-bug28121
include/m_string.h:
Auto merged
mysql-test/r/type_float.result:
Auto merged
mysql-test/t/type_float.test:
Auto merged
sql/init.cc:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/field.cc:
Manual merge.
sql/field.h:
Manual merge.
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 151 |
1 files changed, 60 insertions, 91 deletions
diff --git a/sql/field.cc b/sql/field.cc index e8718c9e407..159c275c59d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3769,56 +3769,9 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) int Field_float::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; - float j; - int error= 0; + int error= truncate(&nr, FLT_MAX); + float j= nr; - if (isnan(nr)) - { - j= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - j= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (dec >= NOT_FIXED_DEC) - { - max_value= FLT_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - /* - The following comparison is needed to not get an overflow if nr - is close to FLT_MAX - */ - if (fabs(nr) < FLT_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - j= (float)-max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - j= (float)max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - j= (float) nr; - } - #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -4062,48 +4015,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) int Field_double::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; - int error= 0; - - if (isnan(nr)) - { - nr= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - nr= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (not_fixed) - { - max_value= DBL_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - if (fabs(nr) < DBL_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - nr= -max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - nr= max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - } + int error= truncate(&nr, DBL_MAX); #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) @@ -4123,6 +4035,63 @@ int Field_double::store(longlong nr, bool unsigned_val) (double) nr); } +/* + If a field has fixed length, truncate the double argument pointed to by 'nr' + appropriately. + Also ensure that the argument is within [-max_value; max_value] range. +*/ + +int Field_real::truncate(double *nr, double max_value) +{ + int error= 1; + double res= *nr; + + if (isnan(res)) + { + res= 0; + set_null(); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + else if (unsigned_flag && res < 0) + { + res= 0; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + + if (!not_fixed) + { + uint order= field_length - dec; + uint step= array_elements(log_10) - 1; + max_value= 1.0; + for (; order > step; order-= step) + max_value*= log_10[step]; + max_value*= log_10[order]; + max_value-= 1.0 / log_10[dec]; + + double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec]; + res= floor(res) + tmp; + } + + if (res < -max_value) + { + res= -max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else if (res > max_value) + { + res= max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else + error= 0; + +end: + *nr= res; + return error; +} + int Field_real::store_decimal(const my_decimal *dm) { |