• Alexander Barkov's avatar
    MDEV-14454 Binary protocol returns wrong collation ID for SP OUT parameters · 563f1d89
    Alexander Barkov authored
    Item_param::set_value() did not set Item::collation and
    Item_param::str_value_ptr.str_charset properly. So both
    metadata and data for OUT parameters were sent in a wrong
    way to the client.
    
    This patch removes the old implementation of Item_param::set_value()
    and rewrites it using Type_handler::Item_param_set_from_value(),
    so now setting IN and OUT parameters share the a lot of code.
    
    1. Item_param::set_str() now:
      - accepts two additional parameters fromcs, tocs
      - sets str_value_ptr, to make sure it's always in sync with str_value,
        even without Item_param::convert_str_value()
      - does collation.set(tocs, DERIVATION_COERCIBLE),
        to make sure that DTCollation is valid even without
        Item_param::convert_str_value()
    
    2. Item_param::set_value(), which is used to set OUT parameters,
       now reuses Type_handler::Item_param_set_from_value().
    
    3. Cleanup: moving Item_param::str_value_ptr to private,
       as it's not needed outside.
    
    4. Cleanup: adding a new virtual method
       Settable_routine_parameter::get_item_param()
       and using it a few new DBUG_ASSERTs, where
       Item_param cannot appear.
    
    After this change:
    1. Assigning of IN parameters works as before:
    a. Item_param::set_str() is called and sets the value as a binary string
    b. The original value is sent to the query used for binary/general logging
    c. Item_param::convert_str_value() converts the value from the client
       character set to the connection character set
    
    2. Assigning of OUT parameters works in the new way:
    a. Item_param::set_str() and sets the value
       using the source Item's collation, so both Item::collation
       and Item_param::str_value_ptr.str_charset are properly set.
    b. Protocol_binary::send_out_parameters() sends the
       value to the client correctly:
       - Protocol::send_result_set_metadata() uses Item::collation.collation
         (which is now properly set), to detect if conversion is needed,
         and sends a correct collation ID.
       - Protocol::send_result_set_row() calls Type_handler::Item_send_str(),
         which uses Item_param::str_value_ptr.str_charset
         (which is now properly set) to actually perform the conversion.
    563f1d89
item.cc 279 KB