diff options
author | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-08-24 16:47:08 -0300 |
---|---|---|
committer | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-08-24 16:47:08 -0300 |
commit | fc3945950452a12ea7e47c685a73d5d22d338ec2 (patch) | |
tree | fe8fbd0e53c223e8a3b365787c5f910f8fe7695d /sql/field.h | |
parent | e31a41d10be057fd5b2928b8e03a78e734d39b2a (diff) | |
download | mariadb-git-fc3945950452a12ea7e47c685a73d5d22d338ec2.tar.gz |
Bug#45261: Crash, stored procedure + decimal
The problem was that creating a DECIMAL column from a decimal
value could lead to a failed assertion as decimal values can
have a higher precision than those attached to a table. The
assert could be triggered by creating a table from a decimal
with a large (> 30) scale. Also, there was a problem in
calculating the number of digits in the integral and fractional
parts if both exceeded the maximum number of digits permitted
by the new decimal type.
The solution is to ensure that truncation procedure is executed
when deducing a DECIMAL column from a decimal value of higher
precision. If the integer part is equal to or bigger than the
maximum precision for the DECIMAL type (65), the integer part
is truncated to fit and the fractional becomes zero. Otherwise,
the fractional part is truncated to fit into the space left
after the integer part is copied.
This patch borrows code and ideas from Martin Hansson's patch.
mysql-test/r/type_newdecimal.result:
Add test case result for Bug#45261. Also, update test case to
reflect that an additive operation increases the precision of
the resulting type by 1.
mysql-test/t/type_newdecimal.test:
Add test case for Bug#45261
sql/field.cc:
Added DBUG_ASSERT to ensure object's invariant is maintained.
Implement method to create a field to hold a decimal value
from an item.
sql/field.h:
Explain member variable. Add method to create a new decimal field.
sql/item.cc:
The precision should only be capped when storing the value
on a table. Also, this makes it impossible to calculate the
integer part if Item::decimals (the scale) is larger than the
precision.
sql/item.h:
Simplify calculation of integer part.
sql/item_cmpfunc.cc:
Do not limit the precision. It will be capped later.
sql/item_func.cc:
Use new method for allocating a new decimal field.
Add a specialized method for retrieving the precision
of a user variable item.
sql/item_func.h:
Add method to return the precision of a user variable.
sql/item_sum.cc:
Use new method for allocating a new decimal field.
sql/my_decimal.h:
The integer part could be improperly calculated for a decimal
with 31 digits in the fractional part.
sql/sql_select.cc:
Use new method which truncates the integer or decimal parts
as needed.
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/sql/field.h b/sql/field.h index 5136f760fc1..a9299256f88 100644 --- a/sql/field.h +++ b/sql/field.h @@ -608,6 +608,10 @@ protected: class Field_num :public Field { public: + /** + The scale of the Field's value, i.e. the number of digits to the right + of the decimal point. + */ const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, @@ -766,6 +770,11 @@ public: Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg, bool unsigned_arg); + /* + Create a field to hold a decimal value from an item. + Truncates the precision and/or scale if necessary. + */ + static Field_new_decimal *new_decimal_field(const Item *item); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } |