diff options
author | Georgi Kodinov <joro@sun.com> | 2009-11-20 12:10:47 +0200 |
---|---|---|
committer | Georgi Kodinov <joro@sun.com> | 2009-11-20 12:10:47 +0200 |
commit | c2c334918f31e64bfc1ed253cd70744a0a350cc8 (patch) | |
tree | 6dd67d2e2233b91b60411032a36b63de5922949d | |
parent | 3f6825653e789ca66adebeb01642457a7447fc73 (diff) | |
download | mariadb-git-c2c334918f31e64bfc1ed253cd70744a0a350cc8.tar.gz |
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.
-rw-r--r-- | mysql-test/r/type_newdecimal.result | 284 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal.test | 226 | ||||
-rw-r--r-- | sql/field.cc | 44 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 39 | ||||
-rw-r--r-- | sql/item_sum.cc | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 41 |
8 files changed, 560 insertions, 85 deletions
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 748aadee4fb..70ee3a56cf3 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -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 diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index cd3c3f81510..2cf7ab8fbdf 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1286,3 +1286,229 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567 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 diff --git a/sql/field.cc b/sql/field.cc index 354c911e1c0..01ccc338782 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2486,6 +2486,50 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, } +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); diff --git a/sql/field.h b/sql/field.h index 784b9133790..ae074cc1a30 100644 --- a/sql/field.h +++ b/sql/field.h @@ -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 *); }; diff --git a/sql/item.cc b/sql/item.cc index e1dbc1ba21a..ab70996e541 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4899,9 +4899,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) 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, diff --git a/sql/item_func.cc b/sql/item_func.cc index ac52f36474a..977a0de39af 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -451,45 +451,8 @@ Field *Item_func::tmp_table_field(TABLE *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 diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 38251294053..7bbe167e7ac 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, 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(bool group, TABLE *table, 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) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 18fc3b20748..569d8183ab6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9466,47 +9466,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, 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 |