12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
/* drop and alter of tables */
19
#include <plugin/myisam/myisam.h>
20
#include <drizzled/show.h>
21
#include <drizzled/error.h>
22
#include <drizzled/gettext.h>
23
#include <drizzled/data_home.h>
24
#include <drizzled/sql_parse.h>
25
#include <drizzled/my_hash.h>
26
#include <drizzled/sql_lex.h>
27
#include <drizzled/session.h>
28
#include <drizzled/sql_base.h>
29
#include <drizzled/strfunc.h>
30
#include <drizzled/lock.h>
31
#include <drizzled/unireg.h>
32
#include <drizzled/item/int.h>
33
#include <drizzled/item/empty_string.h>
34
#include <drizzled/transaction_services.h>
35
#include <drizzled/transaction_services.h>
36
#include <drizzled/table_proto.h>
37
#include <drizzled/plugin/client.h>
38
#include <drizzled/identifier.h>
39
#include <drizzled/internal/m_string.h>
40
#include <drizzled/global_charset_info.h>
41
#include <drizzled/charset.h>
43
#include <drizzled/definition/cache.h>
45
#include <drizzled/statement/alter_table.h>
46
#include <drizzled/sql_table.h>
47
#include <drizzled/pthread_globals.h>
48
#include <drizzled/typelib.h>
49
#include <drizzled/plugin/storage_engine.h>
54
#include <boost/unordered_set.hpp>
61
bool is_primary_key(KeyInfo *key_info)
63
static const char * primary_key_name="PRIMARY";
64
return (strcmp(key_info->name, primary_key_name)==0);
67
const char* is_primary_key_name(const char* key_name)
69
static const char * primary_key_name="PRIMARY";
70
if (strcmp(key_name, primary_key_name)==0)
76
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
77
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
79
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
84
If the table character set was not given explicitly,
85
let's fetch the database default character set and
86
apply it to the table.
88
identifier::Schema identifier(db);
89
if (create_info->default_table_charset == NULL)
90
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
18
#include "mysql_priv.h"
24
int creating_table= 0; // How many mysql_create_table are running
26
const char *primary_key_name="PRIMARY";
28
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
29
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
30
static int copy_data_between_tables(TABLE *from,TABLE *to,
31
List<Create_field> &create, bool ignore,
32
uint order_num, ORDER *order,
33
ha_rows *copied,ha_rows *deleted,
34
enum enum_enable_or_disable keys_onoff,
35
bool error_if_not_empty);
37
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
38
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
40
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
41
Alter_info *alter_info,
44
handler *file, KEY **key_info_buffer,
45
uint *key_count, int select_field_count);
47
mysql_prepare_alter_table(THD *thd, TABLE *table,
48
HA_CREATE_INFO *create_info,
49
Alter_info *alter_info);
52
Translate a file name to a table name (WL #1324).
55
filename_to_tablename()
56
from The file name in my_charset_filename.
57
to OUT The table name in system_charset_info.
58
to_length The size of the table name buffer.
63
uint filename_to_tablename(const char *from, char *to, uint to_length)
68
if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
70
/* Temporary table name. */
71
res= (strnmov(to, from, to_length) - to);
75
res= strconvert(&my_charset_filename, from,
76
system_charset_info, to, to_length, &errors);
77
if (errors) // Old 5.0 name
79
res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) -
81
sql_print_error("Invalid (old?) table or database name '%s'", from);
83
TODO: add a stored procedure for fix table and database names,
84
and mention its name in error log.
94
Translate a table name to a file name (WL #1324).
97
tablename_to_filename()
98
from The table name in system_charset_info.
99
to OUT The file name in my_charset_filename.
100
to_length The size of the file name buffer.
106
uint tablename_to_filename(const char *from, char *to, uint to_length)
110
if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
111
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
112
return((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
114
(from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
115
length= strconvert(system_charset_info, from,
116
&my_charset_filename, to, to_length, &errors);
117
if (check_if_legal_tablename(to) &&
118
length + 4 < to_length)
120
memcpy(to + length, "@@@", 4);
128
Creates path to a file: mysql_data_dir/db/table.ext
131
build_table_filename()
132
buff Where to write result in my_charset_filename.
133
This may be the same as table_name.
135
db Database name in system_charset_info.
136
table_name Table name in system_charset_info.
138
flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
139
table_name is temporary, do not change.
143
Uses database and table name, and extension to create
144
a file name in mysql_data_dir. Database and table
145
names are converted from system_charset_info into "fscs".
146
Unless flags indicate a temporary table name.
147
'db' is always converted.
148
'ext' is not converted.
150
The conversion suppression is required for ALTER TABLE. This
151
statement creates intermediate tables. These are regular
152
(non-temporary) tables with a temporary name. Their path names must
153
be derivable from the table name. So we cannot use
154
build_tmptable_filename() for them.
160
uint build_table_filename(char *buff, size_t bufflen, const char *db,
161
const char *table_name, const char *ext, uint flags)
163
char dbbuff[FN_REFLEN];
164
char tbbuff[FN_REFLEN];
166
if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
167
strnmov(tbbuff, table_name, sizeof(tbbuff));
169
VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
171
VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
173
char *end = buff + bufflen;
174
/* Don't add FN_ROOTDIR if mysql_data_home already includes it */
175
char *pos = strnmov(buff, mysql_data_home, bufflen);
176
int rootdir_len= strlen(FN_ROOTDIR);
177
if (pos - rootdir_len >= buff &&
178
memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
179
pos= strnmov(pos, FN_ROOTDIR, end - pos);
180
pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
182
unpack_dirname(buff, buff);
185
pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
192
Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
195
build_tmptable_filename()
196
thd The thread handle.
197
buff Where to write result in my_charset_filename.
202
Uses current_pid, thread_id, and tmp_table counter to create
203
a file name in mysql_tmpdir.
209
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
212
char *p= strnmov(buff, mysql_tmpdir, bufflen);
213
snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
214
tmp_file_prefix, current_pid,
215
thd->thread_id, thd->tmp_table++, reg_ext);
217
if (lower_case_table_names)
219
/* Convert all except tmpdir to lower case */
220
my_casedn_str(files_charset_info, p);
223
uint length= unpack_filename(buff, buff);
228
--------------------------------------------------------------------------
233
This module is used to ensure that we can recover from crashes that occur
234
in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
235
We need to ensure that both t1 and t2 are dropped and not only t1 and
236
also that each table drop is entirely done and not "half-baked".
238
To support this we create log entries for each meta-data statement in the
239
ddl log while we are executing. These entries are dropped when the
240
operation is completed.
242
At recovery those entries that were not completed will be executed.
244
There is only one ddl log in the system and it is protected by a mutex
245
and there is a global struct that contains information about its current
249
First version written in 2006 by Mikael Ronstrom
250
--------------------------------------------------------------------------
254
struct st_global_ddl_log
257
We need to adjust buffer size to be able to handle downgrades/upgrades
258
where IO_SIZE has changed. We'll set the buffer size such that we can
259
handle that the buffer size was upto 4 times bigger in the version
260
that wrote the DDL log.
262
char file_entry_buf[4*IO_SIZE];
263
char file_name_str[FN_REFLEN];
265
DDL_LOG_MEMORY_ENTRY *first_free;
266
DDL_LOG_MEMORY_ENTRY *first_used;
274
st_global_ddl_log() : inited(false), do_release(false) {}
277
st_global_ddl_log global_ddl_log;
279
pthread_mutex_t LOCK_gdl;
281
#define DDL_LOG_ENTRY_TYPE_POS 0
282
#define DDL_LOG_ACTION_TYPE_POS 1
283
#define DDL_LOG_PHASE_POS 2
284
#define DDL_LOG_NEXT_ENTRY_POS 4
285
#define DDL_LOG_NAME_POS 8
287
#define DDL_LOG_NUM_ENTRY_POS 0
288
#define DDL_LOG_NAME_LEN_POS 4
289
#define DDL_LOG_IO_SIZE_POS 8
292
Read one entry from ddl log file
294
read_ddl_log_file_entry()
295
entry_no Entry number to read
301
static bool read_ddl_log_file_entry(uint entry_no)
304
File file_id= global_ddl_log.file_id;
305
uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
306
ssize_t io_size= (ssize_t)global_ddl_log.io_size;
308
if (pread(file_id, file_entry_buf, io_size, io_size * entry_no) != io_size)
315
Write one entry from ddl log file
317
write_ddl_log_file_entry()
318
entry_no Entry number to read
324
static bool write_ddl_log_file_entry(uint entry_no)
327
File file_id= global_ddl_log.file_id;
328
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
330
if (pwrite(file_id, (uchar*)file_entry_buf,
331
IO_SIZE, IO_SIZE * entry_no) != IO_SIZE)
340
write_ddl_log_header()
346
static bool write_ddl_log_header()
351
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
352
global_ddl_log.num_entries);
354
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
357
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
359
if (write_ddl_log_file_entry(0UL))
361
sql_print_error("Error writing ddl log header");
364
VOID(sync_ddl_log());
370
Create ddl log file name
372
create_ddl_log_file_name()
373
file_name Filename setup
378
static inline void create_ddl_log_file_name(char *file_name)
380
strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
385
Read header of ddl log file
387
read_ddl_log_header()
389
> 0 Last entry in ddl log
390
0 No entries in ddl log
392
When we read the ddl log header we get information about maximum sizes
393
of names in the ddl log and we also get information about the number
394
of entries in the ddl log.
397
static uint read_ddl_log_header()
399
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
400
char file_name[FN_REFLEN];
402
bool successful_open= false;
404
create_ddl_log_file_name(file_name);
405
if ((global_ddl_log.file_id= my_open(file_name,
406
O_RDWR | O_BINARY, MYF(0))) >= 0)
408
if (read_ddl_log_file_entry(0UL))
410
/* Write message into error log */
411
sql_print_error("Failed to read ddl log file in recovery");
414
successful_open= true;
416
entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
417
global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
420
global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
421
assert(global_ddl_log.io_size <=
422
sizeof(global_ddl_log.file_entry_buf));
428
global_ddl_log.first_free= NULL;
429
global_ddl_log.first_used= NULL;
430
global_ddl_log.num_entries= 0;
431
VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
432
global_ddl_log.do_release= true;
441
read_entry Number of entry to read
442
out:entry_info Information from entry
447
Read a specified entry in the ddl log
450
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
452
char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
456
if (read_ddl_log_file_entry(read_entry))
460
ddl_log_entry->entry_pos= read_entry;
461
single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
462
ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
463
single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
464
ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
465
ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
466
ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
467
ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
468
inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
469
ddl_log_entry->from_name= &file_entry_buf[inx];
470
inx+= global_ddl_log.name_len;
471
ddl_log_entry->handler_name= &file_entry_buf[inx];
482
Write the header of the ddl log file and length of names. Also set
483
number of entries to zero.
490
static bool init_ddl_log()
492
char file_name[FN_REFLEN];
494
if (global_ddl_log.inited)
497
global_ddl_log.io_size= IO_SIZE;
498
create_ddl_log_file_name(file_name);
499
if ((global_ddl_log.file_id= my_create(file_name,
501
O_RDWR | O_TRUNC | O_BINARY,
504
/* Couldn't create ddl log file, this is serious error */
505
sql_print_error("Failed to open ddl log file");
508
global_ddl_log.inited= true;
509
if (write_ddl_log_header())
511
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
512
global_ddl_log.inited= false;
522
Execute one action in a ddl log entry
524
execute_ddl_log_action()
525
ddl_log_entry Information in action entry to execute
531
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
533
bool frm_action= false;
534
LEX_STRING handler_name;
538
char to_path[FN_REFLEN];
539
char from_path[FN_REFLEN];
542
if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
546
handler_name.str= (char*)ddl_log_entry->handler_name;
547
handler_name.length= strlen(ddl_log_entry->handler_name);
548
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
549
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
553
plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
556
my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
559
hton= plugin_data(plugin, handlerton*);
560
file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
563
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
567
switch (ddl_log_entry->action_type)
569
case DDL_LOG_REPLACE_ACTION:
570
case DDL_LOG_DELETE_ACTION:
572
if (ddl_log_entry->phase == 0)
576
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
577
if ((error= my_delete(to_path, MYF(MY_WME))))
579
if (my_errno != ENOENT)
585
if ((error= file->ha_delete_table(ddl_log_entry->name)))
587
if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
591
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
593
VOID(sync_ddl_log());
595
if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
598
assert(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
600
Fall through and perform the rename action of the replace
601
action. We have already indicated the success of the delete
602
action in the log entry by stepping up the phase.
605
case DDL_LOG_RENAME_ACTION:
610
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
611
strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
612
if (my_rename(from_path, to_path, MYF(MY_WME)))
617
if (file->ha_rename_table(ddl_log_entry->from_name,
618
ddl_log_entry->name))
621
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
623
VOID(sync_ddl_log());
633
free_root(&mem_root, MYF(0));
639
Get a free entry in the ddl log
641
get_free_ddl_log_entry()
642
out:active_entry A ddl log memory entry returned
648
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
651
DDL_LOG_MEMORY_ENTRY *used_entry;
652
DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
654
if (global_ddl_log.first_free == NULL)
656
if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
657
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
659
sql_print_error("Failed to allocate memory for ddl log free list");
662
global_ddl_log.num_entries++;
663
used_entry->entry_pos= global_ddl_log.num_entries;
668
used_entry= global_ddl_log.first_free;
669
global_ddl_log.first_free= used_entry->next_log_entry;
670
*write_header= false;
673
Move from free list to used list
675
used_entry->next_log_entry= first_used;
676
used_entry->prev_log_entry= NULL;
677
global_ddl_log.first_used= used_entry;
679
first_used->prev_log_entry= used_entry;
681
*active_entry= used_entry;
687
External interface methods for the DDL log Module
688
---------------------------------------------------
693
write_ddl_log_entry()
694
ddl_log_entry Information about log entry
695
out:entry_written Entry information written into
702
A careful write of the ddl log is performed to ensure that we can
703
handle crashes occurring during CREATE and ALTER TABLE processing.
706
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
707
DDL_LOG_MEMORY_ENTRY **active_entry)
709
bool error, write_header;
715
global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
716
(char)DDL_LOG_ENTRY_CODE;
717
global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
718
(char)ddl_log_entry->action_type;
719
global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
720
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
721
ddl_log_entry->next_entry);
722
assert(strlen(ddl_log_entry->name) < FN_LEN);
723
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
724
ddl_log_entry->name, FN_LEN - 1);
725
if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
726
ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
728
assert(strlen(ddl_log_entry->from_name) < FN_LEN);
729
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
730
ddl_log_entry->from_name, FN_LEN - 1);
733
global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
734
assert(strlen(ddl_log_entry->handler_name) < FN_LEN);
735
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
736
ddl_log_entry->handler_name, FN_LEN - 1);
737
if (get_free_ddl_log_entry(active_entry, &write_header))
742
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
745
sql_print_error("Failed to write entry_no = %u",
746
(*active_entry)->entry_pos);
748
if (write_header && !error)
750
VOID(sync_ddl_log());
751
if (write_ddl_log_header())
755
release_ddl_log_memory_entry(*active_entry);
761
Write final entry in the ddl log
763
write_execute_ddl_log_entry()
764
first_entry First entry in linked list of entries
765
to execute, if 0 = NULL it means that
766
the entry is removed and the entries
767
are put into the free list.
768
complete Flag indicating we are simply writing
769
info about that entry has been completed
770
in:out:active_entry Entry to execute, 0 = NULL if the entry
771
is written first time and needs to be
772
returned. In this case the entry written
773
is returned in this parameter
779
This is the last write in the ddl log. The previous log entries have
780
already been written but not yet synched to disk.
781
We write a couple of log entries that describes action to perform.
782
This entries are set-up in a linked list, however only when a first
783
execute entry is put as the first entry these will be executed.
784
This routine writes this first
787
bool write_execute_ddl_log_entry(uint first_entry,
789
DDL_LOG_MEMORY_ENTRY **active_entry)
791
bool write_header= false;
792
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
801
We haven't synched the log entries yet, we synch them now before
802
writing the execute entry. If complete is true we haven't written
803
any log entries before, we are only here to write the execute
804
entry to indicate it is done.
806
VOID(sync_ddl_log());
807
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
810
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
811
file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
812
file_entry_buf[DDL_LOG_PHASE_POS]= 0;
813
int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
814
file_entry_buf[DDL_LOG_NAME_POS]= 0;
815
file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
816
file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
817
if (!(*active_entry))
819
if (get_free_ddl_log_entry(active_entry, &write_header))
824
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
826
sql_print_error("Error writing execute entry in ddl log");
827
release_ddl_log_memory_entry(*active_entry);
830
VOID(sync_ddl_log());
833
if (write_ddl_log_header())
835
release_ddl_log_memory_entry(*active_entry);
844
For complex rename operations we need to deactivate individual entries.
846
deactivate_ddl_log_entry()
847
entry_no Entry position of record to change
852
During replace operations where we start with an existing table called
853
t1 and a replacement table called t1#temp or something else and where
854
we want to delete t1 and rename t1#temp to t1 this is not possible to
855
do in a safe manner unless the ddl log is informed of the phases in
858
Delete actions are 1-phase actions that can be ignored immediately after
860
Rename actions from x to y is also a 1-phase action since there is no
861
interaction with any other handlers named x and y.
862
Replace action where drop y and x -> y happens needs to be a two-phase
863
action. Thus the first phase will drop y and the second phase will
867
bool deactivate_ddl_log_entry(uint entry_no)
869
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
871
if (!read_ddl_log_file_entry(entry_no))
873
if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
875
if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
876
file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
877
(file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
878
file_entry_buf[DDL_LOG_PHASE_POS] == 1))
879
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
880
else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
882
assert(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
883
file_entry_buf[DDL_LOG_PHASE_POS]= 1;
889
if (write_ddl_log_file_entry(entry_no))
891
sql_print_error("Error in deactivating log entry. Position = %u",
899
sql_print_error("Failed in reading entry before deactivating it");
919
if ((!global_ddl_log.recovery_phase) &&
924
if (my_sync(global_ddl_log.file_id, MYF(0)))
926
/* Write to error log */
927
sql_print_error("Failed to sync ddl log");
935
Release a log memory entry
937
release_ddl_log_memory_entry()
938
log_memory_entry Log memory entry to release
943
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
945
DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
946
DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
947
DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
949
global_ddl_log.first_free= log_entry;
950
log_entry->next_log_entry= first_free;
953
prev_log_entry->next_log_entry= next_log_entry;
955
global_ddl_log.first_used= next_log_entry;
957
next_log_entry->prev_log_entry= prev_log_entry;
963
Execute one entry in the ddl log. Executing an entry means executing
964
a linked list of actions.
966
execute_ddl_log_entry()
967
first_entry Reference to first action in entry
973
bool execute_ddl_log_entry(THD *thd, uint first_entry)
975
DDL_LOG_ENTRY ddl_log_entry;
976
uint read_entry= first_entry;
978
pthread_mutex_lock(&LOCK_gdl);
981
if (read_ddl_log_entry(read_entry, &ddl_log_entry))
983
/* Write to error log and continue with next log entry */
984
sql_print_error("Failed to read entry = %u from ddl log",
988
assert(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
989
ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
991
if (execute_ddl_log_action(thd, &ddl_log_entry))
993
/* Write to error log and continue with next log entry */
994
sql_print_error("Failed to execute action for entry = %u from ddl log",
998
read_entry= ddl_log_entry.next_entry;
999
} while (read_entry);
1000
pthread_mutex_unlock(&LOCK_gdl);
1013
static void close_ddl_log()
1015
if (global_ddl_log.file_id >= 0)
1017
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
1018
global_ddl_log.file_id= (File) -1;
1025
Execute the ddl log at recovery of MySQL Server
1027
execute_ddl_log_recovery()
1032
void execute_ddl_log_recovery()
1034
uint num_entries, i;
1036
DDL_LOG_ENTRY ddl_log_entry;
1037
char file_name[FN_REFLEN];
1040
Initialise global_ddl_log struct
1042
bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
1043
global_ddl_log.inited= false;
1044
global_ddl_log.recovery_phase= true;
1045
global_ddl_log.io_size= IO_SIZE;
1046
global_ddl_log.file_id= (File) -1;
1049
To be able to run this from boot, we allocate a temporary THD
1053
thd->thread_stack= (char*) &thd;
1054
thd->store_globals();
1056
num_entries= read_ddl_log_header();
1057
for (i= 1; i < num_entries + 1; i++)
1059
if (read_ddl_log_entry(i, &ddl_log_entry))
1061
sql_print_error("Failed to read entry no = %u from ddl log",
1065
if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
1067
if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
1069
/* Real unpleasant scenario but we continue anyways. */
1075
create_ddl_log_file_name(file_name);
1076
VOID(my_delete(file_name, MYF(0)));
1077
global_ddl_log.recovery_phase= false;
1079
/* Remember that we don't have a THD */
1080
my_pthread_setspecific_ptr(THR_THD, 0);
1086
Release all memory allocated to the ddl log
1093
void release_ddl_log()
1095
DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
1096
DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
1098
if (!global_ddl_log.do_release)
1101
pthread_mutex_lock(&LOCK_gdl);
1104
DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
1105
my_free(used_list, MYF(0));
1110
DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
1111
my_free(free_list, MYF(0));
1115
global_ddl_log.inited= 0;
1116
pthread_mutex_unlock(&LOCK_gdl);
1117
VOID(pthread_mutex_destroy(&LOCK_gdl));
1118
global_ddl_log.do_release= false;
1124
---------------------------------------------------------------------------
1127
--------------------
1129
---------------------------------------------------------------------------
1137
clear_error is clear_error to be called
97
1138
query Query to log
98
1139
query_length Length of query
1296
2603
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1297
2604
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1301
2608
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1303
if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
2610
if (sql_field->sql_type == MYSQL_TYPE_BLOB)
1305
2612
/* The user has given a length to the blob column */
2613
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1306
2614
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1308
2616
sql_field->length= 0;
1313
static bool locked_create_event(Session *session,
1314
const identifier::Table &identifier,
1315
HA_CREATE_INFO *create_info,
1316
message::Table &table_proto,
1317
AlterInfo *alter_info,
1318
bool is_if_not_exists,
1319
bool internal_tmp_table,
1322
KeyInfo *key_info_buffer)
2623
Preparation of Create_field for SP function return values.
2624
Based on code used in the inner loop of mysql_prepare_create_table()
2628
sp_prepare_create_field()
2630
sql_field Field to prepare
2633
Prepares the field structures for field creation.
2637
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1329
@note if we are building a temp table we need to check to see if a temp table
1330
already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1331
to create a table under a temporary table.
1334
plugin::StorageEngine::doesTableExist(*session, identifier,
1335
identifier.getType() != message::Table::STANDARD );
1339
if (is_if_not_exists)
1342
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1343
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1344
identifier.getTableName().c_str());
1345
create_info->table_existed= 1; // Mark that table existed
1349
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
if (identifier.getType() == message::Table::STANDARD) // We have a real table
1357
We don't assert here, but check the result, because the table could be
1358
in the table definition cache and in the same time the .frm could be
1359
missing from the disk, in case of manual intervention which deletes
1360
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1361
Then she could create the table. This case is pretty obscure and
1362
therefore we don't introduce a new error message only for it.
1365
@todo improve this error condition.
1367
if (definition::Cache::singleton().find(identifier.getKey()))
1369
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1376
session->set_proc_info("creating table");
1377
create_info->table_existed= 0; // Mark that table is created
1379
create_info->table_options= db_options;
1381
if (not rea_create_table(session, identifier,
1383
create_info, alter_info->create_list,
1384
key_count, key_info_buffer))
1389
if (identifier.getType() == message::Table::TEMPORARY)
1391
/* Open table and put in temporary table list */
1392
if (not (session->open_temporary_table(identifier)))
1394
(void) session->rm_temporary_table(identifier);
1400
We keep this behind the lock to make sure ordering is correct for a table.
1401
This is a very unlikely problem where before we would write out to the
1402
trans log, someone would do a delete/create operation.
1405
if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1407
TransactionServices &transaction_services= TransactionServices::singleton();
1408
transaction_services.createTable(*session, table_proto);
2639
if (sql_field->sql_type == MYSQL_TYPE_SET ||
2640
sql_field->sql_type == MYSQL_TYPE_ENUM)
2642
uint32 field_length, dummy;
2643
if (sql_field->sql_type == MYSQL_TYPE_SET)
2645
calculate_interval_lengths(sql_field->charset,
2646
sql_field->interval, &dummy,
2648
sql_field->length= field_length +
2649
(sql_field->interval->count - 1);
2651
else /* MYSQL_TYPE_ENUM */
2653
calculate_interval_lengths(sql_field->charset,
2654
sql_field->interval,
2655
&field_length, &dummy);
2656
sql_field->length= field_length;
2658
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
2661
sql_field->create_length_to_internal_length();
2662
assert(sql_field->def == 0);
2663
/* Can't go wrong as sql_field->def is not defined */
2664
(void) prepare_blob_field(thd, sql_field);
1416
Ignore the name of this function... it locks :(
1421
create_table_no_lock()
1422
session Thread object
2672
mysql_create_table_no_lock()
1424
2675
table_name Table name
1425
2676
create_info Create information (like MAX_ROWS)
1426
2677
fields List of fields to create
1427
2678
keys List of keys to create
1428
2679
internal_tmp_table Set to 1 if this is an internal temporary table
1433
2684
If one creates a temporary table, this is automatically opened
1435
2686
Note that this function assumes that caller already have taken
1436
2687
name-lock on table being created or used some other way to ensure
1437
that concurrent operations won't intervene. create_table()
2688
that concurrent operations won't intervene. mysql_create_table()
1438
2689
is a wrapper that can be used for this.
2691
no_log is needed for the case of CREATE ... SELECT,
2692
as the logging will be done later in sql_insert.cc
2693
select_field_count is also used for CREATE ... SELECT,
2694
and must be zero for standard create of table.
1445
bool create_table_no_lock(Session *session,
1446
const identifier::Table &identifier,
2701
bool mysql_create_table_no_lock(THD *thd,
2702
const char *db, const char *table_name,
1447
2703
HA_CREATE_INFO *create_info,
1448
message::Table &table_proto,
1449
AlterInfo *alter_info,
2704
Alter_info *alter_info,
1450
2705
bool internal_tmp_table,
1451
uint32_t select_field_count,
1452
bool is_if_not_exists)
2706
uint select_field_count)
2708
char path[FN_REFLEN];
1454
2711
uint db_options, key_count;
1455
KeyInfo *key_info_buffer;
2712
KEY *key_info_buffer;
1456
2714
bool error= true;
1458
2715
/* Check for duplicate fields and check type of table to create */
1459
if (not alter_info->create_list.elements)
2716
if (!alter_info->create_list.elements)
1461
2718
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1465
assert(identifier.getTableName() == table_proto.name());
2722
if (check_engine(thd, table_name, create_info))
1466
2724
db_options= create_info->table_options;
1468
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1470
/* Build a Table object to pass down to the engine, and the do the actual create. */
1471
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1474
&key_info_buffer, &key_count,
1475
select_field_count))
1477
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
error= locked_create_event(session,
1485
db_options, key_count,
1489
session->set_proc_info("After create");
2725
if (create_info->row_type == ROW_TYPE_DYNAMIC)
2726
db_options|=HA_OPTION_PACK_RECORD;
2727
alias= table_case_name(create_info, table_name);
2728
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
2729
create_info->db_type)))
2731
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
2735
set_table_default_charset(thd, create_info, (char*) db);
2737
if (mysql_prepare_create_table(thd, create_info, alter_info,
2740
&key_info_buffer, &key_count,
2741
select_field_count))
2744
/* Check if table exists */
2745
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2747
path_length= build_tmptable_filename(thd, path, sizeof(path));
2748
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
2753
/* check if the table name contains FN_DEVCHAR when defined */
2754
if (strchr(alias, FN_DEVCHAR))
2756
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
2760
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
2761
internal_tmp_table ? FN_IS_TMP : 0);
2764
/* Check if table already exists */
2765
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
2766
find_temporary_table(thd, db, table_name))
2768
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2770
create_info->table_existed= 1; // Mark that table existed
2771
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2772
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
2777
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
2781
VOID(pthread_mutex_lock(&LOCK_open));
2782
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2784
if (!access(path,F_OK))
2786
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2788
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2789
goto unlock_and_end;
2792
We don't assert here, but check the result, because the table could be
2793
in the table definition cache and in the same time the .frm could be
2794
missing from the disk, in case of manual intervention which deletes
2795
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
2796
Then she could create the table. This case is pretty obscure and
2797
therefore we don't introduce a new error message only for it.
2799
if (get_cached_table_share(db, alias))
2801
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2802
goto unlock_and_end;
2807
Check that table with given name does not already
2808
exist in any storage engine. In such a case it should
2809
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
2810
unless user specified CREATE TABLE IF EXISTS
2811
The LOCK_open mutex has been locked to make sure no
2812
one else is attempting to discover the table. Since
2813
it's not on disk as a frm file, no one could be using it!
2815
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2817
bool create_if_not_exists =
2818
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
2819
int retcode = ha_table_exists_in_engine(thd, db, table_name);
2822
case HA_ERR_NO_SUCH_TABLE:
2823
/* Normal case, no table exists. we can go and create it */
2825
case HA_ERR_TABLE_EXIST:
2827
if (create_if_not_exists)
2829
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2830
goto unlock_and_end;
2833
my_error(retcode, MYF(0),table_name);
2834
goto unlock_and_end;
2838
thd_proc_info(thd, "creating table");
2839
create_info->table_existed= 0; // Mark that table is created
2841
#ifdef HAVE_READLINK
2842
if (test_if_data_home_dir(create_info->data_file_name))
2844
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
2845
goto unlock_and_end;
2847
if (test_if_data_home_dir(create_info->index_file_name))
2849
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
2850
goto unlock_and_end;
2854
#endif /* HAVE_READLINK */
2856
if (create_info->data_file_name)
2857
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
2858
"DATA DIRECTORY option ignored");
2859
if (create_info->index_file_name)
2860
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
2861
"INDEX DIRECTORY option ignored");
2862
create_info->data_file_name= create_info->index_file_name= 0;
2864
create_info->table_options=db_options;
2866
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
2867
if (rea_create_table(thd, path, db, table_name,
2868
create_info, alter_info->create_list,
2869
key_count, key_info_buffer, file))
2870
goto unlock_and_end;
2872
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2874
/* Open table and put in temporary table list */
2875
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
2877
(void) rm_temporary_table(create_info->db_type, path, false);
2878
goto unlock_and_end;
2880
thd->thread_specific_used= true;
2884
Don't write statement if:
2885
- It is an internal temporary table,
2886
- Row-based logging is used and it we are creating a temporary table, or
2887
- The binary log is not open.
2888
Otherwise, the statement shall be binlogged.
2890
if (!internal_tmp_table &&
2891
(!thd->current_stmt_binlog_row_based ||
2892
(thd->current_stmt_binlog_row_based &&
2893
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
2894
write_bin_log(thd, true, thd->query, thd->query_length);
2897
VOID(pthread_mutex_unlock(&LOCK_open));
2900
thd_proc_info(thd, "After create");
2906
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2907
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
2909
create_info->table_existed= 1; // Mark that table existed
2910
goto unlock_and_end;
1495
@note the following two methods implement create [temporary] table.
2915
Database locking aware wrapper for mysql_create_table_no_lock(),
1497
static bool drizzle_create_table(Session *session,
1498
const identifier::Table &identifier,
1499
HA_CREATE_INFO *create_info,
1500
message::Table &table_proto,
1501
AlterInfo *alter_info,
1502
bool internal_tmp_table,
1503
uint32_t select_field_count,
1504
bool is_if_not_exists)
2918
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
2919
HA_CREATE_INFO *create_info,
2920
Alter_info *alter_info,
2921
bool internal_tmp_table,
2922
uint select_field_count)
1506
Table *name_lock= NULL;
2924
TABLE *name_lock= 0;
1509
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1513
else if (name_lock == NULL)
1515
if (is_if_not_exists)
1517
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1518
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1519
identifier.getTableName().c_str());
1520
create_info->table_existed= 1;
1525
my_error(ER_TABLE_EXISTS_ERROR, identifier);
2927
/* Wait for any database locks */
2928
pthread_mutex_lock(&LOCK_lock_db);
2929
while (!thd->killed &&
2930
hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
2932
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
2933
pthread_mutex_lock(&LOCK_lock_db);
2938
pthread_mutex_unlock(&LOCK_lock_db);
2942
pthread_mutex_unlock(&LOCK_lock_db);
2944
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2946
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
1531
result= create_table_no_lock(session,
2953
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2955
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2956
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
2958
create_info->table_existed= 1;
2963
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2970
result= mysql_create_table_no_lock(thd, db, table_name, create_info,
2973
select_field_count);
1543
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1544
session->unlink_open_table(name_lock);
2978
pthread_mutex_lock(&LOCK_open);
2979
unlink_open_table(thd, name_lock, false);
2980
pthread_mutex_unlock(&LOCK_open);
2982
pthread_mutex_lock(&LOCK_lock_db);
2983
if (!--creating_table && creating_database)
2984
pthread_cond_signal(&COND_refresh);
2985
pthread_mutex_unlock(&LOCK_lock_db);
1547
2986
return(result);
1552
Database locking aware wrapper for create_table_no_lock(),
1554
bool create_table(Session *session,
1555
const identifier::Table &identifier,
1556
HA_CREATE_INFO *create_info,
1557
message::Table &table_proto,
1558
AlterInfo *alter_info,
1559
bool internal_tmp_table,
1560
uint32_t select_field_count,
1561
bool is_if_not_exists)
1563
if (identifier.isTmp())
1565
return create_table_no_lock(session,
1575
return drizzle_create_table(session,
1587
2991
** Give the key name after the first field with an optional '_#' after
1591
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
2995
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1593
for (KeyInfo *key=start ; key != end ; key++)
2997
for (KEY *key=start ; key != end ; key++)
1594
2998
if (!my_strcasecmp(system_charset_info,name,key->name))
2103
bool create_like_table(Session* session,
2104
identifier::Table::const_reference destination_identifier,
2105
identifier::Table::const_reference source_identifier,
2106
message::Table &create_table_proto,
2107
bool is_if_not_exists,
3904
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
3905
HA_CREATE_INFO *create_info)
3907
TABLE *name_lock= 0;
3908
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
3909
uint dst_path_length;
3910
char *db= table->db;
3911
char *table_name= table->table_name;
2110
3913
bool res= true;
2111
bool table_exists= false;
3917
/* CREATE TABLE ... LIKE is not allowed for views. */
3918
src_table->required_type= FRMTYPE_TABLE;
3921
By opening source table we guarantee that it exists and no concurrent
3922
DDL operation will mess with it. Later we also take an exclusive
3923
name-lock on target table name, which makes copying of .frm file,
3924
call to ha_create_table() and binlogging atomic against concurrent DML
3925
and DDL operations on target table. Thus by holding both these "locks"
3926
we ensure that our statement is properly isolated from all concurrent
3927
operations which matter.
3929
if (open_tables(thd, &src_table, ¬_used, 0))
3932
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
2114
3935
Check that destination tables does not exist. Note that its name
2115
3936
was already checked when it was added to the table list.
2117
For temporary tables we don't aim to grab locks.
2119
if (destination_identifier.isTmp())
2121
if (session->find_temporary_table(destination_identifier))
2127
bool was_created= create_table_wrapper(*session,
2129
destination_identifier,
2132
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2134
(void) session->rm_temporary_table(destination_identifier, true);
2136
else if (not session->open_temporary_table(destination_identifier))
2138
// We created, but we can't open... also, a hack.
2139
(void) session->rm_temporary_table(destination_identifier, true);
2147
else // Standard table which will require locks.
2149
Table *name_lock= 0;
2151
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2155
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2156
session->unlink_open_table(name_lock);
2166
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2170
else // Otherwise we create the table
2174
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
source_identifier, is_engine_set);
2179
// So we blew the creation of the table, and we scramble to clean up
2180
// anything that might have been created (read... it is a hack)
2181
if (not was_created)
2183
plugin::StorageEngine::dropTable(*session, destination_identifier);
3938
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3940
if (find_temporary_table(thd, db, table_name))
3942
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
3943
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
3947
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
3951
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
3952
db, table_name, reg_ext, 0);
3953
if (!access(dst_path, F_OK))
3958
Create a new table by copying from source table
3960
Altough exclusive name-lock on target table protects us from concurrent
3961
DML and DDL operations on it we still want to wrap .FRM creation and call
3962
to ha_create_table() in critical section protected by LOCK_open in order
3963
to provide minimal atomicity against operations which disregard name-locks,
3964
like I_S implementation, for example. This is a temporary and should not
3965
be copied. Instead we should fix our code to always honor name-locks.
3967
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
3968
during the call to ha_create_table(). See bug #28614 for more info.
3970
VOID(pthread_mutex_lock(&LOCK_open));
3971
if (src_table->schema_table)
3973
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
3975
VOID(pthread_mutex_unlock(&LOCK_open));
3979
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
3981
if (my_errno == ENOENT)
3982
my_error(ER_BAD_DB_ERROR,MYF(0),db);
3984
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
3985
VOID(pthread_mutex_unlock(&LOCK_open));
3990
As mysql_truncate don't work on a new table at this stage of
3991
creation, instead create the table directly (for both normal
3992
and temporary tables).
3994
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
3995
if (thd->variables.keep_files_on_create)
3996
create_info->options|= HA_CREATE_KEEP_FILES;
3997
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3998
VOID(pthread_mutex_unlock(&LOCK_open));
4000
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
4002
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
4005
(void) rm_temporary_table(create_info->db_type,
4006
dst_path, false); /* purecov: inspected */
4007
goto err; /* purecov: inspected */
4012
(void) quick_rm_table(create_info->db_type, db,
4013
table_name, 0); /* purecov: inspected */
4014
goto err; /* purecov: inspected */
4018
We have to write the query before we unlock the tables.
4020
if (thd->current_stmt_binlog_row_based)
4023
Since temporary tables are not replicated under row-based
4024
replication, CREATE TABLE ... LIKE ... needs special
4025
treatement. We have four cases to consider, according to the
4026
following decision table:
4028
==== ========= ========= ==============================
4029
Case Target Source Write to binary log
4030
==== ========= ========= ==============================
4031
1 normal normal Original statement
4032
2 normal temporary Generated statement
4033
3 temporary normal Nothing
4034
4 temporary temporary Nothing
4035
==== ========= ========= ==============================
4037
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
4039
if (src_table->table->s->tmp_table) // Case 2
4042
String query(buf, sizeof(buf), system_charset_info);
4043
query.length(0); // Have to zero it since constructor doesn't
4047
Here we open the destination table, on which we already have
4048
name-lock. This is needed for store_create_info() to work.
4049
The table will be closed by unlink_open_table() at the end
4052
table->table= name_lock;
4053
VOID(pthread_mutex_lock(&LOCK_open));
4054
if (reopen_name_locked_table(thd, table, false))
4056
VOID(pthread_mutex_unlock(&LOCK_open));
4059
VOID(pthread_mutex_unlock(&LOCK_open));
4061
int result= store_create_info(thd, table, &query,
4064
assert(result == 0); // store_create_info() always return 0
4065
write_bin_log(thd, true, query.ptr(), query.length());
4068
write_bin_log(thd, true, thd->query, thd->query_length);
4071
Case 3 and 4 does nothing under RBR
4075
write_bin_log(thd, true, thd->query, thd->query_length);
4081
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
4083
char warn_buff[MYSQL_ERRMSG_SIZE];
4084
snprintf(warn_buff, sizeof(warn_buff),
4085
ER(ER_TABLE_EXISTS_ERROR), table_name);
4086
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4087
ER_TABLE_EXISTS_ERROR,warn_buff);
4091
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
4096
pthread_mutex_lock(&LOCK_open);
4097
unlink_open_table(thd, name_lock, false);
4098
pthread_mutex_unlock(&LOCK_open);
4104
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
4106
thr_lock_type lock_type = TL_READ_NO_INSERT;
4108
return(mysql_admin_table(thd, tables, check_opt,
4109
"analyze", lock_type, 1, 0, 0, 0,
4110
&handler::ha_analyze));
4114
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
4116
thr_lock_type lock_type = TL_READ_NO_INSERT;
4118
return(mysql_admin_table(thd, tables, check_opt,
4120
0, 0, HA_OPEN_FOR_REPAIR, 0,
4121
&handler::ha_check));
4125
/* table_list should contain just one table */
4127
mysql_discard_or_import_tablespace(THD *thd,
4128
TABLE_LIST *table_list,
4129
enum tablespace_op_type tablespace_op)
4136
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
4140
thd_proc_info(thd, "discard_or_import_tablespace");
4142
discard= test(tablespace_op == DISCARD_TABLESPACE);
4145
We set this flag so that ha_innobase::open and ::external_lock() do
4146
not complain when we lock the table
4148
thd->tablespace_op= true;
4149
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
4151
thd->tablespace_op=false;
4155
error= table->file->ha_discard_or_import_tablespace(discard);
4157
thd_proc_info(thd, "end");
4162
/* The ALTER TABLE is always in its own transaction */
4163
error = ha_autocommit_or_rollback(thd, 0);
4164
if (end_active_trans(thd))
4168
write_bin_log(thd, false, thd->query, thd->query_length);
4171
ha_autocommit_or_rollback(thd, error);
4172
thd->tablespace_op=false;
4180
table->file->print_error(error, MYF(0));
4186
Copy all changes detected by parser to the HA_ALTER_FLAGS
4189
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
4191
uint flags= alter_info->flags;
4193
if (ALTER_ADD_COLUMN & flags)
4194
*alter_flags|= HA_ADD_COLUMN;
4195
if (ALTER_DROP_COLUMN & flags)
4196
*alter_flags|= HA_DROP_COLUMN;
4197
if (ALTER_RENAME & flags)
4198
*alter_flags|= HA_RENAME_TABLE;
4199
if (ALTER_CHANGE_COLUMN & flags)
4200
*alter_flags|= HA_CHANGE_COLUMN;
4201
if (ALTER_COLUMN_DEFAULT & flags)
4202
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
4203
if (ALTER_COLUMN_STORAGE & flags)
4204
*alter_flags|= HA_COLUMN_STORAGE;
4205
if (ALTER_COLUMN_FORMAT & flags)
4206
*alter_flags|= HA_COLUMN_FORMAT;
4207
if (ALTER_COLUMN_ORDER & flags)
4208
*alter_flags|= HA_ALTER_COLUMN_ORDER;
4209
if (ALTER_STORAGE & flags)
4210
*alter_flags|= HA_ALTER_STORAGE;
4211
if (ALTER_ROW_FORMAT & flags)
4212
*alter_flags|= HA_ALTER_ROW_FORMAT;
4213
if (ALTER_RECREATE & flags)
4214
*alter_flags|= HA_RECREATE;
4215
if (ALTER_FOREIGN_KEY & flags)
4216
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4222
@param table The original table.
4223
@param alter_info Alter options, fields and keys for the new
4225
@param create_info Create options for the new table.
4226
@param order_num Number of order list elements.
4227
@param[out] ha_alter_flags Flags that indicate what will be changed
4228
@param[out] ha_alter_info Data structures needed for on-line alter
4229
@param[out] table_changes Information about particular change
4231
First argument 'table' contains information of the original
4232
table, which includes all corresponding parts that the new
4233
table has in arguments create_list, key_list and create_info.
4235
By comparing the changes between the original and new table
4236
we can determine how much it has changed after ALTER TABLE
4237
and whether we need to make a copy of the table, or just change
4240
Mark any changes detected in the ha_alter_flags.
4242
If there are no data changes, but index changes, 'index_drop_buffer'
4243
and/or 'index_add_buffer' are populated with offsets into
4244
table->key_info or key_info_buffer respectively for the indexes
4245
that need to be dropped and/or (re-)created.
4248
@retval false success
4253
compare_tables(THD *thd,
4255
Alter_info *alter_info,
4256
HA_CREATE_INFO *create_info,
4258
HA_ALTER_FLAGS *alter_flags,
4259
HA_ALTER_INFO *ha_alter_info,
4260
uint *table_changes)
4262
Field **f_ptr, *field;
4263
uint table_changes_local= 0;
4264
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
4265
Create_field *new_field;
4266
KEY_PART_INFO *key_part;
4269
Remember if the new definition has new VARCHAR column;
4270
create_info->varchar will be reset in mysql_prepare_create_table.
4272
bool varchar= create_info->varchar;
4276
Create a copy of alter_info.
4277
To compare the new and old table definitions, we need to "prepare"
4278
the new definition - transform it from parser output to a format
4279
that describes the final table layout (all column defaults are
4280
initialized, duplicate columns are removed). This is done by
4281
mysql_prepare_create_table. Unfortunately,
4282
mysql_prepare_create_table performs its transformations
4283
"in-place", that is, modifies the argument. Since we would
4284
like to keep compare_tables() idempotent (not altering any
4285
of the arguments) we create a copy of alter_info here and
4286
pass it to mysql_prepare_create_table, then use the result
4287
to evaluate possibility of fast ALTER TABLE, and then
4290
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4291
THD *thd= table->in_use;
4292
uint db_options= 0; /* not used */
4293
/* Create the prepared information. */
4294
if (mysql_prepare_create_table(thd, create_info,
4296
(table->s->tmp_table != NO_TMP_TABLE),
4299
&ha_alter_info->key_info_buffer,
4300
&ha_alter_info->key_count,
4301
/* select_field_count */ 0))
4303
/* Allocate result buffers. */
4304
if (! (ha_alter_info->index_drop_buffer=
4305
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
4306
! (ha_alter_info->index_add_buffer=
4307
(uint*) thd->alloc(sizeof(uint) *
4308
tmp_alter_info.key_list.elements)))
4312
First we setup ha_alter_flags based on what was detected
4315
setup_ha_alter_flags(alter_info, alter_flags);
4319
Some very basic checks. If number of fields changes, or the
4320
handler, we need to run full ALTER TABLE. In the future
4321
new fields can be added and old dropped without copy, but
4324
Test also that engine was not given during ALTER TABLE, or
4325
we are force to run regular alter table (copy).
4326
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
4328
For the following ones we also want to run regular alter table:
4329
ALTER TABLE tbl_name ORDER BY ..
4330
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
4332
At the moment we can't handle altering temporary tables without a copy.
4333
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
4334
In that case we always do full copy.
4336
There was a bug prior to mysql-4.0.25. Number of null fields was
4337
calculated incorrectly. As a result frm and data files gets out of
4338
sync after fast alter table. There is no way to determine by which
4339
mysql version (in 4.0 and 4.1 branches) table was created, thus we
4340
disable fast alter table for all tables created by mysql versions
4341
prior to 5.0 branch.
4344
if (table->s->fields != alter_info->create_list.elements ||
4345
table->s->db_type() != create_info->db_type ||
4346
table->s->tmp_table ||
4347
create_info->used_fields & HA_CREATE_USED_ENGINE ||
4348
create_info->used_fields & HA_CREATE_USED_CHARSET ||
4349
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
4350
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
4351
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
4353
!table->s->mysql_version ||
4354
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4356
*table_changes= IS_EQUAL_NO;
4358
Check what has changed and set alter_flags
4360
if (table->s->fields < alter_info->create_list.elements)
4361
*alter_flags|= HA_ADD_COLUMN;
4362
else if (table->s->fields > alter_info->create_list.elements)
4363
*alter_flags|= HA_DROP_COLUMN;
4364
if (create_info->db_type != table->s->db_type() ||
4365
create_info->used_fields & HA_CREATE_USED_ENGINE)
4366
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
4367
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
4368
*alter_flags|= HA_CHANGE_CHARACTER_SET;
4369
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
4370
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
4371
if (alter_info->flags & ALTER_RECREATE)
4372
*alter_flags|= HA_RECREATE;
4373
/* TODO check for ADD/DROP FOREIGN KEY */
4374
if (alter_info->flags & ALTER_FOREIGN_KEY)
4375
*alter_flags|= HA_ALTER_FOREIGN_KEY;
4376
if (!table->s->mysql_version ||
4377
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
4378
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4381
Go through fields and check if the original ones are compatible
4384
for (f_ptr= table->field, new_field= new_field_it++;
4385
(new_field && (field= *f_ptr));
4386
f_ptr++, new_field= new_field_it++)
4388
/* Make sure we have at least the default charset in use. */
4389
if (!new_field->charset)
4390
new_field->charset= create_info->default_table_charset;
4392
/* Don't pack rows in old tables if the user has requested this. */
4393
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
4394
(new_field->flags & BLOB_FLAG) ||
4395
(new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
4396
create_info->table_options|= HA_OPTION_PACK_RECORD;
4398
/* Check how fields have been modified */
4399
if (alter_info->flags & ALTER_CHANGE_COLUMN)
4401
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
4402
if (!(table_changes_local= field->is_equal(new_field)))
4403
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4405
/* Check if field was renamed */
4406
field->flags&= ~FIELD_IS_RENAMED;
4407
if (my_strcasecmp(system_charset_info,
4409
new_field->field_name))
4411
field->flags|= FIELD_IS_RENAMED;
4412
*alter_flags|= HA_ALTER_COLUMN_NAME;
4415
*table_changes&= table_changes_local;
4416
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
4417
*alter_flags|= HA_ALTER_COLUMN_TYPE;
4419
/* Check that NULL behavior is same for old and new fields */
4420
if ((new_field->flags & NOT_NULL_FLAG) !=
4421
(uint) (field->flags & NOT_NULL_FLAG))
4423
*table_changes= IS_EQUAL_NO;
4424
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
4428
/* Clear indexed marker */
4429
field->flags&= ~FIELD_IN_ADD_INDEX;
4433
Go through keys and check if the original ones are compatible
4437
KEY *table_key_end= table->key_info + table->s->keys;
4440
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
4443
Step through all keys of the old table and search matching new keys.
4445
ha_alter_info->index_drop_count= 0;
4446
ha_alter_info->index_add_count= 0;
4447
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4449
KEY_PART_INFO *table_part;
4450
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
4451
KEY_PART_INFO *new_part;
4453
/* Search a new key with the same name. */
4454
for (new_key= ha_alter_info->key_info_buffer;
4455
new_key < new_key_end;
4458
if (! strcmp(table_key->name, new_key->name))
4461
if (new_key >= new_key_end)
4463
/* Key not found. Add the offset of the key to the drop buffer. */
4464
ha_alter_info->index_drop_buffer
4465
[ha_alter_info->index_drop_count++]=
4466
table_key - table->key_info;
4467
if (table_key->flags & HA_NOSAME)
4469
/* Unique key. Check for "PRIMARY". */
4470
if (! my_strcasecmp(system_charset_info,
4471
table_key->name, primary_key_name))
4472
*alter_flags|= HA_DROP_PK_INDEX;
4474
*alter_flags|= HA_DROP_UNIQUE_INDEX;
4477
*alter_flags|= HA_DROP_INDEX;
4478
*table_changes= IS_EQUAL_NO;
4482
/* Check that the key types are compatible between old and new tables. */
4483
if ((table_key->algorithm != new_key->algorithm) ||
4484
((table_key->flags & HA_KEYFLAG_MASK) !=
4485
(new_key->flags & HA_KEYFLAG_MASK)) ||
4486
(table_key->key_parts != new_key->key_parts))
4488
if (table_key->flags & HA_NOSAME)
4490
// Unique key. Check for "PRIMARY".
4491
if (! my_strcasecmp(system_charset_info,
4492
table_key->name, primary_key_name))
4493
*alter_flags|= HA_ALTER_PK_INDEX;
4495
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4498
*alter_flags|= HA_ALTER_INDEX;
4503
Check that the key parts remain compatible between the old and
4506
for (table_part= table_key->key_part, new_part= new_key->key_part;
4507
table_part < table_part_end;
4508
table_part++, new_part++)
4511
Key definition has changed if we are using a different field or
4512
if the used key part length is different. We know that the fields
4513
did not change. Comparing field numbers is sufficient.
4515
if ((table_part->length != new_part->length) ||
4516
(table_part->fieldnr - 1 != new_part->fieldnr))
4518
if (table_key->flags & HA_NOSAME)
4520
/* Unique key. Check for "PRIMARY" */
4521
if (! my_strcasecmp(system_charset_info,
4522
table_key->name, primary_key_name))
4523
*alter_flags|= HA_ALTER_PK_INDEX;
4525
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
4528
*alter_flags|= HA_ALTER_INDEX;
4535
/* Key modified. Add the offset of the key to both buffers. */
4536
ha_alter_info->index_drop_buffer
4537
[ha_alter_info->index_drop_count++]=
4538
table_key - table->key_info;
4539
ha_alter_info->index_add_buffer
4540
[ha_alter_info->index_add_count++]=
4541
new_key - ha_alter_info->key_info_buffer;
4542
key_part= new_key->key_part;
4543
end= key_part + new_key->key_parts;
4544
for(; key_part != end; key_part++)
4546
/* Mark field to be part of new key */
4547
if ((field= table->field[key_part->fieldnr]))
4548
field->flags|= FIELD_IN_ADD_INDEX;
4550
*table_changes= IS_EQUAL_NO;
4552
/*end of for (; table_key < table_key_end;) */
4555
Step through all keys of the new table and find matching old keys.
4557
for (new_key= ha_alter_info->key_info_buffer;
4558
new_key < new_key_end;
4561
/* Search an old key with the same name. */
4562
for (table_key= table->key_info; table_key < table_key_end; table_key++)
4564
if (! strcmp(table_key->name, new_key->name))
4567
if (table_key >= table_key_end)
4569
/* Key not found. Add the offset of the key to the add buffer. */
4570
ha_alter_info->index_add_buffer
4571
[ha_alter_info->index_add_count++]=
4572
new_key - ha_alter_info->key_info_buffer;
4573
key_part= new_key->key_part;
4574
end= key_part + new_key->key_parts;
4575
for(; key_part != end; key_part++)
4577
/* Mark field to be part of new key */
4578
if ((field= table->field[key_part->fieldnr]))
4579
field->flags|= FIELD_IN_ADD_INDEX;
4581
if (new_key->flags & HA_NOSAME)
4583
/* Unique key. Check for "PRIMARY" */
4584
if (! my_strcasecmp(system_charset_info,
4585
new_key->name, primary_key_name))
4586
*alter_flags|= HA_ADD_PK_INDEX;
4588
*alter_flags|= HA_ADD_UNIQUE_INDEX;
4591
*alter_flags|= HA_ADD_INDEX;
4592
*table_changes= IS_EQUAL_NO;
4601
Manages enabling/disabling of indexes for ALTER TABLE
4604
alter_table_manage_keys()
4606
indexes_were_disabled Whether the indexes of the from table
4608
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
4616
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
4617
enum enum_enable_or_disable keys_onoff)
4620
switch (keys_onoff) {
4622
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4625
if (!indexes_were_disabled)
4627
/* fall-through: disabled indexes */
4629
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4632
if (error == HA_ERR_WRONG_COMMAND)
4634
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4635
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4636
table->s->table_name.str);
4639
table->file->print_error(error, MYF(0));
4644
int create_temporary_table(THD *thd,
4648
HA_CREATE_INFO *create_info,
4649
Alter_info *alter_info,
4653
char index_file[FN_REFLEN], data_file[FN_REFLEN];
4654
handlerton *old_db_type, *new_db_type;
4655
old_db_type= table->s->db_type();
4656
new_db_type= create_info->db_type;
4658
Handling of symlinked tables:
4660
Create new data file and index file on the same disk as the
4661
old data and index files.
4663
Rename new data file over old data file and new index file over
4665
Symlinks are not changed.
4668
Create new data file and index file on the same disk as the
4669
old data and index files. Create also symlinks to point at
4672
At end, rename intermediate tables, and symlinks to intermediate
4673
table, to final table name.
4674
Remove old table and old symlinks
4676
If rename is made to another database:
4677
Create new tables in new database.
4679
Remove old table and symlinks.
4681
if (db_changed) // Ignore symlink if db changed
4683
if (create_info->index_file_name)
4685
/* Fix index_file_name to have 'tmp_name' as basename */
4686
strmov(index_file, tmp_name);
4687
create_info->index_file_name=fn_same(index_file,
4688
create_info->index_file_name,
4691
if (create_info->data_file_name)
4693
/* Fix data_file_name to have 'tmp_name' as basename */
4694
strmov(data_file, tmp_name);
4695
create_info->data_file_name=fn_same(data_file,
4696
create_info->data_file_name,
4701
create_info->data_file_name=create_info->index_file_name=0;
4704
Create a table with a temporary name.
4705
With create_info->frm_only == 1 this creates a .frm file only.
4706
We don't log the statement, it will be logged later.
4708
tmp_disable_binlog(thd);
4709
error= mysql_create_table(thd, new_db, tmp_name,
4710
create_info, alter_info, 1, 0);
4711
reenable_binlog(thd);
4717
Create a temporary table that reflects what an alter table operation
4721
create_altered_table()
4723
table The original table
4724
create_info Information from the parsing phase about new
4726
alter_info Lists of fields, keys to be changed, added
4728
db_change Specifies if the table is moved to another database
4730
A temporary table with all changes
4733
The temporary table is created without storing it in any storage engine
4734
and is opened only to get the table struct and frm file reference.
4736
TABLE *create_altered_table(THD *thd,
4739
HA_CREATE_INFO *create_info,
4740
Alter_info *alter_info,
4744
HA_CREATE_INFO altered_create_info(*create_info);
4745
TABLE *altered_table;
4747
char path[FN_REFLEN];
4749
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
4750
tmp_file_prefix, current_pid, thd->thread_id);
4751
/* Safety fix for InnoDB */
4752
if (lower_case_table_names)
4753
my_casedn_str(files_charset_info, tmp_name);
4754
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
4755
altered_create_info.frm_only= 1;
4756
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4757
&altered_create_info,
4758
alter_info, db_change)))
4763
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4765
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
4767
return(altered_table);
4774
Perform a fast or on-line alter table
4777
mysql_fast_or_online_alter_table()
4779
table The original table
4780
altered_table A temporary table showing how we will change table
4781
create_info Information from the parsing phase about new
4783
alter_info Storage place for data used during different phases
4784
ha_alter_flags Bitmask that shows what will be changed
4785
keys_onoff Specifies if keys are to be enabled/disabled
4788
>0 An error occured during the on-line alter table operation
4789
-1 Error when re-opening table
4791
If mysql_alter_table does not need to copy the table, it is
4792
either a fast alter table where the storage engine does not
4793
need to know about the change, only the frm will change,
4794
or the storage engine supports performing the alter table
4795
operation directly, on-line without mysql having to copy
4798
int mysql_fast_or_online_alter_table(THD *thd,
4800
TABLE *altered_table,
4801
HA_CREATE_INFO *create_info,
4802
HA_ALTER_INFO *alter_info,
4803
HA_ALTER_FLAGS *ha_alter_flags,
4804
enum enum_enable_or_disable keys_onoff)
4807
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
4813
Tell the handler to prepare for the online alter
4815
if ((error= table->file->alter_table_phase1(thd,
4825
Tell the storage engine to perform the online alter table
4827
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
4828
we need to wrap the next call with a DDL lock.
4830
if ((error= table->file->alter_table_phase2(thd,
4840
The final .frm file is already created as a temporary file
4841
and will be renamed to the original table name.
4843
VOID(pthread_mutex_lock(&LOCK_open));
4844
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4845
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4847
close_data_files_and_morph_locks(thd,
4848
table->pos_in_table_list->db,
4849
table->pos_in_table_list->table_name);
4850
if (mysql_rename_table(NULL,
4851
altered_table->s->db.str,
4852
altered_table->s->table_name.str,
4854
table->s->table_name.str, FN_FROM_IS_TMP))
4857
VOID(pthread_mutex_unlock(&LOCK_open));
4860
broadcast_refresh();
4861
VOID(pthread_mutex_unlock(&LOCK_open));
4864
The ALTER TABLE is always in its own transaction.
4865
Commit must not be called while LOCK_open is locked. It could call
4866
wait_if_global_read_lock(), which could create a deadlock if called
4869
error= ha_autocommit_or_rollback(thd, 0);
4877
VOID(pthread_mutex_lock(&LOCK_open));
4878
if (reopen_table(table))
4883
VOID(pthread_mutex_unlock(&LOCK_open));
4887
Tell the handler that the changed frm is on disk and table
4890
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
4896
We are going to reopen table down on the road, so we have to restore
4897
state of the TABLE object which we used for obtaining of handler
4898
object to make it suitable for reopening.
4900
assert(t_table == table);
4901
table->open_placeholder= 1;
4902
VOID(pthread_mutex_lock(&LOCK_open));
4903
close_handle_and_leave_table_as_lock(table);
4904
VOID(pthread_mutex_unlock(&LOCK_open));
4915
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
4917
This function transforms parse output of ALTER TABLE - lists of
4918
columns and keys to add, drop or modify into, essentially,
4919
CREATE TABLE definition - a list of columns and keys of the new
4920
table. While doing so, it also performs some (bug not all)
4923
This function is invoked when we know that we're going to
4924
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
4925
is not possible, perhaps because the ALTER statement contains
4926
instructions that require change in table data, not only in
4927
table definition or indexes.
4929
@param[in,out] thd thread handle. Used as a memory pool
4930
and source of environment information.
4931
@param[in] table the source table, open and locked
4932
Used as an interface to the storage engine
4933
to acquire additional information about
4935
@param[in,out] create_info A blob with CREATE/ALTER TABLE
4937
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
4938
Originally create_info was used only in
4939
CREATE TABLE and alter_info only in ALTER TABLE.
4940
But since ALTER might end-up doing CREATE,
4941
this distinction is gone and we just carry
4942
around two structures.
4945
Fills various create_info members based on information retrieved
4946
from the storage engine.
4947
Sets create_info->varchar if the table has a VARCHAR column.
4948
Prepares alter_info->create_list and alter_info->key_list with
4949
columns and keys of the new table.
4950
@retval true error, out of memory or a semantical error in ALTER
4952
@retval false success
4956
mysql_prepare_alter_table(THD *thd, TABLE *table,
4957
HA_CREATE_INFO *create_info,
4958
Alter_info *alter_info)
4960
/* New column definitions are added here */
4961
List<Create_field> new_create_list;
4962
/* New key definitions are added here */
4963
List<Key> new_key_list;
4964
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
4965
List_iterator<Create_field> def_it(alter_info->create_list);
4966
List_iterator<Alter_column> alter_it(alter_info->alter_list);
4967
List_iterator<Key> key_it(alter_info->key_list);
4968
List_iterator<Create_field> find_it(new_create_list);
4969
List_iterator<Create_field> field_it(new_create_list);
4970
List<Key_part_spec> key_parts;
4971
uint db_create_options= (table->s->db_create_options
4972
& ~(HA_OPTION_PACK_RECORD));
4973
uint used_fields= create_info->used_fields;
4974
KEY *key_info=table->key_info;
4978
create_info->varchar= false;
4979
/* Let new create options override the old ones */
4980
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
4981
create_info->min_rows= table->s->min_rows;
4982
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
4983
create_info->max_rows= table->s->max_rows;
4984
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
4985
create_info->avg_row_length= table->s->avg_row_length;
4986
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
4987
create_info->default_table_charset= table->s->table_charset;
4988
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
4990
/* Table has an autoincrement, copy value to new table */
4991
table->file->info(HA_STATUS_AUTO);
4992
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4994
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4995
create_info->key_block_size= table->s->key_block_size;
4996
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4997
create_info->transactional= table->s->transactional;
4999
restore_record(table, s->default_values); // Empty record for DEFAULT
5003
First collect all fields from table which isn't in drop_list
5005
Field **f_ptr,*field;
5006
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
5008
if (field->type() == MYSQL_TYPE_STRING)
5009
create_info->varchar= true;
5010
/* Check if field should be dropped */
5013
while ((drop=drop_it++))
5015
if (drop->type == Alter_drop::COLUMN &&
5016
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
5018
/* Reset auto_increment value if it was dropped */
5019
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
5020
!(used_fields & HA_CREATE_USED_AUTO))
5022
create_info->auto_increment_value=0;
5023
create_info->used_fields|=HA_CREATE_USED_AUTO;
5033
/* Check if field is changed */
5035
while ((def=def_it++))
5038
!my_strcasecmp(system_charset_info,field->field_name, def->change))
5042
{ // Field is changed
5046
new_create_list.push_back(def);
5053
This field was not dropped and not changed, add it to the list
5056
def= new Create_field(field, field);
5057
new_create_list.push_back(def);
5058
alter_it.rewind(); // Change default if ALTER
5059
Alter_column *alter;
5060
while ((alter=alter_it++))
5062
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
5067
if (def->sql_type == MYSQL_TYPE_BLOB)
5069
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
5072
if ((def->def=alter->def)) // Use new default
5073
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
5075
def->flags|= NO_DEFAULT_VALUE_FLAG;
5081
while ((def=def_it++)) // Add new columns
5083
if (def->change && ! def->field)
5085
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
5089
Check that the DATE/DATETIME not null field we are going to add is
5090
either has a default value or the '0000-00-00' is allowed by the
5092
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
5093
flag to allow ALTER TABLE only if the table to be altered is empty.
5095
if ((def->sql_type == MYSQL_TYPE_NEWDATE ||
5096
def->sql_type == MYSQL_TYPE_DATETIME) &&
5097
!alter_info->datetime_field &&
5098
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
5099
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
5101
alter_info->datetime_field= def;
5102
alter_info->error_if_not_empty= true;
5105
new_create_list.push_back(def);
5106
else if (def->after == first_keyword)
5107
new_create_list.push_front(def);
5112
while ((find=find_it++)) // Add new columns
5114
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
5119
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
5122
find_it.after(def); // Put element after this
5124
XXX: hack for Bug#28427.
5125
If column order has changed, force OFFLINE ALTER TABLE
5126
without querying engine capabilities. If we ever have an
5127
engine that supports online ALTER TABLE CHANGE COLUMN
5128
<name> AFTER <name1> (Falcon?), this fix will effectively
5129
disable the capability.
5130
TODO: detect the situation in compare_tables, behave based
5131
on engine capabilities.
5133
if (alter_info->build_method == HA_BUILD_ONLINE)
5135
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5138
alter_info->build_method= HA_BUILD_OFFLINE;
5141
if (alter_info->alter_list.elements)
5143
my_error(ER_BAD_FIELD_ERROR, MYF(0),
5144
alter_info->alter_list.head()->name, table->s->table_name.str);
5147
if (!new_create_list.elements)
5149
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
5155
Collect all keys which isn't in drop list. Add only those
5156
for which some fields exists.
5159
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
5161
char *key_name= key_info->name;
5164
while ((drop=drop_it++))
5166
if (drop->type == Alter_drop::KEY &&
5167
!my_strcasecmp(system_charset_info,key_name, drop->name))
5176
KEY_PART_INFO *key_part= key_info->key_part;
5178
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
5180
if (!key_part->field)
5181
continue; // Wrong field (from UNIREG)
5182
const char *key_part_name=key_part->field->field_name;
5183
Create_field *cfield;
5185
while ((cfield=field_it++))
5189
if (!my_strcasecmp(system_charset_info, key_part_name,
5193
else if (!my_strcasecmp(system_charset_info,
5194
key_part_name, cfield->field_name))
5198
continue; // Field is removed
5199
uint key_part_length=key_part->length;
5200
if (cfield->field) // Not new field
5203
If the field can't have only a part used in a key according to its
5204
new type, or should not be used partially according to its
5205
previous type, or the field length is less than the key part
5206
length, unset the key part length.
5208
We also unset the key part length if it is the same as the
5209
old field's length, so the whole new field will be used.
5211
BLOBs may have cfield->length == 0, which is why we test it before
5212
checking whether cfield->length < key_part_length (in chars).
5214
if (!Field::type_can_have_key_part(cfield->field->type()) ||
5215
!Field::type_can_have_key_part(cfield->sql_type) ||
5216
(cfield->field->field_length == key_part_length &&
5217
!f_is_blob(key_part->key_type)) ||
5218
(cfield->length && (cfield->length < key_part_length /
5219
key_part->field->charset()->mbmaxlen)))
5220
key_part_length= 0; // Use whole field
5222
key_part_length /= key_part->field->charset()->mbmaxlen;
5223
key_parts.push_back(new Key_part_spec(cfield->field_name,
5224
strlen(cfield->field_name),
5227
if (key_parts.elements)
5229
KEY_CREATE_INFO key_create_info;
5231
enum Key::Keytype key_type;
5232
bzero((char*) &key_create_info, sizeof(key_create_info));
5234
key_create_info.algorithm= key_info->algorithm;
5235
if (key_info->flags & HA_USES_BLOCK_SIZE)
5236
key_create_info.block_size= key_info->block_size;
5237
if (key_info->flags & HA_USES_COMMENT)
5238
key_create_info.comment= key_info->comment;
5240
if (key_info->flags & HA_NOSAME)
5242
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
5243
key_type= Key::PRIMARY;
5245
key_type= Key::UNIQUE;
5248
key_type= Key::MULTIPLE;
5250
key= new Key(key_type, key_name, strlen(key_name),
5252
test(key_info->flags & HA_GENERATED_KEY),
5254
new_key_list.push_back(key);
5259
while ((key=key_it++)) // Add new keys
5261
if (key->type != Key::FOREIGN_KEY)
5262
new_key_list.push_back(key);
5263
if (key->name.str &&
5264
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
5266
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
5272
if (alter_info->drop_list.elements)
5274
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5275
alter_info->drop_list.head()->name);
5278
if (alter_info->alter_list.elements)
5280
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
5281
alter_info->alter_list.head()->name);
5285
if (!create_info->comment.str)
5287
create_info->comment.str= table->s->comment.str;
5288
create_info->comment.length= table->s->comment.length;
5291
table->file->update_create_info(create_info);
5292
if ((create_info->table_options &
5293
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
5294
(used_fields & HA_CREATE_USED_PACK_KEYS))
5295
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
5296
if (create_info->table_options &
5297
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
5298
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
5299
if (create_info->table_options &
5300
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
5301
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
5302
HA_OPTION_NO_DELAY_KEY_WRITE);
5303
create_info->table_options|= db_create_options;
5305
if (table->s->tmp_table)
5306
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
5309
alter_info->create_list.swap(new_create_list);
5310
alter_info->key_list.swap(new_key_list);
5322
new_db If there is a RENAME clause
5323
new_name If there is a RENAME clause
5324
create_info Information from the parsing phase about new
5326
table_list The table to change.
5327
alter_info Lists of fields, keys to be changed, added
5329
order_num How many ORDER BY fields has been specified.
5330
order List of fields to ORDER BY.
5331
ignore Whether we have ALTER IGNORE TABLE
5334
This is a veery long function and is everything but the kitchen sink :)
5335
It is used to alter a table and not only by ALTER TABLE but also
5336
CREATE|DROP INDEX are mapped on this function.
5338
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
5339
or both, then this function short cuts its operation by renaming
5340
the table and/or enabling/disabling the keys. In this case, the FRM is
5341
not changed, directly by mysql_alter_table. However, if there is a
5342
RENAME + change of a field, or an index, the short cut is not used.
5343
See how `create_list` is used to generate the new FRM regarding the
5344
structure of the fields. The same is done for the indices of the table.
5346
Important is the fact, that this function tries to do as little work as
5347
possible, by finding out whether a intermediate table is needed to copy
5348
data into and when finishing the altering to use it as the original table.
5349
For this reason the function compare_tables() is called, which decides
5350
based on all kind of data how similar are the new and the original
5358
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
5359
HA_CREATE_INFO *create_info,
5360
TABLE_LIST *table_list,
5361
Alter_info *alter_info,
5362
uint order_num, ORDER *order, bool ignore)
5364
TABLE *table, *new_table=0, *name_lock= 0;;
5366
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
5367
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
5368
char path[FN_REFLEN];
5369
ha_rows copied= 0,deleted= 0;
5370
handlerton *old_db_type, *new_db_type, *save_old_db_type;
5371
legacy_db_type table_type;
5372
frm_type_enum frm_type;
5374
if (table_list && table_list->schema_table)
5376
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
5381
Assign variables table_name, new_name, db, new_db, path
5382
to simplify further comparisons: we want to see if it's a RENAME
5383
later just by comparing the pointers, avoiding the need for strcmp.
5385
thd_proc_info(thd, "init");
5386
table_name=table_list->table_name;
5387
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
5389
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
5391
build_table_filename(path, sizeof(path), db, table_name, "", 0);
5393
mysql_ha_rm_tables(thd, table_list, false);
5395
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
5396
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
5397
/* Conditionally writes to binlog. */
5398
return(mysql_discard_or_import_tablespace(thd,table_list,
5399
alter_info->tablespace_op));
5400
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
5401
"/", table_name, reg_ext, NullS);
5402
(void) unpack_filename(new_name_buff, new_name_buff);
5404
If this is just a rename of a view, short cut to the
5405
following scenario: 1) lock LOCK_open 2) do a RENAME
5406
2) unlock LOCK_open.
5407
This is a copy-paste added to make sure
5408
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
5409
as an independent branch in mysql_execute_command. The need
5410
for a copy-paste arose because the main code flow of ALTER TABLE
5411
... RENAME tries to use open_ltable, which does not work for views
5412
(open_ltable was never modified to merge table lists of child tables
5413
into the main table list, like open_tables does).
5414
This code is wrong and will be removed, please do not copy.
5416
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
5418
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
5420
table->use_all_columns();
5423
Prohibit changing of the UNION list of a non-temporary MERGE table
5424
under LOCK tables. It would be quite difficult to reuse a shrinked
5425
set of tables from the old table or to open a new TABLE object for
5426
an extended list and verify that they belong to locked tables.
5428
if (thd->locked_tables &&
5429
(create_info->used_fields & HA_CREATE_USED_UNION) &&
5430
(table->s->tmp_table == NO_TMP_TABLE))
5432
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
5436
/* Check that we are not trying to rename to an existing table */
5439
strmov(new_name_buff,new_name);
5440
strmov(new_alias= new_alias_buff, new_name);
5441
if (lower_case_table_names)
5443
if (lower_case_table_names != 2)
5445
my_casedn_str(files_charset_info, new_name_buff);
5446
new_alias= new_name; // Create lower case table name
5448
my_casedn_str(files_charset_info, new_name);
5451
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
5454
Source and destination table names are equal: make later check
5457
new_alias= new_name= table_name;
5461
if (table->s->tmp_table != NO_TMP_TABLE)
5463
if (find_temporary_table(thd,new_db,new_name_buff))
5465
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
5471
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
5475
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5479
build_table_filename(new_name_buff, sizeof(new_name_buff),
5480
new_db, new_name_buff, reg_ext, 0);
5481
if (!access(new_name_buff, F_OK))
5483
/* Table will be closed in do_command() */
5484
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
5492
new_alias= (lower_case_table_names == 2) ? alias : table_name;
5493
new_name= table_name;
5496
old_db_type= table->s->db_type();
5497
if (!create_info->db_type)
5499
create_info->db_type= old_db_type;
5502
if (check_engine(thd, new_name, create_info))
5504
new_db_type= create_info->db_type;
5506
if (new_db_type != old_db_type ||
5507
!table->file->can_switch_engines())
5509
my_error(ER_ROW_IS_REFERENCED, MYF(0));
5513
if (create_info->row_type == ROW_TYPE_NOT_USED)
5514
create_info->row_type= table->s->row_type;
5516
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
5517
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
5519
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
5523
thd_proc_info(thd, "setup");
5524
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
5525
!table->s->tmp_table) // no need to touch frm
5527
switch (alter_info->keys_onoff) {
5532
wait_while_table_is_used() ensures that table being altered is
5533
opened only by this thread and that TABLE::TABLE_SHARE::version
5534
of TABLE object corresponding to this table is 0.
5535
The latter guarantees that no DML statement will open this table
5536
until ALTER TABLE finishes (i.e. until close_thread_tables())
5537
while the fact that the table is still open gives us protection
5538
from concurrent DDL statements.
5540
VOID(pthread_mutex_lock(&LOCK_open));
5541
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5542
VOID(pthread_mutex_unlock(&LOCK_open));
5543
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5544
/* COND_refresh will be signaled in close_thread_tables() */
5547
VOID(pthread_mutex_lock(&LOCK_open));
5548
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5549
VOID(pthread_mutex_unlock(&LOCK_open));
5550
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
5551
/* COND_refresh will be signaled in close_thread_tables() */
5558
if (error == HA_ERR_WRONG_COMMAND)
5561
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5562
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5566
VOID(pthread_mutex_lock(&LOCK_open));
5568
Unlike to the above case close_cached_table() below will remove ALL
5569
instances of TABLE from table cache (it will also remove table lock
5570
held by this thread). So to make actual table renaming and writing
5571
to binlog atomic we have to put them into the same critical section
5572
protected by LOCK_open mutex. This also removes gap for races between
5573
access() and mysql_rename_table() calls.
5576
if (!error && (new_name != table_name || new_db != db))
5578
thd_proc_info(thd, "rename");
5580
Then do a 'simple' rename of the table. First we need to close all
5581
instances of 'source' table.
5583
close_cached_table(thd, table);
5585
Then, we want check once again that target table does not exist.
5586
Actually the order of these two steps does not matter since
5587
earlier we took name-lock on the target table, so we do them
5588
in this particular order only to be consistent with 5.0, in which
5589
we don't take this name-lock and where this order really matters.
5590
TODO: Investigate if we need this access() check at all.
5592
if (!access(new_name_buff,F_OK))
5594
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
5599
*fn_ext(new_name)=0;
5600
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
5604
VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
5611
if (error == HA_ERR_WRONG_COMMAND)
5614
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5615
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
5621
write_bin_log(thd, true, thd->query, thd->query_length);
5626
table->file->print_error(error, MYF(0));
2193
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2194
session->unlink_open_table(name_lock);
2200
if (is_if_not_exists)
2202
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2205
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
5630
unlink_open_table(thd, name_lock, false);
5631
VOID(pthread_mutex_unlock(&LOCK_open));
5632
table_list->table= NULL; // For query cache
5636
/* We have to do full alter table. */
5639
If the old table had partitions and we are doing ALTER TABLE ...
5640
engine= <new_engine>, the new table must preserve the original
5641
partitioning. That means that the new engine is still the
5642
partitioning engine, not the engine specified in the parser.
5643
This is discovered in prep_alter_part_table, which in such case
5644
updates create_info->db_type.
5645
Now we need to update the stack copy of create_info->db_type,
5646
as otherwise we won't be able to correctly move the files of the
5647
temporary table to the result table files.
5649
new_db_type= create_info->db_type;
5651
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
5654
set_table_default_charset(thd, create_info, db);
5657
if (thd->variables.old_alter_table
5658
|| (table->s->db_type() != create_info->db_type)
5661
if (alter_info->build_method == HA_BUILD_ONLINE)
5663
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5666
alter_info->build_method= HA_BUILD_OFFLINE;
5669
if (alter_info->build_method != HA_BUILD_OFFLINE)
5671
TABLE *altered_table= 0;
5672
HA_ALTER_INFO ha_alter_info;
5673
HA_ALTER_FLAGS ha_alter_flags;
5674
uint table_changes= IS_EQUAL_YES;
5675
bool need_copy_table= true;
5676
/* Check how much the tables differ. */
5677
if (compare_tables(thd, table, alter_info,
5678
create_info, order_num,
5687
Check if storage engine supports altering the table
5693
If table is not renamed, changed database and
5694
some change was detected then check if engine
5695
can do the change on-line
5697
if (new_name == table_name && new_db == db &&
5698
ha_alter_flags.is_set())
5700
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
5704
check if table can be altered on-line
5706
if (!(altered_table= create_altered_table(thd,
5711
!strcmp(db, new_db))))
5714
switch (table->file->check_if_supported_alter(altered_table,
5718
case HA_ALTER_SUPPORTED_WAIT_LOCK:
5719
case HA_ALTER_SUPPORTED_NO_LOCK:
5721
@todo: Currently we always acquire an exclusive name
5722
lock on the table metadata when performing fast or online
5723
ALTER TABLE. In future we may consider this unnecessary,
5724
and narrow the scope of the exclusive name lock to only
5725
cover manipulation with .frms. Storage engine API
5726
call check_if_supported_alter has provision for this
5729
need_copy_table= false;
5731
case HA_ALTER_NOT_SUPPORTED:
5732
if (alter_info->build_method == HA_BUILD_ONLINE)
5734
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
5735
close_temporary_table(thd, altered_table, 1, 1);
5738
need_copy_table= true;
5740
case HA_ALTER_ERROR:
5742
close_temporary_table(thd, altered_table, 1, 1);
5747
/* TODO need to check if changes can be handled as fast ALTER TABLE */
5749
need_copy_table= true;
5751
if (!need_copy_table)
5753
error= mysql_fast_or_online_alter_table(thd,
5759
alter_info->keys_onoff);
5762
mysql_unlock_tables(thd, thd->lock);
5765
close_temporary_table(thd, altered_table, 1, 1);
5771
goto err_with_placeholders;
5778
pthread_mutex_lock(&LOCK_open);
5784
close_temporary_table(thd, altered_table, 1, 1);
5787
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
5788
current_pid, thd->thread_id);
5789
/* Safety fix for innodb */
5790
if (lower_case_table_names)
5791
my_casedn_str(files_charset_info, tmp_name);
5794
/* Create a temporary table with the new format */
5795
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
5796
create_info, alter_info,
5797
!strcmp(db, new_db))))
5802
/* Open the table so we need to copy the data to it. */
5803
if (table->s->tmp_table)
5806
bzero((void*) &tbl, sizeof(tbl));
5808
tbl.table_name= tbl.alias= tmp_name;
5809
/* Table is in thd->temporary_tables */
5810
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
5811
MYSQL_LOCK_IGNORE_FLUSH);
5815
char path[FN_REFLEN];
5816
/* table is a normal table: Create temporary table in same directory */
5817
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
5819
/* Open our intermediate table */
5820
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
5825
/* Copy the data if necessary. */
5826
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
5827
thd->cuted_fields=0L;
5828
thd_proc_info(thd, "copy to tmp table");
5831
We do not copy data for MERGE tables. Only the children have data.
5832
MERGE tables have HA_NO_COPY_ON_ALTER set.
5834
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
5836
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
5837
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
5838
new_table->next_number_field=new_table->found_next_number_field;
5839
error= copy_data_between_tables(table, new_table,
5840
alter_info->create_list, ignore,
5841
order_num, order, &copied, &deleted,
5842
alter_info->keys_onoff,
5843
alter_info->error_if_not_empty);
5847
VOID(pthread_mutex_lock(&LOCK_open));
5848
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
5849
VOID(pthread_mutex_unlock(&LOCK_open));
5850
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
5851
alter_info->keys_onoff);
5852
error= ha_autocommit_or_rollback(thd, 0);
5853
if (end_active_trans(thd))
5856
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
5858
if (table->s->tmp_table != NO_TMP_TABLE)
5860
/* We changed a temporary table */
5863
/* Close lock if this is a transactional table */
5866
mysql_unlock_tables(thd, thd->lock);
5869
/* Remove link to old table and rename the new one */
5870
close_temporary_table(thd, table, 1, 1);
5871
/* Should pass the 'new_name' as we store table name in the cache */
5872
if (rename_temporary_table(thd, new_table, new_db, new_name))
5874
/* We don't replicate alter table statement on temporary tables */
5875
if (!thd->current_stmt_binlog_row_based)
5876
write_bin_log(thd, true, thd->query, thd->query_length);
5883
Close the intermediate table that will be the new table.
5884
Note that MERGE tables do not have their children attached here.
5886
intern_close_table(new_table);
5887
my_free(new_table,MYF(0));
5889
VOID(pthread_mutex_lock(&LOCK_open));
5892
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5893
VOID(pthread_mutex_unlock(&LOCK_open));
5898
Data is copied. Now we:
5899
1) Wait until all other threads close old version of table.
5900
2) Close instances of table open by this thread and replace them
5901
with exclusive name-locks.
5902
3) Rename the old table to a temp name, rename the new one to the
5904
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
5905
we reopen new version of table.
5906
5) Write statement to the binary log.
5907
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
5908
remove name-locks from list of open tables and table cache.
5909
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
5910
call to remove name-locks from table cache and list of open table.
5913
thd_proc_info(thd, "rename result table");
5914
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
5915
current_pid, thd->thread_id);
5916
if (lower_case_table_names)
5917
my_casedn_str(files_charset_info, old_name);
5919
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
5920
close_data_files_and_morph_locks(thd, db, table_name);
5923
save_old_db_type= old_db_type;
5926
This leads to the storage engine (SE) not being notified for renames in
5927
mysql_rename_table(), because we just juggle with the FRM and nothing
5928
more. If we have an intermediate table, then we notify the SE that
5929
it should become the actual table. Later, we will recycle the old table.
5930
However, in case of ALTER TABLE RENAME there might be no intermediate
5931
table. This is when the old and new tables are compatible, according to
5932
compare_table(). Then, we need one additional call to
5933
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
5934
actual rename in the SE and the FRM is not touched. Note that, if the
5935
table is renamed and the SE is also changed, then an intermediate table
5936
is created and the additional call will not take place.
5938
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
5942
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5944
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
5945
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
5947
/* Try to get everything back. */
5949
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
5950
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5951
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
5957
/* This shouldn't happen. But let us play it safe. */
5958
goto err_with_placeholders;
5961
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
5964
if (thd->locked_tables && new_name == table_name && new_db == db)
5966
thd->in_lock_tables= 1;
5967
error= reopen_tables(thd, 1, 1);
5968
thd->in_lock_tables= 0;
5970
goto err_with_placeholders;
5972
VOID(pthread_mutex_unlock(&LOCK_open));
5974
thd_proc_info(thd, "end");
5976
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
5977
thd->query, thd->query_length,
5980
assert(!(mysql_bin_log.is_open() &&
5981
thd->current_stmt_binlog_row_based &&
5982
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
5983
write_bin_log(thd, true, thd->query, thd->query_length);
5985
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
5988
For the alter table to be properly flushed to the logs, we
5989
have to open the new table. If not, we get a problem on server
5990
shutdown. But we do not need to attach MERGE children.
5992
char path[FN_REFLEN];
5994
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
5995
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
5998
intern_close_table(t_table);
5999
my_free(t_table, MYF(0));
6002
sql_print_warning("Could not open table %s.%s after rename\n",
6004
ha_flush_logs(old_db_type);
6006
table_list->table=0; // For query cache
6008
if (thd->locked_tables && (new_name != table_name || new_db != db))
6011
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
6012
to remove placeholders for the old table and for the target table
6013
from the list of open tables and table cache. If we are not under
6014
LOCK TABLES we can rely on close_thread_tables() doing this job.
6016
pthread_mutex_lock(&LOCK_open);
6017
unlink_open_table(thd, table, false);
6018
unlink_open_table(thd, name_lock, false);
6019
pthread_mutex_unlock(&LOCK_open);
6023
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
6024
(ulong) (copied + deleted), (ulong) deleted,
6025
(ulong) thd->cuted_fields);
6026
my_ok(thd, copied + deleted, 0L, tmp_name);
6027
thd->some_tables_deleted=0;
6033
/* close_temporary_table() frees the new_table pointer. */
6034
close_temporary_table(thd, new_table, 1, 1);
6037
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
6041
No default value was provided for a DATE/DATETIME field, the
6042
current sql_mode doesn't allow the '0000-00-00' value and
6043
the table to be altered isn't empty.
6046
if (alter_info->error_if_not_empty && thd->row_count)
6048
const char *f_val= 0;
6049
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
6050
switch (alter_info->datetime_field->sql_type)
6052
case MYSQL_TYPE_NEWDATE:
6053
f_val= "0000-00-00";
6054
t_type= MYSQL_TIMESTAMP_DATE;
6056
case MYSQL_TYPE_DATETIME:
6057
f_val= "0000-00-00 00:00:00";
6058
t_type= MYSQL_TIMESTAMP_DATETIME;
6061
/* Shouldn't get here. */
6064
bool save_abort_on_warning= thd->abort_on_warning;
6065
thd->abort_on_warning= true;
6066
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
6067
f_val, strlength(f_val), t_type,
6068
alter_info->datetime_field->field_name);
6069
thd->abort_on_warning= save_abort_on_warning;
6073
pthread_mutex_lock(&LOCK_open);
6074
unlink_open_table(thd, name_lock, false);
6075
pthread_mutex_unlock(&LOCK_open);
6079
err_with_placeholders:
6081
An error happened while we were holding exclusive name-lock on table
6082
being altered. To be safe under LOCK TABLES we should remove placeholders
6083
from list of open tables list and table cache.
6085
unlink_open_table(thd, table, false);
6087
unlink_open_table(thd, name_lock, false);
6088
VOID(pthread_mutex_unlock(&LOCK_open));
6091
/* mysql_alter_table */
6094
copy_data_between_tables(TABLE *from,TABLE *to,
6095
List<Create_field> &create,
6097
uint order_num, ORDER *order,
6100
enum enum_enable_or_disable keys_onoff,
6101
bool error_if_not_empty)
6104
Copy_field *copy,*copy_end;
6105
ulong found_count,delete_count;
6106
THD *thd= current_thd;
6108
SORT_FIELD *sortorder;
6112
List<Item> all_fields;
6113
ha_rows examined_rows;
6114
bool auto_increment_field_copied= 0;
6115
ulong save_sql_mode;
6116
uint64_t prev_insert_id;
6119
Turn off recovery logging since rollback of an alter table is to
6120
delete the new table so there is no need to log the changes to it.
6122
This needs to be done before external_lock
6124
error= ha_enable_transaction(thd, false);
6128
if (!(copy= new Copy_field[to->s->fields]))
6129
return(-1); /* purecov: inspected */
6131
if (to->file->ha_external_lock(thd, F_WRLCK))
6134
/* We need external lock before we can disable/enable keys */
6135
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
6137
/* We can abort alter table for any table type */
6138
thd->abort_on_warning= !ignore;
6140
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
6141
to->file->ha_start_bulk_insert(from->file->stats.records);
6143
save_sql_mode= thd->variables.sql_mode;
6145
List_iterator<Create_field> it(create);
6148
for (Field **ptr=to->field ; *ptr ; ptr++)
6153
if (*ptr == to->next_number_field)
6155
auto_increment_field_copied= true;
6157
If we are going to copy contents of one auto_increment column to
6158
another auto_increment column it is sensible to preserve zeroes.
6159
This condition also covers case when we are don't actually alter
6160
auto_increment column.
6162
if (def->field == from->found_next_number_field)
6163
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
6165
(copy_end++)->set(*ptr,def->field,0);
6170
found_count=delete_count=0;
6174
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
6176
char warn_buff[MYSQL_ERRMSG_SIZE];
6177
snprintf(warn_buff, sizeof(warn_buff),
6178
"ORDER BY ignored as there is a user-defined clustered index"
6179
" in the table '%-.192s'", from->s->table_name.str);
6180
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
6185
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
6186
MYF(MY_FAE | MY_ZEROFILL));
6187
bzero((char *) &tables, sizeof(tables));
6189
tables.alias= tables.table_name= from->s->table_name.str;
6190
tables.db= from->s->db.str;
6193
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
6194
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
6195
&tables, fields, all_fields, order) ||
6196
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
6197
(from->sort.found_records= filesort(thd, from, sortorder, length,
6198
(SQL_SELECT *) 0, HA_POS_ERROR,
6199
1, &examined_rows)) ==
6205
/* Tell handler that we have values for all columns in the to table */
6206
to->use_all_columns();
6207
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
6209
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
6211
restore_record(to, s->default_values); // Create empty record
6212
while (!(error=info.read_record(&info)))
6216
thd->send_kill_message();
6221
/* Return error if source table isn't empty. */
6222
if (error_if_not_empty)
6227
if (to->next_number_field)
6229
if (auto_increment_field_copied)
6230
to->auto_increment_field_not_null= true;
6232
to->next_number_field->reset();
6235
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
6237
copy_ptr->do_copy(copy_ptr);
6239
prev_insert_id= to->file->next_insert_id;
6240
error=to->file->ha_write_row(to->record[0]);
6241
to->auto_increment_field_not_null= false;
6245
to->file->is_fatal_error(error, HA_CHECK_DUP))
6247
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
6249
uint key_nr= to->file->get_dup_key(error);
6250
if ((int) key_nr >= 0)
6252
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
6254
(to->key_info[0].key_part[0].field->flags &
6255
AUTO_INCREMENT_FLAG))
6256
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
6257
to->file->print_keydup_error(key_nr, err_msg);
6262
to->file->print_error(error,MYF(0));
6265
to->file->restore_auto_increment(prev_insert_id);
6271
end_read_record(&info);
6272
free_io_cache(from);
6273
delete [] copy; // This is never 0
6275
if (to->file->ha_end_bulk_insert() && error <= 0)
6277
to->file->print_error(my_errno,MYF(0));
6280
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
6282
if (ha_enable_transaction(thd, true))
6289
Ensure that the new table is saved properly to disk so that we
6292
if (ha_autocommit_or_rollback(thd, 0))
6294
if (end_active_trans(thd))
6298
thd->variables.sql_mode= save_sql_mode;
6299
thd->abort_on_warning= 0;
6300
free_io_cache(from);
6301
*copied= found_count;
6302
*deleted=delete_count;
6303
to->file->ha_release_auto_increment();
6304
if (to->file->ha_external_lock(thd,F_UNLCK))
6306
return(error > 0 ? -1 : 0);
6311
Recreates tables by calling mysql_alter_table().
6314
mysql_recreate_table()
6316
tables Tables to recreate
6319
Like mysql_alter_table().
6321
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
6323
HA_CREATE_INFO create_info;
6324
Alter_info alter_info;
6326
assert(!table_list->next_global);
6328
table_list->table has been closed and freed. Do not reference
6329
uninitialized data. open_tables() could fail.
6331
table_list->table= NULL;
6333
bzero((char*) &create_info, sizeof(create_info));
6334
create_info.row_type=ROW_TYPE_NOT_USED;
6335
create_info.default_table_charset=default_charset_info;
6336
/* Force alter table to recreate table */
6337
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
6338
return(mysql_alter_table(thd, NullS, NullS, &create_info,
6339
table_list, &alter_info, 0,
6344
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
6345
HA_CHECK_OPT *check_opt)
6348
List<Item> field_list;
6350
Protocol *protocol= thd->protocol;
6352
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
6353
item->maybe_null= 1;
6354
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
6355
MY_INT64_NUM_DECIMAL_DIGITS));
6356
item->maybe_null= 1;
6357
if (protocol->send_fields(&field_list,
6358
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
6361
/* Open one table after the other to keep lock time as short as possible. */
6362
for (table= tables; table; table= table->next_local)
6364
char table_name[NAME_LEN*2+2];
6367
strxmov(table_name, table->db ,".", table->table_name, NullS);
6369
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
6370
thd->clear_error(); // these errors shouldn't get client
6372
protocol->prepare_for_resend();
6373
protocol->store(table_name, system_charset_info);
6377
/* Table didn't exist */
6378
protocol->store_null();
6383
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
6384
!(check_opt->flags & T_EXTEND))
6385
protocol->store((uint64_t)t->file->checksum());
6386
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
6387
(check_opt->flags & T_QUICK))
6388
protocol->store_null();
6391
/* calculating table's checksum */
6393
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
6395
t->use_all_columns();
6397
if (t->file->ha_rnd_init(1))
6398
protocol->store_null();
6403
ha_checksum row_crc= 0;
6404
int error= t->file->rnd_next(t->record[0]);
6405
if (unlikely(error))
6407
if (error == HA_ERR_RECORD_DELETED)
6411
if (t->s->null_bytes)
6413
/* fix undefined null bits */
6414
t->record[0][t->s->null_bytes-1] |= null_mask;
6415
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
6416
t->record[0][0] |= 1;
6418
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
6421
for (uint i= 0; i < t->s->fields; i++ )
6423
Field *f= t->field[i];
6424
if ((f->type() == MYSQL_TYPE_BLOB) ||
6425
(f->type() == MYSQL_TYPE_VARCHAR))
6429
row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
6432
row_crc= my_checksum(row_crc, f->ptr,
6438
protocol->store((uint64_t)crc);
6439
t->file->ha_rnd_end();
6443
close_thread_tables(thd);
6444
table->table=0; // For query cache
6446
if (protocol->write())
6454
close_thread_tables(thd); // Shouldn't be needed
6460
static bool check_engine(THD *thd, const char *table_name,
6461
HA_CREATE_INFO *create_info)
6463
handlerton **new_engine= &create_info->db_type;
6464
handlerton *req_engine= *new_engine;
6465
bool no_substitution= 1;
6466
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
6467
no_substitution, 1)))
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2224
"analyze", lock_type, true,
2225
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2236
&Cursor::ha_check));
2239
} /* namespace drizzled */
6470
if (req_engine && req_engine != *new_engine)
6472
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
6473
ER_WARN_USING_OTHER_HANDLER,
6474
ER(ER_WARN_USING_OTHER_HANDLER),
6475
ha_resolve_storage_engine_name(*new_engine),
6478
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
6479
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
6481
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
6483
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
6484
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
6488
*new_engine= myisam_hton;