16
16
/* drop and alter of tables */
19
#include <plugin/myisam/myisam.h>
20
#include <drizzled/show.h>
21
#include <drizzled/error.h>
22
#include <drizzled/gettext.h>
23
#include <drizzled/data_home.h>
24
#include <drizzled/sql_parse.h>
25
#include <drizzled/my_hash.h>
26
#include <drizzled/sql_lex.h>
27
#include <drizzled/session.h>
28
#include <drizzled/sql_base.h>
29
#include "drizzled/strfunc.h"
30
#include <drizzled/db.h>
31
#include <drizzled/lock.h>
32
#include <drizzled/unireg.h>
33
#include <drizzled/item/int.h>
34
#include <drizzled/item/empty_string.h>
35
#include <drizzled/transaction_services.h>
36
#include "drizzled/transaction_services.h"
37
#include <drizzled/table_proto.h>
38
#include <drizzled/plugin/client.h>
39
#include <drizzled/identifier.h>
40
#include "drizzled/internal/m_string.h"
41
#include "drizzled/global_charset_info.h"
42
#include "drizzled/charset.h"
45
#include "drizzled/statement/alter_table.h"
46
#include "drizzled/sql_table.h"
47
#include "drizzled/pthread_globals.h"
52
#include <boost/unordered_set.hpp>
59
extern pid_t current_pid;
61
bool is_primary_key(KeyInfo *key_info)
63
static const char * primary_key_name="PRIMARY";
64
return (strcmp(key_info->name, primary_key_name)==0);
67
const char* is_primary_key_name(const char* key_name)
69
static const char * primary_key_name="PRIMARY";
70
if (strcmp(key_name, primary_key_name)==0)
76
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
77
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
79
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
84
If the table character set was not given explicitly,
85
let's fetch the database default character set and
86
apply it to the table.
88
SchemaIdentifier identifier(db);
89
if (create_info->default_table_charset == NULL)
90
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
18
#include "mysql_priv.h"
24
int creating_table= 0; // How many mysql_create_table are running
26
const char *primary_key_name="PRIMARY";
28
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
29
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
30
static int copy_data_between_tables(TABLE *from,TABLE *to,
31
List<Create_field> &create, bool ignore,
32
uint order_num, ORDER *order,
33
ha_rows *copied,ha_rows *deleted,
34
enum enum_enable_or_disable keys_onoff,
35
bool error_if_not_empty);
37
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
38
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
40
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
41
Alter_info *alter_info,
44
handler *file, KEY **key_info_buffer,
45
uint *key_count, int select_field_count);
47
mysql_prepare_alter_table(THD *thd, TABLE *table,
48
HA_CREATE_INFO *create_info,
49
Alter_info *alter_info);
53
/* Wait until we get a 'mysql_kill' signal */
55
static void wait_for_kill_signal(THD *thd)
57
while (thd->killed == 0)
59
// Reset signal and continue as if nothing happend
60
thd->killed= THD::NOT_KILLED;
66
Translate a file name to a table name (WL #1324).
69
filename_to_tablename()
70
from The file name in my_charset_filename.
71
to OUT The table name in system_charset_info.
72
to_length The size of the table name buffer.
78
uint filename_to_tablename(const char *from, char *to, uint to_length)
82
DBUG_ENTER("filename_to_tablename");
83
DBUG_PRINT("enter", ("from '%s'", from));
85
if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
87
/* Temporary table name. */
88
res= (strnmov(to, from, to_length) - to);
92
res= strconvert(&my_charset_filename, from,
93
system_charset_info, to, to_length, &errors);
94
if (errors) // Old 5.0 name
96
res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) -
98
sql_print_error("Invalid (old?) table or database name '%s'", from);
100
TODO: add a stored procedure for fix table and database names,
101
and mention its name in error log.
106
DBUG_PRINT("exit", ("to '%s'", to));
112
Translate a table name to a file name (WL #1324).
115
tablename_to_filename()
116
from The table name in system_charset_info.
117
to OUT The file name in my_charset_filename.
118
to_length The size of the file name buffer.
124
uint tablename_to_filename(const char *from, char *to, uint to_length)
127
DBUG_ENTER("tablename_to_filename");
128
DBUG_PRINT("enter", ("from '%s'", from));
130
if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
131
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
132
DBUG_RETURN((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
134
(from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
135
length= strconvert(system_charset_info, from,
136
&my_charset_filename, to, to_length, &errors);
137
if (check_if_legal_tablename(to) &&
138
length + 4 < to_length)
140
memcpy(to + length, "@@@", 4);
143
DBUG_PRINT("exit", ("to '%s'", to));
149
Creates path to a file: mysql_data_dir/db/table.ext
152
build_table_filename()
153
buff Where to write result in my_charset_filename.
154
This may be the same as table_name.
156
db Database name in system_charset_info.
157
table_name Table name in system_charset_info.
159
flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
160
table_name is temporary, do not change.
164
Uses database and table name, and extension to create
165
a file name in mysql_data_dir. Database and table
166
names are converted from system_charset_info into "fscs".
167
Unless flags indicate a temporary table name.
168
'db' is always converted.
169
'ext' is not converted.
171
The conversion suppression is required for ALTER TABLE. This
172
statement creates intermediate tables. These are regular
173
(non-temporary) tables with a temporary name. Their path names must
174
be derivable from the table name. So we cannot use
175
build_tmptable_filename() for them.
181
uint build_table_filename(char *buff, size_t bufflen, const char *db,
182
const char *table_name, const char *ext, uint flags)
184
char dbbuff[FN_REFLEN];
185
char tbbuff[FN_REFLEN];
186
DBUG_ENTER("build_table_filename");
187
DBUG_PRINT("enter", ("db: '%s' table_name: '%s' ext: '%s' flags: %x",
188
db, table_name, ext, flags));
190
if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
191
strnmov(tbbuff, table_name, sizeof(tbbuff));
193
VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
195
VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
197
char *end = buff + bufflen;
198
/* Don't add FN_ROOTDIR if mysql_data_home already includes it */
199
char *pos = strnmov(buff, mysql_data_home, bufflen);
200
int rootdir_len= strlen(FN_ROOTDIR);
201
if (pos - rootdir_len >= buff &&
202
memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
203
pos= strnmov(pos, FN_ROOTDIR, end - pos);
204
pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
206
unpack_dirname(buff, buff);
209
pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
211
DBUG_PRINT("exit", ("buff: '%s'", buff));
212
DBUG_RETURN(pos - buff);
217
Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
220
build_tmptable_filename()
221
thd The thread handle.
222
buff Where to write result in my_charset_filename.
227
Uses current_pid, thread_id, and tmp_table counter to create
228
a file name in mysql_tmpdir.
234
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
236
DBUG_ENTER("build_tmptable_filename");
238
char *p= strnmov(buff, mysql_tmpdir, bufflen);
239
snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
240
tmp_file_prefix, current_pid,
241
thd->thread_id, thd->tmp_table++, reg_ext);
243
if (lower_case_table_names)
245
/* Convert all except tmpdir to lower case */
246
my_casedn_str(files_charset_info, p);
249
uint length= unpack_filename(buff, buff);
250
DBUG_PRINT("exit", ("buff: '%s'", buff));
255
--------------------------------------------------------------------------
260
This module is used to ensure that we can recover from crashes that occur
261
in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
262
We need to ensure that both t1 and t2 are dropped and not only t1 and
263
also that each table drop is entirely done and not "half-baked".
265
To support this we create log entries for each meta-data statement in the
266
ddl log while we are executing. These entries are dropped when the
267
operation is completed.
269
At recovery those entries that were not completed will be executed.
271
There is only one ddl log in the system and it is protected by a mutex
272
and there is a global struct that contains information about its current
276
First version written in 2006 by Mikael Ronstrom
277
--------------------------------------------------------------------------
281
struct st_global_ddl_log
284
We need to adjust buffer size to be able to handle downgrades/upgrades
285
where IO_SIZE has changed. We'll set the buffer size such that we can
286
handle that the buffer size was upto 4 times bigger in the version
287
that wrote the DDL log.
289
char file_entry_buf[4*IO_SIZE];
290
char file_name_str[FN_REFLEN];
292
DDL_LOG_MEMORY_ENTRY *first_free;
293
DDL_LOG_MEMORY_ENTRY *first_used;
301
st_global_ddl_log() : inited(false), do_release(false) {}
304
st_global_ddl_log global_ddl_log;
306
pthread_mutex_t LOCK_gdl;
308
#define DDL_LOG_ENTRY_TYPE_POS 0
309
#define DDL_LOG_ACTION_TYPE_POS 1
310
#define DDL_LOG_PHASE_POS 2
311
#define DDL_LOG_NEXT_ENTRY_POS 4
312
#define DDL_LOG_NAME_POS 8
314
#define DDL_LOG_NUM_ENTRY_POS 0
315
#define DDL_LOG_NAME_LEN_POS 4
316
#define DDL_LOG_IO_SIZE_POS 8
319
Read one entry from ddl log file
321
read_ddl_log_file_entry()
322
entry_no Entry number to read
328
static bool read_ddl_log_file_entry(uint entry_no)
331
File file_id= global_ddl_log.file_id;
332
uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
333
ssize_t io_size= (ssize_t)global_ddl_log.io_size;
334
DBUG_ENTER("read_ddl_log_file_entry");
336
if (pread(file_id, file_entry_buf, io_size, io_size * entry_no) != io_size)
343
Write one entry from ddl log file
345
write_ddl_log_file_entry()
346
entry_no Entry number to read
352
static bool write_ddl_log_file_entry(uint entry_no)
355
File file_id= global_ddl_log.file_id;
356
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
357
DBUG_ENTER("write_ddl_log_file_entry");
359
if (pwrite(file_id, (uchar*)file_entry_buf,
360
IO_SIZE, IO_SIZE * entry_no) != IO_SIZE)
369
write_ddl_log_header()
375
static bool write_ddl_log_header()
379
DBUG_ENTER("write_ddl_log_header");
381
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
382
global_ddl_log.num_entries);
384
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
387
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
389
if (write_ddl_log_file_entry(0UL))
391
sql_print_error("Error writing ddl log header");
394
VOID(sync_ddl_log());
400
Create ddl log file name
402
create_ddl_log_file_name()
403
file_name Filename setup
408
static inline void create_ddl_log_file_name(char *file_name)
410
strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
415
Read header of ddl log file
417
read_ddl_log_header()
419
> 0 Last entry in ddl log
420
0 No entries in ddl log
422
When we read the ddl log header we get information about maximum sizes
423
of names in the ddl log and we also get information about the number
424
of entries in the ddl log.
427
static uint read_ddl_log_header()
429
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
430
char file_name[FN_REFLEN];
432
bool successful_open= false;
433
DBUG_ENTER("read_ddl_log_header");
435
create_ddl_log_file_name(file_name);
436
if ((global_ddl_log.file_id= my_open(file_name,
437
O_RDWR | O_BINARY, MYF(0))) >= 0)
439
if (read_ddl_log_file_entry(0UL))
441
/* Write message into error log */
442
sql_print_error("Failed to read ddl log file in recovery");
445
successful_open= true;
447
entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
448
global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
451
global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
452
DBUG_ASSERT(global_ddl_log.io_size <=
453
sizeof(global_ddl_log.file_entry_buf));
459
global_ddl_log.first_free= NULL;
460
global_ddl_log.first_used= NULL;
461
global_ddl_log.num_entries= 0;
462
VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
463
global_ddl_log.do_release= true;
464
DBUG_RETURN(entry_no);
472
read_entry Number of entry to read
473
out:entry_info Information from entry
478
Read a specified entry in the ddl log
481
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
483
char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
486
DBUG_ENTER("read_ddl_log_entry");
488
if (read_ddl_log_file_entry(read_entry))
492
ddl_log_entry->entry_pos= read_entry;
493
single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
494
ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
495
single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
496
ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
497
ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
498
ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
499
ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
500
inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
501
ddl_log_entry->from_name= &file_entry_buf[inx];
502
inx+= global_ddl_log.name_len;
503
ddl_log_entry->handler_name= &file_entry_buf[inx];
514
Write the header of the ddl log file and length of names. Also set
515
number of entries to zero.
522
static bool init_ddl_log()
524
char file_name[FN_REFLEN];
525
DBUG_ENTER("init_ddl_log");
527
if (global_ddl_log.inited)
530
global_ddl_log.io_size= IO_SIZE;
531
create_ddl_log_file_name(file_name);
532
if ((global_ddl_log.file_id= my_create(file_name,
534
O_RDWR | O_TRUNC | O_BINARY,
537
/* Couldn't create ddl log file, this is serious error */
538
sql_print_error("Failed to open ddl log file");
541
global_ddl_log.inited= true;
542
if (write_ddl_log_header())
544
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
545
global_ddl_log.inited= false;
555
Execute one action in a ddl log entry
557
execute_ddl_log_action()
558
ddl_log_entry Information in action entry to execute
564
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
566
bool frm_action= false;
567
LEX_STRING handler_name;
571
char to_path[FN_REFLEN];
572
char from_path[FN_REFLEN];
574
DBUG_ENTER("execute_ddl_log_action");
576
if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
580
handler_name.str= (char*)ddl_log_entry->handler_name;
581
handler_name.length= strlen(ddl_log_entry->handler_name);
582
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
583
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
587
plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
590
my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
593
hton= plugin_data(plugin, handlerton*);
594
file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
597
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
601
switch (ddl_log_entry->action_type)
603
case DDL_LOG_REPLACE_ACTION:
604
case DDL_LOG_DELETE_ACTION:
606
if (ddl_log_entry->phase == 0)
610
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
611
if ((error= my_delete(to_path, MYF(MY_WME))))
613
if (my_errno != ENOENT)
619
if ((error= file->ha_delete_table(ddl_log_entry->name)))
621
if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
625
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
627
VOID(sync_ddl_log());
629
if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
632
DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
634
Fall through and perform the rename action of the replace
635
action. We have already indicated the success of the delete
636
action in the log entry by stepping up the phase.
639
case DDL_LOG_RENAME_ACTION:
644
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
645
strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
646
if (my_rename(from_path, to_path, MYF(MY_WME)))
651
if (file->ha_rename_table(ddl_log_entry->from_name,
652
ddl_log_entry->name))
655
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
657
VOID(sync_ddl_log());
667
free_root(&mem_root, MYF(0));
673
Get a free entry in the ddl log
675
get_free_ddl_log_entry()
676
out:active_entry A ddl log memory entry returned
682
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
685
DDL_LOG_MEMORY_ENTRY *used_entry;
686
DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
687
DBUG_ENTER("get_free_ddl_log_entry");
689
if (global_ddl_log.first_free == NULL)
691
if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
692
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
694
sql_print_error("Failed to allocate memory for ddl log free list");
697
global_ddl_log.num_entries++;
698
used_entry->entry_pos= global_ddl_log.num_entries;
703
used_entry= global_ddl_log.first_free;
704
global_ddl_log.first_free= used_entry->next_log_entry;
705
*write_header= false;
708
Move from free list to used list
710
used_entry->next_log_entry= first_used;
711
used_entry->prev_log_entry= NULL;
712
global_ddl_log.first_used= used_entry;
714
first_used->prev_log_entry= used_entry;
716
*active_entry= used_entry;
722
External interface methods for the DDL log Module
723
---------------------------------------------------
728
write_ddl_log_entry()
729
ddl_log_entry Information about log entry
730
out:entry_written Entry information written into
737
A careful write of the ddl log is performed to ensure that we can
738
handle crashes occurring during CREATE and ALTER TABLE processing.
741
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
742
DDL_LOG_MEMORY_ENTRY **active_entry)
744
bool error, write_header;
745
DBUG_ENTER("write_ddl_log_entry");
751
global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
752
(char)DDL_LOG_ENTRY_CODE;
753
global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
754
(char)ddl_log_entry->action_type;
755
global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
756
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
757
ddl_log_entry->next_entry);
758
DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_LEN);
759
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
760
ddl_log_entry->name, FN_LEN - 1);
761
if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
762
ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
764
DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_LEN);
765
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
766
ddl_log_entry->from_name, FN_LEN - 1);
769
global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
770
DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_LEN);
771
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
772
ddl_log_entry->handler_name, FN_LEN - 1);
773
if (get_free_ddl_log_entry(active_entry, &write_header))
778
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
781
sql_print_error("Failed to write entry_no = %u",
782
(*active_entry)->entry_pos);
784
if (write_header && !error)
786
VOID(sync_ddl_log());
787
if (write_ddl_log_header())
791
release_ddl_log_memory_entry(*active_entry);
797
Write final entry in the ddl log
799
write_execute_ddl_log_entry()
800
first_entry First entry in linked list of entries
801
to execute, if 0 = NULL it means that
802
the entry is removed and the entries
803
are put into the free list.
804
complete Flag indicating we are simply writing
805
info about that entry has been completed
806
in:out:active_entry Entry to execute, 0 = NULL if the entry
807
is written first time and needs to be
808
returned. In this case the entry written
809
is returned in this parameter
815
This is the last write in the ddl log. The previous log entries have
816
already been written but not yet synched to disk.
817
We write a couple of log entries that describes action to perform.
818
This entries are set-up in a linked list, however only when a first
819
execute entry is put as the first entry these will be executed.
820
This routine writes this first
823
bool write_execute_ddl_log_entry(uint first_entry,
825
DDL_LOG_MEMORY_ENTRY **active_entry)
827
bool write_header= false;
828
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
829
DBUG_ENTER("write_execute_ddl_log_entry");
838
We haven't synched the log entries yet, we synch them now before
839
writing the execute entry. If complete is true we haven't written
840
any log entries before, we are only here to write the execute
841
entry to indicate it is done.
843
VOID(sync_ddl_log());
844
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
847
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
848
file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
849
file_entry_buf[DDL_LOG_PHASE_POS]= 0;
850
int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
851
file_entry_buf[DDL_LOG_NAME_POS]= 0;
852
file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
853
file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
854
if (!(*active_entry))
856
if (get_free_ddl_log_entry(active_entry, &write_header))
861
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
863
sql_print_error("Error writing execute entry in ddl log");
864
release_ddl_log_memory_entry(*active_entry);
867
VOID(sync_ddl_log());
870
if (write_ddl_log_header())
872
release_ddl_log_memory_entry(*active_entry);
881
For complex rename operations we need to deactivate individual entries.
883
deactivate_ddl_log_entry()
884
entry_no Entry position of record to change
889
During replace operations where we start with an existing table called
890
t1 and a replacement table called t1#temp or something else and where
891
we want to delete t1 and rename t1#temp to t1 this is not possible to
892
do in a safe manner unless the ddl log is informed of the phases in
895
Delete actions are 1-phase actions that can be ignored immediately after
897
Rename actions from x to y is also a 1-phase action since there is no
898
interaction with any other handlers named x and y.
899
Replace action where drop y and x -> y happens needs to be a two-phase
900
action. Thus the first phase will drop y and the second phase will
904
bool deactivate_ddl_log_entry(uint entry_no)
906
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
907
DBUG_ENTER("deactivate_ddl_log_entry");
909
if (!read_ddl_log_file_entry(entry_no))
911
if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
913
if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
914
file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
915
(file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
916
file_entry_buf[DDL_LOG_PHASE_POS] == 1))
917
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
918
else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
920
DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
921
file_entry_buf[DDL_LOG_PHASE_POS]= 1;
927
if (write_ddl_log_file_entry(entry_no))
929
sql_print_error("Error in deactivating log entry. Position = %u",
937
sql_print_error("Failed in reading entry before deactivating it");
956
DBUG_ENTER("sync_ddl_log");
958
if ((!global_ddl_log.recovery_phase) &&
963
if (my_sync(global_ddl_log.file_id, MYF(0)))
965
/* Write to error log */
966
sql_print_error("Failed to sync ddl log");
974
Release a log memory entry
976
release_ddl_log_memory_entry()
977
log_memory_entry Log memory entry to release
982
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
984
DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
985
DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
986
DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
987
DBUG_ENTER("release_ddl_log_memory_entry");
989
global_ddl_log.first_free= log_entry;
990
log_entry->next_log_entry= first_free;
993
prev_log_entry->next_log_entry= next_log_entry;
995
global_ddl_log.first_used= next_log_entry;
997
next_log_entry->prev_log_entry= prev_log_entry;
1003
Execute one entry in the ddl log. Executing an entry means executing
1004
a linked list of actions.
1006
execute_ddl_log_entry()
1007
first_entry Reference to first action in entry
1013
bool execute_ddl_log_entry(THD *thd, uint first_entry)
1015
DDL_LOG_ENTRY ddl_log_entry;
1016
uint read_entry= first_entry;
1017
DBUG_ENTER("execute_ddl_log_entry");
1019
pthread_mutex_lock(&LOCK_gdl);
1022
if (read_ddl_log_entry(read_entry, &ddl_log_entry))
1024
/* Write to error log and continue with next log entry */
1025
sql_print_error("Failed to read entry = %u from ddl log",
1029
DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
1030
ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
1032
if (execute_ddl_log_action(thd, &ddl_log_entry))
1034
/* Write to error log and continue with next log entry */
1035
sql_print_error("Failed to execute action for entry = %u from ddl log",
1039
read_entry= ddl_log_entry.next_entry;
1040
} while (read_entry);
1041
pthread_mutex_unlock(&LOCK_gdl);
1054
static void close_ddl_log()
1056
DBUG_ENTER("close_ddl_log");
1057
if (global_ddl_log.file_id >= 0)
1059
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
1060
global_ddl_log.file_id= (File) -1;
1067
Execute the ddl log at recovery of MySQL Server
1069
execute_ddl_log_recovery()
1074
void execute_ddl_log_recovery()
1076
uint num_entries, i;
1078
DDL_LOG_ENTRY ddl_log_entry;
1079
char file_name[FN_REFLEN];
1080
DBUG_ENTER("execute_ddl_log_recovery");
1083
Initialise global_ddl_log struct
1085
bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
1086
global_ddl_log.inited= false;
1087
global_ddl_log.recovery_phase= true;
1088
global_ddl_log.io_size= IO_SIZE;
1089
global_ddl_log.file_id= (File) -1;
1092
To be able to run this from boot, we allocate a temporary THD
1096
thd->thread_stack= (char*) &thd;
1097
thd->store_globals();
1099
num_entries= read_ddl_log_header();
1100
for (i= 1; i < num_entries + 1; i++)
1102
if (read_ddl_log_entry(i, &ddl_log_entry))
1104
sql_print_error("Failed to read entry no = %u from ddl log",
1108
if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
1110
if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
1112
/* Real unpleasant scenario but we continue anyways. */
1118
create_ddl_log_file_name(file_name);
1119
VOID(my_delete(file_name, MYF(0)));
1120
global_ddl_log.recovery_phase= false;
1122
/* Remember that we don't have a THD */
1123
my_pthread_setspecific_ptr(THR_THD, 0);
1129
Release all memory allocated to the ddl log
1136
void release_ddl_log()
1138
DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
1139
DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
1140
DBUG_ENTER("release_ddl_log");
1142
if (!global_ddl_log.do_release)
1145
pthread_mutex_lock(&LOCK_gdl);
1148
DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
1149
my_free(used_list, MYF(0));
1154
DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
1155
my_free(free_list, MYF(0));
1159
global_ddl_log.inited= 0;
1160
pthread_mutex_unlock(&LOCK_gdl);
1161
VOID(pthread_mutex_destroy(&LOCK_gdl));
1162
global_ddl_log.do_release= false;
1168
---------------------------------------------------------------------------
1171
--------------------
1173
---------------------------------------------------------------------------
1181
clear_error is clear_error to be called
97
1182
query Query to log
98
1183
query_length Length of query
2073
bool mysql_create_like_table(Session* session,
2074
TableIdentifier &destination_identifier,
2075
TableList* table, TableList* src_table,
2076
message::Table &create_table_proto,
2077
bool is_if_not_exists,
4024
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
4025
HA_CREATE_INFO *create_info)
4027
TABLE *name_lock= 0;
4028
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
4029
uint dst_path_length;
2080
4030
char *db= table->db;
2081
4031
char *table_name= table->table_name;
2082
4033
bool res= true;
4035
DBUG_ENTER("mysql_create_like_table");
4038
/* CREATE TABLE ... LIKE is not allowed for views. */
4039
src_table->required_type= FRMTYPE_TABLE;
2086
4042
By opening source table we guarantee that it exists and no concurrent
2087
4043
DDL operation will mess with it. Later we also take an exclusive
2088
name-lock on target table name, which makes copying of .frm cursor,
2089
call to plugin::StorageEngine::createTable() and binlogging atomic
2090
against concurrent DML and DDL operations on target table.
2091
Thus by holding both these "locks" we ensure that our statement is
2092
properly isolated from all concurrent operations which matter.
4044
name-lock on target table name, which makes copying of .frm file,
4045
call to ha_create_table() and binlogging atomic against concurrent DML
4046
and DDL operations on target table. Thus by holding both these "locks"
4047
we ensure that our statement is properly isolated from all concurrent
4048
operations which matter.
2094
if (session->open_tables_from_list(&src_table, ¬_used))
2097
TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2098
src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
4050
if (open_tables(thd, &src_table, ¬_used, 0))
4053
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
4055
DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
2103
4058
Check that destination tables does not exist. Note that its name
2104
4059
was already checked when it was added to the table list.
2106
For temporary tables we don't aim to grab locks.
2108
bool table_exists= false;
2109
if (destination_identifier.isTmp())
2111
if (session->find_temporary_table(db, table_name))
2117
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2118
src_identifier, is_engine_set);
2119
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2121
(void) session->rm_temporary_table(destination_identifier, true);
2123
else if (not session->open_temporary_table(destination_identifier))
2125
// We created, but we can't open... also, a hack.
2126
(void) session->rm_temporary_table(destination_identifier, true);
2134
else // Standard table which will require locks.
2136
Table *name_lock= 0;
2138
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2142
boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2143
session->unlink_open_table(name_lock);
2153
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2157
else // Otherwise we create the table
2161
boost::mutex::scoped_lock lock(LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2162
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2163
src_identifier, is_engine_set);
2166
// So we blew the creation of the table, and we scramble to clean up
2167
// anything that might have been created (read... it is a hack)
2168
if (not was_created)
2170
quick_rm_table(*session, destination_identifier);
4061
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
4063
if (find_temporary_table(thd, db, table_name))
4065
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
4066
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
4070
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
4074
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
4075
db, table_name, reg_ext, 0);
4076
if (!access(dst_path, F_OK))
4080
DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
4083
Create a new table by copying from source table
4085
Altough exclusive name-lock on target table protects us from concurrent
4086
DML and DDL operations on it we still want to wrap .FRM creation and call
4087
to ha_create_table() in critical section protected by LOCK_open in order
4088
to provide minimal atomicity against operations which disregard name-locks,
4089
like I_S implementation, for example. This is a temporary and should not
4090
be copied. Instead we should fix our code to always honor name-locks.
4092
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
4093
during the call to ha_create_table(). See bug #28614 for more info.
4095
VOID(pthread_mutex_lock(&LOCK_open));
4096
if (src_table->schema_table)
4098
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
4100
VOID(pthread_mutex_unlock(&LOCK_open));
4104
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
4106
if (my_errno == ENOENT)
4107
my_error(ER_BAD_DB_ERROR,MYF(0),db);
4109
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
4110
VOID(pthread_mutex_unlock(&LOCK_open));
4115
As mysql_truncate don't work on a new table at this stage of
4116
creation, instead create the table directly (for both normal
4117
and temporary tables).
4119
DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
4121
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
4122
if (thd->variables.keep_files_on_create)
4123
create_info->options|= HA_CREATE_KEEP_FILES;
4124
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
4125
VOID(pthread_mutex_unlock(&LOCK_open));
4127
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
4129
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
4132
(void) rm_temporary_table(create_info->db_type,
4133
dst_path, false); /* purecov: inspected */
4134
goto err; /* purecov: inspected */
4139
(void) quick_rm_table(create_info->db_type, db,
4140
table_name, 0); /* purecov: inspected */
4141
goto err; /* purecov: inspected */
4144
DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
4147
We have to write the query before we unlock the tables.
4149
if (thd->current_stmt_binlog_row_based)
4152
Since temporary tables are not replicated under row-based
4153
replication, CREATE TABLE ... LIKE ... needs special
4154
treatement. We have four cases to consider, according to the
4155
following decision table:
4157
==== ========= ========= ==============================
4158
Case Target Source Write to binary log
4159
==== ========= ========= ==============================
4160
1 normal normal Original statement
4161
2 normal temporary Generated statement
4162
3 temporary normal Nothing
4163
4 temporary temporary Nothing
4164
==== ========= ========= ==============================
4166
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
4168
if (src_table->table->s->tmp_table) // Case 2
4171
String query(buf, sizeof(buf), system_charset_info);
4172
query.length(0); // Have to zero it since constructor doesn't
4176
Here we open the destination table, on which we already have
4177
name-lock. This is needed for store_create_info() to work.
4178
The table will be closed by unlink_open_table() at the end
4181
table->table= name_lock;
4182
VOID(pthread_mutex_lock(&LOCK_open));
4183
if (reopen_name_locked_table(thd, table, false))
4185
VOID(pthread_mutex_unlock(&LOCK_open));
4188
VOID(pthread_mutex_unlock(&LOCK_open));
4190
IF_DBUG(int result=) store_create_info(thd, table, &query,
4193
DBUG_ASSERT(result == 0); // store_create_info() always return 0
4194
write_bin_log(thd, true, query.ptr(), query.length());
4197
write_bin_log(thd, true, thd->query, thd->query_length);
4200
Case 3 and 4 does nothing under RBR
4204
write_bin_log(thd, true, thd->query, thd->query_length);
4210
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
4212
char warn_buff[MYSQL_ERRMSG_SIZE];
4213
snprintf(warn_buff, sizeof(warn_buff),
4214
ER(ER_TABLE_EXISTS_ERROR), table_name);
4215
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4216
ER_TABLE_EXISTS_ERROR,warn_buff);
4220
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
4225
pthread_mutex_lock(&LOCK_open);
4226
unlink_open_table(thd, name_lock, false);
4227
pthread_mutex_unlock(&LOCK_open);
4233
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
4235
thr_lock_type lock_type = TL_READ_NO_INSERT;
4237
DBUG_ENTER("mysql_analyze_table");
4238
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
4239
"analyze", lock_type, 1, 0, 0, 0,
4240
&handler::ha_analyze));
4244
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
4246
thr_lock_type lock_type = TL_READ_NO_INSERT;
4248
DBUG_ENTER("mysql_check_table");
4249
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
4251
0, 0, HA_OPEN_FOR_REPAIR, 0,
4252
&handler::ha_check));
4256
/* table_list should contain just one table */
4258
mysql_discard_or_import_tablespace(THD *thd,
4259
TABLE_LIST *table_list,
4260
enum tablespace_op_type tablespace_op)
4265
DBUG_ENTER("mysql_discard_or_import_tablespace");
4268
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
4272
thd_proc_info(thd, "discard_or_import_tablespace");
4274
discard= test(tablespace_op == DISCARD_TABLESPACE);
4277
We set this flag so that ha_innobase::open and ::external_lock() do
4278
not complain when we lock the table
4280
thd->tablespace_op= true;
4281
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
4283
thd->tablespace_op=false;
4287
error= table->file->ha_discard_or_import_tablespace(discard);
4289
thd_proc_info(thd, "end");
4294
/* The ALTER TABLE is always in its own transaction */
4295
error = ha_autocommit_or_rollback(thd, 0);
4296
if (end_active_trans(thd))
4300
write_bin_log(thd, false, thd->query, thd->query_length);
4303
ha_autocommit_or_rollback(thd, error);
4304
thd->tablespace_op=false;
4312
table->file->print_error(error, MYF(0));
4318
Copy all changes detected by parser to the HA_ALTER_FLAGS
4321
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
4323
uint flags= alter_info->flags;
4325
if (ALTER_ADD_COLUMN & flags)
4326
*alter_flags|= HA_ADD_COLUMN;
4327
if (ALTER_DROP_COLUMN & flags)
4328
*alter_flags|= HA_DROP_COLUMN;
4329
if (ALTER_RENAME & flags)
4330
*alter_flags|= HA_RENAME_TABLE;
4331
if (ALTER_CHANGE_COLUMN & flags)
4332
*alter_flags|= HA_CHANGE_COLUMN;
4333
if (ALTER_COLUMN_DEFAULT & flags)
4334
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
4335
if (ALTER_COLUMN_STORAGE & flags)
4336
*alter_flags|= HA_COLUMN_STORAGE;
4337
if (ALTER_COLUMN_FORMAT & flags)
4338
*alter_flags|= HA_COLUMN_FORMAT;
4339
if (ALTER_COLUMN_ORDER & flags)
4340
*alter_flags|= HA_ALTER_COLUMN_ORDER;
4341
if (ALTER_STORAGE & flags)
4342
*alter_flags|= HA_ALTER_STORAGE;
4343
if (ALTER_ROW_FORMAT & flags)
4344
*alter_flags|= HA_ALTER_ROW_FORMAT;
4345
if (ALTER_RECREATE & flags)
4346
*alter_flags|= HA_RECREATE;
4347
if (ALTER_FOREIGN_KEY & flags)
4348
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4354
@param table The original table.
4355
@param alter_info Alter options, fields and keys for the new
4357
@param create_info Create options for the new table.
4358
@param order_num Number of order list elements.
4359
@param[out] ha_alter_flags Flags that indicate what will be changed
4360
@param[out] ha_alter_info Data structures needed for on-line alter
4361
@param[out] table_changes Information about particular change
4363
First argument 'table' contains information of the original
4364
table, which includes all corresponding parts that the new
4365
table has in arguments create_list, key_list and create_info.
4367
By comparing the changes between the original and new table
4368
we can determine how much it has changed after ALTER TABLE
4369
and whether we need to make a copy of the table, or just change
4372
Mark any changes detected in the ha_alter_flags.
4374
If there are no data changes, but index changes, 'index_drop_buffer'
4375
and/or 'index_add_buffer' are populated with offsets into
4376
table->key_info or key_info_buffer respectively for the indexes
4377
that need to be dropped and/or (re-)created.
4380
@retval false success
4385
compare_tables(THD *thd,
4387
Alter_info *alter_info,
4388
HA_CREATE_INFO *create_info,
4390
HA_ALTER_FLAGS *alter_flags,
4391
HA_ALTER_INFO *ha_alter_info,
4392
uint *table_changes)
4394
Field **f_ptr, *field;
4395
uint table_changes_local= 0;
4396
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
4397
Create_field *new_field;
4398
KEY_PART_INFO *key_part;
4401
Remember if the new definition has new VARCHAR column;
4402
create_info->varchar will be reset in mysql_prepare_create_table.
4404
bool varchar= create_info->varchar;
4405
DBUG_ENTER("compare_tables");
4409
Create a copy of alter_info.
4410
To compare the new and old table definitions, we need to "prepare"
4411
the new definition - transform it from parser output to a format
4412
that describes the final table layout (all column defaults are
4413
initialized, duplicate columns are removed). This is done by
4414
mysql_prepare_create_table. Unfortunately,
4415
mysql_prepare_create_table performs its transformations
4416
"in-place", that is, modifies the argument. Since we would
4417
like to keep compare_tables() idempotent (not altering any
4418
of the arguments) we create a copy of alter_info here and
4419
pass it to mysql_prepare_create_table, then use the result
4420
to evaluate possibility of fast ALTER TABLE, and then
4423
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4424
THD *thd= table->in_use;
4425
uint db_options= 0; /* not used */
4426
/* Create the prepared information. */
4427
if (mysql_prepare_create_table(thd, create_info,
4429
(table->s->tmp_table != NO_TMP_TABLE),
4432
&ha_alter_info->key_info_buffer,
4433
&ha_alter_info->key_count,
4434
/* select_field_count */ 0))
4436
/* Allocate result buffers. */
4437
if (! (ha_alter_info->index_drop_buffer=
4438
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
4439
! (ha_alter_info->index_add_buffer=
4440
(uint*) thd->alloc(sizeof(uint) *
4441
tmp_alter_info.key_list.elements)))
4445
First we setup ha_alter_flags based on what was detected
4448
setup_ha_alter_flags(alter_info, alter_flags);
4452
char dbug_string[HA_MAX_ALTER_FLAGS+1];
4453
alter_flags->print(dbug_string);
4454
DBUG_PRINT("info", ("alter_flags: %s", (char *) dbug_string));
4459
Some very basic checks. If number of fields changes, or the
4460
handler, we need to run full ALTER TABLE. In the future
4461
new fields can be added and old dropped without copy, but
4464
Test also that engine was not given during ALTER TABLE, or
4465
we are force to run regular alter table (copy).
4466
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
4468
For the following ones we also want to run regular alter table:
4469
ALTER TABLE tbl_name ORDER BY ..
4470
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
4472
At the moment we can't handle altering temporary tables without a copy.
4473
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
4474
In that case we always do full copy.
4476
There was a bug prior to mysql-4.0.25. Number of null fields was
4477
calculated incorrectly. As a result frm and data files gets out of
4478
sync after fast alter table. There is no way to determine by which
4479
mysql version (in 4.0 and 4.1 branches) table was created, thus we
4480
disable fast alter table for all tables created by mysql versions
4481
prior to 5.0 branch.
4484
if (table->s->fields != alter_info->create_list.elements ||
4485
table->s->db_type() != create_info->db_type ||
4486
table->s->tmp_table ||
4487
create_info->used_fields & HA_CREATE_USED_ENGINE ||
4488
create_info->used_fields & HA_CREATE_USED_CHARSET ||
4489
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
4490
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
4491
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
4493
!table->s->mysql_version ||
4494
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4496
*table_changes= IS_EQUAL_NO;
4498
Check what has changed and set alter_flags
4500
if (table->s->fields < alter_info->create_list.elements)
4501
*alter_flags|= HA_ADD_COLUMN;
4502
else if (table->s->fields > alter_info->create_list.elements)
4503
*alter_flags|= HA_DROP_COLUMN;
4504
if (create_info->db_type != table->s->db_type() ||
4505
create_info->used_fields & HA_CREATE_USED_ENGINE)
4506
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
4507
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
4508
*alter_flags|= HA_CHANGE_CHARACTER_SET;
4509
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
4510
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
4511
if (alter_info->flags & ALTER_RECREATE)
4512
*alter_flags|= HA_RECREATE;
4513
/* TODO check for ADD/DROP FOREIGN KEY */
4514
if (alter_info->flags & ALTER_FOREIGN_KEY)
4515
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4516
if (!table->s->mysql_version ||
4517
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4518
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4521
Go through fields and check if the original ones are compatible
4524
for (f_ptr= table->field, new_field= new_field_it++;
4525
(new_field && (field= *f_ptr));
4526
f_ptr++, new_field= new_field_it++)
4528
/* Make sure we have at least the default charset in use. */
4529
if (!new_field->charset)
4530
new_field->charset= create_info->default_table_charset;
4532
/* Don't pack rows in old tables if the user has requested this. */
4533
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
4534
(new_field->flags & BLOB_FLAG) ||
4535
(new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
4536
create_info->table_options|= HA_OPTION_PACK_RECORD;
4538
/* Check how fields have been modified */
4539
if (alter_info->flags & ALTER_CHANGE_COLUMN)
4541
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
4542
if (!(table_changes_local= field->is_equal(new_field)))
4543
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4545
/* Check if field was renamed */
4546
field->flags&= ~FIELD_IS_RENAMED;
4547
if (my_strcasecmp(system_charset_info,
4549
new_field->field_name))
4551
field->flags|= FIELD_IS_RENAMED;
4552
*alter_flags|= HA_ALTER_COLUMN_NAME;
4555
*table_changes&= table_changes_local;
4556
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
4557
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4559
/* Check that NULL behavior is same for old and new fields */
4560
if ((new_field->flags & NOT_NULL_FLAG) !=
4561
(uint) (field->flags & NOT_NULL_FLAG))
4563
*table_changes= IS_EQUAL_NO;
4564
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
4568
/* Clear indexed marker */
4569
field->flags&= ~FIELD_IN_ADD_INDEX;
4573
Go through keys and check if the original ones are compatible
4577
KEY *table_key_end= table->key_info + table->s->keys;
4580
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
4582
DBUG_PRINT("info", ("index count old: %d new: %d",
4583
table->s->keys, ha_alter_info->key_count));
4585
Step through all keys of the old table and search matching new keys.
4587
ha_alter_info->index_drop_count= 0;
4588
ha_alter_info->index_add_count= 0;
4589
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4591
KEY_PART_INFO *table_part;
4592
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
4593
KEY_PART_INFO *new_part;
4595
/* Search a new key with the same name. */
4596
for (new_key= ha_alter_info->key_info_buffer;
4597
new_key < new_key_end;
4600
if (! strcmp(table_key->name, new_key->name))
4603
if (new_key >= new_key_end)
4605
/* Key not found. Add the offset of the key to the drop buffer. */
4606
ha_alter_info->index_drop_buffer
4607
[ha_alter_info->index_drop_count++]=
4608
table_key - table->key_info;
4609
if (table_key->flags & HA_NOSAME)
4611
/* Unique key. Check for "PRIMARY". */
4612
if (! my_strcasecmp(system_charset_info,
4613
table_key->name, primary_key_name))
4614
*alter_flags|= HA_DROP_PK_INDEX;
4616
*alter_flags|= HA_DROP_UNIQUE_INDEX;
4619
*alter_flags|= HA_DROP_INDEX;
4620
*table_changes= IS_EQUAL_NO;
4621
DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
4625
/* Check that the key types are compatible between old and new tables. */
4626
if ((table_key->algorithm != new_key->algorithm) ||
4627
((table_key->flags & HA_KEYFLAG_MASK) !=
4628
(new_key->flags & HA_KEYFLAG_MASK)) ||
4629
(table_key->key_parts != new_key->key_parts))
4631
if (table_key->flags & HA_NOSAME)
4633
// Unique key. Check for "PRIMARY".
4634
if (! my_strcasecmp(system_charset_info,
4635
table_key->name, primary_key_name))
4636
*alter_flags|= HA_ALTER_PK_INDEX;
4638
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4641
*alter_flags|= HA_ALTER_INDEX;
4646
Check that the key parts remain compatible between the old and
4649
for (table_part= table_key->key_part, new_part= new_key->key_part;
4650
table_part < table_part_end;
4651
table_part++, new_part++)
4654
Key definition has changed if we are using a different field or
4655
if the used key part length is different. We know that the fields
4656
did not change. Comparing field numbers is sufficient.
4658
if ((table_part->length != new_part->length) ||
4659
(table_part->fieldnr - 1 != new_part->fieldnr))
4661
if (table_key->flags & HA_NOSAME)
4663
/* Unique key. Check for "PRIMARY" */
4664
if (! my_strcasecmp(system_charset_info,
4665
table_key->name, primary_key_name))
4666
*alter_flags|= HA_ALTER_PK_INDEX;
4668
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4671
*alter_flags|= HA_ALTER_INDEX;
4678
/* Key modified. Add the offset of the key to both buffers. */
4679
ha_alter_info->index_drop_buffer
4680
[ha_alter_info->index_drop_count++]=
4681
table_key - table->key_info;
4682
ha_alter_info->index_add_buffer
4683
[ha_alter_info->index_add_count++]=
4684
new_key - ha_alter_info->key_info_buffer;
4685
key_part= new_key->key_part;
4686
end= key_part + new_key->key_parts;
4687
for(; key_part != end; key_part++)
4689
/* Mark field to be part of new key */
4690
if ((field= table->field[key_part->fieldnr]))
4691
field->flags|= FIELD_IN_ADD_INDEX;
4693
*table_changes= IS_EQUAL_NO;
4694
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
4696
/*end of for (; table_key < table_key_end;) */
4699
Step through all keys of the new table and find matching old keys.
4701
for (new_key= ha_alter_info->key_info_buffer;
4702
new_key < new_key_end;
4705
/* Search an old key with the same name. */
4706
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4708
if (! strcmp(table_key->name, new_key->name))
4711
if (table_key >= table_key_end)
4713
/* Key not found. Add the offset of the key to the add buffer. */
4714
ha_alter_info->index_add_buffer
4715
[ha_alter_info->index_add_count++]=
4716
new_key - ha_alter_info->key_info_buffer;
4717
key_part= new_key->key_part;
4718
end= key_part + new_key->key_parts;
4719
for(; key_part != end; key_part++)
4721
/* Mark field to be part of new key */
4722
if ((field= table->field[key_part->fieldnr]))
4723
field->flags|= FIELD_IN_ADD_INDEX;
4725
if (new_key->flags & HA_NOSAME)
4727
/* Unique key. Check for "PRIMARY" */
4728
if (! my_strcasecmp(system_charset_info,
4729
new_key->name, primary_key_name))
4730
*alter_flags|= HA_ADD_PK_INDEX;
4732
*alter_flags|= HA_ADD_UNIQUE_INDEX;
4735
*alter_flags|= HA_ADD_INDEX;
4736
*table_changes= IS_EQUAL_NO;
4737
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
4742
char dbug_string[HA_MAX_ALTER_FLAGS+1];
4743
alter_flags->print(dbug_string);
4744
DBUG_PRINT("info", ("alter_flags: %s", (char *) dbug_string));
4753
Manages enabling/disabling of indexes for ALTER TABLE
4756
alter_table_manage_keys()
4758
indexes_were_disabled Whether the indexes of the from table
4760
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
4768
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
4769
enum enum_enable_or_disable keys_onoff)
4772
DBUG_ENTER("alter_table_manage_keys");
4773
DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
4774
table, indexes_were_disabled, keys_onoff));
4776
switch (keys_onoff) {
4778
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4781
if (!indexes_were_disabled)
4783
/* fall-through: disabled indexes */
4785
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4788
if (error == HA_ERR_WRONG_COMMAND)
4790
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4791
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4792
table->s->table_name.str);
4795
table->file->print_error(error, MYF(0));
4800
int create_temporary_table(THD *thd,
4804
HA_CREATE_INFO *create_info,
4805
Alter_info *alter_info,
4809
char index_file[FN_REFLEN], data_file[FN_REFLEN];
4810
handlerton *old_db_type, *new_db_type;
4811
DBUG_ENTER("create_temporary_table");
4812
old_db_type= table->s->db_type();
4813
new_db_type= create_info->db_type;
4815
Handling of symlinked tables:
4817
Create new data file and index file on the same disk as the
4818
old data and index files.
4820
Rename new data file over old data file and new index file over
4822
Symlinks are not changed.
4825
Create new data file and index file on the same disk as the
4826
old data and index files. Create also symlinks to point at
4829
At end, rename intermediate tables, and symlinks to intermediate
4830
table, to final table name.
4831
Remove old table and old symlinks
4833
If rename is made to another database:
4834
Create new tables in new database.
4836
Remove old table and symlinks.
4838
if (db_changed) // Ignore symlink if db changed
4840
if (create_info->index_file_name)
4842
/* Fix index_file_name to have 'tmp_name' as basename */
4843
strmov(index_file, tmp_name);
4844
create_info->index_file_name=fn_same(index_file,
4845
create_info->index_file_name,
4848
if (create_info->data_file_name)
4850
/* Fix data_file_name to have 'tmp_name' as basename */
4851
strmov(data_file, tmp_name);
4852
create_info->data_file_name=fn_same(data_file,
4853
create_info->data_file_name,
4858
create_info->data_file_name=create_info->index_file_name=0;
4860
if (new_db_type == old_db_type)
4863
Table has not changed storage engine.
4864
If STORAGE and TABLESPACE have not been changed than copy them
4865
from the original table
4867
if (!create_info->tablespace &&
4868
table->s->tablespace &&
4869
create_info->default_storage_media == HA_SM_DEFAULT)
4870
create_info->tablespace= table->s->tablespace;
4871
if (create_info->default_storage_media == HA_SM_DEFAULT)
4872
create_info->default_storage_media= table->s->default_storage_media;
4876
Create a table with a temporary name.
4877
With create_info->frm_only == 1 this creates a .frm file only.
4878
We don't log the statement, it will be logged later.
4880
tmp_disable_binlog(thd);
4881
error= mysql_create_table(thd, new_db, tmp_name,
4882
create_info, alter_info, 1, 0);
4883
reenable_binlog(thd);
4889
Create a temporary table that reflects what an alter table operation
4893
create_altered_table()
4895
table The original table
4896
create_info Information from the parsing phase about new
4898
alter_info Lists of fields, keys to be changed, added
4900
db_change Specifies if the table is moved to another database
4902
A temporary table with all changes
4905
The temporary table is created without storing it in any storage engine
4906
and is opened only to get the table struct and frm file reference.
4908
TABLE *create_altered_table(THD *thd,
4911
HA_CREATE_INFO *create_info,
4912
Alter_info *alter_info,
4916
HA_CREATE_INFO altered_create_info(*create_info);
4917
TABLE *altered_table;
4919
char path[FN_REFLEN];
4920
DBUG_ENTER("create_altered_table");
4922
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
4923
tmp_file_prefix, current_pid, thd->thread_id);
4924
/* Safety fix for InnoDB */
4925
if (lower_case_table_names)
4926
my_casedn_str(files_charset_info, tmp_name);
4927
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
4928
altered_create_info.frm_only= 1;
4929
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4930
&altered_create_info,
4931
alter_info, db_change)))
4933
DBUG_PRINT("info", ("Error %u while creating temporary table", error));
4937
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4939
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
4941
DBUG_RETURN(altered_table);
4948
Perform a fast or on-line alter table
4951
mysql_fast_or_online_alter_table()
4953
table The original table
4954
altered_table A temporary table showing how we will change table
4955
create_info Information from the parsing phase about new
4957
alter_info Storage place for data used during different phases
4958
ha_alter_flags Bitmask that shows what will be changed
4959
keys_onoff Specifies if keys are to be enabled/disabled
4962
>0 An error occured during the on-line alter table operation
4963
-1 Error when re-opening table
4965
If mysql_alter_table does not need to copy the table, it is
4966
either a fast alter table where the storage engine does not
4967
need to know about the change, only the frm will change,
4968
or the storage engine supports performing the alter table
4969
operation directly, on-line without mysql having to copy
4972
int mysql_fast_or_online_alter_table(THD *thd,
4974
TABLE *altered_table,
4975
HA_CREATE_INFO *create_info,
4976
HA_ALTER_INFO *alter_info,
4977
HA_ALTER_FLAGS *ha_alter_flags,
4978
enum enum_enable_or_disable keys_onoff)
4981
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
4984
DBUG_ENTER(" mysql_fast_or_online_alter_table");
4988
Tell the handler to prepare for the online alter
4990
if ((error= table->file->alter_table_phase1(thd,
5000
Tell the storage engine to perform the online alter table
5002
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
5003
we need to wrap the next call with a DDL lock.
5005
if ((error= table->file->alter_table_phase2(thd,
5015
The final .frm file is already created as a temporary file
5016
and will be renamed to the original table name.
5018
VOID(pthread_mutex_lock(&LOCK_open));
5019
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5020
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
5022
close_data_files_and_morph_locks(thd,
5023
table->pos_in_table_list->db,
5024
table->pos_in_table_list->table_name);
5025
if (mysql_rename_table(NULL,
5026
altered_table->s->db.str,
5027
altered_table->s->table_name.str,
5029
table->s->table_name.str, FN_FROM_IS_TMP))
5032
VOID(pthread_mutex_unlock(&LOCK_open));
5035
broadcast_refresh();
5036
VOID(pthread_mutex_unlock(&LOCK_open));
5039
The ALTER TABLE is always in its own transaction.
5040
Commit must not be called while LOCK_open is locked. It could call
5041
wait_if_global_read_lock(), which could create a deadlock if called
5044
error= ha_autocommit_or_rollback(thd, 0);
5052
VOID(pthread_mutex_lock(&LOCK_open));
5053
if (reopen_table(table))
5058
VOID(pthread_mutex_unlock(&LOCK_open));
5062
Tell the handler that the changed frm is on disk and table
5065
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
5071
We are going to reopen table down on the road, so we have to restore
5072
state of the TABLE object which we used for obtaining of handler
5073
object to make it suitable for reopening.
5075
DBUG_ASSERT(t_table == table);
5076
table->open_placeholder= 1;
5077
VOID(pthread_mutex_lock(&LOCK_open));
5078
close_handle_and_leave_table_as_lock(table);
5079
VOID(pthread_mutex_unlock(&LOCK_open));
5084
DBUG_PRINT("info", ("Got error %u", error));
5090
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
5092
This function transforms parse output of ALTER TABLE - lists of
5093
columns and keys to add, drop or modify into, essentially,
5094
CREATE TABLE definition - a list of columns and keys of the new
5095
table. While doing so, it also performs some (bug not all)
5098
This function is invoked when we know that we're going to
5099
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
5100
is not possible, perhaps because the ALTER statement contains
5101
instructions that require change in table data, not only in
5102
table definition or indexes.
5104
@param[in,out] thd thread handle. Used as a memory pool
5105
and source of environment information.
5106
@param[in] table the source table, open and locked
5107
Used as an interface to the storage engine
5108
to acquire additional information about
5110
@param[in,out] create_info A blob with CREATE/ALTER TABLE
5112
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
5113
Originally create_info was used only in
5114
CREATE TABLE and alter_info only in ALTER TABLE.
5115
But since ALTER might end-up doing CREATE,
5116
this distinction is gone and we just carry
5117
around two structures.
5120
Fills various create_info members based on information retrieved
5121
from the storage engine.
5122
Sets create_info->varchar if the table has a VARCHAR column.
5123
Prepares alter_info->create_list and alter_info->key_list with
5124
columns and keys of the new table.
5125
@retval true error, out of memory or a semantical error in ALTER
5127
@retval false success
5131
mysql_prepare_alter_table(THD *thd, TABLE *table,
5132
HA_CREATE_INFO *create_info,
5133
Alter_info *alter_info)
5135
/* New column definitions are added here */
5136
List<Create_field> new_create_list;
5137
/* New key definitions are added here */
5138
List<Key> new_key_list;
5139
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
5140
List_iterator<Create_field> def_it(alter_info->create_list);
5141
List_iterator<Alter_column> alter_it(alter_info->alter_list);
5142
List_iterator<Key> key_it(alter_info->key_list);
5143
List_iterator<Create_field> find_it(new_create_list);
5144
List_iterator<Create_field> field_it(new_create_list);
5145
List<Key_part_spec> key_parts;
5146
uint db_create_options= (table->s->db_create_options
5147
& ~(HA_OPTION_PACK_RECORD));
5148
uint used_fields= create_info->used_fields;
5149
KEY *key_info=table->key_info;
5152
DBUG_ENTER("mysql_prepare_alter_table");
5154
create_info->varchar= false;
5155
/* Let new create options override the old ones */
5156
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
5157
create_info->min_rows= table->s->min_rows;
5158
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
5159
create_info->max_rows= table->s->max_rows;
5160
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
5161
create_info->avg_row_length= table->s->avg_row_length;
5162
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
5163
create_info->default_table_charset= table->s->table_charset;
5164
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
5166
/* Table has an autoincrement, copy value to new table */
5167
table->file->info(HA_STATUS_AUTO);
5168
create_info->auto_increment_value= table->file->stats.auto_increment_value;
5170
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
5171
create_info->key_block_size= table->s->key_block_size;
5172
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
5173
create_info->transactional= table->s->transactional;
5175
restore_record(table, s->default_values); // Empty record for DEFAULT
5179
First collect all fields from table which isn't in drop_list
5181
Field **f_ptr,*field;
5182
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
5184
if (field->type() == MYSQL_TYPE_STRING)
5185
create_info->varchar= true;
5186
/* Check if field should be dropped */
5189
while ((drop=drop_it++))
5191
if (drop->type == Alter_drop::COLUMN &&
5192
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
5194
/* Reset auto_increment value if it was dropped */
5195
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
5196
!(used_fields & HA_CREATE_USED_AUTO))
5198
create_info->auto_increment_value=0;
5199
create_info->used_fields|=HA_CREATE_USED_AUTO;
5209
/* Check if field is changed */
5211
while ((def=def_it++))
5214
!my_strcasecmp(system_charset_info,field->field_name, def->change))
5218
{ // Field is changed
5222
new_create_list.push_back(def);
5229
This field was not dropped and not changed, add it to the list
5232
def= new Create_field(field, field);
5233
new_create_list.push_back(def);
5234
alter_it.rewind(); // Change default if ALTER
5235
Alter_column *alter;
5236
while ((alter=alter_it++))
5238
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
5243
if (def->sql_type == MYSQL_TYPE_BLOB)
5245
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
5248
if ((def->def=alter->def)) // Use new default
5249
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
5251
def->flags|= NO_DEFAULT_VALUE_FLAG;
5257
while ((def=def_it++)) // Add new columns
5259
if (def->change && ! def->field)
5261
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
5265
Check that the DATE/DATETIME not null field we are going to add is
5266
either has a default value or the '0000-00-00' is allowed by the
5268
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
5269
flag to allow ALTER TABLE only if the table to be altered is empty.
5271
if ((def->sql_type == MYSQL_TYPE_NEWDATE ||
5272
def->sql_type == MYSQL_TYPE_DATETIME) &&
5273
!alter_info->datetime_field &&
5274
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
5275
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
5277
alter_info->datetime_field= def;
5278
alter_info->error_if_not_empty= true;
5281
new_create_list.push_back(def);
5282
else if (def->after == first_keyword)
5283
new_create_list.push_front(def);
5288
while ((find=find_it++)) // Add new columns
5290
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
5295
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
5298
find_it.after(def); // Put element after this
5300
XXX: hack for Bug#28427.
5301
If column order has changed, force OFFLINE ALTER TABLE
5302
without querying engine capabilities. If we ever have an
5303
engine that supports online ALTER TABLE CHANGE COLUMN
5304
<name> AFTER <name1> (Falcon?), this fix will effectively
5305
disable the capability.
5306
TODO: detect the situation in compare_tables, behave based
5307
on engine capabilities.
5309
if (alter_info->build_method == HA_BUILD_ONLINE)
5311
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5314
alter_info->build_method= HA_BUILD_OFFLINE;
5317
if (alter_info->alter_list.elements)
5319
my_error(ER_BAD_FIELD_ERROR, MYF(0),
5320
alter_info->alter_list.head()->name, table->s->table_name.str);
5323
if (!new_create_list.elements)
5325
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
5331
Collect all keys which isn't in drop list. Add only those
5332
for which some fields exists.
5335
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
5337
char *key_name= key_info->name;
5340
while ((drop=drop_it++))
5342
if (drop->type == Alter_drop::KEY &&
5343
!my_strcasecmp(system_charset_info,key_name, drop->name))
5352
KEY_PART_INFO *key_part= key_info->key_part;
5354
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
5356
if (!key_part->field)
5357
continue; // Wrong field (from UNIREG)
5358
const char *key_part_name=key_part->field->field_name;
5359
Create_field *cfield;
5361
while ((cfield=field_it++))
5365
if (!my_strcasecmp(system_charset_info, key_part_name,
5369
else if (!my_strcasecmp(system_charset_info,
5370
key_part_name, cfield->field_name))
5374
continue; // Field is removed
5375
uint key_part_length=key_part->length;
5376
if (cfield->field) // Not new field
5379
If the field can't have only a part used in a key according to its
5380
new type, or should not be used partially according to its
5381
previous type, or the field length is less than the key part
5382
length, unset the key part length.
5384
We also unset the key part length if it is the same as the
5385
old field's length, so the whole new field will be used.
5387
BLOBs may have cfield->length == 0, which is why we test it before
5388
checking whether cfield->length < key_part_length (in chars).
5390
if (!Field::type_can_have_key_part(cfield->field->type()) ||
5391
!Field::type_can_have_key_part(cfield->sql_type) ||
5392
(cfield->field->field_length == key_part_length &&
5393
!f_is_blob(key_part->key_type)) ||
5394
(cfield->length && (cfield->length < key_part_length /
5395
key_part->field->charset()->mbmaxlen)))
5396
key_part_length= 0; // Use whole field
5398
key_part_length /= key_part->field->charset()->mbmaxlen;
5399
key_parts.push_back(new Key_part_spec(cfield->field_name,
5400
strlen(cfield->field_name),
5403
if (key_parts.elements)
5405
KEY_CREATE_INFO key_create_info;
5407
enum Key::Keytype key_type;
5408
bzero((char*) &key_create_info, sizeof(key_create_info));
5410
key_create_info.algorithm= key_info->algorithm;
5411
if (key_info->flags & HA_USES_BLOCK_SIZE)
5412
key_create_info.block_size= key_info->block_size;
5413
if (key_info->flags & HA_USES_COMMENT)
5414
key_create_info.comment= key_info->comment;
5416
if (key_info->flags & HA_NOSAME)
5418
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
5419
key_type= Key::PRIMARY;
5421
key_type= Key::UNIQUE;
5424
key_type= Key::MULTIPLE;
5426
key= new Key(key_type, key_name, strlen(key_name),
5428
test(key_info->flags & HA_GENERATED_KEY),
5430
new_key_list.push_back(key);
5435
while ((key=key_it++)) // Add new keys
5437
if (key->type != Key::FOREIGN_KEY)
5438
new_key_list.push_back(key);
5439
if (key->name.str &&
5440
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
5442
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
5448
if (alter_info->drop_list.elements)
5450
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5451
alter_info->drop_list.head()->name);
5454
if (alter_info->alter_list.elements)
5456
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5457
alter_info->alter_list.head()->name);
5461
if (!create_info->comment.str)
5463
create_info->comment.str= table->s->comment.str;
5464
create_info->comment.length= table->s->comment.length;
5467
table->file->update_create_info(create_info);
5468
if ((create_info->table_options &
5469
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
5470
(used_fields & HA_CREATE_USED_PACK_KEYS))
5471
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
5472
if (create_info->table_options &
5473
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
5474
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
5475
if (create_info->table_options &
5476
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
5477
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
5478
HA_OPTION_NO_DELAY_KEY_WRITE);
5479
create_info->table_options|= db_create_options;
5481
if (table->s->tmp_table)
5482
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
5485
alter_info->create_list.swap(new_create_list);
5486
alter_info->key_list.swap(new_key_list);
5498
new_db If there is a RENAME clause
5499
new_name If there is a RENAME clause
5500
create_info Information from the parsing phase about new
5502
table_list The table to change.
5503
alter_info Lists of fields, keys to be changed, added
5505
order_num How many ORDER BY fields has been specified.
5506
order List of fields to ORDER BY.
5507
ignore Whether we have ALTER IGNORE TABLE
5510
This is a veery long function and is everything but the kitchen sink :)
5511
It is used to alter a table and not only by ALTER TABLE but also
5512
CREATE|DROP INDEX are mapped on this function.
5514
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
5515
or both, then this function short cuts its operation by renaming
5516
the table and/or enabling/disabling the keys. In this case, the FRM is
5517
not changed, directly by mysql_alter_table. However, if there is a
5518
RENAME + change of a field, or an index, the short cut is not used.
5519
See how `create_list` is used to generate the new FRM regarding the
5520
structure of the fields. The same is done for the indices of the table.
5522
Important is the fact, that this function tries to do as little work as
5523
possible, by finding out whether a intermediate table is needed to copy
5524
data into and when finishing the altering to use it as the original table.
5525
For this reason the function compare_tables() is called, which decides
5526
based on all kind of data how similar are the new and the original
5534
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
5535
HA_CREATE_INFO *create_info,
5536
TABLE_LIST *table_list,
5537
Alter_info *alter_info,
5538
uint order_num, ORDER *order, bool ignore)
5540
TABLE *table, *new_table=0, *name_lock= 0;;
5542
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
5543
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
5544
char path[FN_REFLEN];
5545
ha_rows copied= 0,deleted= 0;
5546
handlerton *old_db_type, *new_db_type, *save_old_db_type;
5547
legacy_db_type table_type;
5548
frm_type_enum frm_type;
5549
DBUG_ENTER("mysql_alter_table");
5551
if (table_list && table_list->schema_table)
5553
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
5558
Assign variables table_name, new_name, db, new_db, path
5559
to simplify further comparisons: we want to see if it's a RENAME
5560
later just by comparing the pointers, avoiding the need for strcmp.
5562
thd_proc_info(thd, "init");
5563
table_name=table_list->table_name;
5564
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
5566
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
5568
build_table_filename(path, sizeof(path), db, table_name, "", 0);
5570
mysql_ha_rm_tables(thd, table_list, false);
5572
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
5573
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
5574
/* Conditionally writes to binlog. */
5575
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
5576
alter_info->tablespace_op));
5577
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
5578
"/", table_name, reg_ext, NullS);
5579
(void) unpack_filename(new_name_buff, new_name_buff);
5581
If this is just a rename of a view, short cut to the
5582
following scenario: 1) lock LOCK_open 2) do a RENAME
5583
2) unlock LOCK_open.
5584
This is a copy-paste added to make sure
5585
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
5586
as an independent branch in mysql_execute_command. The need
5587
for a copy-paste arose because the main code flow of ALTER TABLE
5588
... RENAME tries to use open_ltable, which does not work for views
5589
(open_ltable was never modified to merge table lists of child tables
5590
into the main table list, like open_tables does).
5591
This code is wrong and will be removed, please do not copy.
5593
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
5595
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
5597
table->use_all_columns();
5600
Prohibit changing of the UNION list of a non-temporary MERGE table
5601
under LOCK tables. It would be quite difficult to reuse a shrinked
5602
set of tables from the old table or to open a new TABLE object for
5603
an extended list and verify that they belong to locked tables.
5605
if (thd->locked_tables &&
5606
(create_info->used_fields & HA_CREATE_USED_UNION) &&
5607
(table->s->tmp_table == NO_TMP_TABLE))
5609
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
5613
/* Check that we are not trying to rename to an existing table */
5616
DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name));
5617
strmov(new_name_buff,new_name);
5618
strmov(new_alias= new_alias_buff, new_name);
5619
if (lower_case_table_names)
5621
if (lower_case_table_names != 2)
5623
my_casedn_str(files_charset_info, new_name_buff);
5624
new_alias= new_name; // Create lower case table name
5626
my_casedn_str(files_charset_info, new_name);
5629
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
5632
Source and destination table names are equal: make later check
5635
new_alias= new_name= table_name;
5639
if (table->s->tmp_table != NO_TMP_TABLE)
5641
if (find_temporary_table(thd,new_db,new_name_buff))
5643
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
5649
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
5653
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5657
build_table_filename(new_name_buff, sizeof(new_name_buff),
5658
new_db, new_name_buff, reg_ext, 0);
5659
if (!access(new_name_buff, F_OK))
5661
/* Table will be closed in do_command() */
5662
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5670
new_alias= (lower_case_table_names == 2) ? alias : table_name;
5671
new_name= table_name;
5674
old_db_type= table->s->db_type();
5675
if (!create_info->db_type)
5677
create_info->db_type= old_db_type;
5680
if (check_engine(thd, new_name, create_info))
5682
new_db_type= create_info->db_type;
5684
if (new_db_type != old_db_type ||
5685
!table->file->can_switch_engines())
5687
my_error(ER_ROW_IS_REFERENCED, MYF(0));
5691
if (create_info->row_type == ROW_TYPE_NOT_USED)
5692
create_info->row_type= table->s->row_type;
5694
DBUG_PRINT("info", ("old type: %s new type: %s",
5695
ha_resolve_storage_engine_name(old_db_type),
5696
ha_resolve_storage_engine_name(new_db_type)));
5697
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
5698
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
5700
DBUG_PRINT("info", ("doesn't support alter"));
5701
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
5705
thd_proc_info(thd, "setup");
5706
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
5707
!table->s->tmp_table) // no need to touch frm
5709
switch (alter_info->keys_onoff) {
5714
wait_while_table_is_used() ensures that table being altered is
5715
opened only by this thread and that TABLE::TABLE_SHARE::version
5716
of TABLE object corresponding to this table is 0.
5717
The latter guarantees that no DML statement will open this table
5718
until ALTER TABLE finishes (i.e. until close_thread_tables())
5719
while the fact that the table is still open gives us protection
5720
from concurrent DDL statements.
5722
VOID(pthread_mutex_lock(&LOCK_open));
5723
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5724
VOID(pthread_mutex_unlock(&LOCK_open));
5725
DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
5726
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5727
/* COND_refresh will be signaled in close_thread_tables() */
5730
VOID(pthread_mutex_lock(&LOCK_open));
5731
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5732
VOID(pthread_mutex_unlock(&LOCK_open));
5733
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5734
/* COND_refresh will be signaled in close_thread_tables() */
5741
if (error == HA_ERR_WRONG_COMMAND)
5744
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5745
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5749
VOID(pthread_mutex_lock(&LOCK_open));
5751
Unlike to the above case close_cached_table() below will remove ALL
5752
instances of TABLE from table cache (it will also remove table lock
5753
held by this thread). So to make actual table renaming and writing
5754
to binlog atomic we have to put them into the same critical section
5755
protected by LOCK_open mutex. This also removes gap for races between
5756
access() and mysql_rename_table() calls.
5759
if (!error && (new_name != table_name || new_db != db))
5761
thd_proc_info(thd, "rename");
5763
Then do a 'simple' rename of the table. First we need to close all
5764
instances of 'source' table.
5766
close_cached_table(thd, table);
5768
Then, we want check once again that target table does not exist.
5769
Actually the order of these two steps does not matter since
5770
earlier we took name-lock on the target table, so we do them
5771
in this particular order only to be consistent with 5.0, in which
5772
we don't take this name-lock and where this order really matters.
5773
TODO: Investigate if we need this access() check at all.
5775
if (!access(new_name_buff,F_OK))
5777
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
5782
*fn_ext(new_name)=0;
5783
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
5787
VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
5794
if (error == HA_ERR_WRONG_COMMAND)
5797
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5798
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5804
write_bin_log(thd, true, thd->query, thd->query_length);
5809
table->file->print_error(error, MYF(0));
2180
boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2181
session->unlink_open_table(name_lock);
2187
if (is_if_not_exists)
2189
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2190
snprintf(warn_buff, sizeof(warn_buff),
2191
ER(ER_TABLE_EXISTS_ERROR), table_name);
2192
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2193
ER_TABLE_EXISTS_ERROR,warn_buff);
2198
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2206
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2208
thr_lock_type lock_type = TL_READ_NO_INSERT;
2210
return(mysql_admin_table(session, tables, check_opt,
2211
"analyze", lock_type, true,
2212
&Cursor::ha_analyze));
2216
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2218
thr_lock_type lock_type = TL_READ_NO_INSERT;
2220
return(mysql_admin_table(session, tables, check_opt,
2223
&Cursor::ha_check));
2226
} /* namespace drizzled */
5813
unlink_open_table(thd, name_lock, false);
5814
VOID(pthread_mutex_unlock(&LOCK_open));
5815
table_list->table= NULL; // For query cache
5819
/* We have to do full alter table. */
5822
If the old table had partitions and we are doing ALTER TABLE ...
5823
engine= <new_engine>, the new table must preserve the original
5824
partitioning. That means that the new engine is still the
5825
partitioning engine, not the engine specified in the parser.
5826
This is discovered in prep_alter_part_table, which in such case
5827
updates create_info->db_type.
5828
Now we need to update the stack copy of create_info->db_type,
5829
as otherwise we won't be able to correctly move the files of the
5830
temporary table to the result table files.
5832
new_db_type= create_info->db_type;
5834
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
5837
set_table_default_charset(thd, create_info, db);
5840
if (thd->variables.old_alter_table
5841
|| (table->s->db_type() != create_info->db_type)
5844
if (alter_info->build_method == HA_BUILD_ONLINE)
5846
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5849
alter_info->build_method= HA_BUILD_OFFLINE;
5852
if (alter_info->build_method != HA_BUILD_OFFLINE)
5854
TABLE *altered_table= 0;
5855
HA_ALTER_INFO ha_alter_info;
5856
HA_ALTER_FLAGS ha_alter_flags;
5857
uint table_changes= IS_EQUAL_YES;
5858
bool need_copy_table= true;
5859
/* Check how much the tables differ. */
5860
if (compare_tables(thd, table, alter_info,
5861
create_info, order_num,
5870
Check if storage engine supports altering the table
5876
char dbug_string[HA_MAX_ALTER_FLAGS+1];
5877
ha_alter_flags.print(dbug_string);
5878
DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
5879
need_copy_table, table_changes,
5880
(char *) dbug_string));
5885
If table is not renamed, changed database and
5886
some change was detected then check if engine
5887
can do the change on-line
5889
if (new_name == table_name && new_db == db &&
5890
ha_alter_flags.is_set())
5892
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
5896
check if table can be altered on-line
5898
if (!(altered_table= create_altered_table(thd,
5903
!strcmp(db, new_db))))
5906
switch (table->file->check_if_supported_alter(altered_table,
5910
case HA_ALTER_SUPPORTED_WAIT_LOCK:
5911
case HA_ALTER_SUPPORTED_NO_LOCK:
5913
@todo: Currently we always acquire an exclusive name
5914
lock on the table metadata when performing fast or online
5915
ALTER TABLE. In future we may consider this unnecessary,
5916
and narrow the scope of the exclusive name lock to only
5917
cover manipulation with .frms. Storage engine API
5918
call check_if_supported_alter has provision for this
5921
need_copy_table= false;
5923
case HA_ALTER_NOT_SUPPORTED:
5924
if (alter_info->build_method == HA_BUILD_ONLINE)
5926
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5927
close_temporary_table(thd, altered_table, 1, 1);
5930
need_copy_table= true;
5932
case HA_ALTER_ERROR:
5934
close_temporary_table(thd, altered_table, 1, 1);
5939
char dbug_string[HA_MAX_ALTER_FLAGS+1];
5940
ha_alter_flags.print(dbug_string);
5941
DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
5942
need_copy_table, table_changes,
5943
(char *) dbug_string));
5948
/* TODO need to check if changes can be handled as fast ALTER TABLE */
5950
need_copy_table= true;
5952
if (!need_copy_table)
5954
error= mysql_fast_or_online_alter_table(thd,
5960
alter_info->keys_onoff);
5963
mysql_unlock_tables(thd, thd->lock);
5966
close_temporary_table(thd, altered_table, 1, 1);
5972
goto err_with_placeholders;
5979
pthread_mutex_lock(&LOCK_open);
5985
close_temporary_table(thd, altered_table, 1, 1);
5988
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
5989
current_pid, thd->thread_id);
5990
/* Safety fix for innodb */
5991
if (lower_case_table_names)
5992
my_casedn_str(files_charset_info, tmp_name);
5995
/* Create a temporary table with the new format */
5996
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
5997
create_info, alter_info,
5998
!strcmp(db, new_db))))
6003
/* Open the table so we need to copy the data to it. */
6004
if (table->s->tmp_table)
6007
bzero((void*) &tbl, sizeof(tbl));
6009
tbl.table_name= tbl.alias= tmp_name;
6010
/* Table is in thd->temporary_tables */
6011
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
6012
MYSQL_LOCK_IGNORE_FLUSH);
6016
char path[FN_REFLEN];
6017
/* table is a normal table: Create temporary table in same directory */
6018
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
6020
/* Open our intermediate table */
6021
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
6026
/* Copy the data if necessary. */
6027
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
6028
thd->cuted_fields=0L;
6029
thd_proc_info(thd, "copy to tmp table");
6032
We do not copy data for MERGE tables. Only the children have data.
6033
MERGE tables have HA_NO_COPY_ON_ALTER set.
6035
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
6037
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
6038
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
6039
new_table->next_number_field=new_table->found_next_number_field;
6040
error= copy_data_between_tables(table, new_table,
6041
alter_info->create_list, ignore,
6042
order_num, order, &copied, &deleted,
6043
alter_info->keys_onoff,
6044
alter_info->error_if_not_empty);
6048
VOID(pthread_mutex_lock(&LOCK_open));
6049
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
6050
VOID(pthread_mutex_unlock(&LOCK_open));
6051
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
6052
alter_info->keys_onoff);
6053
error= ha_autocommit_or_rollback(thd, 0);
6054
if (end_active_trans(thd))
6057
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
6059
if (table->s->tmp_table != NO_TMP_TABLE)
6061
/* We changed a temporary table */
6064
/* Close lock if this is a transactional table */
6067
mysql_unlock_tables(thd, thd->lock);
6070
/* Remove link to old table and rename the new one */
6071
close_temporary_table(thd, table, 1, 1);
6072
/* Should pass the 'new_name' as we store table name in the cache */
6073
if (rename_temporary_table(thd, new_table, new_db, new_name))
6075
/* We don't replicate alter table statement on temporary tables */
6076
if (!thd->current_stmt_binlog_row_based)
6077
write_bin_log(thd, true, thd->query, thd->query_length);
6084
Close the intermediate table that will be the new table.
6085
Note that MERGE tables do not have their children attached here.
6087
intern_close_table(new_table);
6088
my_free(new_table,MYF(0));
6090
VOID(pthread_mutex_lock(&LOCK_open));
6093
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6094
VOID(pthread_mutex_unlock(&LOCK_open));
6099
Data is copied. Now we:
6100
1) Wait until all other threads close old version of table.
6101
2) Close instances of table open by this thread and replace them
6102
with exclusive name-locks.
6103
3) Rename the old table to a temp name, rename the new one to the
6105
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
6106
we reopen new version of table.
6107
5) Write statement to the binary log.
6108
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
6109
remove name-locks from list of open tables and table cache.
6110
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
6111
call to remove name-locks from table cache and list of open table.
6114
thd_proc_info(thd, "rename result table");
6115
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
6116
current_pid, thd->thread_id);
6117
if (lower_case_table_names)
6118
my_casedn_str(files_charset_info, old_name);
6120
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
6121
close_data_files_and_morph_locks(thd, db, table_name);
6124
save_old_db_type= old_db_type;
6127
This leads to the storage engine (SE) not being notified for renames in
6128
mysql_rename_table(), because we just juggle with the FRM and nothing
6129
more. If we have an intermediate table, then we notify the SE that
6130
it should become the actual table. Later, we will recycle the old table.
6131
However, in case of ALTER TABLE RENAME there might be no intermediate
6132
table. This is when the old and new tables are compatible, according to
6133
compare_table(). Then, we need one additional call to
6134
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
6135
actual rename in the SE and the FRM is not touched. Note that, if the
6136
table is renamed and the SE is also changed, then an intermediate table
6137
is created and the additional call will not take place.
6139
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
6143
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6145
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
6146
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
6148
/* Try to get everything back. */
6150
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
6151
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6152
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
6158
/* This shouldn't happen. But let us play it safe. */
6159
goto err_with_placeholders;
6162
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
6165
if (thd->locked_tables && new_name == table_name && new_db == db)
6167
thd->in_lock_tables= 1;
6168
error= reopen_tables(thd, 1, 1);
6169
thd->in_lock_tables= 0;
6171
goto err_with_placeholders;
6173
VOID(pthread_mutex_unlock(&LOCK_open));
6175
thd_proc_info(thd, "end");
6177
DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
6179
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
6180
thd->query, thd->query_length,
6183
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
6184
thd->current_stmt_binlog_row_based &&
6185
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
6186
write_bin_log(thd, true, thd->query, thd->query_length);
6188
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
6191
For the alter table to be properly flushed to the logs, we
6192
have to open the new table. If not, we get a problem on server
6193
shutdown. But we do not need to attach MERGE children.
6195
char path[FN_REFLEN];
6197
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
6198
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
6201
intern_close_table(t_table);
6202
my_free(t_table, MYF(0));
6205
sql_print_warning("Could not open table %s.%s after rename\n",
6207
ha_flush_logs(old_db_type);
6209
table_list->table=0; // For query cache
6211
if (thd->locked_tables && (new_name != table_name || new_db != db))
6214
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
6215
to remove placeholders for the old table and for the target table
6216
from the list of open tables and table cache. If we are not under
6217
LOCK TABLES we can rely on close_thread_tables() doing this job.
6219
pthread_mutex_lock(&LOCK_open);
6220
unlink_open_table(thd, table, false);
6221
unlink_open_table(thd, name_lock, false);
6222
pthread_mutex_unlock(&LOCK_open);
6226
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
6227
(ulong) (copied + deleted), (ulong) deleted,
6228
(ulong) thd->cuted_fields);
6229
my_ok(thd, copied + deleted, 0L, tmp_name);
6230
thd->some_tables_deleted=0;
6236
/* close_temporary_table() frees the new_table pointer. */
6237
close_temporary_table(thd, new_table, 1, 1);
6240
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6244
No default value was provided for a DATE/DATETIME field, the
6245
current sql_mode doesn't allow the '0000-00-00' value and
6246
the table to be altered isn't empty.
6249
if (alter_info->error_if_not_empty && thd->row_count)
6251
const char *f_val= 0;
6252
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
6253
switch (alter_info->datetime_field->sql_type)
6255
case MYSQL_TYPE_NEWDATE:
6256
f_val= "0000-00-00";
6257
t_type= MYSQL_TIMESTAMP_DATE;
6259
case MYSQL_TYPE_DATETIME:
6260
f_val= "0000-00-00 00:00:00";
6261
t_type= MYSQL_TIMESTAMP_DATETIME;
6264
/* Shouldn't get here. */
6267
bool save_abort_on_warning= thd->abort_on_warning;
6268
thd->abort_on_warning= true;
6269
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
6270
f_val, strlength(f_val), t_type,
6271
alter_info->datetime_field->field_name);
6272
thd->abort_on_warning= save_abort_on_warning;
6276
pthread_mutex_lock(&LOCK_open);
6277
unlink_open_table(thd, name_lock, false);
6278
pthread_mutex_unlock(&LOCK_open);
6282
err_with_placeholders:
6284
An error happened while we were holding exclusive name-lock on table
6285
being altered. To be safe under LOCK TABLES we should remove placeholders
6286
from list of open tables list and table cache.
6288
unlink_open_table(thd, table, false);
6290
unlink_open_table(thd, name_lock, false);
6291
VOID(pthread_mutex_unlock(&LOCK_open));
6294
/* mysql_alter_table */
6297
copy_data_between_tables(TABLE *from,TABLE *to,
6298
List<Create_field> &create,
6300
uint order_num, ORDER *order,
6303
enum enum_enable_or_disable keys_onoff,
6304
bool error_if_not_empty)
6307
Copy_field *copy,*copy_end;
6308
ulong found_count,delete_count;
6309
THD *thd= current_thd;
6311
SORT_FIELD *sortorder;
6315
List<Item> all_fields;
6316
ha_rows examined_rows;
6317
bool auto_increment_field_copied= 0;
6318
ulong save_sql_mode;
6319
ulonglong prev_insert_id;
6320
DBUG_ENTER("copy_data_between_tables");
6323
Turn off recovery logging since rollback of an alter table is to
6324
delete the new table so there is no need to log the changes to it.
6326
This needs to be done before external_lock
6328
error= ha_enable_transaction(thd, false);
6332
if (!(copy= new Copy_field[to->s->fields]))
6333
DBUG_RETURN(-1); /* purecov: inspected */
6335
if (to->file->ha_external_lock(thd, F_WRLCK))
6338
/* We need external lock before we can disable/enable keys */
6339
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
6341
/* We can abort alter table for any table type */
6342
thd->abort_on_warning= !ignore;
6344
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
6345
to->file->ha_start_bulk_insert(from->file->stats.records);
6347
save_sql_mode= thd->variables.sql_mode;
6349
List_iterator<Create_field> it(create);
6352
for (Field **ptr=to->field ; *ptr ; ptr++)
6357
if (*ptr == to->next_number_field)
6359
auto_increment_field_copied= true;
6361
If we are going to copy contents of one auto_increment column to
6362
another auto_increment column it is sensible to preserve zeroes.
6363
This condition also covers case when we are don't actually alter
6364
auto_increment column.
6366
if (def->field == from->found_next_number_field)
6367
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
6369
(copy_end++)->set(*ptr,def->field,0);
6374
found_count=delete_count=0;
6378
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
6380
char warn_buff[MYSQL_ERRMSG_SIZE];
6381
snprintf(warn_buff, sizeof(warn_buff),
6382
"ORDER BY ignored as there is a user-defined clustered index"
6383
" in the table '%-.192s'", from->s->table_name.str);
6384
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
6389
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
6390
MYF(MY_FAE | MY_ZEROFILL));
6391
bzero((char *) &tables, sizeof(tables));
6393
tables.alias= tables.table_name= from->s->table_name.str;
6394
tables.db= from->s->db.str;
6397
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
6398
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
6399
&tables, fields, all_fields, order) ||
6400
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
6401
(from->sort.found_records= filesort(thd, from, sortorder, length,
6402
(SQL_SELECT *) 0, HA_POS_ERROR,
6403
1, &examined_rows)) ==
6409
/* Tell handler that we have values for all columns in the to table */
6410
to->use_all_columns();
6411
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
6413
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
6415
restore_record(to, s->default_values); // Create empty record
6416
while (!(error=info.read_record(&info)))
6420
thd->send_kill_message();
6425
/* Return error if source table isn't empty. */
6426
if (error_if_not_empty)
6431
if (to->next_number_field)
6433
if (auto_increment_field_copied)
6434
to->auto_increment_field_not_null= true;
6436
to->next_number_field->reset();
6439
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
6441
copy_ptr->do_copy(copy_ptr);
6443
prev_insert_id= to->file->next_insert_id;
6444
error=to->file->ha_write_row(to->record[0]);
6445
to->auto_increment_field_not_null= false;
6449
to->file->is_fatal_error(error, HA_CHECK_DUP))
6451
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
6453
uint key_nr= to->file->get_dup_key(error);
6454
if ((int) key_nr >= 0)
6456
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
6458
(to->key_info[0].key_part[0].field->flags &
6459
AUTO_INCREMENT_FLAG))
6460
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
6461
to->file->print_keydup_error(key_nr, err_msg);
6466
to->file->print_error(error,MYF(0));
6469
to->file->restore_auto_increment(prev_insert_id);
6475
end_read_record(&info);
6476
free_io_cache(from);
6477
delete [] copy; // This is never 0
6479
if (to->file->ha_end_bulk_insert() && error <= 0)
6481
to->file->print_error(my_errno,MYF(0));
6484
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
6486
if (ha_enable_transaction(thd, true))
6493
Ensure that the new table is saved properly to disk so that we
6496
if (ha_autocommit_or_rollback(thd, 0))
6498
if (end_active_trans(thd))
6502
thd->variables.sql_mode= save_sql_mode;
6503
thd->abort_on_warning= 0;
6504
free_io_cache(from);
6505
*copied= found_count;
6506
*deleted=delete_count;
6507
to->file->ha_release_auto_increment();
6508
if (to->file->ha_external_lock(thd,F_UNLCK))
6510
DBUG_RETURN(error > 0 ? -1 : 0);
6515
Recreates tables by calling mysql_alter_table().
6518
mysql_recreate_table()
6520
tables Tables to recreate
6523
Like mysql_alter_table().
6525
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
6527
HA_CREATE_INFO create_info;
6528
Alter_info alter_info;
6530
DBUG_ENTER("mysql_recreate_table");
6531
DBUG_ASSERT(!table_list->next_global);
6533
table_list->table has been closed and freed. Do not reference
6534
uninitialized data. open_tables() could fail.
6536
table_list->table= NULL;
6538
bzero((char*) &create_info, sizeof(create_info));
6539
create_info.row_type=ROW_TYPE_NOT_USED;
6540
create_info.default_table_charset=default_charset_info;
6541
/* Force alter table to recreate table */
6542
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
6543
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
6544
table_list, &alter_info, 0,
6549
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
6550
HA_CHECK_OPT *check_opt)
6553
List<Item> field_list;
6555
Protocol *protocol= thd->protocol;
6556
DBUG_ENTER("mysql_checksum_table");
6558
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
6559
item->maybe_null= 1;
6560
field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
6561
MY_INT64_NUM_DECIMAL_DIGITS));
6562
item->maybe_null= 1;
6563
if (protocol->send_fields(&field_list,
6564
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
6567
/* Open one table after the other to keep lock time as short as possible. */
6568
for (table= tables; table; table= table->next_local)
6570
char table_name[NAME_LEN*2+2];
6573
strxmov(table_name, table->db ,".", table->table_name, NullS);
6575
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
6576
thd->clear_error(); // these errors shouldn't get client
6578
protocol->prepare_for_resend();
6579
protocol->store(table_name, system_charset_info);
6583
/* Table didn't exist */
6584
protocol->store_null();
6589
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
6590
!(check_opt->flags & T_EXTEND))
6591
protocol->store((ulonglong)t->file->checksum());
6592
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
6593
(check_opt->flags & T_QUICK))
6594
protocol->store_null();
6597
/* calculating table's checksum */
6599
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
6601
t->use_all_columns();
6603
if (t->file->ha_rnd_init(1))
6604
protocol->store_null();
6609
ha_checksum row_crc= 0;
6610
int error= t->file->rnd_next(t->record[0]);
6611
if (unlikely(error))
6613
if (error == HA_ERR_RECORD_DELETED)
6617
if (t->s->null_bytes)
6619
/* fix undefined null bits */
6620
t->record[0][t->s->null_bytes-1] |= null_mask;
6621
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
6622
t->record[0][0] |= 1;
6624
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
6627
for (uint i= 0; i < t->s->fields; i++ )
6629
Field *f= t->field[i];
6630
if ((f->type() == MYSQL_TYPE_BLOB) ||
6631
(f->type() == MYSQL_TYPE_VARCHAR))
6635
row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
6638
row_crc= my_checksum(row_crc, f->ptr,
6644
protocol->store((ulonglong)crc);
6645
t->file->ha_rnd_end();
6649
close_thread_tables(thd);
6650
table->table=0; // For query cache
6652
if (protocol->write())
6660
close_thread_tables(thd); // Shouldn't be needed
6666
static bool check_engine(THD *thd, const char *table_name,
6667
HA_CREATE_INFO *create_info)
6669
handlerton **new_engine= &create_info->db_type;
6670
handlerton *req_engine= *new_engine;
6671
bool no_substitution= 1;
6672
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
6673
no_substitution, 1)))
6676
if (req_engine && req_engine != *new_engine)
6678
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
6679
ER_WARN_USING_OTHER_HANDLER,
6680
ER(ER_WARN_USING_OTHER_HANDLER),
6681
ha_resolve_storage_engine_name(*new_engine),
6684
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
6685
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
6687
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
6689
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
6690
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
6694
*new_engine= myisam_hton;