1
/* Copyright (C) 2000-2004 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* drop and alter of tables */
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
my_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
uint io_size= global_ddl_log.io_size;
334
DBUG_ENTER("read_ddl_log_file_entry");
336
if (my_pread(file_id, file_entry_buf, io_size, io_size * entry_no,
337
MYF(MY_WME)) != io_size)
344
Write one entry from ddl log file
346
write_ddl_log_file_entry()
347
entry_no Entry number to read
353
static bool write_ddl_log_file_entry(uint entry_no)
356
File file_id= global_ddl_log.file_id;
357
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
358
DBUG_ENTER("write_ddl_log_file_entry");
360
if (my_pwrite(file_id, (uchar*)file_entry_buf,
361
IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE)
370
write_ddl_log_header()
376
static bool write_ddl_log_header()
380
DBUG_ENTER("write_ddl_log_header");
382
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
383
global_ddl_log.num_entries);
385
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
388
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
390
if (write_ddl_log_file_entry(0UL))
392
sql_print_error("Error writing ddl log header");
395
VOID(sync_ddl_log());
401
Create ddl log file name
403
create_ddl_log_file_name()
404
file_name Filename setup
409
static inline void create_ddl_log_file_name(char *file_name)
411
strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
416
Read header of ddl log file
418
read_ddl_log_header()
420
> 0 Last entry in ddl log
421
0 No entries in ddl log
423
When we read the ddl log header we get information about maximum sizes
424
of names in the ddl log and we also get information about the number
425
of entries in the ddl log.
428
static uint read_ddl_log_header()
430
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
431
char file_name[FN_REFLEN];
433
bool successful_open= FALSE;
434
DBUG_ENTER("read_ddl_log_header");
436
create_ddl_log_file_name(file_name);
437
if ((global_ddl_log.file_id= my_open(file_name,
438
O_RDWR | O_BINARY, MYF(0))) >= 0)
440
if (read_ddl_log_file_entry(0UL))
442
/* Write message into error log */
443
sql_print_error("Failed to read ddl log file in recovery");
446
successful_open= TRUE;
448
entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
449
global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
452
global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
453
DBUG_ASSERT(global_ddl_log.io_size <=
454
sizeof(global_ddl_log.file_entry_buf));
460
global_ddl_log.first_free= NULL;
461
global_ddl_log.first_used= NULL;
462
global_ddl_log.num_entries= 0;
463
VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
464
global_ddl_log.do_release= true;
465
DBUG_RETURN(entry_no);
473
read_entry Number of entry to read
474
out:entry_info Information from entry
479
Read a specified entry in the ddl log
482
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
484
char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
487
DBUG_ENTER("read_ddl_log_entry");
489
if (read_ddl_log_file_entry(read_entry))
493
ddl_log_entry->entry_pos= read_entry;
494
single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
495
ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
496
single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
497
ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
498
ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
499
ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
500
ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
501
inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
502
ddl_log_entry->from_name= &file_entry_buf[inx];
503
inx+= global_ddl_log.name_len;
504
ddl_log_entry->handler_name= &file_entry_buf[inx];
515
Write the header of the ddl log file and length of names. Also set
516
number of entries to zero.
523
static bool init_ddl_log()
525
char file_name[FN_REFLEN];
526
DBUG_ENTER("init_ddl_log");
528
if (global_ddl_log.inited)
531
global_ddl_log.io_size= IO_SIZE;
532
create_ddl_log_file_name(file_name);
533
if ((global_ddl_log.file_id= my_create(file_name,
535
O_RDWR | O_TRUNC | O_BINARY,
538
/* Couldn't create ddl log file, this is serious error */
539
sql_print_error("Failed to open ddl log file");
542
global_ddl_log.inited= TRUE;
543
if (write_ddl_log_header())
545
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
546
global_ddl_log.inited= FALSE;
556
Execute one action in a ddl log entry
558
execute_ddl_log_action()
559
ddl_log_entry Information in action entry to execute
565
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
567
bool frm_action= FALSE;
568
LEX_STRING handler_name;
572
char to_path[FN_REFLEN];
573
char from_path[FN_REFLEN];
575
DBUG_ENTER("execute_ddl_log_action");
577
if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
581
handler_name.str= (char*)ddl_log_entry->handler_name;
582
handler_name.length= strlen(ddl_log_entry->handler_name);
583
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
584
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
588
plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
591
my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
594
hton= plugin_data(plugin, handlerton*);
595
file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
598
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
602
switch (ddl_log_entry->action_type)
604
case DDL_LOG_REPLACE_ACTION:
605
case DDL_LOG_DELETE_ACTION:
607
if (ddl_log_entry->phase == 0)
611
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
612
if ((error= my_delete(to_path, MYF(MY_WME))))
614
if (my_errno != ENOENT)
620
if ((error= file->ha_delete_table(ddl_log_entry->name)))
622
if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
626
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
628
VOID(sync_ddl_log());
630
if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
633
DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
635
Fall through and perform the rename action of the replace
636
action. We have already indicated the success of the delete
637
action in the log entry by stepping up the phase.
640
case DDL_LOG_RENAME_ACTION:
645
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
646
strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
647
if (my_rename(from_path, to_path, MYF(MY_WME)))
652
if (file->ha_rename_table(ddl_log_entry->from_name,
653
ddl_log_entry->name))
656
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
658
VOID(sync_ddl_log());
668
free_root(&mem_root, MYF(0));
674
Get a free entry in the ddl log
676
get_free_ddl_log_entry()
677
out:active_entry A ddl log memory entry returned
683
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
686
DDL_LOG_MEMORY_ENTRY *used_entry;
687
DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
688
DBUG_ENTER("get_free_ddl_log_entry");
690
if (global_ddl_log.first_free == NULL)
692
if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
693
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
695
sql_print_error("Failed to allocate memory for ddl log free list");
698
global_ddl_log.num_entries++;
699
used_entry->entry_pos= global_ddl_log.num_entries;
704
used_entry= global_ddl_log.first_free;
705
global_ddl_log.first_free= used_entry->next_log_entry;
706
*write_header= FALSE;
709
Move from free list to used list
711
used_entry->next_log_entry= first_used;
712
used_entry->prev_log_entry= NULL;
713
global_ddl_log.first_used= used_entry;
715
first_used->prev_log_entry= used_entry;
717
*active_entry= used_entry;
723
External interface methods for the DDL log Module
724
---------------------------------------------------
729
write_ddl_log_entry()
730
ddl_log_entry Information about log entry
731
out:entry_written Entry information written into
738
A careful write of the ddl log is performed to ensure that we can
739
handle crashes occurring during CREATE and ALTER TABLE processing.
742
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
743
DDL_LOG_MEMORY_ENTRY **active_entry)
745
bool error, write_header;
746
DBUG_ENTER("write_ddl_log_entry");
752
global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
753
(char)DDL_LOG_ENTRY_CODE;
754
global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
755
(char)ddl_log_entry->action_type;
756
global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
757
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
758
ddl_log_entry->next_entry);
759
DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_LEN);
760
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
761
ddl_log_entry->name, FN_LEN - 1);
762
if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
763
ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
765
DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_LEN);
766
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
767
ddl_log_entry->from_name, FN_LEN - 1);
770
global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
771
DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_LEN);
772
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
773
ddl_log_entry->handler_name, FN_LEN - 1);
774
if (get_free_ddl_log_entry(active_entry, &write_header))
779
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
782
sql_print_error("Failed to write entry_no = %u",
783
(*active_entry)->entry_pos);
785
if (write_header && !error)
787
VOID(sync_ddl_log());
788
if (write_ddl_log_header())
792
release_ddl_log_memory_entry(*active_entry);
798
Write final entry in the ddl log
800
write_execute_ddl_log_entry()
801
first_entry First entry in linked list of entries
802
to execute, if 0 = NULL it means that
803
the entry is removed and the entries
804
are put into the free list.
805
complete Flag indicating we are simply writing
806
info about that entry has been completed
807
in:out:active_entry Entry to execute, 0 = NULL if the entry
808
is written first time and needs to be
809
returned. In this case the entry written
810
is returned in this parameter
816
This is the last write in the ddl log. The previous log entries have
817
already been written but not yet synched to disk.
818
We write a couple of log entries that describes action to perform.
819
This entries are set-up in a linked list, however only when a first
820
execute entry is put as the first entry these will be executed.
821
This routine writes this first
824
bool write_execute_ddl_log_entry(uint first_entry,
826
DDL_LOG_MEMORY_ENTRY **active_entry)
828
bool write_header= FALSE;
829
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
830
DBUG_ENTER("write_execute_ddl_log_entry");
839
We haven't synched the log entries yet, we synch them now before
840
writing the execute entry. If complete is true we haven't written
841
any log entries before, we are only here to write the execute
842
entry to indicate it is done.
844
VOID(sync_ddl_log());
845
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
848
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
849
file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
850
file_entry_buf[DDL_LOG_PHASE_POS]= 0;
851
int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
852
file_entry_buf[DDL_LOG_NAME_POS]= 0;
853
file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
854
file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
855
if (!(*active_entry))
857
if (get_free_ddl_log_entry(active_entry, &write_header))
862
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
864
sql_print_error("Error writing execute entry in ddl log");
865
release_ddl_log_memory_entry(*active_entry);
868
VOID(sync_ddl_log());
871
if (write_ddl_log_header())
873
release_ddl_log_memory_entry(*active_entry);
882
For complex rename operations we need to deactivate individual entries.
884
deactivate_ddl_log_entry()
885
entry_no Entry position of record to change
890
During replace operations where we start with an existing table called
891
t1 and a replacement table called t1#temp or something else and where
892
we want to delete t1 and rename t1#temp to t1 this is not possible to
893
do in a safe manner unless the ddl log is informed of the phases in
896
Delete actions are 1-phase actions that can be ignored immediately after
898
Rename actions from x to y is also a 1-phase action since there is no
899
interaction with any other handlers named x and y.
900
Replace action where drop y and x -> y happens needs to be a two-phase
901
action. Thus the first phase will drop y and the second phase will
905
bool deactivate_ddl_log_entry(uint entry_no)
907
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
908
DBUG_ENTER("deactivate_ddl_log_entry");
910
if (!read_ddl_log_file_entry(entry_no))
912
if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
914
if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
915
file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
916
(file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
917
file_entry_buf[DDL_LOG_PHASE_POS] == 1))
918
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
919
else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
921
DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
922
file_entry_buf[DDL_LOG_PHASE_POS]= 1;
928
if (write_ddl_log_file_entry(entry_no))
930
sql_print_error("Error in deactivating log entry. Position = %u",
938
sql_print_error("Failed in reading entry before deactivating it");
957
DBUG_ENTER("sync_ddl_log");
959
if ((!global_ddl_log.recovery_phase) &&
964
if (my_sync(global_ddl_log.file_id, MYF(0)))
966
/* Write to error log */
967
sql_print_error("Failed to sync ddl log");
975
Release a log memory entry
977
release_ddl_log_memory_entry()
978
log_memory_entry Log memory entry to release
983
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
985
DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
986
DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
987
DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
988
DBUG_ENTER("release_ddl_log_memory_entry");
990
global_ddl_log.first_free= log_entry;
991
log_entry->next_log_entry= first_free;
994
prev_log_entry->next_log_entry= next_log_entry;
996
global_ddl_log.first_used= next_log_entry;
998
next_log_entry->prev_log_entry= prev_log_entry;
1004
Execute one entry in the ddl log. Executing an entry means executing
1005
a linked list of actions.
1007
execute_ddl_log_entry()
1008
first_entry Reference to first action in entry
1014
bool execute_ddl_log_entry(THD *thd, uint first_entry)
1016
DDL_LOG_ENTRY ddl_log_entry;
1017
uint read_entry= first_entry;
1018
DBUG_ENTER("execute_ddl_log_entry");
1020
pthread_mutex_lock(&LOCK_gdl);
1023
if (read_ddl_log_entry(read_entry, &ddl_log_entry))
1025
/* Write to error log and continue with next log entry */
1026
sql_print_error("Failed to read entry = %u from ddl log",
1030
DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
1031
ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
1033
if (execute_ddl_log_action(thd, &ddl_log_entry))
1035
/* Write to error log and continue with next log entry */
1036
sql_print_error("Failed to execute action for entry = %u from ddl log",
1040
read_entry= ddl_log_entry.next_entry;
1041
} while (read_entry);
1042
pthread_mutex_unlock(&LOCK_gdl);
1055
static void close_ddl_log()
1057
DBUG_ENTER("close_ddl_log");
1058
if (global_ddl_log.file_id >= 0)
1060
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
1061
global_ddl_log.file_id= (File) -1;
1068
Execute the ddl log at recovery of MySQL Server
1070
execute_ddl_log_recovery()
1075
void execute_ddl_log_recovery()
1077
uint num_entries, i;
1079
DDL_LOG_ENTRY ddl_log_entry;
1080
char file_name[FN_REFLEN];
1081
DBUG_ENTER("execute_ddl_log_recovery");
1084
Initialise global_ddl_log struct
1086
bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
1087
global_ddl_log.inited= FALSE;
1088
global_ddl_log.recovery_phase= TRUE;
1089
global_ddl_log.io_size= IO_SIZE;
1090
global_ddl_log.file_id= (File) -1;
1093
To be able to run this from boot, we allocate a temporary THD
1097
thd->thread_stack= (char*) &thd;
1098
thd->store_globals();
1100
num_entries= read_ddl_log_header();
1101
for (i= 1; i < num_entries + 1; i++)
1103
if (read_ddl_log_entry(i, &ddl_log_entry))
1105
sql_print_error("Failed to read entry no = %u from ddl log",
1109
if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
1111
if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
1113
/* Real unpleasant scenario but we continue anyways. */
1119
create_ddl_log_file_name(file_name);
1120
VOID(my_delete(file_name, MYF(0)));
1121
global_ddl_log.recovery_phase= FALSE;
1123
/* Remember that we don't have a THD */
1124
my_pthread_setspecific_ptr(THR_THD, 0);
1130
Release all memory allocated to the ddl log
1137
void release_ddl_log()
1139
DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
1140
DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
1141
DBUG_ENTER("release_ddl_log");
1143
if (!global_ddl_log.do_release)
1146
pthread_mutex_lock(&LOCK_gdl);
1149
DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
1150
my_free(used_list, MYF(0));
1155
DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
1156
my_free(free_list, MYF(0));
1160
global_ddl_log.inited= 0;
1161
pthread_mutex_unlock(&LOCK_gdl);
1162
VOID(pthread_mutex_destroy(&LOCK_gdl));
1163
global_ddl_log.do_release= false;
1169
---------------------------------------------------------------------------
1172
--------------------
1174
---------------------------------------------------------------------------
1182
clear_error is clear_error to be called
1184
query_length Length of query
1190
Write the binlog if open, routine used in multiple places in this
1194
void write_bin_log(THD *thd, bool clear_error,
1195
char const *query, ulong query_length)
1197
if (mysql_bin_log.is_open())
1201
thd->binlog_query(THD::STMT_QUERY_TYPE,
1202
query, query_length, FALSE, FALSE);
1208
delete (drop) tables.
1213
tables List of tables to delete
1214
if_exists If 1, don't give error if one table doesn't exists
1217
Will delete all tables that can be deleted and give a compact error
1218
messages for tables that could not be deleted.
1219
If a table is in use, we will wait for all users to free the table
1222
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
1223
not if under LOCK TABLES.
1226
FALSE OK. In this case ok packet is sent to user
1231
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
1232
my_bool drop_temporary)
1234
bool error, need_start_waiting= FALSE;
1235
DBUG_ENTER("mysql_rm_table");
1237
if (tables && tables->schema_table)
1239
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
1243
/* mark for close and remove all cached entries */
1245
if (!drop_temporary)
1247
if (!thd->locked_tables &&
1248
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
1253
Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
1254
LOCK_open during wait_if_global_read_lock(), other threads could not
1255
close their tables. This would make a pretty deadlock.
1257
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
1259
if (need_start_waiting)
1260
start_waiting_global_read_lock(thd);
1269
Execute the drop of a normal or temporary table
1272
mysql_rm_table_part2()
1274
tables Tables to drop
1275
if_exists If set, don't give an error if table doesn't exists.
1276
In this case we give an warning of level 'NOTE'
1277
drop_temporary Only drop temporary tables
1278
drop_view Allow to delete VIEW .frm
1279
dont_log_query Don't write query to log files. This will also not
1280
generate warnings if the handler files doesn't exists
1283
When logging to the binary log, we should log
1284
tmp_tables and transactional tables as separate statements if we
1285
are in a transaction; This is needed to get these tables into the
1286
cached binary log that is only written on COMMIT.
1288
The current code only writes DROP statements that only uses temporary
1289
tables to the cache binary log. This should be ok on most cases, but
1295
-1 Thread was killed
1298
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
1299
bool drop_temporary, bool drop_view,
1300
bool dont_log_query)
1303
char path[FN_REFLEN], *alias;
1305
String wrong_tables;
1307
int non_temp_tables_count= 0;
1308
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
1310
DBUG_ENTER("mysql_rm_table_part2");
1312
if (thd->current_stmt_binlog_row_based && !dont_log_query)
1314
built_query.set_charset(system_charset_info);
1316
built_query.append("DROP TABLE IF EXISTS ");
1318
built_query.append("DROP TABLE ");
1321
mysql_ha_rm_tables(thd, tables, FALSE);
1323
pthread_mutex_lock(&LOCK_open);
1326
If we have the table in the definition cache, we don't have to check the
1327
.frm file to find if the table is a normal table (not view) and what
1331
for (table= tables; table; table= table->next_local)
1334
table->db_type= NULL;
1335
if ((share= get_cached_table_share(table->db, table->table_name)))
1336
table->db_type= share->db_type();
1339
if (!drop_temporary && lock_table_names_exclusively(thd, tables))
1341
pthread_mutex_unlock(&LOCK_open);
1345
/* Don't give warnings for not found errors, as we already generate notes */
1346
thd->no_warnings_for_error= 1;
1348
for (table= tables; table; table= table->next_local)
1351
handlerton *table_type;
1352
enum legacy_db_type frm_db_type;
1354
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: 0x%lx s: 0x%lx",
1355
table->db, table->table_name, (long) table->table,
1356
table->table ? (long) table->table->s : (long) -1));
1358
error= drop_temporary_table(thd, table);
1362
// removed temporary table
1363
tmp_table_deleted= 1;
1366
DBUG_ASSERT(thd->in_sub_stmt);
1368
goto err_with_placeholders;
1370
// temporary table not found
1375
If row-based replication is used and the table is not a
1376
temporary table, we add the table name to the drop statement
1377
being built. The string always end in a comma and the comma
1378
will be chopped off before being written to the binary log.
1380
if (thd->current_stmt_binlog_row_based && !dont_log_query)
1382
non_temp_tables_count++;
1384
Don't write the database name if it is the current one (or if
1387
built_query.append("`");
1388
if (thd->db == NULL || strcmp(db,thd->db) != 0)
1390
built_query.append(db);
1391
built_query.append("`.`");
1394
built_query.append(table->table_name);
1395
built_query.append("`,");
1398
table_type= table->db_type;
1399
if (!drop_temporary)
1401
TABLE *locked_table;
1402
abort_locked_tables(thd, db, table->table_name);
1403
remove_table_from_cache(thd, db, table->table_name,
1404
RTFC_WAIT_OTHER_THREAD_FLAG |
1405
RTFC_CHECK_KILLED_FLAG);
1407
If the table was used in lock tables, remember it so that
1408
unlock_table_names can free it
1410
if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
1411
table->table= locked_table;
1416
goto err_with_placeholders;
1418
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
1419
/* remove .frm file and engine files */
1420
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1421
table->internal_tmp_table ?
1424
if (drop_temporary ||
1425
((table_type == NULL && (access(path, F_OK) && ha_create_table_from_engine(thd, db, alias))) ||
1426
(!drop_view && mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
1428
// Table was not found on disk and table can't be created from engine
1430
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1431
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
1439
if (table_type == NULL)
1441
mysql_frm_type(thd, path, &frm_db_type);
1442
table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
1444
// Remove extension for delete
1445
*(end= path + path_length - reg_ext_length)= '\0';
1446
error= ha_delete_table(thd, table_type, path, db, table->table_name,
1448
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
1449
(if_exists || table_type == NULL))
1454
if (error == HA_ERR_ROW_IS_REFERENCED)
1456
/* the table is referenced by a foreign key constraint */
1457
foreign_key_error=1;
1459
if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
1462
/* Delete the table definition file */
1463
strmov(end,reg_ext);
1464
if (!(new_error=my_delete(path,MYF(MY_WME))))
1466
some_tables_deleted=1;
1474
if (wrong_tables.length())
1475
wrong_tables.append(',');
1476
wrong_tables.append(String(table->table_name,system_charset_info));
1478
DBUG_PRINT("table", ("table: 0x%lx s: 0x%lx", (long) table->table,
1479
table->table ? (long) table->table->s : (long) -1));
1482
It's safe to unlock LOCK_open: we have an exclusive lock
1485
pthread_mutex_unlock(&LOCK_open);
1486
thd->thread_specific_used|= tmp_table_deleted;
1488
if (wrong_tables.length())
1490
if (!foreign_key_error)
1491
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
1492
wrong_tables.c_ptr());
1494
my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
1498
if (some_tables_deleted || tmp_table_deleted || !error)
1500
if (!dont_log_query)
1502
if (!thd->current_stmt_binlog_row_based ||
1503
(non_temp_tables_count > 0 && !tmp_table_deleted))
1506
In this case, we are either using statement-based
1507
replication or using row-based replication but have only
1508
deleted one or more non-temporary tables (and no temporary
1509
tables). In this case, we can write the original query into
1512
write_bin_log(thd, !error, thd->query, thd->query_length);
1514
else if (thd->current_stmt_binlog_row_based &&
1515
non_temp_tables_count > 0 &&
1519
In this case we have deleted both temporary and
1520
non-temporary tables, so:
1521
- since we have deleted a non-temporary table we have to
1522
binlog the statement, but
1523
- since we have deleted a temporary table we cannot binlog
1524
the statement (since the table has not been created on the
1525
slave, this might cause the slave to stop).
1527
Instead, we write a built statement, only containing the
1528
non-temporary tables, to the binary log
1530
built_query.chop(); // Chop of the last comma
1531
built_query.append(" /* generated by server */");
1532
write_bin_log(thd, !error, built_query.ptr(), built_query.length());
1535
The remaining cases are:
1536
- no tables where deleted and
1537
- only temporary tables where deleted and row-based
1538
replication is used.
1539
In both these cases, nothing should be written to the binary
1544
pthread_mutex_lock(&LOCK_open);
1545
err_with_placeholders:
1546
unlock_table_names(thd, tables, (TABLE_LIST*) 0);
1547
pthread_mutex_unlock(&LOCK_open);
1548
thd->no_warnings_for_error= 0;
1554
Quickly remove a table.
1558
base The handlerton handle.
1559
db The database name.
1560
table_name The table name.
1561
flags flags for build_table_filename().
1568
bool quick_rm_table(handlerton *base,const char *db,
1569
const char *table_name, uint flags)
1571
char path[FN_REFLEN];
1573
DBUG_ENTER("quick_rm_table");
1575
uint path_length= build_table_filename(path, sizeof(path),
1576
db, table_name, reg_ext, flags);
1577
if (my_delete(path,MYF(0)))
1578
error= 1; /* purecov: inspected */
1579
path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
1580
DBUG_RETURN(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
1585
Sort keys in the following order:
1587
- UNIQUE keys where all column are NOT NULL
1588
- UNIQUE keys that don't contain partial segments
1593
This will make checking for duplicated keys faster and ensure that
1594
PRIMARY keys are prioritized.
1597
static int sort_keys(KEY *a, KEY *b)
1599
ulong a_flags= a->flags, b_flags= b->flags;
1601
if (a_flags & HA_NOSAME)
1603
if (!(b_flags & HA_NOSAME))
1605
if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
1607
/* Sort NOT NULL keys before other keys */
1608
return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
1610
if (a->name == primary_key_name)
1612
if (b->name == primary_key_name)
1614
/* Sort keys don't containing partial segments before others */
1615
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
1616
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
1618
else if (b_flags & HA_NOSAME)
1619
return 1; // Prefer b
1622
Prefer original key order. usable_key_parts contains here
1623
the original key position.
1625
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
1626
(a->usable_key_parts > b->usable_key_parts) ? 1 :
1631
Check TYPELIB (set or enum) for duplicates
1634
check_duplicates_in_interval()
1635
set_or_name "SET" or "ENUM" string for warning message
1636
name name of the checked column
1637
typelib list of values for the column
1638
dup_val_count returns count of duplicate elements
1641
This function prints an warning for each value in list
1642
which has some duplicates on its right
1649
bool check_duplicates_in_interval(const char *set_or_name,
1650
const char *name, TYPELIB *typelib,
1651
CHARSET_INFO *cs, unsigned int *dup_val_count)
1653
TYPELIB tmp= *typelib;
1654
const char **cur_value= typelib->type_names;
1655
unsigned int *cur_length= typelib->type_lengths;
1658
for ( ; tmp.count > 1; cur_value++, cur_length++)
1663
if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
1665
my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
1666
name,*cur_value,set_or_name);
1675
Check TYPELIB (set or enum) max and total lengths
1678
calculate_interval_lengths()
1679
cs charset+collation pair of the interval
1680
typelib list of values for the column
1681
max_length length of the longest item
1682
tot_length sum of the item lengths
1685
After this function call:
1686
- ENUM uses max_length
1687
- SET uses tot_length.
1692
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
1693
uint32 *max_length, uint32 *tot_length)
1697
*max_length= *tot_length= 0;
1698
for (pos= interval->type_names, len= interval->type_lengths;
1699
*pos ; pos++, len++)
1701
uint length= cs->cset->numchars(cs, *pos, *pos + *len);
1702
*tot_length+= length;
1703
set_if_bigger(*max_length, (uint32)length);
1709
Prepare a create_table instance for packing
1712
prepare_create_field()
1713
sql_field field to prepare for packing
1714
blob_columns count for BLOBs
1715
timestamps count for timestamps
1716
table_flags table flags
1719
This function prepares a Create_field instance.
1720
Fields such as pack_flag are valid after this call.
1727
int prepare_create_field(Create_field *sql_field,
1729
int *timestamps, int *timestamps_with_niladic,
1730
longlong table_flags)
1732
unsigned int dup_val_count;
1733
DBUG_ENTER("prepare_field");
1736
This code came from mysql_prepare_create_table.
1737
Indent preserved to make patching easier
1739
DBUG_ASSERT(sql_field->charset);
1741
switch (sql_field->sql_type) {
1742
case MYSQL_TYPE_BLOB:
1743
case MYSQL_TYPE_MEDIUM_BLOB:
1744
case MYSQL_TYPE_TINY_BLOB:
1745
case MYSQL_TYPE_LONG_BLOB:
1746
sql_field->pack_flag=FIELDFLAG_BLOB |
1747
pack_length_to_packflag(sql_field->pack_length -
1748
portable_sizeof_char_ptr);
1749
if (sql_field->charset->state & MY_CS_BINSORT)
1750
sql_field->pack_flag|=FIELDFLAG_BINARY;
1751
sql_field->length=8; // Unireg field length
1752
sql_field->unireg_check=Field::BLOB_FIELD;
1755
case MYSQL_TYPE_VARCHAR:
1756
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
1757
if (table_flags & HA_NO_VARCHAR)
1759
/* convert VARCHAR to CHAR because handler is not yet up to date */
1760
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
1761
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
1762
(uint) sql_field->length);
1763
if ((sql_field->length / sql_field->charset->mbmaxlen) >
1764
MAX_FIELD_CHARLENGTH)
1766
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
1767
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
1773
case MYSQL_TYPE_STRING:
1774
sql_field->pack_flag=0;
1775
if (sql_field->charset->state & MY_CS_BINSORT)
1776
sql_field->pack_flag|=FIELDFLAG_BINARY;
1778
case MYSQL_TYPE_ENUM:
1779
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
1781
if (sql_field->charset->state & MY_CS_BINSORT)
1782
sql_field->pack_flag|=FIELDFLAG_BINARY;
1783
sql_field->unireg_check=Field::INTERVAL_FIELD;
1784
if (check_duplicates_in_interval("ENUM",sql_field->field_name,
1785
sql_field->interval,
1786
sql_field->charset, &dup_val_count))
1789
case MYSQL_TYPE_SET:
1790
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
1792
if (sql_field->charset->state & MY_CS_BINSORT)
1793
sql_field->pack_flag|=FIELDFLAG_BINARY;
1794
sql_field->unireg_check=Field::BIT_FIELD;
1795
if (check_duplicates_in_interval("SET",sql_field->field_name,
1796
sql_field->interval,
1797
sql_field->charset, &dup_val_count))
1799
/* Check that count of unique members is not more then 64 */
1800
if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
1802
my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
1806
case MYSQL_TYPE_DATE: // Rest of string types
1807
case MYSQL_TYPE_NEWDATE:
1808
case MYSQL_TYPE_TIME:
1809
case MYSQL_TYPE_DATETIME:
1810
case MYSQL_TYPE_NULL:
1811
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
1813
case MYSQL_TYPE_BIT:
1815
We have sql_field->pack_flag already set here, see
1816
mysql_prepare_create_table().
1819
case MYSQL_TYPE_NEWDECIMAL:
1820
sql_field->pack_flag=(FIELDFLAG_NUMBER |
1821
(sql_field->flags & UNSIGNED_FLAG ? 0 :
1822
FIELDFLAG_DECIMAL) |
1823
(sql_field->flags & ZEROFILL_FLAG ?
1824
FIELDFLAG_ZEROFILL : 0) |
1825
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
1827
case MYSQL_TYPE_TIMESTAMP:
1828
/* We should replace old TIMESTAMP fields with their newer analogs */
1829
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
1833
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
1834
(*timestamps_with_niladic)++;
1837
sql_field->unireg_check= Field::NONE;
1839
else if (sql_field->unireg_check != Field::NONE)
1840
(*timestamps_with_niladic)++;
1845
sql_field->pack_flag=(FIELDFLAG_NUMBER |
1846
(sql_field->flags & UNSIGNED_FLAG ? 0 :
1847
FIELDFLAG_DECIMAL) |
1848
(sql_field->flags & ZEROFILL_FLAG ?
1849
FIELDFLAG_ZEROFILL : 0) |
1850
f_settype((uint) sql_field->sql_type) |
1851
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
1854
if (!(sql_field->flags & NOT_NULL_FLAG))
1855
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
1856
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
1857
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
1862
Preparation for table creation
1865
mysql_prepare_create_table()
1867
create_info Create information (like MAX_ROWS).
1868
alter_info List of columns and indexes to create
1869
tmp_table If a temporary table is to be created.
1870
db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
1871
file The handler for the new table.
1872
key_info_buffer OUT An array of KEY structs for the indexes.
1873
key_count OUT The number of elements in the array.
1874
select_field_count The number of fields coming from a select table.
1877
Prepares the table and key structures for table creation.
1880
sets create_info->varchar if the table has a varchar
1888
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
1889
Alter_info *alter_info,
1892
handler *file, KEY **key_info_buffer,
1893
uint *key_count, int select_field_count)
1895
const char *key_name;
1896
Create_field *sql_field,*dup_field;
1897
uint field,null_fields,blob_columns,max_key_length;
1898
ulong record_offset= 0;
1900
KEY_PART_INFO *key_part_info;
1901
int timestamps= 0, timestamps_with_niladic= 0;
1902
int field_no,dup_no;
1903
int select_field_pos,auto_increment=0;
1904
List_iterator<Create_field> it(alter_info->create_list);
1905
List_iterator<Create_field> it2(alter_info->create_list);
1906
uint total_uneven_bit_length= 0;
1907
DBUG_ENTER("mysql_prepare_create_table");
1909
select_field_pos= alter_info->create_list.elements - select_field_count;
1910
null_fields=blob_columns=0;
1911
create_info->varchar= 0;
1912
max_key_length= file->max_key_length();
1914
for (field_no=0; (sql_field=it++) ; field_no++)
1916
CHARSET_INFO *save_cs;
1919
Initialize length from its original value (number of characters),
1920
which was set in the parser. This is necessary if we're
1921
executing a prepared statement for the second time.
1923
sql_field->length= sql_field->char_length;
1924
if (!sql_field->charset)
1925
sql_field->charset= create_info->default_table_charset;
1927
table_charset is set in ALTER TABLE if we want change character set
1928
for all varchar/char columns.
1929
But the table charset must not affect the BLOB fields, so don't
1930
allow to change my_charset_bin to somethig else.
1932
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
1933
sql_field->charset= create_info->table_charset;
1935
save_cs= sql_field->charset;
1936
if ((sql_field->flags & BINCMP_FLAG) &&
1937
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
1938
MY_CS_BINSORT,MYF(0))))
1941
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
1942
STRING_WITH_LEN("_bin"));
1943
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
1948
Convert the default value from client character
1949
set into the column character set if necessary.
1951
if (sql_field->def &&
1952
save_cs != sql_field->def->collation.collation &&
1953
(sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
1954
sql_field->sql_type == MYSQL_TYPE_STRING ||
1955
sql_field->sql_type == MYSQL_TYPE_SET ||
1956
sql_field->sql_type == MYSQL_TYPE_ENUM))
1959
Starting from 5.1 we work here with a copy of Create_field
1960
created by the caller, not with the instance that was
1961
originally created during parsing. It's OK to create
1962
a temporary item and initialize with it a member of the
1963
copy -- this item will be thrown away along with the copy
1964
at the end of execution, and thus not introduce a dangling
1965
pointer in the parsed tree of a prepared statement or a
1966
stored procedure statement.
1968
sql_field->def= sql_field->def->safe_charset_converter(save_cs);
1970
if (sql_field->def == NULL)
1972
/* Could not convert */
1973
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1978
if (sql_field->sql_type == MYSQL_TYPE_SET ||
1979
sql_field->sql_type == MYSQL_TYPE_ENUM)
1982
CHARSET_INFO *cs= sql_field->charset;
1983
TYPELIB *interval= sql_field->interval;
1986
Create typelib from interval_list, and if necessary
1987
convert strings from client character set to the
1988
column character set.
1993
Create the typelib in runtime memory - we will free the
1994
occupied memory at the same time when we free this
1995
sql_field -- at the end of execution.
1997
interval= sql_field->interval= typelib(thd->mem_root,
1998
sql_field->interval_list);
1999
List_iterator<String> int_it(sql_field->interval_list);
2002
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
2003
(uchar*) comma_buf +
2005
DBUG_ASSERT(comma_length > 0);
2006
for (uint i= 0; (tmp= int_it++); i++)
2009
if (String::needs_conversion(tmp->length(), tmp->charset(),
2013
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
2014
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
2016
interval->type_lengths[i]= conv.length();
2019
// Strip trailing spaces.
2020
lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
2021
interval->type_lengths[i]);
2022
interval->type_lengths[i]= lengthsp;
2023
((uchar *)interval->type_names[i])[lengthsp]= '\0';
2024
if (sql_field->sql_type == MYSQL_TYPE_SET)
2026
if (cs->coll->instr(cs, interval->type_names[i],
2027
interval->type_lengths[i],
2028
comma_buf, comma_length, NULL, 0))
2030
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
2035
sql_field->interval_list.empty(); // Don't need interval_list anymore
2038
if (sql_field->sql_type == MYSQL_TYPE_SET)
2040
uint32 field_length;
2041
if (sql_field->def != NULL)
2046
String str, *def= sql_field->def->val_str(&str);
2047
if (def == NULL) /* SQL "NULL" maps to NULL */
2049
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
2051
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
2055
/* else, NULL is an allowed value */
2056
(void) find_set(interval, NULL, 0,
2057
cs, ¬_used, ¬_used2, ¬_found);
2061
(void) find_set(interval, def->ptr(), def->length(),
2062
cs, ¬_used, ¬_used2, ¬_found);
2067
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
2071
calculate_interval_lengths(cs, interval, &dummy, &field_length);
2072
sql_field->length= field_length + (interval->count - 1);
2074
else /* MYSQL_TYPE_ENUM */
2076
uint32 field_length;
2077
DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
2078
if (sql_field->def != NULL)
2080
String str, *def= sql_field->def->val_str(&str);
2081
if (def == NULL) /* SQL "NULL" maps to NULL */
2083
if ((sql_field->flags & NOT_NULL_FLAG) != 0)
2085
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
2089
/* else, the defaults yield the correct length for NULLs. */
2093
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
2094
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
2096
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
2101
calculate_interval_lengths(cs, interval, &field_length, &dummy);
2102
sql_field->length= field_length;
2104
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
2107
if (sql_field->sql_type == MYSQL_TYPE_BIT)
2109
sql_field->pack_flag= FIELDFLAG_NUMBER;
2110
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
2111
total_uneven_bit_length+= sql_field->length & 7;
2113
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
2116
sql_field->create_length_to_internal_length();
2117
if (prepare_blob_field(thd, sql_field))
2120
if (!(sql_field->flags & NOT_NULL_FLAG))
2123
if (check_column_name(sql_field->field_name))
2125
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
2129
/* Check if we have used the same field name before */
2130
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
2132
if (my_strcasecmp(system_charset_info,
2133
sql_field->field_name,
2134
dup_field->field_name) == 0)
2137
If this was a CREATE ... SELECT statement, accept a field
2138
redefinition if we are changing a field in the SELECT part
2140
if (field_no < select_field_pos || dup_no >= select_field_pos)
2142
my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
2147
/* Field redefined */
2148
sql_field->def= dup_field->def;
2149
sql_field->sql_type= dup_field->sql_type;
2150
sql_field->charset= (dup_field->charset ?
2151
dup_field->charset :
2152
create_info->default_table_charset);
2153
sql_field->length= dup_field->char_length;
2154
sql_field->pack_length= dup_field->pack_length;
2155
sql_field->key_length= dup_field->key_length;
2156
sql_field->decimals= dup_field->decimals;
2157
sql_field->create_length_to_internal_length();
2158
sql_field->unireg_check= dup_field->unireg_check;
2160
We're making one field from two, the result field will have
2161
dup_field->flags as flags. If we've incremented null_fields
2162
because of sql_field->flags, decrement it back.
2164
if (!(sql_field->flags & NOT_NULL_FLAG))
2166
sql_field->flags= dup_field->flags;
2167
sql_field->interval= dup_field->interval;
2168
it2.remove(); // Remove first (create) definition
2174
/* Don't pack rows in old tables if the user has requested this */
2175
if ((sql_field->flags & BLOB_FLAG) ||
2176
(sql_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
2177
(*db_options)|= HA_OPTION_PACK_RECORD;
2181
/* record_offset will be increased with 'length-of-null-bits' later */
2183
null_fields+= total_uneven_bit_length;
2186
while ((sql_field=it++))
2188
DBUG_ASSERT(sql_field->charset != 0);
2190
if (prepare_create_field(sql_field, &blob_columns,
2191
×tamps, ×tamps_with_niladic,
2192
file->ha_table_flags()))
2194
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
2195
create_info->varchar= TRUE;
2196
sql_field->offset= record_offset;
2197
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
2199
record_offset+= sql_field->pack_length;
2201
if (timestamps_with_niladic > 1)
2203
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
2204
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
2207
if (auto_increment > 1)
2209
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
2212
if (auto_increment &&
2213
(file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
2215
my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
2216
ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
2220
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
2222
my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
2229
List_iterator<Key> key_iterator(alter_info->key_list);
2230
List_iterator<Key> key_iterator2(alter_info->key_list);
2231
uint key_parts=0, fk_key_count=0;
2232
bool primary_key=0,unique_key=0;
2234
uint tmp, key_number;
2235
/* special marker for keys to be ignored */
2236
static char ignore_key[1];
2238
/* Calculate number of key segements */
2241
while ((key=key_iterator++))
2243
DBUG_PRINT("info", ("key name: '%s' type: %d", key->name.str ? key->name.str :
2244
"(none)" , key->type));
2245
if (key->type == Key::FOREIGN_KEY)
2248
Foreign_key *fk_key= (Foreign_key*) key;
2249
if (fk_key->ref_columns.elements &&
2250
fk_key->ref_columns.elements != fk_key->columns.elements)
2252
my_error(ER_WRONG_FK_DEF, MYF(0),
2253
(fk_key->name.str ? fk_key->name.str :
2254
"foreign key without name"),
2255
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
2261
tmp=file->max_key_parts();
2262
if (key->columns.elements > tmp)
2264
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
2267
if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
2269
key_iterator2.rewind ();
2270
if (key->type != Key::FOREIGN_KEY)
2272
while ((key2 = key_iterator2++) != key)
2275
foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
2276
'generated', and a generated key is a prefix of the other key.
2277
Then we do not need the generated shorter key.
2279
if ((key2->type != Key::FOREIGN_KEY &&
2280
key2->name.str != ignore_key &&
2281
!foreign_key_prefix(key, key2)))
2283
/* TODO: issue warning message */
2284
/* mark that the generated key should be ignored */
2285
if (!key2->generated ||
2286
(key->generated && key->columns.elements <
2287
key2->columns.elements))
2288
key->name.str= ignore_key;
2291
key2->name.str= ignore_key;
2292
key_parts-= key2->columns.elements;
2299
if (key->name.str != ignore_key)
2300
key_parts+=key->columns.elements;
2303
if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
2304
!my_strcasecmp(system_charset_info,key->name.str, primary_key_name))
2306
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
2310
tmp=file->max_keys();
2311
if (*key_count > tmp)
2313
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
2317
(*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
2318
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
2319
if (!*key_info_buffer || ! key_part_info)
2320
DBUG_RETURN(TRUE); // Out of memory
2322
key_iterator.rewind();
2324
for (; (key=key_iterator++) ; key_number++)
2327
Key_part_spec *column;
2329
if (key->name.str == ignore_key)
2331
/* ignore redundant keys */
2334
while (key && key->name.str == ignore_key);
2339
switch (key->type) {
2343
case Key::FOREIGN_KEY:
2344
key_number--; // Skip this key
2347
key_info->flags = HA_NOSAME;
2351
key_info->flags|= HA_GENERATED_KEY;
2353
key_info->key_parts=(uint8) key->columns.elements;
2354
key_info->key_part=key_part_info;
2355
key_info->usable_key_parts= key_number;
2356
key_info->algorithm= key->key_create_info.algorithm;
2358
/* Take block size from key part or table part */
2360
TODO: Add warning if block size changes. We can't do it here, as
2361
this may depend on the size of the key
2363
key_info->block_size= (key->key_create_info.block_size ?
2364
key->key_create_info.block_size :
2365
create_info->key_block_size);
2367
if (key_info->block_size)
2368
key_info->flags|= HA_USES_BLOCK_SIZE;
2370
uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
2371
key->key_create_info.comment.str,
2372
key->key_create_info.comment.str +
2373
key->key_create_info.comment.length,
2374
INDEX_COMMENT_MAXLEN);
2376
if (tmp_len < key->key_create_info.comment.length)
2378
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
2379
key->key_create_info.comment.str,"INDEX COMMENT",
2380
(uint) INDEX_COMMENT_MAXLEN);
2384
key_info->comment.length= key->key_create_info.comment.length;
2385
if (key_info->comment.length > 0)
2387
key_info->flags|= HA_USES_COMMENT;
2388
key_info->comment.str= key->key_create_info.comment.str;
2391
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
2392
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
2395
Key_part_spec *dup_column;
2399
while ((sql_field=it++) &&
2400
my_strcasecmp(system_charset_info,
2401
column->field_name.str,
2402
sql_field->field_name))
2406
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
2409
while ((dup_column= cols2++) != column)
2411
if (!my_strcasecmp(system_charset_info,
2412
column->field_name.str, dup_column->field_name.str))
2414
my_printf_error(ER_DUP_FIELDNAME,
2415
ER(ER_DUP_FIELDNAME),MYF(0),
2416
column->field_name.str);
2422
column->length*= sql_field->charset->mbmaxlen;
2424
if (f_is_blob(sql_field->pack_flag))
2426
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
2428
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
2431
if (!column->length)
2433
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
2437
if (!(sql_field->flags & NOT_NULL_FLAG))
2439
if (key->type == Key::PRIMARY)
2441
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
2442
sql_field->flags|= NOT_NULL_FLAG;
2443
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
2448
key_info->flags|= HA_NULL_PART_KEY;
2449
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
2451
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
2456
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
2458
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
2459
auto_increment--; // Field is used
2463
key_part_info->fieldnr= field;
2464
key_part_info->offset= (uint16) sql_field->offset;
2465
key_part_info->key_type=sql_field->pack_flag;
2466
length= sql_field->key_length;
2470
if (f_is_blob(sql_field->pack_flag))
2472
if ((length=column->length) > max_key_length ||
2473
length > file->max_key_part_length())
2475
length=min(max_key_length, file->max_key_part_length());
2476
if (key->type == Key::MULTIPLE)
2478
/* not a critical problem */
2479
char warn_buff[MYSQL_ERRMSG_SIZE];
2480
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
2482
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2483
ER_TOO_LONG_KEY, warn_buff);
2484
/* Align key length to multibyte char boundary */
2485
length-= length % sql_field->charset->mbmaxlen;
2489
my_error(ER_TOO_LONG_KEY,MYF(0),length);
2494
else if ((column->length > length ||
2495
!Field::type_can_have_key_part (sql_field->sql_type) ||
2496
((f_is_packed(sql_field->pack_flag) ||
2497
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
2498
(key_info->flags & HA_NOSAME))) &&
2499
column->length != length)))
2501
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
2504
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
2505
length=column->length;
2507
else if (length == 0)
2509
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
2512
if (length > file->max_key_part_length())
2514
length= file->max_key_part_length();
2515
if (key->type == Key::MULTIPLE)
2517
/* not a critical problem */
2518
char warn_buff[MYSQL_ERRMSG_SIZE];
2519
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
2521
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2522
ER_TOO_LONG_KEY, warn_buff);
2523
/* Align key length to multibyte char boundary */
2524
length-= length % sql_field->charset->mbmaxlen;
2528
my_error(ER_TOO_LONG_KEY,MYF(0),length);
2532
key_part_info->length=(uint16) length;
2533
/* Use packed keys for long strings on the first column */
2534
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
2535
(length >= KEY_DEFAULT_PACK_LENGTH &&
2536
(sql_field->sql_type == MYSQL_TYPE_STRING ||
2537
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
2538
sql_field->pack_flag & FIELDFLAG_BLOB)))
2540
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
2541
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
2542
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
2544
key_info->flags|= HA_PACK_KEY;
2546
/* Check if the key segment is partial, set the key flag accordingly */
2547
if (length != sql_field->key_length)
2548
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
2553
/* Create the key name based on the first column (if not given) */
2556
if (key->type == Key::PRIMARY)
2560
my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
2564
key_name=primary_key_name;
2567
else if (!(key_name= key->name.str))
2568
key_name=make_unique_key_name(sql_field->field_name,
2569
*key_info_buffer, key_info);
2570
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
2572
my_error(ER_DUP_KEYNAME, MYF(0), key_name);
2575
key_info->name=(char*) key_name;
2578
if (!key_info->name || check_column_name(key_info->name))
2580
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
2583
if (!(key_info->flags & HA_NULL_PART_KEY))
2585
key_info->key_length=(uint16) key_length;
2586
if (key_length > max_key_length)
2588
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
2593
if (!unique_key && !primary_key &&
2594
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
2596
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
2599
if (auto_increment > 0)
2601
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
2604
/* Sort keys in optimized order */
2605
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
2606
(qsort_cmp) sort_keys);
2607
create_info->null_bits= null_fields;
2611
while ((sql_field=it++))
2613
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
2615
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
2617
sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
2618
(sql_field->flags & NOT_NULL_FLAG) &&
2619
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
2622
An error should be reported if:
2623
- NO_ZERO_DATE SQL mode is active;
2624
- there is no explicit DEFAULT clause (default column value);
2625
- this is a TIMESTAMP column;
2626
- the column is not NULL;
2627
- this is not the DEFAULT CURRENT_TIMESTAMP column.
2629
In other words, an error should be reported if
2630
- NO_ZERO_DATE SQL mode is active;
2631
- the column definition is equivalent to
2632
'column_name TIMESTAMP DEFAULT 0'.
2635
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
2645
Set table default charset, if not set
2648
set_table_default_charset()
2649
create_info Table create information
2652
If the table character set was not given explicitely,
2653
let's fetch the database default character set and
2654
apply it to the table.
2657
static void set_table_default_charset(THD *thd,
2658
HA_CREATE_INFO *create_info, char *db)
2661
If the table character set was not given explicitly,
2662
let's fetch the database default character set and
2663
apply it to the table.
2665
if (!create_info->default_table_charset)
2667
HA_CREATE_INFO db_info;
2669
load_db_opt_by_name(thd, db, &db_info);
2671
create_info->default_table_charset= db_info.default_table_charset;
2677
Extend long VARCHAR fields to blob & prepare field if it's a blob
2680
prepare_blob_field()
2681
sql_field Field to check
2685
1 Error (sql_field can't be converted to blob)
2686
In this case the error is given
2689
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
2691
DBUG_ENTER("prepare_blob_field");
2693
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
2694
!(sql_field->flags & BLOB_FLAG))
2696
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
2697
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
2701
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
2703
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
2705
/* The user has given a length to the blob column */
2706
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
2707
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
2709
sql_field->length= 0;
2716
Preparation of Create_field for SP function return values.
2717
Based on code used in the inner loop of mysql_prepare_create_table()
2721
sp_prepare_create_field()
2723
sql_field Field to prepare
2726
Prepares the field structures for field creation.
2730
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
2732
if (sql_field->sql_type == MYSQL_TYPE_SET ||
2733
sql_field->sql_type == MYSQL_TYPE_ENUM)
2735
uint32 field_length, dummy;
2736
if (sql_field->sql_type == MYSQL_TYPE_SET)
2738
calculate_interval_lengths(sql_field->charset,
2739
sql_field->interval, &dummy,
2741
sql_field->length= field_length +
2742
(sql_field->interval->count - 1);
2744
else /* MYSQL_TYPE_ENUM */
2746
calculate_interval_lengths(sql_field->charset,
2747
sql_field->interval,
2748
&field_length, &dummy);
2749
sql_field->length= field_length;
2751
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
2754
if (sql_field->sql_type == MYSQL_TYPE_BIT)
2756
sql_field->pack_flag= FIELDFLAG_NUMBER |
2757
FIELDFLAG_TREAT_BIT_AS_CHAR;
2759
sql_field->create_length_to_internal_length();
2760
DBUG_ASSERT(sql_field->def == 0);
2761
/* Can't go wrong as sql_field->def is not defined */
2762
(void) prepare_blob_field(thd, sql_field);
2770
mysql_create_table_no_lock()
2773
table_name Table name
2774
create_info Create information (like MAX_ROWS)
2775
fields List of fields to create
2776
keys List of keys to create
2777
internal_tmp_table Set to 1 if this is an internal temporary table
2782
If one creates a temporary table, this is automatically opened
2784
Note that this function assumes that caller already have taken
2785
name-lock on table being created or used some other way to ensure
2786
that concurrent operations won't intervene. mysql_create_table()
2787
is a wrapper that can be used for this.
2789
no_log is needed for the case of CREATE ... SELECT,
2790
as the logging will be done later in sql_insert.cc
2791
select_field_count is also used for CREATE ... SELECT,
2792
and must be zero for standard create of table.
2799
bool mysql_create_table_no_lock(THD *thd,
2800
const char *db, const char *table_name,
2801
HA_CREATE_INFO *create_info,
2802
Alter_info *alter_info,
2803
bool internal_tmp_table,
2804
uint select_field_count)
2806
char path[FN_REFLEN];
2809
uint db_options, key_count;
2810
KEY *key_info_buffer;
2813
DBUG_ENTER("mysql_create_table_no_lock");
2814
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
2815
db, table_name, internal_tmp_table));
2818
/* Check for duplicate fields and check type of table to create */
2819
if (!alter_info->create_list.elements)
2821
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
2825
if (check_engine(thd, table_name, create_info))
2827
db_options= create_info->table_options;
2828
if (create_info->row_type == ROW_TYPE_DYNAMIC)
2829
db_options|=HA_OPTION_PACK_RECORD;
2830
alias= table_case_name(create_info, table_name);
2831
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
2832
create_info->db_type)))
2834
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
2838
set_table_default_charset(thd, create_info, (char*) db);
2840
if (mysql_prepare_create_table(thd, create_info, alter_info,
2843
&key_info_buffer, &key_count,
2844
select_field_count))
2847
/* Check if table exists */
2848
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2850
path_length= build_tmptable_filename(thd, path, sizeof(path));
2851
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
2856
/* check if the table name contains FN_DEVCHAR when defined */
2857
if (strchr(alias, FN_DEVCHAR))
2859
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
2863
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
2864
internal_tmp_table ? FN_IS_TMP : 0);
2867
/* Check if table already exists */
2868
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
2869
find_temporary_table(thd, db, table_name))
2871
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2873
create_info->table_existed= 1; // Mark that table existed
2874
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2875
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
2880
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
2884
VOID(pthread_mutex_lock(&LOCK_open));
2885
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2887
if (!access(path,F_OK))
2889
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2891
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2892
goto unlock_and_end;
2895
We don't assert here, but check the result, because the table could be
2896
in the table definition cache and in the same time the .frm could be
2897
missing from the disk, in case of manual intervention which deletes
2898
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
2899
Then she could create the table. This case is pretty obscure and
2900
therefore we don't introduce a new error message only for it.
2902
if (get_cached_table_share(db, alias))
2904
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2905
goto unlock_and_end;
2910
Check that table with given name does not already
2911
exist in any storage engine. In such a case it should
2912
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
2913
unless user specified CREATE TABLE IF EXISTS
2914
The LOCK_open mutex has been locked to make sure no
2915
one else is attempting to discover the table. Since
2916
it's not on disk as a frm file, no one could be using it!
2918
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2920
bool create_if_not_exists =
2921
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
2922
int retcode = ha_table_exists_in_engine(thd, db, table_name);
2923
DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
2926
case HA_ERR_NO_SUCH_TABLE:
2927
/* Normal case, no table exists. we can go and create it */
2929
case HA_ERR_TABLE_EXIST:
2930
DBUG_PRINT("info", ("Table existed in handler"));
2932
if (create_if_not_exists)
2934
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2935
goto unlock_and_end;
2938
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
2939
my_error(retcode, MYF(0),table_name);
2940
goto unlock_and_end;
2944
thd_proc_info(thd, "creating table");
2945
create_info->table_existed= 0; // Mark that table is created
2947
#ifdef HAVE_READLINK
2948
if (test_if_data_home_dir(create_info->data_file_name))
2950
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
2951
goto unlock_and_end;
2953
if (test_if_data_home_dir(create_info->index_file_name))
2955
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
2956
goto unlock_and_end;
2960
#endif /* HAVE_READLINK */
2962
if (create_info->data_file_name)
2963
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
2964
"DATA DIRECTORY option ignored");
2965
if (create_info->index_file_name)
2966
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
2967
"INDEX DIRECTORY option ignored");
2968
create_info->data_file_name= create_info->index_file_name= 0;
2970
create_info->table_options=db_options;
2972
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
2973
if (rea_create_table(thd, path, db, table_name,
2974
create_info, alter_info->create_list,
2975
key_count, key_info_buffer, file))
2976
goto unlock_and_end;
2978
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2980
/* Open table and put in temporary table list */
2981
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
2983
(void) rm_temporary_table(create_info->db_type, path, false);
2984
goto unlock_and_end;
2986
thd->thread_specific_used= TRUE;
2990
Don't write statement if:
2991
- It is an internal temporary table,
2992
- Row-based logging is used and it we are creating a temporary table, or
2993
- The binary log is not open.
2994
Otherwise, the statement shall be binlogged.
2996
if (!internal_tmp_table &&
2997
(!thd->current_stmt_binlog_row_based ||
2998
(thd->current_stmt_binlog_row_based &&
2999
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
3000
write_bin_log(thd, TRUE, thd->query, thd->query_length);
3003
VOID(pthread_mutex_unlock(&LOCK_open));
3006
thd_proc_info(thd, "After create");
3012
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
3013
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
3015
create_info->table_existed= 1; // Mark that table existed
3016
goto unlock_and_end;
3021
Database locking aware wrapper for mysql_create_table_no_lock(),
3024
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
3025
HA_CREATE_INFO *create_info,
3026
Alter_info *alter_info,
3027
bool internal_tmp_table,
3028
uint select_field_count)
3030
TABLE *name_lock= 0;
3032
DBUG_ENTER("mysql_create_table");
3034
/* Wait for any database locks */
3035
pthread_mutex_lock(&LOCK_lock_db);
3036
while (!thd->killed &&
3037
hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
3039
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
3040
pthread_mutex_lock(&LOCK_lock_db);
3045
pthread_mutex_unlock(&LOCK_lock_db);
3049
pthread_mutex_unlock(&LOCK_lock_db);
3051
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
3053
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
3060
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
3062
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
3063
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
3065
create_info->table_existed= 1;
3070
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
3077
result= mysql_create_table_no_lock(thd, db, table_name, create_info,
3080
select_field_count);
3085
pthread_mutex_lock(&LOCK_open);
3086
unlink_open_table(thd, name_lock, FALSE);
3087
pthread_mutex_unlock(&LOCK_open);
3089
pthread_mutex_lock(&LOCK_lock_db);
3090
if (!--creating_table && creating_database)
3091
pthread_cond_signal(&COND_refresh);
3092
pthread_mutex_unlock(&LOCK_lock_db);
3093
DBUG_RETURN(result);
3098
** Give the key name after the first field with an optional '_#' after
3102
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
3104
for (KEY *key=start ; key != end ; key++)
3105
if (!my_strcasecmp(system_charset_info,name,key->name))
3112
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
3114
char buff[MAX_FIELD_NAME],*buff_end;
3116
if (!check_if_keyname_exists(field_name,start,end) &&
3117
my_strcasecmp(system_charset_info,field_name,primary_key_name))
3118
return (char*) field_name; // Use fieldname
3119
buff_end=strmake(buff,field_name, sizeof(buff)-4);
3122
Only 3 chars + '\0' left, so need to limit to 2 digit
3123
This is ok as we can't have more than 100 keys anyway
3125
for (uint i=2 ; i< 100; i++)
3128
int10_to_str(i, buff_end+1, 10);
3129
if (!check_if_keyname_exists(buff,start,end))
3130
return sql_strdup(buff);
3132
return (char*) "not_specified"; // Should never happen
3136
/****************************************************************************
3137
** Alter a table definition
3138
****************************************************************************/
3145
mysql_rename_table()
3146
base The handlerton handle.
3147
old_db The old database name.
3148
old_name The old table name.
3149
new_db The new database name.
3150
new_name The new table name.
3151
flags flags for build_table_filename().
3152
FN_FROM_IS_TMP old_name is temporary.
3153
FN_TO_IS_TMP new_name is temporary.
3154
NO_FRM_RENAME Don't rename the FRM file
3155
but only the table in the storage engine.
3163
mysql_rename_table(handlerton *base, const char *old_db,
3164
const char *old_name, const char *new_db,
3165
const char *new_name, uint flags)
3167
THD *thd= current_thd;
3168
char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
3169
char *from_base= from, *to_base= to;
3170
char tmp_name[NAME_LEN+1];
3173
DBUG_ENTER("mysql_rename_table");
3174
DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'",
3175
old_db, old_name, new_db, new_name));
3177
file= (base == NULL ? 0 :
3178
get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
3180
build_table_filename(from, sizeof(from), old_db, old_name, "",
3181
flags & FN_FROM_IS_TMP);
3182
build_table_filename(to, sizeof(to), new_db, new_name, "",
3183
flags & FN_TO_IS_TMP);
3186
If lower_case_table_names == 2 (case-preserving but case-insensitive
3187
file system) and the storage is not HA_FILE_BASED, we need to provide
3188
a lowercase file name, but we leave the .frm in mixed case.
3190
if (lower_case_table_names == 2 && file &&
3191
!(file->ha_table_flags() & HA_FILE_BASED))
3193
strmov(tmp_name, old_name);
3194
my_casedn_str(files_charset_info, tmp_name);
3195
build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
3196
flags & FN_FROM_IS_TMP);
3199
strmov(tmp_name, new_name);
3200
my_casedn_str(files_charset_info, tmp_name);
3201
build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
3202
flags & FN_TO_IS_TMP);
3205
if (!file || !(error=file->ha_rename_table(from_base, to_base)))
3207
if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
3210
/* Restore old file name */
3212
file->ha_rename_table(to_base, from_base);
3216
if (error == HA_ERR_WRONG_COMMAND)
3217
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
3219
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
3220
DBUG_RETURN(error != 0);
3225
Force all other threads to stop using the table
3228
wait_while_table_is_used()
3230
table Table to remove from cache
3231
function HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
3232
HA_EXTRA_FORCE_REOPEN if table is not be used
3233
HA_EXTRA_PREPARE_FOR_RENAME if table is to be renamed
3235
When returning, the table will be unusable for other threads until
3236
the table is closed.
3240
Win32 clients must also have a WRITE LOCK on the table !
3243
void wait_while_table_is_used(THD *thd, TABLE *table,
3244
enum ha_extra_function function)
3246
DBUG_ENTER("wait_while_table_is_used");
3247
DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu",
3248
table->s->table_name.str, (ulong) table->s,
3249
table->db_stat, table->s->version));
3251
safe_mutex_assert_owner(&LOCK_open);
3253
VOID(table->file->extra(function));
3254
/* Mark all tables that are in use as 'old' */
3255
mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */
3257
/* Wait until all there are no other threads that has this table open */
3258
remove_table_from_cache(thd, table->s->db.str,
3259
table->s->table_name.str,
3260
RTFC_WAIT_OTHER_THREAD_FLAG);
3265
Close a cached table
3268
close_cached_table()
3270
table Table to remove from cache
3273
Function ends by signaling threads waiting for the table to try to
3278
Win32 clients must also have a WRITE LOCK on the table !
3281
void close_cached_table(THD *thd, TABLE *table)
3283
DBUG_ENTER("close_cached_table");
3285
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3286
/* Close lock if this is not got with LOCK TABLES */
3289
mysql_unlock_tables(thd, thd->lock);
3290
thd->lock=0; // Start locked threads
3292
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
3293
unlink_open_table(thd, table, TRUE);
3295
/* When lock on LOCK_open is freed other threads can continue */
3296
broadcast_refresh();
3300
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
3301
const char* operator_name, const char* errmsg)
3304
Protocol *protocol= thd->protocol;
3305
protocol->prepare_for_resend();
3306
protocol->store(table->alias, system_charset_info);
3307
protocol->store((char*) operator_name, system_charset_info);
3308
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3309
protocol->store(errmsg, system_charset_info);
3311
if (protocol->write())
3317
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
3318
HA_CHECK_OPT *check_opt)
3321
TABLE tmp_table, *table;
3323
char from[FN_REFLEN],tmp[FN_REFLEN+32];
3326
DBUG_ENTER("prepare_for_repair");
3328
if (!(check_opt->sql_flags & TT_USEFRM))
3331
if (!(table= table_list->table)) /* if open_ltable failed */
3333
char key[MAX_DBKEY_LENGTH];
3336
key_length= create_table_def_key(thd, key, table_list, 0);
3337
pthread_mutex_lock(&LOCK_open);
3338
if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
3341
pthread_mutex_unlock(&LOCK_open);
3342
DBUG_RETURN(0); // Can't open frm file
3345
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
3347
release_table_share(share, RELEASE_NORMAL);
3348
pthread_mutex_unlock(&LOCK_open);
3349
DBUG_RETURN(0); // Out of memory
3352
pthread_mutex_unlock(&LOCK_open);
3356
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
3358
if (table->s->tmp_table)
3360
error= send_check_errmsg(thd, table_list, "repair",
3361
"Cannot repair temporary table from .frm file");
3366
User gave us USE_FRM which means that the header in the index file is
3368
In this case we will try to fix the table the following way:
3369
- Rename the data file to a temporary name
3370
- Truncate the table
3371
- Replace the new data file with the old one
3372
- Run a normal repair using the new index file and the old data file
3376
Check if this is a table type that stores index and data separately,
3377
like ISAM or MyISAM. We assume fixed order of engine file name
3378
extentions array. First element of engine file name extentions array
3379
is meta/index file extention. Second element - data file extention.
3381
ext= table->file->bas_ext();
3382
if (!ext[0] || !ext[1])
3383
goto end; // No data file
3385
// Name of data file
3386
strxmov(from, table->s->normalized_path.str, ext[1], NullS);
3387
if (!my_stat(from, &stat_info, MYF(0)))
3388
goto end; // Can't use USE_FRM flag
3390
my_snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
3391
from, current_pid, thd->thread_id);
3393
/* If we could open the table, close it */
3394
if (table_list->table)
3396
pthread_mutex_lock(&LOCK_open);
3397
close_cached_table(thd, table);
3398
pthread_mutex_unlock(&LOCK_open);
3400
if (lock_and_wait_for_table_name(thd,table_list))
3405
if (my_rename(from, tmp, MYF(MY_WME)))
3407
pthread_mutex_lock(&LOCK_open);
3408
unlock_table_name(thd, table_list);
3409
pthread_mutex_unlock(&LOCK_open);
3410
error= send_check_errmsg(thd, table_list, "repair",
3411
"Failed renaming data file");
3414
if (mysql_truncate(thd, table_list, 1))
3416
pthread_mutex_lock(&LOCK_open);
3417
unlock_table_name(thd, table_list);
3418
pthread_mutex_unlock(&LOCK_open);
3419
error= send_check_errmsg(thd, table_list, "repair",
3420
"Failed generating table from .frm file");
3423
if (my_rename(tmp, from, MYF(MY_WME)))
3425
pthread_mutex_lock(&LOCK_open);
3426
unlock_table_name(thd, table_list);
3427
pthread_mutex_unlock(&LOCK_open);
3428
error= send_check_errmsg(thd, table_list, "repair",
3429
"Failed restoring .MYD file");
3434
Now we should be able to open the partially repaired table
3435
to finish the repair in the handler later on.
3437
pthread_mutex_lock(&LOCK_open);
3438
if (reopen_name_locked_table(thd, table_list, TRUE))
3440
unlock_table_name(thd, table_list);
3441
pthread_mutex_unlock(&LOCK_open);
3442
error= send_check_errmsg(thd, table_list, "repair",
3443
"Failed to open partially repaired table");
3446
pthread_mutex_unlock(&LOCK_open);
3449
if (table == &tmp_table)
3451
pthread_mutex_lock(&LOCK_open);
3452
closefrm(table, 1); // Free allocated memory
3453
pthread_mutex_unlock(&LOCK_open);
3462
FALSE Message sent to net (admin operation went ok)
3463
TRUE Message should be sent by caller
3464
(admin operation or network communication failed)
3466
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
3467
HA_CHECK_OPT* check_opt,
3468
const char *operator_name,
3469
thr_lock_type lock_type,
3470
bool open_for_modify,
3471
bool no_warnings_for_error,
3472
uint extra_open_options,
3473
int (*prepare_func)(THD *, TABLE_LIST *,
3475
int (handler::*operator_func)(THD *,
3479
SELECT_LEX *select= &thd->lex->select_lex;
3480
List<Item> field_list;
3482
Protocol *protocol= thd->protocol;
3485
CHARSET_INFO *cs= system_charset_info;
3486
DBUG_ENTER("mysql_admin_table");
3488
if (end_active_trans(thd))
3490
field_list.push_back(item = new Item_empty_string("Table",
3493
item->maybe_null = 1;
3494
field_list.push_back(item = new Item_empty_string("Op", 10, cs));
3495
item->maybe_null = 1;
3496
field_list.push_back(item = new Item_empty_string("Msg_type", 10, cs));
3497
item->maybe_null = 1;
3498
field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
3499
item->maybe_null = 1;
3500
if (protocol->send_fields(&field_list,
3501
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
3504
mysql_ha_rm_tables(thd, tables, FALSE);
3506
for (table= tables; table; table= table->next_local)
3508
char table_name[NAME_LEN*2+2];
3509
char* db = table->db;
3512
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
3513
DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
3514
strxmov(table_name, db, ".", table->table_name, NullS);
3515
thd->open_options|= extra_open_options;
3516
table->lock_type= lock_type;
3517
/* open only one table from local list of command */
3519
TABLE_LIST *save_next_global, *save_next_local;
3520
save_next_global= table->next_global;
3521
table->next_global= 0;
3522
save_next_local= table->next_local;
3523
table->next_local= 0;
3524
select->table_list.first= (uchar*)table;
3526
Time zone tables and SP tables can be add to lex->query_tables list,
3527
so it have to be prepared.
3528
TODO: Investigate if we can put extra tables into argument instead of
3529
using lex->query_tables
3531
lex->query_tables= table;
3532
lex->query_tables_last= &table->next_global;
3533
lex->query_tables_own_last= 0;
3534
thd->no_warnings_for_error= no_warnings_for_error;
3535
table->required_type=FRMTYPE_TABLE;
3537
open_and_lock_tables(thd, table);
3538
thd->no_warnings_for_error= 0;
3539
table->next_global= save_next_global;
3540
table->next_local= save_next_local;
3541
thd->open_options&= ~extra_open_options;
3543
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
3547
DBUG_PRINT("admin", ("calling prepare_func"));
3548
switch ((*prepare_func)(thd, table, check_opt)) {
3549
case 1: // error, message written to net
3550
ha_autocommit_or_rollback(thd, 1);
3551
end_trans(thd, ROLLBACK);
3552
close_thread_tables(thd);
3553
DBUG_PRINT("admin", ("simple error, admin next table"));
3555
case -1: // error, message could be written to net
3556
/* purecov: begin inspected */
3557
DBUG_PRINT("admin", ("severe error, stop"));
3560
default: // should be 0 otherwise
3561
DBUG_PRINT("admin", ("prepare_func succeeded"));
3567
CHECK TABLE command is only command where VIEW allowed here and this
3568
command use only temporary teble method for VIEWs resolving => there
3569
can't be VIEW tree substitition of join view => if opening table
3570
succeed then table->table will have real TABLE pointer as value (in
3571
case of join view substitution table->table can be 0, but here it is
3576
DBUG_PRINT("admin", ("open table failed"));
3577
if (!thd->warn_list.elements)
3578
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
3579
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
3583
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
3585
/* purecov: begin inspected */
3586
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
3588
DBUG_PRINT("admin", ("sending error message"));
3589
protocol->prepare_for_resend();
3590
protocol->store(table_name, system_charset_info);
3591
protocol->store(operator_name, system_charset_info);
3592
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3593
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
3595
protocol->store(buff, length, system_charset_info);
3596
ha_autocommit_or_rollback(thd, 0);
3597
end_trans(thd, COMMIT);
3598
close_thread_tables(thd);
3599
lex->reset_query_tables_list(FALSE);
3600
table->table=0; // For query cache
3601
if (protocol->write())
3607
/* Close all instances of the table to allow repair to rename files */
3608
if (lock_type == TL_WRITE && table->table->s->version)
3610
DBUG_PRINT("admin", ("removing table from cache"));
3611
pthread_mutex_lock(&LOCK_open);
3612
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
3613
"Waiting to get writelock");
3614
mysql_lock_abort(thd,table->table, TRUE);
3615
remove_table_from_cache(thd, table->table->s->db.str,
3616
table->table->s->table_name.str,
3617
RTFC_WAIT_OTHER_THREAD_FLAG |
3618
RTFC_CHECK_KILLED_FLAG);
3619
thd->exit_cond(old_message);
3620
DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
3626
if (table->table->s->crashed && operator_func == &handler::ha_check)
3628
/* purecov: begin inspected */
3629
DBUG_PRINT("admin", ("sending crashed warning"));
3630
protocol->prepare_for_resend();
3631
protocol->store(table_name, system_charset_info);
3632
protocol->store(operator_name, system_charset_info);
3633
protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
3634
protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
3635
system_charset_info);
3636
if (protocol->write())
3641
if (operator_func == &handler::ha_repair &&
3642
!(check_opt->sql_flags & TT_USEFRM))
3644
if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
3645
(table->table->file->ha_check_for_upgrade(check_opt) ==
3646
HA_ADMIN_NEEDS_ALTER))
3648
DBUG_PRINT("admin", ("recreating table"));
3649
ha_autocommit_or_rollback(thd, 1);
3650
close_thread_tables(thd);
3651
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
3652
result_code= mysql_recreate_table(thd, table);
3653
reenable_binlog(thd);
3655
mysql_recreate_table() can push OK or ERROR.
3656
Clear 'OK' status. If there is an error, keep it:
3657
we will store the error message in a result set row
3660
if (thd->main_da.is_ok())
3661
thd->main_da.reset_diagnostics_area();
3666
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
3667
result_code = (table->table->file->*operator_func)(thd, check_opt);
3668
DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
3672
lex->cleanup_after_one_table_open();
3673
thd->clear_error(); // these errors shouldn't get client
3675
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
3679
protocol->prepare_for_resend();
3680
protocol->store(table_name, system_charset_info);
3681
protocol->store((char*) operator_name, system_charset_info);
3682
protocol->store(warning_level_names[err->level].str,
3683
warning_level_names[err->level].length,
3684
system_charset_info);
3685
protocol->store(err->msg, system_charset_info);
3686
if (protocol->write())
3689
mysql_reset_errors(thd, true);
3691
protocol->prepare_for_resend();
3692
protocol->store(table_name, system_charset_info);
3693
protocol->store(operator_name, system_charset_info);
3695
send_result_message:
3697
DBUG_PRINT("info", ("result_code: %d", result_code));
3698
switch (result_code) {
3699
case HA_ADMIN_NOT_IMPLEMENTED:
3701
char buf[ERRMSGSIZE+20];
3702
uint length=my_snprintf(buf, ERRMSGSIZE,
3703
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
3704
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
3705
protocol->store(buf, length, system_charset_info);
3709
case HA_ADMIN_NOT_BASE_TABLE:
3711
char buf[ERRMSGSIZE+20];
3712
uint length= my_snprintf(buf, ERRMSGSIZE,
3713
ER(ER_BAD_TABLE_ERROR), table_name);
3714
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
3715
protocol->store(buf, length, system_charset_info);
3720
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
3721
protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
3724
case HA_ADMIN_FAILED:
3725
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
3726
protocol->store(STRING_WITH_LEN("Operation failed"),
3727
system_charset_info);
3730
case HA_ADMIN_REJECT:
3731
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
3732
protocol->store(STRING_WITH_LEN("Operation need committed state"),
3733
system_charset_info);
3734
open_for_modify= FALSE;
3737
case HA_ADMIN_ALREADY_DONE:
3738
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
3739
protocol->store(STRING_WITH_LEN("Table is already up to date"),
3740
system_charset_info);
3743
case HA_ADMIN_CORRUPT:
3744
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3745
protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
3749
case HA_ADMIN_INVALID:
3750
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3751
protocol->store(STRING_WITH_LEN("Invalid argument"),
3752
system_charset_info);
3755
case HA_ADMIN_TRY_ALTER:
3758
This is currently used only by InnoDB. ha_innobase::optimize() answers
3759
"try with alter", so here we close the table, do an ALTER TABLE,
3760
reopen the table and do ha_innobase::analyze() on it.
3762
ha_autocommit_or_rollback(thd, 0);
3763
close_thread_tables(thd);
3764
TABLE_LIST *save_next_local= table->next_local,
3765
*save_next_global= table->next_global;
3766
table->next_local= table->next_global= 0;
3767
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
3768
result_code= mysql_recreate_table(thd, table);
3769
reenable_binlog(thd);
3771
mysql_recreate_table() can push OK or ERROR.
3772
Clear 'OK' status. If there is an error, keep it:
3773
we will store the error message in a result set row
3776
if (thd->main_da.is_ok())
3777
thd->main_da.reset_diagnostics_area();
3778
ha_autocommit_or_rollback(thd, 0);
3779
close_thread_tables(thd);
3780
if (!result_code) // recreation went ok
3782
if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
3783
((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
3784
result_code= 0; // analyze went ok
3786
if (result_code) // either mysql_recreate_table or analyze failed
3788
DBUG_ASSERT(thd->is_error());
3789
if (thd->is_error())
3791
const char *err_msg= thd->main_da.message();
3794
sql_print_error(err_msg);
3798
/* Hijack the row already in-progress. */
3799
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3800
protocol->store(err_msg, system_charset_info);
3801
(void)protocol->write();
3802
/* Start off another row for HA_ADMIN_FAILED */
3803
protocol->prepare_for_resend();
3804
protocol->store(table_name, system_charset_info);
3805
protocol->store(operator_name, system_charset_info);
3810
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
3811
table->next_local= save_next_local;
3812
table->next_global= save_next_global;
3813
goto send_result_message;
3815
case HA_ADMIN_WRONG_CHECKSUM:
3817
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
3818
protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
3819
system_charset_info);
3823
case HA_ADMIN_NEEDS_UPGRADE:
3824
case HA_ADMIN_NEEDS_ALTER:
3826
char buf[ERRMSGSIZE];
3829
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3830
length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
3831
protocol->store(buf, length, system_charset_info);
3836
default: // Probably HA_ADMIN_INTERNAL_ERROR
3838
char buf[ERRMSGSIZE+20];
3839
uint length=my_snprintf(buf, ERRMSGSIZE,
3840
"Unknown - internal error %d during operation",
3842
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
3843
protocol->store(buf, length, system_charset_info);
3851
table->table->s->version=0; // Force close of table
3852
else if (open_for_modify)
3854
if (table->table->s->tmp_table)
3855
table->table->file->info(HA_STATUS_CONST);
3858
pthread_mutex_lock(&LOCK_open);
3859
remove_table_from_cache(thd, table->table->s->db.str,
3860
table->table->s->table_name.str, RTFC_NO_FLAG);
3861
pthread_mutex_unlock(&LOCK_open);
3865
ha_autocommit_or_rollback(thd, 0);
3866
end_trans(thd, COMMIT);
3867
close_thread_tables(thd);
3868
table->table=0; // For query cache
3869
if (protocol->write())
3877
ha_autocommit_or_rollback(thd, 1);
3878
end_trans(thd, ROLLBACK);
3879
close_thread_tables(thd); // Shouldn't be needed
3886
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
3888
DBUG_ENTER("mysql_repair_table");
3889
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
3890
"repair", TL_WRITE, 1,
3891
test(check_opt->sql_flags & TT_USEFRM),
3893
&prepare_for_repair,
3894
&handler::ha_repair));
3898
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
3900
DBUG_ENTER("mysql_optimize_table");
3901
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
3902
"optimize", TL_WRITE, 1,0,0,0,
3903
&handler::ha_optimize));
3908
Assigned specified indexes for a table into key cache
3911
mysql_assign_to_keycache()
3913
tables Table list (one table only)
3920
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
3921
LEX_STRING *key_cache_name)
3923
HA_CHECK_OPT check_opt;
3924
KEY_CACHE *key_cache;
3925
DBUG_ENTER("mysql_assign_to_keycache");
3928
pthread_mutex_lock(&LOCK_global_system_variables);
3929
if (!(key_cache= get_key_cache(key_cache_name)))
3931
pthread_mutex_unlock(&LOCK_global_system_variables);
3932
my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
3935
pthread_mutex_unlock(&LOCK_global_system_variables);
3936
check_opt.key_cache= key_cache;
3937
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
3938
"assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
3939
0, 0, &handler::assign_to_keycache));
3944
Reassign all tables assigned to a key cache to another key cache
3947
reassign_keycache_tables()
3949
src_cache Reference to the key cache to clean up
3950
dest_cache New key cache
3953
This is called when one sets a key cache size to zero, in which
3954
case we have to move the tables associated to this key cache to
3957
One has to ensure that one never calls this function while
3958
some other thread is changing the key cache. This is assured by
3959
the caller setting src_cache->in_init before calling this function.
3961
We don't delete the old key cache as there may still be pointers pointing
3962
to it for a while after this function returns.
3968
int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
3969
KEY_CACHE *dst_cache)
3971
DBUG_ENTER("reassign_keycache_tables");
3973
DBUG_ASSERT(src_cache != dst_cache);
3974
DBUG_ASSERT(src_cache->in_init);
3975
src_cache->param_buff_size= 0; // Free key cache
3976
ha_resize_key_cache(src_cache);
3977
ha_change_key_cache(src_cache, dst_cache);
3983
Preload specified indexes for a table into key cache
3986
mysql_preload_keys()
3988
tables Table list (one table only)
3995
bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
3997
DBUG_ENTER("mysql_preload_keys");
3999
We cannot allow concurrent inserts. The storage engine reads
4000
directly from the index file, bypassing the cache. It could read
4001
outdated information if parallel inserts into cache blocks happen.
4003
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
4004
"preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
4005
&handler::preload_keys));
4011
@brief Create frm file based on I_S table
4013
@param[in] thd thread handler
4014
@param[in] schema_table I_S table
4015
@param[in] dst_path path where frm should be created
4016
@param[in] create_info Create info
4018
@return Operation status
4024
bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table,
4025
char *dst_path, HA_CREATE_INFO *create_info)
4027
HA_CREATE_INFO local_create_info;
4028
Alter_info alter_info;
4029
bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
4030
uint keys= schema_table->table->s->keys;
4032
DBUG_ENTER("mysql_create_like_schema_frm");
4034
bzero((char*) &local_create_info, sizeof(local_create_info));
4035
local_create_info.db_type= schema_table->table->s->db_type();
4036
local_create_info.row_type= schema_table->table->s->row_type;
4037
local_create_info.default_table_charset=default_charset_info;
4038
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
4039
schema_table->table->use_all_columns();
4040
if (mysql_prepare_alter_table(thd, schema_table->table,
4041
&local_create_info, &alter_info))
4043
if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
4044
tmp_table, &db_options,
4045
schema_table->table->file,
4046
&schema_table->table->s->key_info, &keys, 0))
4048
local_create_info.max_rows= 0;
4049
if (mysql_create_frm(thd, dst_path, NullS, NullS,
4050
&local_create_info, alter_info.create_list,
4051
keys, schema_table->table->s->key_info,
4052
schema_table->table->file))
4059
Create a table identical to the specified table
4062
mysql_create_like_table()
4064
table Table list element for target table
4065
src_table Table list element for source table
4066
create_info Create info
4073
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
4074
HA_CREATE_INFO *create_info)
4076
TABLE *name_lock= 0;
4077
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
4078
uint dst_path_length;
4079
char *db= table->db;
4080
char *table_name= table->table_name;
4084
DBUG_ENTER("mysql_create_like_table");
4087
/* CREATE TABLE ... LIKE is not allowed for views. */
4088
src_table->required_type= FRMTYPE_TABLE;
4091
By opening source table we guarantee that it exists and no concurrent
4092
DDL operation will mess with it. Later we also take an exclusive
4093
name-lock on target table name, which makes copying of .frm file,
4094
call to ha_create_table() and binlogging atomic against concurrent DML
4095
and DDL operations on target table. Thus by holding both these "locks"
4096
we ensure that our statement is properly isolated from all concurrent
4097
operations which matter.
4099
if (open_tables(thd, &src_table, ¬_used, 0))
4102
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
4104
DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
4107
Check that destination tables does not exist. Note that its name
4108
was already checked when it was added to the table list.
4110
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
4112
if (find_temporary_table(thd, db, table_name))
4114
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
4115
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
4119
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
4123
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
4124
db, table_name, reg_ext, 0);
4125
if (!access(dst_path, F_OK))
4129
DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
4132
Create a new table by copying from source table
4134
Altough exclusive name-lock on target table protects us from concurrent
4135
DML and DDL operations on it we still want to wrap .FRM creation and call
4136
to ha_create_table() in critical section protected by LOCK_open in order
4137
to provide minimal atomicity against operations which disregard name-locks,
4138
like I_S implementation, for example. This is a temporary and should not
4139
be copied. Instead we should fix our code to always honor name-locks.
4141
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
4142
during the call to ha_create_table(). See bug #28614 for more info.
4144
VOID(pthread_mutex_lock(&LOCK_open));
4145
if (src_table->schema_table)
4147
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
4149
VOID(pthread_mutex_unlock(&LOCK_open));
4153
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
4155
if (my_errno == ENOENT)
4156
my_error(ER_BAD_DB_ERROR,MYF(0),db);
4158
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
4159
VOID(pthread_mutex_unlock(&LOCK_open));
4164
As mysql_truncate don't work on a new table at this stage of
4165
creation, instead create the table directly (for both normal
4166
and temporary tables).
4168
DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
4170
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
4171
if (thd->variables.keep_files_on_create)
4172
create_info->options|= HA_CREATE_KEEP_FILES;
4173
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
4174
VOID(pthread_mutex_unlock(&LOCK_open));
4176
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
4178
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
4181
(void) rm_temporary_table(create_info->db_type,
4182
dst_path, false); /* purecov: inspected */
4183
goto err; /* purecov: inspected */
4188
(void) quick_rm_table(create_info->db_type, db,
4189
table_name, 0); /* purecov: inspected */
4190
goto err; /* purecov: inspected */
4193
DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
4196
We have to write the query before we unlock the tables.
4198
if (thd->current_stmt_binlog_row_based)
4201
Since temporary tables are not replicated under row-based
4202
replication, CREATE TABLE ... LIKE ... needs special
4203
treatement. We have four cases to consider, according to the
4204
following decision table:
4206
==== ========= ========= ==============================
4207
Case Target Source Write to binary log
4208
==== ========= ========= ==============================
4209
1 normal normal Original statement
4210
2 normal temporary Generated statement
4211
3 temporary normal Nothing
4212
4 temporary temporary Nothing
4213
==== ========= ========= ==============================
4215
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
4217
if (src_table->table->s->tmp_table) // Case 2
4220
String query(buf, sizeof(buf), system_charset_info);
4221
query.length(0); // Have to zero it since constructor doesn't
4225
Here we open the destination table, on which we already have
4226
name-lock. This is needed for store_create_info() to work.
4227
The table will be closed by unlink_open_table() at the end
4230
table->table= name_lock;
4231
VOID(pthread_mutex_lock(&LOCK_open));
4232
if (reopen_name_locked_table(thd, table, FALSE))
4234
VOID(pthread_mutex_unlock(&LOCK_open));
4237
VOID(pthread_mutex_unlock(&LOCK_open));
4239
IF_DBUG(int result=) store_create_info(thd, table, &query,
4242
DBUG_ASSERT(result == 0); // store_create_info() always return 0
4243
write_bin_log(thd, TRUE, query.ptr(), query.length());
4246
write_bin_log(thd, TRUE, thd->query, thd->query_length);
4249
Case 3 and 4 does nothing under RBR
4253
write_bin_log(thd, TRUE, thd->query, thd->query_length);
4259
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
4261
char warn_buff[MYSQL_ERRMSG_SIZE];
4262
my_snprintf(warn_buff, sizeof(warn_buff),
4263
ER(ER_TABLE_EXISTS_ERROR), table_name);
4264
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4265
ER_TABLE_EXISTS_ERROR,warn_buff);
4269
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
4274
pthread_mutex_lock(&LOCK_open);
4275
unlink_open_table(thd, name_lock, FALSE);
4276
pthread_mutex_unlock(&LOCK_open);
4282
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
4284
thr_lock_type lock_type = TL_READ_NO_INSERT;
4286
DBUG_ENTER("mysql_analyze_table");
4287
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
4288
"analyze", lock_type, 1, 0, 0, 0,
4289
&handler::ha_analyze));
4293
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
4295
thr_lock_type lock_type = TL_READ_NO_INSERT;
4297
DBUG_ENTER("mysql_check_table");
4298
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
4300
0, 0, HA_OPEN_FOR_REPAIR, 0,
4301
&handler::ha_check));
4305
/* table_list should contain just one table */
4307
mysql_discard_or_import_tablespace(THD *thd,
4308
TABLE_LIST *table_list,
4309
enum tablespace_op_type tablespace_op)
4314
DBUG_ENTER("mysql_discard_or_import_tablespace");
4317
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
4321
thd_proc_info(thd, "discard_or_import_tablespace");
4323
discard= test(tablespace_op == DISCARD_TABLESPACE);
4326
We set this flag so that ha_innobase::open and ::external_lock() do
4327
not complain when we lock the table
4329
thd->tablespace_op= TRUE;
4330
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
4332
thd->tablespace_op=FALSE;
4336
error= table->file->ha_discard_or_import_tablespace(discard);
4338
thd_proc_info(thd, "end");
4343
/* The ALTER TABLE is always in its own transaction */
4344
error = ha_autocommit_or_rollback(thd, 0);
4345
if (end_active_trans(thd))
4349
write_bin_log(thd, FALSE, thd->query, thd->query_length);
4352
ha_autocommit_or_rollback(thd, error);
4353
thd->tablespace_op=FALSE;
4361
table->file->print_error(error, MYF(0));
4367
Copy all changes detected by parser to the HA_ALTER_FLAGS
4370
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
4372
uint flags= alter_info->flags;
4374
if (ALTER_ADD_COLUMN & flags)
4375
*alter_flags|= HA_ADD_COLUMN;
4376
if (ALTER_DROP_COLUMN & flags)
4377
*alter_flags|= HA_DROP_COLUMN;
4378
if (ALTER_RENAME & flags)
4379
*alter_flags|= HA_RENAME_TABLE;
4380
if (ALTER_CHANGE_COLUMN & flags)
4381
*alter_flags|= HA_CHANGE_COLUMN;
4382
if (ALTER_COLUMN_DEFAULT & flags)
4383
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
4384
if (ALTER_COLUMN_STORAGE & flags)
4385
*alter_flags|= HA_COLUMN_STORAGE;
4386
if (ALTER_COLUMN_FORMAT & flags)
4387
*alter_flags|= HA_COLUMN_FORMAT;
4388
if (ALTER_COLUMN_ORDER & flags)
4389
*alter_flags|= HA_ALTER_COLUMN_ORDER;
4390
if (ALTER_STORAGE & flags)
4391
*alter_flags|= HA_ALTER_STORAGE;
4392
if (ALTER_ROW_FORMAT & flags)
4393
*alter_flags|= HA_ALTER_ROW_FORMAT;
4394
if (ALTER_RECREATE & flags)
4395
*alter_flags|= HA_RECREATE;
4396
if (ALTER_FOREIGN_KEY & flags)
4397
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4403
@param table The original table.
4404
@param alter_info Alter options, fields and keys for the new
4406
@param create_info Create options for the new table.
4407
@param order_num Number of order list elements.
4408
@param[out] ha_alter_flags Flags that indicate what will be changed
4409
@param[out] ha_alter_info Data structures needed for on-line alter
4410
@param[out] table_changes Information about particular change
4412
First argument 'table' contains information of the original
4413
table, which includes all corresponding parts that the new
4414
table has in arguments create_list, key_list and create_info.
4416
By comparing the changes between the original and new table
4417
we can determine how much it has changed after ALTER TABLE
4418
and whether we need to make a copy of the table, or just change
4421
Mark any changes detected in the ha_alter_flags.
4423
If there are no data changes, but index changes, 'index_drop_buffer'
4424
and/or 'index_add_buffer' are populated with offsets into
4425
table->key_info or key_info_buffer respectively for the indexes
4426
that need to be dropped and/or (re-)created.
4429
@retval FALSE success
4434
compare_tables(THD *thd,
4436
Alter_info *alter_info,
4437
HA_CREATE_INFO *create_info,
4439
HA_ALTER_FLAGS *alter_flags,
4440
HA_ALTER_INFO *ha_alter_info,
4441
uint *table_changes)
4443
Field **f_ptr, *field;
4444
uint table_changes_local= 0;
4445
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
4446
Create_field *new_field;
4447
KEY_PART_INFO *key_part;
4450
Remember if the new definition has new VARCHAR column;
4451
create_info->varchar will be reset in mysql_prepare_create_table.
4453
bool varchar= create_info->varchar;
4454
DBUG_ENTER("compare_tables");
4458
Create a copy of alter_info.
4459
To compare the new and old table definitions, we need to "prepare"
4460
the new definition - transform it from parser output to a format
4461
that describes the final table layout (all column defaults are
4462
initialized, duplicate columns are removed). This is done by
4463
mysql_prepare_create_table. Unfortunately,
4464
mysql_prepare_create_table performs its transformations
4465
"in-place", that is, modifies the argument. Since we would
4466
like to keep compare_tables() idempotent (not altering any
4467
of the arguments) we create a copy of alter_info here and
4468
pass it to mysql_prepare_create_table, then use the result
4469
to evaluate possibility of fast ALTER TABLE, and then
4472
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4473
THD *thd= table->in_use;
4474
uint db_options= 0; /* not used */
4475
/* Create the prepared information. */
4476
if (mysql_prepare_create_table(thd, create_info,
4478
(table->s->tmp_table != NO_TMP_TABLE),
4481
&ha_alter_info->key_info_buffer,
4482
&ha_alter_info->key_count,
4483
/* select_field_count */ 0))
4485
/* Allocate result buffers. */
4486
if (! (ha_alter_info->index_drop_buffer=
4487
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
4488
! (ha_alter_info->index_add_buffer=
4489
(uint*) thd->alloc(sizeof(uint) *
4490
tmp_alter_info.key_list.elements)))
4494
First we setup ha_alter_flags based on what was detected
4497
setup_ha_alter_flags(alter_info, alter_flags);
4501
char dbug_string[HA_MAX_ALTER_FLAGS+1];
4502
alter_flags->print(dbug_string);
4503
DBUG_PRINT("info", ("alter_flags: %s", (char *) dbug_string));
4508
Some very basic checks. If number of fields changes, or the
4509
handler, we need to run full ALTER TABLE. In the future
4510
new fields can be added and old dropped without copy, but
4513
Test also that engine was not given during ALTER TABLE, or
4514
we are force to run regular alter table (copy).
4515
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
4517
For the following ones we also want to run regular alter table:
4518
ALTER TABLE tbl_name ORDER BY ..
4519
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
4521
At the moment we can't handle altering temporary tables without a copy.
4522
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
4523
In that case we always do full copy.
4525
There was a bug prior to mysql-4.0.25. Number of null fields was
4526
calculated incorrectly. As a result frm and data files gets out of
4527
sync after fast alter table. There is no way to determine by which
4528
mysql version (in 4.0 and 4.1 branches) table was created, thus we
4529
disable fast alter table for all tables created by mysql versions
4530
prior to 5.0 branch.
4533
if (table->s->fields != alter_info->create_list.elements ||
4534
table->s->db_type() != create_info->db_type ||
4535
table->s->tmp_table ||
4536
create_info->used_fields & HA_CREATE_USED_ENGINE ||
4537
create_info->used_fields & HA_CREATE_USED_CHARSET ||
4538
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
4539
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
4540
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
4542
!table->s->mysql_version ||
4543
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4545
*table_changes= IS_EQUAL_NO;
4547
Check what has changed and set alter_flags
4549
if (table->s->fields < alter_info->create_list.elements)
4550
*alter_flags|= HA_ADD_COLUMN;
4551
else if (table->s->fields > alter_info->create_list.elements)
4552
*alter_flags|= HA_DROP_COLUMN;
4553
if (create_info->db_type != table->s->db_type() ||
4554
create_info->used_fields & HA_CREATE_USED_ENGINE)
4555
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
4556
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
4557
*alter_flags|= HA_CHANGE_CHARACTER_SET;
4558
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
4559
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
4560
if (alter_info->flags & ALTER_RECREATE)
4561
*alter_flags|= HA_RECREATE;
4562
/* TODO check for ADD/DROP FOREIGN KEY */
4563
if (alter_info->flags & ALTER_FOREIGN_KEY)
4564
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4565
if (!table->s->mysql_version ||
4566
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4567
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4570
Go through fields and check if the original ones are compatible
4573
for (f_ptr= table->field, new_field= new_field_it++;
4574
(new_field && (field= *f_ptr));
4575
f_ptr++, new_field= new_field_it++)
4577
/* Make sure we have at least the default charset in use. */
4578
if (!new_field->charset)
4579
new_field->charset= create_info->default_table_charset;
4581
/* Don't pack rows in old tables if the user has requested this. */
4582
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
4583
(new_field->flags & BLOB_FLAG) ||
4584
(new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
4585
create_info->table_options|= HA_OPTION_PACK_RECORD;
4587
/* Check how fields have been modified */
4588
if (alter_info->flags & ALTER_CHANGE_COLUMN)
4590
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
4591
if (!(table_changes_local= field->is_equal(new_field)))
4592
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4594
/* Check if field was renamed */
4595
field->flags&= ~FIELD_IS_RENAMED;
4596
if (my_strcasecmp(system_charset_info,
4598
new_field->field_name))
4600
field->flags|= FIELD_IS_RENAMED;
4601
*alter_flags|= HA_ALTER_COLUMN_NAME;
4604
*table_changes&= table_changes_local;
4605
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
4606
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4608
/* Check that NULL behavior is same for old and new fields */
4609
if ((new_field->flags & NOT_NULL_FLAG) !=
4610
(uint) (field->flags & NOT_NULL_FLAG))
4612
*table_changes= IS_EQUAL_NO;
4613
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
4617
/* Clear indexed marker */
4618
field->flags&= ~FIELD_IN_ADD_INDEX;
4622
Go through keys and check if the original ones are compatible
4626
KEY *table_key_end= table->key_info + table->s->keys;
4629
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
4631
DBUG_PRINT("info", ("index count old: %d new: %d",
4632
table->s->keys, ha_alter_info->key_count));
4634
Step through all keys of the old table and search matching new keys.
4636
ha_alter_info->index_drop_count= 0;
4637
ha_alter_info->index_add_count= 0;
4638
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4640
KEY_PART_INFO *table_part;
4641
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
4642
KEY_PART_INFO *new_part;
4644
/* Search a new key with the same name. */
4645
for (new_key= ha_alter_info->key_info_buffer;
4646
new_key < new_key_end;
4649
if (! strcmp(table_key->name, new_key->name))
4652
if (new_key >= new_key_end)
4654
/* Key not found. Add the offset of the key to the drop buffer. */
4655
ha_alter_info->index_drop_buffer
4656
[ha_alter_info->index_drop_count++]=
4657
table_key - table->key_info;
4658
if (table_key->flags & HA_NOSAME)
4660
/* Unique key. Check for "PRIMARY". */
4661
if (! my_strcasecmp(system_charset_info,
4662
table_key->name, primary_key_name))
4663
*alter_flags|= HA_DROP_PK_INDEX;
4665
*alter_flags|= HA_DROP_UNIQUE_INDEX;
4668
*alter_flags|= HA_DROP_INDEX;
4669
*table_changes= IS_EQUAL_NO;
4670
DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
4674
/* Check that the key types are compatible between old and new tables. */
4675
if ((table_key->algorithm != new_key->algorithm) ||
4676
((table_key->flags & HA_KEYFLAG_MASK) !=
4677
(new_key->flags & HA_KEYFLAG_MASK)) ||
4678
(table_key->key_parts != new_key->key_parts))
4680
if (table_key->flags & HA_NOSAME)
4682
// Unique key. Check for "PRIMARY".
4683
if (! my_strcasecmp(system_charset_info,
4684
table_key->name, primary_key_name))
4685
*alter_flags|= HA_ALTER_PK_INDEX;
4687
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4690
*alter_flags|= HA_ALTER_INDEX;
4695
Check that the key parts remain compatible between the old and
4698
for (table_part= table_key->key_part, new_part= new_key->key_part;
4699
table_part < table_part_end;
4700
table_part++, new_part++)
4703
Key definition has changed if we are using a different field or
4704
if the used key part length is different. We know that the fields
4705
did not change. Comparing field numbers is sufficient.
4707
if ((table_part->length != new_part->length) ||
4708
(table_part->fieldnr - 1 != new_part->fieldnr))
4710
if (table_key->flags & HA_NOSAME)
4712
/* Unique key. Check for "PRIMARY" */
4713
if (! my_strcasecmp(system_charset_info,
4714
table_key->name, primary_key_name))
4715
*alter_flags|= HA_ALTER_PK_INDEX;
4717
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4720
*alter_flags|= HA_ALTER_INDEX;
4727
/* Key modified. Add the offset of the key to both buffers. */
4728
ha_alter_info->index_drop_buffer
4729
[ha_alter_info->index_drop_count++]=
4730
table_key - table->key_info;
4731
ha_alter_info->index_add_buffer
4732
[ha_alter_info->index_add_count++]=
4733
new_key - ha_alter_info->key_info_buffer;
4734
key_part= new_key->key_part;
4735
end= key_part + new_key->key_parts;
4736
for(; key_part != end; key_part++)
4738
/* Mark field to be part of new key */
4739
if ((field= table->field[key_part->fieldnr]))
4740
field->flags|= FIELD_IN_ADD_INDEX;
4742
*table_changes= IS_EQUAL_NO;
4743
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
4745
/*end of for (; table_key < table_key_end;) */
4748
Step through all keys of the new table and find matching old keys.
4750
for (new_key= ha_alter_info->key_info_buffer;
4751
new_key < new_key_end;
4754
/* Search an old key with the same name. */
4755
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4757
if (! strcmp(table_key->name, new_key->name))
4760
if (table_key >= table_key_end)
4762
/* Key not found. Add the offset of the key to the add buffer. */
4763
ha_alter_info->index_add_buffer
4764
[ha_alter_info->index_add_count++]=
4765
new_key - ha_alter_info->key_info_buffer;
4766
key_part= new_key->key_part;
4767
end= key_part + new_key->key_parts;
4768
for(; key_part != end; key_part++)
4770
/* Mark field to be part of new key */
4771
if ((field= table->field[key_part->fieldnr]))
4772
field->flags|= FIELD_IN_ADD_INDEX;
4774
if (new_key->flags & HA_NOSAME)
4776
/* Unique key. Check for "PRIMARY" */
4777
if (! my_strcasecmp(system_charset_info,
4778
new_key->name, primary_key_name))
4779
*alter_flags|= HA_ADD_PK_INDEX;
4781
*alter_flags|= HA_ADD_UNIQUE_INDEX;
4784
*alter_flags|= HA_ADD_INDEX;
4785
*table_changes= IS_EQUAL_NO;
4786
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
4791
char dbug_string[HA_MAX_ALTER_FLAGS+1];
4792
alter_flags->print(dbug_string);
4793
DBUG_PRINT("info", ("alter_flags: %s", (char *) dbug_string));
4802
Manages enabling/disabling of indexes for ALTER TABLE
4805
alter_table_manage_keys()
4807
indexes_were_disabled Whether the indexes of the from table
4809
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
4817
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
4818
enum enum_enable_or_disable keys_onoff)
4821
DBUG_ENTER("alter_table_manage_keys");
4822
DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
4823
table, indexes_were_disabled, keys_onoff));
4825
switch (keys_onoff) {
4827
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4830
if (!indexes_were_disabled)
4832
/* fall-through: disabled indexes */
4834
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4837
if (error == HA_ERR_WRONG_COMMAND)
4839
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4840
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4841
table->s->table_name.str);
4844
table->file->print_error(error, MYF(0));
4849
int create_temporary_table(THD *thd,
4853
HA_CREATE_INFO *create_info,
4854
Alter_info *alter_info,
4858
char index_file[FN_REFLEN], data_file[FN_REFLEN];
4859
handlerton *old_db_type, *new_db_type;
4860
DBUG_ENTER("create_temporary_table");
4861
old_db_type= table->s->db_type();
4862
new_db_type= create_info->db_type;
4864
Handling of symlinked tables:
4866
Create new data file and index file on the same disk as the
4867
old data and index files.
4869
Rename new data file over old data file and new index file over
4871
Symlinks are not changed.
4874
Create new data file and index file on the same disk as the
4875
old data and index files. Create also symlinks to point at
4878
At end, rename intermediate tables, and symlinks to intermediate
4879
table, to final table name.
4880
Remove old table and old symlinks
4882
If rename is made to another database:
4883
Create new tables in new database.
4885
Remove old table and symlinks.
4887
if (db_changed) // Ignore symlink if db changed
4889
if (create_info->index_file_name)
4891
/* Fix index_file_name to have 'tmp_name' as basename */
4892
strmov(index_file, tmp_name);
4893
create_info->index_file_name=fn_same(index_file,
4894
create_info->index_file_name,
4897
if (create_info->data_file_name)
4899
/* Fix data_file_name to have 'tmp_name' as basename */
4900
strmov(data_file, tmp_name);
4901
create_info->data_file_name=fn_same(data_file,
4902
create_info->data_file_name,
4907
create_info->data_file_name=create_info->index_file_name=0;
4909
if (new_db_type == old_db_type)
4912
Table has not changed storage engine.
4913
If STORAGE and TABLESPACE have not been changed than copy them
4914
from the original table
4916
if (!create_info->tablespace &&
4917
table->s->tablespace &&
4918
create_info->default_storage_media == HA_SM_DEFAULT)
4919
create_info->tablespace= table->s->tablespace;
4920
if (create_info->default_storage_media == HA_SM_DEFAULT)
4921
create_info->default_storage_media= table->s->default_storage_media;
4925
Create a table with a temporary name.
4926
With create_info->frm_only == 1 this creates a .frm file only.
4927
We don't log the statement, it will be logged later.
4929
tmp_disable_binlog(thd);
4930
error= mysql_create_table(thd, new_db, tmp_name,
4931
create_info, alter_info, 1, 0);
4932
reenable_binlog(thd);
4938
Create a temporary table that reflects what an alter table operation
4942
create_altered_table()
4944
table The original table
4945
create_info Information from the parsing phase about new
4947
alter_info Lists of fields, keys to be changed, added
4949
db_change Specifies if the table is moved to another database
4951
A temporary table with all changes
4954
The temporary table is created without storing it in any storage engine
4955
and is opened only to get the table struct and frm file reference.
4957
TABLE *create_altered_table(THD *thd,
4960
HA_CREATE_INFO *create_info,
4961
Alter_info *alter_info,
4965
HA_CREATE_INFO altered_create_info(*create_info);
4966
TABLE *altered_table;
4968
char path[FN_REFLEN];
4969
DBUG_ENTER("create_altered_table");
4971
my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
4972
tmp_file_prefix, current_pid, thd->thread_id);
4973
/* Safety fix for InnoDB */
4974
if (lower_case_table_names)
4975
my_casedn_str(files_charset_info, tmp_name);
4976
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
4977
altered_create_info.frm_only= 1;
4978
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4979
&altered_create_info,
4980
alter_info, db_change)))
4982
DBUG_PRINT("info", ("Error %u while creating temporary table", error));
4986
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4988
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
4990
DBUG_RETURN(altered_table);
4997
Perform a fast or on-line alter table
5000
mysql_fast_or_online_alter_table()
5002
table The original table
5003
altered_table A temporary table showing how we will change table
5004
create_info Information from the parsing phase about new
5006
alter_info Storage place for data used during different phases
5007
ha_alter_flags Bitmask that shows what will be changed
5008
keys_onoff Specifies if keys are to be enabled/disabled
5011
>0 An error occured during the on-line alter table operation
5012
-1 Error when re-opening table
5014
If mysql_alter_table does not need to copy the table, it is
5015
either a fast alter table where the storage engine does not
5016
need to know about the change, only the frm will change,
5017
or the storage engine supports performing the alter table
5018
operation directly, on-line without mysql having to copy
5021
int mysql_fast_or_online_alter_table(THD *thd,
5023
TABLE *altered_table,
5024
HA_CREATE_INFO *create_info,
5025
HA_ALTER_INFO *alter_info,
5026
HA_ALTER_FLAGS *ha_alter_flags,
5027
enum enum_enable_or_disable keys_onoff)
5030
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
5033
DBUG_ENTER(" mysql_fast_or_online_alter_table");
5037
Tell the handler to prepare for the online alter
5039
if ((error= table->file->alter_table_phase1(thd,
5049
Tell the storage engine to perform the online alter table
5051
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
5052
we need to wrap the next call with a DDL lock.
5054
if ((error= table->file->alter_table_phase2(thd,
5064
The final .frm file is already created as a temporary file
5065
and will be renamed to the original table name.
5067
VOID(pthread_mutex_lock(&LOCK_open));
5068
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5069
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
5071
close_data_files_and_morph_locks(thd,
5072
table->pos_in_table_list->db,
5073
table->pos_in_table_list->table_name);
5074
if (mysql_rename_table(NULL,
5075
altered_table->s->db.str,
5076
altered_table->s->table_name.str,
5078
table->s->table_name.str, FN_FROM_IS_TMP))
5081
VOID(pthread_mutex_unlock(&LOCK_open));
5084
broadcast_refresh();
5085
VOID(pthread_mutex_unlock(&LOCK_open));
5088
The ALTER TABLE is always in its own transaction.
5089
Commit must not be called while LOCK_open is locked. It could call
5090
wait_if_global_read_lock(), which could create a deadlock if called
5093
error= ha_autocommit_or_rollback(thd, 0);
5101
VOID(pthread_mutex_lock(&LOCK_open));
5102
if (reopen_table(table))
5107
VOID(pthread_mutex_unlock(&LOCK_open));
5111
Tell the handler that the changed frm is on disk and table
5114
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
5120
We are going to reopen table down on the road, so we have to restore
5121
state of the TABLE object which we used for obtaining of handler
5122
object to make it suitable for reopening.
5124
DBUG_ASSERT(t_table == table);
5125
table->open_placeholder= 1;
5126
VOID(pthread_mutex_lock(&LOCK_open));
5127
close_handle_and_leave_table_as_lock(table);
5128
VOID(pthread_mutex_unlock(&LOCK_open));
5133
DBUG_PRINT("info", ("Got error %u", error));
5139
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
5141
This function transforms parse output of ALTER TABLE - lists of
5142
columns and keys to add, drop or modify into, essentially,
5143
CREATE TABLE definition - a list of columns and keys of the new
5144
table. While doing so, it also performs some (bug not all)
5147
This function is invoked when we know that we're going to
5148
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
5149
is not possible, perhaps because the ALTER statement contains
5150
instructions that require change in table data, not only in
5151
table definition or indexes.
5153
@param[in,out] thd thread handle. Used as a memory pool
5154
and source of environment information.
5155
@param[in] table the source table, open and locked
5156
Used as an interface to the storage engine
5157
to acquire additional information about
5159
@param[in,out] create_info A blob with CREATE/ALTER TABLE
5161
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
5162
Originally create_info was used only in
5163
CREATE TABLE and alter_info only in ALTER TABLE.
5164
But since ALTER might end-up doing CREATE,
5165
this distinction is gone and we just carry
5166
around two structures.
5169
Fills various create_info members based on information retrieved
5170
from the storage engine.
5171
Sets create_info->varchar if the table has a VARCHAR column.
5172
Prepares alter_info->create_list and alter_info->key_list with
5173
columns and keys of the new table.
5174
@retval TRUE error, out of memory or a semantical error in ALTER
5176
@retval FALSE success
5180
mysql_prepare_alter_table(THD *thd, TABLE *table,
5181
HA_CREATE_INFO *create_info,
5182
Alter_info *alter_info)
5184
/* New column definitions are added here */
5185
List<Create_field> new_create_list;
5186
/* New key definitions are added here */
5187
List<Key> new_key_list;
5188
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
5189
List_iterator<Create_field> def_it(alter_info->create_list);
5190
List_iterator<Alter_column> alter_it(alter_info->alter_list);
5191
List_iterator<Key> key_it(alter_info->key_list);
5192
List_iterator<Create_field> find_it(new_create_list);
5193
List_iterator<Create_field> field_it(new_create_list);
5194
List<Key_part_spec> key_parts;
5195
uint db_create_options= (table->s->db_create_options
5196
& ~(HA_OPTION_PACK_RECORD));
5197
uint used_fields= create_info->used_fields;
5198
KEY *key_info=table->key_info;
5201
DBUG_ENTER("mysql_prepare_alter_table");
5203
create_info->varchar= FALSE;
5204
/* Let new create options override the old ones */
5205
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
5206
create_info->min_rows= table->s->min_rows;
5207
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
5208
create_info->max_rows= table->s->max_rows;
5209
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
5210
create_info->avg_row_length= table->s->avg_row_length;
5211
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
5212
create_info->default_table_charset= table->s->table_charset;
5213
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
5215
/* Table has an autoincrement, copy value to new table */
5216
table->file->info(HA_STATUS_AUTO);
5217
create_info->auto_increment_value= table->file->stats.auto_increment_value;
5219
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
5220
create_info->key_block_size= table->s->key_block_size;
5221
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
5222
create_info->transactional= table->s->transactional;
5224
restore_record(table, s->default_values); // Empty record for DEFAULT
5228
First collect all fields from table which isn't in drop_list
5230
Field **f_ptr,*field;
5231
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
5233
if (field->type() == MYSQL_TYPE_STRING)
5234
create_info->varchar= TRUE;
5235
/* Check if field should be dropped */
5238
while ((drop=drop_it++))
5240
if (drop->type == Alter_drop::COLUMN &&
5241
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
5243
/* Reset auto_increment value if it was dropped */
5244
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
5245
!(used_fields & HA_CREATE_USED_AUTO))
5247
create_info->auto_increment_value=0;
5248
create_info->used_fields|=HA_CREATE_USED_AUTO;
5258
/* Check if field is changed */
5260
while ((def=def_it++))
5263
!my_strcasecmp(system_charset_info,field->field_name, def->change))
5267
{ // Field is changed
5271
new_create_list.push_back(def);
5278
This field was not dropped and not changed, add it to the list
5281
def= new Create_field(field, field);
5282
new_create_list.push_back(def);
5283
alter_it.rewind(); // Change default if ALTER
5284
Alter_column *alter;
5285
while ((alter=alter_it++))
5287
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
5292
if (def->sql_type == MYSQL_TYPE_BLOB)
5294
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
5297
if ((def->def=alter->def)) // Use new default
5298
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
5300
def->flags|= NO_DEFAULT_VALUE_FLAG;
5306
while ((def=def_it++)) // Add new columns
5308
if (def->change && ! def->field)
5310
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
5314
Check that the DATE/DATETIME not null field we are going to add is
5315
either has a default value or the '0000-00-00' is allowed by the
5317
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
5318
flag to allow ALTER TABLE only if the table to be altered is empty.
5320
if ((def->sql_type == MYSQL_TYPE_DATE ||
5321
def->sql_type == MYSQL_TYPE_NEWDATE ||
5322
def->sql_type == MYSQL_TYPE_DATETIME) &&
5323
!alter_info->datetime_field &&
5324
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
5325
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
5327
alter_info->datetime_field= def;
5328
alter_info->error_if_not_empty= TRUE;
5331
new_create_list.push_back(def);
5332
else if (def->after == first_keyword)
5333
new_create_list.push_front(def);
5338
while ((find=find_it++)) // Add new columns
5340
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
5345
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
5348
find_it.after(def); // Put element after this
5350
XXX: hack for Bug#28427.
5351
If column order has changed, force OFFLINE ALTER TABLE
5352
without querying engine capabilities. If we ever have an
5353
engine that supports online ALTER TABLE CHANGE COLUMN
5354
<name> AFTER <name1> (Falcon?), this fix will effectively
5355
disable the capability.
5356
TODO: detect the situation in compare_tables, behave based
5357
on engine capabilities.
5359
if (alter_info->build_method == HA_BUILD_ONLINE)
5361
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5364
alter_info->build_method= HA_BUILD_OFFLINE;
5367
if (alter_info->alter_list.elements)
5369
my_error(ER_BAD_FIELD_ERROR, MYF(0),
5370
alter_info->alter_list.head()->name, table->s->table_name.str);
5373
if (!new_create_list.elements)
5375
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
5381
Collect all keys which isn't in drop list. Add only those
5382
for which some fields exists.
5385
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
5387
char *key_name= key_info->name;
5390
while ((drop=drop_it++))
5392
if (drop->type == Alter_drop::KEY &&
5393
!my_strcasecmp(system_charset_info,key_name, drop->name))
5402
KEY_PART_INFO *key_part= key_info->key_part;
5404
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
5406
if (!key_part->field)
5407
continue; // Wrong field (from UNIREG)
5408
const char *key_part_name=key_part->field->field_name;
5409
Create_field *cfield;
5411
while ((cfield=field_it++))
5415
if (!my_strcasecmp(system_charset_info, key_part_name,
5419
else if (!my_strcasecmp(system_charset_info,
5420
key_part_name, cfield->field_name))
5424
continue; // Field is removed
5425
uint key_part_length=key_part->length;
5426
if (cfield->field) // Not new field
5429
If the field can't have only a part used in a key according to its
5430
new type, or should not be used partially according to its
5431
previous type, or the field length is less than the key part
5432
length, unset the key part length.
5434
We also unset the key part length if it is the same as the
5435
old field's length, so the whole new field will be used.
5437
BLOBs may have cfield->length == 0, which is why we test it before
5438
checking whether cfield->length < key_part_length (in chars).
5440
if (!Field::type_can_have_key_part(cfield->field->type()) ||
5441
!Field::type_can_have_key_part(cfield->sql_type) ||
5442
(cfield->field->field_length == key_part_length &&
5443
!f_is_blob(key_part->key_type)) ||
5444
(cfield->length && (cfield->length < key_part_length /
5445
key_part->field->charset()->mbmaxlen)))
5446
key_part_length= 0; // Use whole field
5448
key_part_length /= key_part->field->charset()->mbmaxlen;
5449
key_parts.push_back(new Key_part_spec(cfield->field_name,
5450
strlen(cfield->field_name),
5453
if (key_parts.elements)
5455
KEY_CREATE_INFO key_create_info;
5457
enum Key::Keytype key_type;
5458
bzero((char*) &key_create_info, sizeof(key_create_info));
5460
key_create_info.algorithm= key_info->algorithm;
5461
if (key_info->flags & HA_USES_BLOCK_SIZE)
5462
key_create_info.block_size= key_info->block_size;
5463
if (key_info->flags & HA_USES_COMMENT)
5464
key_create_info.comment= key_info->comment;
5466
if (key_info->flags & HA_NOSAME)
5468
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
5469
key_type= Key::PRIMARY;
5471
key_type= Key::UNIQUE;
5474
key_type= Key::MULTIPLE;
5476
key= new Key(key_type, key_name, strlen(key_name),
5478
test(key_info->flags & HA_GENERATED_KEY),
5480
new_key_list.push_back(key);
5485
while ((key=key_it++)) // Add new keys
5487
if (key->type != Key::FOREIGN_KEY)
5488
new_key_list.push_back(key);
5489
if (key->name.str &&
5490
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
5492
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
5498
if (alter_info->drop_list.elements)
5500
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5501
alter_info->drop_list.head()->name);
5504
if (alter_info->alter_list.elements)
5506
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5507
alter_info->alter_list.head()->name);
5511
if (!create_info->comment.str)
5513
create_info->comment.str= table->s->comment.str;
5514
create_info->comment.length= table->s->comment.length;
5517
table->file->update_create_info(create_info);
5518
if ((create_info->table_options &
5519
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
5520
(used_fields & HA_CREATE_USED_PACK_KEYS))
5521
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
5522
if (create_info->table_options &
5523
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
5524
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
5525
if (create_info->table_options &
5526
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
5527
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
5528
HA_OPTION_NO_DELAY_KEY_WRITE);
5529
create_info->table_options|= db_create_options;
5531
if (table->s->tmp_table)
5532
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
5535
alter_info->create_list.swap(new_create_list);
5536
alter_info->key_list.swap(new_key_list);
5548
new_db If there is a RENAME clause
5549
new_name If there is a RENAME clause
5550
create_info Information from the parsing phase about new
5552
table_list The table to change.
5553
alter_info Lists of fields, keys to be changed, added
5555
order_num How many ORDER BY fields has been specified.
5556
order List of fields to ORDER BY.
5557
ignore Whether we have ALTER IGNORE TABLE
5560
This is a veery long function and is everything but the kitchen sink :)
5561
It is used to alter a table and not only by ALTER TABLE but also
5562
CREATE|DROP INDEX are mapped on this function.
5564
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
5565
or both, then this function short cuts its operation by renaming
5566
the table and/or enabling/disabling the keys. In this case, the FRM is
5567
not changed, directly by mysql_alter_table. However, if there is a
5568
RENAME + change of a field, or an index, the short cut is not used.
5569
See how `create_list` is used to generate the new FRM regarding the
5570
structure of the fields. The same is done for the indices of the table.
5572
Important is the fact, that this function tries to do as little work as
5573
possible, by finding out whether a intermediate table is needed to copy
5574
data into and when finishing the altering to use it as the original table.
5575
For this reason the function compare_tables() is called, which decides
5576
based on all kind of data how similar are the new and the original
5584
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
5585
HA_CREATE_INFO *create_info,
5586
TABLE_LIST *table_list,
5587
Alter_info *alter_info,
5588
uint order_num, ORDER *order, bool ignore)
5590
TABLE *table, *new_table=0, *name_lock= 0;;
5592
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
5593
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
5594
char path[FN_REFLEN];
5595
ha_rows copied= 0,deleted= 0;
5596
handlerton *old_db_type, *new_db_type, *save_old_db_type;
5597
legacy_db_type table_type;
5598
frm_type_enum frm_type;
5599
DBUG_ENTER("mysql_alter_table");
5601
if (table_list && table_list->schema_table)
5603
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
5608
Assign variables table_name, new_name, db, new_db, path
5609
to simplify further comparisons: we want to see if it's a RENAME
5610
later just by comparing the pointers, avoiding the need for strcmp.
5612
thd_proc_info(thd, "init");
5613
table_name=table_list->table_name;
5614
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
5616
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
5618
build_table_filename(path, sizeof(path), db, table_name, "", 0);
5620
mysql_ha_rm_tables(thd, table_list, FALSE);
5622
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
5623
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
5624
/* Conditionally writes to binlog. */
5625
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
5626
alter_info->tablespace_op));
5627
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
5628
"/", table_name, reg_ext, NullS);
5629
(void) unpack_filename(new_name_buff, new_name_buff);
5631
If this is just a rename of a view, short cut to the
5632
following scenario: 1) lock LOCK_open 2) do a RENAME
5633
2) unlock LOCK_open.
5634
This is a copy-paste added to make sure
5635
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
5636
as an independent branch in mysql_execute_command. The need
5637
for a copy-paste arose because the main code flow of ALTER TABLE
5638
... RENAME tries to use open_ltable, which does not work for views
5639
(open_ltable was never modified to merge table lists of child tables
5640
into the main table list, like open_tables does).
5641
This code is wrong and will be removed, please do not copy.
5643
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
5645
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
5647
table->use_all_columns();
5650
Prohibit changing of the UNION list of a non-temporary MERGE table
5651
under LOCK tables. It would be quite difficult to reuse a shrinked
5652
set of tables from the old table or to open a new TABLE object for
5653
an extended list and verify that they belong to locked tables.
5655
if (thd->locked_tables &&
5656
(create_info->used_fields & HA_CREATE_USED_UNION) &&
5657
(table->s->tmp_table == NO_TMP_TABLE))
5659
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
5663
/* Check that we are not trying to rename to an existing table */
5666
DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name));
5667
strmov(new_name_buff,new_name);
5668
strmov(new_alias= new_alias_buff, new_name);
5669
if (lower_case_table_names)
5671
if (lower_case_table_names != 2)
5673
my_casedn_str(files_charset_info, new_name_buff);
5674
new_alias= new_name; // Create lower case table name
5676
my_casedn_str(files_charset_info, new_name);
5679
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
5682
Source and destination table names are equal: make later check
5685
new_alias= new_name= table_name;
5689
if (table->s->tmp_table != NO_TMP_TABLE)
5691
if (find_temporary_table(thd,new_db,new_name_buff))
5693
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
5699
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
5703
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5707
build_table_filename(new_name_buff, sizeof(new_name_buff),
5708
new_db, new_name_buff, reg_ext, 0);
5709
if (!access(new_name_buff, F_OK))
5711
/* Table will be closed in do_command() */
5712
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5720
new_alias= (lower_case_table_names == 2) ? alias : table_name;
5721
new_name= table_name;
5724
old_db_type= table->s->db_type();
5725
if (!create_info->db_type)
5727
create_info->db_type= old_db_type;
5730
if (check_engine(thd, new_name, create_info))
5732
new_db_type= create_info->db_type;
5734
if (new_db_type != old_db_type ||
5735
!table->file->can_switch_engines())
5737
my_error(ER_ROW_IS_REFERENCED, MYF(0));
5741
if (create_info->row_type == ROW_TYPE_NOT_USED)
5742
create_info->row_type= table->s->row_type;
5744
DBUG_PRINT("info", ("old type: %s new type: %s",
5745
ha_resolve_storage_engine_name(old_db_type),
5746
ha_resolve_storage_engine_name(new_db_type)));
5747
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
5748
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
5750
DBUG_PRINT("info", ("doesn't support alter"));
5751
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
5755
thd_proc_info(thd, "setup");
5756
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
5757
!table->s->tmp_table) // no need to touch frm
5759
switch (alter_info->keys_onoff) {
5764
wait_while_table_is_used() ensures that table being altered is
5765
opened only by this thread and that TABLE::TABLE_SHARE::version
5766
of TABLE object corresponding to this table is 0.
5767
The latter guarantees that no DML statement will open this table
5768
until ALTER TABLE finishes (i.e. until close_thread_tables())
5769
while the fact that the table is still open gives us protection
5770
from concurrent DDL statements.
5772
VOID(pthread_mutex_lock(&LOCK_open));
5773
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5774
VOID(pthread_mutex_unlock(&LOCK_open));
5775
DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
5776
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5777
/* COND_refresh will be signaled in close_thread_tables() */
5780
VOID(pthread_mutex_lock(&LOCK_open));
5781
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5782
VOID(pthread_mutex_unlock(&LOCK_open));
5783
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5784
/* COND_refresh will be signaled in close_thread_tables() */
5791
if (error == HA_ERR_WRONG_COMMAND)
5794
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5795
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5799
VOID(pthread_mutex_lock(&LOCK_open));
5801
Unlike to the above case close_cached_table() below will remove ALL
5802
instances of TABLE from table cache (it will also remove table lock
5803
held by this thread). So to make actual table renaming and writing
5804
to binlog atomic we have to put them into the same critical section
5805
protected by LOCK_open mutex. This also removes gap for races between
5806
access() and mysql_rename_table() calls.
5809
if (!error && (new_name != table_name || new_db != db))
5811
thd_proc_info(thd, "rename");
5813
Then do a 'simple' rename of the table. First we need to close all
5814
instances of 'source' table.
5816
close_cached_table(thd, table);
5818
Then, we want check once again that target table does not exist.
5819
Actually the order of these two steps does not matter since
5820
earlier we took name-lock on the target table, so we do them
5821
in this particular order only to be consistent with 5.0, in which
5822
we don't take this name-lock and where this order really matters.
5823
TODO: Investigate if we need this access() check at all.
5825
if (!access(new_name_buff,F_OK))
5827
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
5832
*fn_ext(new_name)=0;
5833
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
5837
VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
5844
if (error == HA_ERR_WRONG_COMMAND)
5847
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5848
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5854
write_bin_log(thd, TRUE, thd->query, thd->query_length);
5859
table->file->print_error(error, MYF(0));
5863
unlink_open_table(thd, name_lock, FALSE);
5864
VOID(pthread_mutex_unlock(&LOCK_open));
5865
table_list->table= NULL; // For query cache
5869
/* We have to do full alter table. */
5872
If the old table had partitions and we are doing ALTER TABLE ...
5873
engine= <new_engine>, the new table must preserve the original
5874
partitioning. That means that the new engine is still the
5875
partitioning engine, not the engine specified in the parser.
5876
This is discovered in prep_alter_part_table, which in such case
5877
updates create_info->db_type.
5878
Now we need to update the stack copy of create_info->db_type,
5879
as otherwise we won't be able to correctly move the files of the
5880
temporary table to the result table files.
5882
new_db_type= create_info->db_type;
5884
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
5887
set_table_default_charset(thd, create_info, db);
5890
if (thd->variables.old_alter_table
5891
|| (table->s->db_type() != create_info->db_type)
5894
if (alter_info->build_method == HA_BUILD_ONLINE)
5896
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5899
alter_info->build_method= HA_BUILD_OFFLINE;
5902
if (alter_info->build_method != HA_BUILD_OFFLINE)
5904
TABLE *altered_table= 0;
5905
HA_ALTER_INFO ha_alter_info;
5906
HA_ALTER_FLAGS ha_alter_flags;
5907
uint table_changes= IS_EQUAL_YES;
5908
bool need_copy_table= TRUE;
5909
/* Check how much the tables differ. */
5910
if (compare_tables(thd, table, alter_info,
5911
create_info, order_num,
5920
Check if storage engine supports altering the table
5926
char dbug_string[HA_MAX_ALTER_FLAGS+1];
5927
ha_alter_flags.print(dbug_string);
5928
DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
5929
need_copy_table, table_changes,
5930
(char *) dbug_string));
5935
If table is not renamed, changed database and
5936
some change was detected then check if engine
5937
can do the change on-line
5939
if (new_name == table_name && new_db == db &&
5940
ha_alter_flags.is_set())
5942
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
5946
check if table can be altered on-line
5948
if (!(altered_table= create_altered_table(thd,
5953
!strcmp(db, new_db))))
5956
switch (table->file->check_if_supported_alter(altered_table,
5960
case HA_ALTER_SUPPORTED_WAIT_LOCK:
5961
case HA_ALTER_SUPPORTED_NO_LOCK:
5963
@todo: Currently we always acquire an exclusive name
5964
lock on the table metadata when performing fast or online
5965
ALTER TABLE. In future we may consider this unnecessary,
5966
and narrow the scope of the exclusive name lock to only
5967
cover manipulation with .frms. Storage engine API
5968
call check_if_supported_alter has provision for this
5971
need_copy_table= FALSE;
5973
case HA_ALTER_NOT_SUPPORTED:
5974
if (alter_info->build_method == HA_BUILD_ONLINE)
5976
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5977
close_temporary_table(thd, altered_table, 1, 1);
5980
need_copy_table= TRUE;
5982
case HA_ALTER_ERROR:
5984
close_temporary_table(thd, altered_table, 1, 1);
5989
char dbug_string[HA_MAX_ALTER_FLAGS+1];
5990
ha_alter_flags.print(dbug_string);
5991
DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
5992
need_copy_table, table_changes,
5993
(char *) dbug_string));
5998
/* TODO need to check if changes can be handled as fast ALTER TABLE */
6000
need_copy_table= TRUE;
6002
if (!need_copy_table)
6004
error= mysql_fast_or_online_alter_table(thd,
6010
alter_info->keys_onoff);
6013
mysql_unlock_tables(thd, thd->lock);
6016
close_temporary_table(thd, altered_table, 1, 1);
6022
goto err_with_placeholders;
6029
pthread_mutex_lock(&LOCK_open);
6035
close_temporary_table(thd, altered_table, 1, 1);
6038
my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
6039
current_pid, thd->thread_id);
6040
/* Safety fix for innodb */
6041
if (lower_case_table_names)
6042
my_casedn_str(files_charset_info, tmp_name);
6045
/* Create a temporary table with the new format */
6046
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
6047
create_info, alter_info,
6048
!strcmp(db, new_db))))
6053
/* Open the table so we need to copy the data to it. */
6054
if (table->s->tmp_table)
6057
bzero((void*) &tbl, sizeof(tbl));
6059
tbl.table_name= tbl.alias= tmp_name;
6060
/* Table is in thd->temporary_tables */
6061
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
6062
MYSQL_LOCK_IGNORE_FLUSH);
6066
char path[FN_REFLEN];
6067
/* table is a normal table: Create temporary table in same directory */
6068
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
6070
/* Open our intermediate table */
6071
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
6076
/* Copy the data if necessary. */
6077
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
6078
thd->cuted_fields=0L;
6079
thd_proc_info(thd, "copy to tmp table");
6082
We do not copy data for MERGE tables. Only the children have data.
6083
MERGE tables have HA_NO_COPY_ON_ALTER set.
6085
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
6087
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
6088
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
6089
new_table->next_number_field=new_table->found_next_number_field;
6090
error= copy_data_between_tables(table, new_table,
6091
alter_info->create_list, ignore,
6092
order_num, order, &copied, &deleted,
6093
alter_info->keys_onoff,
6094
alter_info->error_if_not_empty);
6098
VOID(pthread_mutex_lock(&LOCK_open));
6099
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
6100
VOID(pthread_mutex_unlock(&LOCK_open));
6101
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
6102
alter_info->keys_onoff);
6103
error= ha_autocommit_or_rollback(thd, 0);
6104
if (end_active_trans(thd))
6107
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
6109
if (table->s->tmp_table != NO_TMP_TABLE)
6111
/* We changed a temporary table */
6114
/* Close lock if this is a transactional table */
6117
mysql_unlock_tables(thd, thd->lock);
6120
/* Remove link to old table and rename the new one */
6121
close_temporary_table(thd, table, 1, 1);
6122
/* Should pass the 'new_name' as we store table name in the cache */
6123
if (rename_temporary_table(thd, new_table, new_db, new_name))
6125
/* We don't replicate alter table statement on temporary tables */
6126
if (!thd->current_stmt_binlog_row_based)
6127
write_bin_log(thd, TRUE, thd->query, thd->query_length);
6134
Close the intermediate table that will be the new table.
6135
Note that MERGE tables do not have their children attached here.
6137
intern_close_table(new_table);
6138
my_free(new_table,MYF(0));
6140
VOID(pthread_mutex_lock(&LOCK_open));
6143
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6144
VOID(pthread_mutex_unlock(&LOCK_open));
6149
Data is copied. Now we:
6150
1) Wait until all other threads close old version of table.
6151
2) Close instances of table open by this thread and replace them
6152
with exclusive name-locks.
6153
3) Rename the old table to a temp name, rename the new one to the
6155
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
6156
we reopen new version of table.
6157
5) Write statement to the binary log.
6158
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
6159
remove name-locks from list of open tables and table cache.
6160
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
6161
call to remove name-locks from table cache and list of open table.
6164
thd_proc_info(thd, "rename result table");
6165
my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
6166
current_pid, thd->thread_id);
6167
if (lower_case_table_names)
6168
my_casedn_str(files_charset_info, old_name);
6170
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
6171
close_data_files_and_morph_locks(thd, db, table_name);
6174
save_old_db_type= old_db_type;
6177
This leads to the storage engine (SE) not being notified for renames in
6178
mysql_rename_table(), because we just juggle with the FRM and nothing
6179
more. If we have an intermediate table, then we notify the SE that
6180
it should become the actual table. Later, we will recycle the old table.
6181
However, in case of ALTER TABLE RENAME there might be no intermediate
6182
table. This is when the old and new tables are compatible, according to
6183
compare_table(). Then, we need one additional call to
6184
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
6185
actual rename in the SE and the FRM is not touched. Note that, if the
6186
table is renamed and the SE is also changed, then an intermediate table
6187
is created and the additional call will not take place.
6189
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
6193
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6195
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
6196
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
6198
/* Try to get everything back. */
6200
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
6201
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6202
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
6208
/* This shouldn't happen. But let us play it safe. */
6209
goto err_with_placeholders;
6212
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
6215
if (thd->locked_tables && new_name == table_name && new_db == db)
6217
thd->in_lock_tables= 1;
6218
error= reopen_tables(thd, 1, 1);
6219
thd->in_lock_tables= 0;
6221
goto err_with_placeholders;
6223
VOID(pthread_mutex_unlock(&LOCK_open));
6225
thd_proc_info(thd, "end");
6227
DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
6229
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
6230
thd->query, thd->query_length,
6233
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
6234
thd->current_stmt_binlog_row_based &&
6235
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
6236
write_bin_log(thd, TRUE, thd->query, thd->query_length);
6238
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
6241
For the alter table to be properly flushed to the logs, we
6242
have to open the new table. If not, we get a problem on server
6243
shutdown. But we do not need to attach MERGE children.
6245
char path[FN_REFLEN];
6247
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
6248
t_table= open_temporary_table(thd, path, new_db, tmp_name, FALSE, OTM_OPEN);
6251
intern_close_table(t_table);
6252
my_free(t_table, MYF(0));
6255
sql_print_warning("Could not open table %s.%s after rename\n",
6257
ha_flush_logs(old_db_type);
6259
table_list->table=0; // For query cache
6261
if (thd->locked_tables && (new_name != table_name || new_db != db))
6264
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
6265
to remove placeholders for the old table and for the target table
6266
from the list of open tables and table cache. If we are not under
6267
LOCK TABLES we can rely on close_thread_tables() doing this job.
6269
pthread_mutex_lock(&LOCK_open);
6270
unlink_open_table(thd, table, FALSE);
6271
unlink_open_table(thd, name_lock, FALSE);
6272
pthread_mutex_unlock(&LOCK_open);
6276
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
6277
(ulong) (copied + deleted), (ulong) deleted,
6278
(ulong) thd->cuted_fields);
6279
my_ok(thd, copied + deleted, 0L, tmp_name);
6280
thd->some_tables_deleted=0;
6286
/* close_temporary_table() frees the new_table pointer. */
6287
close_temporary_table(thd, new_table, 1, 1);
6290
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6294
No default value was provided for a DATE/DATETIME field, the
6295
current sql_mode doesn't allow the '0000-00-00' value and
6296
the table to be altered isn't empty.
6299
if (alter_info->error_if_not_empty && thd->row_count)
6301
const char *f_val= 0;
6302
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
6303
switch (alter_info->datetime_field->sql_type)
6305
case MYSQL_TYPE_DATE:
6306
case MYSQL_TYPE_NEWDATE:
6307
f_val= "0000-00-00";
6308
t_type= MYSQL_TIMESTAMP_DATE;
6310
case MYSQL_TYPE_DATETIME:
6311
f_val= "0000-00-00 00:00:00";
6312
t_type= MYSQL_TIMESTAMP_DATETIME;
6315
/* Shouldn't get here. */
6318
bool save_abort_on_warning= thd->abort_on_warning;
6319
thd->abort_on_warning= TRUE;
6320
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
6321
f_val, strlength(f_val), t_type,
6322
alter_info->datetime_field->field_name);
6323
thd->abort_on_warning= save_abort_on_warning;
6327
pthread_mutex_lock(&LOCK_open);
6328
unlink_open_table(thd, name_lock, FALSE);
6329
pthread_mutex_unlock(&LOCK_open);
6333
err_with_placeholders:
6335
An error happened while we were holding exclusive name-lock on table
6336
being altered. To be safe under LOCK TABLES we should remove placeholders
6337
from list of open tables list and table cache.
6339
unlink_open_table(thd, table, FALSE);
6341
unlink_open_table(thd, name_lock, FALSE);
6342
VOID(pthread_mutex_unlock(&LOCK_open));
6345
/* mysql_alter_table */
6348
copy_data_between_tables(TABLE *from,TABLE *to,
6349
List<Create_field> &create,
6351
uint order_num, ORDER *order,
6354
enum enum_enable_or_disable keys_onoff,
6355
bool error_if_not_empty)
6358
Copy_field *copy,*copy_end;
6359
ulong found_count,delete_count;
6360
THD *thd= current_thd;
6362
SORT_FIELD *sortorder;
6366
List<Item> all_fields;
6367
ha_rows examined_rows;
6368
bool auto_increment_field_copied= 0;
6369
ulong save_sql_mode;
6370
ulonglong prev_insert_id;
6371
DBUG_ENTER("copy_data_between_tables");
6374
Turn off recovery logging since rollback of an alter table is to
6375
delete the new table so there is no need to log the changes to it.
6377
This needs to be done before external_lock
6379
error= ha_enable_transaction(thd, FALSE);
6383
if (!(copy= new Copy_field[to->s->fields]))
6384
DBUG_RETURN(-1); /* purecov: inspected */
6386
if (to->file->ha_external_lock(thd, F_WRLCK))
6389
/* We need external lock before we can disable/enable keys */
6390
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
6392
/* We can abort alter table for any table type */
6393
thd->abort_on_warning= !ignore;
6395
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
6396
to->file->ha_start_bulk_insert(from->file->stats.records);
6398
save_sql_mode= thd->variables.sql_mode;
6400
List_iterator<Create_field> it(create);
6403
for (Field **ptr=to->field ; *ptr ; ptr++)
6408
if (*ptr == to->next_number_field)
6410
auto_increment_field_copied= TRUE;
6412
If we are going to copy contents of one auto_increment column to
6413
another auto_increment column it is sensible to preserve zeroes.
6414
This condition also covers case when we are don't actually alter
6415
auto_increment column.
6417
if (def->field == from->found_next_number_field)
6418
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
6420
(copy_end++)->set(*ptr,def->field,0);
6425
found_count=delete_count=0;
6429
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
6431
char warn_buff[MYSQL_ERRMSG_SIZE];
6432
my_snprintf(warn_buff, sizeof(warn_buff),
6433
"ORDER BY ignored as there is a user-defined clustered index"
6434
" in the table '%-.192s'", from->s->table_name.str);
6435
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
6440
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
6441
MYF(MY_FAE | MY_ZEROFILL));
6442
bzero((char *) &tables, sizeof(tables));
6444
tables.alias= tables.table_name= from->s->table_name.str;
6445
tables.db= from->s->db.str;
6448
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
6449
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
6450
&tables, fields, all_fields, order) ||
6451
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
6452
(from->sort.found_records= filesort(thd, from, sortorder, length,
6453
(SQL_SELECT *) 0, HA_POS_ERROR,
6454
1, &examined_rows)) ==
6460
/* Tell handler that we have values for all columns in the to table */
6461
to->use_all_columns();
6462
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
6464
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
6466
restore_record(to, s->default_values); // Create empty record
6467
while (!(error=info.read_record(&info)))
6471
thd->send_kill_message();
6476
/* Return error if source table isn't empty. */
6477
if (error_if_not_empty)
6482
if (to->next_number_field)
6484
if (auto_increment_field_copied)
6485
to->auto_increment_field_not_null= TRUE;
6487
to->next_number_field->reset();
6490
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
6492
copy_ptr->do_copy(copy_ptr);
6494
prev_insert_id= to->file->next_insert_id;
6495
error=to->file->ha_write_row(to->record[0]);
6496
to->auto_increment_field_not_null= FALSE;
6500
to->file->is_fatal_error(error, HA_CHECK_DUP))
6502
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
6504
uint key_nr= to->file->get_dup_key(error);
6505
if ((int) key_nr >= 0)
6507
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
6509
(to->key_info[0].key_part[0].field->flags &
6510
AUTO_INCREMENT_FLAG))
6511
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
6512
to->file->print_keydup_error(key_nr, err_msg);
6517
to->file->print_error(error,MYF(0));
6520
to->file->restore_auto_increment(prev_insert_id);
6526
end_read_record(&info);
6527
free_io_cache(from);
6528
delete [] copy; // This is never 0
6530
if (to->file->ha_end_bulk_insert() && error <= 0)
6532
to->file->print_error(my_errno,MYF(0));
6535
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
6537
if (ha_enable_transaction(thd, TRUE))
6544
Ensure that the new table is saved properly to disk so that we
6547
if (ha_autocommit_or_rollback(thd, 0))
6549
if (end_active_trans(thd))
6553
thd->variables.sql_mode= save_sql_mode;
6554
thd->abort_on_warning= 0;
6555
free_io_cache(from);
6556
*copied= found_count;
6557
*deleted=delete_count;
6558
to->file->ha_release_auto_increment();
6559
if (to->file->ha_external_lock(thd,F_UNLCK))
6561
DBUG_RETURN(error > 0 ? -1 : 0);
6566
Recreates tables by calling mysql_alter_table().
6569
mysql_recreate_table()
6571
tables Tables to recreate
6574
Like mysql_alter_table().
6576
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
6578
HA_CREATE_INFO create_info;
6579
Alter_info alter_info;
6581
DBUG_ENTER("mysql_recreate_table");
6582
DBUG_ASSERT(!table_list->next_global);
6584
table_list->table has been closed and freed. Do not reference
6585
uninitialized data. open_tables() could fail.
6587
table_list->table= NULL;
6589
bzero((char*) &create_info, sizeof(create_info));
6590
create_info.row_type=ROW_TYPE_NOT_USED;
6591
create_info.default_table_charset=default_charset_info;
6592
/* Force alter table to recreate table */
6593
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
6594
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
6595
table_list, &alter_info, 0,
6600
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
6601
HA_CHECK_OPT *check_opt)
6604
List<Item> field_list;
6606
Protocol *protocol= thd->protocol;
6607
DBUG_ENTER("mysql_checksum_table");
6609
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
6610
item->maybe_null= 1;
6611
field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
6612
MY_INT64_NUM_DECIMAL_DIGITS));
6613
item->maybe_null= 1;
6614
if (protocol->send_fields(&field_list,
6615
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
6618
/* Open one table after the other to keep lock time as short as possible. */
6619
for (table= tables; table; table= table->next_local)
6621
char table_name[NAME_LEN*2+2];
6624
strxmov(table_name, table->db ,".", table->table_name, NullS);
6626
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
6627
thd->clear_error(); // these errors shouldn't get client
6629
protocol->prepare_for_resend();
6630
protocol->store(table_name, system_charset_info);
6634
/* Table didn't exist */
6635
protocol->store_null();
6640
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
6641
!(check_opt->flags & T_EXTEND))
6642
protocol->store((ulonglong)t->file->checksum());
6643
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
6644
(check_opt->flags & T_QUICK))
6645
protocol->store_null();
6648
/* calculating table's checksum */
6650
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
6652
t->use_all_columns();
6654
if (t->file->ha_rnd_init(1))
6655
protocol->store_null();
6660
ha_checksum row_crc= 0;
6661
int error= t->file->rnd_next(t->record[0]);
6662
if (unlikely(error))
6664
if (error == HA_ERR_RECORD_DELETED)
6668
if (t->s->null_bytes)
6670
/* fix undefined null bits */
6671
t->record[0][t->s->null_bytes-1] |= null_mask;
6672
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
6673
t->record[0][0] |= 1;
6675
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
6678
for (uint i= 0; i < t->s->fields; i++ )
6680
Field *f= t->field[i];
6681
if ((f->type() == MYSQL_TYPE_BLOB) ||
6682
(f->type() == MYSQL_TYPE_VARCHAR))
6686
row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
6689
row_crc= my_checksum(row_crc, f->ptr,
6695
protocol->store((ulonglong)crc);
6696
t->file->ha_rnd_end();
6700
close_thread_tables(thd);
6701
table->table=0; // For query cache
6703
if (protocol->write())
6711
close_thread_tables(thd); // Shouldn't be needed
6717
static bool check_engine(THD *thd, const char *table_name,
6718
HA_CREATE_INFO *create_info)
6720
handlerton **new_engine= &create_info->db_type;
6721
handlerton *req_engine= *new_engine;
6722
bool no_substitution= 1;
6723
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
6724
no_substitution, 1)))
6727
if (req_engine && req_engine != *new_engine)
6729
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
6730
ER_WARN_USING_OTHER_HANDLER,
6731
ER(ER_WARN_USING_OTHER_HANDLER),
6732
ha_resolve_storage_engine_name(*new_engine),
6735
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
6736
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
6738
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
6740
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
6741
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
6745
*new_engine= myisam_hton;