List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:November 20 2009 10:10am
Subject:bzr commit into mysql-5.1-bugteam branch (joro:3199) Bug#45261 Bug#48370
View as plain text  
#At file:///home/kgeorge/mysql/work/B45261-5.1-bugteam/ based on revid:magne.mahre@stripped

 3199 Georgi Kodinov	2009-11-20
      Bug #45261 : Crash, stored procedure + decimal
      Bug #48370  Absolutely wrong calculations with GROUP BY and
        decimal fields when using IF
      
      Added the test cases in the above two bugs for regression
      testing.
      Added additional tests that demonstrate a incomplete fix.
      Added a new factory method for Field_new_decimal to 
      create a field from an (decimal returning) Item.
      In the new method made sure that all the precision and 
      length variables are capped in a proper way. 
      This is required because Item's can have larger precision
      than the decimal fields and thus need to be capped when
      creating a field based on an Item type.
      Fixed the wrong typecast to Item_decimal.

    modified:
      mysql-test/r/type_newdecimal.result
      mysql-test/t/type_newdecimal.test
      sql/field.cc
      sql/field.h
      sql/item.cc
      sql/item_func.cc
      sql/item_sum.cc
      sql/sql_select.cc
=== modified file 'mysql-test/r/type_newdecimal.result'
--- a/mysql-test/r/type_newdecimal.result	2009-11-02 11:21:39 +0000
+++ b/mysql-test/r/type_newdecimal.result	2009-11-20 10:10:47 +0000
@@ -1630,3 +1630,287 @@ SELECT my_col FROM t1;
 my_col
 0.012345687012345687012345687012
 DROP TABLE t1;
+#
+# Bug#45261: Crash, stored procedure + decimal
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,0)	NO		0	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,0)	NO		0	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,0)	NO		0	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
+AS c1;
+Warnings:
+Error	1292	Truncated incorrect DECIMAL value: ''
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,0)	NO		0	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999.999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
+AS c1;
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(31,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+AS c1;
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(31,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+AS c1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(30,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+0.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999.999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,1)	NO		0.0	
+SELECT * FROM t1;
+c1
+9999999999999999999999999999999999999999999999999999999999999999.9
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
+AS c1;
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,1)	NO		0.0	
+SELECT * FROM t1;
+c1
+9999999999999999999999999999999999999999999999999999999999999999.9
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
+AS c1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(30,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+0.123456789012345678901234567890
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 1
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(33,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+123.123456789012345678901234567890
+DROP TABLE t1;
+CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,30)	NO		0.000000000000000000000000000000	
+SELECT * FROM t1;
+c1
+2.100000000000000000000000000000
+DROP TABLE t1;
+#
+# Test that the integer and decimal parts are properly calculated.
+#
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 3
+DESC t2;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(32,30)	YES		NULL	
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 1
+Note	1265	Data truncated for column 'c1' at row 2
+Note	1265	Data truncated for column 'c1' at row 3
+DESC t2;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(34,0)	YES		NULL	
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
+Warnings:
+Note	1265	Data truncated for column 'c1' at row 1
+DESC t2;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,30)	YES		NULL	
+DROP TABLE t1,t2;
+#
+# Test that variables get maximum precision.
+#
+SET @decimal= 1.1;
+CREATE TABLE t1 SELECT @decimal AS c1;
+DESC t1;
+Field	Type	Null	Key	Default	Extra
+c1	decimal(65,30)	YES		NULL	
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
+#
+# Bug #45261 : Crash, stored procedure + decimal
+# Original test by the reporter.
+#
+# should not crash
+CREATE TABLE t1 
+SELECT .123456789012345678901234567890123456789012345678901234567890123456 AS a;
+Warnings:
+Note	1265	Data truncated for column 'a' at row 1
+DROP TABLE t1;
+CREATE PROCEDURE test_proc()
+BEGIN
+# The las non critical CUSER definition is:
+# DECLARE mycursor CURSOR FOR SELECT 1 % 
+# .12345678912345678912345678912345678912345678912345678912345678912 AS my_col;
+DECLARE mycursor CURSOR FOR 
+SELECT 1 % 
+.123456789123456789123456789123456789123456789123456789123456789123456789123456789 
+AS my_col;
+OPEN mycursor;
+CLOSE mycursor;
+END|
+# should not crash
+CALL test_proc();
+DROP PROCEDURE test_proc;
+#
+# Bug #48370  Absolutely wrong calculations with GROUP BY and 
+# decimal fields when using IF
+#
+CREATE TABLE currencies (id int, rate decimal(16,4), 
+PRIMARY KEY (id), KEY (rate));
+INSERT INTO currencies VALUES (11,0.7028);
+INSERT INTO currencies VALUES (1,1);
+CREATE TABLE payments (
+id int,
+supplier_id int,
+status int,
+currency_id int,
+vat decimal(7,4),
+PRIMARY KEY (id),
+KEY currency_id (currency_id),
+KEY supplier_id (supplier_id)
+);
+INSERT INTO payments (id,status,vat,supplier_id,currency_id) VALUES
+(3001,2,0.0000,344,11), (1,2,0.0000,1,1);
+CREATE TABLE sub_tasks (
+id int,
+currency_id int,
+price decimal(16,4),
+discount decimal(10,4),
+payment_id int,
+PRIMARY KEY (id),
+KEY currency_id (currency_id),
+KEY payment_id (payment_id)
+) ;
+INSERT INTO sub_tasks (id, price, discount, payment_id, currency_id) VALUES
+(52, 12.60, 0, 3001, 11), (56, 14.58, 0, 3001, 11);
+# should return 1 and the same values in col 2 and 3
+select STRAIGHT_JOIN
+(1 + PAY.vat) AS mult,
+SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 2)) * 
+CUR.rate / CUR.rate, 2)
+) v_net_with_discount,
+SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 1)) *
+CUR.rate / CUR.rate , 2) 
+* (1 + PAY.vat)
+) v_total
+from
+currencies CUR, payments PAY, sub_tasks SUB
+where
+SUB.payment_id = PAY.id and
+PAY.currency_id = CUR.id and
+PAY.id > 2
+group by PAY.id + 1;
+mult	v_net_with_discount	v_total
+1.0000	27.18	27.180000
+DROP TABLE currencies, payments, sub_tasks;
+End of 5.1 tests

