#include "mysql_priv.h"#include <hash.h>#include <myisam.h>#include <my_dir.h>#include "sp_head.h"#include "sql_trigger.h"#include "sql_show.h"Include dependency graph for sql_table.cc:

Go to the source code of this file.
Classes | |
| struct | st_global_ddl_log |
Defines | |
| #define | MYSQL50_TABLE_NAME_PREFIX "#mysql50#" |
| #define | MYSQL50_TABLE_NAME_PREFIX_LENGTH 9 |
| #define | ALTER_TABLE_DATA_CHANGED 1 |
| #define | ALTER_TABLE_INDEX_CHANGED 2 |
| #define | DDL_LOG_ENTRY_TYPE_POS 0 |
| #define | DDL_LOG_ACTION_TYPE_POS 1 |
| #define | DDL_LOG_PHASE_POS 2 |
| #define | DDL_LOG_NEXT_ENTRY_POS 4 |
| #define | DDL_LOG_NAME_POS 8 |
| #define | DDL_LOG_NUM_ENTRY_POS 0 |
| #define | DDL_LOG_NAME_LEN_POS 4 |
| #define | DDL_LOG_IO_SIZE_POS 8 |
Typedefs | |
| typedef st_global_ddl_log | GLOBAL_DDL_LOG |
Functions | |
| static bool | check_if_keyname_exists (const char *name, KEY *start, KEY *end) |
| static char * | make_unique_key_name (const char *field_name, KEY *start, KEY *end) |
| 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) |
| static bool | prepare_blob_field (THD *thd, create_field *sql_field) |
| static bool | check_engine (THD *thd, const char *table_name, HA_CREATE_INFO *create_info) |
| static int | mysql_prepare_table (THD *thd, HA_CREATE_INFO *create_info, List< create_field > *fields, List< Key > *keys, bool tmp_table, uint *db_options, handler *file, KEY **key_info_buffer, uint *key_count, int select_field_count) |
| uint | filename_to_tablename (const char *from, char *to, uint to_length) |
| uint | tablename_to_filename (const char *from, char *to, uint to_length) |
| uint | build_table_filename (char *buff, size_t bufflen, const char *db, const char *table_name, const char *ext, uint flags) |
| uint | build_tmptable_filename (THD *thd, char *buff, size_t bufflen) |
| static int | mysql_copy_create_list (List< create_field > *orig_create_list, List< create_field > *new_create_list) |
| static int | mysql_copy_key_list (List< Key > *orig_key, List< Key > *new_key) |
| static bool | read_ddl_log_file_entry (uint entry_no) |
| static bool | write_ddl_log_file_entry (uint entry_no) |
| static bool | write_ddl_log_header () |
| static void | create_ddl_log_file_name (char *file_name) |
| static uint | read_ddl_log_header () |
| bool | read_ddl_log_entry (uint read_entry, DDL_LOG_ENTRY *ddl_log_entry) |
| static bool | init_ddl_log () |
| static int | execute_ddl_log_action (THD *thd, DDL_LOG_ENTRY *ddl_log_entry) |
| static bool | get_free_ddl_log_entry (DDL_LOG_MEMORY_ENTRY **active_entry, bool *write_header) |
| bool | write_ddl_log_entry (DDL_LOG_ENTRY *ddl_log_entry, DDL_LOG_MEMORY_ENTRY **active_entry) |
| bool | write_execute_ddl_log_entry (uint first_entry, bool complete, DDL_LOG_MEMORY_ENTRY **active_entry) |
| bool | deactivate_ddl_log_entry (uint entry_no) |
| bool | sync_ddl_log () |
| void | release_ddl_log_memory_entry (DDL_LOG_MEMORY_ENTRY *log_entry) |
| bool | execute_ddl_log_entry (THD *thd, uint first_entry) |
| void | execute_ddl_log_recovery () |
| void | release_ddl_log () |
| bool | mysql_write_frm (ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) |
| void | write_bin_log (THD *thd, bool clear_error, char const *query, ulong query_length) |
| bool | mysql_rm_table (THD *thd, TABLE_LIST *tables, my_bool if_exists, my_bool drop_temporary) |
| int | mysql_rm_table_part2_with_lock (THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool dont_log_query) |
| int | mysql_rm_table_part2 (THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool drop_view, bool dont_log_query) |
| bool | quick_rm_table (handlerton *base, const char *db, const char *table_name, uint flags) |
| static int | sort_keys (KEY *a, KEY *b) |
| void | check_duplicates_in_interval (const char *set_or_name, const char *name, TYPELIB *typelib, CHARSET_INFO *cs) |
| void | calculate_interval_lengths (CHARSET_INFO *cs, TYPELIB *interval, uint32 *max_length, uint32 *tot_length) |
| int | prepare_create_field (create_field *sql_field, uint *blob_columns, int *timestamps, int *timestamps_with_niladic, uint table_flags) |
| static void | set_table_default_charset (THD *thd, HA_CREATE_INFO *create_info, char *db) |
| void | sp_prepare_create_field (THD *thd, create_field *sql_field) |
| static HA_CREATE_INFO * | copy_create_info (HA_CREATE_INFO *lex_create_info) |
| bool | mysql_create_table_internal (THD *thd, const char *db, const char *table_name, HA_CREATE_INFO *lex_create_info, List< create_field > &fields, List< Key > &keys, bool internal_tmp_table, uint select_field_count, bool use_copy_create_info) |
| bool | mysql_create_table (THD *thd, const char *db, const char *table_name, HA_CREATE_INFO *create_info, List< create_field > &fields, List< Key > &keys, bool internal_tmp_table, uint select_field_count, bool use_copy_create_info) |
| bool | mysql_rename_table (handlerton *base, const char *old_db, const char *old_name, const char *new_db, const char *new_name, uint flags) |
| static void | wait_while_table_is_used (THD *thd, TABLE *table, enum ha_extra_function function) |
| void | close_cached_table (THD *thd, TABLE *table) |
| static int | send_check_errmsg (THD *thd, TABLE_LIST *table, const char *operator_name, const char *errmsg) |
| static int | prepare_for_restore (THD *thd, TABLE_LIST *table, HA_CHECK_OPT *check_opt) |
| static int | prepare_for_repair (THD *thd, TABLE_LIST *table_list, HA_CHECK_OPT *check_opt) |
| static bool | mysql_admin_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt, const char *operator_name, thr_lock_type lock_type, bool open_for_modify, bool no_warnings_for_error, uint extra_open_options, int(*prepare_func)(THD *, TABLE_LIST *, HA_CHECK_OPT *), int(handler::*operator_func)(THD *, HA_CHECK_OPT *), int(view_operator_func)(THD *, TABLE_LIST *)) |
| bool | mysql_backup_table (THD *thd, TABLE_LIST *table_list) |
| bool | mysql_restore_table (THD *thd, TABLE_LIST *table_list) |
| bool | mysql_repair_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) |
| bool | mysql_optimize_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) |
| bool | mysql_assign_to_keycache (THD *thd, TABLE_LIST *tables, LEX_STRING *key_cache_name) |
| int | reassign_keycache_tables (THD *thd, KEY_CACHE *src_cache, KEY_CACHE *dst_cache) |
| bool | mysql_preload_keys (THD *thd, TABLE_LIST *tables) |
| bool | mysql_create_like_table (THD *thd, TABLE_LIST *table, HA_CREATE_INFO *lex_create_info, Table_ident *table_ident) |
| bool | mysql_analyze_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) |
| bool | mysql_check_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) |
| static int | mysql_discard_or_import_tablespace (THD *thd, TABLE_LIST *table_list, enum tablespace_op_type tablespace_op) |
| static uint | compare_tables (TABLE *table, List< create_field > *create_list, KEY *key_info_buffer, uint key_count, HA_CREATE_INFO *create_info, ALTER_INFO *alter_info, uint order_num, uint *index_drop_buffer, uint *index_drop_count, uint *index_add_buffer, uint *index_add_count, bool varchar) |
| bool | mysql_alter_table (THD *thd, char *new_db, char *new_name, HA_CREATE_INFO *lex_create_info, TABLE_LIST *table_list, List< create_field > &fields, List< Key > &keys, uint order_num, ORDER *order, bool ignore, ALTER_INFO *alter_info, bool do_send_ok) |
| bool | mysql_recreate_table (THD *thd, TABLE_LIST *table_list, bool do_send_ok) |
| bool | mysql_checksum_table (THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) |
Variables | |
| int | creating_table = 0 |
| const char * | primary_key_name = "PRIMARY" |
| GLOBAL_DDL_LOG | global_ddl_log |
| pthread_mutex_t | LOCK_gdl |
| #define ALTER_TABLE_DATA_CHANGED 1 |
| #define ALTER_TABLE_INDEX_CHANGED 2 |
| #define DDL_LOG_ACTION_TYPE_POS 1 |
Definition at line 385 of file sql_table.cc.
Referenced by deactivate_ddl_log_entry(), read_ddl_log_entry(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
| #define DDL_LOG_ENTRY_TYPE_POS 0 |
Definition at line 384 of file sql_table.cc.
Referenced by deactivate_ddl_log_entry(), read_ddl_log_entry(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
| #define DDL_LOG_IO_SIZE_POS 8 |
Definition at line 392 of file sql_table.cc.
Referenced by read_ddl_log_header(), and write_ddl_log_header().
| #define DDL_LOG_NAME_LEN_POS 4 |
Definition at line 391 of file sql_table.cc.
Referenced by read_ddl_log_header(), and write_ddl_log_header().
| #define DDL_LOG_NAME_POS 8 |
Definition at line 388 of file sql_table.cc.
Referenced by read_ddl_log_entry(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
| #define DDL_LOG_NEXT_ENTRY_POS 4 |
Definition at line 387 of file sql_table.cc.
Referenced by read_ddl_log_entry(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
| #define DDL_LOG_NUM_ENTRY_POS 0 |
Definition at line 390 of file sql_table.cc.
Referenced by read_ddl_log_header(), and write_ddl_log_header().
| #define DDL_LOG_PHASE_POS 2 |
Definition at line 386 of file sql_table.cc.
Referenced by deactivate_ddl_log_entry(), read_ddl_log_entry(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
| #define MYSQL50_TABLE_NAME_PREFIX "#mysql50#" |
Definition at line 51 of file sql_table.cc.
Referenced by filename_to_tablename(), and tablename_to_filename().
| #define MYSQL50_TABLE_NAME_PREFIX_LENGTH 9 |
| typedef struct st_global_ddl_log GLOBAL_DDL_LOG |
| uint build_table_filename | ( | char * | buff, | |
| size_t | bufflen, | |||
| const char * | db, | |||
| const char * | table_name, | |||
| const char * | ext, | |||
| uint | flags | |||
| ) |
Definition at line 170 of file sql_table.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, FN_REFLEN, mysql_data_home, NullS, strnmov(), strxnmov(), tablename_to_filename(), and VOID.
Referenced by add_table_for_trigger(), alloc_table_share(), Table_triggers_list::change_table_name_in_trignames(), check_db_dir_existence(), Table_triggers_list::check_n_load(), Table_triggers_list::create_trigger(), get_all_tables(), load_db_opt_by_name(), mysql_alter_db(), mysql_alter_table(), mysql_create_db(), mysql_create_like_table(), mysql_create_table_internal(), mysql_drop_view(), mysql_register_view(), mysql_rename_db(), mysql_rename_table(), mysql_rm_db(), mysql_rm_table_part2(), mysql_table_grant(), mysql_truncate(), mysql_write_frm(), open_table(), prepare_for_restore(), quick_rm_table(), rename_tables(), rm_trigger_file(), rm_trigname_file(), and save_trigger_file().
00172 { 00173 uint length; 00174 char dbbuff[FN_REFLEN]; 00175 char tbbuff[FN_REFLEN]; 00176 DBUG_ENTER("build_table_filename"); 00177 00178 if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP 00179 strnmov(tbbuff, table_name, sizeof(tbbuff)); 00180 else 00181 VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); 00182 00183 VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); 00184 length= strxnmov(buff, bufflen, mysql_data_home, "/", dbbuff, 00185 "/", tbbuff, ext, NullS) - buff; 00186 DBUG_PRINT("exit", ("buff: '%s'", buff)); 00187 DBUG_RETURN(length); 00188 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 209 of file sql_table.cc.
References current_pid, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, my_snprintf(), NullS, reg_ext, strxnmov(), tmp_file_prefix, tmp_file_prefix_length, and unpack_filename().
Referenced by mysql_create_like_table(), and mysql_create_table_internal().
00210 { 00211 uint length; 00212 char tmp_table_name[tmp_file_prefix_length+22+22+22+3]; 00213 DBUG_ENTER("build_tmptable_filename"); 00214 00215 my_snprintf(tmp_table_name, sizeof(tmp_table_name), 00216 "%s%lx_%lx_%x", 00217 tmp_file_prefix, current_pid, 00218 thd->thread_id, thd->tmp_table++); 00219 00220 strxnmov(buff, bufflen, mysql_tmpdir, "/", tmp_table_name, reg_ext, NullS); 00221 length= unpack_filename(buff, buff); 00222 DBUG_PRINT("exit", ("buff: '%s'", buff)); 00223 DBUG_RETURN(length); 00224 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void calculate_interval_lengths | ( | CHARSET_INFO * | cs, | |
| TYPELIB * | interval, | |||
| uint32 * | max_length, | |||
| uint32 * | tot_length | |||
| ) |
Definition at line 1961 of file sql_table.cc.
References charset_info_st::cset, interval, my_charset_handler_st::numchars, pos(), and set_if_bigger.
Referenced by mysql_prepare_table(), and sp_prepare_create_field().
01963 { 01964 const char **pos; 01965 uint *len; 01966 *max_length= *tot_length= 0; 01967 for (pos= interval->type_names, len= interval->type_lengths; 01968 *pos ; pos++, len++) 01969 { 01970 uint length= cs->cset->numchars(cs, *pos, *pos + *len); 01971 *tot_length+= length; 01972 set_if_bigger(*max_length, (uint32)length); 01973 } 01974 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void check_duplicates_in_interval | ( | const char * | set_or_name, | |
| const char * | name, | |||
| TYPELIB * | typelib, | |||
| CHARSET_INFO * | cs | |||
| ) |
Definition at line 1919 of file sql_table.cc.
References st_typelib::count, current_thd, ER, ER_DUPLICATED_VALUE_IN_TYPE, find_type2(), push_warning_printf(), st_typelib::type_lengths, st_typelib::type_names, typelib(), and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by prepare_create_field().
01922 { 01923 TYPELIB tmp= *typelib; 01924 const char **cur_value= typelib->type_names; 01925 unsigned int *cur_length= typelib->type_lengths; 01926 01927 for ( ; tmp.count > 1; cur_value++, cur_length++) 01928 { 01929 tmp.type_names++; 01930 tmp.type_lengths++; 01931 tmp.count--; 01932 if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs)) 01933 { 01934 push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE, 01935 ER_DUPLICATED_VALUE_IN_TYPE, 01936 ER(ER_DUPLICATED_VALUE_IN_TYPE), 01937 name,*cur_value,set_or_name); 01938 } 01939 } 01940 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool check_engine | ( | THD * | thd, | |
| const char * | table_name, | |||
| HA_CREATE_INFO * | create_info | |||
| ) | [static] |
Definition at line 6748 of file sql_table.cc.
References st_ha_create_information::db_type, ER, ER_ILLEGAL_HA_CREATE_OPTION, ER_WARN_USING_OTHER_HANDLER, FALSE, ha_check_storage_engine_flag(), ha_checktype(), HA_CREATE_USED_ENGINE, ha_legacy_type(), HA_LEX_CREATE_TMP_TABLE, ha_resolve_storage_engine_name(), hton2plugin, HTON_TEMPORARY_NOT_SUPPORTED, MODE_NO_ENGINE_SUBSTITUTION, my_error(), MYF, myisam_hton, st_plugin_int::name, st_ha_create_information::options, push_warning_printf(), LEX_STRING::str, test, TRUE, st_ha_create_information::used_fields, and MYSQL_ERROR::WARN_LEVEL_WARN.
Referenced by mysql_alter_table(), and mysql_create_table_internal().
06750 { 06751 handlerton **new_engine= &create_info->db_type; 06752 handlerton *req_engine= *new_engine; 06753 bool no_substitution= 06754 test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION); 06755 if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine), 06756 no_substitution, 1))) 06757 return TRUE; 06758 06759 if (req_engine && req_engine != *new_engine) 06760 { 06761 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 06762 ER_WARN_USING_OTHER_HANDLER, 06763 ER(ER_WARN_USING_OTHER_HANDLER), 06764 ha_resolve_storage_engine_name(*new_engine), 06765 table_name); 06766 } 06767 if (create_info->options & HA_LEX_CREATE_TMP_TABLE && 06768 ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED)) 06769 { 06770 if (create_info->used_fields & HA_CREATE_USED_ENGINE) 06771 { 06772 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), 06773 hton2plugin[(*new_engine)->slot]->name.str, "TEMPORARY"); 06774 *new_engine= 0; 06775 return TRUE; 06776 } 06777 *new_engine= &myisam_hton; 06778 } 06779 return FALSE; 06780 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3582 of file sql_table.cc.
References key, my_strcasecmp, start(), and system_charset_info.
Referenced by make_unique_key_name().
03583 { 03584 for (KEY *key=start ; key != end ; key++) 03585 if (!my_strcasecmp(system_charset_info,name,key->name)) 03586 return 1; 03587 return 0; 03588 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void close_cached_table | ( | THD * | thd, | |
| TABLE * | table | |||
| ) |
Definition at line 3757 of file sql_table.cc.
References broadcast_refresh(), DBUG_ENTER, DBUG_VOID_RETURN, HA_EXTRA_PREPARE_FOR_DELETE, mysql_unlock_tables(), unlink_open_table(), and wait_while_table_is_used().
Referenced by mysql_alter_table(), and prepare_for_repair().
03758 { 03759 DBUG_ENTER("close_cached_table"); 03760 03761 wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DELETE); 03762 /* Close lock if this is not got with LOCK TABLES */ 03763 if (thd->lock) 03764 { 03765 mysql_unlock_tables(thd, thd->lock); 03766 thd->lock=0; // Start locked threads 03767 } 03768 /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ 03769 thd->open_tables=unlink_open_table(thd,thd->open_tables,table); 03770 03771 /* When lock on LOCK_open is freed other threads can continue */ 03772 broadcast_refresh(); 03773 DBUG_VOID_RETURN; 03774 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static uint compare_tables | ( | TABLE * | table, | |
| List< create_field > * | create_list, | |||
| KEY * | key_info_buffer, | |||
| uint | key_count, | |||
| HA_CREATE_INFO * | create_info, | |||
| ALTER_INFO * | alter_info, | |||
| uint | order_num, | |||
| uint * | index_drop_buffer, | |||
| uint * | index_drop_count, | |||
| uint * | index_add_buffer, | |||
| uint * | index_add_count, | |||
| bool | varchar | |||
| ) | [static] |
Definition at line 4902 of file sql_table.cc.
References st_key::algorithm, ALTER_TABLE_DATA_CHANGED, BLOB_FLAG, create_field::charset, st_ha_create_information::db_type, st_table_share::db_type, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_ha_create_information::default_table_charset, base_list::elements, st_table::field, FIELD_IN_ADD_INDEX, FIELD_IS_RENAMED, create_field::field_name, Field::field_name, st_key_part_info::fieldnr, st_table_share::fields, st_key::flags, Field::flags, create_field::flags, FRM_VER_TRUE_VARCHAR, st_table_share::frm_version, HA_CREATE_USED_CHARSET, HA_CREATE_USED_DEFAULT_CHARSET, HA_CREATE_USED_ENGINE, HA_KEYFLAG_MASK, HA_OPTION_PACK_RECORD, Field::is_equal(), st_table::key_info, st_key::key_part, st_key::key_parts, st_table_share::keys, st_key_part_info::length, my_strcasecmp, MYSQL_TYPE_VARCHAR, st_table_share::mysql_version, st_key::name, NOT_NULL_FLAG, st_ha_create_information::row_type, ROW_TYPE_DYNAMIC, ROW_TYPE_FIXED, st_table::s, create_field::sql_type, strcmp(), system_charset_info, st_ha_create_information::table_options, st_table_share::tmp_table, and st_ha_create_information::used_fields.
Referenced by mysql_alter_table().
04909 { 04910 Field **f_ptr, *field; 04911 uint changes= 0, tmp; 04912 List_iterator_fast<create_field> new_field_it(*create_list); 04913 create_field *new_field; 04914 KEY_PART_INFO *key_part; 04915 KEY_PART_INFO *end; 04916 DBUG_ENTER("compare_tables"); 04917 04918 /* 04919 Some very basic checks. If number of fields changes, or the 04920 handler, we need to run full ALTER TABLE. In the future 04921 new fields can be added and old dropped without copy, but 04922 not yet. 04923 04924 Test also that engine was not given during ALTER TABLE, or 04925 we are force to run regular alter table (copy). 04926 E.g. ALTER TABLE tbl_name ENGINE=MyISAM. 04927 04928 For the following ones we also want to run regular alter table: 04929 ALTER TABLE tbl_name ORDER BY .. 04930 ALTER TABLE tbl_name CONVERT TO CHARACTER SET .. 04931 04932 At the moment we can't handle altering temporary tables without a copy. 04933 We also test if OPTIMIZE TABLE was given and was mapped to alter table. 04934 In that case we always do full copy. 04935 04936 There was a bug prior to mysql-4.0.25. Number of null fields was 04937 calculated incorrectly. As a result frm and data files gets out of 04938 sync after fast alter table. There is no way to determine by which 04939 mysql version (in 4.0 and 4.1 branches) table was created, thus we 04940 disable fast alter table for all tables created by mysql versions 04941 prior to 5.0 branch. 04942 See BUG#6236. 04943 */ 04944 if (table->s->fields != create_list->elements || 04945 table->s->db_type != create_info->db_type || 04946 table->s->tmp_table || 04947 create_info->used_fields & HA_CREATE_USED_ENGINE || 04948 create_info->used_fields & HA_CREATE_USED_CHARSET || 04949 create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET || 04950 (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) || 04951 order_num || 04952 !table->s->mysql_version || 04953 (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar)) 04954 DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); 04955 04956 /* 04957 Go through fields and check if the original ones are compatible 04958 with new table. 04959 */ 04960 for (f_ptr= table->field, new_field= new_field_it++; 04961 (field= *f_ptr); f_ptr++, new_field= new_field_it++) 04962 { 04963 /* Make sure we have at least the default charset in use. */ 04964 if (!new_field->charset) 04965 new_field->charset= create_info->default_table_charset; 04966 04967 /* Check that NULL behavior is same for old and new fields */ 04968 if ((new_field->flags & NOT_NULL_FLAG) != 04969 (uint) (field->flags & NOT_NULL_FLAG)) 04970 DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); 04971 04972 /* Don't pack rows in old tables if the user has requested this. */ 04973 if (create_info->row_type == ROW_TYPE_DYNAMIC || 04974 (new_field->flags & BLOB_FLAG) || 04975 new_field->sql_type == MYSQL_TYPE_VARCHAR && 04976 create_info->row_type != ROW_TYPE_FIXED) 04977 create_info->table_options|= HA_OPTION_PACK_RECORD; 04978 04979 /* Check if field was renamed */ 04980 field->flags&= ~FIELD_IS_RENAMED; 04981 if (my_strcasecmp(system_charset_info, 04982 field->field_name, 04983 new_field->field_name)) 04984 field->flags|= FIELD_IS_RENAMED; 04985 04986 /* Evaluate changes bitmap and send to check_if_incompatible_data() */ 04987 if (!(tmp= field->is_equal(new_field))) 04988 DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); 04989 // Clear indexed marker 04990 field->flags&= ~FIELD_IN_ADD_INDEX; 04991 changes|= tmp; 04992 } 04993 04994 /* 04995 Go through keys and check if the original ones are compatible 04996 with new table. 04997 */ 04998 KEY *table_key; 04999 KEY *table_key_end= table->key_info + table->s->keys; 05000 KEY *new_key; 05001 KEY *new_key_end= key_info_buffer + key_count; 05002 05003 DBUG_PRINT("info", ("index count old: %d new: %d", 05004 table->s->keys, key_count)); 05005 /* 05006 Step through all keys of the old table and search matching new keys. 05007 */ 05008 *index_drop_count= 0; 05009 *index_add_count= 0; 05010 for (table_key= table->key_info; table_key < table_key_end; table_key++) 05011 { 05012 KEY_PART_INFO *table_part; 05013 KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts; 05014 KEY_PART_INFO *new_part; 05015 05016 /* Search a new key with the same name. */ 05017 for (new_key= key_info_buffer; new_key < new_key_end; new_key++) 05018 { 05019 if (! strcmp(table_key->name, new_key->name)) 05020 break; 05021 } 05022 if (new_key >= new_key_end) 05023 { 05024 /* Key not found. Add the offset of the key to the drop buffer. */ 05025 index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info; 05026 DBUG_PRINT("info", ("index dropped: '%s'", table_key->name)); 05027 continue; 05028 } 05029 05030 /* Check that the key types are compatible between old and new tables. */ 05031 if ((table_key->algorithm != new_key->algorithm) || 05032 ((table_key->flags & HA_KEYFLAG_MASK) != 05033 (new_key->flags & HA_KEYFLAG_MASK)) || 05034 (table_key->key_parts != new_key->key_parts)) 05035 goto index_changed; 05036 05037 /* 05038 Check that the key parts remain compatible between the old and 05039 new tables. 05040 */ 05041 for (table_part= table_key->key_part, new_part= new_key->key_part; 05042 table_part < table_part_end; 05043 table_part++, new_part++) 05044 { 05045 /* 05046 Key definition has changed if we are using a different field or 05047 if the used key part length is different. We know that the fields 05048 did not change. Comparing field numbers is sufficient. 05049 */ 05050 if ((table_part->length != new_part->length) || 05051 (table_part->fieldnr - 1 != new_part->fieldnr)) 05052 goto index_changed; 05053 } 05054 continue; 05055 05056 index_changed: 05057 /* Key modified. Add the offset of the key to both buffers. */ 05058 index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info; 05059 index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer; 05060 key_part= new_key->key_part; 05061 end= key_part + new_key->key_parts; 05062 for(; key_part != end; key_part++) 05063 { 05064 // Mark field to be part of new key 05065 field= table->field[key_part->fieldnr]; 05066 field->flags|= FIELD_IN_ADD_INDEX; 05067 } 05068 DBUG_PRINT("info", ("index changed: '%s'", table_key->name)); 05069 } 05070 /*end of for (; table_key < table_key_end;) */ 05071 05072 /* 05073 Step through all keys of the new table and find matching old keys. 05074 */ 05075 for (new_key= key_info_buffer; new_key < new_key_end; new_key++) 05076 { 05077 /* Search an old key with the same name. */ 05078 for (table_key= table->key_info; table_key < table_key_end; table_key++) 05079 { 05080 if (! strcmp(table_key->name, new_key->name)) 05081 break; 05082 } 05083 if (table_key >= table_key_end) 05084 { 05085 /* Key not found. Add the offset of the key to the add buffer. */ 05086 index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer; 05087 key_part= new_key->key_part; 05088 end= key_part + new_key->key_parts; 05089 for(; key_part != end; key_part++) 05090 { 05091 // Mark field to be part of new key 05092 field= table->field[key_part->fieldnr]; 05093 field->flags|= FIELD_IN_ADD_INDEX; 05094 } 05095 DBUG_PRINT("info", ("index added: '%s'", new_key->name)); 05096 } 05097 } 05098 05099 /* Check if changes are compatible with current handler without a copy */ 05100 if (table->file->check_if_incompatible_data(create_info, changes)) 05101 DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); 05102 05103 if (*index_drop_count || *index_add_count) 05104 DBUG_RETURN(ALTER_TABLE_INDEX_CHANGED); 05105 05106 DBUG_RETURN(0); // Tables are compatible 05107 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static HA_CREATE_INFO* copy_create_info | ( | HA_CREATE_INFO * | lex_create_info | ) | [static] |
Definition at line 3129 of file sql_table.cc.
References mem_alloc_error(), memcpy, and sql_alloc().
Referenced by mysql_alter_table(), mysql_create_like_table(), and mysql_create_table_internal().
03130 { 03131 HA_CREATE_INFO *create_info; 03132 if (!(create_info= (HA_CREATE_INFO*)sql_alloc(sizeof(HA_CREATE_INFO)))) 03133 mem_alloc_error(sizeof(HA_CREATE_INFO)); 03134 else 03135 memcpy((void*)create_info, (void*)lex_create_info, sizeof(HA_CREATE_INFO)); 03136 return create_info; 03137 }
Here is the call graph for this function:

Here is the caller graph for this function:

| 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 | |||
| ) | [static] |
Definition at line 6405 of file sql_table.cc.
References AUTO_INCREMENT_FLAG, bzero, mySTL::copy(), current_thd, DBUG_ENTER, DBUG_RETURN, end_read_record(), ER, ER_DUP_ENTRY, ER_DUP_ENTRY_AUTOINCREMENT_CASE, err, F_UNLCK, F_WRLCK, FALSE, create_field::field, filesort(), free_io_cache(), from, HA_CHECK_DUP, ha_commit, ha_commit_stmt, ha_enable_transaction(), HA_EXTRA_IGNORE_DUP_KEY, HA_EXTRA_NO_IGNORE_DUP_KEY, HA_POS_ERROR, HA_STATUS_VARIABLE, info, init_read_record(), make_unireg_sortorder(), MODE_NO_AUTO_VALUE_ON_ZERO, MODE_STRICT_ALL_TABLES, MODE_STRICT_TRANS_TABLES, my_errno, MY_FAE, my_malloc(), MY_ZEROFILL, MYF, order, prev_insert_id(), st_read_record::read_record, restore_record, setup_order(), test, to, and TRUE.
06411 { 06412 int error; 06413 Copy_field *copy,*copy_end; 06414 ulong found_count,delete_count; 06415 THD *thd= current_thd; 06416 uint length; 06417 SORT_FIELD *sortorder; 06418 READ_RECORD info; 06419 TABLE_LIST tables; 06420 List<Item> fields; 06421 List<Item> all_fields; 06422 ha_rows examined_rows; 06423 bool auto_increment_field_copied= 0; 06424 ulong save_sql_mode; 06425 ulonglong prev_insert_id; 06426 DBUG_ENTER("copy_data_between_tables"); 06427 06428 /* 06429 Turn off recovery logging since rollback of an alter table is to 06430 delete the new table so there is no need to log the changes to it. 06431 06432 This needs to be done before external_lock 06433 */ 06434 error= ha_enable_transaction(thd, FALSE); 06435 if (error) 06436 DBUG_RETURN(-1); 06437 06438 if (!(copy= new Copy_field[to->s->fields])) 06439 DBUG_RETURN(-1); /* purecov: inspected */ 06440 06441 if (to->file->ha_external_lock(thd, F_WRLCK)) 06442 DBUG_RETURN(-1); 06443 06444 /* We can abort alter table for any table type */ 06445 thd->no_trans_update= 0; 06446 thd->abort_on_warning= !ignore && test(thd->variables.sql_mode & 06447 (MODE_STRICT_TRANS_TABLES | 06448 MODE_STRICT_ALL_TABLES)); 06449 06450 from->file->info(HA_STATUS_VARIABLE); 06451 to->file->ha_start_bulk_insert(from->file->stats.records); 06452 06453 save_sql_mode= thd->variables.sql_mode; 06454 06455 List_iterator<create_field> it(create); 06456 create_field *def; 06457 copy_end=copy; 06458 for (Field **ptr=to->field ; *ptr ; ptr++) 06459 { 06460 def=it++; 06461 if (def->field) 06462 { 06463 if (*ptr == to->next_number_field) 06464 { 06465 auto_increment_field_copied= TRUE; 06466 /* 06467 If we are going to copy contents of one auto_increment column to 06468 another auto_increment column it is sensible to preserve zeroes. 06469 This condition also covers case when we are don't actually alter 06470 auto_increment column. 06471 */ 06472 if (def->field == from->found_next_number_field) 06473 thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO; 06474 } 06475 (copy_end++)->set(*ptr,def->field,0); 06476 } 06477 06478 } 06479 06480 found_count=delete_count=0; 06481 06482 if (order) 06483 { 06484 from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), 06485 MYF(MY_FAE | MY_ZEROFILL)); 06486 bzero((char*) &tables,sizeof(tables)); 06487 tables.table= from; 06488 tables.alias= tables.table_name= from->s->table_name.str; 06489 tables.db= from->s->db.str; 06490 error=1; 06491 06492 if (thd->lex->select_lex.setup_ref_array(thd, order_num) || 06493 setup_order(thd, thd->lex->select_lex.ref_pointer_array, 06494 &tables, fields, all_fields, order) || 06495 !(sortorder=make_unireg_sortorder(order, &length)) || 06496 (from->sort.found_records = filesort(thd, from, sortorder, length, 06497 (SQL_SELECT *) 0, HA_POS_ERROR, 1, 06498 &examined_rows)) == 06499 HA_POS_ERROR) 06500 goto err; 06501 }; 06502 06503 /* Tell handler that we have values for all columns in the to table */ 06504 to->use_all_columns(); 06505 init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1); 06506 if (ignore) 06507 to->file->extra(HA_EXTRA_IGNORE_DUP_KEY); 06508 thd->row_count= 0; 06509 restore_record(to, s->default_values); // Create empty record 06510 while (!(error=info.read_record(&info))) 06511 { 06512 if (thd->killed) 06513 { 06514 thd->send_kill_message(); 06515 error= 1; 06516 break; 06517 } 06518 thd->row_count++; 06519 if (to->next_number_field) 06520 { 06521 if (auto_increment_field_copied) 06522 to->auto_increment_field_not_null= TRUE; 06523 else 06524 to->next_number_field->reset(); 06525 } 06526 06527 for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++) 06528 { 06529 copy_ptr->do_copy(copy_ptr); 06530 } 06531 prev_insert_id= to->file->next_insert_id; 06532 if ((error=to->file->ha_write_row((byte*) to->record[0]))) 06533 { 06534 if (!ignore || 06535 to->file->is_fatal_error(error, HA_CHECK_DUP)) 06536 { 06537 if (!to->file->is_fatal_error(error, HA_CHECK_DUP)) 06538 { 06539 uint key_nr= to->file->get_dup_key(error); 06540 if ((int) key_nr >= 0) 06541 { 06542 const char *err_msg= ER(ER_DUP_ENTRY); 06543 if (key_nr == 0 && 06544 (to->key_info[0].key_part[0].field->flags & 06545 AUTO_INCREMENT_FLAG)) 06546 err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE); 06547 to->file->print_keydup_error(key_nr, err_msg); 06548 break; 06549 } 06550 } 06551 06552 to->file->print_error(error,MYF(0)); 06553 break; 06554 } 06555 to->file->restore_auto_increment(prev_insert_id); 06556 delete_count++; 06557 } 06558 else 06559 found_count++; 06560 } 06561 end_read_record(&info); 06562 free_io_cache(from); 06563 delete [] copy; // This is never 0 06564 06565 if (to->file->ha_end_bulk_insert() && error <= 0) 06566 { 06567 to->file->print_error(my_errno,MYF(0)); 06568 error=1; 06569 } 06570 to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); 06571 06572 ha_enable_transaction(thd,TRUE); 06573 06574 /* 06575 Ensure that the new table is saved properly to disk so that we 06576 can do a rename 06577 */ 06578 if (ha_commit_stmt(thd)) 06579 error=1; 06580 if (ha_commit(thd)) 06581 error=1; 06582 06583 err: 06584 thd->variables.sql_mode= save_sql_mode; 06585 thd->abort_on_warning= 0; 06586 free_io_cache(from); 06587 *copied= found_count; 06588 *deleted=delete_count; 06589 to->file->ha_release_auto_increment(); 06590 if (to->file->ha_external_lock(thd,F_UNLCK)) 06591 error=1; 06592 DBUG_RETURN(error > 0 ? -1 : 0); 06593 }
Here is the call graph for this function:

