Commit 89adedcb authored by Alexander Barkov's avatar Alexander Barkov

Step#3 MDEV-27896 Wrong result upon `COLLATE latin1_bin CHARACTER SET latin1`...

Step#3 MDEV-27896 Wrong result upon `COLLATE latin1_bin CHARACTER SET latin1` on the table or the database level

Splitting Lex_exact_charset_extended_collation_attrs_st into small components.

- Adding classes:
  * Lex_exact_charset
  * Lex_context_collation
  * Lex_exact_collation
  * Lex_extended_collation_st
  * Lex_extended_collation
  and moving pieces of the code from methods
  * merge_charset_clause_and_collate_clause()
  * merge_collate_clause_and_collate_clause()
  into smaller methods in the new classes.
  It's easier to read, handle and reuse the code this way.

- Moving static methods find_default_collation() and find_binary_collation()
  from Lex_exact_charset_extended_collation_attrs_st to non-static methods in
  Lex_exact_charset_opt_extended_collate, as now it's a better place for them.

- Using Lex_extended_collation_st in sql_yacc.yy to handle COLLATE clauses,
  to handle both context and extended collations
  (instead of the previous notation with NULL CHARSET_INFO pointer
   meaning DEFAULT, and not-NULL meaning an exact collation).
  This change will also help to add more context (UCA1400) collations soon.
  The old notation with CHARSET_INFO won't be enough.

- Adding LEX::set_names() and reusing it in two places in sql_yacc.yy

- Removing the opt_collate_or_default rule. It's was used only
  to handle the CONVERT TO related grammar. Had to add some code duplication,
  but it will be gone in one of the next commits.