=== modified file 'mysql-test/t/type_newdecimal.test'
--- a/mysql-test/t/type_newdecimal.test	2009-11-02 11:21:39 +0000
+++ b/mysql-test/t/type_newdecimal.test	2009-11-20 10:10:47 +0000
@@ -1286,3 +1286,229 @@ CREATE TABLE t1 SELECT 1 % .123456789123
 DESCRIBE t1;
 SELECT my_col FROM t1;
 DROP TABLE t1;
+
+--echo #
+--echo # Bug#45261: Crash, stored procedure + decimal
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 SELECT
+  /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+  .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
+  AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Test that the integer and decimal parts are properly calculated.
+--echo #
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+--echo #
+--echo # Test that variables get maximum precision.
+--echo #
+
+SET @decimal= 1.1;
+CREATE TABLE t1 SELECT @decimal AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug #45261 : Crash, stored procedure + decimal
+--echo # Original test by the reporter.
+--echo #
+
+--echo # should not crash
+CREATE TABLE t1 
+SELECT .123456789012345678901234567890123456789012345678901234567890123456 AS a;
+DROP TABLE t1;
+
+delimiter |;
+CREATE PROCEDURE test_proc()
+BEGIN
+  # The las non critical CUSER definition is:
+  # DECLARE mycursor CURSOR FOR SELECT 1 % 
+  # .12345678912345678912345678912345678912345678912345678912345678912 AS my_col;
+  DECLARE mycursor CURSOR FOR 
+SELECT 1 % 
+.123456789123456789123456789123456789123456789123456789123456789123456789123456789 
+  AS my_col;
+
+  OPEN mycursor;
+  CLOSE mycursor;
+END|
+delimiter ;|
+--echo # should not crash
+CALL test_proc();
+DROP PROCEDURE test_proc;
+
+--echo #
+--echo # Bug #48370  Absolutely wrong calculations with GROUP BY and 
+--echo # decimal fields when using IF
+--echo #
+
+CREATE TABLE currencies (id int, rate decimal(16,4), 
+  PRIMARY KEY (id), KEY (rate));
+
+INSERT INTO currencies VALUES (11,0.7028);
+INSERT INTO currencies VALUES (1,1);
+
+CREATE TABLE payments (
+  id int,
+  supplier_id int,
+  status int,
+  currency_id int,
+  vat decimal(7,4),
+  PRIMARY KEY (id),
+  KEY currency_id (currency_id),
+  KEY supplier_id (supplier_id)
+);
+
+INSERT INTO payments (id,status,vat,supplier_id,currency_id) VALUES
+(3001,2,0.0000,344,11), (1,2,0.0000,1,1);
+
+CREATE TABLE sub_tasks (
+  id int,
+  currency_id int,
+  price decimal(16,4),
+  discount decimal(10,4),
+  payment_id int,
+  PRIMARY KEY (id),
+  KEY currency_id (currency_id),
+  KEY payment_id (payment_id)
+) ;
+
+INSERT INTO sub_tasks (id, price, discount, payment_id, currency_id) VALUES
+(52, 12.60, 0, 3001, 11), (56, 14.58, 0, 3001, 11);
+
+--echo # should return 1 and the same values in col 2 and 3
+select STRAIGHT_JOIN
+  (1 + PAY.vat) AS mult,
+  SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 2)) * 
+            CUR.rate / CUR.rate, 2)
+  ) v_net_with_discount,
+
+  SUM(ROUND((SUB.price - ROUND(ROUND(SUB.price, 2) * SUB.discount, 1)) *
+            CUR.rate / CUR.rate , 2) 
+      * (1 + PAY.vat)
+  ) v_total
+from
+   currencies CUR, payments PAY, sub_tasks SUB
+where
+  SUB.payment_id = PAY.id and
+  PAY.currency_id = CUR.id and
+  PAY.id > 2
+group by PAY.id + 1;
+
+DROP TABLE currencies, payments, sub_tasks;
+
+
+--echo End of 5.1 tests

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2009-11-02 11:21:39 +0000
+++ b/sql/field.cc	2009-11-20 10:10:47 +0000
@@ -2486,6 +2486,50 @@ Field_new_decimal::Field_new_decimal(uin
 }
 
 