| static void create_ddl_log_file_name | ( | char * | file_name | ) | [inline, static] |
Definition at line 485 of file sql_table.cc.
References mysql_data_home, NullS, and strxmov().
Referenced by init_ddl_log(), and read_ddl_log_header().
00486 { 00487 strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS); 00488 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 993 of file sql_table.cc.
References DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, DDL_LOG_ACTION_TYPE_POS, DDL_LOG_ENTRY_TYPE_POS, DDL_LOG_PHASE_POS, FALSE, st_global_ddl_log::file_entry_buf, global_ddl_log, read_ddl_log_file_entry(), sql_print_error(), TRUE, and write_ddl_log_file_entry().
Referenced by execute_ddl_log_action(), and mysql_write_frm().
00994 { 00995 char *file_entry_buf= (char*)global_ddl_log.file_entry_buf; 00996 DBUG_ENTER("deactivate_ddl_log_entry"); 00997 00998 if (!read_ddl_log_file_entry(entry_no)) 00999 { 01000 if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE) 01001 { 01002 if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION || 01003 file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION || 01004 (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION && 01005 file_entry_buf[DDL_LOG_PHASE_POS] == 1)) 01006 file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE; 01007 else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION) 01008 { 01009 DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0); 01010 file_entry_buf[DDL_LOG_PHASE_POS]= 1; 01011 } 01012 else 01013 { 01014 DBUG_ASSERT(0); 01015 } 01016 if (write_ddl_log_file_entry(entry_no)) 01017 { 01018 sql_print_error("Error in deactivating log entry. Position = %u", 01019 entry_no); 01020 DBUG_RETURN(TRUE); 01021 } 01022 } 01023 } 01024 else 01025 { 01026 sql_print_error("Failed in reading entry before deactivating it"); 01027 DBUG_RETURN(TRUE); 01028 } 01029 DBUG_RETURN(FALSE); 01030 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int execute_ddl_log_action | ( | THD * | thd, | |
| DDL_LOG_ENTRY * | ddl_log_entry | |||
| ) | [static] |
Definition at line 641 of file sql_table.cc.
References bzero, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, deactivate_ddl_log_entry(), handler::delete_table(), ER_ILLEGAL_HA, error, FALSE, FN_REFLEN, free_root(), get_new_handler(), HA_ERR_NO_SUCH_TABLE, ha_resolve_by_name(), init_sql_alloc(), LEX_STRING::length, mem_alloc_error(), my_delete(), my_errno, my_error(), my_rename(), MY_WME, MYF, NULL, NullS, reg_ext, handler::rename_table(), LEX_STRING::str, strcmp(), strlen(), strxmov(), sync_ddl_log(), TABLE_ALLOC_BLOCK_SIZE, TRUE, and VOID.
Referenced by execute_ddl_log_entry().
00642 { 00643 bool frm_action= FALSE; 00644 LEX_STRING handler_name; 00645 handler *file= NULL; 00646 MEM_ROOT mem_root; 00647 int error= TRUE; 00648 char to_path[FN_REFLEN]; 00649 char from_path[FN_REFLEN]; 00650 char *par_ext= (char*)".par"; 00651 handlerton *hton; 00652 DBUG_ENTER("execute_ddl_log_action"); 00653 00654 if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE) 00655 { 00656 DBUG_RETURN(FALSE); 00657 } 00658 handler_name.str= (char*)ddl_log_entry->handler_name; 00659 handler_name.length= strlen(ddl_log_entry->handler_name); 00660 init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 00661 if (!strcmp(ddl_log_entry->handler_name, reg_ext)) 00662 frm_action= TRUE; 00663 else 00664 { 00665 TABLE_SHARE dummy; 00666 00667 hton= ha_resolve_by_name(thd, &handler_name); 00668 if (!hton) 00669 { 00670 my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name); 00671 goto error; 00672 } 00673 bzero(&dummy, sizeof(TABLE_SHARE)); 00674 file= get_new_handler(&dummy, &mem_root, hton); 00675 if (!file) 00676 { 00677 mem_alloc_error(sizeof(handler)); 00678 goto error; 00679 } 00680 } 00681 switch (ddl_log_entry->action_type) 00682 { 00683 case DDL_LOG_REPLACE_ACTION: 00684 case DDL_LOG_DELETE_ACTION: 00685 { 00686 if (ddl_log_entry->phase == 0) 00687 { 00688 if (frm_action) 00689 { 00690 strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); 00691 if ((error= my_delete(to_path, MYF(MY_WME)))) 00692 { 00693 if (my_errno != ENOENT) 00694 break; 00695 } 00696 #ifdef WITH_PARTITION_STORAGE_ENGINE 00697 strxmov(to_path, ddl_log_entry->name, par_ext, NullS); 00698 VOID(my_delete(to_path, MYF(MY_WME))); 00699 #endif 00700 } 00701 else 00702 { 00703 if ((error= file->delete_table(ddl_log_entry->name))) 00704 { 00705 if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE) 00706 break; 00707 } 00708 } 00709 if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos))) 00710 break; 00711 VOID(sync_ddl_log()); 00712 error= FALSE; 00713 if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION) 00714 break; 00715 } 00716 DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION); 00717 /* 00718 Fall through and perform the rename action of the replace 00719 action. We have already indicated the success of the delete 00720 action in the log entry by stepping up the phase. 00721 */ 00722 } 00723 case DDL_LOG_RENAME_ACTION: 00724 { 00725 error= TRUE; 00726 if (frm_action) 00727 { 00728 strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); 00729 strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS); 00730 if (my_rename(from_path, to_path, MYF(MY_WME))) 00731 break; 00732 #ifdef WITH_PARTITION_STORAGE_ENGINE 00733 strxmov(to_path, ddl_log_entry->name, par_ext, NullS); 00734 strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS); 00735 VOID(my_rename(from_path, to_path, MYF(MY_WME))); 00736 #endif 00737 } 00738 else 00739 { 00740 if (file->rename_table(ddl_log_entry->from_name, 00741 ddl_log_entry->name)) 00742 break; 00743 } 00744 if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos))) 00745 break; 00746 VOID(sync_ddl_log()); 00747 error= FALSE; 00748 break; 00749 } 00750 default: 00751 DBUG_ASSERT(0); 00752 break; 00753 } 00754 delete file; 00755 error: 00756 free_root(&mem_root, MYF(0)); 00757 DBUG_RETURN(error); 00758 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1102 of file sql_table.cc.
References DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, execute_ddl_log_action(), FALSE, LOCK_gdl, pthread_mutex_lock, pthread_mutex_unlock, read_ddl_log_entry(), and sql_print_error().
Referenced by execute_ddl_log_recovery().
01103 { 01104 DDL_LOG_ENTRY ddl_log_entry; 01105 uint read_entry= first_entry; 01106 DBUG_ENTER("execute_ddl_log_entry"); 01107 01108 pthread_mutex_lock(&LOCK_gdl); 01109 do 01110 { 01111 if (read_ddl_log_entry(read_entry, &ddl_log_entry)) 01112 { 01113 /* Write to error log and continue with next log entry */ 01114 sql_print_error("Failed to read entry = %u from ddl log", 01115 read_entry); 01116 break; 01117 } 01118 DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE || 01119 ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE); 01120 01121 if (execute_ddl_log_action(thd, &ddl_log_entry)) 01122 { 01123 /* Write to error log and continue with next log entry */ 01124 sql_print_error("Failed to execute action for entry = %u from ddl log", 01125 read_entry); 01126 break; 01127 } 01128 read_entry= ddl_log_entry.next_entry; 01129 } while (read_entry); 01130 pthread_mutex_unlock(&LOCK_gdl); 01131 DBUG_RETURN(FALSE); 01132 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void execute_ddl_log_recovery | ( | ) |
Definition at line 1143 of file sql_table.cc.
References bzero, DBUG_ENTER, DBUG_VOID_RETURN, execute_ddl_log_entry(), FALSE, st_global_ddl_log::file_entry_buf, st_global_ddl_log::file_id, FN_REFLEN, global_ddl_log, st_global_ddl_log::inited, IO_SIZE, st_global_ddl_log::io_size, read_ddl_log_entry(), read_ddl_log_header(), st_global_ddl_log::recovery_phase, sql_print_error(), and TRUE.
Referenced by main().
01144 { 01145 uint num_entries, i; 01146 THD *thd; 01147 DDL_LOG_ENTRY ddl_log_entry; 01148 char file_name[FN_REFLEN]; 01149 DBUG_ENTER("execute_ddl_log_recovery"); 01150 01151 /* 01152 Initialise global_ddl_log struct 01153 */ 01154 bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf)); 01155 global_ddl_log.inited= FALSE; 01156 global_ddl_log.recovery_phase= TRUE; 01157 global_ddl_log.io_size= IO_SIZE; 01158 global_ddl_log.file_id= (File) -1; 01159 01160 /* 01161 To be able to run this from boot, we allocate a temporary THD 01162 */ 01163 if (!(thd=new THD)) 01164 DBUG_VOID_RETURN; 01165 thd->thread_stack= (char*) &thd; 01166 thd->store_globals(); 01167 01168 num_entries= read_ddl_log_header(); 01169 for (i= 1; i < num_entries + 1; i++) 01170 { 01171 if (read_ddl_log_entry(i, &ddl_log_entry)) 01172 { 01173 sql_print_error("Failed to read entry no = %u from ddl log", 01174 i); 01175 continue; 01176 } 01177 if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE) 01178 { 01179 if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry)) 01180 { 01181 /* Real unpleasant scenario but we continue anyways. */ 01182 continue; 01183 } 01184 } 01185 } 01186 create_ddl_log_file_name(file_name); 01187 VOID(my_delete(file_name, MYF(0))); 01188 global_ddl_log.recovery_phase= FALSE; 01189 delete thd; 01190 /* Remember that we don't have a THD */ 01191 my_pthread_setspecific_ptr(THR_THD, 0); 01192 DBUG_VOID_RETURN; 01193 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 68 of file sql_table.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, memcmp(), my_charset_filename, MYSQL50_TABLE_NAME_PREFIX, NullS, sql_print_error(), strconvert(), strnmov(), strxnmov(), system_charset_info, tmp_file_prefix, and tmp_file_prefix_length.
Referenced by find_files(), mysql_rename_db(), and mysql_rm_known_files().
00069 { 00070 uint errors; 00071 uint res; 00072 DBUG_ENTER("filename_to_tablename"); 00073 DBUG_PRINT("enter", ("from '%s'", from)); 00074 00075 if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length)) 00076 { 00077 /* Temporary table name. */ 00078 res= (strnmov(to, from, to_length) - to); 00079 } 00080 else 00081 { 00082 res= strconvert(&my_charset_filename, from, 00083 system_charset_info, to, to_length, &errors); 00084 if (errors) // Old 5.0 name 00085 { 00086 res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) - 00087 to); 00088 sql_print_error("Invalid (old?) table or database name '%s'", from); 00089 /* 00090 TODO: add a stored procedure for fix table and database names, 00091 and mention its name in error log. 00092 */ 00093 } 00094 } 00095 00096 DBUG_PRINT("exit", ("to '%s'", to)); 00097 DBUG_RETURN(res); 00098 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool get_free_ddl_log_entry | ( | DDL_LOG_MEMORY_ENTRY ** | active_entry, | |
| bool * | write_header | |||
| ) | [static] |
Definition at line 771 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, FALSE, st_global_ddl_log::first_free, st_global_ddl_log::first_used, global_ddl_log, my_malloc(), MY_WME, MYF, NULL, st_global_ddl_log::num_entries, sql_print_error(), and TRUE.
Referenced by write_ddl_log_entry(), and write_execute_ddl_log_entry().
00773 { 00774 DDL_LOG_MEMORY_ENTRY *used_entry; 00775 DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used; 00776 DBUG_ENTER("get_free_ddl_log_entry"); 00777 00778 if (global_ddl_log.first_free == NULL) 00779 { 00780 if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc( 00781 sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME)))) 00782 { 00783 sql_print_error("Failed to allocate memory for ddl log free list"); 00784 DBUG_RETURN(TRUE); 00785 } 00786 global_ddl_log.num_entries++; 00787 used_entry->entry_pos= global_ddl_log.num_entries; 00788 *write_header= TRUE; 00789 } 00790 else 00791 { 00792 used_entry= global_ddl_log.first_free; 00793 global_ddl_log.first_free= used_entry->next_log_entry; 00794 *write_header= FALSE; 00795 } 00796 /* 00797 Move from free list to used list 00798 */ 00799 used_entry->next_log_entry= first_used; 00800 used_entry->prev_log_entry= NULL; 00801 global_ddl_log.first_used= used_entry; 00802 if (first_used) 00803 first_used->prev_log_entry= used_entry; 00804 00805 *active_entry= used_entry; 00806 DBUG_RETURN(FALSE); 00807 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool init_ddl_log | ( | ) | [static] |
Definition at line 598 of file sql_table.cc.
References create_ddl_log_file_name(), CREATE_MODE, DBUG_ENTER, DBUG_RETURN, error, FALSE, st_global_ddl_log::file_id, FN_REFLEN, global_ddl_log, st_global_ddl_log::inited, IO_SIZE, st_global_ddl_log::io_size, my_close(), my_create(), MY_WME, MYF, O_BINARY, sql_print_error(), TRUE, VOID, and write_ddl_log_header().
Referenced by sync_ddl_log(), write_ddl_log_entry(), and write_execute_ddl_log_entry().
00599 { 00600 bool error= FALSE; 00601 char file_name[FN_REFLEN]; 00602 DBUG_ENTER("init_ddl_log"); 00603 00604 if (global_ddl_log.inited) 00605 goto end; 00606 00607 global_ddl_log.io_size= IO_SIZE; 00608 create_ddl_log_file_name(file_name); 00609 if ((global_ddl_log.file_id= my_create(file_name, 00610 CREATE_MODE, 00611 O_RDWR | O_TRUNC | O_BINARY, 00612 MYF(MY_WME))) < 0) 00613 { 00614 /* Couldn't create ddl log file, this is serious error */ 00615 sql_print_error("Failed to open ddl log file"); 00616 DBUG_RETURN(TRUE); 00617 } 00618 global_ddl_log.inited= TRUE; 00619 if (write_ddl_log_header()) 00620 { 00621 VOID(my_close(global_ddl_log.file_id, MYF(MY_WME))); 00622 global_ddl_log.inited= FALSE; 00623 DBUG_RETURN(TRUE); 00624 } 00625 00626 end: 00627 DBUG_RETURN(FALSE); 00628 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3592 of file sql_table.cc.
References check_if_keyname_exists(), int10_to_str(), MAX_FIELD_NAME, my_strcasecmp, primary_key_name, sql_strdup(), start(), strmake(), and system_charset_info.
03593 { 03594 char buff[MAX_FIELD_NAME],*buff_end; 03595 03596 if (!check_if_keyname_exists(field_name,start,end) && 03597 my_strcasecmp(system_charset_info,field_name,primary_key_name)) 03598 return (char*) field_name; // Use fieldname 03599 buff_end=strmake(buff,field_name, sizeof(buff)-4); 03600 03601 /* 03602 Only 3 chars + '\0' left, so need to limit to 2 digit 03603 This is ok as we can't have more than 100 keys anyway 03604 */ 03605 for (uint i=2 ; i< 100; i++) 03606 { 03607 *buff_end= '_'; 03608 int10_to_str(i, buff_end+1, 10); 03609 if (!check_if_keyname_exists(buff,start,end)) 03610 return sql_strdup(buff); 03611 } 03612 return (char*) "not_specified"; // Should never happen 03613 }
Here is the call graph for this function:

| static bool mysql_admin_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt, | |||
| const char * | operator_name, | |||
| thr_lock_type | lock_type, | |||
| bool | open_for_modify, | |||
| bool | no_warnings_for_error, | |||
| uint | extra_open_options, | |||
| int(*)(THD *, TABLE_LIST *, HA_CHECK_OPT *) | prepare_func, | |||
| int(handler::*)(THD *, HA_CHECK_OPT *) | operator_func, | |||
| int(view_operator_func)(THD *, TABLE_LIST *) | ||||
| ) | [static] |
Definition at line 4003 of file sql_table.cc.
References handler::analyze(), buf, handler::check_old_types(), close_thread_tables(), COND_refresh, st_table_share::crashed, st_table_share::db, st_table_list::db, db, st_table::db_stat, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, end_active_trans(), ER, ER_CHECK_NO_SUCH_TABLE, ER_CHECK_NOT_IMPLEMENTED, ER_OPEN_AS_READONLY, ER_TABLE_NEEDS_UPGRADE, ER_VIEW_CHECKSUM, err, ERRMSGSIZE, FALSE, fatal_error(), st_table::file, FN_REFLEN, FRMTYPE_TABLE, HA_ADMIN_ALREADY_DONE, HA_ADMIN_CORRUPT, HA_ADMIN_FAILED, HA_ADMIN_INVALID, HA_ADMIN_NEEDS_ALTER, HA_ADMIN_NEEDS_UPGRADE, HA_ADMIN_NOT_BASE_TABLE, HA_ADMIN_NOT_IMPLEMENTED, HA_ADMIN_OK, HA_ADMIN_REJECT, HA_ADMIN_TRY_ALTER, HA_ADMIN_WRONG_CHECKSUM, ha_autocommit_or_rollback(), handler::ha_check(), handler::ha_check_for_upgrade(), HA_READ_ONLY, handler::ha_repair(), HA_STATUS_CONST, handler::info(), LOCK_open, st_table_list::lock_type, st_table_share::log_table, Item::maybe_null, my_snprintf(), MYSQL_ERRMSG_SIZE, mysql_ha_flush(), mysql_lock_abort(), mysql_recreate_table(), NAME_LEN, st_table_list::next_global, st_table_list::next_local, NULL, NullS, open_and_lock_tables(), open_ltable(), st_table::pos_in_table_list, Protocol::prepare_for_resend(), pthread_mutex_lock, pthread_mutex_unlock, List< T >::push_back(), remove_table_from_cache(), st_table_list::required_type, st_table::s, send_eof(), Protocol::SEND_EOF, Protocol::send_fields(), Protocol::SEND_NUM_ROWS, sql_print_error(), Protocol::store(), LEX_STRING::str, STRING_WITH_LEN, strlen(), strxmov(), system_charset_info, st_table_list::table, st_table_share::table_name, st_table_list::table_name, TL_WRITE, st_table_share::tmp_table, TRUE, st_table_share::version, st_table_list::view, view_checksum(), and Protocol::write().
Referenced by mysql_analyze_table(), mysql_assign_to_keycache(), mysql_backup_table(), mysql_check_table(), mysql_optimize_table(), mysql_preload_keys(), mysql_repair_table(), and mysql_restore_table().
04015 { 04016 TABLE_LIST *table, *save_next_global, *save_next_local; 04017 SELECT_LEX *select= &thd->lex->select_lex; 04018 List<Item> field_list; 04019 Item *item; 04020 Protocol *protocol= thd->protocol; 04021 LEX *lex= thd->lex; 04022 int result_code; 04023 DBUG_ENTER("mysql_admin_table"); 04024 04025 if (end_active_trans(thd)) 04026 DBUG_RETURN(1); 04027 field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2)); 04028 item->maybe_null = 1; 04029 field_list.push_back(item = new Item_empty_string("Op", 10)); 04030 item->maybe_null = 1; 04031 field_list.push_back(item = new Item_empty_string("Msg_type", 10)); 04032 item->maybe_null = 1; 04033 field_list.push_back(item = new Item_empty_string("Msg_text", 255)); 04034 item->maybe_null = 1; 04035 if (protocol->send_fields(&field_list, 04036 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 04037 DBUG_RETURN(TRUE); 04038 04039 mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE); 04040 for (table= tables; table; table= table->next_local) 04041 { 04042 char table_name[NAME_LEN*2+2]; 04043 char* db = table->db; 04044 bool fatal_error=0; 04045 04046 strxmov(table_name, db, ".", table->table_name, NullS); 04047 thd->open_options|= extra_open_options; 04048 table->lock_type= lock_type; 04049 /* open only one table from local list of command */ 04050 save_next_global= table->next_global; 04051 table->next_global= 0; 04052 save_next_local= table->next_local; 04053 table->next_local= 0; 04054 select->table_list.first= (byte*)table; 04055 /* 04056 Time zone tables and SP tables can be add to lex->query_tables list, 04057 so it have to be prepared. 04058 TODO: Investigate if we can put extra tables into argument instead of 04059 using lex->query_tables 04060 */ 04061 lex->query_tables= table; 04062 lex->query_tables_last= &table->next_global; 04063 lex->query_tables_own_last= 0; 04064 thd->no_warnings_for_error= no_warnings_for_error; 04065 if (view_operator_func == NULL) 04066 table->required_type=FRMTYPE_TABLE; 04067 open_and_lock_tables(thd, table); 04068 thd->no_warnings_for_error= 0; 04069 table->next_global= save_next_global; 04070 table->next_local= save_next_local; 04071 thd->open_options&= ~extra_open_options; 04072 04073 if (prepare_func) 04074 { 04075 switch ((*prepare_func)(thd, table, check_opt)) { 04076 case 1: // error, message written to net 04077 ha_autocommit_or_rollback(thd, 1); 04078 close_thread_tables(thd); 04079 continue; 04080 case -1: // error, message could be written to net 04081 goto err; 04082 default: // should be 0 otherwise 04083 ; 04084 } 04085 } 04086 04087 /* 04088 CHECK TABLE command is only command where VIEW allowed here and this 04089 command use only temporary teble method for VIEWs resolving => there 04090 can't be VIEW tree substitition of join view => if opening table 04091 succeed then table->table will have real TABLE pointer as value (in 04092 case of join view substitution table->table can be 0, but here it is 04093 impossible) 04094 */ 04095 if (!table->table) 04096 { 04097 char buf[ERRMSGSIZE+ERRMSGSIZE+2]; 04098 const char *err_msg; 04099 protocol->prepare_for_resend(); 04100 protocol->store(table_name, system_charset_info); 04101 protocol->store(operator_name, system_charset_info); 04102 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04103 if (!(err_msg=thd->net.last_error)) 04104 err_msg=ER(ER_CHECK_NO_SUCH_TABLE); 04105 /* if it was a view will check md5 sum */ 04106 if (table->view && 04107 view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM) 04108 { 04109 strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS); 04110 err_msg= (const char *)buf; 04111 } 04112 protocol->store(err_msg, system_charset_info); 04113 lex->cleanup_after_one_table_open(); 04114 thd->clear_error(); 04115 /* 04116 View opening can be interrupted in the middle of process so some 04117 tables can be left opening 04118 */ 04119 ha_autocommit_or_rollback(thd, 1); 04120 close_thread_tables(thd); 04121 lex->reset_query_tables_list(FALSE); 04122 if (protocol->write()) 04123 goto err; 04124 continue; 04125 } 04126 04127 if (table->view) 04128 { 04129 result_code= (*view_operator_func)(thd, table); 04130 goto send_result; 04131 } 04132 04133 table->table->pos_in_table_list= table; 04134 if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) 04135 { 04136 char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; 04137 uint length; 04138 protocol->prepare_for_resend(); 04139 protocol->store(table_name, system_charset_info); 04140 protocol->store(operator_name, system_charset_info); 04141 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04142 length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), 04143 table_name); 04144 protocol->store(buff, length, system_charset_info); 04145 ha_autocommit_or_rollback(thd, 0); 04146 close_thread_tables(thd); 04147 lex->reset_query_tables_list(FALSE); 04148 table->table=0; // For query cache 04149 if (protocol->write()) 04150 goto err; 04151 continue; 04152 } 04153 04154 /* Close all instances of the table to allow repair to rename files */ 04155 if (lock_type == TL_WRITE && table->table->s->version && 04156 !table->table->s->log_table) 04157 { 04158 pthread_mutex_lock(&LOCK_open); 04159 const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, 04160 "Waiting to get writelock"); 04161 mysql_lock_abort(thd,table->table, TRUE); 04162 remove_table_from_cache(thd, table->table->s->db.str, 04163 table->table->s->table_name.str, 04164 RTFC_WAIT_OTHER_THREAD_FLAG | 04165 RTFC_CHECK_KILLED_FLAG); 04166 thd->exit_cond(old_message); 04167 if (thd->killed) 04168 goto err; 04169 /* Flush entries in the query cache involving this table. */ 04170 query_cache_invalidate3(thd, table->table, 0); 04171 open_for_modify= 0; 04172 } 04173 04174 if (table->table->s->crashed && operator_func == &handler::ha_check) 04175 { 04176 protocol->prepare_for_resend(); 04177 protocol->store(table_name, system_charset_info); 04178 protocol->store(operator_name, system_charset_info); 04179 protocol->store(STRING_WITH_LEN("warning"), system_charset_info); 04180 protocol->store(STRING_WITH_LEN("Table is marked as crashed"), 04181 system_charset_info); 04182 if (protocol->write()) 04183 goto err; 04184 } 04185 04186 if (operator_func == &handler::ha_repair) 04187 { 04188 if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) || 04189 (table->table->file->ha_check_for_upgrade(check_opt) == 04190 HA_ADMIN_NEEDS_ALTER)) 04191 { 04192 ha_autocommit_or_rollback(thd, 1); 04193 close_thread_tables(thd); 04194 tmp_disable_binlog(thd); // binlogging is done by caller if wanted 04195 result_code= mysql_recreate_table(thd, table, 0); 04196 reenable_binlog(thd); 04197 goto send_result; 04198 } 04199 04200 } 04201 04202 result_code = (table->table->file->*operator_func)(thd, check_opt); 04203 04204 send_result: 04205 04206 lex->cleanup_after_one_table_open(); 04207 thd->clear_error(); // these errors shouldn't get client 04208 protocol->prepare_for_resend(); 04209 protocol->store(table_name, system_charset_info); 04210 protocol->store(operator_name, system_charset_info); 04211 04212 send_result_message: 04213 04214 DBUG_PRINT("info", ("result_code: %d", result_code)); 04215 switch (result_code) { 04216 case HA_ADMIN_NOT_IMPLEMENTED: 04217 { 04218 char buf[ERRMSGSIZE+20]; 04219 uint length=my_snprintf(buf, ERRMSGSIZE, 04220 ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); 04221 protocol->store(STRING_WITH_LEN("note"), system_charset_info); 04222 protocol->store(buf, length, system_charset_info); 04223 } 04224 break; 04225 04226 case HA_ADMIN_NOT_BASE_TABLE: 04227 { 04228 char buf[ERRMSGSIZE+20]; 04229 uint length= my_snprintf(buf, ERRMSGSIZE, 04230 ER(ER_BAD_TABLE_ERROR), table_name); 04231 protocol->store(STRING_WITH_LEN("note"), system_charset_info); 04232 protocol->store(buf, length, system_charset_info); 04233 } 04234 break; 04235 04236 case HA_ADMIN_OK: 04237 protocol->store(STRING_WITH_LEN("status"), system_charset_info); 04238 protocol->store(STRING_WITH_LEN("OK"), system_charset_info); 04239 break; 04240 04241 case HA_ADMIN_FAILED: 04242 protocol->store(STRING_WITH_LEN("status"), system_charset_info); 04243 protocol->store(STRING_WITH_LEN("Operation failed"), 04244 system_charset_info); 04245 break; 04246 04247 case HA_ADMIN_REJECT: 04248 protocol->store(STRING_WITH_LEN("status"), system_charset_info); 04249 protocol->store(STRING_WITH_LEN("Operation need committed state"), 04250 system_charset_info); 04251 open_for_modify= FALSE; 04252 break; 04253 04254 case HA_ADMIN_ALREADY_DONE: 04255 protocol->store(STRING_WITH_LEN("status"), system_charset_info); 04256 protocol->store(STRING_WITH_LEN("Table is already up to date"), 04257 system_charset_info); 04258 break; 04259 04260 case HA_ADMIN_CORRUPT: 04261 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04262 protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info); 04263 fatal_error=1; 04264 break; 04265 04266 case HA_ADMIN_INVALID: 04267 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04268 protocol->store(STRING_WITH_LEN("Invalid argument"), 04269 system_charset_info); 04270 break; 04271 04272 case HA_ADMIN_TRY_ALTER: 04273 { 04274 /* 04275 This is currently used only by InnoDB. ha_innobase::optimize() answers 04276 "try with alter", so here we close the table, do an ALTER TABLE, 04277 reopen the table and do ha_innobase::analyze() on it. 04278 */ 04279 ha_autocommit_or_rollback(thd, 0); 04280 close_thread_tables(thd); 04281 TABLE_LIST *save_next_local= table->next_local, 04282 *save_next_global= table->next_global; 04283 table->next_local= table->next_global= 0; 04284 tmp_disable_binlog(thd); // binlogging is done by caller if wanted 04285 result_code= mysql_recreate_table(thd, table, 0); 04286 reenable_binlog(thd); 04287 ha_autocommit_or_rollback(thd, 0); 04288 close_thread_tables(thd); 04289 if (!result_code) // recreation went ok 04290 { 04291 if ((table->table= open_ltable(thd, table, lock_type)) && 04292 ((result_code= table->table->file->analyze(thd, check_opt)) > 0)) 04293 result_code= 0; // analyze went ok 04294 } 04295 if (result_code) // either mysql_recreate_table or analyze failed 04296 { 04297 const char *err_msg; 04298 if ((err_msg= thd->net.last_error)) 04299 { 04300 if (!thd->vio_ok()) 04301 { 04302 sql_print_error(err_msg); 04303 } 04304 else 04305 { 04306 /* Hijack the row already in-progress. */ 04307 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04308 protocol->store(err_msg, system_charset_info); 04309 (void)protocol->write(); 04310 /* Start off another row for HA_ADMIN_FAILED */ 04311 protocol->prepare_for_resend(); 04312 protocol->store(table_name, system_charset_info); 04313 protocol->store(operator_name, system_charset_info); 04314 } 04315 } 04316 } 04317 result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; 04318 table->next_local= save_next_local; 04319 table->next_global= save_next_global; 04320 goto send_result_message; 04321 } 04322 case HA_ADMIN_WRONG_CHECKSUM: 04323 { 04324 protocol->store(STRING_WITH_LEN("note"), system_charset_info); 04325 protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)), 04326 system_charset_info); 04327 break; 04328 } 04329 04330 case HA_ADMIN_NEEDS_UPGRADE: 04331 case HA_ADMIN_NEEDS_ALTER: 04332 { 04333 char buf[ERRMSGSIZE]; 04334 uint length; 04335 04336 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04337 length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name); 04338 protocol->store(buf, length, system_charset_info); 04339 fatal_error=1; 04340 break; 04341 } 04342 04343 default: // Probably HA_ADMIN_INTERNAL_ERROR 04344 { 04345 char buf[ERRMSGSIZE+20]; 04346 uint length=my_snprintf(buf, ERRMSGSIZE, 04347 "Unknown - internal error %d during operation", 04348 result_code); 04349 protocol->store(STRING_WITH_LEN("error"), system_charset_info); 04350 protocol->store(buf, length, system_charset_info); 04351 fatal_error=1; 04352 break; 04353 } 04354 } 04355 if (table->table) 04356 { 04357 /* in the below check we do not refresh the log tables */ 04358 if (fatal_error) 04359 table->table->s->version=0; // Force close of table 04360 else if (open_for_modify && !table->table->s->log_table) 04361 { 04362 if (table->table->s->tmp_table) 04363 table->table->file->info(HA_STATUS_CONST); 04364 else 04365 { 04366 pthread_mutex_lock(&LOCK_open); 04367 remove_table_from_cache(thd, table->table->s->db.str, 04368 table->table->s->table_name.str, RTFC_NO_FLAG); 04369 pthread_mutex_unlock(&LOCK_open); 04370 } 04371 /* May be something modified consequently we have to invalidate cache */ 04372 query_cache_invalidate3(thd, table->table, 0); 04373 } 04374 } 04375 ha_autocommit_or_rollback(thd, 0); 04376 close_thread_tables(thd); 04377 table->table=0; // For query cache 04378 if (protocol->write()) 04379 goto err; 04380 } 04381 04382 send_eof(thd); 04383 DBUG_RETURN(FALSE); 04384 04385 err: 04386 ha_autocommit_or_rollback(thd, 1); 04387 close_thread_tables(thd); // Shouldn't be needed 04388 if (table) 04389 table->table=0; 04390 DBUG_RETURN(TRUE); 04391 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_alter_table | ( | THD * | thd, | |
| char * | new_db, | |||
| char * | new_name, | |||
| HA_CREATE_INFO * | lex_create_info, | |||
| TABLE_LIST * | table_list, | |||
| List< create_field > & | fields, | |||
| List< Key > & | keys, | |||
| uint | order_num, | |||
| ORDER * | order, | |||
| bool | ignore, | |||
| ALTER_INFO * | alter_info, | |||
| bool | do_send_ok | |||
| ) |
Definition at line 5114 of file sql_table.cc.
References access, List_iterator< T >::after(), create_field::after, st_key::algorithm, st_table::alias, st_table_list::alias, handlerton::alter_table_flags, ALTER_TABLE_INDEX_CHANGED, st_ha_create_information::auto_increment_value, st_table_share::avg_row_length, st_ha_create_information::avg_row_length, st_key::block_size, build_table_filename(), bzero, handler::can_switch_engines(), create_field::change, Table_triggers_list::change_table_name(), Field::charset(), check_engine(), close_cached_table(), Alter_drop::COLUMN, Key::columns, st_table_share::comment, st_ha_create_information::comment, compare_tables(), copy_create_info(), current_pid, st_table_list::db, db, st_table_share::db_create_options, st_table_share::db_type, handlerton::db_type, st_ha_create_information::db_type, DB_TYPE_CSV_DB, DB_TYPE_MYISAM, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, Alter_column::def, create_field::def, st_ha_create_information::default_table_charset, DISABLE, handler::disable_indexes(), base_list::elements, base_list::empty(), ENABLE, handler::enable_indexes(), ER, ER_BAD_FIELD_ERROR, ER_BAD_LOG_ENGINE, ER_BLOB_CANT_HAVE_DEFAULT, ER_CANT_ALTER_LOG_TABLE, ER_CANT_DROP_FIELD_OR_KEY, ER_CANT_REMOVE_ALL_FIELDS, ER_ILLEGAL_HA, ER_ROW_IS_REFERENCED, ER_TABLE_EXISTS_ERROR, ER_WRONG_NAME_FOR_INDEX, err, error, f_is_blob, F_OK, FALSE, st_key_part_info::field, create_field::field, st_table::field, Field::field_length, create_field::field_name, Field::field_name, FIELD_TYPE_BLOB, st_table::file, files_charset_info, find(), find_temporary_table(), first_keyword, st_key::flags, create_field::flags, fn_ext(), FN_REFLEN, Key::FOREIGN_KEY, Key::FULLTEXT, Key::generated, ha_check_storage_engine_flag(), HA_CREATE_USED_AUTO, HA_CREATE_USED_AVG_ROW_LENGTH, HA_CREATE_USED_DEFAULT_CHARSET, HA_CREATE_USED_ENGINE, HA_CREATE_USED_KEY_BLOCK_SIZE, HA_CREATE_USED_MAX_ROWS, HA_CREATE_USED_MIN_ROWS, HA_CREATE_USED_PACK_KEYS, HA_ERR_WRONG_COMMAND, HA_EXTRA_FORCE_REOPEN, HA_FULLTEXT, HA_GENERATED_KEY, HA_KEY_SWITCH_NONUNIQ_SAVE, HA_LEX_CREATE_TMP_TABLE, HA_NOSAME, HA_ONLINE_DROP_INDEX, HA_ONLINE_DROP_INDEX_NO_WRITES, HA_ONLINE_DROP_PK_INDEX, HA_ONLINE_DROP_PK_INDEX_NO_WRITES, HA_ONLINE_DROP_UNIQUE_INDEX, HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES, HA_OPTION_CHECKSUM, HA_OPTION_DELAY_KEY_WRITE, HA_OPTION_NO_CHECKSUM, HA_OPTION_NO_DELAY_KEY_WRITE, HA_OPTION_PACK_KEYS, HA_OPTION_PACK_RECORD, ha_resolve_storage_engine_name(), HA_SPATIAL, HA_USES_BLOCK_SIZE, HA_USES_PARSER, HTON_ALTER_NOT_SUPPORTED, LOGGER::is_general_log_table_enabled(), LOGGER::is_slow_log_table_enabled(), key, Alter_drop::KEY, st_table_share::key_block_size, st_ha_create_information::key_block_size, Key::key_create_info, st_table::key_info, st_key::key_part, st_key::key_parts, st_key_part_info::key_type, st_table_share::keys, keys, LEAVE_AS_IS, LEX_STRING::length, create_field::length, st_key_part_info::length, LINT_INIT, LOCK_open, logger, lower_case_table_names, st_table_share::max_rows, st_ha_create_information::max_rows, charset_info_st::mbmaxlen, st_table_share::min_rows, st_ha_create_information::min_rows, MTYP_TYPENR, Key::MULTIPLE, my_casedn_str, my_error(), my_message(), my_snprintf(), my_strcasecmp, MYF, mysql_discard_or_import_tablespace(), mysql_ha_flush(), mysql_prepare_table(), mysql_rename_table(), MYSQL_TYPE_STRING, Key::name, charset_info_st::name, st_key::name, Alter_column::name, Alter_drop::name, Field::NEXT_NUMBER, NO_DEFAULT_VALUE_FLAG, NO_TMP_TABLE, open_ltable(), opt_log, opt_slow_log, st_ha_create_information::options, st_key::parser_name, path, Key::PRIMARY, primary_key_name, handler::print_error(), pthread_mutex_lock, pthread_mutex_unlock, List< T >::push_back(), List< T >::push_front(), push_warning_printf(), reg_ext, List_iterator< T >::remove(), restore_record, List_iterator< T >::rewind(), st_table_share::row_type, st_ha_create_information::row_type, ROW_TYPE_NOT_USED, st_table::s, send_ok(), set_table_default_charset(), Key::SPATIAL, create_field::sql_type, LEX_STRING::str, strmov(), system_charset_info, st_table_list::table, table_alias_charset, st_table_share::table_charset, st_table_list::table_name, st_ha_create_information::table_options, test, TL_WRITE_ALLOW_READ, tmp_file_prefix, st_table_share::tmp_table, TRUE, Key::type, Alter_drop::type, Field::type(), Field::type_can_have_key_part(), Key::UNIQUE, Field::unireg_check, handler::update_create_info(), st_table::use_all_columns(), st_ha_create_information::used_fields, st_table_share::version, VOID, wait_while_table_is_used(), MYSQL_ERROR::WARN_LEVEL_NOTE, WITH_PARTITION_STORAGE_ENGINE, and write_bin_log().
Referenced by mysql_create_index(), mysql_drop_index(), mysql_execute_command(), and mysql_recreate_table().
05120 { 05121 TABLE *table,*new_table=0; 05122 int error; 05123 char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN]; 05124 char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias; 05125 char index_file[FN_REFLEN], data_file[FN_REFLEN]; 05126 char path[FN_REFLEN]; 05127 char reg_path[FN_REFLEN+1]; 05128 ha_rows copied,deleted; 05129 uint db_create_options, used_fields; 05130 handlerton *old_db_type, *new_db_type; 05131 HA_CREATE_INFO *create_info; 05132 uint need_copy_table= 0; 05133 bool no_table_reopen= FALSE, varchar= FALSE; 05134 #ifdef WITH_PARTITION_STORAGE_ENGINE 05135 uint fast_alter_partition= 0; 05136 bool partition_changed= FALSE; 05137 #endif 05138 List<create_field> prepared_create_list; 05139 List<Key> prepared_key_list; 05140 bool need_lock_for_indexes= TRUE; 05141 uint db_options= 0; 05142 uint key_count; 05143 KEY *key_info_buffer; 05144 uint index_drop_count; 05145 uint *index_drop_buffer; 05146 uint index_add_count; 05147 uint *index_add_buffer; 05148 bool committed= 0; 05149 DBUG_ENTER("mysql_alter_table"); 05150 05151 LINT_INIT(index_add_count); 05152 LINT_INIT(index_drop_count); 05153 LINT_INIT(index_add_buffer); 05154 LINT_INIT(index_drop_buffer); 05155 05156 if (table_list && table_list->db && 05157 !my_strcasecmp(system_charset_info, table_list->db, "mysql") && 05158 table_list->table_name) 05159 { 05160 enum enum_table_kind { NOT_LOG_TABLE= 1, GENERAL_LOG, SLOW_LOG } 05161 table_kind= NOT_LOG_TABLE; 05162 05163 if (!my_strcasecmp(system_charset_info, table_list->table_name, 05164 "general_log")) 05165 table_kind= GENERAL_LOG; 05166 else 05167 if (!my_strcasecmp(system_charset_info, table_list->table_name, 05168 "slow_log")) 05169 table_kind= SLOW_LOG; 05170 05171 /* Disable alter of enabled log tables */ 05172 if ((table_kind == GENERAL_LOG && opt_log && 05173 logger.is_general_log_table_enabled()) || 05174 (table_kind == SLOW_LOG && opt_slow_log && 05175 logger.is_slow_log_table_enabled())) 05176 { 05177 my_error(ER_CANT_ALTER_LOG_TABLE, MYF(0)); 05178 DBUG_RETURN(TRUE); 05179 } 05180 05181 /* Disable alter of log tables to unsupported engine */ 05182 if ((table_kind == GENERAL_LOG || table_kind == SLOW_LOG) && 05183 (lex_create_info->used_fields & HA_CREATE_USED_ENGINE) && 05184 (!lex_create_info->db_type || /* unknown engine */ 05185 !(lex_create_info->db_type->db_type == DB_TYPE_MYISAM || 05186 lex_create_info->db_type->db_type == DB_TYPE_CSV_DB))) 05187 { 05188 my_error(ER_BAD_LOG_ENGINE, MYF(0)); 05189 DBUG_RETURN(TRUE); 05190 } 05191 } 05192 05193 thd->proc_info="init"; 05194 if (!(create_info= copy_create_info(lex_create_info))) 05195 { 05196 DBUG_RETURN(TRUE); 05197 } 05198 table_name=table_list->table_name; 05199 alias= (lower_case_table_names == 2) ? table_list->alias : table_name; 05200 db=table_list->db; 05201 if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db)) 05202 new_db= db; 05203 build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0); 05204 build_table_filename(path, sizeof(path), db, table_name, "", 0); 05205 05206 used_fields=create_info->used_fields; 05207 05208 mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE); 05209 05210 /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ 05211 if (alter_info->tablespace_op != NO_TABLESPACE_OP) 05212 DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, 05213 alter_info->tablespace_op)); 05214 if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) 05215 DBUG_RETURN(TRUE); 05216 table->use_all_columns(); 05217 05218 /* Check that we are not trying to rename to an existing table */ 05219 if (new_name) 05220 { 05221 DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name)); 05222 strmov(new_name_buff,new_name); 05223 strmov(new_alias= new_alias_buff, new_name); 05224 if (lower_case_table_names) 05225 { 05226 if (lower_case_table_names != 2) 05227 { 05228 my_casedn_str(files_charset_info, new_name_buff); 05229 new_alias= new_name; // Create lower case table name 05230 } 05231 my_casedn_str(files_charset_info, new_name); 05232 } 05233 if (new_db == db && 05234 !my_strcasecmp(table_alias_charset, new_name_buff, table_name)) 05235 { 05236 /* 05237 Source and destination table names are equal: make later check 05238 easier. 05239 */ 05240 new_alias= new_name= table_name; 05241 } 05242 else 05243 { 05244 if (table->s->tmp_table != NO_TMP_TABLE) 05245 { 05246 if (find_temporary_table(thd,new_db,new_name_buff)) 05247 { 05248 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); 05249 DBUG_RETURN(TRUE); 05250 } 05251 } 05252 else 05253 { 05254 build_table_filename(new_name_buff, sizeof(new_name_buff), 05255 new_db, new_name_buff, reg_ext, 0); 05256 if (!access(new_name_buff, F_OK)) 05257 { 05258 /* Table will be closed in do_command() */ 05259 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); 05260 DBUG_RETURN(TRUE); 05261 } 05262 } 05263 } 05264 } 05265 else 05266 { 05267 new_alias= (lower_case_table_names == 2) ? alias : table_name; 05268 new_name= table_name; 05269 } 05270 05271 old_db_type= table->s->db_type; 05272 if (!create_info->db_type) 05273 { 05274 #ifdef WITH_PARTITION_STORAGE_ENGINE 05275 if (table->part_info && 05276 create_info->used_fields & HA_CREATE_USED_ENGINE) 05277 { 05278 /* 05279 This case happens when the user specified 05280 ENGINE = x where x is a non-existing storage engine 05281 We set create_info->db_type to default_engine_type 05282 to ensure we don't change underlying engine type 05283 due to a erroneously given engine name. 05284 */ 05285 create_info->db_type= table->part_info->default_engine_type; 05286 } 05287 else 05288 #endif 05289 create_info->db_type= old_db_type; 05290 } 05291 05292 #ifdef WITH_PARTITION_STORAGE_ENGINE 05293 if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type, 05294 &partition_changed, &fast_alter_partition)) 05295 { 05296 DBUG_RETURN(TRUE); 05297 } 05298 #endif 05299 if (check_engine(thd, new_name, create_info)) 05300 DBUG_RETURN(TRUE); 05301 new_db_type= create_info->db_type; 05302 if (create_info->row_type == ROW_TYPE_NOT_USED) 05303 create_info->row_type= table->s->row_type; 05304 05305 DBUG_PRINT("info", ("old type: %s new type: %s", 05306 ha_resolve_storage_engine_name(old_db_type), 05307 ha_resolve_storage_engine_name(new_db_type))); 05308 if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) || 05309 ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED)) 05310 { 05311 DBUG_PRINT("info", ("doesn't support alter")); 05312 my_error(ER_ILLEGAL_HA, MYF(0), table_name); 05313 DBUG_RETURN(TRUE); 05314 } 05315 05316 thd->proc_info="setup"; 05317 if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && 05318 !table->s->tmp_table) // no need to touch frm 05319 { 05320 error=0; 05321 if (new_name != table_name || new_db != db) 05322 { 05323 thd->proc_info="rename"; 05324 VOID(pthread_mutex_lock(&LOCK_open)); 05325 /* Then do a 'simple' rename of the table */ 05326 error=0; 05327 if (!access(new_name_buff,F_OK)) 05328 { 05329 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name); 05330 error= -1; 05331 } 05332 else 05333 { 05334 *fn_ext(new_name)=0; 05335 table->s->version= 0; // Force removal of table def 05336 close_cached_table(thd, table); 05337 if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0)) 05338 error= -1; 05339 else if (Table_triggers_list::change_table_name(thd, db, table_name, 05340 new_db, new_alias)) 05341 { 05342 VOID(mysql_rename_table(old_db_type, new_db, new_alias, db, 05343 table_name, 0)); 05344 error= -1; 05345 } 05346 } 05347 VOID(pthread_mutex_unlock(&LOCK_open)); 05348 } 05349 05350 if (!error) 05351 { 05352 switch (alter_info->keys_onoff) { 05353 case LEAVE_AS_IS: 05354 break; 05355 case ENABLE: 05356 VOID(pthread_mutex_lock(&LOCK_open)); 05357 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); 05358 VOID(pthread_mutex_unlock(&LOCK_open)); 05359 error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); 05360 /* COND_refresh will be signaled in close_thread_tables() */ 05361 break; 05362 case DISABLE: 05363 VOID(pthread_mutex_lock(&LOCK_open)); 05364 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); 05365 VOID(pthread_mutex_unlock(&LOCK_open)); 05366 error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); 05367 /* COND_refresh will be signaled in close_thread_tables() */ 05368 break; 05369 } 05370 } 05371 05372 if (error == HA_ERR_WRONG_COMMAND) 05373 { 05374 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 05375 ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), 05376 table->alias); 05377 error=0; 05378 } 05379 if (!error) 05380 { 05381 write_bin_log(thd, TRUE, thd->query, thd->query_length); 05382 if (do_send_ok) 05383 send_ok(thd); 05384 } 05385 else if (error > 0) 05386 { 05387 table->file->print_error(error, MYF(0)); 05388 error= -1; 05389 } 05390 table_list->table=0; // For query cache 05391 query_cache_invalidate3(thd, table_list, 0); 05392 DBUG_RETURN(error); 05393 } 05394 05395 /* Full alter table */ 05396 05397 /* Let new create options override the old ones */ 05398 if (!(used_fields & HA_CREATE_USED_MIN_ROWS)) 05399 create_info->min_rows= table->s->min_rows; 05400 if (!(used_fields & HA_CREATE_USED_MAX_ROWS)) 05401 create_info->max_rows= table->s->max_rows; 05402 if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) 05403 create_info->avg_row_length= table->s->avg_row_length; 05404 if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) 05405 create_info->default_table_charset= table->s->table_charset; 05406 if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) 05407 create_info->key_block_size= table->s->key_block_size; 05408 05409 restore_record(table, s->default_values); // Empty record for DEFAULT 05410 List_iterator<Alter_drop> drop_it(alter_info->drop_list); 05411 List_iterator<create_field> def_it(fields); 05412 List_iterator<Alter_column> alter_it(alter_info->alter_list); 05413 List<create_field> create_list; // Add new fields here 05414 List<Key> key_list; // Add new keys here 05415 create_field *def; 05416 05417 /* 05418 First collect all fields from table which isn't in drop_list 05419 */ 05420 05421 Field **f_ptr,*field; 05422 for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) 05423 { 05424 if (field->type() == MYSQL_TYPE_STRING) 05425 varchar= TRUE; 05426 /* Check if field should be dropped */ 05427 Alter_drop *drop; 05428 drop_it.rewind(); 05429 while ((drop=drop_it++)) 05430 { 05431 if (drop->type == Alter_drop::COLUMN && 05432 !my_strcasecmp(system_charset_info,field->field_name, drop->name)) 05433 { 05434 /* Reset auto_increment value if it was dropped */ 05435 if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && 05436 !(used_fields & HA_CREATE_USED_AUTO)) 05437 { 05438 create_info->auto_increment_value=0; 05439 create_info->used_fields|=HA_CREATE_USED_AUTO; 05440 } 05441 break; 05442 } 05443 } 05444 if (drop) 05445 { 05446 drop_it.remove(); 05447 continue; 05448 } 05449 /* Check if field is changed */ 05450 def_it.rewind(); 05451 while ((def=def_it++)) 05452 { 05453 if (def->change && 05454 !my_strcasecmp(system_charset_info,field->field_name, def->change)) 05455 break; 05456 } 05457 if (def) 05458 { // Field is changed 05459 def->field=field; 05460 if (!def->after) 05461 { 05462 create_list.push_back(def); 05463 def_it.remove(); 05464 } 05465 } 05466 else 05467 { 05468 /* 05469 This field was not dropped and not changed, add it to the list 05470 for the new table. 05471 */ 05472 create_list.push_back(def=new create_field(field,field)); 05473 alter_it.rewind(); // Change default if ALTER 05474 Alter_column *alter; 05475 while ((alter=alter_it++)) 05476 { 05477 if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) 05478 break; 05479 } 05480 if (alter) 05481 { 05482 if (def->sql_type == FIELD_TYPE_BLOB) 05483 { 05484 my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); 05485 DBUG_RETURN(TRUE); 05486 } 05487 if ((def->def=alter->def)) // Use new default 05488 def->flags&= ~NO_DEFAULT_VALUE_FLAG; 05489 else 05490 def->flags|= NO_DEFAULT_VALUE_FLAG; 05491 alter_it.remove(); 05492 } 05493 } 05494 } 05495 def_it.rewind(); 05496 List_iterator<create_field> find_it(create_list); 05497 while ((def=def_it++)) // Add new columns 05498 { 05499 if (def->change && ! def->field) 05500 { 05501 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name); 05502 DBUG_RETURN(TRUE); 05503 } 05504 if (!def->after) 05505 create_list.push_back(def); 05506 else if (def->after == first_keyword) 05507 create_list.push_front(def); 05508 else 05509 { 05510 create_field *find; 05511 find_it.rewind(); 05512 while ((find=find_it++)) // Add new columns 05513 { 05514 if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) 05515 break; 05516 } 05517 if (!find) 05518 { 05519 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name); 05520 DBUG_RETURN(TRUE); 05521 } 05522 find_it.after(def); // Put element after this 05523 } 05524 } 05525 if (alter_info->alter_list.elements) 05526 { 05527 my_error(ER_BAD_FIELD_ERROR, MYF(0), 05528 alter_info->alter_list.head()->name, table_name); 05529 DBUG_RETURN(TRUE); 05530 } 05531 if (!create_list.elements) 05532 { 05533 my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS), 05534 MYF(0)); 05535 DBUG_RETURN(TRUE); 05536 } 05537 05538 /* 05539 Collect all keys which isn't in drop list. Add only those 05540 for which some fields exists. 05541 */ 05542 05543 List_iterator<Key> key_it(keys); 05544 List_iterator<create_field> field_it(create_list); 05545 List<key_part_spec> key_parts; 05546 05547 KEY *key_info=table->key_info; 05548 for (uint i=0 ; i < table->s->keys ; i++,key_info++) 05549 { 05550 char *key_name= key_info->name; 05551 Alter_drop *drop; 05552 drop_it.rewind(); 05553 while ((drop=drop_it++)) 05554 { 05555 if (drop->type == Alter_drop::KEY && 05556 !my_strcasecmp(system_charset_info,key_name, drop->name)) 05557 break; 05558 } 05559 if (drop) 05560 { 05561 drop_it.remove(); 05562 continue; 05563 } 05564 05565 KEY_PART_INFO *key_part= key_info->key_part; 05566 key_parts.empty(); 05567 for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) 05568 { 05569 if (!key_part->field) 05570 continue; // Wrong field (from UNIREG) 05571 const char *key_part_name=key_part->field->field_name; 05572 create_field *cfield; 05573 field_it.rewind(); 05574 while ((cfield=field_it++)) 05575 { 05576 if (cfield->change) 05577 { 05578 if (!my_strcasecmp(system_charset_info, key_part_name, 05579 cfield->change)) 05580 break; 05581 } 05582 else if (!my_strcasecmp(system_charset_info, 05583 key_part_name, cfield->field_name)) 05584 break; 05585 } 05586 if (!cfield) 05587 continue; // Field is removed 05588 uint key_part_length=key_part->length; 05589 if (cfield->field) // Not new field 05590 { 05591 /* 05592 If the field can't have only a part used in a key according to its 05593 new type, or should not be used partially according to its 05594 previous type, or the field length is less than the key part 05595 length, unset the key part length. 05596 05597 We also unset the key part length if it is the same as the 05598 old field's length, so the whole new field will be used. 05599 05600 BLOBs may have cfield->length == 0, which is why we test it before 05601 checking whether cfield->length < key_part_length (in chars). 05602 */ 05603 if (!Field::type_can_have_key_part(cfield->field->type()) || 05604 !Field::type_can_have_key_part(cfield->sql_type) || 05605 (cfield->field->field_length == key_part_length && 05606 !f_is_blob(key_part->key_type)) || 05607 (cfield->length && (cfield->length < key_part_length / 05608 key_part->field->charset()->mbmaxlen))) 05609 key_part_length= 0; // Use whole field 05610 } 05611 key_part_length /= key_part->field->charset()->mbmaxlen; 05612 key_parts.push_back(new key_part_spec(cfield->field_name, 05613 key_part_length)); 05614 } 05615 if (key_parts.elements) 05616 { 05617 KEY_CREATE_INFO key_create_info; 05618 bzero((char*) &key_create_info, sizeof(key_create_info)); 05619 05620 key_create_info.algorithm= key_info->algorithm; 05621 if (key_info->flags & HA_USES_BLOCK_SIZE) 05622 key_create_info.block_size= key_info->block_size; 05623 if (key_info->flags & HA_USES_PARSER) 05624 key_create_info.parser_name= *key_info->parser_name; 05625 05626 key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : 05627 (key_info->flags & HA_NOSAME ? 05628 (!my_strcasecmp(system_charset_info, 05629 key_name, primary_key_name) ? 05630 Key::PRIMARY : Key::UNIQUE) : 05631 (key_info->flags & HA_FULLTEXT ? 05632 Key::FULLTEXT : Key::MULTIPLE)), 05633 key_name, 05634 &key_create_info, 05635 test(key_info->flags & HA_GENERATED_KEY), 05636 key_parts)); 05637 } 05638 } 05639 { 05640 Key *key; 05641 while ((key=key_it++)) // Add new keys 05642 { 05643 if (key->type != Key::FOREIGN_KEY) 05644 key_list.push_back(key); 05645 if (key->name && 05646 !my_strcasecmp(system_charset_info,key->name,primary_key_name)) 05647 { 05648 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); 05649 DBUG_RETURN(TRUE); 05650 } 05651 } 05652 } 05653 05654 if (alter_info->drop_list.elements) 05655 { 05656 my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), 05657 alter_info->drop_list.head()->name); 05658 goto err; 05659 } 05660 if (alter_info->alter_list.elements) 05661 { 05662 my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), 05663 alter_info->alter_list.head()->name); 05664 goto err; 05665 } 05666 05667 db_create_options= table->s->db_create_options & ~(HA_OPTION_PACK_RECORD); 05668 my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix, 05669 current_pid, thd->thread_id); 05670 /* Safety fix for innodb */ 05671 if (lower_case_table_names) 05672 my_casedn_str(files_charset_info, tmp_name); 05673 if (new_db_type != old_db_type && !table->file->can_switch_engines()) { 05674 my_error(ER_ROW_IS_REFERENCED, MYF(0)); 05675 goto err; 05676 } 05677 create_info->db_type=new_db_type; 05678 if (!create_info->comment.str) 05679 { 05680 create_info->comment.str= table->s->comment.str; 05681 create_info->comment.length= table->s->comment.length; 05682 } 05683 05684 table->file->update_create_info(create_info); 05685 if ((create_info->table_options & 05686 (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) || 05687 (used_fields & HA_CREATE_USED_PACK_KEYS)) 05688 db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); 05689 if (create_info->table_options & 05690 (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM)) 05691 db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM); 05692 if (create_info->table_options & 05693 (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE)) 05694 db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE | 05695 HA_OPTION_NO_DELAY_KEY_WRITE); 05696 create_info->table_options|= db_create_options; 05697 05698 if (table->s->tmp_table) 05699 create_info->options|=HA_LEX_CREATE_TMP_TABLE; 05700 05701 set_table_default_charset(thd, create_info, db); 05702 05703 { 05704 /* 05705 For some purposes we need prepared table structures and translated 05706 key descriptions with proper default key name assignment. 05707 05708 Unfortunately, mysql_prepare_table() modifies the field and key 05709 lists. mysql_create_table() needs the unmodified lists. Hence, we 05710 need to copy the lists and all their elements. The lists contain 05711 pointers to the elements only. 05712 05713 We cannot copy conditionally because the partition code always 05714 needs prepared lists and compare_tables() needs them and is almost 05715 always called. 05716 */ 05717 05718 /* Copy fields. */ 05719 List_iterator<create_field> prep_field_it(create_list); 05720 create_field *prep_field; 05721 while ((prep_field= prep_field_it++)) 05722 prepared_create_list.push_back(new create_field(*prep_field)); 05723 05724 /* Copy keys and key parts. */ 05725 List_iterator<Key> prep_key_it(key_list); 05726 Key *prep_key; 05727 while ((prep_key= prep_key_it++)) 05728 { 05729 List<key_part_spec> prep_columns; 05730 List_iterator<key_part_spec> prep_col_it(prep_key->columns); 05731 key_part_spec *prep_col; 05732 05733 while ((prep_col= prep_col_it++)) 05734 prep_columns.push_back(new key_part_spec(*prep_col)); 05735 prepared_key_list.push_back(new Key(prep_key->type, prep_key->name, 05736 &prep_key->key_create_info, 05737 prep_key->generated, prep_columns)); 05738 } 05739 05740 /* Create the prepared information. */ 05741 if (mysql_prepare_table(thd, create_info, &prepared_create_list, 05742 &prepared_key_list, 05743 (table->s->tmp_table != NO_TMP_TABLE), &db_options, 05744 table->file, &key_info_buffer, &key_count, 0)) 05745 goto err; 05746 } 05747 05748 if (thd->variables.old_alter_table 05749 || (table->s->db_type != create_info->db_type) 05750 #ifdef WITH_PARTITION_STORAGE_ENGINE 05751 || partition_changed 05752 #endif 05753 ) 05754 need_copy_table= 1; 05755 else 05756 { 05757 /* Try to optimize ALTER TABLE. Allocate result buffers. */ 05758 if (! (index_drop_buffer= 05759 (uint*) thd->alloc(sizeof(uint) * table->s->keys)) || 05760 ! (index_add_buffer= 05761 (uint*) thd->alloc(sizeof(uint) * prepared_key_list.elements))) 05762 goto err; 05763 /* Check how much the tables differ. */ 05764 need_copy_table= compare_tables(table, &prepared_create_list, 05765 key_info_buffer, key_count, 05766 create_info, alter_info, order_num, 05767 index_drop_buffer, &index_drop_count, 05768 index_add_buffer, &index_add_count, 05769 varchar); 05770 } 05771 05772 /* 05773 If there are index changes only, try to do them online. "Index 05774 changes only" means also that the handler for the table does not 05775 change. The table is open and locked. The handler can be accessed. 05776 */ 05777 if (need_copy_table == ALTER_TABLE_INDEX_CHANGED) 05778 { 05779 int pk_changed= 0; 05780 ulong alter_flags= 0; 05781 ulong needed_online_flags= 0; 05782 ulong needed_fast_flags= 0; 05783 KEY *key; 05784 uint *idx_p; 05785 uint *idx_end_p; 05786 05787 if (table->s->db_type->alter_table_flags) 05788 alter_flags= table->s->db_type->alter_table_flags(alter_info->flags); 05789 DBUG_PRINT("info", ("alter_flags: %lu", alter_flags)); 05790 /* Check dropped indexes. */ 05791 for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count; 05792 idx_p < idx_end_p; 05793 idx_p++) 05794 { 05795 key= table->key_info + *idx_p; 05796 DBUG_PRINT("info", ("index dropped: '%s'", key->name)); 05797 if (key->flags & HA_NOSAME) 05798 { 05799 /* Unique key. Check for "PRIMARY". */ 05800 if (! my_strcasecmp(system_charset_info, 05801 key->name, primary_key_name)) 05802 { 05803 /* Primary key. */ 05804 needed_online_flags|= HA_ONLINE_DROP_PK_INDEX; 05805 needed_fast_flags|= HA_ONLINE_DROP_PK_INDEX_NO_WRITES; 05806 pk_changed++; 05807 } 05808 else 05809 { 05810 /* Non-primary unique key. */ 05811 needed_online_flags|= HA_ONLINE_DROP_UNIQUE_INDEX; 05812 needed_fast_flags|= HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES; 05813 } 05814 } 05815 else 05816 { 05817 /* Non-unique key. */ 05818 needed_online_flags|= HA_ONLINE_DROP_INDEX; 05819 needed_fast_flags|= HA_ONLINE_DROP_INDEX_NO_WRITES; 05820 } 05821 } 05822 05823 /* Check added indexes. */ 05824 for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count; 05825 idx_p < idx_end_p; 05826 idx_p++) 05827 { 05828 key= key_info_buffer + *idx_p; 05829 DBUG_PRINT("info", ("index added: '%s'", key->name)); 05830 if (key->flags & HA_NOSAME) 05831 { 05832 /* Unique key. Check for "PRIMARY". */ 05833 if (! my_strcasecmp(system_charset_info, 05834 key->name, primary_key_name)) 05835 { 05836 /* Primary key. */ 05837 needed_online_flags|= HA_ONLINE_ADD_PK_INDEX; 05838 needed_fast_flags|= HA_ONLINE_ADD_PK_INDEX_NO_WRITES; 05839 pk_changed++; 05840 } 05841 else 05842 { 05843 /* Non-primary unique key. */ 05844 needed_online_flags|= HA_ONLINE_ADD_UNIQUE_INDEX; 05845 needed_fast_flags|= HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES; 05846 } 05847 } 05848 else 05849 { 05850 /* Non-unique key. */ 05851 needed_online_flags|= HA_ONLINE_ADD_INDEX; 05852 needed_fast_flags|= HA_ONLINE_ADD_INDEX_NO_WRITES; 05853 } 05854 } 05855 05856 /* 05857 Online or fast add/drop index is possible only if 05858 the primary key is not added and dropped in the same statement. 05859 Otherwise we have to recreate the table. 05860 need_copy_table is no-zero at this place. 05861 */ 05862 if ( pk_changed < 2 ) 05863 { 05864 if ((alter_flags & needed_online_flags) == needed_online_flags) 05865 { 05866 /* All required online flags are present. */ 05867 need_copy_table= 0; 05868 need_lock_for_indexes= FALSE; 05869 } 05870 else if ((alter_flags & needed_fast_flags) == needed_fast_flags) 05871 { 05872 /* All required fast flags are present. */ 05873 need_copy_table= 0; 05874 } 05875 } 05876 DBUG_PRINT("info", ("need_copy_table: %u need_lock: %d", 05877 need_copy_table, need_lock_for_indexes)); 05878 } 05879 05880 /* 05881 better have a negative test here, instead of positive, like 05882 alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|... 05883 so that ALTER TABLE won't break when somebody will add new flag 05884 */ 05885 if (!need_copy_table) 05886 create_info->frm_only= 1; 05887 05888 #ifdef WITH_PARTITION_STORAGE_ENGINE 05889 if (fast_alter_partition) 05890 { 05891 DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, 05892 create_info, table_list, 05893 &create_list, &key_list, 05894 db, table_name, 05895 fast_alter_partition)); 05896 } 05897 #endif 05898 05899 /* 05900 Handling of symlinked tables: 05901 If no rename: 05902 Create new data file and index file on the same disk as the 05903 old data and index files. 05904 Copy data. 05905 Rename new data file over old data file and new index file over 05906 old index file. 05907 Symlinks are not changed. 05908 05909 If rename: 05910 Create new data file and index file on the same disk as the 05911 old data and index files. Create also symlinks to point at 05912 the new tables. 05913 Copy data. 05914 At end, rename temporary tables and symlinks to temporary table 05915 to final table name. 05916 Remove old table and old symlinks 05917 05918 If rename is made to another database: 05919 Create new tables in new database. 05920 Copy data. 05921 Remove old table and symlinks. 05922 */ 05923 if (!strcmp(db, new_db)) // Ignore symlink if db changed 05924 { 05925 if (create_info->index_file_name) 05926 { 05927 /* Fix index_file_name to have 'tmp_name' as basename */ 05928 strmov(index_file, tmp_name); 05929 create_info->index_file_name=fn_same(index_file, 05930 create_info->index_file_name, 05931 1); 05932 } 05933 if (create_info->data_file_name) 05934 { 05935 /* Fix data_file_name to have 'tmp_name' as basename */ 05936 strmov(data_file, tmp_name); 05937 create_info->data_file_name=fn_same(data_file, 05938 create_info->data_file_name, 05939 1); 05940 } 05941 } 05942 else 05943 create_info->data_file_name=create_info->index_file_name=0; 05944 05945 /* 05946 Create a table with a temporary name. 05947 With create_info->frm_only == 1 this creates a .frm file only. 05948 We don't log the statement, it will be logged later. 05949 */ 05950 tmp_disable_binlog(thd); 05951 error= mysql_create_table(thd, new_db, tmp_name, 05952 create_info,create_list,key_list,1,0,0); 05953 reenable_binlog(thd); 05954 if (error) 05955 DBUG_RETURN(error); 05956 05957 /* Open the table if we need to copy the data. */ 05958 if (need_copy_table) 05959 { 05960 if (table->s->tmp_table) 05961 { 05962 TABLE_LIST tbl; 05963 bzero((void*) &tbl, sizeof(tbl)); 05964 tbl.db= new_db; 05965 tbl.table_name= tbl.alias= tmp_name; 05966 /* Table is in thd->temporary_tables */ 05967 new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0, 05968 MYSQL_LOCK_IGNORE_FLUSH); 05969 } 05970 else 05971 { 05972 char path[FN_REFLEN]; 05973 /* table is a normal table: Create temporary table in same directory */ 05974 build_table_filename(path, sizeof(path), new_db, tmp_name, "", 05975 FN_IS_TMP); 05976 new_table=open_temporary_table(thd, path, new_db, tmp_name,0); 05977 } 05978 if (!new_table) 05979 goto err1; 05980 } 05981 05982 /* Copy the data if necessary. */ 05983 thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields 05984 thd->cuted_fields=0L; 05985 thd->proc_info="copy to tmp table"; 05986 copied=deleted=0; 05987 if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER)) 05988 { 05989 /* We don't want update TIMESTAMP fields during ALTER TABLE. */ 05990 new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; 05991 new_table->next_number_field=new_table->found_next_number_field; 05992 error=copy_data_between_tables(table, new_table, create_list, ignore, 05993 order_num, order, &copied, &deleted); 05994 } 05995 thd->count_cuted_fields= CHECK_FIELD_IGNORE; 05996 05997 /* If we did not need to copy, we might still need to add/drop indexes. */ 05998 if (! new_table) 05999 { 06000 uint *key_numbers; 06001 uint *keyno_p; 06002 KEY *key_info; 06003 KEY *key; 06004 uint *idx_p; 06005 uint *idx_end_p; 06006 KEY_PART_INFO *key_part; 06007 KEY_PART_INFO *part_end; 06008 DBUG_PRINT("info", ("No new_table, checking add/drop index")); 06009 06010 table->file->prepare_for_alter(); 06011 if (index_add_count) 06012 { 06013 #ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892 06014 if (! need_lock_for_indexes) 06015 { 06016 /* Downgrade the write lock. */ 06017 mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE); 06018 } 06019 06020 /* Create a new .frm file for crash recovery. */ 06021 /* TODO: Must set INDEX_TO_BE_ADDED flags in the frm file. */ 06022 VOID(pthread_mutex_lock(&LOCK_open)); 06023 error= (mysql_create_frm(thd, reg_path, db, table_name, 06024 create_info, prepared_create_list, key_count, 06025 key_info_buffer, table->file) || 06026 table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG, 06027 create_info)); 06028 VOID(pthread_mutex_unlock(&LOCK_open)); 06029 if (error) 06030 goto err1; 06031 #endif 06032 06033 /* The add_index() method takes an array of KEY structs. */ 06034 key_info= (KEY*) thd->alloc(sizeof(KEY) * index_add_count); 06035 key= key_info; 06036 for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count; 06037 idx_p < idx_end_p; 06038 idx_p++, key++) 06039 { 06040 /* Copy the KEY struct. */ 06041 *key= key_info_buffer[*idx_p]; 06042 /* Fix the key parts. */ 06043 part_end= key->key_part + key->key_parts; 06044 for (key_part= key->key_part; key_part < part_end; key_part++) 06045 key_part->field= table->field[key_part->fieldnr]; 06046 } 06047 /* Add the indexes. */ 06048 if ((error= table->file->add_index(table, key_info, index_add_count))) 06049 { 06050 /* 06051 Exchange the key_info for the error message. If we exchange 06052 key number by key name in the message later, we need correct info. 06053 */ 06054 KEY *save_key_info= table->key_info; 06055 table->key_info= key_info; 06056 table->file->print_error(error, MYF(0)); 06057 table->key_info= save_key_info; 06058 goto err1; 06059 } 06060 } 06061 /*end of if (index_add_count)*/ 06062 06063 if (index_drop_count) 06064 { 06065 #ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892 06066 /* Create a new .frm file for crash recovery. */ 06067 /* TODO: Must set INDEX_IS_ADDED in the frm file. */ 06068 /* TODO: Must set INDEX_TO_BE_DROPPED in the frm file. */ 06069 VOID(pthread_mutex_lock(&LOCK_open)); 06070 error= (mysql_create_frm(thd, reg_path, db, table_name, 06071 create_info, prepared_create_list, key_count, 06072 key_info_buffer, table->file) || 06073 table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG, 06074 create_info)); 06075 VOID(pthread_mutex_unlock(&LOCK_open)); 06076 if (error) 06077 goto err1; 06078 06079 if (! need_lock_for_indexes) 06080 { 06081 LOCK_PARAM_TYPE lpt; 06082 06083 lpt.thd= thd; 06084 lpt.table= table; 06085 lpt.db= db; 06086 lpt.table_name= table_name; 06087 lpt.create_info= create_info; 06088 lpt.create_list= &create_list; 06089 lpt.key_count= key_count; 06090 lpt.key_info_buffer= key_info_buffer; 06091 abort_and_upgrade_lock(lpt); 06092 } 06093 #endif 06094 06095 /* The prepare_drop_index() method takes an array of key numbers. */ 06096 key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count); 06097 keyno_p= key_numbers; 06098 /* Get the number of each key. */ 06099 for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count; 06100 idx_p < idx_end_p; 06101 idx_p++, keyno_p++) 06102 *keyno_p= *idx_p; 06103 /* 06104 Tell the handler to prepare for drop indexes. 06105 This re-numbers the indexes to get rid of gaps. 06106 */ 06107 if ((error= table->file->prepare_drop_index(table, key_numbers, 06108 index_drop_count))) 06109 { 06110 table->file->print_error(error, MYF(0)); 06111 goto err1; 06112 } 06113 06114 #ifdef XXX_TO_BE_DONE_LATER_BY_WL3020 06115 if (! need_lock_for_indexes) 06116 { 06117 /* Downgrade the lock again. */ 06118 if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ) 06119 { 06120 LOCK_PARAM_TYPE lpt; 06121 06122 lpt.thd= thd; 06123 lpt.table= table; 06124 lpt.db= db; 06125 lpt.table_name= table_name; 06126 lpt.create_info= create_info; 06127 lpt.create_list= &create_list; 06128 lpt.key_count= key_count; 06129 lpt.key_info_buffer= key_info_buffer; 06130 close_open_tables_and_downgrade(lpt); 06131 } 06132 } 06133 #endif 06134 06135 /* Tell the handler to finally drop the indexes. */ 06136 if ((error= table->file->final_drop_index(table))) 06137 { 06138 table->file->print_error(error, MYF(0)); 06139 goto err1; 06140 } 06141 } 06142 /*end of if (index_drop_count)*/ 06143 06144 /* 06145 The final .frm file is already created as a temporary file 06146 and will be renamed to the original table name later. 06147 */ 06148 06149 /* Need to commit before a table is unlocked (NDB requirement). */ 06150 DBUG_PRINT("info", ("Committing before unlocking table")); 06151 if (ha_commit_stmt(thd) || ha_commit(thd)) 06152 goto err1; 06153 committed= 1; 06154 } 06155 /*end of if (! new_table) for add/drop index*/ 06156 06157 if (table->s->tmp_table != NO_TMP_TABLE) 06158 { 06159 /* We changed a temporary table */ 06160 if (error) 06161 goto err1; 06162 /* Close lock if this is a transactional table */ 06163 if (thd->lock) 06164 { 06165 mysql_unlock_tables(thd, thd->lock); 06166 thd->lock=0; 06167 } 06168 /* Remove link to old table and rename the new one */ 06169 close_temporary_table(thd, table, 1, 1); 06170 /* Should pass the 'new_name' as we store table name in the cache */ 06171 if (rename_temporary_table(thd, new_table, new_db, new_name)) 06172 goto err1; 06173 /* We don't replicate alter table statement on temporary tables */ 06174 if (!thd->current_stmt_binlog_row_based) 06175 write_bin_log(thd, TRUE, thd->query, thd->query_length); 06176 goto end_temporary; 06177 } 06178 06179 if (new_table) 06180 { 06181 /* close temporary table that will be the new table */ 06182 intern_close_table(new_table); 06183 my_free((gptr) new_table,MYF(0)); 06184 } 06185 VOID(pthread_mutex_lock(&LOCK_open)); 06186 if (error) 06187 { 06188 VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); 06189 VOID(pthread_mutex_unlock(&LOCK_open)); 06190 goto err; 06191 } 06192 06193 /* 06194 Data is copied. Now we rename the old table to a temp name, 06195 rename the new one to the old name, remove all entries from the old table 06196 from the cache, free all locks, close the old table and remove it. 06197 */ 06198 06199 thd->proc_info="rename result table"; 06200 my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix, 06201 current_pid, thd->thread_id); 06202 if (lower_case_table_names) 06203 my_casedn_str(files_charset_info, old_name); 06204 if (new_name != table_name || new_db != db) 06205 { 06206 if (!access(new_name_buff,F_OK)) 06207 { 06208 error=1; 06209 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); 06210 VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); 06211 VOID(pthread_mutex_unlock(&LOCK_open)); 06212 goto err; 06213 } 06214 } 06215 06216 #if !defined( __WIN__) 06217 if (table->file->has_transactions()) 06218 #endif 06219 { 06220 /* 06221 Win32 and InnoDB can't drop a table that is in use, so we must 06222 close the original table at before doing the rename 06223 */ 06224 table->s->version= 0; // Force removal of table def 06225 close_cached_table(thd, table); 06226 table=0; // Marker that table is closed 06227 no_table_reopen= TRUE; 06228 } 06229 #if !defined( __WIN__) 06230 else 06231 table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore 06232 #endif 06233 06234 06235 error=0; 06236 if (!need_copy_table) 06237 new_db_type=old_db_type= NULL; // this type cannot happen in regular ALTER 06238 if (mysql_rename_table(old_db_type, db, table_name, db, old_name, 06239 FN_TO_IS_TMP)) 06240 { 06241 error=1; 06242 VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); 06243 } 06244 else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db, 06245 new_alias, FN_FROM_IS_TMP) || 06246 (new_name != table_name || new_db != db) && // we also do rename 06247 Table_triggers_list::change_table_name(thd, db, table_name, 06248 new_db, new_alias)) 06249 { 06250 /* Try to get everything back. */ 06251 error=1; 06252 VOID(quick_rm_table(new_db_type,new_db,new_alias, 0)); 06253 VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); 06254 VOID(mysql_rename_table(old_db_type, db, old_name, db, alias, 06255 FN_FROM_IS_TMP)); 06256 } 06257 if (error) 06258 { 06259 /* 06260 This shouldn't happen. We solve this the safe way by 06261 closing the locked table. 06262 */ 06263 if (table) 06264 { 06265 table->s->version= 0; // Force removal of table def 06266 close_cached_table(thd,table); 06267 } 06268 VOID(pthread_mutex_unlock(&LOCK_open)); 06269 goto err; 06270 } 06271 if (! need_copy_table) 06272 { 06273 if (! table) 06274 { 06275 VOID(pthread_mutex_unlock(&LOCK_open)); 06276 if (! (table= open_ltable(thd, table_list, TL_WRITE_ALLOW_READ))) 06277 goto err; 06278 VOID(pthread_mutex_lock(&LOCK_open)); 06279 } 06280 /* Tell the handler that a new frm file is in place. */ 06281 if (table->file->create_handler_files(path, NULL, CHF_INDEX_FLAG, 06282 create_info)) 06283 { 06284 VOID(pthread_mutex_unlock(&LOCK_open)); 06285 goto err; 06286 } 06287 } 06288 if (thd->lock || new_name != table_name || no_table_reopen) // True if WIN32 06289 { 06290 /* 06291 Not table locking or alter table with rename. 06292 Free locks and remove old table 06293 */ 06294 if (table) 06295 { 06296 table->s->version= 0; // Force removal of table def 06297 close_cached_table(thd,table); 06298 } 06299 VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); 06300 } 06301 else 06302 { 06303 /* 06304 Using LOCK TABLES without rename. 06305 This code is never executed on WIN32! 06306 Remove old renamed table, reopen table and get new locks 06307 */ 06308 if (table) 06309 { 06310 VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file 06311 /* Mark in-use copies old */ 06312 remove_table_from_cache(thd,db,table_name,RTFC_NO_FLAG); 06313 /* end threads waiting on lock */ 06314 mysql_lock_abort(thd,table, TRUE); 06315 } 06316 VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); 06317 if (close_data_tables(thd,db,table_name) || 06318 reopen_tables(thd,1,0)) 06319 { // This shouldn't happen 06320 if (table) 06321 { 06322 table->s->version= 0; // Force removal of table def 06323 close_cached_table(thd,table); // Remove lock for table 06324 } 06325 VOID(pthread_mutex_unlock(&LOCK_open)); 06326 goto err; 06327 } 06328 } 06329 VOID(pthread_mutex_unlock(&LOCK_open)); 06330 broadcast_refresh(); 06331 /* 06332 The ALTER TABLE is always in its own transaction. 06333 Commit must not be called while LOCK_open is locked. It could call 06334 wait_if_global_read_lock(), which could create a deadlock if called 06335 with LOCK_open. 06336 */ 06337 if (!committed) 06338 { 06339 error = ha_commit_stmt(thd); 06340 if (ha_commit(thd)) 06341 error=1; 06342 if (error) 06343 goto err; 06344 } 06345 thd->proc_info="end"; 06346 06347 ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE, 06348 thd->query, thd->query_length, 06349 db, table_name); 06350 06351 DBUG_ASSERT(!(mysql_bin_log.is_open() && thd->current_stmt_binlog_row_based && 06352 (create_info->options & HA_LEX_CREATE_TMP_TABLE))); 06353 write_bin_log(thd, TRUE, thd->query, thd->query_length); 06354 /* 06355 TODO RONM: This problem needs to handled for Berkeley DB partitions 06356 as well 06357 */ 06358 if (ha_check_storage_engine_flag(old_db_type,HTON_FLUSH_AFTER_RENAME)) 06359 { 06360 /* 06361 For the alter table to be properly flushed to the logs, we 06362 have to open the new table. If not, we get a problem on server 06363 shutdown. 06364 */ 06365 char path[FN_REFLEN]; 06366 build_table_filename(path, sizeof(path), new_db, table_name, "", 0); 06367 table=open_temporary_table(thd, path, new_db, tmp_name,0); 06368 if (table) 06369 { 06370 intern_close_table(table); 06371 my_free((char*) table, MYF(0)); 06372 } 06373 else 06374 sql_print_warning("Could not open table %s.%s after rename\n", 06375 new_db,table_name); 06376 ha_flush_logs(old_db_type); 06377 } 06378 table_list->table=0; // For query cache 06379 query_cache_invalidate3(thd, table_list, 0); 06380 06381 end_temporary: 06382 my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), 06383 (ulong) (copied + deleted), (ulong) deleted, 06384 (ulong) thd->cuted_fields); 06385 if (do_send_ok) 06386 send_ok(thd,copied+deleted,0L,tmp_name); 06387 thd->some_tables_deleted=0; 06388 DBUG_RETURN(FALSE); 06389 06390 err1: 06391 if (new_table) 06392 { 06393 /* close_temporary_table() frees the new_table pointer. */ 06394 close_temporary_table(thd, new_table, 1, 1); 06395 } 06396 else 06397 VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); 06398 06399 err: 06400 DBUG_RETURN(TRUE); 06401 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_analyze_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) |
Definition at line 4774 of file sql_table.cc.
References handler::analyze(), DBUG_ENTER, DBUG_RETURN, mysql_admin_table(), and TL_READ_NO_INSERT.
Referenced by mysql_execute_command().
04775 { 04776 thr_lock_type lock_type = TL_READ_NO_INSERT; 04777 04778 DBUG_ENTER("mysql_analyze_table"); 04779 DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, 04780 "analyze", lock_type, 1, 0, 0, 0, 04781 &handler::analyze, 0)); 04782 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_assign_to_keycache | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| LEX_STRING * | key_cache_name | |||
| ) |
Definition at line 4447 of file sql_table.cc.
References handler::assign_to_keycache(), DBUG_ENTER, DBUG_RETURN, ER_UNKNOWN_KEY_CACHE, get_key_cache(), st_ha_check_opt::init(), st_ha_check_opt::key_cache, LOCK_global_system_variables, my_error(), MYF, mysql_admin_table(), pthread_mutex_lock, pthread_mutex_unlock, LEX_STRING::str, TL_READ_NO_INSERT, and TRUE.
Referenced by mysql_execute_command().
04449 { 04450 HA_CHECK_OPT check_opt; 04451 KEY_CACHE *key_cache; 04452 DBUG_ENTER("mysql_assign_to_keycache"); 04453 04454 check_opt.init(); 04455 pthread_mutex_lock(&LOCK_global_system_variables); 04456 if (!(key_cache= get_key_cache(key_cache_name))) 04457 { 04458 pthread_mutex_unlock(&LOCK_global_system_variables); 04459 my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str); 04460 DBUG_RETURN(TRUE); 04461 } 04462 pthread_mutex_unlock(&LOCK_global_system_variables); 04463 check_opt.key_cache= key_cache; 04464 DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, 04465 "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, 04466 0, 0, &handler::assign_to_keycache, 0)); 04467 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_backup_table | ( | THD * | thd, | |
| TABLE_LIST * | table_list | |||
| ) |
Definition at line 4394 of file sql_table.cc.
References handler::backup(), DBUG_ENTER, DBUG_RETURN, mysql_admin_table(), and TL_READ.
Referenced by mysql_execute_command().
04395 { 04396 DBUG_ENTER("mysql_backup_table"); 04397 DBUG_RETURN(mysql_admin_table(thd, table_list, 0, 04398 "backup", TL_READ, 0, 0, 0, 0, 04399 &handler::backup, 0)); 04400 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_check_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) |
Definition at line 4785 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, handler::ha_check(), HA_OPEN_FOR_REPAIR, mysql_admin_table(), TL_READ_NO_INSERT, and view_checksum().
Referenced by mysql_execute_command().
04786 { 04787 thr_lock_type lock_type = TL_READ_NO_INSERT; 04788 04789 DBUG_ENTER("mysql_check_table"); 04790 DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, 04791 "check", lock_type, 04792 0, HA_OPEN_FOR_REPAIR, 0, 0, 04793 &handler::ha_check, &view_checksum)); 04794 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_checksum_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) |
Definition at line 6631 of file sql_table.cc.
References handler::checksum(), close_thread_tables(), st_table_list::db, st_table_share::db_create_options, DBUG_ENTER, DBUG_RETURN, err, f, FALSE, st_table::field, FIELD_TYPE_BLOB, st_table_share::fields, st_table::file, st_ha_check_opt::flags, HA_ERR_RECORD_DELETED, HA_HAS_CHECKSUM, HA_OPTION_PACK_RECORD, handler::ha_rnd_end(), handler::ha_rnd_init(), handler::ha_table_flags(), st_table_share::last_null_bit_pos, String::length(), Item::maybe_null, my_checksum(), MYSQL_TYPE_VARCHAR, NAME_LEN, st_table_list::next_local, st_table_share::null_bytes, NullS, open_ltable(), st_table::pos_in_table_list, Protocol::prepare_for_resend(), String::ptr(), List< T >::push_back(), st_table::record, handler::rnd_next(), st_table::s, send_eof(), Protocol::SEND_EOF, Protocol::send_fields(), Protocol::SEND_NUM_ROWS, Protocol::store(), Protocol::store_null(), strxmov(), system_charset_info, T_EXTEND, T_QUICK, st_table_list::table, st_table_list::table_name, TL_READ, TRUE, unlikely, st_table::use_all_columns(), and Protocol::write().
Referenced by mysql_execute_command().
06633 { 06634 TABLE_LIST *table; 06635 List<Item> field_list; 06636 Item *item; 06637 Protocol *protocol= thd->protocol; 06638 DBUG_ENTER("mysql_checksum_table"); 06639 06640 field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2)); 06641 item->maybe_null= 1; 06642 field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21)); 06643 item->maybe_null= 1; 06644 if (protocol->send_fields(&field_list, 06645 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 06646 DBUG_RETURN(TRUE); 06647 06648 for (table= tables; table; table= table->next_local) 06649 { 06650 char table_name[NAME_LEN*2+2]; 06651 TABLE *t; 06652 06653 strxmov(table_name, table->db ,".", table->table_name, NullS); 06654 06655 t= table->table= open_ltable(thd, table, TL_READ); 06656 thd->clear_error(); // these errors shouldn't get client 06657 06658 protocol->prepare_for_resend(); 06659 protocol->store(table_name, system_charset_info); 06660 06661 if (!t) 06662 { 06663 /* Table didn't exist */ 06664 protocol->store_null(); 06665 thd->clear_error(); 06666 } 06667 else 06668 { 06669 t->pos_in_table_list= table; 06670 06671 if (t->file->ha_table_flags() & HA_HAS_CHECKSUM && 06672 !(check_opt->flags & T_EXTEND)) 06673 protocol->store((ulonglong)t->file->checksum()); 06674 else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) && 06675 (check_opt->flags & T_QUICK)) 06676 protocol->store_null(); 06677 else 06678 { 06679 /* calculating table's checksum */ 06680 ha_checksum crc= 0; 06681 uchar null_mask=256 - (1 << t->s->last_null_bit_pos); 06682 06683 t->use_all_columns(); 06684 06685 if (t->file->ha_rnd_init(1)) 06686 protocol->store_null(); 06687 else 06688 { 06689 for (;;) 06690 { 06691 ha_checksum row_crc= 0; 06692 int error= t->file->rnd_next(t->record[0]); 06693 if (unlikely(error)) 06694 { 06695 if (error == HA_ERR_RECORD_DELETED) 06696 continue; 06697 break; 06698 } 06699 if (t->s->null_bytes) 06700 { 06701 /* fix undefined null bits */ 06702 t->record[0][t->s->null_bytes-1] |= null_mask; 06703 if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD)) 06704 t->record[0][0] |= 1; 06705 06706 row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes); 06707 } 06708 06709 for (uint i= 0; i < t->s->fields; i++ ) 06710 { 06711 Field *f= t->field[i]; 06712 if ((f->type() == FIELD_TYPE_BLOB) || 06713 (f->type() == MYSQL_TYPE_VARCHAR)) 06714 { 06715 String tmp; 06716 f->val_str(&tmp); 06717 row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length()); 06718 } 06719 else 06720 row_crc= my_checksum(row_crc, (byte*) f->ptr, 06721 f->pack_length()); 06722 } 06723 06724 crc+= row_crc; 06725 } 06726 protocol->store((ulonglong)crc); 06727 t->file->ha_rnd_end(); 06728 } 06729 } 06730 thd->clear_error(); 06731 close_thread_tables(thd); 06732 table->table=0; // For query cache 06733 } 06734 if (protocol->write()) 06735 goto err; 06736 } 06737 06738 send_eof(thd); 06739 DBUG_RETURN(FALSE); 06740 06741 err: 06742 close_thread_tables(thd); // Shouldn't be needed 06743 if (table) 06744 table->table=0; 06745 DBUG_RETURN(TRUE); 06746 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int mysql_copy_create_list | ( | List< create_field > * | orig_create_list, | |
| List< create_field > * | new_create_list | |||
| ) | [static] |
Definition at line 250 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, FALSE, mem_alloc_error(), List< T >::push_back(), and TRUE.
Referenced by mysql_write_frm().
00252 { 00253 List_iterator<create_field> prep_field_it(*orig_create_list); 00254 create_field *prep_field; 00255 DBUG_ENTER("mysql_copy_create_list"); 00256 00257 while ((prep_field= prep_field_it++)) 00258 { 00259 create_field *field= new create_field(*prep_field); 00260 if (!field || new_create_list->push_back(field)) 00261 { 00262 mem_alloc_error(2); 00263 DBUG_RETURN(TRUE); 00264 } 00265 } 00266 DBUG_RETURN(FALSE); 00267 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 286 of file sql_table.cc.
References Key::columns, DBUG_ENTER, DBUG_RETURN, FALSE, Key::generated, Key::key_create_info, mem_alloc_error(), Key::name, List< T >::push_back(), TRUE, and Key::type.
Referenced by mysql_write_frm().
00288 { 00289 List_iterator<Key> prep_key_it(*orig_key); 00290 Key *prep_key; 00291 DBUG_ENTER("mysql_copy_key_list"); 00292 00293 while ((prep_key= prep_key_it++)) 00294 { 00295 List<key_part_spec> prep_columns; 00296 List_iterator<key_part_spec> prep_col_it(prep_key->columns); 00297 key_part_spec *prep_col; 00298 Key *temp_key; 00299 00300 while ((prep_col= prep_col_it++)) 00301 { 00302 key_part_spec *prep_key_part; 00303 00304 if (!(prep_key_part= new key_part_spec(*prep_col))) 00305 { 00306 mem_alloc_error(sizeof(key_part_spec)); 00307 DBUG_RETURN(TRUE); 00308 } 00309 if (prep_columns.push_back(prep_key_part)) 00310 { 00311 mem_alloc_error(2); 00312 DBUG_RETURN(TRUE); 00313 } 00314 } 00315 if (!(temp_key= new Key(prep_key->type, prep_key->name, 00316 &prep_key->key_create_info, 00317 prep_key->generated, 00318 prep_columns))) 00319 { 00320 mem_alloc_error(sizeof(Key)); 00321 DBUG_RETURN(TRUE); 00322 } 00323 if (new_key->push_back(temp_key)) 00324 { 00325 mem_alloc_error(2); 00326 DBUG_RETURN(TRUE); 00327 } 00328 } 00329 DBUG_RETURN(FALSE); 00330 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_create_like_table | ( | THD * | thd, | |
| TABLE_LIST * | table, | |||
| HA_CREATE_INFO * | lex_create_info, | |||
| Table_ident * | table_ident | |||
| ) |
Definition at line 4546 of file sql_table.cc.
References access, buf, build_table_filename(), build_tmptable_filename(), bzero, check_db_name(), check_table_name(), copy_create_info(), st_table_list::db, db, st_ha_create_information::db_type, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, ER, ER_BAD_DB_ERROR, ER_CANT_CREATE_FILE, ER_TABLE_EXISTS_ERROR, ER_WRONG_DB_NAME, ER_WRONG_OBJECT, ER_WRONG_TABLE_NAME, err, error, F_OK, FALSE, files_charset_info, find_temporary_table(), fn_format(), FN_REFLEN, FRMTYPE_TABLE, HA_CREATE_DELAY_KEY_WRITE, ha_create_table(), HA_LEX_CREATE_IF_NOT_EXISTS, HA_LEX_CREATE_TMP_TABLE, lock_and_wait_for_table_name(), LOCK_open, lower_case_table_names, my_casedn_str, my_copy(), MY_DONT_OVERWRITE_FILE, my_errno, my_error(), MY_REPLACE_EXT, my_snprintf(), MYF, MYSQL_ERRMSG_SIZE, mysql_frm_type(), NAME_LEN, NullS, open_ltable(), open_temporary_table(), st_ha_create_information::options, st_table_share::path, pthread_mutex_lock, pthread_mutex_unlock, push_warning(), query, quick_rm_table(), reg_ext, reg_ext_length, rm_temporary_table(), st_table::s, store_create_info(), LEX_STRING::str, strmov(), strxmov(), system_charset_info, st_table_list::table_name, st_ha_create_information::table_options, TL_READ_NO_INSERT, TRUE, unlock_table_name(), unpack_filename(), MYSQL_ERROR::WARN_LEVEL_NOTE, and write_bin_log().
Referenced by mysql_execute_command().
04549 { 04550 TABLE *tmp_table; 04551 char src_path[FN_REFLEN], dst_path[FN_REFLEN], tmp_path[FN_REFLEN]; 04552 uint dst_path_length; 04553 char *db= table->db; 04554 char *table_name= table->table_name; 04555 char *src_db; 04556 char *src_table= table_ident->table.str; 04557 int err; 04558 bool res= TRUE; 04559 enum legacy_db_type not_used; 04560 HA_CREATE_INFO *create_info; 04561 04562 TABLE_LIST src_tables_list; 04563 DBUG_ENTER("mysql_create_like_table"); 04564 04565 if (!(create_info= copy_create_info(lex_create_info))) 04566 { 04567 DBUG_RETURN(TRUE); 04568 } 04569 DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */ 04570 src_db= table_ident->db.str; 04571 04572 /* 04573 Validate the source table 04574 */ 04575 if (table_ident->table.length > NAME_LEN || 04576 (table_ident->table.length && 04577 check_table_name(src_table,table_ident->table.length))) 04578 { 04579 my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); 04580 DBUG_RETURN(TRUE); 04581 } 04582 if (!src_db || check_db_name(src_db)) 04583 { 04584 my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); 04585 DBUG_RETURN(-1); 04586 } 04587 04588 bzero((gptr)&src_tables_list, sizeof(src_tables_list)); 04589 src_tables_list.db= src_db; 04590 src_tables_list.table_name= src_table; 04591 04592 if (lock_and_wait_for_table_name(thd, &src_tables_list)) 04593 goto err; 04594 04595 if ((tmp_table= find_temporary_table(thd, src_db, src_table))) 04596 strxmov(src_path, tmp_table->s->path.str, reg_ext, NullS); 04597 else 04598 { 04599 build_table_filename(src_path, sizeof(src_path), 04600 src_db, src_table, reg_ext, 0); 04601 /* Resolve symlinks (for windows) */ 04602 unpack_filename(src_path, src_path); 04603 if (lower_case_table_names) 04604 my_casedn_str(files_charset_info, src_path); 04605 if (access(src_path, F_OK)) 04606 { 04607 my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); 04608 goto err; 04609 } 04610 } 04611 04612 /* 04613 create like should be not allowed for Views, Triggers, ... 04614 */ 04615 if (mysql_frm_type(thd, src_path, ¬_used) != FRMTYPE_TABLE) 04616 { 04617 my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE"); 04618 goto err; 04619 } 04620 04621 /* 04622 Validate the destination table 04623 04624 skip the destination table name checking as this is already 04625 validated. 04626 */ 04627 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 04628 { 04629 if (find_temporary_table(thd, db, table_name)) 04630 goto table_exists; 04631 dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path)); 04632 if (lower_case_table_names) 04633 my_casedn_str(files_charset_info, dst_path); 04634 create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; 04635 } 04636 else 04637 { 04638 dst_path_length= build_table_filename(dst_path, sizeof(dst_path), 04639 db, table_name, reg_ext, 0); 04640 if (!access(dst_path, F_OK)) 04641 goto table_exists; 04642 } 04643 04644 /* 04645 Create a new table by copying from source table 04646 */ 04647 if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) 04648 { 04649 if (my_errno == ENOENT) 04650 my_error(ER_BAD_DB_ERROR,MYF(0),db); 04651 else 04652 my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno); 04653 goto err; 04654 } 04655 04656 /* 04657 As mysql_truncate don't work on a new table at this stage of 04658 creation, instead create the table directly (for both normal 04659 and temporary tables). 04660 */ 04661 #ifdef WITH_PARTITION_STORAGE_ENGINE 04662 /* 04663 For partitioned tables we need to copy the .par file as well since 04664 it is used in open_table_def to even be able to create a new handler. 04665 There is no way to find out here if the original table is a 04666 partitioned table so we copy the file and ignore any errors. 04667 */ 04668 fn_format(tmp_path, dst_path, reg_ext, ".par", MYF(MY_REPLACE_EXT)); 04669 strmov(dst_path, tmp_path); 04670 fn_format(tmp_path, src_path, reg_ext, ".par", MYF(MY_REPLACE_EXT)); 04671 strmov(src_path, tmp_path); 04672 my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)); 04673 #endif 04674 dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm 04675 err= ha_create_table(thd, dst_path, db, table_name, create_info, 1); 04676 04677 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 04678 { 04679 if (err || !open_temporary_table(thd, dst_path, db, table_name, 1)) 04680 { 04681 (void) rm_temporary_table(create_info->db_type, 04682 dst_path); /* purecov: inspected */ 04683 goto err; /* purecov: inspected */ 04684 } 04685 } 04686 else if (err) 04687 { 04688 (void) quick_rm_table(create_info->db_type, db, 04689 table_name, 0); /* purecov: inspected */ 04690 goto err; /* purecov: inspected */ 04691 } 04692 04693 /* 04694 We have to write the query before we unlock the tables. 04695 */ 04696 if (thd->current_stmt_binlog_row_based) 04697 { 04698 /* 04699 Since temporary tables are not replicated under row-based 04700 replication, CREATE TABLE ... LIKE ... needs special 04701 treatement. We have four cases to consider, according to the 04702 following decision table: 04703 04704 ==== ========= ========= ============================== 04705 Case Target Source Write to binary log 04706 ==== ========= ========= ============================== 04707 1 normal normal Original statement 04708 2 normal temporary Generated statement 04709 3 temporary normal Nothing 04710 4 temporary temporary Nothing 04711 ==== ========= ========= ============================== 04712 04713 The variable 'tmp_table' below is used to see if the source 04714 table is a temporary table: if it is set, then the source table 04715 was a temporary table and we can take apropriate actions. 04716 */ 04717 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) 04718 { 04719 if (tmp_table) // Case 2 04720 { 04721 char buf[2048]; 04722 String query(buf, sizeof(buf), system_charset_info); 04723 query.length(0); // Have to zero it since constructor doesn't 04724 TABLE *table_ptr; 04725 int error; 04726 04727 /* 04728 Let's open and lock the table: it will be closed (and 04729 unlocked) by close_thread_tables() at the end of the 04730 statement anyway. 04731 */ 04732 if (!(table_ptr= open_ltable(thd, table, TL_READ_NO_INSERT))) 04733 goto err; 04734 04735 int result= store_create_info(thd, table, &query, create_info); 04736 04737 DBUG_ASSERT(result == 0); // store_create_info() always return 0 04738 write_bin_log(thd, TRUE, query.ptr(), query.length()); 04739 } 04740 else // Case 1 04741 write_bin_log(thd, TRUE, thd->query, thd->query_length); 04742 } 04743 /* 04744 Case 3 and 4 does nothing under RBR 04745 */ 04746 } 04747 else 04748 write_bin_log(thd, TRUE, thd->query, thd->query_length); 04749 04750 res= FALSE; 04751 goto err; 04752 04753 table_exists: 04754 if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) 04755 { 04756 char warn_buff[MYSQL_ERRMSG_SIZE]; 04757 my_snprintf(warn_buff, sizeof(warn_buff), 04758 ER(ER_TABLE_EXISTS_ERROR), table_name); 04759 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 04760 ER_TABLE_EXISTS_ERROR,warn_buff); 04761 res= FALSE; 04762 } 04763 else 04764 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); 04765 04766 err: 04767 pthread_mutex_lock(&LOCK_open); 04768 unlock_table_name(thd, &src_tables_list); 04769 pthread_mutex_unlock(&LOCK_open); 04770 DBUG_RETURN(res); 04771 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_create_table | ( | THD * | thd, | |
| const char * | db, | |||
| const char * | table_name, | |||
| HA_CREATE_INFO * | create_info, | |||
| List< create_field > & | fields, | |||
| List< Key > & | keys, | |||
| bool | internal_tmp_table, | |||
| uint | select_field_count, | |||
| bool | use_copy_create_info | |||
| ) |
Definition at line 3537 of file sql_table.cc.
References COND_refresh, creating_database, creating_table, DBUG_ENTER, DBUG_RETURN, hash_search(), keys, lock_db_cache, LOCK_lock_db, mysql_create_table_internal(), pthread_mutex_lock, pthread_mutex_unlock, strlen(), TRUE, and wait_for_condition().
Referenced by create_table_from_items(), and mysql_execute_command().
03543 { 03544 bool result; 03545 DBUG_ENTER("mysql_create_table"); 03546 03547 /* Wait for any database locks */ 03548 pthread_mutex_lock(&LOCK_lock_db); 03549 while (!thd->killed && 03550 hash_search(&lock_db_cache,(byte*) db, strlen(db))) 03551 { 03552 wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); 03553 pthread_mutex_lock(&LOCK_lock_db); 03554 } 03555 03556 if (thd->killed) 03557 { 03558 pthread_mutex_unlock(&LOCK_lock_db); 03559 DBUG_RETURN(TRUE); 03560 } 03561 creating_table++; 03562 pthread_mutex_unlock(&LOCK_lock_db); 03563 03564 result= mysql_create_table_internal(thd, db, table_name, create_info, 03565 fields, keys, internal_tmp_table, 03566 select_field_count, 03567 use_copy_create_info); 03568 03569 pthread_mutex_lock(&LOCK_lock_db); 03570 if (!--creating_table && creating_database) 03571 pthread_cond_signal(&COND_refresh); 03572 pthread_mutex_unlock(&LOCK_lock_db); 03573 DBUG_RETURN(result); 03574 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_create_table_internal | ( | THD * | thd, | |
| const char * | db, | |||
| const char * | table_name, | |||
| HA_CREATE_INFO * | lex_create_info, | |||
| List< create_field > & | fields, | |||
| List< Key > & | keys, | |||
| bool | internal_tmp_table, | |||
| uint | select_field_count, | |||
| bool | use_copy_create_info | |||
| ) |
Definition at line 3171 of file sql_table.cc.
References access, build_table_filename(), build_tmptable_filename(), check_engine(), partition_info::check_partition_info(), copy_create_info(), st_ha_create_information::data_file_name, st_ha_create_information::db_type, DB_TYPE_DEFAULT, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, partition_info::default_engine_type, base_list::elements, ER, ER_CANNOT_ADD_FOREIGN, ER_PARTITION_NO_TEMPORARY, ER_TABLE_EXISTS_ERROR, ER_TABLE_MUST_HAVE_COLUMNS, ER_WRONG_TABLE_NAME, err, error, F_OK, FALSE, files_charset_info, find_temporary_table(), FN_DEVCHAR, FN_REFLEN, Key::FOREIGN_KEY, generate_partition_syntax(), get_cached_table_share(), handler::get_default_no_partitions(), get_ha_partition(), get_new_handler(), HA_CAN_PARTITION, ha_checktype(), HA_CREATE_DELAY_KEY_WRITE, HA_CREATE_USED_ENGINE, ha_legacy_type(), HA_LEX_CREATE_IF_NOT_EXISTS, HA_LEX_CREATE_TMP_TABLE, HA_OPTION_PACK_RECORD, ha_table_exists_in_engine(), HA_USE_AUTO_PARTITION, st_ha_create_information::index_file_name, int(), partition_info::is_auto_partitioned, partition_info::is_sub_partitioned(), key, keys, LOCK_open, lower_case_table_names, mem_alloc_error(), MODE_NO_DIR_IN_CREATE, my_casedn_str, my_error(), my_message(), MYF, mysql_prepare_table(), partition_info::no_parts, partition_info::no_subparts, NULL, open_temporary_table(), st_ha_create_information::options, partition_info::part_info_len, partition_info::part_info_string, PART_TO_BE_DROPPED, handlerton::partition_flags, partition_info::partitions, path, pthread_mutex_lock, pthread_mutex_unlock, push_warning_printf(), rea_create_table(), reg_ext, reg_ext_length, rm_temporary_table(), st_ha_create_information::row_type, ROW_TYPE_DYNAMIC, handler::set_auto_partitions(), set_table_default_charset(), SQLCOM_CREATE_TABLE, start(), st_ha_create_information::table_existed, st_ha_create_information::table_options, TRUE, partition_info::use_default_no_partitions, partition_info::use_default_no_subpartitions, st_ha_create_information::used_fields, VOID, MYSQL_ERROR::WARN_LEVEL_NOTE, and write_bin_log().
Referenced by mysql_create_table().
03178 { 03179 char path[FN_REFLEN]; 03180 uint path_length; 03181 const char *alias; 03182 uint db_options, key_count; 03183 KEY *key_info_buffer; 03184 HA_CREATE_INFO *create_info; 03185 handler *file; 03186 bool error= TRUE; 03187 DBUG_ENTER("mysql_create_table_internal"); 03188 DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d", 03189 db, table_name, internal_tmp_table)); 03190 03191 if (use_copy_create_info) 03192 { 03193 if (!(create_info= copy_create_info(lex_create_info))) 03194 { 03195 DBUG_RETURN(TRUE); 03196 } 03197 } 03198 else 03199 create_info= lex_create_info; 03200 03201 /* Check for duplicate fields and check type of table to create */ 03202 if (!fields.elements) 03203 { 03204 my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS), 03205 MYF(0)); 03206 DBUG_RETURN(TRUE); 03207 } 03208 if (check_engine(thd, table_name, create_info)) 03209 DBUG_RETURN(TRUE); 03210 db_options= create_info->table_options; 03211 if (create_info->row_type == ROW_TYPE_DYNAMIC) 03212 db_options|=HA_OPTION_PACK_RECORD; 03213 alias= table_case_name(create_info, table_name); 03214 if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, 03215 create_info->db_type))) 03216 { 03217 mem_alloc_error(sizeof(handler)); 03218 DBUG_RETURN(TRUE); 03219 } 03220 #ifdef WITH_PARTITION_STORAGE_ENGINE 03221 partition_info *part_info= thd->work_part_info; 03222 03223 if (!part_info && create_info->db_type->partition_flags && 03224 (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION)) 03225 { 03226 /* 03227 Table is not defined as a partitioned table but the engine handles 03228 all tables as partitioned. The handler will set up the partition info 03229 object with the default settings. 03230 */ 03231 thd->work_part_info= part_info= new partition_info(); 03232 if (!part_info) 03233 { 03234 mem_alloc_error(sizeof(partition_info)); 03235 DBUG_RETURN(TRUE); 03236 } 03237 file->set_auto_partitions(part_info); 03238 part_info->default_engine_type= create_info->db_type; 03239 part_info->is_auto_partitioned= TRUE; 03240 } 03241 if (part_info) 03242 { 03243 /* 03244 The table has been specified as a partitioned table. 03245 If this is part of an ALTER TABLE the handler will be the partition 03246 handler but we need to specify the default handler to use for 03247 partitions also in the call to check_partition_info. We transport 03248 this information in the default_db_type variable, it is either 03249 DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command. 03250 03251 Check that we don't use foreign keys in the table since it won't 03252 work even with InnoDB beneath it. 03253 */ 03254 List_iterator<Key> key_iterator(keys); 03255 Key *key; 03256 handlerton *part_engine_type= create_info->db_type; 03257 char *part_syntax_buf; 03258 uint syntax_len; 03259 handlerton *engine_type; 03260 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 03261 { 03262 my_error(ER_PARTITION_NO_TEMPORARY, MYF(0)); 03263 goto err; 03264 } 03265 while ((key= key_iterator++)) 03266 { 03267 if (key->type == Key::FOREIGN_KEY && 03268 !part_info->is_auto_partitioned) 03269 { 03270 my_error(ER_CANNOT_ADD_FOREIGN, MYF(0)); 03271 goto err; 03272 } 03273 } 03274 if ((part_engine_type == &partition_hton) && 03275 part_info->default_engine_type) 03276 { 03277 /* 03278 This only happens at ALTER TABLE. 03279 default_engine_type was assigned from the engine set in the ALTER 03280 TABLE command. 03281 */ 03282 ; 03283 } 03284 else 03285 { 03286 if (create_info->used_fields & HA_CREATE_USED_ENGINE) 03287 { 03288 part_info->default_engine_type= create_info->db_type; 03289 } 03290 else 03291 { 03292 if (part_info->default_engine_type == NULL) 03293 { 03294 part_info->default_engine_type= ha_checktype(thd, 03295 DB_TYPE_DEFAULT, 0, 0); 03296 } 03297 } 03298 } 03299 DBUG_PRINT("info", ("db_type = %d", 03300 ha_legacy_type(part_info->default_engine_type))); 03301 if (part_info->check_partition_info(thd, &engine_type, file, create_info)) 03302 goto err; 03303 part_info->default_engine_type= engine_type; 03304 03305 /* 03306 We reverse the partitioning parser and generate a standard format 03307 for syntax stored in frm file. 03308 */ 03309 if (!(part_syntax_buf= generate_partition_syntax(part_info, 03310 &syntax_len, 03311 TRUE, TRUE))) 03312 goto err; 03313 part_info->part_info_string= part_syntax_buf; 03314 part_info->part_info_len= syntax_len; 03315 if ((!(engine_type->partition_flags && 03316 engine_type->partition_flags() & HA_CAN_PARTITION)) || 03317 create_info->db_type == &partition_hton) 03318 { 03319 /* 03320 The handler assigned to the table cannot handle partitioning. 03321 Assign the partition handler as the handler of the table. 03322 */ 03323 DBUG_PRINT("info", ("db_type: %d", 03324 ha_legacy_type(create_info->db_type))); 03325 delete file; 03326 create_info->db_type= &partition_hton; 03327 if (!(file= get_ha_partition(part_info))) 03328 { 03329 DBUG_RETURN(TRUE); 03330 } 03331 /* 03332 If we have default number of partitions or subpartitions we 03333 might require to set-up the part_info object such that it 03334 creates a proper .par file. The current part_info object is 03335 only used to create the frm-file and .par-file. 03336 */ 03337 if (part_info->use_default_no_partitions && 03338 part_info->no_parts && 03339 (int)part_info->no_parts != 03340 file->get_default_no_partitions(create_info)) 03341 { 03342 uint i; 03343 List_iterator<partition_element> part_it(part_info->partitions); 03344 part_it++; 03345 DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE); 03346 for (i= 1; i < part_info->partitions.elements; i++) 03347 (part_it++)->part_state= PART_TO_BE_DROPPED; 03348 } 03349 else if (part_info->is_sub_partitioned() && 03350 part_info->use_default_no_subpartitions && 03351 part_info->no_subparts && 03352 (int)part_info->no_subparts != 03353 file->get_default_no_partitions(create_info)) 03354 { 03355 DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE); 03356 part_info->no_subparts= file->get_default_no_partitions(create_info); 03357 } 03358 } 03359 else if (create_info->db_type != engine_type) 03360 { 03361 /* 03362 We come here when we don't use a partitioned handler. 03363 Since we use a partitioned table it must be "native partitioned". 03364 We have switched engine from defaults, most likely only specified 03365 engines in partition clauses. 03366 */ 03367 delete file; 03368 if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, 03369 engine_type))) 03370 { 03371 mem_alloc_error(sizeof(handler)); 03372 DBUG_RETURN(TRUE); 03373 } 03374 } 03375 } 03376 #endif 03377 03378 set_table_default_charset(thd, create_info, (char*) db); 03379 03380 if (mysql_prepare_table(thd, create_info, &fields, 03381 &keys, internal_tmp_table, &db_options, file, 03382 &key_info_buffer, &key_count, 03383 select_field_count)) 03384 goto err; 03385 03386 /* Check if table exists */ 03387 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 03388 { 03389 path_length= build_tmptable_filename(thd, path, sizeof(path)); 03390 if (lower_case_table_names) 03391 my_casedn_str(files_charset_info, path); 03392 create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; 03393 } 03394 else 03395 { 03396 #ifdef FN_DEVCHAR 03397 /* check if the table name contains FN_DEVCHAR when defined */ 03398 const char *start= alias; 03399 while (*start != '\0') 03400 { 03401 if (*start == FN_DEVCHAR) 03402 { 03403 my_error(ER_WRONG_TABLE_NAME, MYF(0), alias); 03404 DBUG_RETURN(TRUE); 03405 } 03406 start++; 03407 } 03408 #endif 03409 path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext, 03410 internal_tmp_table ? FN_IS_TMP : 0); 03411 } 03412 03413 /* Check if table already exists */ 03414 if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) && 03415 find_temporary_table(thd, db, table_name)) 03416 { 03417 if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) 03418 { 03419 create_info->table_existed= 1; // Mark that table existed 03420 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 03421 ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), 03422 alias); 03423 error= 0; 03424 goto err; 03425 } 03426 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); 03427 goto err; 03428 } 03429 03430 VOID(pthread_mutex_lock(&LOCK_open)); 03431 if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) 03432 { 03433 if (!access(path,F_OK)) 03434 { 03435 if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) 03436 goto warn; 03437 my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); 03438 goto unlock_and_end; 03439 } 03440 /* 03441 We don't assert here, but check the result, because the table could be 03442 in the table definition cache and in the same time the .frm could be 03443 missing from the disk, in case of manual intervention which deletes 03444 the .frm file. The user has to use FLUSH TABLES; to clear the cache. 03445 Then she could create the table. This case is pretty obscure and 03446 therefore we don't introduce a new error message only for it. 03447 */ 03448 if (get_cached_table_share(db, alias)) 03449 { 03450 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); 03451 goto unlock_and_end; 03452 } 03453 } 03454 03455 /* 03456 Check that table with given name does not already 03457 exist in any storage engine. In such a case it should 03458 be discovered and the error ER_TABLE_EXISTS_ERROR be returned 03459 unless user specified CREATE TABLE IF EXISTS 03460 The LOCK_open mutex has been locked to make sure no 03461 one else is attempting to discover the table. Since 03462 it's not on disk as a frm file, no one could be using it! 03463 */ 03464 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) 03465 { 03466 bool create_if_not_exists = 03467 create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS; 03468 if (ha_table_exists_in_engine(thd, db, table_name)) 03469 { 03470 DBUG_PRINT("info", ("Table with same name already existed in handler")); 03471 03472 if (create_if_not_exists) 03473 goto warn; 03474 my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); 03475 goto unlock_and_end; 03476 } 03477 } 03478 03479 thd->proc_info="creating table"; 03480 create_info->table_existed= 0; // Mark that table is created 03481 03482 if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) 03483 create_info->data_file_name= create_info->index_file_name= 0; 03484 create_info->table_options=db_options; 03485 03486 path[path_length - reg_ext_length]= '\0'; // Remove .frm extension 03487 if (rea_create_table(thd, path, db, table_name, create_info, fields, 03488 key_count, key_info_buffer, file)) 03489 goto unlock_and_end; 03490 03491 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 03492 { 03493 /* Open table and put in temporary table list */ 03494 if (!(open_temporary_table(thd, path, db, table_name, 1))) 03495 { 03496 (void) rm_temporary_table(create_info->db_type, path); 03497 goto unlock_and_end; 03498 } 03499 thd->tmp_table_used= 1; 03500 } 03501 03502 /* 03503 Don't write statement if: 03504 - It is an internal temporary table, 03505 - Row-based logging is used and it we are creating a temporary table, or 03506 - The binary log is not open. 03507 Otherwise, the statement shall be binlogged. 03508 */ 03509 if (!internal_tmp_table && 03510 (!thd->current_stmt_binlog_row_based || 03511 (thd->current_stmt_binlog_row_based && 03512 !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) 03513 write_bin_log(thd, TRUE, thd->query, thd->query_length); 03514 error= FALSE; 03515 unlock_and_end: 03516 VOID(pthread_mutex_unlock(&LOCK_open)); 03517 03518 err: 03519 thd->proc_info="After create"; 03520 delete file; 03521 DBUG_RETURN(error); 03522 03523 warn: 03524 error= FALSE; 03525 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 03526 ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), 03527 alias); 03528 create_info->table_existed= 1; // Mark that table existed 03529 goto unlock_and_end; 03530 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int mysql_discard_or_import_tablespace | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| enum tablespace_op_type | tablespace_op | |||
| ) | [static] |
Definition at line 4799 of file sql_table.cc.
References close_thread_tables(), DBUG_ENTER, DBUG_RETURN, handler::discard_or_import_tablespace(), err, error, FALSE, st_table::file, ha_autocommit_or_rollback(), ha_commit, ha_commit_stmt, MYF, open_ltable(), handler::print_error(), send_ok(), test, TL_WRITE, TRUE, and write_bin_log().
Referenced by mysql_alter_table().
04802 { 04803 TABLE *table; 04804 my_bool discard; 04805 int error; 04806 DBUG_ENTER("mysql_discard_or_import_tablespace"); 04807 04808 /* 04809 Note that DISCARD/IMPORT TABLESPACE always is the only operation in an 04810 ALTER TABLE 04811 */ 04812 04813 thd->proc_info="discard_or_import_tablespace"; 04814 04815 discard= test(tablespace_op == DISCARD_TABLESPACE); 04816 04817 /* 04818 We set this flag so that ha_innobase::open and ::external_lock() do 04819 not complain when we lock the table 04820 */ 04821 thd->tablespace_op= TRUE; 04822 if (!(table=open_ltable(thd,table_list,TL_WRITE))) 04823 { 04824 thd->tablespace_op=FALSE; 04825 DBUG_RETURN(-1); 04826 } 04827 04828 error=table->file->discard_or_import_tablespace(discard); 04829 04830 thd->proc_info="end"; 04831 04832 if (error) 04833 goto err; 04834 04835 /* 04836 The 0 in the call below means 'not in a transaction', which means 04837 immediate invalidation; that is probably what we wish here 04838 */ 04839 query_cache_invalidate3(thd, table_list, 0); 04840 04841 /* The ALTER TABLE is always in its own transaction */ 04842 error = ha_commit_stmt(thd); 04843 if (ha_commit(thd)) 04844 error=1; 04845 if (error) 04846 goto err; 04847 write_bin_log(thd, FALSE, thd->query, thd->query_length); 04848 04849 err: 04850 ha_autocommit_or_rollback(thd, error); 04851 close_thread_tables(thd); 04852 thd->tablespace_op=FALSE; 04853 04854 if (error == 0) 04855 { 04856 send_ok(thd); 04857 DBUG_RETURN(0); 04858 } 04859 04860 table->file->print_error(error, MYF(0)); 04861 04862 DBUG_RETURN(-1); 04863 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_optimize_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) |
Definition at line 4425 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, mysql_admin_table(), handler::optimize(), and TL_WRITE.
Referenced by mysql_execute_command().
04426 { 04427 DBUG_ENTER("mysql_optimize_table"); 04428 DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, 04429 "optimize", TL_WRITE, 1,0,0,0, 04430 &handler::optimize, 0)); 04431 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_preload_keys | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 4522 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, mysql_admin_table(), handler::preload_keys(), and TL_READ.
Referenced by mysql_execute_command().
04523 { 04524 DBUG_ENTER("mysql_preload_keys"); 04525 DBUG_RETURN(mysql_admin_table(thd, tables, 0, 04526 "preload_keys", TL_READ, 0, 0, 0, 0, 04527 &handler::preload_keys, 0)); 04528 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int mysql_prepare_table | ( | THD * | thd, | |
| HA_CREATE_INFO * | create_info, | |||
| List< create_field > * | fields, | |||
| List< Key > * | keys, | |||
| bool | tmp_table, | |||
| uint * | db_options, | |||
| handler * | file, | |||
| KEY ** | key_info_buffer, | |||
| uint * | key_count, | |||
| int | select_field_count | |||
| ) | [static] |
Definition at line 2169 of file sql_table.cc.
References BINCMP_FLAG, BLOB_FLAG, calculate_interval_lengths(), create_field::char_length, String::charset(), create_field::charset, check_column_name(), charset_info_st::coll, DTCollation::collation, Item::collation, String::copy(), create_field::create_length_to_internal_length(), charset_info_st::cset, charset_info_st::csname, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, create_field::decimals, create_field::def, st_ha_create_information::default_table_charset, base_list::elements, base_list::empty(), ER_DUP_FIELDNAME, ER_ILLEGAL_VALUE_FOR_TYPE, ER_INVALID_DEFAULT, ER_UNKNOWN_COLLATION, ER_WRONG_COLUMN_NAME, create_field::field_name, FIELD_TYPE_BIT, FIELD_TYPE_ENUM, FIELD_TYPE_SET, FIELDFLAG_NUMBER, FIELDFLAG_TREAT_BIT_AS_CHAR, find_set(), find_type2(), create_field::flags, get_charset_by_csname(), HA_CAN_BIT_FIELD, HA_OPTION_PACK_RECORD, handler::ha_table_flags(), my_collation_handler_st::instr, create_field::interval, interval, create_field::interval_list, create_field::key_length, String::length(), create_field::length, my_charset_handler_st::lengthsp, MAX_FIELD_WIDTH, handler::max_key_length(), my_charset_bin, MY_CS_BINSORT, my_error(), my_strcasecmp, MYF, MYSQL_TYPE_VARCHAR, String::needs_conversion(), NOT_NULL_FLAG, NULL, null_fields, create_field::pack_flag, create_field::pack_length, prepare_blob_field(), String::ptr(), List_iterator< T >::remove(), List_iterator< T >::rewind(), st_ha_create_information::row_type, ROW_TYPE_FIXED, Item::safe_charset_converter(), set_if_smaller, create_field::sql_type, STRING_WITH_LEN, strmake(), strmake_root(), system_charset_info, st_ha_create_information::table_charset, typelib(), create_field::unireg_check, Item::val_str(), st_ha_create_information::varchar, and my_charset_handler_st::wc_mb.
Referenced by mysql_alter_table(), mysql_create_table_internal(), and mysql_write_frm().
02175 { 02176 const char *key_name; 02177 create_field *sql_field,*dup_field; 02178 uint field,null_fields,blob_columns,max_key_length; 02179 ulong record_offset= 0; 02180 KEY *key_info; 02181 KEY_PART_INFO *key_part_info; 02182 int timestamps= 0, timestamps_with_niladic= 0; 02183 int field_no,dup_no; 02184 int select_field_pos,auto_increment=0; 02185 List_iterator<create_field> it(*fields),it2(*fields); 02186 uint total_uneven_bit_length= 0; 02187 DBUG_ENTER("mysql_prepare_table"); 02188 02189 select_field_pos= fields->elements - select_field_count; 02190 null_fields=blob_columns=0; 02191 create_info->varchar= 0; 02192 max_key_length= file->max_key_length(); 02193 02194 for (field_no=0; (sql_field=it++) ; field_no++) 02195 { 02196 CHARSET_INFO *save_cs; 02197 02198 /* 02199 Initialize length from its original value (number of characters), 02200 which was set in the parser. This is necessary if we're 02201 executing a prepared statement for the second time. 02202 */ 02203 sql_field->length= sql_field->char_length; 02204 if (!sql_field->charset) 02205 sql_field->charset= create_info->default_table_charset; 02206 /* 02207 table_charset is set in ALTER TABLE if we want change character set 02208 for all varchar/char columns. 02209 But the table charset must not affect the BLOB fields, so don't 02210 allow to change my_charset_bin to somethig else. 02211 */ 02212 if (create_info->table_charset && sql_field->charset != &my_charset_bin) 02213 sql_field->charset= create_info->table_charset; 02214 02215 save_cs= sql_field->charset; 02216 if ((sql_field->flags & BINCMP_FLAG) && 02217 !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, 02218 MY_CS_BINSORT,MYF(0)))) 02219 { 02220 char tmp[64]; 02221 strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), 02222 STRING_WITH_LEN("_bin")); 02223 my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp); 02224 DBUG_RETURN(-1); 02225 } 02226 02227 if (sql_field->sql_type == FIELD_TYPE_SET || 02228 sql_field->sql_type == FIELD_TYPE_ENUM) 02229 { 02230 uint32 dummy; 02231 CHARSET_INFO *cs= sql_field->charset; 02232 TYPELIB *interval= sql_field->interval; 02233 02234 /* 02235 Create typelib from interval_list, and if necessary 02236 convert strings from client character set to the 02237 column character set. 02238 */ 02239 if (!interval) 02240 { 02241 /* 02242 Create the typelib in prepared statement memory if we're 02243 executing one. 02244 */ 02245 MEM_ROOT *stmt_root= thd->stmt_arena->mem_root; 02246 02247 interval= sql_field->interval= typelib(stmt_root, 02248 sql_field->interval_list); 02249 List_iterator<String> it(sql_field->interval_list); 02250 String conv, *tmp; 02251 char comma_buf[2]; 02252 int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf, 02253 (uchar*) comma_buf + 02254 sizeof(comma_buf)); 02255 DBUG_ASSERT(comma_length > 0); 02256 for (uint i= 0; (tmp= it++); i++) 02257 { 02258 uint lengthsp; 02259 if (String::needs_conversion(tmp->length(), tmp->charset(), 02260 cs, &dummy)) 02261 { 02262 uint cnv_errs; 02263 conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); 02264 interval->type_names[i]= strmake_root(stmt_root, conv.ptr(), 02265 conv.length()); 02266 interval->type_lengths[i]= conv.length(); 02267 } 02268 02269 // Strip trailing spaces. 02270 lengthsp= cs->cset->lengthsp(cs, interval->type_names[i], 02271 interval->type_lengths[i]); 02272 interval->type_lengths[i]= lengthsp; 02273 ((uchar *)interval->type_names[i])[lengthsp]= '\0'; 02274 if (sql_field->sql_type == FIELD_TYPE_SET) 02275 { 02276 if (cs->coll->instr(cs, interval->type_names[i], 02277 interval->type_lengths[i], 02278 comma_buf, comma_length, NULL, 0)) 02279 { 02280 my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr()); 02281 DBUG_RETURN(-1); 02282 } 02283 } 02284 } 02285 sql_field->interval_list.empty(); // Don't need interval_list anymore 02286 } 02287 02288 /* 02289 Convert the default value from client character 02290 set into the column character set if necessary. 02291 */ 02292 if (sql_field->def && cs != sql_field->def->collation.collation) 02293 { 02294 Query_arena backup_arena; 02295 bool need_to_change_arena= !thd->stmt_arena->is_conventional(); 02296 if (need_to_change_arena) 02297 { 02298 /* Asser that we don't do that at every PS execute */ 02299 DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || 02300 thd->stmt_arena->is_first_sp_execute()); 02301 thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); 02302 } 02303 02304 sql_field->def= sql_field->def->safe_charset_converter(cs); 02305 02306 if (need_to_change_arena) 02307 thd->restore_active_arena(thd->stmt_arena, &backup_arena); 02308 02309 if (sql_field->def == NULL) 02310 { 02311 /* Could not convert */ 02312 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); 02313 DBUG_RETURN(-1); 02314 } 02315 } 02316 02317 if (sql_field->sql_type == FIELD_TYPE_SET) 02318 { 02319 uint32 field_length; 02320 if (sql_field->def != NULL) 02321 { 02322 char *not_used; 02323 uint not_used2; 02324 bool not_found= 0; 02325 String str, *def= sql_field->def->val_str(&str); 02326 if (def == NULL) /* SQL "NULL" maps to NULL */ 02327 { 02328 if ((sql_field->flags & NOT_NULL_FLAG) != 0) 02329 { 02330 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); 02331 DBUG_RETURN(-1); 02332 } 02333 02334 /* else, NULL is an allowed value */ 02335 (void) find_set(interval, NULL, 0, 02336 cs, ¬_used, ¬_used2, ¬_found); 02337 } 02338 else /* not NULL */ 02339 { 02340 (void) find_set(interval, def->ptr(), def->length(), 02341 cs, ¬_used, ¬_used2, ¬_found); 02342 } 02343 02344 if (not_found) 02345 { 02346 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); 02347 DBUG_RETURN(-1); 02348 } 02349 } 02350 calculate_interval_lengths(cs, interval, &dummy, &field_length); 02351 sql_field->length= field_length + (interval->count - 1); 02352 } 02353 else /* FIELD_TYPE_ENUM */ 02354 { 02355 uint32 field_length; 02356 DBUG_ASSERT(sql_field->sql_type == FIELD_TYPE_ENUM); 02357 if (sql_field->def != NULL) 02358 { 02359 String str, *def= sql_field->def->val_str(&str); 02360 if (def == NULL) /* SQL "NULL" maps to NULL */ 02361 { 02362 if ((sql_field->flags & NOT_NULL_FLAG) != 0) 02363 { 02364 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); 02365 DBUG_RETURN(-1); 02366 } 02367 02368 /* else, the defaults yield the correct length for NULLs. */ 02369 } 02370 else /* not NULL */ 02371 { 02372 def->length(cs->cset->lengthsp(cs, def->ptr(), def->length())); 02373 if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */ 02374 { 02375 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); 02376 DBUG_RETURN(-1); 02377 } 02378 } 02379 } 02380 calculate_interval_lengths(cs, interval, &field_length, &dummy); 02381 sql_field->length= field_length; 02382 } 02383 set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1); 02384 } 02385 02386 if (sql_field->sql_type == FIELD_TYPE_BIT) 02387 { 02388 sql_field->pack_flag= FIELDFLAG_NUMBER; 02389 if (file->ha_table_flags() & HA_CAN_BIT_FIELD) 02390 total_uneven_bit_length+= sql_field->length & 7; 02391 else 02392 sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR; 02393 } 02394 02395 sql_field->create_length_to_internal_length(); 02396 if (prepare_blob_field(thd, sql_field)) 02397 DBUG_RETURN(-1); 02398 02399 if (!(sql_field->flags & NOT_NULL_FLAG)) 02400 null_fields++; 02401 02402 if (check_column_name(sql_field->field_name)) 02403 { 02404 my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name); 02405 DBUG_RETURN(-1); 02406 } 02407 02408 /* Check if we have used the same field name before */ 02409 for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++) 02410 { 02411 if (my_strcasecmp(system_charset_info, 02412 sql_field->field_name, 02413 dup_field->field_name) == 0) 02414 { 02415 /* 02416 If this was a CREATE ... SELECT statement, accept a field 02417 redefinition if we are changing a field in the SELECT part 02418 */ 02419 if (field_no < select_field_pos || dup_no >= select_field_pos) 02420 { 02421 my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name); 02422 DBUG_RETURN(-1); 02423 } 02424 else 02425 { 02426 /* Field redefined */ 02427 sql_field->def= dup_field->def; 02428 sql_field->sql_type= dup_field->sql_type; 02429 sql_field->charset= (dup_field->charset ? 02430 dup_field->charset : 02431 create_info->default_table_charset); 02432 sql_field->length= dup_field->char_length; 02433 sql_field->pack_length= dup_field->pack_length; 02434 sql_field->key_length= dup_field->key_length; 02435 sql_field->create_length_to_internal_length(); 02436 sql_field->decimals= dup_field->decimals; 02437 sql_field->unireg_check= dup_field->unireg_check; 02438 /* 02439 We're making one field from two, the result field will have 02440 dup_field->flags as flags. If we've incremented null_fields 02441 because of sql_field->flags, decrement it back. 02442 */ 02443 if (!(sql_field->flags & NOT_NULL_FLAG)) 02444 null_fields--; 02445 sql_field->flags= dup_field->flags; 02446 sql_field->interval= dup_field->interval; 02447 it2.remove(); // Remove first (create) definition 02448 select_field_pos--; 02449 break; 02450 } 02451 } 02452 } 02453 /* Don't pack rows in old tables if the user has requested this */ 02454 if ((sql_field->flags & BLOB_FLAG) || 02455 sql_field->sql_type == MYSQL_TYPE_VARCHAR && 02456 create_info->row_type != ROW_TYPE_FIXED) 02457 (*db_options)|= HA_OPTION_PACK_RECORD; 02458 it2.rewind(); 02459 } 02460 02461 /* record_offset will be increased with 'length-of-null-bits' later */ 02462 record_offset= 0; 02463 null_fields+= total_uneven_bit_length; 02464 02465 it.rewind(); 02466 while ((sql_field=it++)) 02467 { 02468 DBUG_ASSERT(sql_field->charset != 0); 02469 02470 if (prepare_create_field(sql_field, &blob_columns, 02471 ×tamps, ×tamps_with_niladic, 02472 file->ha_table_flags())) 02473 DBUG_RETURN(-1); 02474 if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) 02475 create_info->varchar= 1; 02476 sql_field->offset= record_offset; 02477 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) 02478 auto_increment++; 02479 record_offset+= sql_field->pack_length; 02480 } 02481 if (timestamps_with_niladic > 1) 02482 { 02483 my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS, 02484 ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0)); 02485 DBUG_RETURN(-1); 02486 } 02487 if (auto_increment > 1) 02488 { 02489 my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0)); 02490 DBUG_RETURN(-1); 02491 } 02492 if (auto_increment && 02493 (file->ha_table_flags() & HA_NO_AUTO_INCREMENT)) 02494 { 02495 my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, 02496 ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0)); 02497 DBUG_RETURN(-1); 02498 } 02499 02500 if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS)) 02501 { 02502 my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB), 02503 MYF(0)); 02504 DBUG_RETURN(-1); 02505 } 02506 02507 /* Create keys */ 02508 02509 List_iterator<Key> key_iterator(*keys), key_iterator2(*keys); 02510 uint key_parts=0, fk_key_count=0; 02511 bool primary_key=0,unique_key=0; 02512 Key *key, *key2; 02513 uint tmp, key_number; 02514 /* special marker for keys to be ignored */ 02515 static char ignore_key[1]; 02516 02517 /* Calculate number of key segements */ 02518 *key_count= 0; 02519 02520 while ((key=key_iterator++)) 02521 { 02522 DBUG_PRINT("info", ("key name: '%s' type: %d", key->name ? key->name : 02523 "(none)" , key->type)); 02524 if (key->type == Key::FOREIGN_KEY) 02525 { 02526 fk_key_count++; 02527 foreign_key *fk_key= (foreign_key*) key; 02528 if (fk_key->ref_columns.elements && 02529 fk_key->ref_columns.elements != fk_key->columns.elements) 02530 { 02531 my_error(ER_WRONG_FK_DEF, MYF(0), 02532 (fk_key->name ? fk_key->name : "foreign key without name"), 02533 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); 02534 DBUG_RETURN(-1); 02535 } 02536 continue; 02537 } 02538 (*key_count)++; 02539 tmp=file->max_key_parts(); 02540 if (key->columns.elements > tmp) 02541 { 02542 my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp); 02543 DBUG_RETURN(-1); 02544 } 02545 if (key->name && strlen(key->name) > NAME_LEN) 02546 { 02547 my_error(ER_TOO_LONG_IDENT, MYF(0), key->name); 02548 DBUG_RETURN(-1); 02549 } 02550 key_iterator2.rewind (); 02551 if (key->type != Key::FOREIGN_KEY) 02552 { 02553 while ((key2 = key_iterator2++) != key) 02554 { 02555 /* 02556 foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is 02557 'generated', and a generated key is a prefix of the other key. 02558 Then we do not need the generated shorter key. 02559 */ 02560 if ((key2->type != Key::FOREIGN_KEY && 02561 key2->name != ignore_key && 02562 !foreign_key_prefix(key, key2))) 02563 { 02564 /* TODO: issue warning message */ 02565 /* mark that the generated key should be ignored */ 02566 if (!key2->generated || 02567 (key->generated && key->columns.elements < 02568 key2->columns.elements)) 02569 key->name= ignore_key; 02570 else 02571 { 02572 key2->name= ignore_key; 02573 key_parts-= key2->columns.elements; 02574 (*key_count)--; 02575 } 02576 break; 02577 } 02578 } 02579 } 02580 if (key->name != ignore_key) 02581 key_parts+=key->columns.elements; 02582 else 02583 (*key_count)--; 02584 if (key->name && !tmp_table && (key->type != Key::PRIMARY) && 02585 !my_strcasecmp(system_charset_info,key->name,primary_key_name)) 02586 { 02587 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); 02588 DBUG_RETURN(-1); 02589 } 02590 } 02591 tmp=file->max_keys(); 02592 if (*key_count > tmp) 02593 { 02594 my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); 02595 DBUG_RETURN(-1); 02596 } 02597 02598 (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count)); 02599 key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); 02600 if (!*key_info_buffer || ! key_part_info) 02601 DBUG_RETURN(-1); // Out of memory 02602 02603 key_iterator.rewind(); 02604 key_number=0; 02605 for (; (key=key_iterator++) ; key_number++) 02606 { 02607 uint key_length=0; 02608 key_part_spec *column; 02609 02610 if (key->name == ignore_key) 02611 { 02612 /* ignore redundant keys */ 02613 do 02614 key=key_iterator++; 02615 while (key && key->name == ignore_key); 02616 if (!key) 02617 break; 02618 } 02619 02620 switch (key->type) { 02621 case Key::MULTIPLE: 02622 key_info->flags= 0; 02623 break; 02624 case Key::FULLTEXT: 02625 key_info->flags= HA_FULLTEXT; 02626 if ((key_info->parser_name= &key->key_create_info.parser_name)->str) 02627 key_info->flags|= HA_USES_PARSER; 02628 else 02629 key_info->parser_name= 0; 02630 break; 02631 case Key::SPATIAL: 02632 #ifdef HAVE_SPATIAL 02633 key_info->flags= HA_SPATIAL; 02634 break; 02635 #else 02636 my_error(ER_FEATURE_DISABLED, MYF(0), 02637 sym_group_geom.name, sym_group_geom.needed_define); 02638 DBUG_RETURN(-1); 02639 #endif 02640 case Key::FOREIGN_KEY: 02641 key_number--; // Skip this key 02642 continue; 02643 default: 02644 key_info->flags = HA_NOSAME; 02645 break; 02646 } 02647 if (key->generated) 02648 key_info->flags|= HA_GENERATED_KEY; 02649 02650 key_info->key_parts=(uint8) key->columns.elements; 02651 key_info->key_part=key_part_info; 02652 key_info->usable_key_parts= key_number; 02653 key_info->algorithm= key->key_create_info.algorithm; 02654 02655 if (key->type == Key::FULLTEXT) 02656 { 02657 if (!(file->ha_table_flags() & HA_CAN_FULLTEXT)) 02658 { 02659 my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT), 02660 MYF(0)); 02661 DBUG_RETURN(-1); 02662 } 02663 } 02664 /* 02665 Make SPATIAL to be RTREE by default 02666 SPATIAL only on BLOB or at least BINARY, this 02667 actually should be replaced by special GEOM type 02668 in near future when new frm file is ready 02669 checking for proper key parts number: 02670 */ 02671 02672 /* TODO: Add proper checks if handler supports key_type and algorithm */ 02673 if (key_info->flags & HA_SPATIAL) 02674 { 02675 if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS)) 02676 { 02677 my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS), 02678 MYF(0)); 02679 DBUG_RETURN(-1); 02680 } 02681 if (key_info->key_parts != 1) 02682 { 02683 my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX"); 02684 DBUG_RETURN(-1); 02685 } 02686 } 02687 else if (key_info->algorithm == HA_KEY_ALG_RTREE) 02688 { 02689 #ifdef HAVE_RTREE_KEYS 02690 if ((key_info->key_parts & 1) == 1) 02691 { 02692 my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX"); 02693 DBUG_RETURN(-1); 02694 } 02695 /* TODO: To be deleted */ 02696 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX"); 02697 DBUG_RETURN(-1); 02698 #else 02699 my_error(ER_FEATURE_DISABLED, MYF(0), 02700 sym_group_rtree.name, sym_group_rtree.needed_define); 02701 DBUG_RETURN(-1); 02702 #endif 02703 } 02704 02705 /* Take block size from key part or table part */ 02706 /* 02707 TODO: Add warning if block size changes. We can't do it here, as 02708 this may depend on the size of the key 02709 */ 02710 key_info->block_size= (key->key_create_info.block_size ? 02711 key->key_create_info.block_size : 02712 create_info->key_block_size); 02713 02714 if (key_info->block_size) 02715 key_info->flags|= HA_USES_BLOCK_SIZE; 02716 02717 List_iterator<key_part_spec> cols(key->columns), cols2(key->columns); 02718 CHARSET_INFO *ft_key_charset=0; // for FULLTEXT 02719 for (uint column_nr=0 ; (column=cols++) ; column_nr++) 02720 { 02721 uint length; 02722 key_part_spec *dup_column; 02723 02724 it.rewind(); 02725 field=0; 02726 while ((sql_field=it++) && 02727 my_strcasecmp(system_charset_info, 02728 column->field_name, 02729 sql_field->field_name)) 02730 field++; 02731 if (!sql_field) 02732 { 02733 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name); 02734 DBUG_RETURN(-1); 02735 } 02736 while ((dup_column= cols2++) != column) 02737 { 02738 if (!my_strcasecmp(system_charset_info, 02739 column->field_name, dup_column->field_name)) 02740 { 02741 my_printf_error(ER_DUP_FIELDNAME, 02742 ER(ER_DUP_FIELDNAME),MYF(0), 02743 column->field_name); 02744 DBUG_RETURN(-1); 02745 } 02746 } 02747 cols2.rewind(); 02748 if (key->type == Key::FULLTEXT) 02749 { 02750 if ((sql_field->sql_type != MYSQL_TYPE_STRING && 02751 sql_field->sql_type != MYSQL_TYPE_VARCHAR && 02752 !f_is_blob(sql_field->pack_flag)) || 02753 sql_field->charset == &my_charset_bin || 02754 sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet 02755 (ft_key_charset && sql_field->charset != ft_key_charset)) 02756 { 02757 my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name); 02758 DBUG_RETURN(-1); 02759 } 02760 ft_key_charset=sql_field->charset; 02761 /* 02762 for fulltext keys keyseg length is 1 for blobs (it's ignored in ft 02763 code anyway, and 0 (set to column width later) for char's. it has 02764 to be correct col width for char's, as char data are not prefixed 02765 with length (unlike blobs, where ft code takes data length from a 02766 data prefix, ignoring column->length). 02767 */ 02768 column->length=test(f_is_blob(sql_field->pack_flag)); 02769 } 02770 else 02771 { 02772 column->length*= sql_field->charset->mbmaxlen; 02773 02774 if (f_is_blob(sql_field->pack_flag) || 02775 (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL)) 02776 { 02777 if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS)) 02778 { 02779 my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name); 02780 DBUG_RETURN(-1); 02781 } 02782 if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type == 02783 Field::GEOM_POINT) 02784 column->length= 21; 02785 if (!column->length) 02786 { 02787 my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name); 02788 DBUG_RETURN(-1); 02789 } 02790 } 02791 #ifdef HAVE_SPATIAL 02792 if (key->type == Key::SPATIAL) 02793 { 02794 if (!column->length) 02795 { 02796 /* 02797 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case 02798 Lately we'll extend this code to support more dimensions 02799 */ 02800 column->length= 4*sizeof(double); 02801 } 02802 } 02803 #endif 02804 if (!(sql_field->flags & NOT_NULL_FLAG)) 02805 { 02806 if (key->type == Key::PRIMARY) 02807 { 02808 /* Implicitly set primary key fields to NOT NULL for ISO conf. */ 02809 sql_field->flags|= NOT_NULL_FLAG; 02810 sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL; 02811 null_fields--; 02812 } 02813 else 02814 { 02815 key_info->flags|= HA_NULL_PART_KEY; 02816 if (!(file->ha_table_flags() & HA_NULL_IN_KEY)) 02817 { 02818 my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name); 02819 DBUG_RETURN(-1); 02820 } 02821 if (key->type == Key::SPATIAL) 02822 { 02823 my_message(ER_SPATIAL_CANT_HAVE_NULL, 02824 ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0)); 02825 DBUG_RETURN(-1); 02826 } 02827 } 02828 } 02829 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) 02830 { 02831 if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY)) 02832 auto_increment--; // Field is used 02833 } 02834 } 02835 02836 key_part_info->fieldnr= field; 02837 key_part_info->offset= (uint16) sql_field->offset; 02838 key_part_info->key_type=sql_field->pack_flag; 02839 length= sql_field->key_length; 02840 02841 if (column->length) 02842 { 02843 if (f_is_blob(sql_field->pack_flag)) 02844 { 02845 if ((length=column->length) > max_key_length || 02846 length > file->max_key_part_length()) 02847 { 02848 length=min(max_key_length, file->max_key_part_length()); 02849 if (key->type == Key::MULTIPLE) 02850 { 02851 /* not a critical problem */ 02852 char warn_buff[MYSQL_ERRMSG_SIZE]; 02853 my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY), 02854 length); 02855 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 02856 ER_TOO_LONG_KEY, warn_buff); 02857 } 02858 else 02859 { 02860 my_error(ER_TOO_LONG_KEY,MYF(0),length); 02861 DBUG_RETURN(-1); 02862 } 02863 } 02864 } 02865 else if (!f_is_geom(sql_field->pack_flag) && 02866 (column->length > length || 02867 ((f_is_packed(sql_field->pack_flag) || 02868 ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && 02869 (key_info->flags & HA_NOSAME))) && 02870 column->length != length))) 02871 { 02872 my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0)); 02873 DBUG_RETURN(-1); 02874 } 02875 else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) 02876 length=column->length; 02877 } 02878 else if (length == 0) 02879 { 02880 my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name); 02881 DBUG_RETURN(-1); 02882 } 02883 if (length > file->max_key_part_length() && key->type != Key::FULLTEXT) 02884 { 02885 length= file->max_key_part_length(); 02886 /* Align key length to multibyte char boundary */ 02887 length-= length % sql_field->charset->mbmaxlen; 02888 if (key->type == Key::MULTIPLE) 02889 { 02890 /* not a critical problem */ 02891 char warn_buff[MYSQL_ERRMSG_SIZE]; 02892 my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY), 02893 length); 02894 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 02895 ER_TOO_LONG_KEY, warn_buff); 02896 } 02897 else 02898 { 02899 my_error(ER_TOO_LONG_KEY,MYF(0),length); 02900 DBUG_RETURN(-1); 02901 } 02902 } 02903 key_part_info->length=(uint16) length; 02904 /* Use packed keys for long strings on the first column */ 02905 if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) && 02906 (length >= KEY_DEFAULT_PACK_LENGTH && 02907 (sql_field->sql_type == MYSQL_TYPE_STRING || 02908 sql_field->sql_type == MYSQL_TYPE_VARCHAR || 02909 sql_field->pack_flag & FIELDFLAG_BLOB))) 02910 { 02911 if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) || 02912 sql_field->sql_type == MYSQL_TYPE_VARCHAR) 02913 key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY; 02914 else 02915 key_info->flags|= HA_PACK_KEY; 02916 } 02917 key_length+=length; 02918 key_part_info++; 02919 02920 /* Create the key name based on the first column (if not given) */ 02921 if (column_nr == 0) 02922 { 02923 if (key->type == Key::PRIMARY) 02924 { 02925 if (primary_key) 02926 { 02927 my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY), 02928 MYF(0)); 02929 DBUG_RETURN(-1); 02930 } 02931 key_name=primary_key_name; 02932 primary_key=1; 02933 } 02934 else if (!(key_name = key->name)) 02935 key_name=make_unique_key_name(sql_field->field_name, 02936 *key_info_buffer, key_info); 02937 if (check_if_keyname_exists(key_name, *key_info_buffer, key_info)) 02938 { 02939 my_error(ER_DUP_KEYNAME, MYF(0), key_name); 02940 DBUG_RETURN(-1); 02941 } 02942 key_info->name=(char*) key_name; 02943 } 02944 } 02945 if (!key_info->name || check_column_name(key_info->name)) 02946 { 02947 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name); 02948 DBUG_RETURN(-1); 02949 } 02950 if (!(key_info->flags & HA_NULL_PART_KEY)) 02951 unique_key=1; 02952 key_info->key_length=(uint16) key_length; 02953 if (key_length > max_key_length && key->type != Key::FULLTEXT) 02954 { 02955 my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length); 02956 DBUG_RETURN(-1); 02957 } 02958 key_info++; 02959 } 02960 if (!unique_key && !primary_key && 02961 (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY)) 02962 { 02963 my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0)); 02964 DBUG_RETURN(-1); 02965 } 02966 if (auto_increment > 0) 02967 { 02968 my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0)); 02969 DBUG_RETURN(-1); 02970 } 02971 /* Sort keys in optimized order */ 02972 qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY), 02973 (qsort_cmp) sort_keys); 02974 create_info->null_bits= null_fields; 02975 02976 DBUG_RETURN(0); 02977 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_recreate_table | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| bool | do_send_ok | |||
| ) |
Definition at line 6608 of file sql_table.cc.
References bzero, DBUG_ENTER, DBUG_RETURN, default_charset_info, mysql_alter_table(), NullS, and ROW_TYPE_NOT_USED.
Referenced by mysql_admin_table(), and mysql_execute_command().
06610 { 06611 DBUG_ENTER("mysql_recreate_table"); 06612 LEX *lex= thd->lex; 06613 HA_CREATE_INFO create_info; 06614 lex->create_list.empty(); 06615 lex->key_list.empty(); 06616 lex->col_list.empty(); 06617 lex->alter_info.reset(); 06618 bzero((char*) &create_info,sizeof(create_info)); 06619 create_info.db_type= 0; 06620 create_info.row_type=ROW_TYPE_NOT_USED; 06621 create_info.default_table_charset=default_charset_info; 06622 /* Force alter table to recreate table */ 06623 lex->alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); 06624 DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, 06625 table_list, lex->create_list, 06626 lex->key_list, 0, (ORDER *) 0, 06627 0, &lex->alter_info, do_send_ok)); 06628 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_rename_table | ( | handlerton * | base, | |
| const char * | old_db, | |||
| const char * | old_name, | |||
| const char * | new_db, | |||
| const char * | new_name, | |||
| uint | flags | |||
| ) |
Definition at line 3641 of file sql_table.cc.
References build_table_filename(), current_thd, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER_ERROR_ON_RENAME, ER_NOT_SUPPORTED_YET, error, files_charset_info, FN_REFLEN, from, get_new_handler(), HA_ERR_WRONG_COMMAND, HA_FILE_BASED, handler::ha_table_flags(), lower_case_table_names, my_casedn_str, my_errno, my_error(), MYF, NAME_LEN, NULL, reg_ext, rename_file_ext(), handler::rename_table(), strmov(), and to.
Referenced by mysql_alter_table(), and rename_tables().
03644 { 03645 THD *thd= current_thd; 03646 char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN]; 03647 char *from_base= from, *to_base= to; 03648 char tmp_name[NAME_LEN+1]; 03649 handler *file; 03650 int error=0; 03651 DBUG_ENTER("mysql_rename_table"); 03652 DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'", 03653 old_db, old_name, new_db, new_name)); 03654 03655 file= (base == NULL ? 0 : 03656 get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base)); 03657 03658 build_table_filename(from, sizeof(from), old_db, old_name, "", 03659 flags & FN_FROM_IS_TMP); 03660 build_table_filename(to, sizeof(to), new_db, new_name, "", 03661 flags & FN_TO_IS_TMP); 03662 03663 /* 03664 If lower_case_table_names == 2 (case-preserving but case-insensitive 03665 file system) and the storage is not HA_FILE_BASED, we need to provide 03666 a lowercase file name, but we leave the .frm in mixed case. 03667 */ 03668 if (lower_case_table_names == 2 && file && 03669 !(file->ha_table_flags() & HA_FILE_BASED)) 03670 { 03671 strmov(tmp_name, old_name); 03672 my_casedn_str(files_charset_info, tmp_name); 03673 build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "", 03674 flags & FN_FROM_IS_TMP); 03675 from_base= lc_from; 03676 03677 strmov(tmp_name, new_name); 03678 my_casedn_str(files_charset_info, tmp_name); 03679 build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "", 03680 flags & FN_TO_IS_TMP); 03681 to_base= lc_to; 03682 } 03683 03684 if (!file || !(error=file->rename_table(from_base, to_base))) 03685 { 03686 if (rename_file_ext(from,to,reg_ext)) 03687 { 03688 error=my_errno; 03689 /* Restore old file name */ 03690 if (file) 03691 file->rename_table(to_base, from_base); 03692 } 03693 } 03694 delete file; 03695 if (error == HA_ERR_WRONG_COMMAND) 03696 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE"); 03697 else if (error) 03698 my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error); 03699 DBUG_RETURN(error != 0); 03700 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_repair_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) |
Definition at line 4413 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, HA_OPEN_FOR_REPAIR, handler::ha_repair(), mysql_admin_table(), prepare_for_repair(), st_ha_check_opt::sql_flags, test, TL_WRITE, and TT_USEFRM.
Referenced by mysql_execute_command().
04414 { 04415 DBUG_ENTER("mysql_repair_table"); 04416 DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, 04417 "repair", TL_WRITE, 1, 04418 test(check_opt->sql_flags & TT_USEFRM), 04419 HA_OPEN_FOR_REPAIR, 04420 &prepare_for_repair, 04421 &handler::ha_repair, 0)); 04422 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_restore_table | ( | THD * | thd, | |
| TABLE_LIST * | table_list | |||
| ) |
Definition at line 4403 of file sql_table.cc.
References DBUG_ENTER, DBUG_RETURN, mysql_admin_table(), prepare_for_restore(), handler::restore(), and TL_WRITE.
Referenced by mysql_execute_command().
04404 { 04405 DBUG_ENTER("mysql_restore_table"); 04406 DBUG_RETURN(mysql_admin_table(thd, table_list, 0, 04407 "restore", TL_WRITE, 1, 1, 0, 04408 &prepare_for_restore, 04409 &handler::restore, 0)); 04410 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_rm_table | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| my_bool | if_exists, | |||
| my_bool | drop_temporary | |||
| ) |
Definition at line 1465 of file sql_table.cc.
References COND_refresh, DBUG_ENTER, DBUG_RETURN, ER_TABLE_NOT_LOCKED_FOR_WRITE, error, FALSE, LOCK_open, my_error(), MYF, mysql_rm_table_part2(), pthread_mutex_lock, pthread_mutex_unlock, send_ok(), start_waiting_global_read_lock(), st_table_list::table_name, TRUE, VOID, and wait_if_global_read_lock().
Referenced by mysql_execute_command().
01467 { 01468 bool error= FALSE, need_start_waiters= FALSE; 01469 DBUG_ENTER("mysql_rm_table"); 01470 01471 /* mark for close and remove all cached entries */ 01472 01473 if (!drop_temporary) 01474 { 01475 if ((error= wait_if_global_read_lock(thd, 0, 1))) 01476 { 01477 my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name); 01478 DBUG_RETURN(TRUE); 01479 } 01480 else 01481 need_start_waiters= TRUE; 01482 } 01483 01484 /* 01485 Acquire LOCK_open after wait_if_global_read_lock(). If we would hold 01486 LOCK_open during wait_if_global_read_lock(), other threads could not 01487 close their tables. This would make a pretty deadlock. 01488 */ 01489 thd->mysys_var->current_mutex= &LOCK_open; 01490 thd->mysys_var->current_cond= &COND_refresh; 01491 VOID(pthread_mutex_lock(&LOCK_open)); 01492 01493 error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0); 01494 01495 pthread_mutex_unlock(&LOCK_open); 01496 01497 pthread_mutex_lock(&thd->mysys_var->mutex); 01498 thd->mysys_var->current_mutex= 0; 01499 thd->mysys_var->current_cond= 0; 01500 pthread_mutex_unlock(&thd->mysys_var->mutex); 01501 01502 if (need_start_waiters) 01503 start_waiting_global_read_lock(thd); 01504 01505 if (error) 01506 DBUG_RETURN(TRUE); 01507 send_ok(thd); 01508 DBUG_RETURN(FALSE); 01509 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mysql_rm_table_part2 | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| bool | if_exists, | |||
| bool | drop_temporary, | |||
| bool | drop_view, | |||
| bool | dont_log_query | |||
| ) |
Definition at line 1584 of file sql_table.cc.
References abort_locked_tables(), access, st_table_list::alias, String::append(), build_table_filename(), close_temporary_table(), db, st_table_list::db, handlerton::db_type, st_table_list::db_type, DBUG_ENTER, DBUG_RETURN, Table_triggers_list::drop_all_triggers(), drop_locked_tables(), ER, ER_BAD_TABLE_ERROR, ER_CANT_DROP_LOG_TABLE, error, F_OK, FN_REFLEN, FRMTYPE_TABLE, get_cached_table_share(), ha_create_table_from_engine(), ha_delete_table(), HA_ERR_NO_SUCH_TABLE, HA_ERR_ROW_IS_REFERENCED, ha_resolve_by_legacy_type(), LOGGER::is_general_log_table_enabled(), LOGGER::is_slow_log_table_enabled(), String::length(), LINT_INIT, LOCK_open, lock_table_names(), logger, lower_case_table_names, my_delete(), my_error(), my_strcasecmp, MY_WME, MYF, mysql_frm_type(), mysql_ha_flush(), st_table_list::next_local, NULL, opt_log, opt_slow_log, path, push_warning_printf(), reg_ext, reg_ext_length, remove_table_from_cache(), safe_mutex_assert_owner, String::set_charset(), strcmp(), strmov(), system_charset_info, st_table_list::table, st_table_list::table_name, TRUE, and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by mysql_rm_table(), and mysql_rm_table_part2_with_lock().
01587 { 01588 TABLE_LIST *table; 01589 char path[FN_REFLEN], *alias; 01590 uint path_length; 01591 String wrong_tables; 01592 int error; 01593 int non_temp_tables_count= 0; 01594 bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; 01595 String built_query; 01596 DBUG_ENTER("mysql_rm_table_part2"); 01597 01598 LINT_INIT(alias); 01599 LINT_INIT(path_length); 01600 safe_mutex_assert_owner(&LOCK_open); 01601 01602 if (thd->current_stmt_binlog_row_based && !dont_log_query) 01603 { 01604 built_query.set_charset(system_charset_info); 01605 if (if_exists) 01606 built_query.append("DROP TABLE IF EXISTS "); 01607 else 01608 built_query.append("DROP TABLE "); 01609 } 01610 /* 01611 If we have the table in the definition cache, we don't have to check the 01612 .frm file to find if the table is a normal table (not view) and what 01613 engine to use. 01614 */ 01615 01616 for (table= tables; table; table= table->next_local) 01617 { 01618 TABLE_SHARE *share; 01619 table->db_type= NULL; 01620 if ((share= get_cached_table_share(table->db, table->table_name))) 01621 table->db_type= share->db_type; 01622 01623 /* Disable drop of enabled log tables */ 01624 if (share && share->log_table && 01625 ((!my_strcasecmp(system_charset_info, table->table_name, 01626 "general_log") && opt_log && 01627 logger.is_general_log_table_enabled()) || 01628 (!my_strcasecmp(system_charset_info, table->table_name, "slow_log") 01629 && opt_slow_log && logger.is_slow_log_table_enabled()))) 01630 { 01631 my_error(ER_CANT_DROP_LOG_TABLE, MYF(0)); 01632 DBUG_RETURN(1); 01633 } 01634 } 01635 01636 if (lock_table_names(thd, tables)) 01637 DBUG_RETURN(1); 01638 01639 /* Don't give warnings for not found errors, as we already generate notes */ 01640 thd->no_warnings_for_error= 1; 01641 01642 for (table= tables; table; table= table->next_local) 01643 { 01644 char *db=table->db; 01645 handlerton *table_type; 01646 enum legacy_db_type frm_db_type; 01647 01648 mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE); 01649 if (!close_temporary_table(thd, table)) 01650 { 01651 tmp_table_deleted=1; 01652 continue; // removed temporary table 01653 } 01654 01655 /* 01656 If row-based replication is used and the table is not a 01657 temporary table, we add the table name to the drop statement 01658 being built. The string always end in a comma and the comma 01659 will be chopped off before being written to the binary log. 01660 */ 01661 if (thd->current_stmt_binlog_row_based && !dont_log_query) 01662 { 01663 non_temp_tables_count++; 01664 /* 01665 Don't write the database name if it is the current one (or if 01666 thd->db is NULL). 01667 */ 01668 built_query.append("`"); 01669 if (thd->db == NULL || strcmp(db,thd->db) != 0) 01670 { 01671 built_query.append(db); 01672 built_query.append("`.`"); 01673 } 01674 01675 built_query.append(table->table_name); 01676 built_query.append("`,"); 01677 } 01678 01679 error=0; 01680 table_type= table->db_type; 01681 if (!drop_temporary) 01682 { 01683 TABLE *locked_table; 01684 abort_locked_tables(thd, db, table->table_name); 01685 remove_table_from_cache(thd, db, table->table_name, 01686 RTFC_WAIT_OTHER_THREAD_FLAG | 01687 RTFC_CHECK_KILLED_FLAG); 01688 /* 01689 If the table was used in lock tables, remember it so that 01690 unlock_table_names can free it 01691 */ 01692 if ((locked_table= drop_locked_tables(thd, db, table->table_name))) 01693 table->table= locked_table; 01694 01695 if (thd->killed) 01696 { 01697 thd->no_warnings_for_error= 0; 01698 DBUG_RETURN(-1); 01699 } 01700 alias= (lower_case_table_names == 2) ? table->alias : table->table_name; 01701 /* remove .frm file and engine files */ 01702 path_length= build_table_filename(path, sizeof(path), 01703 db, alias, reg_ext, 0); 01704 } 01705 if (drop_temporary || 01706 (table_type == NULL && 01707 (access(path, F_OK) && 01708 ha_create_table_from_engine(thd, db, alias)) || 01709 (!drop_view && 01710 mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE))) 01711 { 01712 // Table was not found on disk and table can't be created from engine 01713 if (if_exists) 01714 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 01715 ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), 01716 table->table_name); 01717 else 01718 error= 1; 01719 } 01720 else 01721 { 01722 char *end; 01723 if (table_type == NULL) 01724 { 01725 mysql_frm_type(thd, path, &frm_db_type); 01726 table_type= ha_resolve_by_legacy_type(thd, frm_db_type); 01727 } 01728 // Remove extension for delete 01729 *(end= path + path_length - reg_ext_length)= '\0'; 01730 error= ha_delete_table(thd, table_type, path, db, table->table_name, 01731 !dont_log_query); 01732 if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 01733 (if_exists || table_type == NULL)) 01734 error= 0; 01735 if (error == HA_ERR_ROW_IS_REFERENCED) 01736 { 01737 /* the table is referenced by a foreign key constraint */ 01738 foreign_key_error=1; 01739 } 01740 if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) 01741 { 01742 int new_error; 01743 /* Delete the table definition file */ 01744 strmov(end,reg_ext); 01745 if (!(new_error=my_delete(path,MYF(MY_WME)))) 01746 { 01747 some_tables_deleted=1; 01748 new_error= Table_triggers_list::drop_all_triggers(thd, db, 01749 table->table_name); 01750 } 01751 error|= new_error; 01752 } 01753 } 01754 if (error) 01755 { 01756 if (wrong_tables.length()) 01757 wrong_tables.append(','); 01758 wrong_tables.append(String(table->table_name,system_charset_info)); 01759 } 01760 } 01761 thd->tmp_table_used= tmp_table_deleted; 01762 error= 0; 01763 if (wrong_tables.length()) 01764 { 01765 if (!foreign_key_error) 01766 my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0), 01767 wrong_tables.c_ptr()); 01768 else 01769 my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); 01770 error= 1; 01771 } 01772 01773 if (some_tables_deleted || tmp_table_deleted || !error) 01774 { 01775 query_cache_invalidate3(thd, tables, 0); 01776 if (!dont_log_query) 01777 { 01778 if (!thd->current_stmt_binlog_row_based || 01779 non_temp_tables_count > 0 && !tmp_table_deleted) 01780 { 01781 /* 01782 In this case, we are either using statement-based 01783 replication or using row-based replication but have only 01784 deleted one or more non-temporary tables (and no temporary 01785 tables). In this case, we can write the original query into 01786 the binary log. 01787 */ 01788 write_bin_log(thd, !error, thd->query, thd->query_length); 01789 } 01790 else if (thd->current_stmt_binlog_row_based && 01791 non_temp_tables_count > 0 && 01792 tmp_table_deleted) 01793 { 01794 /* 01795 In this case we have deleted both temporary and 01796 non-temporary tables, so: 01797 - since we have deleted a non-temporary table we have to 01798 binlog the statement, but 01799 - since we have deleted a temporary table we cannot binlog 01800 the statement (since the table has not been created on the 01801 slave, this might cause the slave to stop). 01802 01803 Instead, we write a built statement, only containing the 01804 non-temporary tables, to the binary log 01805 */ 01806 built_query.chop(); // Chop of the last comma 01807 built_query.append(" /* generated by server */"); 01808 write_bin_log(thd, !error, built_query.ptr(), built_query.length()); 01809 } 01810 /* 01811 The remaining cases are: 01812 - no tables where deleted and 01813 - only temporary tables where deleted and row-based 01814 replication is used. 01815 In both these cases, nothing should be written to the binary 01816 log. 01817 */ 01818 } 01819 } 01820 01821 unlock_table_names(thd, tables, (TABLE_LIST*) 0); 01822 thd->no_warnings_for_error= 0; 01823 DBUG_RETURN(error); 01824 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mysql_rm_table_part2_with_lock | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| bool | if_exists, | |||
| bool | drop_temporary, | |||
| bool | dont_log_query | |||
| ) |
Definition at line 1532 of file sql_table.cc.
References COND_refresh, error, LOCK_open, mysql_rm_table_part2(), pthread_mutex_lock, pthread_mutex_unlock, and VOID.
Referenced by mysql_rm_known_files().
01535 { 01536 int error; 01537 thd->mysys_var->current_mutex= &LOCK_open; 01538 thd->mysys_var->current_cond= &COND_refresh; 01539 VOID(pthread_mutex_lock(&LOCK_open)); 01540 01541 error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 1, 01542 dont_log_query); 01543 01544 pthread_mutex_unlock(&LOCK_open); 01545 01546 pthread_mutex_lock(&thd->mysys_var->mutex); 01547 thd->mysys_var->current_mutex= 0; 01548 thd->mysys_var->current_cond= 0; 01549 pthread_mutex_unlock(&thd->mysys_var->mutex); 01550 return error; 01551 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1268 of file sql_table.cc.
References build_table_filename(), CHF_CREATE_FLAG, CHF_DELETE_FLAG, CHF_RENAME_FLAG, data, DBUG_ENTER, DBUG_RETURN, deactivate_ddl_log_entry(), error, FALSE, FN_REFLEN, partition_info::frm_log_entry, generate_partition_syntax(), LOCK_open, mem_alloc_error(), MY_ALLOW_ZERO_PTR, my_delete(), my_free, my_rename(), MY_WME, MYF, mysql_copy_create_list(), mysql_copy_key_list(), mysql_create_frm(), mysql_prepare_table(), NULL, NullS, packfrm(), partition_info::part_info_len, partition_info::part_info_string, path, pthread_mutex_lock, pthread_mutex_unlock, readfrm(), reg_ext, strxmov(), sync_ddl_log(), TRUE, VOID, and WITH_PARTITION_STORAGE_ENGINE.
01269 { 01270 /* 01271 Prepare table to prepare for writing a new frm file where the 01272 partitions in add/drop state have temporarily changed their state 01273 We set tmp_table to avoid get errors on naming of primary key index. 01274 */ 01275 int error= 0; 01276 char path[FN_REFLEN+1]; 01277 char shadow_path[FN_REFLEN+1]; 01278 char shadow_frm_name[FN_REFLEN+1]; 01279 char frm_name[FN_REFLEN+1]; 01280 DBUG_ENTER("mysql_write_frm"); 01281 01282 /* 01283 Build shadow frm file name 01284 */ 01285 build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, 01286 lpt->table_name, "#", 0); 01287 strxmov(shadow_frm_name, shadow_path, reg_ext, NullS); 01288 if (flags & WFRM_WRITE_SHADOW) 01289 { 01290 if (mysql_copy_create_list(lpt->create_list, 01291 &lpt->new_create_list) || 01292 mysql_copy_key_list(lpt->key_list, 01293 &lpt->new_key_list) || 01294 mysql_prepare_table(lpt->thd, lpt->create_info, 01295 &lpt->new_create_list, 01296 &lpt->new_key_list, 01297 /*tmp_table*/ 1, 01298 &lpt->db_options, 01299 lpt->table->file, 01300 &lpt->key_info_buffer, 01301 &lpt->key_count, 01302 /*select_field_count*/ 0)) 01303 { 01304 DBUG_RETURN(TRUE); 01305 } 01306 #ifdef WITH_PARTITION_STORAGE_ENGINE 01307 { 01308 partition_info *part_info= lpt->table->part_info; 01309 char *part_syntax_buf; 01310 uint syntax_len; 01311 01312 if (part_info) 01313 { 01314 if (!(part_syntax_buf= generate_partition_syntax(part_info, 01315 &syntax_len, 01316 TRUE, TRUE))) 01317 { 01318 DBUG_RETURN(TRUE); 01319 } 01320 part_info->part_info_string= part_syntax_buf; 01321 part_info->part_info_len= syntax_len; 01322 } 01323 } 01324 #endif 01325 /* Write shadow frm file */ 01326 lpt->create_info->table_options= lpt->db_options; 01327 if ((mysql_create_frm(lpt->thd, shadow_frm_name, lpt->db, 01328 lpt->table_name, lpt->create_info, 01329 lpt->new_create_list, lpt->key_count, 01330 lpt->key_info_buffer, lpt->table->file)) || 01331 lpt->table->file->create_handler_files(shadow_path, NULL, 01332 CHF_CREATE_FLAG, 01333 lpt->create_info)) 01334 { 01335 my_delete(shadow_frm_name, MYF(0)); 01336 error= 1; 01337 goto end; 01338 } 01339 } 01340 if (flags & WFRM_PACK_FRM) 01341 { 01342 /* 01343 We need to pack the frm file and after packing it we delete the 01344 frm file to ensure it doesn't get used. This is only used for 01345 handlers that have the main version of the frm file stored in the 01346 handler. 01347 */ 01348 const void *data= 0; 01349 uint length= 0; 01350 if (readfrm(shadow_path, &data, &length) || 01351 packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len)) 01352 { 01353 my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); 01354 my_free((char*)lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR)); 01355 mem_alloc_error(length); 01356 error= 1; 01357 goto end; 01358 } 01359 error= my_delete(shadow_frm_name, MYF(MY_WME)); 01360 } 01361 if (flags & WFRM_INSTALL_SHADOW) 01362 { 01363 #ifdef WITH_PARTITION_STORAGE_ENGINE 01364 partition_info *part_info= lpt->part_info; 01365 #endif 01366 /* 01367 Build frm file name 01368 */ 01369 build_table_filename(path, sizeof(path), lpt->db, 01370 lpt->table_name, "", 0); 01371 strxmov(frm_name, path, reg_ext, NullS); 01372 /* 01373 When we are changing to use new frm file we need to ensure that we 01374 don't collide with another thread in process to open the frm file. 01375 We start by deleting the .frm file and possible .par file. Then we 01376 write to the DDL log that we have completed the delete phase by 01377 increasing the phase of the log entry. Next step is to rename the 01378 new .frm file and the new .par file to the real name. After 01379 completing this we write a new phase to the log entry that will 01380 deactivate it. 01381 */ 01382 VOID(pthread_mutex_lock(&LOCK_open)); 01383 if (my_delete(frm_name, MYF(MY_WME)) || 01384 #ifdef WITH_PARTITION_STORAGE_ENGINE 01385 lpt->table->file->create_handler_files(path, shadow_path, 01386 CHF_DELETE_FLAG, NULL) || 01387 deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos) || 01388 (sync_ddl_log(), FALSE) || 01389 #endif 01390 #ifdef WITH_PARTITION_STORAGE_ENGINE 01391 my_rename(shadow_frm_name, frm_name, MYF(MY_WME)) || 01392 lpt->table->file->create_handler_files(path, shadow_path, 01393 CHF_RENAME_FLAG, NULL)) 01394 #else 01395 my_rename(shadow_frm_name, frm_name, MYF(MY_WME))) 01396 #endif 01397 { 01398 error= 1; 01399 } 01400 VOID(pthread_mutex_unlock(&LOCK_open)); 01401 #ifdef WITH_PARTITION_STORAGE_ENGINE 01402 deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos); 01403 part_info->frm_log_entry= NULL; 01404 VOID(sync_ddl_log()); 01405 #endif 01406 } 01407 01408 end: 01409 DBUG_RETURN(error); 01410 }
Here is the call graph for this function:

| static bool prepare_blob_field | ( | THD * | thd, | |
| create_field * | sql_field | |||
| ) | [static] |
Definition at line 3025 of file sql_table.cc.
References BLOB_FLAG, calc_pack_length(), create_field::charset, DBUG_ENTER, DBUG_RETURN, create_field::def, ER, ER_AUTO_CONVERT, ER_TOO_BIG_FIELDLENGTH, create_field::field_name, FIELD_TYPE_BLOB, create_field::flags, get_blob_type_from_length(), create_field::length, MAX_FIELD_VARCHARLENGTH, charset_info_st::mbmaxlen, MODE_STRICT_ALL_TABLES, MODE_STRICT_TRANS_TABLES, my_charset_bin, my_error(), MYF, MYSQL_ERRMSG_SIZE, create_field::pack_length, push_warning(), create_field::sql_type, and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by mysql_prepare_table(), and sp_prepare_create_field().
03026 { 03027 DBUG_ENTER("prepare_blob_field"); 03028 03029 if (sql_field->length > MAX_FIELD_VARCHARLENGTH && 03030 !(sql_field->flags & BLOB_FLAG)) 03031 { 03032 /* Convert long VARCHAR columns to TEXT or BLOB */ 03033 char warn_buff[MYSQL_ERRMSG_SIZE]; 03034 03035 if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | 03036 MODE_STRICT_ALL_TABLES))) 03037 { 03038 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name, 03039 MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen); 03040 DBUG_RETURN(1); 03041 } 03042 sql_field->sql_type= FIELD_TYPE_BLOB; 03043 sql_field->flags|= BLOB_FLAG; 03044 sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name, 03045 (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR", 03046 (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT"); 03047 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, 03048 warn_buff); 03049 } 03050 03051 if ((sql_field->flags & BLOB_FLAG) && sql_field->length) 03052 { 03053 if (sql_field->sql_type == FIELD_TYPE_BLOB) 03054 { 03055 /* The user has given a length to the blob column */ 03056 sql_field->sql_type= get_blob_type_from_length(sql_field->length); 03057 sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0); 03058 } 03059 sql_field->length= 0; 03060 } 03061 DBUG_RETURN(0); 03062 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int prepare_create_field | ( | create_field * | sql_field, | |
| uint * | blob_columns, | |||
| int * | timestamps, | |||
| int * | timestamps_with_niladic, | |||
| uint | table_flags | |||
| ) |
Definition at line 1996 of file sql_table.cc.
References Field::BIT_FIELD, Field::BLOB_FIELD, calc_pack_length(), create_field::charset, check_duplicates_in_interval(), DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, create_field::decimals, ER, ER_CHECK_NOT_IMPLEMENTED, ER_FEATURE_DISABLED, ER_TOO_BIG_FIELDLENGTH, f_settype, create_field::field_name, FIELD_TYPE_BIT, FIELD_TYPE_BLOB, FIELD_TYPE_DATE, FIELD_TYPE_DATETIME, FIELD_TYPE_ENUM, FIELD_TYPE_GEOMETRY, FIELD_TYPE_LONG_BLOB, FIELD_TYPE_MEDIUM_BLOB, FIELD_TYPE_NEWDATE, FIELD_TYPE_NEWDECIMAL, FIELD_TYPE_NULL, FIELD_TYPE_SET, FIELD_TYPE_STRING, FIELD_TYPE_TIME, FIELD_TYPE_TIMESTAMP, FIELD_TYPE_TINY_BLOB, FIELDFLAG_BINARY, FIELDFLAG_BITFIELD, FIELDFLAG_BLOB, FIELDFLAG_DEC_SHIFT, FIELDFLAG_DECIMAL, FIELDFLAG_GEOM, FIELDFLAG_INTERVAL, FIELDFLAG_MAYBE_NULL, FIELDFLAG_NO_DEFAULT, FIELDFLAG_NUMBER, FIELDFLAG_ZEROFILL, create_field::flags, HA_CAN_GEOMETRY, HA_NO_VARCHAR, create_field::interval, Field::INTERVAL_FIELD, create_field::length, MAX_FIELD_CHARLENGTH, charset_info_st::mbmaxlen, MY_CS_BINSORT, my_printf_error(), MYF, MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VARCHAR, st_sym_group::name, st_sym_group::needed_define, NO_DEFAULT_VALUE_FLAG, Field::NONE, NOT_NULL_FLAG, create_field::pack_flag, create_field::pack_length, pack_length_to_packflag(), portable_sizeof_char_ptr, create_field::sql_type, charset_info_st::state, sym_group_geom, Field::TIMESTAMP_DNUN_FIELD, Field::TIMESTAMP_OLD_FIELD, create_field::unireg_check, UNSIGNED_FLAG, and ZEROFILL_FLAG.
Referenced by sp_head::fill_field_definition().
02000 { 02001 DBUG_ENTER("prepare_field"); 02002 02003 /* 02004 This code came from mysql_prepare_table. 02005 Indent preserved to make patching easier 02006 */ 02007 DBUG_ASSERT(sql_field->charset); 02008 02009 switch (sql_field->sql_type) { 02010 case FIELD_TYPE_BLOB: 02011 case FIELD_TYPE_MEDIUM_BLOB: 02012 case FIELD_TYPE_TINY_BLOB: 02013 case FIELD_TYPE_LONG_BLOB: 02014 sql_field->pack_flag=FIELDFLAG_BLOB | 02015 pack_length_to_packflag(sql_field->pack_length - 02016 portable_sizeof_char_ptr); 02017 if (sql_field->charset->state & MY_CS_BINSORT) 02018 sql_field->pack_flag|=FIELDFLAG_BINARY; 02019 sql_field->length=8; // Unireg field length 02020 sql_field->unireg_check=Field::BLOB_FIELD; 02021 (*blob_columns)++; 02022 break; 02023 case FIELD_TYPE_GEOMETRY: 02024 #ifdef HAVE_SPATIAL 02025 if (!(table_flags & HA_CAN_GEOMETRY)) 02026 { 02027 my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), 02028 MYF(0), "GEOMETRY"); 02029 DBUG_RETURN(1); 02030 } 02031 sql_field->pack_flag=FIELDFLAG_GEOM | 02032 pack_length_to_packflag(sql_field->pack_length - 02033 portable_sizeof_char_ptr); 02034 if (sql_field->charset->state & MY_CS_BINSORT) 02035 sql_field->pack_flag|=FIELDFLAG_BINARY; 02036 sql_field->length=8; // Unireg field length 02037 sql_field->unireg_check=Field::BLOB_FIELD; 02038 (*blob_columns)++; 02039 break; 02040 #else 02041 my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), 02042 sym_group_geom.name, sym_group_geom.needed_define); 02043 DBUG_RETURN(1); 02044 #endif /*HAVE_SPATIAL*/ 02045 case MYSQL_TYPE_VARCHAR: 02046 #ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR 02047 if (table_flags & HA_NO_VARCHAR) 02048 { 02049 /* convert VARCHAR to CHAR because handler is not yet up to date */ 02050 sql_field->sql_type= MYSQL_TYPE_VAR_STRING; 02051 sql_field->pack_length= calc_pack_length(sql_field->sql_type, 02052 (uint) sql_field->length); 02053 if ((sql_field->length / sql_field->charset->mbmaxlen) > 02054 MAX_FIELD_CHARLENGTH) 02055 { 02056 my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH), 02057 MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH); 02058 DBUG_RETURN(1); 02059 } 02060 } 02061 #endif 02062 /* fall through */ 02063 case FIELD_TYPE_STRING: 02064 sql_field->pack_flag=0; 02065 if (sql_field->charset->state & MY_CS_BINSORT) 02066 sql_field->pack_flag|=FIELDFLAG_BINARY; 02067 break; 02068 case FIELD_TYPE_ENUM: 02069 sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | 02070 FIELDFLAG_INTERVAL; 02071 if (sql_field->charset->state & MY_CS_BINSORT) 02072 sql_field->pack_flag|=FIELDFLAG_BINARY; 02073 sql_field->unireg_check=Field::INTERVAL_FIELD; 02074 check_duplicates_in_interval("ENUM",sql_field->field_name, 02075 sql_field->interval, 02076 sql_field->charset); 02077 break; 02078 case FIELD_TYPE_SET: 02079 sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | 02080 FIELDFLAG_BITFIELD; 02081 if (sql_field->charset->state & MY_CS_BINSORT) 02082 sql_field->pack_flag|=FIELDFLAG_BINARY; 02083 sql_field->unireg_check=Field::BIT_FIELD; 02084 check_duplicates_in_interval("SET",sql_field->field_name, 02085 sql_field->interval, 02086 sql_field->charset); 02087 break; 02088 case FIELD_TYPE_DATE: // Rest of string types 02089 case FIELD_TYPE_NEWDATE: 02090 case FIELD_TYPE_TIME: 02091 case FIELD_TYPE_DATETIME: 02092 case FIELD_TYPE_NULL: 02093 sql_field->pack_flag=f_settype((uint) sql_field->sql_type); 02094 break; 02095 case FIELD_TYPE_BIT: 02096 /* 02097 We have sql_field->pack_flag already set here, see mysql_prepare_table(). 02098 */ 02099 break; 02100 case FIELD_TYPE_NEWDECIMAL: 02101 sql_field->pack_flag=(FIELDFLAG_NUMBER | 02102 (sql_field->flags & UNSIGNED_FLAG ? 0 : 02103 FIELDFLAG_DECIMAL) | 02104 (sql_field->flags & ZEROFILL_FLAG ? 02105 FIELDFLAG_ZEROFILL : 0) | 02106 (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); 02107 break; 02108 case FIELD_TYPE_TIMESTAMP: 02109 /* We should replace old TIMESTAMP fields with their newer analogs */ 02110 if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) 02111 { 02112 if (!*timestamps) 02113 { 02114 sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; 02115 (*timestamps_with_niladic)++; 02116 } 02117 else 02118 sql_field->unireg_check= Field::NONE; 02119 } 02120 else if (sql_field->unireg_check != Field::NONE) 02121 (*timestamps_with_niladic)++; 02122 02123 (*timestamps)++; 02124 /* fall-through */ 02125 default: 02126 sql_field->pack_flag=(FIELDFLAG_NUMBER | 02127 (sql_field->flags & UNSIGNED_FLAG ? 0 : 02128 FIELDFLAG_DECIMAL) | 02129 (sql_field->flags & ZEROFILL_FLAG ? 02130 FIELDFLAG_ZEROFILL : 0) | 02131 f_settype((uint) sql_field->sql_type) | 02132 (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); 02133 break; 02134 } 02135 if (!(sql_field->flags & NOT_NULL_FLAG)) 02136 sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL; 02137 if (sql_field->flags & NO_DEFAULT_VALUE_FLAG) 02138 sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; 02139 DBUG_RETURN(0); 02140 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int prepare_for_repair | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| HA_CHECK_OPT * | check_opt | |||
| ) | [static] |
Definition at line 3857 of file sql_table.cc.
References handler::bas_ext(), close_cached_table(), closefrm(), create_table_def_key(), current_pid, DBUG_ENTER, DBUG_RETURN, error, FALSE, st_table::file, FN_REFLEN, from, get_table_share(), key, key_length, lock_and_wait_for_table_name(), LOCK_open, MAX_DBKEY_LENGTH, my_rename(), my_snprintf(), my_stat(), MY_STAT, MY_WME, MYF, mysql_truncate(), st_table_share::normalized_path, NullS, open_table_from_share(), pthread_mutex_lock, pthread_mutex_unlock, RELEASE_NORMAL, release_table_share(), reopen_name_locked_table(), st_table::s, send_check_errmsg(), st_ha_check_opt::sql_flags, LEX_STRING::str, strxmov(), st_table_list::table, st_table_share::tmp_table, TT_USEFRM, and unlock_table_name().
Referenced by mysql_repair_table().
03859 { 03860 int error= 0; 03861 TABLE tmp_table, *table; 03862 TABLE_SHARE *share; 03863 char from[FN_REFLEN],tmp[FN_REFLEN+32]; 03864 const char **ext; 03865 MY_STAT stat_info; 03866 DBUG_ENTER("prepare_for_repair"); 03867 03868 if (!(check_opt->sql_flags & TT_USEFRM)) 03869 DBUG_RETURN(0); 03870 03871 if (!(table= table_list->table)) /* if open_ltable failed */ 03872 { 03873 char key[MAX_DBKEY_LENGTH]; 03874 uint key_length; 03875 03876 key_length= create_table_def_key(thd, key, table_list, 0); 03877 pthread_mutex_lock(&LOCK_open); 03878 if (!(share= (get_table_share(thd, table_list, key, key_length, 0, 03879 &error)))) 03880 { 03881 pthread_mutex_unlock(&LOCK_open); 03882 DBUG_RETURN(0); // Can't open frm file 03883 } 03884 03885 if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE)) 03886 { 03887 release_table_share(share, RELEASE_NORMAL); 03888 pthread_mutex_unlock(&LOCK_open); 03889 DBUG_RETURN(0); // Out of memory 03890 } 03891 table= &tmp_table; 03892 pthread_mutex_unlock(&LOCK_open); 03893 } 03894 /* 03895 REPAIR TABLE ... USE_FRM for temporary tables makes little sense. 03896 */ 03897 if (table->s->tmp_table) 03898 { 03899 error= send_check_errmsg(thd, table_list, "repair", 03900 "Cannot repair temporary table from .frm file"); 03901 goto end; 03902 } 03903 03904 /* 03905 User gave us USE_FRM which means that the header in the index file is 03906 trashed. 03907 In this case we will try to fix the table the following way: 03908 - Rename the data file to a temporary name 03909 - Truncate the table 03910 - Replace the new data file with the old one 03911 - Run a normal repair using the new index file and the old data file 03912 */ 03913 03914 /* 03915 Check if this is a table type that stores index and data separately, 03916 like ISAM or MyISAM 03917 */ 03918 ext= table->file->bas_ext(); 03919 if (!ext[0] || !ext[1]) 03920 goto end; // No data file 03921 03922 // Name of data file 03923 strxmov(from, table->s->normalized_path.str, ext[1], NullS); 03924 if (!my_stat(from, &stat_info, MYF(0))) 03925 goto end; // Can't use USE_FRM flag 03926 03927 my_snprintf(tmp, sizeof(tmp), "%s-%lx_%lx", 03928 from, current_pid, thd->thread_id); 03929 03930 /* If we could open the table, close it */ 03931 if (table_list->table) 03932 { 03933 pthread_mutex_lock(&LOCK_open); 03934 close_cached_table(thd, table); 03935 pthread_mutex_unlock(&LOCK_open); 03936 } 03937 if (lock_and_wait_for_table_name(thd,table_list)) 03938 { 03939 error= -1; 03940 goto end; 03941 } 03942 if (my_rename(from, tmp, MYF(MY_WME))) 03943 { 03944 pthread_mutex_lock(&LOCK_open); 03945 unlock_table_name(thd, table_list); 03946 pthread_mutex_unlock(&LOCK_open); 03947 error= send_check_errmsg(thd, table_list, "repair", 03948 "Failed renaming data file"); 03949 goto end; 03950 } 03951 if (mysql_truncate(thd, table_list, 1)) 03952 { 03953 pthread_mutex_lock(&LOCK_open); 03954 unlock_table_name(thd, table_list); 03955 pthread_mutex_unlock(&LOCK_open); 03956 error= send_check_errmsg(thd, table_list, "repair", 03957 "Failed generating table from .frm file"); 03958 goto end; 03959 } 03960 if (my_rename(tmp, from, MYF(MY_WME))) 03961 { 03962 pthread_mutex_lock(&LOCK_open); 03963 unlock_table_name(thd, table_list); 03964 pthread_mutex_unlock(&LOCK_open); 03965 error= send_check_errmsg(thd, table_list, "repair", 03966 "Failed restoring .MYD file"); 03967 goto end; 03968 } 03969 03970 /* 03971 Now we should be able to open the partially repaired table 03972 to finish the repair in the handler later on. 03973 */ 03974 pthread_mutex_lock(&LOCK_open); 03975 if (reopen_name_locked_table(thd, table_list)) 03976 { 03977 unlock_table_name(thd, table_list); 03978 pthread_mutex_unlock(&LOCK_open); 03979 error= send_check_errmsg(thd, table_list, "repair", 03980 "Failed to open partially repaired table"); 03981 goto end; 03982 } 03983 pthread_mutex_unlock(&LOCK_open); 03984 03985 end: 03986 if (table == &tmp_table) 03987 { 03988 pthread_mutex_lock(&LOCK_open); 03989 closefrm(table, 1); // Free allocated memory 03990 pthread_mutex_unlock(&LOCK_open); 03991 } 03992 DBUG_RETURN(error); 03993 }
Here is the call graph for this function:


