diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 127 |
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()); } |