• Alexander Barkov's avatar
    Fixing a few problems with data type and metadata for INT result functions... · d9304914
    Alexander Barkov authored
    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.
    d9304914
item_func.h 93.2 KB