107
102
assert(select_lex->db);
109
104
/* Chicken/Egg... we need to search for the table, to know if the table exists, so we can build a full identifier from it */
110
message::table::shared_ptr original_table_message;
105
message::Table original_table_message;
112
TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
107
TableIdentifier identifier(first_table->db, first_table->table_name);
113
108
if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
116
identifier.getSQLPath(path);
117
my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
110
my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
121
114
if (not create_info.db_type)
123
116
create_info.db_type=
124
plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
117
plugin::StorageEngine::findByName(*session, original_table_message.engine().name());
126
119
if (not create_info.db_type)
129
identifier.getSQLPath(path);
130
my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
121
my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
136
127
if (not validateCreateTableOption())
139
132
/* ALTER TABLE ends previous transaction */
140
133
if (not session->endActiveTransaction())
143
if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
138
if (not (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
147
if (original_table_message->type() == message::Table::STANDARD )
144
if (original_table_message.type() == message::Table::STANDARD )
149
TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
150
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
151
session->lex->name.str ? session->lex->name.str : first_table->getTableName());
146
TableIdentifier identifier(first_table->db, first_table->table_name);
147
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
148
session->lex->name.str ? session->lex->name.str : first_table->table_name);
153
150
res= alter_table(session,
157
*original_table_message,
154
original_table_message,
158
155
create_table_message,
161
158
select_lex->order_list.elements,
162
(Order *) select_lex->order_list.first,
159
(order_st *) select_lex->order_list.first,
163
160
session->lex->ignore);
167
TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
168
Table *table= session->find_temporary_table(catch22);
164
Table *table= session->find_temporary_table(first_table);
171
TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
172
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
173
session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
174
table->getMutableShare()->getPath());
167
TableIdentifier identifier(first_table->db, first_table->table_name, table->s->getPath());
168
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
169
session->lex->name.str ? session->lex->name.str : first_table->table_name,
170
table->s->getPath());
176
172
res= alter_table(session,
180
*original_table_message,
176
original_table_message,
181
177
create_table_message,
184
180
select_lex->order_list.elements,
185
(Order *) select_lex->order_list.first,
181
(order_st *) select_lex->order_list.first,
186
182
session->lex->ignore);
264
259
table_options= table_message.mutable_options();
266
261
if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
267
create_info->default_table_charset= table->getShare()->table_charset;
262
create_info->default_table_charset= table->s->table_charset;
268
263
if (! (used_fields & HA_CREATE_USED_AUTO) &&
269
264
table->found_next_number_field)
271
266
/* Table has an autoincrement, copy value to new table */
272
267
table->cursor->info(HA_STATUS_AUTO);
273
268
create_info->auto_increment_value= table->cursor->stats.auto_increment_value;
274
if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
275
table_options->set_has_user_set_auto_increment_value(false);
277
270
table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
278
271
CreateField *def;
368
359
if (def->change && ! def->field)
370
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
361
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->getTableName());
374
If we have been given a field which has no default value, and is not null then we need to bail.
365
Check that the DATE/DATETIME not null field we are going to add is
366
either has a default value or the '0000-00-00' is allowed by the
368
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
369
flag to allow ALTER Table only if the table to be altered is empty.
376
if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
371
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
372
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
373
! alter_info->datetime_field &&
374
! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
375
session->variables.sql_mode & MODE_NO_ZERO_DATE)
377
alter_info->datetime_field= def;
378
378
alter_info->error_if_not_empty= true;
380
380
if (! def->after)
382
381
new_create_list.push_back(def);
384
382
else if (def->after == first_keyword)
386
383
new_create_list.push_front(def);
390
386
CreateField *find;
423
419
my_error(ER_BAD_FIELD_ERROR,
425
421
alter_info->alter_list.head()->name,
426
table->getMutableShare()->getTableName());
422
table->s->getTableName());
429
425
if (! new_create_list.elements)
431
427
my_message(ER_CANT_REMOVE_ALL_FIELDS,
432
428
ER(ER_CANT_REMOVE_ALL_FIELDS),
438
434
Collect all keys which isn't in drop list. Add only those
439
435
for which some fields exists.
441
for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
437
for (uint32_t i= 0; i < table->s->keys; i++, key_info++)
443
439
char *key_name= key_info->name;
537
533
new_key_list.push_back(key);
541
/* Copy over existing foreign keys */
542
for (int j= 0; j < original_proto.fk_constraint_size(); j++)
546
while ((drop= drop_it++))
548
if (drop->type == AlterDrop::FOREIGN_KEY &&
549
! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), drop->name))
560
message::Table::ForeignKeyConstraint *pfkey= table_message.add_fk_constraint();
561
*pfkey= original_proto.fk_constraint(j);
566
538
while ((key= key_it++)) /* Add new keys */
568
if (key->type == Key::FOREIGN_KEY)
570
if (((Foreign_key *)key)->validate(new_create_list))
575
Foreign_key *fkey= (Foreign_key*)key;
576
add_foreign_key_to_table_message(&table_message,
540
if (key->type == Key::FOREIGN_KEY &&
541
((Foreign_key *)key)->validate(new_create_list))
586
543
if (key->type != Key::FOREIGN_KEY)
587
544
new_key_list.push_back(key);
589
545
if (key->name.str && is_primary_key_name(key->name.str))
591
547
my_error(ER_WRONG_NAME_FOR_INDEX,
599
/* Fix names of foreign keys being added */
600
for (int j= 0; j < table_message.fk_constraint_size(); j++)
602
if (! table_message.fk_constraint(j).has_name())
604
std::string name(table->getMutableShare()->getTableName());
607
name.append("_ibfk_");
608
snprintf(number, sizeof(number), "%d", j+1);
611
message::Table::ForeignKeyConstraint *pfkey= table_message.mutable_fk_constraint(j);
612
pfkey->set_name(name);
616
555
if (alter_info->drop_list.elements)
618
557
my_error(ER_CANT_DROP_FIELD_OR_KEY,
620
559
alter_info->drop_list.head()->name);
623
562
if (alter_info->alter_list.elements)
625
564
my_error(ER_CANT_DROP_FIELD_OR_KEY,
627
566
alter_info->alter_list.head()->name);
631
570
if (not table_message.options().has_comment()
632
&& table->getMutableShare()->hasComment())
633
table_options->set_comment(table->getMutableShare()->getComment());
571
&& table->s->hasComment())
572
table_options->set_comment(table->s->getComment());
635
if (table->getShare()->getType())
574
if (table->s->tmp_table)
637
576
table_message.set_type(message::Table::TEMPORARY);
640
579
table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
641
table_message.set_version(table->getShare()->getTableProto()->version());
642
table_message.set_uuid(table->getShare()->getTableProto()->uuid());
581
table_message.set_update_timestamp(time(NULL));
645
584
alter_info->create_list.swap(new_create_list);
646
585
alter_info->key_list.swap(new_key_list);
648
588
size_t num_engine_options= table_message.engine().options_size();
649
589
size_t original_num_engine_options= original_proto.engine().options_size();
807
740
if (not name_lock)
810
new_table_identifier.getSQLPath(path);
811
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
742
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
815
746
if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
818
new_table_identifier.getSQLPath(path);
820
748
/* Table will be closed by Session::executeCommand() */
821
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
749
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
823
table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
751
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
824
752
session.unlink_open_table(name_lock);
825
table::Cache::singleton().mutex().unlock();
753
pthread_mutex_unlock(&LOCK_open);
934
859
if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
935
860
new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
938
new_table_identifier.getSQLPath(path);
939
my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
862
my_error(ER_ILLEGAL_HA, MYF(0), new_table_identifier.getSQLPath().c_str());
867
if (create_info->row_type == ROW_TYPE_NOT_USED)
869
message::Table::TableOptions *table_options;
870
table_options= create_proto.mutable_options();
872
create_info->row_type= table->s->row_type;
873
table_options->set_row_type(original_table_definition->options().row_type());
944
876
session->set_proc_info("setup");
970
902
while the fact that the table is still open gives us protection
971
903
from concurrent DDL statements.
973
table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
905
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
974
906
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
975
table::Cache::singleton().mutex().unlock();
907
pthread_mutex_unlock(&LOCK_open);
976
908
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
977
909
/* COND_refresh will be signaled in close_thread_tables() */
980
table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
912
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
981
913
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
982
table::Cache::singleton().mutex().unlock();
914
pthread_mutex_unlock(&LOCK_open);
983
915
error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
984
916
/* COND_refresh will be signaled in close_thread_tables() */
995
927
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
996
928
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1000
table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
932
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
1002
934
Unlike to the above case close_cached_table() below will remove ALL
1003
935
instances of Table from table cache (it will also remove table lock
1004
936
held by this thread). So to make actual table renaming and writing
1005
937
to binlog atomic we have to put them into the same critical section
1006
protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
938
protected by LOCK_open mutex. This also removes gap for races between
1007
939
access() and mysql_rename_table() calls.
1026
958
if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1029
new_table_identifier.getSQLPath(path);
1030
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
960
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
1035
if (mysql_rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
965
if (mysql_rename_table(original_engine, original_table_identifier, new_table_identifier))
1102
1030
/* Open the table so we need to copy the data to it. */
1103
Table *new_table= open_alter_table(session, table, new_table_as_temporary);
1031
new_table= open_alter_table(session, table, new_table_as_temporary);
1106
1033
if (not new_table)
1108
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1035
quick_rm_table(*session, new_table_as_temporary);
1112
1039
/* Copy the data if necessary. */
1114
/* We must not ignore bad input! */
1115
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; // calc cuted fields
1041
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
1116
1042
session->cuted_fields= 0L;
1117
1043
session->set_proc_info("copy to tmp table");
1118
1044
copied= deleted= 0;
1150
1075
if (alter_info->error_if_not_empty && session->row_count)
1152
my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
1077
const char *f_val= 0;
1078
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
1080
switch (alter_info->datetime_field->sql_type)
1082
case DRIZZLE_TYPE_DATE:
1083
f_val= "0000-00-00";
1084
t_type= DRIZZLE_TIMESTAMP_DATE;
1086
case DRIZZLE_TYPE_DATETIME:
1087
f_val= "0000-00-00 00:00:00";
1088
t_type= DRIZZLE_TIMESTAMP_DATETIME;
1091
/* Shouldn't get here. */
1094
bool save_abort_on_warning= session->abort_on_warning;
1095
session->abort_on_warning= true;
1096
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1097
f_val, internal::strlength(f_val), t_type,
1098
alter_info->datetime_field->field_name);
1099
session->abort_on_warning= save_abort_on_warning;
1155
1102
if (original_table_identifier.isTmp())
1175
1122
Note that MERGE tables do not have their children attached here.
1177
1124
new_table->intern_close_table();
1178
if (new_table->hasShare())
1180
delete new_table->getMutableShare();
1127
if (new_table->s->newed)
1129
delete new_table->s;
1186
table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1142
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1188
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1189
table::Cache::singleton().mutex().unlock();
1144
quick_rm_table(*session, new_table_as_temporary);
1145
pthread_mutex_unlock(&LOCK_open);
1205
1161
session->close_temporary_table(table);
1207
1163
/* Should pass the 'new_name' as we store table name in the cache */
1208
new_table->getMutableShare()->setIdentifier(new_table_identifier);
1164
if (new_table->renameAlterTemporaryTable(new_table_identifier))
1166
session->close_temporary_table(new_table);
1210
1171
new_table_identifier.setPath(new_table_as_temporary.getPath());
1212
if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1173
if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier) != 0)
1272
1242
compare_table(). Then, we need one additional call to
1274
1244
TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
1275
old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1276
message::Table::TEMPORARY);
1245
old_name, message::Table::TEMPORARY);
1278
if (mysql_rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1247
if (mysql_rename_table(original_engine, original_table_identifier, original_table_to_drop))
1281
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1250
quick_rm_table(*session, new_table_as_temporary);
1285
if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1254
if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier) != 0)
1287
1256
/* Try to get everything back. */
1290
plugin::StorageEngine::dropTable(*session, new_table_identifier);
1292
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1294
mysql_rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1259
quick_rm_table(*session, new_table_identifier);
1261
quick_rm_table(*session, new_table_as_temporary);
1263
mysql_rename_table(original_engine, original_table_to_drop, original_table_identifier);
1298
plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1267
quick_rm_table(*session, original_table_to_drop);
1438
1407
TransactionServices &transaction_services= TransactionServices::singleton();
1443
* Since open_temporary_table() doesn't invoke lockTables(), we
1444
* don't get the usual automatic call to StorageEngine::startStatement(), so
1445
* we manually call it here...
1447
to->getMutableShare()->getEngine()->startStatement(session);
1449
if (!(copy= new CopyField[to->getShare()->sizeFields()]))
1409
if (!(copy= new CopyField[to->s->fields]))
1452
1412
if (to->cursor->ha_external_lock(session, F_WRLCK))
1455
1415
/* We need external lock before we can disable/enable keys */
1456
alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1416
alter_table_manage_keys(to, from->cursor->indexes_are_disabled(), keys_onoff);
1458
1418
/* We can abort alter table for any table type */
1459
1419
session->abort_on_warning= !ignore;
1484
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1444
if (to->s->primary_key != MAX_KEY && to->cursor->primary_key_is_clustered())
1486
1446
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1487
1447
snprintf(warn_buff, sizeof(warn_buff),
1488
1448
_("order_st BY ignored because there is a user-defined clustered "
1489
1449
"index in the table '%-.192s'"),
1490
from->getMutableShare()->getTableName());
1450
from->s->getTableName());
1491
1451
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1496
FileSort filesort(*session);
1497
1456
from->sort.io_cache= new internal::IO_CACHE;
1457
memset(from->sort.io_cache, 0, sizeof(internal::IO_CACHE));
1499
1459
memset(&tables, 0, sizeof(tables));
1500
1460
tables.table= from;
1501
tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1502
tables.alias= const_cast<char *>(tables.getTableName());
1503
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1461
tables.alias= tables.table_name= const_cast<char *>(from->s->getTableName());
1462
tables.db= const_cast<char *>(from->s->getSchemaName());
1506
1465
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1507
1466
setup_order(session, session->lex->select_lex.ref_pointer_array,
1508
1467
&tables, fields, all_fields, order) ||
1509
1468
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1510
(from->sort.found_records= filesort.run(from, sortorder, length,
1511
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1512
1, examined_rows)) == HA_POS_ERROR)
1469
(from->sort.found_records= filesort(session, from, sortorder, length,
1470
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1471
1, &examined_rows)) ==
1546
1506
to->next_number_field->reset();
1549
for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1509
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1551
if (not copy->to_field->hasDefault() and copy->from_null_ptr and *copy->from_null_ptr & copy->from_bit)
1553
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1554
ER_WARN_DATA_TRUNCATED, 1);
1555
copy->to_field->reset();
1560
1511
copy_ptr->do_copy(copy_ptr);
1568
1513
prev_insert_id= to->cursor->next_insert_id;
1569
1514
error= to->cursor->insertRecord(to->record[0]);
1570
1515
to->auto_increment_field_not_null= false;
1574
if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1520
to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1576
1522
to->print_error(error, MYF(0));
1646
1592
Table *new_table;
1648
1594
/* Open the table so we need to copy the data to it. */
1649
if (table->getShare()->getType())
1595
if (table->s->tmp_table)
1652
tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1598
tbl.db= const_cast<char *>(identifier.getSchemaName().c_str());
1653
1599
tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1654
tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
1600
tbl.table_name= const_cast<char *>(identifier.getTableName().c_str());
1656
1602
/* Table is in session->temporary_tables */
1657
1603
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);