+Field *Field_new_decimal::create_from_item (Item *item)
+{
+  uint8 dec= item->decimals;
+  uint8 intg= item->decimal_precision() - dec;
+  uint32 len= item->max_length;
+
+  DBUG_ASSERT (item->result_type() == DECIMAL_RESULT);
+
+  /*
+    Trying to put too many digits overall in a DECIMAL(prec,dec)
+    will always throw a warning. We must limit dec to
+    DECIMAL_MAX_SCALE however to prevent an assert() later.
+  */
+
+  if (dec > 0)
+  {
+    signed int overflow;
+
+    dec= min(dec, DECIMAL_MAX_SCALE);
+
+    /*
+      If the value still overflows the field with the corrected dec,
+      we'll throw out decimals rather than integers. This is still
+      bad and of course throws a truncation warning.
+      +1: for decimal point
+      */
+
+    const int required_length=
+      my_decimal_precision_to_length(intg + dec, dec,
+                                     item->unsigned_flag);
+
+    overflow= required_length - len;
+
+    if (overflow > 0)
+      dec= max(0, dec - overflow);            // too long, discard fract
+    else
+      /* Corrected value fits. */
+      len= required_length;
+  }
+  return new Field_new_decimal(len, item->maybe_null, item->name,
+                               dec, item->unsigned_flag);
+}
+
+
 int Field_new_decimal::reset(void)
 {
   store_value(&decimal_zero);

=== modified file 'sql/field.h'
--- a/sql/field.h	2009-11-02 11:21:39 +0000
+++ b/sql/field.h	2009-11-20 10:10:47 +0000
@@ -807,6 +807,7 @@ public:
   uint is_equal(Create_field *new_field);
   virtual const uchar *unpack(uchar* to, const uchar *from,
                               uint param_data, bool low_byte_first);
+  static Field *create_from_item (Item *);
 };
 
 

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2009-11-06 19:42:24 +0000
+++ b/sql/item.cc	2009-11-20 10:10:47 +0000
@@ -4899,9 +4899,7 @@ Field *Item::tmp_table_field_from_field_
   switch (field_type()) {
   case MYSQL_TYPE_DECIMAL:
   case MYSQL_TYPE_NEWDECIMAL:
-    field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0,
-                                 Field::NONE, name, decimals, 0,
-                                 unsigned_flag);
+    field= Field_new_decimal::create_from_item(this);
     break;
   case MYSQL_TYPE_TINY:
     field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2009-11-02 11:21:39 +0000
