summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc151
1 files changed, 94 insertions, 57 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 43fa10fab3c..449478a7fa4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2202,7 +2202,7 @@ bool check_duplicates_in_interval(const char *set_or_name,
bool Column_definition::
prepare_charset_for_string(const Column_derived_attributes *dattr)
{
- CHARSET_INFO *tmp= lex_charset_collation().
+ CHARSET_INFO *tmp= charset_collation_attrs().
resolved_to_character_set(dattr->charset());
if (!tmp)
return true;
@@ -3875,38 +3875,6 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
/*
- Set table default charset, if not set
-
- SYNOPSIS
- set_table_default_charset()
- create_info Table create information
-
- DESCRIPTION
- If the table character set was not given explicitly,
- let's fetch the database default character set and
- apply it to the table.
-*/
-
-static void set_table_default_charset(THD *thd, HA_CREATE_INFO *create_info,
- const LEX_CSTRING &db)
-{
- /*
- If the table character set was not given explicitly,
- let's fetch the database default character set and
- apply it to the table.
- */
- if (!create_info->default_table_charset)
- {
- Schema_specification_st db_info;
-
- load_db_opt_by_name(thd, db.str, &db_info);
-
- create_info->default_table_charset= db_info.default_table_charset;
- }
-}
-
-
-/*
Extend long VARCHAR fields to blob & prepare field if it's a blob
SYNOPSIS
@@ -4064,14 +4032,14 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
handler *file;
DBUG_ENTER("mysql_create_frm_image");
+ DBUG_ASSERT(create_info->default_table_charset);
+
if (!alter_info->create_list.elements)
{
my_error(ER_TABLE_MUST_HAVE_COLUMNS, MYF(0));
DBUG_RETURN(NULL);
}
- set_table_default_charset(thd, create_info, db);
-
db_options= create_info->table_options_with_row_type();
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
@@ -4345,6 +4313,7 @@ err:
@retval -1 table existed but IF NOT EXISTS was used
*/
+static
int create_table_impl(THD *thd,
DDL_LOG_STATE *ddl_log_state_create,
DDL_LOG_STATE *ddl_log_state_rm,
@@ -4365,6 +4334,8 @@ int create_table_impl(THD *thd,
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d path: %s",
db.str, table_name.str, internal_tmp_table, path.str));
+ DBUG_ASSERT(create_info->default_table_charset);
+
/* Easy check for ddl logging if we are creating a temporary table */
if (create_info->tmp_table())
{
@@ -4703,6 +4674,8 @@ int mysql_create_table_no_lock(THD *thd,
LEX_CSTRING cpath;
LEX_CUSTRING frm= {0,0};
+ DBUG_ASSERT(create_info->default_table_charset);
+
if (create_info->tmp_table())
path_length= build_tmptable_filename(thd, path, sizeof(path));
else
@@ -4771,6 +4744,8 @@ int mysql_create_table_no_lock(THD *thd,
close of thread tables.
*/
+
+static
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
Table_specification_st *create_info,
Alter_info *alter_info)
@@ -4784,6 +4759,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
bool result;
DBUG_ENTER("mysql_create_table");
+ DBUG_ASSERT(create_info->default_table_charset);
+
DBUG_ASSERT(create_table == thd->lex->query_tables);
bzero(&ddl_log_state_create, sizeof(ddl_log_state_create));
@@ -5222,6 +5199,7 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
TRUE error
*/
+static
bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
Table_specification_st *create_info)
@@ -5296,6 +5274,14 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
local_create_info.db_type= src_table->table->s->db_type();
local_create_info.row_type= src_table->table->s->row_type;
local_create_info.alter_info= &local_alter_info;
+ /*
+ This statement:
+ CREATE TABLE t1 LIKE t2
+ does not support table charset/collation clauses.
+ No needs to copy. Assert they are empty.
+ */
+ DBUG_ASSERT(create_info->default_charset_collation.is_empty());
+ DBUG_ASSERT(create_info->convert_charset_collation.is_empty());
if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
&local_alter_info, &local_alter_ctx))
goto err;
@@ -7949,12 +7935,14 @@ void append_drop_column(THD *thd, String *str, Field *field)
bool
mysql_prepare_alter_table(THD *thd, TABLE *table,
- HA_CREATE_INFO *create_info,
+ Table_specification_st *create_info,
Alter_info *alter_info,
Alter_table_ctx *alter_ctx)
{
/* New column definitions are added here */
List<Create_field> new_create_list;
+ /* System-invisible fields must be added last */
+ List<Create_field> new_create_tail;
/* New key definitions are added here */
List<Key> new_key_list;
List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
@@ -8013,8 +8001,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
create_info->max_rows= table->s->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
create_info->avg_row_length= table->s->avg_row_length;
- if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
- create_info->default_table_charset= table->s->table_charset;
+
+ if (create_info->resolve_to_charset_collation_context(thd,
+ thd->charset_collation_context_alter_table(table->s)))
+ DBUG_RETURN(true);
+
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
{
/* Table has an autoincrement, copy value to new table */
@@ -8181,7 +8172,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
dropped_sys_vers_fields|= field->flags;
drop_it.remove();
}
- else
+ else if (field->invisible < INVISIBLE_SYSTEM)
{
/*
This field was not dropped and not changed, add it to the list
@@ -8232,6 +8223,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_it.remove();
}
}
+ else
+ {
+ DBUG_ASSERT(field->invisible == INVISIBLE_SYSTEM);
+ def= new (thd->mem_root) Create_field(thd, field, field);
+ new_create_tail.push_back(def, thd->mem_root);
+ }
}
/*
@@ -8394,6 +8391,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_it.remove();
}
}
+
+ new_create_list.append(&new_create_tail);
+
if (unlikely(alter_info->alter_list.elements))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
@@ -9763,7 +9763,7 @@ static uint64 get_start_alter_id(THD *thd)
bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
const LEX_CSTRING *new_name,
- HA_CREATE_INFO *create_info,
+ Table_specification_st *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
uint order_num, ORDER *order, bool ignore,
@@ -10356,7 +10356,7 @@ do_continue:;
DBUG_RETURN(true);
}
- set_table_default_charset(thd, create_info, alter_ctx.db);
+ DBUG_ASSERT(create_info->default_table_charset);
if (create_info->check_fields(thd, alter_info,
table_list->table_name, table_list->db) ||
@@ -11776,7 +11776,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
{
- HA_CREATE_INFO create_info;
+ Table_specification_st create_info;
Alter_info alter_info;
TABLE_LIST *next_table= table_list->next_global;
DBUG_ENTER("mysql_recreate_table");
@@ -11788,9 +11788,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
/* hide following tables from open_tables() */
table_list->next_global= NULL;
- bzero((char*) &create_info, sizeof(create_info));
+ create_info.init();
create_info.row_type=ROW_TYPE_NOT_USED;
- create_info.default_table_charset=default_charset_info;
create_info.alter_info= &alter_info;
/* Force alter table to recreate table */
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
@@ -12047,6 +12046,11 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
const bool used_engine= lex->create_info.used_fields & HA_CREATE_USED_ENGINE;
DBUG_ASSERT((m_storage_engine_name.str != NULL) == used_engine);
+
+ if (lex->create_info.resolve_to_charset_collation_context(thd,
+ thd->charset_collation_context_create_table_in_db(first_table->db.str)))
+ DBUG_RETURN(true);
+
if (used_engine)
{
if (resolve_storage_engine_with_error(thd, &lex->create_info.db_type,
@@ -12119,19 +12123,9 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
*/
if (!(create_info.used_fields & HA_CREATE_USED_ENGINE))
create_info.use_default_db_type(thd);
- /*
- If we are using SET CHARSET without DEFAULT, add an implicit
- DEFAULT to not confuse old users. (This may change).
- */
- if ((create_info.used_fields &
- (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
- HA_CREATE_USED_CHARSET)
- {
- create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
- create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
- create_info.default_table_charset= create_info.alter_table_convert_to_charset;
- create_info.alter_table_convert_to_charset= 0;
- }
+
+ DBUG_ASSERT(!(create_info.used_fields & HA_CREATE_USED_CHARSET));
+ DBUG_ASSERT(create_info.convert_charset_collation.is_empty());
/*
If we are a slave, we should add OR REPLACE if we don't have
@@ -12357,3 +12351,46 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
end_with_restore_list:
DBUG_RETURN(res);
}
+
+
+bool HA_CREATE_INFO::
+ resolve_to_charset_collation_context(THD *thd,
+ const Lex_table_charset_collation_attrs_st &default_cscl_arg,
+ const Lex_table_charset_collation_attrs_st &convert_cscl,
+ const Charset_collation_context &ctx)
+{
+ /*
+ If CONVERT TO clauses are specified only (without table default clauses),
+ then we copy CONVERT TO clauses to default clauses, so e.g:
+ CONVERT TO CHARACTER SET utf8mb4
+ means
+ CONVERT TO CHARACTER SET utf8mb4, DEFAULT CHARACTER SET utf8mb4
+ */
+ Lex_table_charset_collation_attrs_st default_cscl=
+ !convert_cscl.is_empty() && default_cscl_arg.is_empty() ?
+ convert_cscl : default_cscl_arg;
+
+ if (default_cscl.is_empty())
+ default_table_charset= ctx.collate_default().charset_info();
+ else
+ {
+ // Make sure we don't do double resolution in direct SQL execution
+ DBUG_ASSERT(!default_table_charset || thd->stmt_arena->is_stmt_execute());
+ if (!(default_table_charset=
+ default_cscl.resolved_to_context(ctx)))
+ return true;
+ }
+
+ if (convert_cscl.is_empty())
+ alter_table_convert_to_charset= NULL;
+ else
+ {
+ // Make sure we don't do double resolution in direct SQL execution
+ DBUG_ASSERT(!alter_table_convert_to_charset ||
+ thd->stmt_arena->is_stmt_execute());
+ if (!(alter_table_convert_to_charset=
+ convert_cscl.resolved_to_context(ctx)))
+ return true;
+ }
+ return false;
+}