Below is the list of changes that have just been committed into a local
4.1 repository of greenman. When greenman does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-03-07 09:25:09-08:00, igreenhoe@stripped +4 -0
Fix for bug #24912: problems with bigint in abs() ceiling() ruond() truncate() mod()
Changed code to look for unsigned_flag in appropriate places.
mysql-test/r/func_math.result@stripped, 2007-03-07 09:25:08-08:00,
igreenhoe@stripped +39 -0
Additional test results to check for incorrect behavior near and around 2^64.
mysql-test/t/func_math.test@stripped, 2007-03-07 09:25:08-08:00,
igreenhoe@stripped +16 -0
Additional tests to check for incorrect behavior near and around 2^64.
sql/item_func.cc@stripped, 2007-03-07 09:25:08-08:00, igreenhoe@stripped +92
-30
Conversion of code to check for unsigned_flag and behave appropriately.
sql/item_func.h@stripped, 2007-03-07 09:25:08-08:00, igreenhoe@stripped +8
-2
Conversion of code to check for unsigned_flag and behave appropriately.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: igreenhoe
# Host: ra.greendragongames.com
# Root: /home/greenman/workspace/mysql/bug-24912/my41-bug-24912
--- 1.272/sql/item_func.cc 2007-03-07 09:25:13 -08:00
+++ 1.273/sql/item_func.cc 2007-03-07 09:25:13 -08:00
@@ -698,11 +698,23 @@ double Item_func_mod::val()
longlong Item_func_mod::val_int()
{
DBUG_ASSERT(fixed == 1);
- longlong value= args[0]->val_int();
- longlong val2= args[1]->val_int();
- if ((null_value=val2 == 0 || args[0]->null_value || args[1]->null_value))
+ longlong value= args[0]->val_int();
+ longlong val2= args[1]->val_int();
+ if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
return 0; /* purecov: inspected */
- return value % val2;
+
+ if (args[0]->unsigned_flag)
+ {
+ if (args[1]->unsigned_flag)
+ return (longlong) (((ulonglong) value) % (ulonglong) val2);
+
+ return (longlong) (((ulonglong) value) % val2);
+ }
+
+ if (args[1]->unsigned_flag)
+ return (longlong) (value % (ulonglong) val2);
+
+ return (longlong) (value % val2);
}
void Item_func_mod::fix_length_and_dec()
@@ -784,17 +796,22 @@ double Item_func_abs::val()
longlong Item_func_abs::val_int()
{
DBUG_ASSERT(fixed == 1);
- longlong value=args[0]->val_int();
- null_value=args[0]->null_value;
- return value >= 0 ? value : -value;
+ longlong value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ unsigned_flag= args[0]->unsigned_flag;
+
+ if ((value >= 0) || (args[0]->unsigned_flag))
+ return value;
+ return -value;
}
void Item_func_abs::fix_length_and_dec()
{
- decimals=args[0]->decimals;
- max_length=args[0]->max_length;
+ decimals= args[0]->decimals;
+ max_length= args[0]->max_length;
hybrid_type= REAL_RESULT;
+
if (args[0]->result_type() == INT_RESULT)
hybrid_type= INT_RESULT;
}
@@ -997,34 +1014,71 @@ void Item_func_integer::fix_length_and_d
decimals=0;
}
+
longlong Item_func_ceiling::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- null_value=args[0]->null_value;
- return (longlong) ceil(value);
+ longlong result;
+
+ if (args[0]->result_type() == INT_RESULT)
+ {
+ result= args[0]->val_int();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ else
+ {
+ double value= ceil(args[0]->val());
+ unsigned_flag= value > LONGLONG_MAX;
+
+ if (unsigned_flag)
+ result= (longlong) ((ulonglong) value);
+ else
+ result= (longlong) value;
+ }
+
+ null_value= args[0]->null_value;
+ return result;
}
longlong Item_func_floor::val_int()
{
DBUG_ASSERT(fixed == 1);
- // the volatile's for BUG #3051 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
- null_value=args[0]->null_value;
- return (longlong) floor(value);
+ longlong result;
+
+ if (args[0]->result_type() == INT_RESULT)
+ {
+ result= args[0]->val_int();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ else
+ {
+ // the volatile's for BUG #3051 to calm optimizer down (because of gcc's bug)
+ volatile double value= floor(args[0]->val());
+ unsigned_flag= value > LONGLONG_MAX;
+
+ if (unsigned_flag)
+ result= (longlong) ((ulonglong) value);
+ else
+ result= (longlong) value;
+ }
+
+ null_value= args[0]->null_value;
+ return result;
}
void Item_func_round::fix_length_and_dec()
{
- max_length=args[0]->max_length;
- decimals=args[0]->decimals;
+ max_length= args[0]->max_length;
+ decimals= args[0]->decimals;
+
if (args[1]->const_item())
{
- int tmp=(int) args[1]->val_int();
- if (tmp < 0)
- decimals=0;
+ longlong tmp= args[1]->val_int();
+ if ((tmp < 0) && (!args[1]->unsigned_flag))
+ decimals= 0;
else
- decimals=min(tmp,NOT_FIXED_DEC);
+ decimals= min(tmp, NOT_FIXED_DEC);
+
if ((tmp= decimals - args[0]->decimals) > 0)
max_length+= tmp;
}
@@ -1033,9 +1087,10 @@ void Item_func_round::fix_length_and_dec
double Item_func_round::val()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- int dec=(int) args[1]->val_int();
- uint abs_dec=abs(dec);
+ double value= args[0]->val();
+ longlong dec= args[1]->val_int();
+ int arg1_signed= (dec < 0) && !args[1]->unsigned_flag;
+ ulonglong abs_dec= (ulonglong) (arg1_signed ? -dec : dec);
double tmp;
/*
tmp2 is here to avoid return the value with 80 bit precision
@@ -1043,20 +1098,27 @@ double Item_func_round::val()
*/
volatile double tmp2;
- if ((null_value=args[0]->null_value || args[1]->null_value))
+ if ((null_value= args[0]->null_value || args[1]->null_value))
return 0.0;
+
tmp=(abs_dec < array_elements(log_10) ?
log_10[abs_dec] : pow(10.0,(double) abs_dec));
- if (truncate)
+ if (0.0 == 1.0 / tmp)
+ {
+ /* This will only happen if tmp is infinite. */
+ tmp2= value;
+ }
+ else if (truncate)
{
if (value >= 0)
- tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
+ tmp2= arg1_signed ? floor(value / tmp) * tmp : floor(value * tmp) / tmp;
else
- tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
+ tmp2= arg1_signed ? ceil(value / tmp) * tmp : ceil(value * tmp) / tmp;
}
else
- tmp2=dec < 0 ? rint(value/tmp)*tmp : rint(value*tmp)/tmp;
+ tmp2= arg1_signed ? rint(value / tmp) * tmp : rint(value * tmp) / tmp;
+
return tmp2;
}
--- 1.134/sql/item_func.h 2007-03-07 09:25:13 -08:00
+++ 1.135/sql/item_func.h 2007-03-07 09:25:13 -08:00
@@ -234,7 +234,7 @@ public:
const char *func_name() const { return "cast_as_signed"; }
double val()
{
- double tmp= args[0]->val();
+ double tmp= val_int();
null_value= args[0]->null_value;
return tmp;
}
@@ -251,8 +251,14 @@ class Item_func_unsigned :public Item_fu
public:
Item_func_unsigned(Item *a) :Item_func_signed(a) {}
const char *func_name() const { return "cast_as_unsigned"; }
+ double val()
+ {
+ double tmp= (ulonglong) val_int();
+ null_value= args[0]->null_value;
+ return tmp;
+ }
void fix_length_and_dec()
- { max_length=args[0]->max_length; unsigned_flag=1; }
+ { max_length= args[0]->max_length; unsigned_flag= 1; }
longlong val_int();
void print(String *str);
};
--- 1.25/mysql-test/r/func_math.result 2007-03-07 09:25:13 -08:00
+++ 1.26/mysql-test/r/func_math.result 2007-03-07 09:25:13 -08:00
@@ -151,3 +151,42 @@ select a from t1 where a='http://www.foo
a
http://www.foo.com/
drop table t1;
+select cast(-2 as unsigned), 18446744073709551614, -2;
+cast(-2 as unsigned) 18446744073709551614 -2
+18446744073709551614 18446744073709551614 -2
+select abs(cast(-2 as unsigned)), abs(18446744073709551614), abs(-2);
+abs(cast(-2 as unsigned)) abs(18446744073709551614) abs(-2)
+18446744073709551614 18446744073709551614 2
+select ceiling(cast(-2 as unsigned)), ceiling(18446744073709551614), ceiling(-2);
+ceiling(cast(-2 as unsigned)) ceiling(18446744073709551614) ceiling(-2)
+18446744073709551614 18446744073709551614 -2
+select floor(cast(-2 as unsigned)), floor(18446744073709551614), floor(-2);
+floor(cast(-2 as unsigned)) floor(18446744073709551614) floor(-2)
+18446744073709551614 18446744073709551614 -2
+select format(cast(-2 as unsigned), 2), format(18446744073709551614, 2), format(-2, 2);
+format(cast(-2 as unsigned), 2) format(18446744073709551614, 2) format(-2, 2)
+18,446,744,073,709,551,616.00 18,446,744,073,709,551,616.00 -2.00
+select sqrt(cast(-2 as unsigned)), sqrt(18446744073709551614), sqrt(-2);
+sqrt(cast(-2 as unsigned)) sqrt(18446744073709551614) sqrt(-2)
+4294967296 4294967296 NULL
+select round(cast(-2 as unsigned), 1), round(18446744073709551614, 1), round(-2, 1);
+round(cast(-2 as unsigned), 1) round(18446744073709551614, 1) round(-2, 1)
+18446744073709551616.0 18446744073709551616.0 -2.0
+select round(4, cast(-2 as unsigned)), round(4, 18446744073709551614), round(4, -2);
+round(4, cast(-2 as unsigned)) round(4, 18446744073709551614) round(4, -2)
+4 4 0
+select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3);
+mod(cast(-2 as unsigned), 3) mod(18446744073709551614, 3) mod(-2, 3)
+2 2 -2
+select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2);
+mod(5, cast(-2 as unsigned)) mod(5, 18446744073709551614) mod(5, -2)
+5 5 1
+select truncate(cast(-2 as unsigned), 1), truncate(18446744073709551614, 1), truncate(-2,
1);
+truncate(cast(-2 as unsigned), 1) truncate(18446744073709551614, 1) truncate(-2, 1)
+18446744073709551616.0 18446744073709551616.0 -2.0
+select truncate(4, cast(-2 as unsigned)), truncate(4, 18446744073709551614), truncate(4,
-2);
+truncate(4, cast(-2 as unsigned)) truncate(4, 18446744073709551614) truncate(4, -2)
+4 4 0
+select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5);
+pow(cast(-2 as unsigned), 5) pow(18446744073709551614, 5) pow(-2, 5)
+2.1359870359209e+96 2.1359870359209e+96 -32
--- 1.19/mysql-test/t/func_math.test 2007-03-07 09:25:13 -08:00
+++ 1.20/mysql-test/t/func_math.test 2007-03-07 09:25:13 -08:00
@@ -98,4 +98,20 @@ insert into t1 values ('http://www.foo.c
select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0));
drop table t1;
+# Bug 24912 -- misc functions have trouble with unsigned
+
+select cast(-2 as unsigned), 18446744073709551614, -2;
+select abs(cast(-2 as unsigned)), abs(18446744073709551614), abs(-2);
+select ceiling(cast(-2 as unsigned)), ceiling(18446744073709551614), ceiling(-2);
+select floor(cast(-2 as unsigned)), floor(18446744073709551614), floor(-2);
+select format(cast(-2 as unsigned), 2), format(18446744073709551614, 2), format(-2, 2);
+select sqrt(cast(-2 as unsigned)), sqrt(18446744073709551614), sqrt(-2);
+select round(cast(-2 as unsigned), 1), round(18446744073709551614, 1), round(-2, 1);
+select round(4, cast(-2 as unsigned)), round(4, 18446744073709551614), round(4, -2);
+select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3);
+select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2);
+select truncate(cast(-2 as unsigned), 1), truncate(18446744073709551614, 1), truncate(-2,
1);
+select truncate(4, cast(-2 as unsigned)), truncate(4, 18446744073709551614), truncate(4,
-2);
+select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5);
+
# End of 4.1 tests
| Thread |
|---|
| • bk commit into 4.1 tree (igreenhoe:1.2626) BUG#24912 | igreenhoe | 7 Mar |