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.cc453
1 files changed, 251 insertions, 202 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f736de24bed..9d540d18c7d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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
@@ -2735,7 +2735,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;
@@ -2743,11 +2744,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)
@@ -2853,7 +2856,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;
@@ -3350,7 +3353,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;
@@ -3368,6 +3371,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
@@ -3418,12 +3478,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",{
@@ -3910,130 +3970,85 @@ 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;
@@ -5528,7 +5543,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))))
{
@@ -5552,7 +5568,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);
@@ -5830,8 +5845,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;
@@ -7560,11 +7575,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 */
@@ -7771,6 +7785,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 :
@@ -7795,24 +7831,6 @@ 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())
{
@@ -8263,15 +8281,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->flags & VERS_SYSTEM_FIELD &&
@@ -9368,6 +9382,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");
/*
@@ -10254,6 +10269,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().
@@ -10296,23 +10328,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.
@@ -10324,10 +10372,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;
}
@@ -10347,7 +10400,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,
@@ -10355,7 +10410,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
@@ -10402,6 +10469,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
@@ -10412,30 +10480,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)
@@ -10451,11 +10497,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:
/*
@@ -10638,14 +10689,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
{