Details
-
Task
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
None
Description
There is a lot of duplicate code related to retrieving and processing val_decimal() results.
This task will reduce the amount of duplicate code using the following changes.
1. Move repeatable pieces as methods to my_decimal
Examples:
longlong i;
|
my_decimal2int(E_DEC_FATAL_ERROR, &m_decimal, attr->unsigned_flag, &i);
|
return i; |
longlong i;
|
my_decimal2int(E_DEC_FATAL_ERROR, &m_decimal, attr->unsigned_flag, &i);
|
return i; |
Also, add new constructors:
my_decimal(const uchar *bin, int prec, int scale) |
my_decimal(Field *field);
|
2. Add a new class VDec, with approximate this structure:
my_decimal m_buffer;
|
my_decima *m_ptr;
|
public: |
VDec(Item *item)
|
{
|
m_ptr= item->val_decimal(&m_buffer);
|
DBUG_ASSERT((m_ptr == NULL) == item->null_value);
|
}
|
longlong to_longlong();
|
double to_real(); |
String *to_string(String *str);
|
bool to_date(MYSQL_TIME *ltime, ulonglong fuzzydate); |
and change a lot of duplicate peaces like this:
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
|
if (null_value) |
return xxx; |
return yyy; |
to:
VDec tmp(this); |
return tmp.is_null() ? xxx : yyy; |
or even to a shorter notation when applicable:
return tmp(this).xxx_or_yyy(); |
3. Add a similar class VDec_op. It will initialize its value using Item_func_hybrid_field_type::decimal_op() instead of Item::val_decimal().
4. Remove methods:
- Item::val_int_unsigned_typecast_from_decimal()
- Item::val_string_from_decimal()
- Item::val_int_from_decimal()
- Item::val_real_from_decimal()
- Item::get_date_from_decimal()
- Item_func_hybrid_field_type::val_decimal_from_decimal_op()
- Item_func_hybrid_field_type::val_str_from_decimal_op()
- Item_func_hybrid_field_type::val_int_from_decimal_op()
- Item_func_hybrid_field_type::val_real_from_decimal_op()
- Item_func_hybrid_field_type:::get_date_from_decimal_op()
and replace their calls to the corresponding VDec methods, e.g.:- return item->val_real_from_decimal();
+ return VDec(item).to_double();
5. Add a helper class VDec2_lazy with approximately this definition:
/*
|
Get and cache val_decimal() values for two items.
|
If the first value appears to be NULL, the second value is not evaluated.
|
*/
|
class VDec2_lazy |
{
|
public: |
VDec m_a;
|
VDec m_b;
|
VDec2_lazy(Item *a, Item *b) :m_a(a)
|
{
|
if (!m_a.is_null()) |
m_b.set(b);
|
}
|
bool has_null() const |
{
|
return m_a.is_null() || m_b.is_null(); |
}
|
};
|
and reuse it instead of duplicate code pieces in Item_func_(plus|minus|mul|div|int_div|mod)::decimal_op().
6. Change tests for item->null_value to tests for VDec::is_null(). For example:
my_decimal buf, *dec= item->val_decimal(&buf);
|
if (item->null_value) |
return NULL; |
to
VDec dec(item);
|
if (dec.is_null()) |
return NULL; |
This will be a good step towards MDEV-6897 (particular, to get rid of Item::null_value).
As a good advantage, this change will make the code more symmetric with the implementation for temporal data types. The new class VDec will to for DECIMAL what classes Time, Date and Datetime do (for TIME, DATE and DATETIME respectively).