Commit fe3dee06 authored by unknown's avatar unknown
Browse files

Fix for bug #20695: Charset introducer overrides charset definition for column.

  - if there are two character set definitions in the column declaration,
    we replace the first one with the second one as we store both in the LEX->charset
    slot. Add a separate slot to the LEX structure to store underscore charset.
  - convert default values to the column charset of STRING, VARSTRING fields 
    if necessary as well.


mysql-test/r/ctype_recoding.result:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - test result.
mysql-test/t/ctype_recoding.test:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - test case.
sql/sql_lex.cc:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET
sql/sql_lex.h:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET
sql/sql_table.cc:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - convert default values to the column charset of VARSTRING, STRING, ENUM, 
      SET fields if necessary.
sql/sql_yacc.yy:
  Fix for bug #20695: Charset introducer overrides charset definition for column.
    - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET
parent ef601901
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -247,3 +247,14 @@ lpad(c1,3,'
select rpad(c1,3,''), rpad('',3,c1) from t1;
rpad(c1,3,'')	rpad('',3,c1)
	
drop table t1;
set names koi8r;
create table t1(a char character set cp1251 default _koi8r 0xFF);
show create table t1;
Table	Create Table
t1	CREATE TABLE `t1` (
  `a` char(1) character set cp1251 default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1(a char character set latin1 default _cp1251 0xFF);
ERROR 42000: Invalid default value for 'a'
+12 −0
Original line number Diff line number Diff line
@@ -186,5 +186,17 @@ select rpad(c1,3,'
# TODO
#select case c1 when '' then '' when '' then '' else 'c' end from t1;
#select export_set(5,c1,''), export_set(5,'',c1) from t1;
drop table t1;

#
# Bug 20695: problem with field default value's character set
#

set names koi8r;
create table t1(a char character set cp1251 default _koi8r 0xFF);
show create table t1;
drop table t1;
--error 1067
create table t1(a char character set latin1 default _cp1251 0xFF);

# End of 4.1 tests
+3 −2
Original line number Diff line number Diff line
@@ -643,7 +643,8 @@ int yylex(void *arg, void *yythd)
      */

      if ((yylval->lex_str.str[0]=='_') && 
          (lex->charset=get_charset_by_csname(yylval->lex_str.str+1,
          (lex->underscore_charset=
             get_charset_by_csname(yylval->lex_str.str + 1,
                                   MY_CS_PRIMARY,MYF(0))))
        return(UNDERSCORE_CHARSET);
      return(result_state);			// IDENT or IDENT_QUOTED
+1 −1
Original line number Diff line number Diff line
@@ -613,7 +613,7 @@ typedef struct st_lex
  LEX_USER *grant_user;
  gptr yacc_yyss,yacc_yyvs;
  THD *thd;
  CHARSET_INFO *charset;
  CHARSET_INFO *charset, *underscore_charset;

  List<key_part_spec> col_list;
  List<key_part_spec> ref_list;
+34 −29
Original line number Diff line number Diff line
@@ -516,6 +516,40 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
      DBUG_RETURN(-1);
    }

    /*
      Convert the default value character
      set into the column character set if necessary.
    */
    if (sql_field->def && 
        savecs != sql_field->def->collation.collation &&
        (sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
         sql_field->sql_type == FIELD_TYPE_STRING ||
         sql_field->sql_type == FIELD_TYPE_SET ||
         sql_field->sql_type == FIELD_TYPE_ENUM))
    {
      Item_arena backup_arena;
      bool need_to_change_arena=
        !thd->current_arena->is_conventional_execution();
      if (need_to_change_arena)
      {
        /* Assert that we don't do that at every PS execute */
        DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
        thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
      }

      sql_field->def= sql_field->def->safe_charset_converter(savecs);

      if (need_to_change_arena)
        thd->restore_backup_item_arena(thd->current_arena, &backup_arena);

      if (sql_field->def == NULL)
      {
        /* Could not convert */
        my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
        DBUG_RETURN(-1);
      }
    }

    if (sql_field->sql_type == FIELD_TYPE_SET ||
        sql_field->sql_type == FIELD_TYPE_ENUM)
    {
@@ -580,35 +614,6 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
        sql_field->interval_list.empty(); // Don't need interval_list anymore
      }

      /*
        Convert the default value from client character
        set into the column character set if necessary.
      */
      if (sql_field->def && cs != sql_field->def->collation.collation)
      {
        Item_arena backup_arena;
        bool need_to_change_arena=
          !thd->current_arena->is_conventional_execution();
        if (need_to_change_arena)
        {
          /* Asser that we don't do that at every PS execute */
          DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
          thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
        }

        sql_field->def= sql_field->def->safe_charset_converter(cs);

        if (need_to_change_arena)
          thd->restore_backup_item_arena(thd->current_arena, &backup_arena);

        if (sql_field->def == NULL)
        {
          /* Could not convert */
          my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
          DBUG_RETURN(-1);
        }
      }

      if (sql_field->sql_type == FIELD_TYPE_SET)
      {
        if (sql_field->def != NULL)
Loading