static int add_column_list_values(String *str, partition_info *part_info,
                                  part_elem_value *list_value,
                                  HA_CREATE_INFO *create_info,
                                  Alter_info *alter_info)
{
  int err= 0;
  uint i;
  List_iterator<const char> it(part_info->part_field_list);
  uint num_elements= part_info->part_field_list.elements;
  bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
                         part_info->num_columns > 1U);

  if (use_parenthesis)
    err+= str->append('(');
  for (i= 0; i < num_elements; i++)
  {
    part_column_list_val *col_val= &list_value->col_val_array[i];
    const char *field_name= it++;
    if (col_val->max_value)
      err+= str->append(STRING_WITH_LEN("MAXVALUE"));
    else if (col_val->null_value)
      err+= str->append(STRING_WITH_LEN("NULL"));
    else
    {
      Item *item_expr= col_val->item_expression;
      if (item_expr->null_value)
        err+= str->append(STRING_WITH_LEN("NULL"));
      else
      {
        CHARSET_INFO *field_cs;
        bool need_cs_check= FALSE;
        Item_result result_type= STRING_RESULT;

        /*
          This function is called at a very early stage, even before
          we have prepared the sql_field objects. Thus we have to
          find the proper sql_field object and get the character set
          from that object.
        */
        if (create_info)
        {
          Create_field *sql_field;

          if (!(sql_field= get_sql_field(field_name,
                                         alter_info)))
          {
            my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
            return 1;
          }
          if (check_part_field(sql_field->real_field_type(),
                               sql_field->field_name.str,
                               &result_type,
                               &need_cs_check))
            return 1;
          if (need_cs_check)
            field_cs= get_sql_field_charset(sql_field, create_info);
          else
            field_cs= NULL;
        }
        else
        {
          Field *field= part_info->part_field_array[i];
          result_type= field->result_type();
          if (check_part_field(field->real_type(),
                               field->field_name.str,
                               &result_type,
                               &need_cs_check))
            return 1;
          DBUG_ASSERT(result_type == field->result_type());
          if (need_cs_check)
            field_cs= field->charset();
          else
            field_cs= NULL;
        }
        if (result_type != item_expr->result_type())
        {
          my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
          return 1;
        }
        if (field_cs && field_cs != item_expr->collation.collation)
        {
          if (!(item_expr= convert_charset_partition_constant(item_expr,
                                                              field_cs)))
          {
            my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
            return 1;
          }
        }
        {
          StringBuffer<MAX_KEY_LENGTH> buf;
          String val_conv, *res;
          val_conv.set_charset(system_charset_info);
          res= item_expr->val_str(&buf);
          if (get_cs_converted_part_value_from_string(current_thd,
                                                      item_expr, res,
                                                      &val_conv, field_cs,
                                                   (bool)(alter_info != NULL)))
            return 1;
          err+= str->append(val_conv);
        }
      }
    }
    if (i != (num_elements - 1))
      err+= str->append(',');
  }
  if (use_parenthesis)
    err+= str->append(')');
  return err;
}