• Alexander Barkov's avatar
    MDEV-11672 mysql_list_field() returns wrong default values for VIEW · f6138883
    Alexander Barkov authored
    The problem happened because Item_ident_for_show::field_type() always
    returned MYSQL_TYPE_DOUBLE and ignored the actual data type of the
    referenced Field. As a result, the execution always used
    Item_ident_for_show::val_real() to send the default value of the field,
    so most default values for non-numeric types were displayed as '0'.
    
    This patch:
    1. Cleanup:
       a. Removes Send_field::charsetnr, as it's been unused since
          introduction of Item::charset_for_protocol() in MySQL-5.5.
       b. Adds the "const" qualifier to Field::char_length().
          This is needed for (5.a), see below.
    
    2. Introduces a new virtual method Type_handler::charset_for_protocol(),
       returning item->collation.collation for string data types, or
       &my_charset_bin for non-string data types.
    
    3. Changes Item::charset_for_protocol() from virtual to non-virtual.
       It now calls type_handler()->charset_for_protocol().
       As a good side effect, duplicate code in Item::charset_for_protocol() and
       Item_temporal_hybrid_func::charset_for_protocol() is now gone.
    
    4. Fixes Item_ident_for_show::field_type() to correctly return
       its data type according to the data type of the referenced field.
       This actually fixes the problem reported in MDEV-11672.
       Now the default value is sent using a correct method, e.g.
       val_str() for VARCHAR/TEXT, or val_int() for INT/BIGINT.
       This required additional changes:
       a. in DBUG_ASSERT in Protocol::store(const char *,size_t,CHARSET_INFO),
          This method is now used by mysqld_list_fields(), which
          (unlike normal SELECT queries) does not set
          field_types/field_pos/field_count.
       b. Item_ident_for_show::Item_ident_for_show() now set standard attributes
          (collation, decimals, max_length, unsigned_flag) according to the
          referenced field, to make charset_for_protocol() return the correct
          value and to make mysqld_list_fields() correctly send default
          values.
    
    5. In order to share the code between Item_field::set_field() and
       Item_ident_for_show::Item_ident_for_show():
       a. Introduces a new method Type_std_attributes::set(const Field*)
       b. To make (a) possible, moves Item::fix_char_length() from Item
          to Type_std_attributes, also moves char_to_byte_length_safe()
          from item.h to sql_type.h
       c. Additionally, moves Item::fix_length_and_charset() and
          Item::max_char_length() from Item to Type_std_attributes.
          This is not directly needed for the fix and is done just for symmetry
          with fix_char_length(), as these three methods are directly related
          to each other.
    f6138883
mysql_client_test.c 529 KB