+++ b/sql/item_func.cc	2009-11-20 10:10:47 +0000
@@ -451,45 +451,8 @@ Field *Item_func::tmp_table_field(TABLE 
     return make_string_field(table);
     break;
   case DECIMAL_RESULT:
-  {
-    uint8 dec= decimals;
-    uint8 intg= decimal_precision() - dec;
-    uint32 len= max_length;
-
-    /*
-      Trying to put too many digits overall in a DECIMAL(prec,dec)
-      will always throw a warning. We must limit dec to
-      DECIMAL_MAX_SCALE however to prevent an assert() later.
-    */
-
-    if (dec > 0)
-    {
-      int overflow;
-
-      dec= min(dec, DECIMAL_MAX_SCALE);
-
-      /*
-        If the value still overflows the field with the corrected dec,
-        we'll throw out decimals rather than integers. This is still
-        bad and of course throws a truncation warning.
-      */
-
-      const int required_length=
-        my_decimal_precision_to_length(intg + dec, dec,
-                                                     unsigned_flag);
-
-      overflow= required_length - len;
-
-      if (overflow > 0)
-        dec= max(0, dec - overflow);            // too long, discard fract
-      else
-        /* Corrected value fits. */
-        len= required_length;
-    }
-
-    field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag);
+    field= Field_new_decimal::create_from_item(this);
     break;
-  }
   case ROW_RESULT:
   default:
     // This case should never be chosen

=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc	2009-11-02 11:21:39 +0000
+++ b/sql/item_sum.cc	2009-11-20 10:10:47 +0000
@@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool g
                                name, table->s, collation.collation);
     break;
   case DECIMAL_RESULT:
-    field= new Field_new_decimal(max_length, maybe_null, name,
-                                 decimals, unsigned_flag);
+    field= Field_new_decimal::create_from_item(this);
     break;
   case ROW_RESULT:
   default:
@@ -1270,8 +1269,7 @@ Field *Item_sum_avg::create_tmp_field(bo
                             0, name, &my_charset_bin);
   }
   else if (hybrid_type == DECIMAL_RESULT)
-    field= new Field_new_decimal(max_length, maybe_null, name,
-                                 decimals, unsigned_flag);
+    field= Field_new_decimal::create_from_item(this);
   else
     field= new Field_double(max_length, maybe_null, name, decimals, TRUE);
   if (field)

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2009-11-10 10:59:02 +0000
+++ b/sql/sql_select.cc	2009-11-20 10:10:47 +0000
@@ -9470,47 +9470,8 @@ static Field *create_tmp_field_from_item
     new_field->set_derivation(item->collation.derivation);
     break;
   case DECIMAL_RESULT:
-  {
-    uint8 dec= item->decimals;
-    uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec;
-    uint32 len= item->max_length;
-
-    /*
-      Trying to put too many digits overall in a DECIMAL(prec,dec)
-      will always throw a warning. We must limit dec to
-      DECIMAL_MAX_SCALE however to prevent an assert() later.
-    */
-
-    if (dec > 0)
-    {
-      signed int overflow;
-
-      dec= min(dec, DECIMAL_MAX_SCALE);
-
-      /*
-        If the value still overflows the field with the corrected dec,
-        we'll throw out decimals rather than integers. This is still
-        bad and of course throws a truncation warning.
-        +1: for decimal point
-      */
-
-      const int required_length=
-        my_decimal_precision_to_length(intg + dec, dec,
-                                                     item->unsigned_flag);
-
-      overflow= required_length - len;
-
-      if (overflow > 0)
-        dec= max(0, dec - overflow);            // too long, discard fract
-      else
-        /* Corrected value fits. */
-        len= required_length;
-    }
-
-    new_field= new Field_new_decimal(len, maybe_null, item->name,
-                                     dec, item->unsigned_flag);
+    new_field= Field_new_decimal::create_from_item(item);
     break;
-  }
   case ROW_RESULT:
   default:
     // This case should never be choosen


Attachment: [text/bzr-bundle] bzr/joro@sun.com-20091120101047-r1bd55p2p65gz8zv.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (joro:3199) Bug#45261 Bug#48370Georgi Kodinov20 Nov