This change will also soon help to add
Lex_extended_charset_extended_collation_attrs_st -
a new class to handle table and database level CHARACTER SET and COLLATE
clauses easier.
parent e7f635e2
......@@ -5514,11 +5514,9 @@ class Column_definition: public Sql_alloc,
{
if (!charset)
return Lex_column_charset_collation_attrs();
return Lex_column_charset_collation_attrs(
charset,
flags & CONTEXT_COLLATION_FLAG ?
Lex_column_charset_collation_attrs_st::TYPE_COLLATE_CONTEXTUALLY_TYPED :
Lex_column_charset_collation_attrs_st::TYPE_CHARACTER_SET);
if (flags & CONTEXT_COLLATION_FLAG)
return Lex_column_charset_collation_attrs(Lex_context_collation(charset));
return Lex_column_charset_collation_attrs(Lex_exact_collation(charset));
}
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -11874,6 +11874,21 @@ bool LEX::sp_create_set_password_instr(THD *thd,
}
bool LEX::set_names(const char *pos,
const Lex_exact_charset_opt_extended_collate &cscl,
bool no_lookahead)
{
if (sp_create_assignment_lex(thd, pos))
return true;
CHARSET_INFO *ci= cscl.collation().charset_info();
set_var_collation_client *var;
var= new (thd->mem_root) set_var_collation_client(ci, ci, ci);
return unlikely(var == NULL) ||
unlikely(thd->lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, no_lookahead));
}
bool LEX::map_data_type(const Lex_ident_sys_st &schema_name,
Lex_field_type_st *type) const
{
......
......@@ -3833,6 +3833,9 @@ struct LEX: public Query_tables_list
int case_stmt_action_then();
bool setup_select_in_parentheses();
bool set_names(const char *pos,
const Lex_exact_charset_opt_extended_collate &cs,
bool no_lookahead);
bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
Item *val);
......
......@@ -215,6 +215,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
Lex_field_type_st Lex_field_type;
Lex_exact_charset_extended_collation_attrs_st
Lex_exact_charset_extended_collation_attrs;
Lex_extended_collation_st Lex_extended_collation;
Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop;
Lex_for_loop_bounds_st for_loop_bounds;
......@@ -1387,6 +1388,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
attribute_list
field_def
%type <Lex_extended_collation>
collation_name
collation_name_or_default
%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
numeric_dyncol_type temporal_dyncol_type string_dyncol_type
......@@ -1579,14 +1584,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
text_or_password
%type <charset>
opt_collate_or_default
charset_name
charset_or_alias
charset_name_or_default
old_or_new_charset_name
old_or_new_charset_name_or_default
collation_name
collation_name_or_default
opt_load_data_charset
UNDERSCORE_CHARSET
......@@ -5532,13 +5534,15 @@ default_collation:
opt_default COLLATE_SYM opt_equal collation_name_or_default
{
HA_CREATE_INFO *cinfo= &Lex->create_info;
bool is_exact= $4.type() == Lex_extended_collation_st::TYPE_EXACT;
CHARSET_INFO *cl= is_exact ? $4.charset_info() : NULL;
if (unlikely((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
cinfo->default_table_charset && $4 &&
!($4= merge_charset_and_collation(cinfo->default_table_charset,
$4))))
cinfo->default_table_charset && cl &&
!(cl= merge_charset_and_collation(cinfo->default_table_charset,
cl))))
MYSQL_YYABORT;
Lex->create_info.default_table_charset= $4;
Lex->create_info.default_table_charset= cl;
Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
}
;
......@@ -5791,7 +5795,7 @@ field_type_or_serial:
field_def
{
auto tmp= $1.charset_collation_attrs();
if (tmp.merge_charset_clause_and_collate_clause($3))
if (tmp.merge_column_charset_clause_and_collate_clause($3))
MYSQL_YYABORT;
Lex->last_field->set_charset_collation_attrs(tmp);
}
......@@ -5831,7 +5835,7 @@ field_def:
| attribute_list compressed_deprecated_column_attribute { $$= $1; }
| attribute_list compressed_deprecated_column_attribute attribute_list
{
if (($$= $1).merge_collate_clause_and_collate_clause($3))
if (($$= $1).merge_column_collate_clause_and_collate_clause($3))
MYSQL_YYABORT;
}
| opt_generated_always AS virtual_column_func
......@@ -6312,7 +6316,7 @@ opt_precision:
attribute_list:
attribute_list attribute
{
if (($$= $1).merge_collate_clause_and_collate_clause($2))
if (($$= $1).merge_column_collate_clause_and_collate_clause($2))
MYSQL_YYABORT;
}
| attribute
......@@ -6339,7 +6343,7 @@ attribute:
}
| COLLATE_SYM collation_name
{
$$.set_collate_exact($2);
$$= Lex_exact_charset_extended_collation_attrs($2);
}
| serial_attribute { $$.init(); }
;
......@@ -6479,20 +6483,17 @@ old_or_new_charset_name_or_default:
collation_name:
ident_or_text
{
if (unlikely(!($$= mysqld_collation_get_by_name($1.str,
CHARSET_INFO *cs;
if (unlikely(!(cs= mysqld_collation_get_by_name($1.str,
thd->get_utf8_flag()))))
MYSQL_YYABORT;
$$= Lex_extended_collation(Lex_exact_collation(cs));
}
;
opt_collate_or_default:
/* empty */ { $$=NULL; }
| COLLATE_SYM collation_name_or_default { $$=$2; }
;
collation_name_or_default:
collation_name { $$=$1; }
| DEFAULT { $$=NULL; }
| DEFAULT { $$.set_collate_default(); }
;
opt_default:
......@@ -6535,11 +6536,18 @@ binary:
}
| charset_or_alias COLLATE_SYM collation_name
{
if ($$.set_charset_collate_exact($1, $3))
if ($3.merge_exact_charset(Lex_exact_charset($1)))
MYSQL_YYABORT;
$$= Lex_exact_charset_extended_collation_attrs($3);
}
| COLLATE_SYM collation_name
{
$$= Lex_exact_charset_extended_collation_attrs($2);
}
| COLLATE_SYM DEFAULT
{
$$.set_collate_default();
}
| COLLATE_SYM collation_name { $$.set_collate_exact($2); }
| COLLATE_SYM DEFAULT { $$.set_collate_default(); }
;
opt_bin_mod:
......@@ -7610,17 +7618,28 @@ alter_list_item:
lex->alter_info.flags|= ALTER_RENAME_INDEX;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default
opt_collate_or_default
{
if (!$4)
{
$4= thd->variables.collation_database;
}
$5= $5 ? $5 : $4;
if (unlikely(!my_charset_same($4,$5)))
if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($4)))
MYSQL_YYABORT;
Lex->alter_info.flags|= ALTER_CONVERT_TO;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default
COLLATE_SYM collation_name_or_default
{
if (!$4)
{
$4= thd->variables.collation_database;
}
bool is_exact= $6.type() == Lex_extended_collation_st::TYPE_EXACT;
CHARSET_INFO *cl= is_exact ? $6.charset_info() : $4;
if (unlikely(!my_charset_same($4,cl)))
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
$5->coll_name.str, $4->cs_name.str));
if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($5)))
cl->coll_name.str, $4->cs_name.str));
if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset(cl)))
MYSQL_YYABORT;
Lex->alter_info.flags|= ALTER_CONVERT_TO;
}
......@@ -9739,7 +9758,9 @@ string_factor_expr:
primary_expr
| string_factor_expr COLLATE_SYM collation_name
{
if (unlikely(!($$= new (thd->mem_root) Item_func_set_collation(thd, $1, $3))))
if (unlikely(!($$= new (thd->mem_root)
Item_func_set_collation(thd, $1,
$3.charset_info()))))
MYSQL_YYABORT;
}
;
......@@ -16581,26 +16602,20 @@ option_value_no_option_type:
thd->parse_error();
MYSQL_YYABORT;
}
| NAMES_SYM charset_name_or_default opt_collate_or_default
| NAMES_SYM charset_name_or_default
{
if (sp_create_assignment_lex(thd, $1.pos()))
CHARSET_INFO *def= global_system_variables.character_set_client;
Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false);
if (Lex->set_names($1.pos(), tmp, yychar == YYEMPTY))
MYSQL_YYABORT;
LEX *lex= Lex;
CHARSET_INFO *cs2;
CHARSET_INFO *cs3;
cs2= $2 ? $2 : global_system_variables.character_set_client;
cs3= $3 ? $3 : cs2;
if (unlikely(!my_charset_same(cs2, cs3)))
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
cs3->coll_name.str, cs2->cs_name.str);
MYSQL_YYABORT;
}
set_var_collation_client *var;
var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
if (unlikely(var == NULL) ||
unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
}
| NAMES_SYM charset_name_or_default
COLLATE_SYM collation_name_or_default
{
CHARSET_INFO *def= global_system_variables.character_set_client;
Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false);
if (tmp.merge_collation($4) ||
Lex->set_names($1.pos(), tmp, yychar == YYEMPTY))
MYSQL_YYABORT;
}
| DEFAULT ROLE_SYM grant_role
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment