18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
#include <drizzled/show.h>
28
#include <drizzled/lock.h>
29
#include <drizzled/session.h>
30
#include <drizzled/statement/alter_table.h>
31
#include <drizzled/global_charset_info.h>
34
#include <drizzled/gettext.h>
35
#include <drizzled/data_home.h>
36
#include <drizzled/sql_table.h>
37
#include <drizzled/table_proto.h>
38
#include <drizzled/optimizer/range.h>
39
#include <drizzled/time_functions.h>
40
#include <drizzled/records.h>
41
#include <drizzled/pthread_globals.h>
42
#include <drizzled/internal/my_sys.h>
43
#include <drizzled/internal/iocache.h>
44
#include <drizzled/plugin/storage_engine.h>
45
#include <drizzled/copy_field.h>
47
#include <drizzled/transaction_services.h>
49
#include <drizzled/filesort.h>
51
#include <drizzled/message.h>
27
#include "drizzled/show.h"
28
#include "drizzled/lock.h"
29
#include "drizzled/session.h"
30
#include "drizzled/statement/alter_table.h"
31
#include "drizzled/global_charset_info.h"
34
#include "drizzled/gettext.h"
35
#include "drizzled/data_home.h"
36
#include "drizzled/sql_table.h"
37
#include "drizzled/table_proto.h"
38
#include "drizzled/optimizer/range.h"
39
#include "drizzled/time_functions.h"
40
#include "drizzled/records.h"
41
#include "drizzled/pthread_globals.h"
42
#include "drizzled/internal/my_sys.h"
43
#include "drizzled/internal/iocache.h"
45
#include "drizzled/transaction_services.h"
53
47
using namespace std;
58
52
extern pid_t current_pid;
60
static int copy_data_between_tables(Session *session,
61
Table *from,Table *to,
54
static int copy_data_between_tables(Table *from,Table *to,
62
55
List<CreateField> &create,
64
57
uint32_t order_num,
68
61
enum enum_enable_or_disable keys_onoff,
69
62
bool error_if_not_empty);
71
static bool prepare_alter_table(Session *session,
64
static bool mysql_prepare_alter_table(Session *session,
73
66
HA_CREATE_INFO *create_info,
74
const message::Table &original_proto,
75
67
message::Table &table_message,
76
68
AlterInfo *alter_info);
78
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
82
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
CreateTable(in_session)
85
in_session->getLex()->sql_command= SQLCOM_ALTER_TABLE;
87
alter_info.build_method= build_arg;
90
} // namespace statement
70
static int create_temporary_table(Session *session,
71
TableIdentifier &identifier,
72
HA_CREATE_INFO *create_info,
73
message::Table &create_message,
74
AlterInfo *alter_info);
76
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
92
78
bool statement::AlterTable::execute()
94
TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
95
TableList *all_tables= getSession()->getLex()->query_tables;
80
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
81
TableList *all_tables= session->lex->query_tables;
96
82
assert(first_table == all_tables && first_table != 0);
97
Select_Lex *select_lex= &getSession()->getLex()->select_lex;
83
Select_Lex *select_lex= &session->lex->select_lex;
98
84
bool need_start_waiting= false;
100
is_engine_set= not createTableMessage().engine().name().empty();
102
86
if (is_engine_set)
104
create_info().db_type=
105
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
89
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
107
if (create_info().db_type == NULL)
91
if (create_info.db_type == NULL)
109
my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
93
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
94
create_table_message.name().c_str());
115
101
/* Must be set in the parser */
116
102
assert(select_lex->db);
118
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 */
119
message::table::shared_ptr original_table_message;
105
message::Table original_table_message;
121
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
if (not (original_table_message= plugin::StorageEngine::getTableMessage(*getSession(), identifier)))
107
TableIdentifier identifier(first_table->db, first_table->table_name);
108
if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
124
my_error(ER_BAD_TABLE_ERROR, identifier);
110
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
128
if (not create_info().db_type)
130
create_info().db_type=
131
plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
133
if (not create_info().db_type)
135
my_error(ER_BAD_TABLE_ERROR, identifier);
141
if (not validateCreateTableOption())
144
if (getSession()->inTransaction())
146
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
150
if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
115
/* ALTER TABLE ends previous transaction */
116
if (not session->endActiveTransaction())
121
if (not (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
154
if (original_table_message->type() == message::Table::STANDARD )
127
if (original_table_message.type() == message::Table::STANDARD )
156
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName());
129
TableIdentifier identifier(first_table->db, first_table->table_name);
130
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
131
session->lex->name.str ? session->lex->name.str : first_table->table_name);
160
res= alter_table(getSession(),
133
res= alter_table(session,
164
*original_table_message,
165
createTableMessage(),
137
create_table_message,
168
140
select_lex->order_list.elements,
169
(Order *) select_lex->order_list.first,
170
getSession()->getLex()->ignore);
141
(order_st *) select_lex->order_list.first,
142
session->lex->ignore);
174
identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
Table *table= getSession()->find_temporary_table(catch22);
146
Table *table= session->find_temporary_table(first_table);
178
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName(),
181
table->getMutableShare()->getPath());
149
TableIdentifier identifier(first_table->db, first_table->table_name, table->s->path.str);
150
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
151
session->lex->name.str ? session->lex->name.str : first_table->table_name,
183
res= alter_table(getSession(),
154
res= alter_table(session,
187
*original_table_message,
188
createTableMessage(),
158
create_table_message,
191
161
select_lex->order_list.elements,
192
(Order *) select_lex->order_list.first,
193
getSession()->getLex()->ignore);
162
(order_st *) select_lex->order_list.first,
163
session->lex->ignore);
244
213
Table instructions
245
214
@retval false success
247
static bool prepare_alter_table(Session *session,
249
HA_CREATE_INFO *create_info,
250
const message::Table &original_proto,
251
message::Table &table_message,
252
AlterInfo *alter_info)
216
static bool mysql_prepare_alter_table(Session *session,
218
HA_CREATE_INFO *create_info,
219
message::Table &table_message,
220
AlterInfo *alter_info)
254
222
/* New column definitions are added here */
255
223
List<CreateField> new_create_list;
256
224
/* New key definitions are added here */
257
225
List<Key> new_key_list;
258
List<AlterDrop>::iterator drop_it(alter_info->drop_list.begin());
259
List<CreateField>::iterator def_it(alter_info->create_list.begin());
260
List<AlterColumn>::iterator alter_it(alter_info->alter_list.begin());
261
List<Key>::iterator key_it(alter_info->key_list.begin());
262
List<CreateField>::iterator find_it(new_create_list.begin());
263
List<CreateField>::iterator field_it(new_create_list.begin());
226
List_iterator<AlterDrop> drop_it(alter_info->drop_list);
227
List_iterator<CreateField> def_it(alter_info->create_list);
228
List_iterator<AlterColumn> alter_it(alter_info->alter_list);
229
List_iterator<Key> key_it(alter_info->key_list);
230
List_iterator<CreateField> find_it(new_create_list);
231
List_iterator<CreateField> field_it(new_create_list);
264
232
List<Key_part_spec> key_parts;
265
233
uint32_t used_fields= create_info->used_fields;
266
KeyInfo *key_info= table->key_info;
234
KEY *key_info= table->key_info;
269
237
/* Let new create options override the old ones */
270
238
message::Table::TableOptions *table_options;
271
239
table_options= table_message.mutable_options();
273
if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
create_info->default_table_charset= table->getShare()->table_charset;
276
if (not (used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
241
if (! (used_fields & HA_CREATE_USED_BLOCK_SIZE))
242
table_options->set_block_size(table->s->block_size);
243
if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
244
create_info->default_table_charset= table->s->table_charset;
245
if (! (used_fields & HA_CREATE_USED_AUTO) &&
246
table->found_next_number_field)
278
248
/* Table has an autoincrement, copy value to new table */
279
249
table->cursor->info(HA_STATUS_AUTO);
280
250
create_info->auto_increment_value= table->cursor->stats.auto_increment_value;
281
if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
282
table_options->set_has_user_set_auto_increment_value(false);
252
if (! (used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
253
&& table->s->hasKeyBlockSize())
254
table_options->set_key_block_size(table->s->getKeyBlockSize());
256
if ((used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
257
&& table_options->key_block_size() == 0)
258
table_options->clear_key_block_size();
285
260
table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
286
261
CreateField *def;
288
263
/* First collect all fields from table which isn't in drop_list */
290
for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
266
for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
292
268
/* Check if field should be dropped */
294
drop_it= alter_info->drop_list.begin();
295
271
while ((drop= drop_it++))
297
273
if (drop->type == AlterDrop::COLUMN &&
345
319
def= new CreateField(field, field);
346
320
new_create_list.push_back(def);
347
alter_it= alter_info->alter_list.begin(); /* Change default if ALTER */
321
alter_it.rewind(); /* Change default if ALTER */
348
322
AlterColumn *alter;
350
323
while ((alter= alter_it++))
352
325
if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
358
330
if (def->sql_type == DRIZZLE_TYPE_BLOB)
360
332
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
364
335
if ((def->def= alter->def))
366
337
/* Use new default */
367
338
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
371
341
def->flags|= NO_DEFAULT_VALUE_FLAG;
373
342
alter_it.remove();
378
def_it= alter_info->create_list.begin();
379
347
while ((def= def_it++)) /* Add new columns */
381
349
if (def->change && ! def->field)
383
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
351
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
387
If we have been given a field which has no default value, and is not null then we need to bail.
355
Check that the DATE/DATETIME not null field we are going to add is
356
either has a default value or the '0000-00-00' is allowed by the
358
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
359
flag to allow ALTER Table only if the table to be altered is empty.
389
if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
361
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
362
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
363
! alter_info->datetime_field &&
364
! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
365
session->variables.sql_mode & MODE_NO_ZERO_DATE)
367
alter_info->datetime_field= def;
391
368
alter_info->error_if_not_empty= true;
393
370
if (! def->after)
395
371
new_create_list.push_back(def);
397
372
else if (def->after == first_keyword)
399
373
new_create_list.push_front(def);
403
376
CreateField *find;
404
find_it= new_create_list.begin();
406
378
while ((find= find_it++)) /* Add new columns */
408
if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
380
if (! my_strcasecmp(system_charset_info,def->after, find->field_name))
414
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
385
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
418
388
find_it.after(def); /* Put element after this */
421
390
XXX: hack for Bug#28427.
422
391
If column order has changed, force OFFLINE ALTER Table
430
399
if (alter_info->build_method == HA_BUILD_ONLINE)
432
my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
401
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query.c_str());
436
404
alter_info->build_method= HA_BUILD_OFFLINE;
440
407
if (alter_info->alter_list.elements)
442
409
my_error(ER_BAD_FIELD_ERROR,
444
411
alter_info->alter_list.head()->name,
445
table->getMutableShare()->getTableName());
412
table->s->table_name.str);
449
if (not new_create_list.elements)
415
if (! new_create_list.elements)
451
417
my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
418
ER(ER_CANT_REMOVE_ALL_FIELDS),
458
424
Collect all keys which isn't in drop list. Add only those
459
425
for which some fields exists.
461
for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
427
for (uint32_t i= 0; i < table->s->keys; i++, key_info++)
463
429
char *key_name= key_info->name;
466
drop_it= alter_info->drop_list.begin();
467
432
while ((drop= drop_it++))
469
434
if (drop->type == AlterDrop::KEY &&
470
435
! my_strcasecmp(system_charset_info, key_name, drop->name))
476
440
drop_it.remove();
480
KeyPartInfo *key_part= key_info->key_part;
444
KEY_PART_INFO *key_part= key_info->key_part;
482
446
for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
484
448
if (! key_part->field)
563
523
new_key_list.push_back(key);
567
/* Copy over existing foreign keys */
568
for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
571
drop_it= alter_info->drop_list.begin();
572
while ((drop= drop_it++))
574
if (drop->type == AlterDrop::FOREIGN_KEY &&
575
! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), drop->name))
586
message::Table::ForeignKeyConstraint *pfkey= table_message.add_fk_constraint();
587
*pfkey= original_proto.fk_constraint(j);
592
528
while ((key= key_it++)) /* Add new keys */
594
if (key->type == Key::FOREIGN_KEY)
596
if (((Foreign_key *)key)->validate(new_create_list))
601
Foreign_key *fkey= (Foreign_key*)key;
602
add_foreign_key_to_table_message(&table_message,
530
if (key->type == Key::FOREIGN_KEY &&
531
((Foreign_key *)key)->validate(new_create_list))
612
533
if (key->type != Key::FOREIGN_KEY)
613
534
new_key_list.push_back(key);
615
535
if (key->name.str && is_primary_key_name(key->name.str))
617
537
my_error(ER_WRONG_NAME_FOR_INDEX,
625
/* Fix names of foreign keys being added */
626
for (int j= 0; j < table_message.fk_constraint_size(); j++)
628
if (! table_message.fk_constraint(j).has_name())
630
std::string name(table->getMutableShare()->getTableName());
633
name.append("_ibfk_");
634
snprintf(number, sizeof(number), "%d", j+1);
637
message::Table::ForeignKeyConstraint *pfkey= table_message.mutable_fk_constraint(j);
638
pfkey->set_name(name);
642
545
if (alter_info->drop_list.elements)
644
547
my_error(ER_CANT_DROP_FIELD_OR_KEY,
646
549
alter_info->drop_list.head()->name);
650
552
if (alter_info->alter_list.elements)
652
554
my_error(ER_CANT_DROP_FIELD_OR_KEY,
654
556
alter_info->alter_list.head()->name);
658
560
if (not table_message.options().has_comment()
659
&& table->getMutableShare()->hasComment())
661
table_options->set_comment(table->getMutableShare()->getComment());
561
&& table->s->hasComment())
562
table_options->set_comment(table->s->getComment());
664
if (table->getShare()->getType())
564
if (table->s->tmp_table)
666
566
table_message.set_type(message::Table::TEMPORARY);
669
table_message.set_creation_timestamp(table->getShare()->getTableMessage()->creation_timestamp());
670
table_message.set_version(table->getShare()->getTableMessage()->version());
671
table_message.set_uuid(table->getShare()->getTableMessage()->uuid());
569
table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
571
table_message.set_update_timestamp(time(NULL));
573
if (not table_message.options().has_comment()
574
&& table->s->hasComment())
575
table_options->set_comment(table->s->getComment());
674
578
alter_info->create_list.swap(new_create_list);
675
579
alter_info->key_list.swap(new_key_list);
677
size_t num_engine_options= table_message.engine().options_size();
678
size_t original_num_engine_options= original_proto.engine().options_size();
679
for (size_t x= 0; x < original_num_engine_options; ++x)
683
for (size_t y= 0; y < num_engine_options; ++y)
685
found= not table_message.engine().options(y).name().compare(original_proto.engine().options(x).name());
693
message::Engine::Option *opt= table_message.mutable_engine()->add_options();
695
opt->set_name(original_proto.engine().options(x).name());
696
opt->set_state(original_proto.engine().options(x).state());
700
drizzled::message::update(table_message);
705
584
/* table_list should contain just one table */
706
static int discard_or_import_tablespace(Session *session,
585
static int mysql_discard_or_import_tablespace(Session *session,
707
586
TableList *table_list,
708
587
enum tablespace_op_type tablespace_op)
714
594
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
717
598
TransactionServices &transaction_services= TransactionServices::singleton();
718
599
session->set_proc_info("discard_or_import_tablespace");
996
879
while the fact that the table is still open gives us protection
997
880
from concurrent DDL statements.
1000
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1001
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
882
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
883
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
884
pthread_mutex_unlock(&LOCK_open);
1003
885
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1005
886
/* COND_refresh will be signaled in close_thread_tables() */
1010
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1011
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1013
error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
889
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
890
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
891
pthread_mutex_unlock(&LOCK_open);
892
error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
893
/* COND_refresh will be signaled in close_thread_tables() */
1019
901
if (error == HA_ERR_WRONG_COMMAND)
1022
904
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
905
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1027
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
909
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
1029
911
Unlike to the above case close_cached_table() below will remove ALL
1030
912
instances of Table from table cache (it will also remove table lock
1031
913
held by this thread). So to make actual table renaming and writing
1032
914
to binlog atomic we have to put them into the same critical section
1033
protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
1034
access() and rename_table() calls.
915
protected by LOCK_open mutex. This also removes gap for races between
916
access() and mysql_rename_table() calls.
1037
if (not error && not (original_table_identifier == new_table_identifier))
919
if (error == 0 && not (original_table_identifier == new_table_identifier))
1039
921
session->set_proc_info("rename");
1252
1149
Note that MERGE tables do not have their children attached here.
1254
1151
new_table->intern_close_table();
1256
if (new_table->hasShare())
1258
delete new_table->getMutableShare();
1265
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
1267
Data is copied. Now we:
1268
1) Wait until all other threads close old version of table.
1269
2) Close instances of table open by this thread and replace them
1270
with exclusive name-locks.
1271
3) Rename the old table to a temp name, rename the new one to the
1273
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1274
we reopen new version of table.
1275
5) Write statement to the binary log.
1276
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1277
remove name-locks from list of open tables and table cache.
1278
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1279
call to remove name-locks from table cache and list of open table.
1282
session->set_proc_info("rename result table");
1284
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1286
my_casedn_str(files_charset_info, old_name);
1288
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1289
session->close_data_files_and_morph_locks(original_table_identifier);
1294
This leads to the storage engine (SE) not being notified for renames in
1295
rename_table(), because we just juggle with the FRM and nothing
1296
more. If we have an intermediate table, then we notify the SE that
1297
it should become the actual table. Later, we will recycle the old table.
1298
However, in case of ALTER Table RENAME there might be no intermediate
1299
table. This is when the old and new tables are compatible, according to
1300
compare_table(). Then, we need one additional call to
1302
identifier::Table original_table_to_drop(original_table_identifier.getSchemaName(),
1303
old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1304
message::Table::TEMPORARY);
1306
drizzled::error_t rename_error= EE_OK;
1307
if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1309
error= ER_ERROR_ON_RENAME;
1310
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1155
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1158
Data is copied. Now we:
1159
1) Wait until all other threads close old version of table.
1160
2) Close instances of table open by this thread and replace them
1161
with exclusive name-locks.
1162
3) Rename the old table to a temp name, rename the new one to the
1164
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1165
we reopen new version of table.
1166
5) Write statement to the binary log.
1167
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1168
remove name-locks from list of open tables and table cache.
1169
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1170
call to remove name-locks from table cache and list of open table.
1173
session->set_proc_info("rename result table");
1175
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1177
my_casedn_str(files_charset_info, old_name);
1179
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1180
session->close_data_files_and_morph_locks(original_table_identifier);
1185
This leads to the storage engine (SE) not being notified for renames in
1186
mysql_rename_table(), because we just juggle with the FRM and nothing
1187
more. If we have an intermediate table, then we notify the SE that
1188
it should become the actual table. Later, we will recycle the old table.
1189
However, in case of ALTER Table RENAME there might be no intermediate
1190
table. This is when the old and new tables are compatible, according to
1191
compare_table(). Then, we need one additional call to
1193
TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
1194
old_name, TEMP_TABLE);
1196
if (mysql_rename_table(original_engine, original_table_identifier, original_table_to_drop, FN_TO_IS_TMP))
1199
quick_rm_table(*session, new_table_as_temporary);
1203
if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier, FN_FROM_IS_TMP) != 0)
1205
/* Try to get everything back. */
1208
quick_rm_table(*session, new_table_identifier);
1210
quick_rm_table(*session, new_table_as_temporary);
1212
mysql_rename_table(original_engine, original_table_to_drop, original_table_identifier, FN_FROM_IS_TMP);
1314
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1316
/* Try to get everything back. */
1317
rename_error= ER_ERROR_ON_RENAME;
1319
plugin::StorageEngine::dropTable(*session, new_table_identifier);
1321
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1323
rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1327
plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1334
An error happened while we were holding exclusive name-lock on table
1335
being altered. To be safe under LOCK TABLES we should remove placeholders
1336
from list of open tables list and table cache.
1338
session->unlink_open_table(table);
1216
quick_rm_table(*session, original_table_to_drop);
1223
An error happened while we were holding exclusive name-lock on table
1224
being altered. To be safe under LOCK TABLES we should remove placeholders
1225
from list of open tables list and table cache.
1227
session->unlink_open_table(table);
1228
pthread_mutex_unlock(&LOCK_open);
1234
pthread_mutex_unlock(&LOCK_open);
1344
1236
session->set_proc_info("end");
1346
write_bin_log(session, *session->getQueryString());
1238
write_bin_log(session, session->query.c_str());
1347
1239
table_list->table= NULL;
1506
1388
found_count=delete_count=0;
1512
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1392
if (to->s->primary_key != MAX_KEY && to->cursor->primary_key_is_clustered())
1394
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1395
snprintf(warn_buff, sizeof(warn_buff),
1396
_("order_st BY ignored because there is a user-defined clustered "
1397
"index in the table '%-.192s'"),
1398
from->s->table_name.str);
1399
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1404
from->sort.io_cache= new internal::IO_CACHE;
1405
memset(from->sort.io_cache, 0, sizeof(internal::IO_CACHE));
1407
memset(&tables, 0, sizeof(tables));
1409
tables.alias= tables.table_name= from->s->table_name.str;
1410
tables.db= const_cast<char *>(from->s->getSchemaName());
1413
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1414
setup_order(session, session->lex->select_lex.ref_pointer_array,
1415
&tables, fields, all_fields, order) ||
1416
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1417
(from->sort.found_records= filesort(session, from, sortorder, length,
1418
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1419
1, &examined_rows)) ==
1514
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1515
snprintf(warn_buff, sizeof(warn_buff),
1516
_("order_st BY ignored because there is a user-defined clustered "
1517
"index in the table '%-.192s'"),
1518
from->getMutableShare()->getTableName());
1519
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1427
/* Tell handler that we have values for all columns in the to table */
1428
to->use_all_columns();
1429
init_read_record(&info, session, from, (optimizer::SqlSelect *) 0, 1,1);
1431
to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1432
session->row_count= 0;
1433
to->restoreRecordAsDefault(); // Create empty record
1434
while (!(error=info.read_record(&info)))
1436
if (session->killed)
1438
session->send_kill_message();
1442
session->row_count++;
1443
/* Return error if source table isn't empty. */
1444
if (error_if_not_empty)
1449
if (to->next_number_field)
1451
if (auto_increment_field_copied)
1452
to->auto_increment_field_not_null= true;
1524
FileSort filesort(*session);
1525
from->sort.io_cache= new internal::IO_CACHE;
1528
tables.setTableName(from->getMutableShare()->getTableName());
1529
tables.alias= tables.getTableName();
1530
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1533
if (session->getLex()->select_lex.setup_ref_array(session, order_num) ||
1534
setup_order(session, session->getLex()->select_lex.ref_pointer_array,
1535
&tables, fields, all_fields, order) ||
1536
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
(from->sort.found_records= filesort.run(from, sortorder, length,
1538
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1539
1, examined_rows)) == HA_POS_ERROR)
1546
/* Tell handler that we have values for all columns in the to table */
1547
to->use_all_columns();
1549
error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
1454
to->next_number_field->reset();
1457
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1459
copy_ptr->do_copy(copy_ptr);
1461
prev_insert_id= to->cursor->next_insert_id;
1462
error= to->cursor->ha_write_row(to->record[0]);
1463
to->auto_increment_field_not_null= false;
1552
to->print_error(errno, MYF(0));
1559
to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1562
session->row_count= 0;
1563
to->restoreRecordAsDefault(); // Create empty record
1564
while (not (error=info.read_record(&info)))
1566
if (session->getKilled())
1568
session->send_kill_message();
1572
session->row_count++;
1573
/* Return error if source table isn't empty. */
1574
if (error_if_not_empty)
1579
if (to->next_number_field)
1581
if (auto_increment_field_copied)
1582
to->auto_increment_field_not_null= true;
1584
to->next_number_field->reset();
1587
for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1589
if (not copy->to_field->hasDefault() and copy->from_null_ptr and *copy->from_null_ptr & copy->from_bit)
1591
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1592
ER_WARN_DATA_TRUNCATED, 1);
1593
copy->to_field->reset();
1598
copy_ptr->do_copy(copy_ptr);
1606
prev_insert_id= to->cursor->next_insert_id;
1607
error= to->cursor->insertRecord(to->record[0]);
1608
to->auto_increment_field_not_null= false;
1467
to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1612
if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1614
to->print_error(error, MYF(0));
1617
to->cursor->restore_auto_increment(prev_insert_id);
1626
info.end_read_record();
1627
from->free_io_cache();
1628
delete [] copy; // This is never 0
1630
if (to->cursor->ha_end_bulk_insert() && error <= 0)
1632
to->print_error(errno, MYF(0));
1635
to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1638
Ensure that the new table is saved properly to disk so that we
1641
if (transaction_services.autocommitOrRollback(*session, false))
1644
if (not session->endActiveTransaction())
1649
session->setAbortOnWarning(false);
1469
to->print_error(error, MYF(0));
1472
to->cursor->restore_auto_increment(prev_insert_id);
1478
end_read_record(&info);
1479
from->free_io_cache();
1480
delete [] copy; // This is never 0
1482
if (to->cursor->ha_end_bulk_insert() && error <= 0)
1484
to->print_error(errno, MYF(0));
1487
to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1490
Ensure that the new table is saved properly to disk so that we
1493
if (transaction_services.ha_autocommit_or_rollback(session, false))
1495
if (! session->endActiveTransaction())
1499
session->abort_on_warning= 0;
1650
1500
from->free_io_cache();
1651
1501
*copied= found_count;
1652
1502
*deleted=delete_count;
1653
1503
to->cursor->ha_release_auto_increment();
1655
if (to->cursor->ha_external_lock(session, F_UNLCK))
1504
if (to->cursor->ha_external_lock(session,F_UNLCK))
1660
1506
return(error > 0 ? -1 : 0);
1663
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1510
create_temporary_table(Session *session,
1511
TableIdentifier &identifier,
1512
HA_CREATE_INFO *create_info,
1513
message::Table &create_proto,
1514
AlterInfo *alter_info)
1519
Create a table with a temporary name.
1520
We don't log the statement, it will be logged later.
1522
create_proto.set_name(identifier.getTableName());
1524
message::Table::StorageEngine *protoengine;
1525
protoengine= create_proto.mutable_engine();
1526
protoengine->set_name(create_info->db_type->getName());
1528
error= mysql_create_table(session,
1530
create_info, create_proto, alter_info, true, 0, false);
1535
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1665
1537
Table *new_table;
1667
1539
/* Open the table so we need to copy the data to it. */
1668
if (table->getShare()->getType())
1540
if (table->s->tmp_table)
1671
tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1543
tbl.db= const_cast<char *>(identifier.getSchemaName().c_str());
1672
1544
tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1673
tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
1545
tbl.table_name= const_cast<char *>(identifier.getTableName().c_str());
1675
1547
/* Table is in session->temporary_tables */
1676
1548
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);