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.cc127
1 files changed, 91 insertions, 36 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 0662747d6b2..06c09cf4ebf 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -37,7 +37,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted,
- enum enum_enable_or_disable keys_onoff);
+ enum enum_enable_or_disable keys_onoff,
+ bool error_if_not_empty);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
@@ -232,18 +233,6 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
}
/*
- Return values for compare_tables().
- If you make compare_tables() non-static, move them to a header file.
-*/
-
-enum enum_compare_tables_result
-{
- ALTER_TABLE_METADATA_ONLY= 0,
- ALTER_TABLE_DATA_CHANGED= 1,
- ALTER_TABLE_INDEX_CHANGED= 2
-};
-
-/*
--------------------------------------------------------------------------
MODULE: DDL log
@@ -319,11 +308,11 @@ static bool read_ddl_log_file_entry(uint entry_no)
{
bool error= FALSE;
File file_id= global_ddl_log.file_id;
- char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
+ uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
uint io_size= global_ddl_log.io_size;
DBUG_ENTER("read_ddl_log_file_entry");
- if (my_pread(file_id, (byte*)file_entry_buf, io_size, io_size * entry_no,
+ if (my_pread(file_id, file_entry_buf, io_size, io_size * entry_no,
MYF(MY_WME)) != io_size)
error= TRUE;
DBUG_RETURN(error);
@@ -347,7 +336,7 @@ static bool write_ddl_log_file_entry(uint entry_no)
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
DBUG_ENTER("write_ddl_log_file_entry");
- if (my_pwrite(file_id, (byte*)file_entry_buf,
+ if (my_pwrite(file_id, (uchar*)file_entry_buf,
IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE)
error= TRUE;
DBUG_RETURN(error);
@@ -560,7 +549,9 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
int error= TRUE;
char to_path[FN_REFLEN];
char from_path[FN_REFLEN];
+#ifdef WITH_PARTITION_STORAGE_ENGINE
char *par_ext= (char*)".par";
+#endif
handlerton *hton;
DBUG_ENTER("execute_ddl_log_action");
@@ -1143,13 +1134,13 @@ void release_ddl_log()
while (used_list)
{
DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
- my_free((char*)used_list, MYF(0));
+ my_free(used_list, MYF(0));
used_list= tmp;
}
while (free_list)
{
DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
- my_free((char*)free_list, MYF(0));
+ my_free(free_list, MYF(0));
free_list= tmp;
}
close_ddl_log();
@@ -1268,13 +1259,13 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
handlers that have the main version of the frm file stored in the
handler.
*/
- const void *data= 0;
- uint length= 0;
+ uchar *data;
+ size_t length;
if (readfrm(shadow_path, &data, &length) ||
packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len))
{
- my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*)lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR));
mem_alloc_error(length);
error= 1;
goto end;
@@ -2926,7 +2917,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE);
}
/* Sort keys in optimized order */
- qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY),
+ qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
(qsort_cmp) sort_keys);
create_info->null_bits= null_fields;
@@ -3478,7 +3469,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
/* Wait for any database locks */
pthread_mutex_lock(&LOCK_lock_db);
while (!thd->killed &&
- hash_search(&lock_db_cache,(byte*) db, strlen(db)))
+ hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
{
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
pthread_mutex_lock(&LOCK_lock_db);
@@ -4021,7 +4012,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->next_global= 0;
save_next_local= table->next_local;
table->next_local= 0;
- select->table_list.first= (byte*)table;
+ select->table_list.first= (uchar*)table;
/*
Time zone tables and SP tables can be add to lex->query_tables list,
so it have to be prepared.
@@ -4918,7 +4909,7 @@ compare_tables(TABLE *table,
Alter_info *alter_info,
HA_CREATE_INFO *create_info,
uint order_num,
- enum enum_compare_tables_result *need_copy_table,
+ enum_alter_table_change_level *need_copy_table,
KEY **key_info_buffer,
uint **index_drop_buffer, uint *index_drop_count,
uint **index_add_buffer, uint *index_add_count)
@@ -5313,7 +5304,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY)
{
- char *tablespace= thd->alloc(FN_LEN);
+ char *tablespace= static_cast<char *>(thd->alloc(FN_LEN));
/*
Regular alter table of disk stored table (no tablespace/storage change)
Copy tablespace name
@@ -5411,6 +5402,23 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name);
goto err;
}
+ /*
+ Check that the DATE/DATETIME not null field we are going to add is
+ either has a default value or the '0000-00-00' is allowed by the
+ set sql mode.
+ 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->sql_type == MYSQL_TYPE_DATE ||
+ def->sql_type == MYSQL_TYPE_NEWDATE ||
+ def->sql_type == MYSQL_TYPE_DATETIME) &&
+ !alter_info->datetime_field &&
+ !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
+ thd->variables.sql_mode & MODE_NO_ZERO_DATE)
+ {
+ alter_info->datetime_field= def;
+ alter_info->error_if_not_empty= TRUE;
+ }
if (!def->after)
new_create_list.push_back(def);
else if (def->after == first_keyword)
@@ -5430,6 +5438,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
goto err;
}
find_it.after(def); // Put element after this
+ alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
}
}
if (alter_info->alter_list.elements)
@@ -5671,7 +5680,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
handlerton *old_db_type, *new_db_type, *save_old_db_type;
legacy_db_type table_type;
frm_type_enum frm_type;
- enum_compare_tables_result need_copy_table= ALTER_TABLE_METADATA_ONLY;
+ enum_alter_table_change_level need_copy_table= ALTER_TABLE_METADATA_ONLY;
#ifdef WITH_PARTITION_STORAGE_ENGINE
uint fast_alter_partition= 0;
bool partition_changed= FALSE;
@@ -6055,6 +6064,8 @@ view_err:
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
goto err;
+
+ need_copy_table= alter_info->change_level;
set_table_default_charset(thd, create_info, db);
@@ -6067,14 +6078,18 @@ view_err:
need_copy_table= ALTER_TABLE_DATA_CHANGED;
else
{
+ enum_alter_table_change_level need_copy_table_res;
/* Check how much the tables differ. */
if (compare_tables(table, alter_info,
create_info, order_num,
- &need_copy_table,
+ &need_copy_table_res,
&key_info_buffer,
&index_drop_buffer, &index_drop_count,
&index_add_buffer, &index_add_count))
goto err;
+
+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
+ need_copy_table= need_copy_table_res;
}
/*
@@ -6309,7 +6324,8 @@ view_err:
error= copy_data_between_tables(table, new_table,
alter_info->create_list, ignore,
order_num, order, &copied, &deleted,
- alter_info->keys_onoff);
+ alter_info->keys_onoff,
+ alter_info->error_if_not_empty);
}
else
{
@@ -6438,7 +6454,7 @@ view_err:
{
/* Close the intermediate table that will be the new table */
intern_close_table(new_table);
- my_free((gptr) new_table,MYF(0));
+ my_free(new_table,MYF(0));
}
VOID(pthread_mutex_lock(&LOCK_open));
if (error)
@@ -6619,7 +6635,7 @@ view_err:
if (t_table)
{
intern_close_table(t_table);
- my_free((char*) t_table, MYF(0));
+ my_free(t_table, MYF(0));
}
else
sql_print_warning("Could not open table %s.%s after rename\n",
@@ -6661,6 +6677,38 @@ err1:
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
err:
+ /*
+ No default value was provided for a DATE/DATETIME field, the
+ current sql_mode doesn't allow the '0000-00-00' value and
+ the table to be altered isn't empty.
+ Report error here.
+ */
+ if (alter_info->error_if_not_empty && thd->row_count)
+ {
+ const char *f_val= 0;
+ enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
+ switch (alter_info->datetime_field->sql_type)
+ {
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_NEWDATE:
+ f_val= "0000-00-00";
+ t_type= MYSQL_TIMESTAMP_DATE;
+ break;
+ case MYSQL_TYPE_DATETIME:
+ f_val= "0000-00-00 00:00:00";
+ t_type= MYSQL_TIMESTAMP_DATETIME;
+ break;
+ default:
+ /* Shouldn't get here. */
+ DBUG_ASSERT(0);
+ }
+ bool save_abort_on_warning= thd->abort_on_warning;
+ thd->abort_on_warning= TRUE;
+ make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ f_val, strlength(f_val), t_type,
+ alter_info->datetime_field->field_name);
+ thd->abort_on_warning= save_abort_on_warning;
+ }
if (name_lock)
{
pthread_mutex_lock(&LOCK_open);
@@ -6690,7 +6738,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
uint order_num, ORDER *order,
ha_rows *copied,
ha_rows *deleted,
- enum enum_enable_or_disable keys_onoff)
+ enum enum_enable_or_disable keys_onoff,
+ bool error_if_not_empty)
{
int error;
Copy_field *copy,*copy_end;
@@ -6802,6 +6851,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
break;
}
thd->row_count++;
+ /* Return error if source table isn't empty. */
+ if (error_if_not_empty)
+ {
+ error= 1;
+ break;
+ }
if (to->next_number_field)
{
if (auto_increment_field_copied)
@@ -6815,7 +6870,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
copy_ptr->do_copy(copy_ptr);
}
prev_insert_id= to->file->next_insert_id;
- error=to->file->write_row((byte*) to->record[0]);
+ error=to->file->write_row(to->record[0]);
to->auto_increment_field_not_null= FALSE;
if (error)
{
@@ -6996,10 +7051,10 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
{
String tmp;
f->val_str(&tmp);
- row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length());
+ row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
}
else
- row_crc= my_checksum(row_crc, (byte*) f->ptr,
+ row_crc= my_checksum(row_crc, f->ptr,
f->pack_length());
}