diff options
author | unknown <vva@eagle.mysql.r18.ru> | 2004-03-06 03:02:12 +0400 |
---|---|---|
committer | unknown <vva@eagle.mysql.r18.ru> | 2004-03-06 03:02:12 +0400 |
commit | 1c15d4dfdc6ed318851c685a10ec09bf18902a97 (patch) | |
tree | e787c609ddbf5fdd5433a8937d3a443697318feb /sql | |
parent | 755f693965b33b8101557ee4a5088adb45a02e56 (diff) | |
parent | f9a59e45ad4fbe39d366f04385b5ef836be36ed4 (diff) | |
download | mariadb-git-1c15d4dfdc6ed318851c685a10ec09bf18902a97.tar.gz |
Merge vvagin@bk-internal.mysql.com:/home/bk/mysql-4.1
into eagle.mysql.r18.ru:/home/vva/work/BUG_2082/mysql-4.1
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 120 |
1 files changed, 84 insertions, 36 deletions
diff --git a/sql/field.cc b/sql/field.cc index 48e7dbb32ca..93827a8cd1f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2271,13 +2271,18 @@ void Field_longlong::sql_type(String &res) const int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) { int err; - Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL,&err)); - if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) + char *end; + double nr= my_strntod(cs,(char*) from,len,&end,&err); + if (!err && (!current_thd->count_cuted_fields || end-from==len)) + { + return Field_float::store(nr); + } + else { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + Field_float::store(nr); return 1; } - return (err) ? 1 : 0; } @@ -2285,28 +2290,48 @@ int Field_float::store(double nr) { float j; int error= 0; - if (dec < NOT_FIXED_DEC) - nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point - if (unsigned_flag && nr < 0) + + if (isnan(nr)) { + j= 0; + set_null(); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - nr=0; error= 1; } - if (nr < -FLT_MAX) + else if (unsigned_flag && nr < 0) { - j= -FLT_MAX; + j= 0; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); error= 1; } - else if (nr > FLT_MAX) + else { - j=FLT_MAX; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - error= 1; + double max_value; + if (dec >= NOT_FIXED_DEC) + { + max_value= FLT_MAX; + } + else + { + max_value= (log_10[field_length]-1)/log_10[dec]; + 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); + error= 1; + } + else if (nr > max_value) + { + j= (float)max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); + error= 1; + } + else + j= (float) nr; } - else - j= (float) nr; + #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -2544,41 +2569,64 @@ void Field_float::sql_type(String &res) const int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) { int err; - double j= my_strntod(cs,(char*) from,len,(char**)0,&err); - if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) - { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - err= 1; - } - if (unsigned_flag && j < 0) + char *end; + double nr= my_strntod(cs,(char*) from,len,&end,&err); + if (!err && (!current_thd->count_cuted_fields || end-from==len)) { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - j=0; - err= 1; + return Field_double::store(nr); } -#ifdef WORDS_BIGENDIAN - if (table->db_low_byte_first) + else { - float8store(ptr,j); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + Field_double::store(nr); + return 1; } - else -#endif - doublestore(ptr,j); - return err; } int Field_double::store(double nr) { int error= 0; - if (dec < NOT_FIXED_DEC) - nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point - if (unsigned_flag && nr < 0) + + if (isnan(nr)) { + nr= 0; + set_null(); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); + error= 1; + } + else if (unsigned_flag && nr < 0) + { + nr= 0; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - nr=0; error= 1; } + else + { + double max_value; + if (dec >= NOT_FIXED_DEC) + { + max_value= DBL_MAX; + } + else + { + max_value= (log_10[field_length]-1)/log_10[dec]; + 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); + error= 1; + } + else if (nr > max_value) + { + nr= max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); + error= 1; + } + } + #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { |