diff options
author | Alexander Barkov <bar@mariadb.org> | 2017-05-23 12:45:47 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-05-23 12:45:47 +0400 |
commit | d9304914bed2d6d45dbc9f43aa1e2f7ea3bbeb13 (patch) | |
tree | 75dd4ffb8bd8095ca7c2b666f2e0939e866ab623 /sql/item_timefunc.h | |
parent | 9b79888df82259743284501af5b156a18edc427f (diff) | |
download | mariadb-git-d9304914bed2d6d45dbc9f43aa1e2f7ea3bbeb13.tar.gz |
Fixing a few problems with data type and metadata for INT result functions (MDEV-12852, MDEV-12853, MDEV-12869)
This is a joint patch for:
MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
MDEV-12869 Wrong metadata for integer additive and multiplicative operators
1. Fixing all Item_func_numhybrid descendants to set the precise
data type handler (type_handler_long or type_handler_longlong)
at fix_fields() time. This fixes MDEV-12869.
2. Fixing Item_func_unsigned_typecast to set the precise data type handler
at fix_fields() time. This fixes MDEV-12852 and MDEV-12853.
This is done by:
- fixing Type_handler::Item_func_unsigned_fix_length_and_dec()
and Type_handler_string_result::Item_func_unsigned_fix_length_and_dec()
to properly detect situations when a negative epxression is converted
to UNSIGNED. In this case, length of the result is now always set to
MAX_BIGINT_WIDTH without trying to use args[0]->max_length, as very
short arguments can produce very long result in such conversion:
CAST(-1 AS UNSIGNED) -> 18446744073709551614
- adding a new virtual method "longlong Item::val_int_max() const",
to preserve the old behavior for expressions like this:
CAST(1 AS UNSIGNED)
to stay under the INT data type (instead of BIGINT) for small
positive integer literals. Using Item::unsigned_flag would not help,
because Item_int does not set unsigned_flag to "true" for positive
numbers.
3. Adding helper methods:
* Item::type_handler_long_or_longlong()
* Type_handler::type_handler_long_or_longlong()
and reusing them in a few places, to reduce code duplication.
4. Making reorganation in create_tmp_field() and
create_field_for_create_select() for Item_hybrid_func and descendants,
to reduce duplicate code. They all now have a similar behavior in
respect of creating fields. Only Item_func_user_var descendants have
a different behavior. So moving the default behvior to Item_hybrid_func,
and overriding behavior on Item_func_user_var level.
Diffstat (limited to 'sql/item_timefunc.h')
-rw-r--r-- | sql/item_timefunc.h | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 55193bce207..2e7142336a4 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -155,7 +155,7 @@ public: return str; } const char *func_name() const { return "month"; } - const Type_handler *type_handler() const { return &type_handler_longlong; } + const Type_handler *type_handler() const { return &type_handler_long; } void fix_length_and_dec() { decimals= 0; @@ -449,7 +449,10 @@ public: decimals= dec; max_length=17 + (decimals ? decimals + 1 : 0); maybe_null= true; - set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT); + if (decimals) + set_handler(&type_handler_newdecimal); + else + set_handler(type_handler_long_or_longlong()); } double real_op() { DBUG_ASSERT(0); return 0; } String *str_op(String *str) { DBUG_ASSERT(0); return 0; } |