1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2009 Sun Microsystems, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
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"
58
extern pid_t current_pid;
60
static int copy_data_between_tables(Session *session,
61
Table *from,Table *to,
62
List<CreateField> &create,
68
enum enum_enable_or_disable keys_onoff,
69
bool error_if_not_empty);
71
static bool prepare_alter_table(Session *session,
73
HA_CREATE_INFO *create_info,
74
const message::Table &original_proto,
75
message::Table &table_message,
76
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->lex->sql_command= SQLCOM_ALTER_TABLE;
87
alter_info.build_method= build_arg;
90
} // namespace statement
92
bool statement::AlterTable::execute()
94
TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
95
TableList *all_tables= getSession()->lex->query_tables;
96
assert(first_table == all_tables && first_table != 0);
97
Select_Lex *select_lex= &getSession()->lex->select_lex;
98
bool need_start_waiting= false;
100
is_engine_set= not createTableMessage().engine().name().empty();
104
create_info().db_type=
105
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
107
if (create_info().db_type == NULL)
109
my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
115
/* Must be set in the parser */
116
assert(select_lex->db);
118
/* 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;
121
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
if (plugin::StorageEngine::getTableDefinition(*getSession(), identifier, original_table_message) != EEXIST)
124
my_error(ER_BAD_TABLE_ERROR, identifier);
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)))
154
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()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName());
160
res= alter_table(getSession(),
164
*original_table_message,
165
createTableMessage(),
168
select_lex->order_list.elements,
169
(Order *) select_lex->order_list.first,
170
getSession()->lex->ignore);
174
identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
Table *table= getSession()->find_temporary_table(catch22);
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()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName(),
181
table->getMutableShare()->getPath());
183
res= alter_table(getSession(),
187
*original_table_message,
188
createTableMessage(),
191
select_lex->order_list.elements,
192
(Order *) select_lex->order_list.first,
193
getSession()->lex->ignore);
198
Release the protection against the global read lock and wake
199
everyone, who might want to set a global read lock.
201
getSession()->startWaitingGlobalReadLock();
208
Prepare column and key definitions for CREATE TABLE in ALTER Table.
210
This function transforms parse output of ALTER Table - lists of
211
columns and keys to add, drop or modify into, essentially,
212
CREATE TABLE definition - a list of columns and keys of the new
213
table. While doing so, it also performs some (bug not all)
216
This function is invoked when we know that we're going to
217
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
218
is not possible, perhaps because the ALTER statement contains
219
instructions that require change in table data, not only in
220
table definition or indexes.
222
@param[in,out] session thread handle. Used as a memory pool
223
and source of environment information.
224
@param[in] table the source table, open and locked
225
Used as an interface to the storage engine
226
to acquire additional information about
228
@param[in,out] create_info A blob with CREATE/ALTER Table
230
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
231
Originally create_info was used only in
232
CREATE TABLE and alter_info only in ALTER Table.
233
But since ALTER might end-up doing CREATE,
234
this distinction is gone and we just carry
235
around two structures.
238
Fills various create_info members based on information retrieved
239
from the storage engine.
240
Sets create_info->varchar if the table has a VARCHAR column.
241
Prepares alter_info->create_list and alter_info->key_list with
242
columns and keys of the new table.
243
@retval true error, out of memory or a semantical error in ALTER
245
@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)
254
/* New column definitions are added here */
255
List<CreateField> new_create_list;
256
/* New key definitions are added here */
257
List<Key> new_key_list;
258
List_iterator<AlterDrop> drop_it(alter_info->drop_list);
259
List_iterator<CreateField> def_it(alter_info->create_list);
260
List_iterator<AlterColumn> alter_it(alter_info->alter_list);
261
List_iterator<Key> key_it(alter_info->key_list);
262
List_iterator<CreateField> find_it(new_create_list);
263
List_iterator<CreateField> field_it(new_create_list);
264
List<Key_part_spec> key_parts;
265
uint32_t used_fields= create_info->used_fields;
266
KeyInfo *key_info= table->key_info;
269
/* Let new create options override the old ones */
270
message::Table::TableOptions *table_options;
271
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)
278
/* Table has an autoincrement, copy value to new table */
279
table->cursor->info(HA_STATUS_AUTO);
280
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);
285
table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
288
/* First collect all fields from table which isn't in drop_list */
290
for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
292
/* Check if field should be dropped */
295
while ((drop= drop_it++))
297
if (drop->type == AlterDrop::COLUMN &&
298
! my_strcasecmp(system_charset_info, field->field_name, drop->name))
300
/* Reset auto_increment value if it was dropped */
301
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
302
! (used_fields & HA_CREATE_USED_AUTO))
304
create_info->auto_increment_value= 0;
305
create_info->used_fields|= HA_CREATE_USED_AUTO;
317
/* Mark that we will read the field */
320
/* Check if field is changed */
322
while ((def= def_it++))
325
! my_strcasecmp(system_charset_info, field->field_name, def->change))
331
/* Field is changed */
335
new_create_list.push_back(def);
342
This field was not dropped and not changed, add it to the list
345
def= new CreateField(field, field);
346
new_create_list.push_back(def);
347
alter_it.rewind(); /* Change default if ALTER */
350
while ((alter= alter_it++))
352
if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
358
if (def->sql_type == DRIZZLE_TYPE_BLOB)
360
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
364
if ((def->def= alter->def))
366
/* Use new default */
367
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
371
def->flags|= NO_DEFAULT_VALUE_FLAG;
379
while ((def= def_it++)) /* Add new columns */
381
if (def->change && ! def->field)
383
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
387
If we have been given a field which has no default value, and is not null then we need to bail.
389
if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
391
alter_info->error_if_not_empty= true;
395
new_create_list.push_back(def);
397
else if (def->after == first_keyword)
399
new_create_list.push_front(def);
406
while ((find= find_it++)) /* Add new columns */
408
if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
414
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
418
find_it.after(def); /* Put element after this */
421
XXX: hack for Bug#28427.
422
If column order has changed, force OFFLINE ALTER Table
423
without querying engine capabilities. If we ever have an
424
engine that supports online ALTER Table CHANGE COLUMN
425
<name> AFTER <name1> (Falcon?), this fix will effectively
426
disable the capability.
427
TODO: detect the situation in compare_tables, behave based
428
on engine capabilities.
430
if (alter_info->build_method == HA_BUILD_ONLINE)
432
my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
436
alter_info->build_method= HA_BUILD_OFFLINE;
440
if (alter_info->alter_list.elements)
442
my_error(ER_BAD_FIELD_ERROR,
444
alter_info->alter_list.head()->name,
445
table->getMutableShare()->getTableName());
449
if (not new_create_list.elements)
451
my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
ER(ER_CANT_REMOVE_ALL_FIELDS),
458
Collect all keys which isn't in drop list. Add only those
459
for which some fields exists.
461
for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
463
char *key_name= key_info->name;
467
while ((drop= drop_it++))
469
if (drop->type == AlterDrop::KEY &&
470
! my_strcasecmp(system_charset_info, key_name, drop->name))
480
KeyPartInfo *key_part= key_info->key_part;
482
for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
484
if (! key_part->field)
485
continue; /* Wrong field (from UNIREG) */
487
const char *key_part_name= key_part->field->field_name;
490
while ((cfield= field_it++))
494
if (not my_strcasecmp(system_charset_info, key_part_name, cfield->change))
497
else if (not my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
502
continue; /* Field is removed */
504
uint32_t key_part_length= key_part->length;
505
if (cfield->field) /* Not new field */
508
If the field can't have only a part used in a key according to its
509
new type, or should not be used partially according to its
510
previous type, or the field length is less than the key part
511
length, unset the key part length.
513
We also unset the key part length if it is the same as the
514
old field's length, so the whole new field will be used.
516
BLOBs may have cfield->length == 0, which is why we test it before
517
checking whether cfield->length < key_part_length (in chars).
519
if (! Field::type_can_have_key_part(cfield->field->type()) ||
520
! Field::type_can_have_key_part(cfield->sql_type) ||
521
(cfield->field->field_length == key_part_length) ||
523
(cfield->length < key_part_length / key_part->field->charset()->mbmaxlen)))
524
key_part_length= 0; /* Use whole field */
526
key_part_length/= key_part->field->charset()->mbmaxlen;
527
key_parts.push_back(new Key_part_spec(cfield->field_name,
528
strlen(cfield->field_name),
531
if (key_parts.elements)
533
key_create_information_st key_create_info= default_key_create_info;
535
Key::Keytype key_type;
537
key_create_info.algorithm= key_info->algorithm;
539
if (key_info->flags & HA_USES_BLOCK_SIZE)
540
key_create_info.block_size= key_info->block_size;
542
if (key_info->flags & HA_USES_COMMENT)
543
key_create_info.comment= key_info->comment;
545
if (key_info->flags & HA_NOSAME)
547
if (is_primary_key_name(key_name))
548
key_type= Key::PRIMARY;
550
key_type= Key::UNIQUE;
554
key_type= Key::MULTIPLE;
557
key= new Key(key_type,
561
test(key_info->flags & HA_GENERATED_KEY),
563
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++)
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
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,
612
if (key->type != Key::FOREIGN_KEY)
613
new_key_list.push_back(key);
615
if (key->name.str && is_primary_key_name(key->name.str))
617
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
if (alter_info->drop_list.elements)
644
my_error(ER_CANT_DROP_FIELD_OR_KEY,
646
alter_info->drop_list.head()->name);
650
if (alter_info->alter_list.elements)
652
my_error(ER_CANT_DROP_FIELD_OR_KEY,
654
alter_info->alter_list.head()->name);
658
if (not table_message.options().has_comment()
659
&& table->getMutableShare()->hasComment())
661
table_options->set_comment(table->getMutableShare()->getComment());
664
if (table->getShare()->getType())
666
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());
674
alter_info->create_list.swap(new_create_list);
675
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
/* table_list should contain just one table */
706
static int discard_or_import_tablespace(Session *session,
707
TableList *table_list,
708
enum tablespace_op_type tablespace_op)
714
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
717
TransactionServices &transaction_services= TransactionServices::singleton();
718
session->set_proc_info("discard_or_import_tablespace");
720
discard= test(tablespace_op == DISCARD_TABLESPACE);
723
We set this flag so that ha_innobase::open and ::external_lock() do
724
not complain when we lock the table
726
session->setDoingTablespaceOperation(true);
727
if (not (table= session->openTableLock(table_list, TL_WRITE)))
729
session->setDoingTablespaceOperation(false);
735
error= table->cursor->ha_discard_or_import_tablespace(discard);
737
session->set_proc_info("end");
742
/* The ALTER Table is always in its own transaction */
743
error= transaction_services.autocommitOrRollback(*session, false);
744
if (not session->endActiveTransaction())
750
write_bin_log(session, *session->getQueryString());
754
(void) transaction_services.autocommitOrRollback(*session, error);
755
session->setDoingTablespaceOperation(false);
763
table->print_error(error, MYF(0));
769
Manages enabling/disabling of indexes for ALTER Table
772
alter_table_manage_keys()
774
indexes_were_disabled Whether the indexes of the from table
776
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
782
static bool alter_table_manage_keys(Session *session,
783
Table *table, int indexes_were_disabled,
784
enum enum_enable_or_disable keys_onoff)
787
switch (keys_onoff) {
789
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
792
if (not indexes_were_disabled)
794
/* fall-through: disabled indexes */
796
error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
799
if (error == HA_ERR_WRONG_COMMAND)
801
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
802
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
803
table->getMutableShare()->getTableName());
808
table->print_error(error, MYF(0));
814
static bool lockTableIfDifferent(Session &session,
815
identifier::Table &original_table_identifier,
816
identifier::Table &new_table_identifier,
819
/* Check that we are not trying to rename to an existing table */
820
if (not (original_table_identifier == new_table_identifier))
822
if (original_table_identifier.isTmp())
825
if (session.find_temporary_table(new_table_identifier))
827
my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
833
if (session.lock_table_name_if_not_cached(new_table_identifier, &name_lock))
840
my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
844
if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
846
/* Table will be closed by Session::executeCommand() */
847
my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
850
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
851
session.unlink_open_table(name_lock);
867
session Thread handle
868
new_db If there is a RENAME clause
869
new_name If there is a RENAME clause
870
create_info Information from the parsing phase about new
872
table_list The table to change.
873
alter_info Lists of fields, keys to be changed, added
875
order_num How many ORDER BY fields has been specified.
876
order List of fields to order_st BY.
877
ignore Whether we have ALTER IGNORE Table
880
This is a veery long function and is everything but the kitchen sink :)
881
It is used to alter a table and not only by ALTER Table but also
882
CREATE|DROP INDEX are mapped on this function.
884
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
885
or both, then this function short cuts its operation by renaming
886
the table and/or enabling/disabling the keys. In this case, the FRM is
887
not changed, directly by alter_table. However, if there is a
888
RENAME + change of a field, or an index, the short cut is not used.
889
See how `create_list` is used to generate the new FRM regarding the
890
structure of the fields. The same is done for the indices of the table.
892
Important is the fact, that this function tries to do as little work as
893
possible, by finding out whether a intermediate table is needed to copy
894
data into and when finishing the altering to use it as the original table.
895
For this reason the function compare_tables() is called, which decides
896
based on all kind of data how similar are the new and the original
904
static bool internal_alter_table(Session *session,
906
identifier::Table &original_table_identifier,
907
identifier::Table &new_table_identifier,
908
HA_CREATE_INFO *create_info,
909
const message::Table &original_proto,
910
message::Table &create_proto,
911
TableList *table_list,
912
AlterInfo *alter_info,
923
if (not original_table_identifier.isValid())
926
if (not new_table_identifier.isValid())
929
session->set_proc_info("init");
931
table->use_all_columns();
933
plugin::StorageEngine *new_engine;
934
plugin::StorageEngine *original_engine;
936
original_engine= table->getMutableShare()->getEngine();
938
if (not create_info->db_type)
940
create_info->db_type= original_engine;
942
new_engine= create_info->db_type;
945
create_proto.set_schema(new_table_identifier.getSchemaName());
946
create_proto.set_type(new_table_identifier.getType());
949
@todo Have a check on the table definition for FK in the future
950
to remove the need for the cursor. (aka can_switch_engines())
952
if (new_engine != original_engine &&
953
not table->cursor->can_switch_engines())
956
my_error(ER_ROW_IS_REFERENCED, MYF(0));
961
if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
964
my_error(ER_ILLEGAL_HA, new_table_identifier);
969
session->set_proc_info("setup");
972
* test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
978
tmp.reset(ALTER_RENAME);
979
tmp.reset(ALTER_KEYS_ONOFF);
980
tmp&= alter_info->flags;
982
if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
984
switch (alter_info->keys_onoff)
991
wait_while_table_is_used() ensures that table being altered is
992
opened only by this thread and that Table::TableShare::version
993
of Table object corresponding to this table is 0.
994
The latter guarantees that no DML statement will open this table
995
until ALTER Table finishes (i.e. until close_thread_tables())
996
while the fact that the table is still open gives us protection
997
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);
1003
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1005
/* 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);
1015
/* COND_refresh will be signaled in close_thread_tables() */
1019
if (error == HA_ERR_WRONG_COMMAND)
1022
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
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 */
1029
Unlike to the above case close_cached_table() below will remove ALL
1030
instances of Table from table cache (it will also remove table lock
1031
held by this thread). So to make actual table renaming and writing
1032
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.
1037
if (not error && not (original_table_identifier == new_table_identifier))
1039
session->set_proc_info("rename");
1041
Then do a 'simple' rename of the table. First we need to close all
1042
instances of 'source' table.
1044
session->close_cached_table(table);
1046
Then, we want check once again that target table does not exist.
1047
Actually the order of these two steps does not matter since
1048
earlier we took name-lock on the target table, so we do them
1049
in this particular order only to be consistent with 5.0, in which
1050
we don't take this name-lock and where this order really matters.
1051
@todo Investigate if we need this access() check at all.
1053
if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1055
my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
1060
if (rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
1067
if (error == HA_ERR_WRONG_COMMAND)
1070
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1077
TransactionServices &transaction_services= TransactionServices::singleton();
1078
transaction_services.allocateNewTransactionId();
1079
write_bin_log(session, *session->getQueryString());
1082
else if (error > EE_OK) // If we have already set the error, we pass along -1
1084
table->print_error(error, MYF(0));
1087
table_list->table= NULL;
1093
/* We have to do full alter table. */
1094
new_engine= create_info->db_type;
1096
if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
1101
set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
1103
alter_info->build_method= HA_BUILD_OFFLINE;
1105
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1107
/* Create a temporary table with the new format */
1109
@note we make an internal temporary table unless the table is a temporary table. In last
1110
case we just use it as is. Neither of these tables require locks in order to be
1113
identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
1115
create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
message::Table::TEMPORARY);
1119
Create a table with a temporary name.
1120
We don't log the statement, it will be logged later.
1122
create_proto.set_name(new_table_as_temporary.getTableName());
1123
create_proto.mutable_engine()->set_name(create_info->db_type->getName());
1125
error= create_table(session,
1126
new_table_as_temporary,
1127
create_info, create_proto, alter_info, true, 0, false);
1134
/* Open the table so we need to copy the data to it. */
1135
Table *new_table= open_alter_table(session, table, new_table_as_temporary);
1140
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1144
/* Copy the data if necessary. */
1146
/* We must not ignore bad input! */
1147
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; // calc cuted fields
1148
session->cuted_fields= 0L;
1149
session->set_proc_info("copy to tmp table");
1152
/* We don't want update TIMESTAMP fields during ALTER Table. */
1153
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1154
new_table->next_number_field= new_table->found_next_number_field;
1155
error= copy_data_between_tables(session,
1158
alter_info->create_list,
1164
alter_info->keys_onoff,
1165
alter_info->error_if_not_empty);
1167
/* We must not ignore bad input! */
1168
assert(session->count_cuted_fields == CHECK_FIELD_ERROR_FOR_NULL);
1171
/* Now we need to resolve what just happened with the data copy. */
1177
No default value was provided for new fields.
1179
if (alter_info->error_if_not_empty && session->row_count)
1181
my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
1184
if (original_table_identifier.isTmp())
1188
/* close_temporary_table() frees the new_table pointer. */
1189
session->close_temporary_table(new_table);
1193
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1203
Close the intermediate table that will be the new table.
1204
Note that MERGE tables do not have their children attached here.
1206
new_table->intern_close_table();
1207
if (new_table->hasShare())
1209
delete new_table->getMutableShare();
1215
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1217
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1222
// Temporary table and success
1223
else if (original_table_identifier.isTmp())
1225
/* Close lock if this is a transactional table */
1228
session->unlockTables(session->lock);
1232
/* Remove link to old table and rename the new one */
1233
session->close_temporary_table(table);
1235
/* Should pass the 'new_name' as we store table name in the cache */
1236
new_table->getMutableShare()->setIdentifier(new_table_identifier);
1238
new_table_identifier.setPath(new_table_as_temporary.getPath());
1240
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1245
// Normal table success
1251
Close the intermediate table that will be the new table.
1252
Note that MERGE tables do not have their children attached here.
1254
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);
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);
1344
session->set_proc_info("end");
1346
write_bin_log(session, *session->getQueryString());
1347
table_list->table= NULL;
1351
* Field::store() may have called my_error(). If this is
1352
* the case, we must not send an ok packet, since
1353
* Diagnostics_area::is_set() will fail an assert.
1355
if (session->is_error())
1357
/* my_error() was called. Return true (which means error...) */
1361
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1362
(ulong) (copied + deleted), (ulong) deleted,
1363
(ulong) session->cuted_fields);
1364
session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
session->some_tables_deleted= false;
1370
bool alter_table(Session *session,
1371
identifier::Table &original_table_identifier,
1372
identifier::Table &new_table_identifier,
1373
HA_CREATE_INFO *create_info,
1374
const message::Table &original_proto,
1375
message::Table &create_proto,
1376
TableList *table_list,
1377
AlterInfo *alter_info,
1385
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
1387
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1388
return discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
1391
session->set_proc_info("init");
1393
if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
1396
session->set_proc_info("gained write lock on table");
1399
Check that we are not trying to rename to an existing table,
1400
if one existed we get a lock, if we can't we error.
1403
Table *name_lock= NULL;
1405
if (not lockTableIfDifferent(*session, original_table_identifier, new_table_identifier, name_lock))
1410
error= internal_alter_table(session,
1412
original_table_identifier,
1413
new_table_identifier,
1425
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1426
session->unlink_open_table(name_lock);
1435
copy_data_between_tables(Session *session,
1436
Table *from, Table *to,
1437
List<CreateField> &create,
1439
uint32_t order_num, Order *order,
1442
enum enum_enable_or_disable keys_onoff,
1443
bool error_if_not_empty)
1446
CopyField *copy,*copy_end;
1447
ulong found_count,delete_count;
1449
SortField *sortorder;
1453
List<Item> all_fields;
1454
ha_rows examined_rows;
1455
bool auto_increment_field_copied= 0;
1456
uint64_t prev_insert_id;
1459
Turn off recovery logging since rollback of an alter table is to
1460
delete the new table so there is no need to log the changes to it.
1462
This needs to be done before external_lock
1464
TransactionServices &transaction_services= TransactionServices::singleton();
1469
* Since open_temporary_table() doesn't invoke lockTables(), we
1470
* don't get the usual automatic call to StorageEngine::startStatement(), so
1471
* we manually call it here...
1473
to->getMutableShare()->getEngine()->startStatement(session);
1475
if (!(copy= new CopyField[to->getShare()->sizeFields()]))
1478
if (to->cursor->ha_external_lock(session, F_WRLCK))
1481
/* We need external lock before we can disable/enable keys */
1482
alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1484
/* We can abort alter table for any table type */
1485
session->setAbortOnWarning(not ignore);
1487
from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1490
List_iterator<CreateField> it(create);
1493
for (Field **ptr= to->getFields(); *ptr ; ptr++)
1498
if (*ptr == to->next_number_field)
1499
auto_increment_field_copied= true;
1501
(copy_end++)->set(*ptr,def->field,0);
1506
found_count=delete_count=0;
1512
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
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,
1524
FileSort filesort(*session);
1525
from->sort.io_cache= new internal::IO_CACHE;
1528
tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1529
tables.alias= const_cast<char *>(tables.getTableName());
1530
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1533
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1534
setup_order(session, session->lex->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);
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;
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);
1650
from->free_io_cache();
1651
*copied= found_count;
1652
*deleted=delete_count;
1653
to->cursor->ha_release_auto_increment();
1655
if (to->cursor->ha_external_lock(session, F_UNLCK))
1660
return(error > 0 ? -1 : 0);
1663
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1667
/* Open the table so we need to copy the data to it. */
1668
if (table->getShare()->getType())
1671
tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1672
tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1673
tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
1675
/* Table is in session->temporary_tables */
1676
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
1680
/* Open our intermediate table */
1681
new_table= session->open_temporary_table(identifier, false);
1687
} /* namespace drizzled */