diff options
author | Alexander Nozdrin <alik@sun.com> | 2009-11-06 17:20:27 +0300 |
---|---|---|
committer | Alexander Nozdrin <alik@sun.com> | 2009-11-06 17:20:27 +0300 |
commit | 7cd11f45beeb162db84dea423a040a296ac2856e (patch) | |
tree | 3fcae3d99a56ba99d825ae4457901d49e4b474e3 /sql/item_func.cc | |
parent | 5462a6dbcc68d51a89356255fb4f398be7d62c27 (diff) | |
parent | 3e2c9aac11a95d8cbb61e1937e4ebe18c7e86698 (diff) | |
download | mariadb-git-7cd11f45beeb162db84dea423a040a296ac2856e.tar.gz |
Manual merge from mysql-trunk-merge.
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 f4db3ef03e7..23af528c256 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); |