diff options
author | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-11-02 09:21:39 -0200 |
---|---|---|
committer | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-11-02 09:21:39 -0200 |
commit | 1ca80ed19e14d8d5837fa900ad75ec1a7a7856e1 (patch) | |
tree | bb35488e2d55c68d42dd179686f0b5b6949f7055 /sql/item_func.cc | |
parent | cd167ee2e9dd4b2e51b0df426542f71c4daa4a02 (diff) | |
download | mariadb-git-1ca80ed19e14d8d5837fa900ad75ec1a7a7856e1.tar.gz |
Bug#48370: Absolutely wrong calculations with GROUP BY and decimal fields when using IF
Bug#45261: Crash, stored procedure + decimal
Revert fix for Bug#45261 due to unforeseen bugs.
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r-- | sql/item_func.cc | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index d9e6f76dd6b..ac52f36474a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -451,8 +451,45 @@ Field *Item_func::tmp_table_field(TABLE *table) return make_string_field(table); break; case DECIMAL_RESULT: - field= Field_new_decimal::new_decimal_field(this); + { + 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); break; + } case ROW_RESULT: default: // This case should never be chosen @@ -4739,19 +4776,6 @@ void Item_func_get_user_var::fix_length_and_dec() } -uint Item_func_get_user_var::decimal_precision() const -{ - uint precision= max_length; - Item_result restype= result_type(); - - /* Default to maximum as the precision is unknown a priori. */ - if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - precision= DECIMAL_MAX_PRECISION; - - return precision; -} - - bool Item_func_get_user_var::const_item() const { return (!var_entry || current_thd->query_id != var_entry->update_query_id); |