diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 2042767c042120cb8259c4ae8fed55513f3d5bb4..0bbed8a1bdf6695955dddb89ac55a6ace7ce2a56 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -248,3 +248,13 @@ select rpad(c1,3,' 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' diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 2d6b55600b1ff6b7c9614f1ab60c68a0a469a290..ddaaa7b9e4f898d5b2d4c166f99567042c5c1756 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -187,4 +187,16 @@ select rpad(c1,3,' #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 diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 935a2b2486e6b16b504c8700719ad44b62c9c1c3..b9e52b62244cfe20ff93ca694db63a250b2daa1a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -663,8 +663,9 @@ int MYSQLlex(void *arg, void *yythd) */ if ((yylval->lex_str.str[0]=='_') && - (lex->charset=get_charset_by_csname(yylval->lex_str.str+1, - MY_CS_PRIMARY,MYF(0)))) + (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 diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7e78a674b35854ee0a0315e9bcfb937e1c92d01b..ce0af39a041b796f98bdd78c6fa16739a08c4317 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -895,7 +895,7 @@ typedef struct st_lex : public Query_tables_list XID *xid; gptr yacc_yyss,yacc_yyvs; THD *thd; - CHARSET_INFO *charset; + CHARSET_INFO *charset, *underscore_charset; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; /* Position (first character index) of SELECT of CREATE VIEW statement */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f0f69676ed2b96198654a6cad760d9dada169df7..20396bcf0b71cc14f12ef8712d7879778f359bf3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2224,6 +2224,40 @@ static 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) { @@ -2285,35 +2319,6 @@ static 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) - { - Query_arena backup_arena; - bool need_to_change_arena= !thd->stmt_arena->is_conventional(); - if (need_to_change_arena) - { - /* Asser that we don't do that at every PS execute */ - DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || - thd->stmt_arena->is_first_sp_execute()); - thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); - } - - sql_field->def= sql_field->def->safe_charset_converter(cs); - - if (need_to_change_arena) - thd->restore_active_arena(thd->stmt_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) { uint32 field_length; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8527f110ce25baf350eb6643d2b0d476c973352f..b1a1e9cb9af7b61bbb0a55a22a3c02ffee96ce9a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8902,7 +8902,7 @@ text_literal: | NCHAR_STRING { $$= new Item_string($1.str,$1.length,national_charset_info); } | UNDERSCORE_CHARSET TEXT_STRING - { $$ = new Item_string($2.str,$2.length,Lex->charset); } + { $$ = new Item_string($2.str,$2.length,Lex->underscore_charset); } | text_literal TEXT_STRING_literal { ((Item_string*) $1)->append($2.str,$2.length); } ; @@ -8980,7 +8980,7 @@ literal: (String*) 0; $$= new Item_string(str ? str->ptr() : "", str ? str->length() : 0, - Lex->charset); + Lex->underscore_charset); } | UNDERSCORE_CHARSET BIN_NUM {