summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <vva@eagle.mysql.r18.ru>2004-03-06 03:02:12 +0400
committerunknown <vva@eagle.mysql.r18.ru>2004-03-06 03:02:12 +0400
commit1c15d4dfdc6ed318851c685a10ec09bf18902a97 (patch)
treee787c609ddbf5fdd5433a8937d3a443697318feb /sql
parent755f693965b33b8101557ee4a5088adb45a02e56 (diff)
parentf9a59e45ad4fbe39d366f04385b5ef836be36ed4 (diff)
downloadmariadb-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.cc120
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)
{