2048
bool mysql_create_like_table(Session* session,
2049
const TableIdentifier &destination_identifier,
2050
TableList* table, TableList* src_table,
2051
message::Table &create_table_proto,
2052
bool is_if_not_exists,
2670
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2671
HA_CREATE_INFO *create_info)
2673
Table *name_lock= 0;
2674
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2675
uint32_t dst_path_length;
2676
char *db= table->db;
2677
char *table_name= table->table_name;
2055
2679
bool res= true;
2056
2680
uint32_t not_used;
2059
2683
By opening source table we guarantee that it exists and no concurrent
2060
2684
DDL operation will mess with it. Later we also take an exclusive
2061
name-lock on target table name, which makes copying of .frm cursor,
2062
call to plugin::StorageEngine::createTable() and binlogging atomic
2063
against concurrent DML and DDL operations on target table.
2064
Thus by holding both these "locks" we ensure that our statement is
2065
properly isolated from all concurrent operations which matter.
2685
name-lock on target table name, which makes copying of .frm file,
2686
call to ha_create_table() and binlogging atomic against concurrent DML
2687
and DDL operations on target table. Thus by holding both these "locks"
2688
we ensure that our statement is properly isolated from all concurrent
2689
operations which matter.
2067
if (session->open_tables_from_list(&src_table, ¬_used))
2691
if (session->open_tables_from_list(&src_table, ¬_used, 0))
2070
TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2694
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2076
2697
Check that destination tables does not exist. Note that its name
2077
2698
was already checked when it was added to the table list.
2079
For temporary tables we don't aim to grab locks.
2081
bool table_exists= false;
2082
if (destination_identifier.isTmp())
2084
if (session->find_temporary_table(destination_identifier))
2090
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
src_identifier, is_engine_set);
2092
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2094
(void) session->rm_temporary_table(destination_identifier, true);
2096
else if (not session->open_temporary_table(destination_identifier))
2098
// We created, but we can't open... also, a hack.
2099
(void) session->rm_temporary_table(destination_identifier, true);
2107
else // Standard table which will require locks.
2109
Table *name_lock= 0;
2111
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2115
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2116
session->unlink_open_table(name_lock);
2126
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2130
else // Otherwise we create the table
2134
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
src_identifier, is_engine_set);
2139
// So we blew the creation of the table, and we scramble to clean up
2140
// anything that might have been created (read... it is a hack)
2141
if (not was_created)
2143
plugin::StorageEngine::dropTable(*session, destination_identifier);
2700
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2702
if (session->find_temporary_table(db, table_name))
2704
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2705
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2709
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2713
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2714
db, table_name, false);
2715
if (table_proto_exists(dst_path)==EEXIST)
2720
Create a new table by copying from source table
2722
Altough exclusive name-lock on target table protects us from concurrent
2723
DML and DDL operations on it we still want to wrap .FRM creation and call
2724
to ha_create_table() in critical section protected by LOCK_open in order
2725
to provide minimal atomicity against operations which disregard name-locks,
2726
like I_S implementation, for example. This is a temporary and should not
2727
be copied. Instead we should fix our code to always honor name-locks.
2729
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2730
during the call to ha_create_table(). See bug #28614 for more info.
2732
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2733
if (src_table->schema_table)
2735
if (mysql_create_like_schema_frm(session, src_table, dst_path, create_info))
2737
pthread_mutex_unlock(&LOCK_open);
2743
int dfecopyr= copy_table_proto_file(src_path, dst_path);
2747
if (my_errno == ENOENT)
2748
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2750
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2751
pthread_mutex_unlock(&LOCK_open);
2757
As mysql_truncate don't work on a new table at this stage of
2758
creation, instead create the table directly (for both normal
2759
and temporary tables).
2762
err= ha_create_table(session, dst_path, db, table_name, create_info, 1);
2763
pthread_mutex_unlock(&LOCK_open);
2765
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2767
if (err || !open_temporary_table(session, dst_path, db, table_name, 1,
2770
(void) rm_temporary_table(create_info->db_type,
2772
goto err; /* purecov: inspected */
2777
(void) quick_rm_table(create_info->db_type, db,
2778
table_name, false); /* purecov: inspected */
2779
goto err; /* purecov: inspected */
2783
We have to write the query before we unlock the tables.
2787
Since temporary tables are not replicated under row-based
2788
replication, CREATE TABLE ... LIKE ... needs special
2789
treatement. We have four cases to consider, according to the
2790
following decision table:
2792
==== ========= ========= ==============================
2793
Case Target Source Write to binary log
2794
==== ========= ========= ==============================
2795
1 normal normal Original statement
2796
2 normal temporary Generated statement
2797
3 temporary normal Nothing
2798
4 temporary temporary Nothing
2799
==== ========= ========= ==============================
2801
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2803
if (src_table->table->s->tmp_table) // Case 2
2806
String query(buf, sizeof(buf), system_charset_info);
2807
query.length(0); // Have to zero it since constructor doesn't
2811
Here we open the destination table, on which we already have
2812
name-lock. This is needed for store_create_info() to work.
2813
The table will be closed by unlink_open_table() at the end
2816
table->table= name_lock;
2817
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2818
if (session->reopen_name_locked_table(table, false))
2820
pthread_mutex_unlock(&LOCK_open);
2823
pthread_mutex_unlock(&LOCK_open);
2825
int result= store_create_info(table, &query, create_info);
2827
assert(result == 0); // store_create_info() always return 0
2828
write_bin_log(session, true, query.ptr(), query.length());
2831
write_bin_log(session, true, session->query, session->query_length);
2839
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2841
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2842
snprintf(warn_buff, sizeof(warn_buff),
2843
ER(ER_TABLE_EXISTS_ERROR), table_name);
2844
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2845
ER_TABLE_EXISTS_ERROR,warn_buff);
2849
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2854
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2855
session->unlink_open_table(name_lock);
2856
pthread_mutex_unlock(&LOCK_open);
2862
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2864
thr_lock_type lock_type = TL_READ_NO_INSERT;
2866
return(mysql_admin_table(session, tables, check_opt,
2867
"analyze", lock_type, 1, 0, 0, 0,
2868
&handler::ha_analyze));
2872
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2874
thr_lock_type lock_type = TL_READ_NO_INSERT;
2876
return(mysql_admin_table(session, tables, check_opt,
2878
0, 0, HA_OPEN_FOR_REPAIR, 0,
2879
&handler::ha_check));
2883
/* table_list should contain just one table */
2885
mysql_discard_or_import_tablespace(Session *session,
2886
TableList *table_list,
2887
enum tablespace_op_type tablespace_op)
2894
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
2898
session->set_proc_info("discard_or_import_tablespace");
2900
discard= test(tablespace_op == DISCARD_TABLESPACE);
2903
We set this flag so that ha_innobase::open and ::external_lock() do
2904
not complain when we lock the table
2906
session->tablespace_op= true;
2907
if (!(table= session->open_ltable(table_list, TL_WRITE)))
2909
session->tablespace_op= false;
2913
error= table->file->ha_discard_or_import_tablespace(discard);
2915
session->set_proc_info("end");
2920
/* The ALTER Table is always in its own transaction */
2921
error = ha_autocommit_or_rollback(session, 0);
2922
if (! session->endActiveTransaction())
2926
write_bin_log(session, false, session->query, session->query_length);
2929
ha_autocommit_or_rollback(session, error);
2930
session->tablespace_op=false;
2938
table->file->print_error(error, MYF(0));
2944
Copy all changes detected by parser to the HA_ALTER_FLAGS
2947
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
2949
uint32_t flags= alter_info->flags;
2951
if (ALTER_ADD_COLUMN & flags)
2952
alter_flags->set(HA_ADD_COLUMN);
2953
if (ALTER_DROP_COLUMN & flags)
2954
alter_flags->set(HA_DROP_COLUMN);
2955
if (ALTER_RENAME & flags)
2956
alter_flags->set(HA_RENAME_TABLE);
2957
if (ALTER_CHANGE_COLUMN & flags)
2958
alter_flags->set(HA_CHANGE_COLUMN);
2959
if (ALTER_COLUMN_DEFAULT & flags)
2960
alter_flags->set(HA_COLUMN_DEFAULT_VALUE);
2961
if (ALTER_COLUMN_STORAGE & flags)
2962
alter_flags->set(HA_COLUMN_STORAGE);
2963
if (ALTER_COLUMN_FORMAT & flags)
2964
alter_flags->set(HA_COLUMN_FORMAT);
2965
if (ALTER_COLUMN_ORDER & flags)
2966
alter_flags->set(HA_ALTER_COLUMN_ORDER);
2967
if (ALTER_STORAGE & flags)
2968
alter_flags->set(HA_ALTER_STORAGE);
2969
if (ALTER_ROW_FORMAT & flags)
2970
alter_flags->set(HA_ALTER_ROW_FORMAT);
2971
if (ALTER_RECREATE & flags)
2972
alter_flags->set(HA_RECREATE);
2973
if (ALTER_FOREIGN_KEY & flags)
2974
alter_flags->set(HA_ALTER_FOREIGN_KEY);
2979
Manages enabling/disabling of indexes for ALTER Table
2982
alter_table_manage_keys()
2984
indexes_were_disabled Whether the indexes of the from table
2986
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
2994
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
2995
enum enum_enable_or_disable keys_onoff)
2998
switch (keys_onoff) {
3000
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3003
if (!indexes_were_disabled)
3005
/* fall-through: disabled indexes */
3007
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3010
if (error == HA_ERR_WRONG_COMMAND)
3012
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3013
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3014
table->s->table_name.str);
3017
table->file->print_error(error, MYF(0));
3023
create_temporary_table(Session *session,
3027
HA_CREATE_INFO *create_info,
3028
Alter_info *alter_info,
3032
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3033
StorageEngine *old_db_type, *new_db_type;
3034
old_db_type= table->s->db_type();
3035
new_db_type= create_info->db_type;
3037
Handling of symlinked tables:
3039
Create new data file and index file on the same disk as the
3040
old data and index files.
3042
Rename new data file over old data file and new index file over
3044
Symlinks are not changed.
3047
Create new data file and index file on the same disk as the
3048
old data and index files. Create also symlinks to point at
3051
At end, rename intermediate tables, and symlinks to intermediate
3052
table, to final table name.
3053
Remove old table and old symlinks
3055
If rename is made to another database:
3056
Create new tables in new database.
3058
Remove old table and symlinks.
3060
if (db_changed) // Ignore symlink if db changed
3062
if (create_info->index_file_name)
3064
/* Fix index_file_name to have 'tmp_name' as basename */
3065
strcpy(index_file, tmp_name);
3066
create_info->index_file_name=fn_same(index_file,
3067
create_info->index_file_name,
3070
if (create_info->data_file_name)
3072
/* Fix data_file_name to have 'tmp_name' as basename */
3073
strcpy(data_file, tmp_name);
3074
create_info->data_file_name=fn_same(data_file,
3075
create_info->data_file_name,
3080
create_info->data_file_name=create_info->index_file_name=0;
3083
Create a table with a temporary name.
3084
We don't log the statement, it will be logged later.
3086
drizzled::message::Table table_proto;
3087
table_proto.set_name(tmp_name);
3088
table_proto.set_type(drizzled::message::Table::TEMPORARY);
3090
drizzled::message::Table::StorageEngine *protoengine;
3091
protoengine= table_proto.mutable_engine();
3092
protoengine->set_name(new_db_type->getName());
3094
error= mysql_create_table(session, new_db, tmp_name,
3095
create_info, &table_proto, alter_info, 1, 0);
3102
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3104
This function transforms parse output of ALTER Table - lists of
3105
columns and keys to add, drop or modify into, essentially,
3106
CREATE TABLE definition - a list of columns and keys of the new
3107
table. While doing so, it also performs some (bug not all)
3110
This function is invoked when we know that we're going to
3111
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3112
is not possible, perhaps because the ALTER statement contains
3113
instructions that require change in table data, not only in
3114
table definition or indexes.
3116
@param[in,out] session thread handle. Used as a memory pool
3117
and source of environment information.
3118
@param[in] table the source table, open and locked
3119
Used as an interface to the storage engine
3120
to acquire additional information about
3122
@param[in,out] create_info A blob with CREATE/ALTER Table
3124
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3125
Originally create_info was used only in
3126
CREATE TABLE and alter_info only in ALTER Table.
3127
But since ALTER might end-up doing CREATE,
3128
this distinction is gone and we just carry
3129
around two structures.
3132
Fills various create_info members based on information retrieved
3133
from the storage engine.
3134
Sets create_info->varchar if the table has a VARCHAR column.
3135
Prepares alter_info->create_list and alter_info->key_list with
3136
columns and keys of the new table.
3137
@retval true error, out of memory or a semantical error in ALTER
3139
@retval false success
3143
mysql_prepare_alter_table(Session *session, Table *table,
3144
HA_CREATE_INFO *create_info,
3145
Alter_info *alter_info)
3147
/* New column definitions are added here */
3148
List<CreateField> new_create_list;
3149
/* New key definitions are added here */
3150
List<Key> new_key_list;
3151
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3152
List_iterator<CreateField> def_it(alter_info->create_list);
3153
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3154
List_iterator<Key> key_it(alter_info->key_list);
3155
List_iterator<CreateField> find_it(new_create_list);
3156
List_iterator<CreateField> field_it(new_create_list);
3157
List<Key_part_spec> key_parts;
3158
uint32_t db_create_options= (table->s->db_create_options
3159
& ~(HA_OPTION_PACK_RECORD));
3160
uint32_t used_fields= create_info->used_fields;
3161
KEY *key_info=table->key_info;
3165
create_info->varchar= false;
3166
/* Let new create options override the old ones */
3167
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3168
create_info->min_rows= table->s->min_rows;
3169
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3170
create_info->max_rows= table->s->max_rows;
3171
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3172
create_info->avg_row_length= table->s->avg_row_length;
3173
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3174
create_info->block_size= table->s->block_size;
3175
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3176
create_info->default_table_charset= table->s->table_charset;
3177
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3179
/* Table has an autoincrement, copy value to new table */
3180
table->file->info(HA_STATUS_AUTO);
3181
create_info->auto_increment_value= table->file->stats.auto_increment_value;
3183
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
3184
create_info->key_block_size= table->s->key_block_size;
3186
table->restoreRecordAsDefault(); // Empty record for DEFAULT
3190
First collect all fields from table which isn't in drop_list
3192
Field **f_ptr,*field;
3193
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
3195
/* Check if field should be dropped */
3198
while ((drop=drop_it++))
3200
if (drop->type == Alter_drop::COLUMN &&
3201
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
3203
/* Reset auto_increment value if it was dropped */
3204
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
3205
!(used_fields & HA_CREATE_USED_AUTO))
3207
create_info->auto_increment_value=0;
3208
create_info->used_fields|=HA_CREATE_USED_AUTO;
3219
/* Mark that we will read the field */
3220
field->setReadSet();
3222
/* Check if field is changed */
3224
while ((def=def_it++))
3227
!my_strcasecmp(system_charset_info,field->field_name, def->change))
3231
{ // Field is changed
3235
new_create_list.push_back(def);
3242
This field was not dropped and not changed, add it to the list
3245
def= new CreateField(field, field);
3246
new_create_list.push_back(def);
3247
alter_it.rewind(); // Change default if ALTER
3248
Alter_column *alter;
3249
while ((alter=alter_it++))
3251
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
3256
if (def->sql_type == DRIZZLE_TYPE_BLOB)
3258
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
3261
if ((def->def=alter->def)) // Use new default
3262
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
3264
def->flags|= NO_DEFAULT_VALUE_FLAG;
3270
while ((def=def_it++)) // Add new columns
3272
if (def->change && ! def->field)
3274
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
3278
Check that the DATE/DATETIME not null field we are going to add is
3279
either has a default value or the '0000-00-00' is allowed by the
3281
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
3282
flag to allow ALTER Table only if the table to be altered is empty.
3284
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
3285
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
3286
!alter_info->datetime_field &&
3287
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
3288
session->variables.sql_mode & MODE_NO_ZERO_DATE)
3290
alter_info->datetime_field= def;
3291
alter_info->error_if_not_empty= true;
3294
new_create_list.push_back(def);
3295
else if (def->after == first_keyword)
3296
new_create_list.push_front(def);
3301
while ((find=find_it++)) // Add new columns
3303
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
3308
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
3311
find_it.after(def); // Put element after this
3313
XXX: hack for Bug#28427.
3314
If column order has changed, force OFFLINE ALTER Table
3315
without querying engine capabilities. If we ever have an
3316
engine that supports online ALTER Table CHANGE COLUMN
3317
<name> AFTER <name1> (Falcon?), this fix will effectively
3318
disable the capability.
3319
TODO: detect the situation in compare_tables, behave based
3320
on engine capabilities.
3322
if (alter_info->build_method == HA_BUILD_ONLINE)
3324
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
3327
alter_info->build_method= HA_BUILD_OFFLINE;
3330
if (alter_info->alter_list.elements)
3332
my_error(ER_BAD_FIELD_ERROR, MYF(0),
3333
alter_info->alter_list.head()->name, table->s->table_name.str);
3336
if (!new_create_list.elements)
3338
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
3344
Collect all keys which isn't in drop list. Add only those
3345
for which some fields exists.
3348
for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
3350
char *key_name= key_info->name;
3353
while ((drop=drop_it++))
3355
if (drop->type == Alter_drop::KEY &&
3356
!my_strcasecmp(system_charset_info,key_name, drop->name))
3365
KEY_PART_INFO *key_part= key_info->key_part;
3367
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
3369
if (!key_part->field)
3370
continue; // Wrong field (from UNIREG)
3371
const char *key_part_name=key_part->field->field_name;
3372
CreateField *cfield;
3374
while ((cfield=field_it++))
3378
if (!my_strcasecmp(system_charset_info, key_part_name,
3382
else if (!my_strcasecmp(system_charset_info,
3383
key_part_name, cfield->field_name))
3387
continue; // Field is removed
3388
uint32_t key_part_length=key_part->length;
3389
if (cfield->field) // Not new field
3392
If the field can't have only a part used in a key according to its
3393
new type, or should not be used partially according to its
3394
previous type, or the field length is less than the key part
3395
length, unset the key part length.
3397
We also unset the key part length if it is the same as the
3398
old field's length, so the whole new field will be used.
3400
BLOBs may have cfield->length == 0, which is why we test it before
3401
checking whether cfield->length < key_part_length (in chars).
3403
if (!Field::type_can_have_key_part(cfield->field->type()) ||
3404
!Field::type_can_have_key_part(cfield->sql_type) ||
3405
(cfield->field->field_length == key_part_length &&
3406
!f_is_blob(key_part->key_type)) ||
3407
(cfield->length && (cfield->length < key_part_length /
3408
key_part->field->charset()->mbmaxlen)))
3409
key_part_length= 0; // Use whole field
3411
key_part_length /= key_part->field->charset()->mbmaxlen;
3412
key_parts.push_back(new Key_part_spec(cfield->field_name,
3413
strlen(cfield->field_name),
3416
if (key_parts.elements)
3418
KEY_CREATE_INFO key_create_info;
3420
enum Key::Keytype key_type;
3421
memset(&key_create_info, 0, sizeof(key_create_info));
3423
key_create_info.algorithm= key_info->algorithm;
3424
if (key_info->flags & HA_USES_BLOCK_SIZE)
3425
key_create_info.block_size= key_info->block_size;
3426
if (key_info->flags & HA_USES_COMMENT)
3427
key_create_info.comment= key_info->comment;
3429
if (key_info->flags & HA_NOSAME)
3431
if (is_primary_key_name(key_name))
3432
key_type= Key::PRIMARY;
3434
key_type= Key::UNIQUE;
3437
key_type= Key::MULTIPLE;
3439
key= new Key(key_type, key_name, strlen(key_name),
3441
test(key_info->flags & HA_GENERATED_KEY),
3443
new_key_list.push_back(key);
3448
while ((key=key_it++)) // Add new keys
3450
if (key->type == Key::FOREIGN_KEY &&
3451
((Foreign_key *)key)->validate(new_create_list))
3453
if (key->type != Key::FOREIGN_KEY)
3454
new_key_list.push_back(key);
3455
if (key->name.str && is_primary_key_name(key->name.str))
3457
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3463
if (alter_info->drop_list.elements)
3465
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3466
alter_info->drop_list.head()->name);
3469
if (alter_info->alter_list.elements)
3471
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3472
alter_info->alter_list.head()->name);
3476
if (!create_info->comment.str)
3478
create_info->comment.str= table->s->comment.str;
3479
create_info->comment.length= table->s->comment.length;
3482
table->file->update_create_info(create_info);
3483
if ((create_info->table_options &
3484
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
3485
(used_fields & HA_CREATE_USED_PACK_KEYS))
3486
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
3487
if (create_info->table_options &
3488
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
3489
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
3490
if (create_info->table_options &
3491
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
3492
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
3493
HA_OPTION_NO_DELAY_KEY_WRITE);
3494
create_info->table_options|= db_create_options;
3496
if (table->s->tmp_table)
3497
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
3500
alter_info->create_list.swap(new_create_list);
3501
alter_info->key_list.swap(new_key_list);
3512
session Thread handle
3513
new_db If there is a RENAME clause
3514
new_name If there is a RENAME clause
3515
create_info Information from the parsing phase about new
3517
table_list The table to change.
3518
alter_info Lists of fields, keys to be changed, added
3520
order_num How many order_st BY fields has been specified.
3521
order List of fields to order_st BY.
3522
ignore Whether we have ALTER IGNORE Table
3525
This is a veery long function and is everything but the kitchen sink :)
3526
It is used to alter a table and not only by ALTER Table but also
3527
CREATE|DROP INDEX are mapped on this function.
3529
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
3530
or both, then this function short cuts its operation by renaming
3531
the table and/or enabling/disabling the keys. In this case, the FRM is
3532
not changed, directly by mysql_alter_table. However, if there is a
3533
RENAME + change of a field, or an index, the short cut is not used.
3534
See how `create_list` is used to generate the new FRM regarding the
3535
structure of the fields. The same is done for the indices of the table.
3537
Important is the fact, that this function tries to do as little work as
3538
possible, by finding out whether a intermediate table is needed to copy
3539
data into and when finishing the altering to use it as the original table.
3540
For this reason the function compare_tables() is called, which decides
3541
based on all kind of data how similar are the new and the original
3549
bool mysql_alter_table(Session *session, char *new_db, char *new_name,
3550
HA_CREATE_INFO *create_info,
3551
TableList *table_list,
3552
Alter_info *alter_info,
3553
uint32_t order_num, order_st *order, bool ignore)
3555
Table *table, *new_table=0, *name_lock= 0;;
3556
string new_name_str;
3558
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
3559
char new_alias_buff[FN_REFLEN], *table_name, *db;
3560
const char *new_alias;
3561
char path[FN_REFLEN];
3562
ha_rows copied= 0,deleted= 0;
3563
StorageEngine *old_db_type, *new_db_type, *save_old_db_type;
3565
new_name_buff[0]= '\0';
3567
if (table_list && table_list->schema_table)
3569
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
3574
Assign variables table_name, new_name, db, new_db, path
3575
to simplify further comparisons: we want to see if it's a RENAME
3576
later just by comparing the pointers, avoiding the need for strcmp.
3578
session->set_proc_info("init");
3579
table_name= table_list->table_name;
3581
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
3583
build_table_filename(path, sizeof(path), db, table_name, false);
3585
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3586
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3587
/* Conditionally writes to binlog. */
3588
return(mysql_discard_or_import_tablespace(session,table_list,
3589
alter_info->tablespace_op));
3591
oss << drizzle_data_home << "/" << db << "/" << table_name;
3593
(void) unpack_filename(new_name_buff, oss.str().c_str());
3595
If this is just a rename of a view, short cut to the
3596
following scenario: 1) lock LOCK_open 2) do a RENAME
3597
2) unlock LOCK_open.
3598
This is a copy-paste added to make sure
3599
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
3600
as an independent branch in mysql_execute_command. The need
3601
for a copy-paste arose because the main code flow of ALTER Table
3602
... RENAME tries to use open_ltable, which does not work for views
3603
(open_ltable was never modified to merge table lists of child tables
3604
into the main table list, like open_tables does).
3605
This code is wrong and will be removed, please do not copy.
3608
if (!(table= session->open_ltable(table_list, TL_WRITE_ALLOW_READ)))
3610
table->use_all_columns();
3612
/* Check that we are not trying to rename to an existing table */
3615
strcpy(new_name_buff, new_name);
3616
strcpy(new_alias_buff, new_name);
3617
new_alias= new_alias_buff;
3619
my_casedn_str(files_charset_info, new_name_buff);
3620
new_alias= new_name; // Create lower case table name
3621
my_casedn_str(files_charset_info, new_name);
3624
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3627
Source and destination table names are equal: make later check
3630
new_alias= new_name= table_name;
3634
if (table->s->tmp_table != NO_TMP_TABLE)
3636
if (session->find_temporary_table(new_db, new_name_buff))
3638
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3644
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3649
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3653
build_table_filename(new_name_buff, sizeof(new_name_buff),
3654
new_db, new_name_buff, false);
3655
if (table_proto_exists(new_name_buff)==EEXIST)
3657
/* Table will be closed by Session::executeCommand() */
3658
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3666
new_alias= table_name;
3667
new_name= table_name;
3670
old_db_type= table->s->db_type();
3671
if (!create_info->db_type)
3673
create_info->db_type= old_db_type;
3676
if(table->s->tmp_table != NO_TMP_TABLE)
3677
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3679
if (check_engine(session, new_name, create_info))
3681
new_db_type= create_info->db_type;
3683
if (new_db_type != old_db_type &&
3684
!table->file->can_switch_engines())
3687
my_error(ER_ROW_IS_REFERENCED, MYF(0));
3691
if (create_info->row_type == ROW_TYPE_NOT_USED)
3692
create_info->row_type= table->s->row_type;
3694
if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
3695
new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
3697
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
3701
session->set_proc_info("setup");
3702
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
3703
!table->s->tmp_table) // no need to touch frm
3705
switch (alter_info->keys_onoff) {
3710
wait_while_table_is_used() ensures that table being altered is
3711
opened only by this thread and that Table::TableShare::version
3712
of Table object corresponding to this table is 0.
3713
The latter guarantees that no DML statement will open this table
3714
until ALTER Table finishes (i.e. until close_thread_tables())
3715
while the fact that the table is still open gives us protection
3716
from concurrent DDL statements.
3718
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3719
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3720
pthread_mutex_unlock(&LOCK_open);
3721
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3722
/* COND_refresh will be signaled in close_thread_tables() */
3725
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3726
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3727
pthread_mutex_unlock(&LOCK_open);
3728
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3729
/* COND_refresh will be signaled in close_thread_tables() */
3736
if (error == HA_ERR_WRONG_COMMAND)
3739
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3740
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3744
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
3746
Unlike to the above case close_cached_table() below will remove ALL
3747
instances of Table from table cache (it will also remove table lock
3748
held by this thread). So to make actual table renaming and writing
3749
to binlog atomic we have to put them into the same critical section
3750
protected by LOCK_open mutex. This also removes gap for races between
3751
access() and mysql_rename_table() calls.
3754
if (!error && (new_name != table_name || new_db != db))
3756
session->set_proc_info("rename");
3758
Then do a 'simple' rename of the table. First we need to close all
3759
instances of 'source' table.
3761
session->close_cached_table(table);
3763
Then, we want check once again that target table does not exist.
3764
Actually the order of these two steps does not matter since
3765
earlier we took name-lock on the target table, so we do them
3766
in this particular order only to be consistent with 5.0, in which
3767
we don't take this name-lock and where this order really matters.
3768
TODO: Investigate if we need this access() check at all.
3770
if (table_proto_exists(new_name)==EEXIST)
3772
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
3777
*fn_ext(new_name)=0;
3778
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3782
mysql_rename_table(old_db_type, new_db, new_alias, db,
3789
if (error == HA_ERR_WRONG_COMMAND)
3792
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3793
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3799
write_bin_log(session, true, session->query, session->query_length);
3804
table->file->print_error(error, MYF(0));
2153
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2154
3808
session->unlink_open_table(name_lock);
2160
if (is_if_not_exists)
3809
pthread_mutex_unlock(&LOCK_open);
3810
table_list->table= NULL; // For query cache
3814
/* We have to do full alter table. */
3817
If the old table had partitions and we are doing ALTER Table ...
3818
engine= <new_engine>, the new table must preserve the original
3819
partitioning. That means that the new engine is still the
3820
partitioning engine, not the engine specified in the parser.
3821
This is discovered in prep_alter_part_table, which in such case
3822
updates create_info->db_type.
3823
Now we need to update the stack copy of create_info->db_type,
3824
as otherwise we won't be able to correctly move the files of the
3825
temporary table to the result table files.
3827
new_db_type= create_info->db_type;
3829
if (mysql_prepare_alter_table(session, table, create_info, alter_info))
3832
set_table_default_charset(create_info, db);
3834
alter_info->build_method= HA_BUILD_OFFLINE;
3836
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
3837
(unsigned long)current_pid, session->thread_id);
3838
/* Safety fix for innodb */
3839
my_casedn_str(files_charset_info, tmp_name);
3842
/* Create a temporary table with the new format */
3843
if ((error= create_temporary_table(session, table, new_db, tmp_name,
3844
create_info, alter_info,
3845
!strcmp(db, new_db))))
3850
/* Open the table so we need to copy the data to it. */
3851
if (table->s->tmp_table)
3855
tbl.alias= tmp_name;
3856
tbl.table_name= tmp_name;
3858
/* Table is in session->temporary_tables */
3859
new_table= session->open_table(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3863
char tmp_path[FN_REFLEN];
3864
/* table is a normal table: Create temporary table in same directory */
3865
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
3866
/* Open our intermediate table */
3867
new_table= open_temporary_table(session, tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3870
if (new_table == NULL)
3873
/* Copy the data if necessary. */
3874
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
3875
session->cuted_fields=0L;
3876
session->set_proc_info("copy to tmp table");
3881
/* We don't want update TIMESTAMP fields during ALTER Table. */
3882
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3883
new_table->next_number_field=new_table->found_next_number_field;
3884
error= copy_data_between_tables(table, new_table,
3885
alter_info->create_list, ignore,
3886
order_num, order, &copied, &deleted,
3887
alter_info->keys_onoff,
3888
alter_info->error_if_not_empty);
3890
/* We must not ignore bad input! */;
3891
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3893
if (table->s->tmp_table != NO_TMP_TABLE)
3895
/* We changed a temporary table */
3898
/* Close lock if this is a transactional table */
3901
mysql_unlock_tables(session, session->lock);
3904
/* Remove link to old table and rename the new one */
3905
session->close_temporary_table(table, true, true);
3906
/* Should pass the 'new_name' as we store table name in the cache */
3907
if (rename_temporary_table(new_table, new_db, new_name))
3915
Close the intermediate table that will be the new table.
3916
Note that MERGE tables do not have their children attached here.
3918
intern_close_table(new_table);
3921
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3924
quick_rm_table(new_db_type, new_db, tmp_name, true);
3925
pthread_mutex_unlock(&LOCK_open);
3930
Data is copied. Now we:
3931
1) Wait until all other threads close old version of table.
3932
2) Close instances of table open by this thread and replace them
3933
with exclusive name-locks.
3934
3) Rename the old table to a temp name, rename the new one to the
3936
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
3937
we reopen new version of table.
3938
5) Write statement to the binary log.
3939
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
3940
remove name-locks from list of open tables and table cache.
3941
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
3942
call to remove name-locks from table cache and list of open table.
3945
session->set_proc_info("rename result table");
3946
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
3947
(unsigned long)current_pid, session->thread_id);
3948
my_casedn_str(files_charset_info, old_name);
3950
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3951
session->close_data_files_and_morph_locks(db, table_name);
3954
save_old_db_type= old_db_type;
3957
This leads to the storage engine (SE) not being notified for renames in
3958
mysql_rename_table(), because we just juggle with the FRM and nothing
3959
more. If we have an intermediate table, then we notify the SE that
3960
it should become the actual table. Later, we will recycle the old table.
3961
However, in case of ALTER Table RENAME there might be no intermediate
3962
table. This is when the old and new tables are compatible, according to
3963
compare_table(). Then, we need one additional call to
3964
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
3965
actual rename in the SE and the FRM is not touched. Note that, if the
3966
table is renamed and the SE is also changed, then an intermediate table
3967
is created and the additional call will not take place.
3969
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
3973
quick_rm_table(new_db_type, new_db, tmp_name, true);
3975
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
3976
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
3978
/* Try to get everything back. */
3980
quick_rm_table(new_db_type, new_db, new_alias, false);
3981
quick_rm_table(new_db_type, new_db, tmp_name, true);
3982
mysql_rename_table(old_db_type, db, old_name, db, table_name,
3988
/* This shouldn't happen. But let us play it safe. */
3989
goto err_with_placeholders;
3992
quick_rm_table(old_db_type, db, old_name, true);
3994
pthread_mutex_unlock(&LOCK_open);
3996
session->set_proc_info("end");
3998
write_bin_log(session, true, session->query, session->query_length);
4000
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
4003
For the alter table to be properly flushed to the logs, we
4004
have to open the new table. If not, we get a problem on server
4005
shutdown. But we do not need to attach MERGE children.
4007
char table_path[FN_REFLEN];
4009
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
4010
t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
4013
intern_close_table(t_table);
4017
errmsg_printf(ERRMSG_LVL_WARN,
4018
_("Could not open table %s.%s after rename\n"),
4020
ha_flush_logs(old_db_type);
4022
table_list->table=0; // For query cache
4026
* Field::store() may have called my_error(). If this is
4027
* the case, we must not send an ok packet, since
4028
* Diagnostics_area::is_set() will fail an assert.
4030
if (! session->is_error())
4032
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
4033
(ulong) (copied + deleted), (ulong) deleted,
4034
(ulong) session->cuted_fields);
4035
session->my_ok(copied + deleted, 0L, tmp_name);
4036
session->some_tables_deleted=0;
4041
/* my_error() was called. Return true (which means error...) */
4048
/* close_temporary_table() frees the new_table pointer. */
4049
session->close_temporary_table(new_table, true, true);
4052
quick_rm_table(new_db_type, new_db, tmp_name, true);
4056
No default value was provided for a DATE/DATETIME field, the
4057
current sql_mode doesn't allow the '0000-00-00' value and
4058
the table to be altered isn't empty.
4061
if (alter_info->error_if_not_empty && session->row_count)
4063
const char *f_val= 0;
4064
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
4065
switch (alter_info->datetime_field->sql_type)
4067
case DRIZZLE_TYPE_DATE:
4068
f_val= "0000-00-00";
4069
t_type= DRIZZLE_TIMESTAMP_DATE;
4071
case DRIZZLE_TYPE_DATETIME:
4072
f_val= "0000-00-00 00:00:00";
4073
t_type= DRIZZLE_TIMESTAMP_DATETIME;
4076
/* Shouldn't get here. */
4079
bool save_abort_on_warning= session->abort_on_warning;
4080
session->abort_on_warning= true;
4081
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
4082
f_val, strlength(f_val), t_type,
4083
alter_info->datetime_field->field_name);
4084
session->abort_on_warning= save_abort_on_warning;
4088
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
4089
session->unlink_open_table(name_lock);
4090
pthread_mutex_unlock(&LOCK_open);
4094
err_with_placeholders:
4096
An error happened while we were holding exclusive name-lock on table
4097
being altered. To be safe under LOCK TABLES we should remove placeholders
4098
from list of open tables list and table cache.
4100
session->unlink_open_table(table);
4102
session->unlink_open_table(name_lock);
4103
pthread_mutex_unlock(&LOCK_open);
4106
/* mysql_alter_table */
4109
copy_data_between_tables(Table *from,Table *to,
4110
List<CreateField> &create,
4112
uint32_t order_num, order_st *order,
4115
enum enum_enable_or_disable keys_onoff,
4116
bool error_if_not_empty)
4119
CopyField *copy,*copy_end;
4120
ulong found_count,delete_count;
4121
Session *session= current_session;
4123
SORT_FIELD *sortorder;
4127
List<Item> all_fields;
4128
ha_rows examined_rows;
4129
bool auto_increment_field_copied= 0;
4130
ulong save_sql_mode;
4131
uint64_t prev_insert_id;
4134
Turn off recovery logging since rollback of an alter table is to
4135
delete the new table so there is no need to log the changes to it.
4137
This needs to be done before external_lock
4139
error= ha_enable_transaction(session, false);
4143
if (!(copy= new CopyField[to->s->fields]))
4144
return -1; /* purecov: inspected */
4146
if (to->file->ha_external_lock(session, F_WRLCK))
4149
/* We need external lock before we can disable/enable keys */
4150
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
4152
/* We can abort alter table for any table type */
4153
session->abort_on_warning= !ignore;
4155
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
4156
to->file->ha_start_bulk_insert(from->file->stats.records);
4158
save_sql_mode= session->variables.sql_mode;
4160
List_iterator<CreateField> it(create);
4163
for (Field **ptr=to->field ; *ptr ; ptr++)
4168
if (*ptr == to->next_number_field)
4169
auto_increment_field_copied= true;
4171
(copy_end++)->set(*ptr,def->field,0);
4176
found_count=delete_count=0;
4180
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2162
4182
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
4183
snprintf(warn_buff, sizeof(warn_buff),
2164
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2165
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
ER_TABLE_EXISTS_ERROR,warn_buff);
2171
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2179
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2181
thr_lock_type lock_type = TL_READ_NO_INSERT;
2183
return(mysql_admin_table(session, tables, check_opt,
2184
"analyze", lock_type, true,
2185
&Cursor::ha_analyze));
2189
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2191
thr_lock_type lock_type = TL_READ_NO_INSERT;
2193
return(mysql_admin_table(session, tables, check_opt,
2196
&Cursor::ha_check));
2199
} /* namespace drizzled */
4184
_("order_st BY ignored because there is a user-defined clustered "
4185
"index in the table '%-.192s'"),
4186
from->s->table_name.str);
4187
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
4192
from->sort.io_cache= new IO_CACHE;
4193
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
4195
memset(&tables, 0, sizeof(tables));
4197
tables.alias= tables.table_name= from->s->table_name.str;
4198
tables.db= from->s->db.str;
4201
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
4202
setup_order(session, session->lex->select_lex.ref_pointer_array,
4203
&tables, fields, all_fields, order) ||
4204
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
4205
(from->sort.found_records= filesort(session, from, sortorder, length,
4206
(SQL_SELECT *) 0, HA_POS_ERROR,
4207
1, &examined_rows)) ==
4213
/* Tell handler that we have values for all columns in the to table */
4214
to->use_all_columns();
4215
init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
4217
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
4218
session->row_count= 0;
4219
to->restoreRecordAsDefault(); // Create empty record
4220
while (!(error=info.read_record(&info)))
4222
if (session->killed)
4224
session->send_kill_message();
4228
session->row_count++;
4229
/* Return error if source table isn't empty. */
4230
if (error_if_not_empty)
4235
if (to->next_number_field)
4237
if (auto_increment_field_copied)
4238
to->auto_increment_field_not_null= true;
4240
to->next_number_field->reset();
4243
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
4245
copy_ptr->do_copy(copy_ptr);
4247
prev_insert_id= to->file->next_insert_id;
4248
error=to->file->ha_write_row(to->record[0]);
4249
to->auto_increment_field_not_null= false;
4253
to->file->is_fatal_error(error, HA_CHECK_DUP))
4255
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
4257
uint32_t key_nr= to->file->get_dup_key(error);
4258
if ((int) key_nr >= 0)
4260
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
4262
(to->key_info[0].key_part[0].field->flags &
4263
AUTO_INCREMENT_FLAG))
4264
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
4265
to->file->print_keydup_error(key_nr, err_msg);
4270
to->file->print_error(error,MYF(0));
4273
to->file->restore_auto_increment(prev_insert_id);
4279
end_read_record(&info);
4280
free_io_cache(from);
4281
delete [] copy; // This is never 0
4283
if (to->file->ha_end_bulk_insert() && error <= 0)
4285
to->file->print_error(my_errno,MYF(0));
4288
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
4290
if (ha_enable_transaction(session, true))
4297
Ensure that the new table is saved properly to disk so that we
4300
if (ha_autocommit_or_rollback(session, 0))
4302
if (! session->endActiveTransaction())
4306
session->variables.sql_mode= save_sql_mode;
4307
session->abort_on_warning= 0;
4308
free_io_cache(from);
4309
*copied= found_count;
4310
*deleted=delete_count;
4311
to->file->ha_release_auto_increment();
4312
if (to->file->ha_external_lock(session,F_UNLCK))
4314
return(error > 0 ? -1 : 0);
4319
Recreates tables by calling mysql_alter_table().
4322
mysql_recreate_table()
4323
session Thread handler
4324
tables Tables to recreate
4327
Like mysql_alter_table().
4329
bool mysql_recreate_table(Session *session, TableList *table_list)
4331
HA_CREATE_INFO create_info;
4332
Alter_info alter_info;
4334
assert(!table_list->next_global);
4336
table_list->table has been closed and freed. Do not reference
4337
uninitialized data. open_tables() could fail.
4339
table_list->table= NULL;
4341
memset(&create_info, 0, sizeof(create_info));
4342
create_info.row_type=ROW_TYPE_NOT_USED;
4343
create_info.default_table_charset=default_charset_info;
4344
/* Force alter table to recreate table */
4345
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
4346
return(mysql_alter_table(session, NULL, NULL, &create_info,
4347
table_list, &alter_info, 0,
4348
(order_st *) 0, 0));
4352
bool mysql_checksum_table(Session *session, TableList *tables,
4353
HA_CHECK_OPT *check_opt)
4356
List<Item> field_list;
4358
Protocol *protocol= session->protocol;
4360
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
4361
item->maybe_null= 1;
4362
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
4363
MY_INT64_NUM_DECIMAL_DIGITS));
4364
item->maybe_null= 1;
4365
if (protocol->sendFields(&field_list,
4366
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4369
/* Open one table after the other to keep lock time as short as possible. */
4370
for (table= tables; table; table= table->next_local)
4372
char table_name[NAME_LEN*2+2];
4375
sprintf(table_name,"%s.%s",table->db,table->table_name);
4377
t= table->table= session->open_ltable(table, TL_READ);
4378
session->clear_error(); // these errors shouldn't get client
4380
protocol->prepareForResend();
4381
protocol->store(table_name);
4385
/* Table didn't exist */
4387
session->clear_error();
4391
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
4392
!(check_opt->flags & T_EXTEND))
4393
protocol->store((uint64_t)t->file->checksum());
4394
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
4395
(check_opt->flags & T_QUICK))
4399
/* calculating table's checksum */
4401
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
4403
t->use_all_columns();
4405
if (t->file->ha_rnd_init(1))
4411
ha_checksum row_crc= 0;
4412
int error= t->file->rnd_next(t->record[0]);
4413
if (unlikely(error))
4415
if (error == HA_ERR_RECORD_DELETED)
4419
if (t->s->null_bytes)
4421
/* fix undefined null bits */
4422
t->record[0][t->s->null_bytes-1] |= null_mask;
4423
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
4424
t->record[0][0] |= 1;
4426
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
4429
for (uint32_t i= 0; i < t->s->fields; i++ )
4431
Field *f= t->field[i];
4432
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
4433
(f->type() == DRIZZLE_TYPE_VARCHAR))
4437
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
4440
row_crc= my_checksum(row_crc, f->ptr,
4446
protocol->store((uint64_t)crc);
4447
t->file->ha_rnd_end();
4450
session->clear_error();
4451
session->close_thread_tables();
4452
table->table=0; // For query cache
4454
if (protocol->write())
4462
session->close_thread_tables(); // Shouldn't be needed
4468
static bool check_engine(Session *session, const char *table_name,
4469
HA_CREATE_INFO *create_info)
4471
StorageEngine **new_engine= &create_info->db_type;
4472
StorageEngine *req_engine= *new_engine;
4473
if (!req_engine->is_enabled())
4475
string engine_name= req_engine->getName();
4476
my_error(ER_FEATURE_DISABLED,MYF(0),
4477
engine_name.c_str(), engine_name.c_str());
4482
if (req_engine && req_engine != *new_engine)
4484
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4485
ER_WARN_USING_OTHER_HANDLER,
4486
ER(ER_WARN_USING_OTHER_HANDLER),
4487
ha_resolve_storage_engine_name(*new_engine).c_str(),
4490
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
4491
(*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
4493
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
4495
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4496
ha_resolve_storage_engine_name(*new_engine).c_str(),
4501
*new_engine= myisam_engine;
4503
if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
4504
&& (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
4506
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4507
ha_resolve_storage_engine_name(*new_engine).c_str(),