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.cc700
1 files changed, 421 insertions, 279 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 619c3fe2654..2d4ff71d0c1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
- Copyright (c) 2010, 2019, MariaDB
+ Copyright (c) 2010, 2020, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
#include "sql_base.h" // lock_table_names
#include "lock.h" // mysql_unlock_tables
#include "strfunc.h" // find_type2, find_set
-#include "sql_truncate.h" // regenerate_locked_table
+#include "sql_truncate.h" // regenerate_locked_table
#include "sql_partition.h" // mem_alloc_error,
// partition_info
// NOT_A_PARTITION_ID
@@ -132,7 +132,7 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p,
*(to_p++)= (char) quote;
while (*conv_name && (end_p - to_p - 1) > 0)
{
- int length= my_charlen(system_charset_info, conv_name, conv_name_end);
+ int length= system_charset_info->charlen(conv_name, conv_name_end);
if (length <= 0)
length= 1;
if (length == 1 && *conv_name == (char) quote)
@@ -1127,8 +1127,8 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
ddl_log_entry->tmp_name));
handler_name.str= (char*)ddl_log_entry->handler_name;
handler_name.length= strlen(ddl_log_entry->handler_name);
- init_sql_alloc(&mem_root, "execute_ddl_log_action", TABLE_ALLOC_BLOCK_SIZE,
- 0, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_gdl, &mem_root, TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(MY_THREAD_SPECIFIC));
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
frm_action= TRUE;
else
@@ -1162,7 +1162,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
- (void) mysql_file_delete(key_file_partition, to_path, MYF(MY_WME));
+ (void) mysql_file_delete(key_file_partition_ddl_log, to_path, MYF(MY_WME));
#endif
}
else
@@ -1200,7 +1200,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
#ifdef WITH_PARTITION_STORAGE_ENGINE
strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS);
- (void) mysql_file_rename(key_file_partition, from_path, to_path, MYF(MY_WME));
+ (void) mysql_file_rename(key_file_partition_ddl_log, from_path, to_path, MYF(MY_WME));
#endif
}
else
@@ -1297,7 +1297,7 @@ static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
if (global_ddl_log.first_free == NULL)
{
- if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
+ if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(key_memory_DDL_LOG_MEMORY_ENTRY,
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
{
sql_print_error("Failed to allocate memory for ddl log free list");
@@ -2443,6 +2443,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{
char *end;
int frm_delete_error= 0;
+
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ !wsrep_should_replicate_ddl(thd, table_type->db_type))
+ {
+ error= 1;
+ goto err;
+ }
+#endif
+
/*
It could happen that table's share in the table definition cache
is the only thing that keeps the engine plugin loaded
@@ -2470,8 +2480,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
table->table= 0;
}
else
- tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str, table->table_name.str,
- false);
+ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str,
+ table->table_name.str);
/* Check that we have an exclusive lock on the table to be dropped. */
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
@@ -2743,7 +2753,8 @@ bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
*/
bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
- const LEX_CSTRING *table_name, uint flags, const char *table_path)
+ const LEX_CSTRING *table_name, uint flags,
+ const char *table_path)
{
char path[FN_REFLEN + 1];
int error= 0;
@@ -2751,11 +2762,13 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
size_t path_length= table_path ?
(strxnmov(path, sizeof(path) - 1, table_path, reg_ext, NullS) - path) :
- build_table_filename(path, sizeof(path)-1, db->str, table_name->str, reg_ext, flags);
- if (mysql_file_delete(key_file_frm, path, MYF(0)))
- error= 1; /* purecov: inspected */
+ build_table_filename(path, sizeof(path)-1, db->str, table_name->str,
+ reg_ext, flags);
+ if (!(flags & NO_FRM_RENAME))
+ if (mysql_file_delete(key_file_frm, path, MYF(0)))
+ error= 1; /* purecov: inspected */
path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
- if (flags & NO_HA_TABLE)
+ if ((flags & (NO_HA_TABLE | NO_PAR_TABLE)) == NO_HA_TABLE)
{
handler *file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base);
if (!file)
@@ -2861,7 +2874,7 @@ static int sort_keys(KEY *a, KEY *b)
*/
bool check_duplicates_in_interval(const char *set_or_name,
- const char *name, TYPELIB *typelib,
+ const char *name, const TYPELIB *typelib,
CHARSET_INFO *cs, unsigned int *dup_val_count)
{
TYPELIB tmp= *typelib;
@@ -2925,12 +2938,11 @@ bool Column_definition::prepare_stage2_typelib(const char *type_name,
}
-uint Column_definition::pack_flag_numeric(uint dec) const
+uint Column_definition::pack_flag_numeric() const
{
return (FIELDFLAG_NUMBER |
(flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
- (flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
- (dec << FIELDFLAG_DEC_SHIFT));
+ (flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0));
}
@@ -3226,8 +3238,7 @@ bool Column_definition::prepare_stage1_check_typelib_default()
}
else /* MYSQL_TYPE_ENUM */
{
- def->length(charset->cset->lengthsp(charset,
- def->ptr(), def->length()));
+ def->length(charset->lengthsp(def->ptr(), def->length()));
not_found= !find_type2(interval, def->ptr(), def->length(), charset);
}
}
@@ -3333,7 +3344,7 @@ static Create_field * add_hash_field(THD * thd, List<Create_field> *create_list,
}
}
cf->field_name= field_name;
- cf->set_handler(&type_handler_longlong);
+ cf->set_handler(&type_handler_slonglong);
key_info->algorithm= HA_KEY_ALG_LONG_HASH;
create_list->push_back(cf,thd->mem_root);
return cf;
@@ -3351,6 +3362,63 @@ mysql_add_invisible_index(THD *thd, List<Key> *key_list,
key_list->push_back(key, thd->mem_root);
return key;
}
+
+
+bool Type_handler_string::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ /*
+ Set length to 0. It's set to the real column width later for CHAR.
+ It has to be the correct col width for CHAR, as its data are not
+ prefixed with length (unlike blobs).
+ */
+ part->length= 0;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
+bool Type_handler_varchar::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ part->length= 0;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
+bool
+Type_handler_blob_common::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ /*
+ Set keyseg length to 1 for blobs.
+ It's ignored in ft code: the data length is taken from the length prefix.
+ */
+ part->length= 1;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
+static bool
+key_add_part_check_null(const handler *file, KEY *key_info,
+ const Column_definition *sql_field,
+ const Key_part_spec *column)
+{
+ if (!(sql_field->flags & NOT_NULL_FLAG))
+ {
+ key_info->flags|= HA_NULL_PART_KEY;
+ if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
+ {
+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
+ return true;
+ }
+ }
+ return false;
+}
+
+
/*
Preparation for table creation
@@ -3401,12 +3469,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_EXECUTE_IF("test_pseudo_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
- "invisible", &type_handler_long, INVISIBLE_SYSTEM,
+ "invisible", &type_handler_slong, INVISIBLE_SYSTEM,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_completely_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
- "invisible", &type_handler_long, INVISIBLE_FULL,
+ "invisible", &type_handler_slong, INVISIBLE_FULL,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_invisible_index",{
@@ -3419,11 +3487,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
LEX_CSTRING* connect_string = &create_info->connect_string;
if (connect_string->length != 0 &&
connect_string->length > CONNECT_STRING_MAXLEN &&
- (system_charset_info->cset->charpos(system_charset_info,
- connect_string->str,
- (connect_string->str +
- connect_string->length),
- CONNECT_STRING_MAXLEN)
+ (system_charset_info->charpos(connect_string->str,
+ (connect_string->str +
+ connect_string->length),
+ CONNECT_STRING_MAXLEN)
< connect_string->length))
{
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
@@ -3893,136 +3960,92 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
cols2.rewind();
- if (key->type == Key::FULLTEXT)
- {
- if ((sql_field->real_field_type() != MYSQL_TYPE_STRING &&
- sql_field->real_field_type() != MYSQL_TYPE_VARCHAR &&
- !f_is_blob(sql_field->pack_flag)) ||
- sql_field->charset == &my_charset_bin ||
- sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
- (ft_key_charset && sql_field->charset != ft_key_charset))
- {
- my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
- DBUG_RETURN(-1);
- }
- ft_key_charset=sql_field->charset;
- /*
- for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
- code anyway, and 0 (set to column width later) for char's. it has
- to be correct col width for char's, as char data are not prefixed
- with length (unlike blobs, where ft code takes data length from a
- data prefix, ignoring column->length).
- */
- column->length= MY_TEST(f_is_blob(sql_field->pack_flag));
- }
- else
- {
- column->length*= sql_field->charset->mbmaxlen;
+ switch(key->type) {
- if (key->type == Key::SPATIAL)
+ case Key::FULLTEXT:
+ if (sql_field->type_handler()->Key_part_spec_init_ft(column,
+ *sql_field) ||
+ (ft_key_charset && sql_field->charset != ft_key_charset))
{
- if (column->length)
- {
- my_error(ER_WRONG_SUB_KEY, MYF(0));
- DBUG_RETURN(TRUE);
- }
- if (!f_is_geom(sql_field->pack_flag))
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
- DBUG_RETURN(TRUE);
- }
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
+ DBUG_RETURN(-1);
}
+ ft_key_charset= sql_field->charset;
+ break;
- if (f_is_blob(sql_field->pack_flag) ||
- (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
+ case Key::SPATIAL:
+ if (sql_field->type_handler()->Key_part_spec_init_spatial(column,
+ *sql_field) ||
+ sql_field->check_vcol_for_key(thd))
+ DBUG_RETURN(TRUE);
+ if (!(sql_field->flags & NOT_NULL_FLAG))
{
- if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
- {
- my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str,
- file->table_type());
- DBUG_RETURN(TRUE);
- }
- if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
- Field::GEOM_POINT)
- column->length= MAX_LEN_GEOM_POINT_FIELD;
- if (!column->length)
- {
- if (key->type == Key::UNIQUE)
- is_hash_field_needed= true;
- else if (key->type == Key::MULTIPLE)
- column->length= file->max_key_length() + 1;
- else
- {
- my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
- DBUG_RETURN(TRUE);
- }
- }
+ my_message(ER_SPATIAL_CANT_HAVE_NULL,
+ ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
+ DBUG_RETURN(TRUE);
}
-#ifdef HAVE_SPATIAL
- if (key->type == Key::SPATIAL)
- {
- if (!column->length)
- {
- /*
- 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
- Lately we'll extend this code to support more dimensions
- */
- column->length= 4*sizeof(double);
- }
- }
-#endif
+ break;
+
+ case Key::PRIMARY:
if (sql_field->vcol_info)
{
- if (key->type == Key::PRIMARY)
- {
- my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
- DBUG_RETURN(TRUE);
- }
- if (sql_field->vcol_info->flags & VCOL_NOT_STRICTLY_DETERMINISTIC)
- {
- /* use check_expression() to report an error */
- check_expression(sql_field->vcol_info, &sql_field->field_name,
- VCOL_GENERATED_STORED);
- DBUG_ASSERT(thd->is_error());
- DBUG_RETURN(TRUE);
- }
+ my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
+ DBUG_RETURN(TRUE);
}
- if (!(sql_field->flags & NOT_NULL_FLAG))
- {
- if (key->type == Key::PRIMARY)
- {
- /* Implicitly set primary key fields to NOT NULL for ISO conf. */
- sql_field->flags|= NOT_NULL_FLAG;
- sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
- null_fields--;
- }
- else
- {
- key_info->flags|= HA_NULL_PART_KEY;
- if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
- {
- my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
- DBUG_RETURN(TRUE);
- }
- if (key->type == Key::SPATIAL)
- {
- my_message(ER_SPATIAL_CANT_HAVE_NULL,
- ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
- DBUG_RETURN(TRUE);
- }
- }
- }
- if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
- {
- if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
- auto_increment--; // Field is used
- }
+ if (sql_field->type_handler()->Key_part_spec_init_primary(column,
+ *sql_field,
+ file))
+ DBUG_RETURN(TRUE);
+ if (!(sql_field->flags & NOT_NULL_FLAG))
+ {
+ /* Implicitly set primary key fields to NOT NULL for ISO conf. */
+ sql_field->flags|= NOT_NULL_FLAG;
+ sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
+ null_fields--;
+ }
+ break;
+
+ case Key::MULTIPLE:
+ if (sql_field->type_handler()->Key_part_spec_init_multiple(column,
+ *sql_field,
+ file) ||
+ sql_field->check_vcol_for_key(thd) ||
+ key_add_part_check_null(file, key_info, sql_field, column))
+ DBUG_RETURN(TRUE);
+ break;
+
+ case Key::FOREIGN_KEY:
+ if (sql_field->type_handler()->Key_part_spec_init_foreign(column,
+ *sql_field,
+ file) ||
+ sql_field->check_vcol_for_key(thd) ||
+ key_add_part_check_null(file, key_info, sql_field, column))
+ DBUG_RETURN(TRUE);
+ break;
+
+ case Key::UNIQUE:
+ if (sql_field->type_handler()->Key_part_spec_init_unique(column,
+ *sql_field, file,
+ &is_hash_field_needed) ||
+ sql_field->check_vcol_for_key(thd) ||
+ key_add_part_check_null(file, key_info, sql_field, column))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+
+ if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
+ {
+ DBUG_ASSERT(key->type != Key::FULLTEXT);
+ DBUG_ASSERT(key->type != Key::SPATIAL);
+ if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
+ auto_increment--; // Field is used
}
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
- uint key_part_length= sql_field->key_length;
+ uint key_part_length= sql_field->type_handler()->
+ calc_key_length(*sql_field);
if (column->length)
{
@@ -4115,19 +4138,14 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
/* Use packed keys for long strings on the first column */
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
!((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
- (key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->real_field_type() == MYSQL_TYPE_STRING ||
- sql_field->real_field_type() == MYSQL_TYPE_VARCHAR ||
- f_is_blob(sql_field->pack_flag))) && !is_hash_field_needed)
- {
- if ((column_nr == 0 && f_is_blob(sql_field->pack_flag)) ||
- sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
- key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
- else
- key_info->flags|= HA_PACK_KEY;
+ (key_part_length >= KEY_DEFAULT_PACK_LENGTH) &&
+ !is_hash_field_needed)
+ {
+ key_info->flags|= sql_field->type_handler()->KEY_pack_flags(column_nr);
}
/* Check if the key segment is partial, set the key flag accordingly */
- if (key_part_length != sql_field->key_length &&
+ if (key_part_length != sql_field->type_handler()->
+ calc_key_length(*sql_field) &&
key_part_length != sql_field->type_handler()->max_octet_length())
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
@@ -4392,8 +4410,9 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
uint err_code, const char *name)
{
DBUG_ENTER("validate_comment_length");
- size_t tmp_len= my_charpos(system_charset_info, comment->str,
- comment->str + comment->length, max_len);
+ size_t tmp_len= system_charset_info->charpos(comment->str,
+ comment->str + comment->length,
+ max_len);
if (tmp_len < comment->length)
{
if (thd->is_strict_mode())
@@ -4489,7 +4508,7 @@ bool Column_definition::prepare_blob_field(THD *thd)
set_handler(Type_handler::blob_type_handler((uint) length));
pack_length= type_handler()->calc_pack_length(0);
}
- length= key_length= 0;
+ length= 0;
}
DBUG_RETURN(0);
}
@@ -5538,7 +5557,8 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
{
if (rename_file_ext(from,to,reg_ext))
error= my_errno;
- (void) file->ha_create_partitioning_metadata(to, from, CHF_RENAME_FLAG);
+ if (!(flags & NO_PAR_TABLE))
+ (void) file->ha_create_partitioning_metadata(to, from, CHF_RENAME_FLAG);
}
else if (!file || likely(!(error=file->ha_rename_table(from_base, to_base))))
{
@@ -5562,7 +5582,6 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
my_error(ER_BAD_DB_ERROR, MYF(0), new_db->str);
else if (error)
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
-
else if (!(flags & FN_IS_TMP))
mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name);
@@ -5663,6 +5682,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
local_create_info.init(create_info->create_like_options());
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;
if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
&local_alter_info, &local_alter_ctx))
goto err;
@@ -5840,8 +5860,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
goto err;
/*
- As the reference table is temporary and may not exist on slave, we must
- force the ENGINE to be present into CREATE TABLE.
+ As the reference table is temporary and may not exist on slave, we
+ must force the ENGINE to be present into CREATE TABLE.
*/
create_info->used_fields|= HA_CREATE_USED_ENGINE;
@@ -6147,7 +6167,7 @@ drop_create_field:
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
- acol->name, (*f_ptr)->field_name.str) == 0)
+ acol->name.str, (*f_ptr)->field_name.str) == 0)
break;
}
if (unlikely(*f_ptr == NULL))
@@ -6155,7 +6175,7 @@ drop_create_field:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR,
ER_THD(thd, ER_BAD_FIELD_ERROR),
- acol->name, table->s->table_name.str);
+ acol->name.str, table->s->table_name.str);
it.remove();
if (alter_info->alter_list.is_empty())
{
@@ -7562,11 +7582,10 @@ static bool mysql_inplace_alter_table(THD *thd,
{
Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN | MYSQL_OPEN_IGNORE_KILLED);
handlerton *db_type= table->s->db_type();
- MDL_ticket *mdl_ticket= table->mdl_ticket;
Alter_info *alter_info= ha_alter_info->alter_info;
bool reopen_tables= false;
bool res;
-
+ handlerton *hton;
DBUG_ENTER("mysql_inplace_alter_table");
/* Downgrade DDL lock while we are waiting for exclusive lock below */
@@ -7629,8 +7648,7 @@ static bool mysql_inplace_alter_table(THD *thd,
goto cleanup;
tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE,
- table->s->db.str, table->s->table_name.str,
- false);
+ table->s->db.str, table->s->table_name.str);
}
/*
@@ -7773,6 +7791,28 @@ static bool mysql_inplace_alter_table(THD *thd,
}
}
+ /* Notify the engine that the table definition has changed */
+
+ hton= table->file->ht;
+ if (hton->notify_tabledef_changed)
+ {
+ char db_buff[FN_REFLEN], table_buff[FN_REFLEN];
+ LEX_CSTRING tmp_db, tmp_table;
+ tmp_db.str= db_buff;
+ tmp_table.str= table_buff;
+ tmp_db.length= tablename_to_filename(table_list->db.str,
+ db_buff, sizeof(db_buff));
+ tmp_table.length= tablename_to_filename(table_list->table_name.str,
+ table_buff, sizeof(table_buff));
+ if ((hton->notify_tabledef_changed)(hton, &tmp_db, &tmp_table,
+ table->s->frm_image,
+ &table->s->tabledef_version))
+ {
+ my_error(HA_ERR_INCOMPATIBLE_DEFINITION, MYF(0));
+ DBUG_RETURN(true);
+ }
+ }
+
close_all_tables_for_name(thd, table->s,
alter_ctx->is_table_renamed() ?
HA_EXTRA_PREPARE_FOR_RENAME :
@@ -7797,30 +7837,12 @@ static bool mysql_inplace_alter_table(THD *thd,
DBUG_RETURN(true);
}
- table_list->mdl_request.ticket= mdl_ticket;
- if (open_table(thd, table_list, &ot_ctx))
- DBUG_RETURN(true);
-
- /*
- Tell the handler that the changed frm is on disk and table
- has been re-opened
- */
- table_list->table->file->ha_notify_table_changed();
-
- /*
- We might be going to reopen table down on the road, so we have to
- restore state of the TABLE object which we used for obtaining of
- handler object to make it usable for later reopening.
- */
- close_thread_table(thd, &thd->open_tables);
- table_list->table= NULL;
-
// Rename altered table if requested.
if (alter_ctx->is_table_renamed())
{
// Remove TABLE and TABLE_SHARE for old name from TDC.
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
- alter_ctx->db.str, alter_ctx->table_name.str, false);
+ alter_ctx->db.str, alter_ctx->table_name.str);
if (mysql_rename_table(db_type, &alter_ctx->db, &alter_ctx->table_name,
&alter_ctx->new_db, &alter_ctx->new_alias, 0))
@@ -7968,6 +7990,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
List<Create_field> new_create_list;
/* New key definitions are added here */
List<Key> new_key_list;
+ List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -8108,24 +8131,6 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
- /*
- If we are doing a rename of a column, update all references in virtual
- column expressions, constraints and defaults to use the new column name
- */
- if (alter_info->flags & ALTER_RENAME_COLUMN)
- {
- if (field->vcol_info)
- field->vcol_info->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- if (field->check_constraint)
- field->check_constraint->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- if (field->default_value)
- field->default_value->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- table->m_needs_reopen= 1; // because new column name is on thd->mem_root
- }
-
/* Check if field is changed */
def_it.rewind();
while ((def=def_it++))
@@ -8199,19 +8204,61 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
while ((alter=alter_it++))
{
if (!my_strcasecmp(system_charset_info,field->field_name.str,
- alter->name))
+ alter->name.str))
break;
}
if (alter)
{
- if ((def->default_value= alter->default_value))
- def->flags&= ~NO_DEFAULT_VALUE_FLAG;
+ if (alter->is_rename())
+ {
+ def->change= alter->name;
+ def->field_name= alter->new_name;
+ column_rename_param.fields.push_back(def);
+ }
else
- def->flags|= NO_DEFAULT_VALUE_FLAG;
+ {
+ if ((def->default_value= alter->default_value))
+ def->flags&= ~NO_DEFAULT_VALUE_FLAG;
+ else
+ def->flags|= NO_DEFAULT_VALUE_FLAG;
+ }
alter_it.remove();
}
}
}
+
+ /*
+ If we are doing a rename of a column, update all references in virtual
+ column expressions, constraints and defaults to use the new column name
+ */
+ if (alter_info->flags & ALTER_RENAME_COLUMN)
+ {
+ alter_it.rewind();
+ Alter_column *alter;
+ while ((alter=alter_it++))
+ {
+ if (alter->is_rename())
+ {
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), alter->name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+ }
+ for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
+ {
+ if (field->vcol_info)
+ field->vcol_info->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ if (field->check_constraint)
+ field->check_constraint->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ if (field->default_value)
+ field->default_value->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ }
+ table->m_needs_reopen= 1; // because new column name is on thd->mem_root
+ }
+
dropped_sys_vers_fields &= VERS_SYSTEM_FIELD;
if ((dropped_sys_vers_fields ||
alter_info->flags & ALTER_DROP_PERIOD) &&
@@ -8265,15 +8312,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
flag to allow ALTER TABLE only if the table to be altered is empty.
*/
- if ((def->real_field_type() == MYSQL_TYPE_DATE ||
- def->real_field_type() == MYSQL_TYPE_NEWDATE ||
- def->real_field_type() == MYSQL_TYPE_DATETIME ||
- def->real_field_type() == MYSQL_TYPE_DATETIME2) &&
- !alter_ctx->datetime_field &&
- !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
- thd->variables.sql_mode & MODE_NO_ZERO_DATE)
- {
- alter_ctx->datetime_field= def;
+ if (!alter_ctx->implicit_default_value_error_field &&
+ !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
+ def->type_handler()->validate_implicit_default_value(thd, *def))
+ {
+ alter_ctx->implicit_default_value_error_field= def;
alter_ctx->error_if_not_empty= TRUE;
}
if (!def->after.str)
@@ -8331,7 +8374,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
while ((alter=alter_it++))
{
if (!my_strcasecmp(system_charset_info,def->field_name.str,
- alter->name))
+ alter->name.str))
break;
}
if (alter)
@@ -8346,7 +8389,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (unlikely(alter_info->alter_list.elements))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
- alter_info->alter_list.head()->name, table->s->table_name.str);
+ alter_info->alter_list.head()->name.str, table->s->table_name.str);
goto err;
}
if (unlikely(!new_create_list.elements))
@@ -8396,6 +8439,39 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
+ /* If this index is to stay in the table check if it has to be renamed. */
+ List_iterator<Alter_rename_key> rename_key_it(rename_key_list);
+ Alter_rename_key *rename_key;
+
+ while ((rename_key= rename_key_it++))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, rename_key->old_name.str))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name.str);
+ goto err;
+ }
+ else if (!my_strcasecmp(system_charset_info, rename_key->new_name.str,
+ primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name.str);
+ goto err;
+ }
+
+ key_name= rename_key->new_name.str;
+ rename_key_it.remove();
+ /*
+ If the user has explicitly renamed the key, we should no longer
+ treat it as generated. Otherwise this key might be automatically
+ dropped by mysql_prepare_create_table() and this will confuse
+ code in fill_alter_inplace_info().
+ */
+ key_info->flags&= ~HA_GENERATED_KEY;
+ break;
+ }
+ }
+
if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
{
setup_keyinfo_hash(key_info);
@@ -8722,6 +8798,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
+ if (rename_key_list.elements)
+ {
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list.head()->old_name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+
if (!create_info->comment.str)
{
create_info->comment.str= table->s->comment.str;
@@ -9114,8 +9197,8 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
ref_table= tbuf;
}
- mdl_request.init(MDL_key::TABLE, ref_db, ref_table, MDL_SHARED_NO_WRITE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, ref_db, ref_table,
+ MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
DBUG_RETURN(true);
@@ -9386,6 +9469,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
Alter_info *alter_info,
uint order_num, ORDER *order, bool ignore)
{
+ bool engine_changed;
DBUG_ENTER("mysql_alter_table");
/*
@@ -9444,6 +9528,17 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
&alter_prelocking_strategy);
thd->open_options&= ~HA_OPEN_FOR_ALTER;
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ (thd->lex->sql_command == SQLCOM_ALTER_TABLE ||
+ thd->lex->sql_command == SQLCOM_CREATE_INDEX ||
+ thd->lex->sql_command == SQLCOM_DROP_INDEX) &&
+ !wsrep_should_replicate_ddl(thd, table_list->table->s->db_type()->db_type))
+ DBUG_RETURN(true);
+#endif
+
+ DEBUG_SYNC(thd, "alter_table_after_open_tables");
+
TABLE *table= table_list->table;
bool versioned= table && table->versioned();
@@ -9528,9 +9623,9 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
MDL_request_list mdl_requests;
MDL_request target_db_mdl_request;
- target_mdl_request.init(MDL_key::TABLE,
- alter_ctx.new_db.str, alter_ctx.new_name.str,
- MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&target_mdl_request, MDL_key::TABLE,
+ alter_ctx.new_db.str, alter_ctx.new_name.str,
+ MDL_EXCLUSIVE, MDL_TRANSACTION);
mdl_requests.push_front(&target_mdl_request);
/*
@@ -9540,9 +9635,9 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
*/
if (alter_ctx.is_database_changed())
{
- target_db_mdl_request.init(MDL_key::SCHEMA, alter_ctx.new_db.str, "",
- MDL_INTENTION_EXCLUSIVE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&target_db_mdl_request, MDL_key::SCHEMA,
+ alter_ctx.new_db.str, "", MDL_INTENTION_EXCLUSIVE,
+ MDL_TRANSACTION);
mdl_requests.push_front(&target_db_mdl_request);
}
@@ -9789,8 +9884,7 @@ do_continue:;
bool fast_alter_partition= false;
{
if (prep_alter_part_table(thd, table, alter_info, create_info,
- &alter_ctx, &partition_changed,
- &fast_alter_partition))
+ &partition_changed, &fast_alter_partition))
{
DBUG_RETURN(true);
}
@@ -10190,7 +10284,7 @@ do_continue:;
if (table->s->tmp_table != NO_TMP_TABLE)
{
/* in case of alter temp table send the tracker in OK packet */
- SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
+ thd->session_tracker.state_change.mark_as_changed(thd);
}
/*
@@ -10273,6 +10367,23 @@ do_continue:;
}
/*
+ Check if file names for the engine are unique. If we change engine
+ and file names are unique then we don't need to rename the original
+ table to a temporary name during the rename phase
+
+ File names are unique if engine changed and
+ - Either new or old engine does not store the table in files
+ - Neither old or new engine uses files from another engine
+ The above is mainly true for the sequence and the partition engine.
+ */
+ engine_changed= ((new_table->file->ht != table->file->ht) &&
+ (((!(new_table->file->ha_table_flags() & HA_FILE_BASED) ||
+ !(table->file->ha_table_flags() & HA_FILE_BASED))) ||
+ (!(table->file->ha_table_flags() & HA_REUSES_FILE_NAMES) &&
+ !(new_table->file->ha_table_flags() &
+ HA_REUSES_FILE_NAMES))));
+
+ /*
Close the intermediate table that will be the new table, but do
not delete it! Even though MERGE tables do not have their children
attached here it is safe to call THD::drop_temporary_table().
@@ -10315,23 +10426,39 @@ do_continue:;
/*
Rename the old table to temporary name to have a backup in case
anything goes wrong while renaming the new table.
+ We only have to do this if name of the table is not changed.
+ If we are changing to use another table handler, we don't
+ have to do the rename as the table names will not interfer.
*/
char backup_name_buff[FN_LEN];
LEX_CSTRING backup_name;
backup_name.str= backup_name_buff;
- backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff),
- "%s2-%lx-%lx", tmp_file_prefix,
+ DBUG_PRINT("info", ("is_table_renamed: %d engine_changed: %d",
+ alter_ctx.is_table_renamed(), engine_changed));
+
+ if (!alter_ctx.is_table_renamed())
+ {
+ backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff),
+ "%s2-%lx-%lx", tmp_file_prefix,
current_pid, (long) thd->thread_id);
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, backup_name_buff);
- if (mysql_rename_table(old_db_type, &alter_ctx.db, &alter_ctx.table_name,
- &alter_ctx.db, &backup_name, FN_TO_IS_TMP))
+ if (lower_case_table_names)
+ my_casedn_str(files_charset_info, backup_name_buff);
+ if (mysql_rename_table(old_db_type, &alter_ctx.db, &alter_ctx.table_name,
+ &alter_ctx.db, &backup_name,
+ FN_TO_IS_TMP |
+ (engine_changed ? NO_HA_TABLE | NO_PAR_TABLE : 0)))
+ {
+ // Rename to temporary name failed, delete the new table, abort ALTER.
+ (void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
+ &alter_ctx.tmp_name, FN_IS_TMP);
+ goto err_with_mdl;
+ }
+ }
+ else
{
- // Rename to temporary name failed, delete the new table, abort ALTER.
- (void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
- &alter_ctx.tmp_name, FN_IS_TMP);
- goto err_with_mdl;
+ /* The original table is the backup */
+ backup_name= alter_ctx.table_name;
}
// Rename the new table to the correct name.
@@ -10343,10 +10470,15 @@ do_continue:;
(void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
&alter_ctx.tmp_name, FN_IS_TMP);
- // Restore the backup of the original table to the old name.
- (void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
- &alter_ctx.db, &alter_ctx.alias,
- FN_FROM_IS_TMP | NO_FK_CHECKS);
+ if (!alter_ctx.is_table_renamed())
+ {
+ // Restore the backup of the original table to the old name.
+ (void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
+ &alter_ctx.db, &alter_ctx.alias,
+ FN_FROM_IS_TMP | NO_FK_CHECKS |
+ (engine_changed ? NO_HA_TABLE | NO_PAR_TABLE :
+ 0));
+ }
goto err_with_mdl;
}
@@ -10366,7 +10498,9 @@ do_continue:;
// Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
&alter_ctx.db, &alter_ctx.alias,
- FN_FROM_IS_TMP | NO_FK_CHECKS);
+ FN_FROM_IS_TMP | NO_FK_CHECKS |
+ (engine_changed ? NO_HA_TABLE | NO_PAR_TABLE :
+ 0));
goto err_with_mdl;
}
rename_table_in_stat_tables(thd, &alter_ctx.db, &alter_ctx.alias,
@@ -10374,7 +10508,19 @@ do_continue:;
}
// ALTER TABLE succeeded, delete the backup of the old table.
- if (quick_rm_table(thd, old_db_type, &alter_ctx.db, &backup_name, FN_IS_TMP))
+ error= quick_rm_table(thd, old_db_type, &alter_ctx.db, &backup_name,
+ FN_IS_TMP |
+ (engine_changed ? NO_HA_TABLE | NO_PAR_TABLE: 0));
+ if (engine_changed)
+ {
+ /* the .frm file was removed but not the original table */
+ error|= quick_rm_table(thd, old_db_type, &alter_ctx.db,
+ &alter_ctx.table_name,
+ NO_FRM_RENAME |
+ (engine_changed ? 0 : FN_IS_TMP));
+ }
+
+ if (error)
{
/*
The fact that deletion of the backup failed is not critical
@@ -10421,6 +10567,7 @@ end_temporary:
DBUG_RETURN(false);
err_new_table_cleanup:
+ DBUG_PRINT("error", ("err_new_table_cleanup"));
my_free(const_cast<uchar*>(frm.str));
/*
No default value was provided for a DATE/DATETIME field, the
@@ -10431,30 +10578,8 @@ err_new_table_cleanup:
if (unlikely(alter_ctx.error_if_not_empty &&
thd->get_stmt_da()->current_row_for_warning()))
{
- const char *f_val= "0000-00-00";
- const char *f_type= "date";
- switch (alter_ctx.datetime_field->real_field_type())
- {
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- break;
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_DATETIME2:
- f_val= "0000-00-00 00:00:00";
- f_type= "datetime";
- break;
- default:
- /* Shouldn't get here. */
- DBUG_ASSERT(0);
- }
- bool save_abort_on_warning= thd->abort_on_warning;
- thd->abort_on_warning= true;
- thd->push_warning_truncated_value_for_field(Sql_condition::WARN_LEVEL_WARN,
- f_type, f_val,
- new_table->s,
- alter_ctx.datetime_field->
- field_name.str);
- thd->abort_on_warning= save_abort_on_warning;
+ Abort_on_warning_instant_set aws(thd, true);
+ alter_ctx.report_implicit_default_value_error(thd, new_table->s);
}
if (new_table)
@@ -10470,11 +10595,16 @@ err_new_table_cleanup:
DBUG_RETURN(true);
err_with_mdl_after_alter:
+ DBUG_PRINT("error", ("err_with_mdl_after_alter"));
/* the table was altered. binlog the operation */
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
thd->is_current_stmt_binlog_format_row() &&
(create_info->tmp_table())));
- write_bin_log(thd, true, thd->query(), thd->query_length());
+ /*
+ We can't reset error as we will return 'true' below and the server
+ expects that error is set
+ */
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err_with_mdl:
/*
@@ -10606,6 +10736,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
+ mysql_stage_set_work_estimated(thd->m_stage_progress_psi, from->file->stats.records);
+
List_iterator<Create_field> it(create);
Create_field *def;
copy_end=copy;
@@ -10657,14 +10789,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
- bool save_abort_on_warning= thd->abort_on_warning;
- thd->abort_on_warning= false;
+ Abort_on_warning_instant_set aws(thd, false);
my_snprintf(warn_buff, sizeof(warn_buff),
"ORDER BY ignored as there is a user-defined clustered index"
" in the table '%-.192s'", from->s->table_name.str);
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
warn_buff);
- thd->abort_on_warning= save_abort_on_warning;
}
else
{
@@ -10708,7 +10838,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
from->file->column_bitmaps_signal();
- THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
/* Add virtual columns to vcol_set to ensure they are updated */
@@ -10854,7 +10983,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
}
else
+ {
+ DEBUG_SYNC(thd, "copy_data_between_tables_before");
found_count++;
+ mysql_stage_set_work_completed(thd->m_stage_progress_psi, found_count);
+ }
thd->get_stmt_da()->inc_current_row_for_warning();
}
@@ -10947,6 +11080,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
bzero((char*) &create_info, sizeof(create_info));
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);
@@ -11226,6 +11360,13 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
goto end_with_restore_list;
}
+ /*
+ Since CREATE_INFO is not full without Alter_info, it is better to pass them
+ as a signle parameter. TODO: remove alter_info argument where create_info is
+ passed.
+ */
+ create_info.alter_info= &alter_info;
+
/* Check privileges */
if ((res= create_table_precheck(thd, select_tables, create_table)))
goto end_with_restore_list;
@@ -11444,7 +11585,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
(!thd->is_current_stmt_binlog_format_row() ||
!create_info.tmp_table()))
{
- WSREP_TO_ISOLATION_BEGIN(create_table->db.str, create_table->table_name.str, NULL);
+ WSREP_TO_ISOLATION_BEGIN_CREATE(create_table->db.str, create_table->table_name.str,
+ create_table, &create_info);
}
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
@@ -11458,7 +11600,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
ON then send session state notification in OK packet */
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
{
- SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
+ thd->session_tracker.state_change.mark_as_changed(thd);
}
my_ok(thd);
}